├── cluster ├── images │ ├── provider-rook │ │ ├── Dockerfile │ │ └── Makefile │ └── provider-rook-controller │ │ ├── Dockerfile │ │ └── Makefile ├── examples │ ├── claim.yaml │ ├── provider.sh │ ├── provider.yaml │ ├── cockroach │ │ └── cockroach.yaml │ └── yugabyte │ │ └── yugabyte.yaml └── local │ └── integration_tests.sh ├── .gitmodules ├── PROJECT ├── config ├── package │ ├── manifests │ │ ├── resources │ │ │ ├── cockroachcluster.ui-schema.yaml │ │ │ ├── yugabytecluster.ui-schema.yaml │ │ │ ├── cockroachclusterclass.ui-schema.yaml │ │ │ ├── yugabyteclusterclass.ui-schema.yaml │ │ │ ├── yugabyteclusterclass.resource.yaml │ │ │ ├── cockroachclusterclass.resource.yaml │ │ │ ├── yugabytecluster.resource.yaml │ │ │ ├── cockroachcluster.icon.svg │ │ │ ├── cockroachclusterclass.icon.svg │ │ │ └── cockroachcluster.resource.yaml │ │ ├── install.yaml │ │ ├── app.yaml │ │ └── icon.svg │ └── samples │ │ ├── install.package.yaml │ │ └── local.install.package.yaml └── crd │ └── rook.crossplane.io_providerconfigs.yaml ├── CODE_OF_CONDUCT.md ├── .gitignore ├── hack ├── linter-violation.tmpl └── boilerplate.go.txt ├── go.mod ├── pkg ├── controller │ ├── doc.go │ ├── rook.go │ ├── config │ │ └── config.go │ └── database │ │ ├── yugabyte │ │ ├── yugabyte.go │ │ └── yugabyte_test.go │ │ └── cockroach │ │ └── cockroach.go └── clients │ ├── database │ ├── yugabyte │ │ ├── yugabyte.go │ │ └── yugabyte_test.go │ └── cockroach │ │ ├── cockroach.go │ │ └── cockroach_test.go │ └── client.go ├── .github ├── workflows │ ├── tag.yml │ ├── promote.yml │ └── ci.yml ├── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── PULL_REQUEST_TEMPLATE.md └── stale.yml ├── OWNERS.md ├── apis ├── database │ ├── database.go │ └── v1alpha1 │ │ ├── doc.go │ │ ├── zz_generated.managedlist.go │ │ ├── register.go │ │ ├── zz_generated.managed.go │ │ ├── types.go │ │ └── zz_generated.deepcopy.go ├── v1beta1 │ ├── doc.go │ ├── zz_generated.pculist.go │ ├── zz_generated.pc.go │ ├── zz_generated.pcu.go │ ├── register.go │ ├── providerconfig_types.go │ └── zz_generated.deepcopy.go ├── v1alpha1 │ ├── doc.go │ ├── types.go │ └── zz_generated.deepcopy.go ├── rook.go └── generate.go ├── DCO ├── INSTALL.md ├── cmd └── provider │ └── main.go ├── README.md ├── package ├── crds │ ├── rook.crossplane.io_providerconfigusages.yaml │ └── rook.crossplane.io_providerconfigs.yaml └── crossplane.yaml ├── Makefile ├── .golangci.yml └── LICENSE /cluster/images/provider-rook/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM BASEIMAGE 2 | 3 | COPY package.yaml . 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "build"] 2 | path = build 3 | url = https://github.com/upbound/build 4 | -------------------------------------------------------------------------------- /PROJECT: -------------------------------------------------------------------------------- 1 | version: "1" 2 | domain: crossplane.io 3 | repo: github.com/crossplane/provider-rook 4 | -------------------------------------------------------------------------------- /config/package/manifests/resources/cockroachcluster.ui-schema.yaml: -------------------------------------------------------------------------------- 1 | version: 0.5 2 | configSections: [] 3 | -------------------------------------------------------------------------------- /config/package/manifests/resources/yugabytecluster.ui-schema.yaml: -------------------------------------------------------------------------------- 1 | version: 0.5 2 | configSections: [] 3 | -------------------------------------------------------------------------------- /config/package/manifests/resources/cockroachclusterclass.ui-schema.yaml: -------------------------------------------------------------------------------- 1 | version: 0.5 2 | configSections: [] 3 | -------------------------------------------------------------------------------- /config/package/manifests/resources/yugabyteclusterclass.ui-schema.yaml: -------------------------------------------------------------------------------- 1 | version: 0.5 2 | configSections: [] 3 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Community Code of Conduct 2 | 3 | This project follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.cache 2 | /.work 3 | /_output 4 | cover.out 5 | /vendor 6 | /.vendor-new 7 | 8 | # ignore GoLand files (debug config etc...) 9 | /.idea 10 | 11 | # ignore IDE folders 12 | .vscode/ -------------------------------------------------------------------------------- /cluster/examples/claim.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: database.crossplane.io/v1alpha1 2 | kind: PostgreSQLInstance 3 | metadata: 4 | name: app-postgresql 5 | spec: 6 | writeConnectionSecretToRef: 7 | name: postgresqlconn 8 | -------------------------------------------------------------------------------- /hack/linter-violation.tmpl: -------------------------------------------------------------------------------- 1 | `{{violation.rule}}`: {{violation.message}} 2 | 3 | Refer to Crossplane's [coding style documentation](https://github.com/crossplane/crossplane/blob/master/CONTRIBUTING.md#coding-style-and-linting) for more information. -------------------------------------------------------------------------------- /config/package/samples/install.package.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: packages.crossplane.io/v1alpha1 3 | kind: ClusterPackageInstall 4 | metadata: 5 | name: provider-rook 6 | namespace: rook 7 | spec: 8 | package: "crossplane/provider-rook:master" 9 | -------------------------------------------------------------------------------- /config/package/samples/local.install.package.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: packages.crossplane.io/v1alpha1 3 | kind: ClusterPackageInstall 4 | metadata: 5 | name: provider-rook 6 | namespace: rook 7 | spec: 8 | source: localhost:5000 9 | package: "crossplane/provider-rook" 10 | -------------------------------------------------------------------------------- /cluster/images/provider-rook-controller/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM BASEIMAGE 2 | RUN apk --no-cache add ca-certificates bash 3 | 4 | ARG ARCH 5 | ARG TINI_VERSION 6 | 7 | ADD provider /usr/local/bin/crossplane-rook-provider 8 | 9 | EXPOSE 8080 10 | USER 1001 11 | ENTRYPOINT ["crossplane-rook-provider"] 12 | -------------------------------------------------------------------------------- /cluster/examples/provider.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | export BASE64ENCODED_K8S_TOKEN=$(base64 ./secrets/token.txt | tr -d "\n") 4 | export BASE64ENCODED_K8S_ENDPOINT=$(base64 ./secrets/endpoint.txt | tr -d "\n") 5 | export BASE64ENCODED_K8S_CLUSTER_CA=$(base64 ./secrets/ca.txt | tr -d "\n") 6 | sed "s/BASE64ENCODED_K8S_TOKEN/$BASE64ENCODED_K8S_TOKEN/g;s/BASE64ENCODED_K8S_ENDPOINT/$BASE64ENCODED_K8S_ENDPOINT/g;s/BASE64ENCODED_K8S_CLUSTER_CA/$BASE64ENCODED_K8S_CLUSTER_CA/g" provider.yaml | kubectl create -f - -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/crossplane/provider-rook 2 | 3 | go 1.13 4 | 5 | require ( 6 | github.com/crossplane/crossplane-runtime v0.12.0 7 | github.com/crossplane/crossplane-tools v0.0.0-20201007233256-88b291e145bb 8 | github.com/google/go-cmp v0.5.0 9 | github.com/pkg/errors v0.9.1 10 | github.com/rook/rook v1.1.2 11 | gopkg.in/alecthomas/kingpin.v2 v2.2.6 12 | k8s.io/api v0.18.8 13 | k8s.io/apimachinery v0.18.8 14 | k8s.io/client-go v0.18.8 15 | sigs.k8s.io/controller-runtime v0.6.2 16 | sigs.k8s.io/controller-tools v0.3.0 17 | ) 18 | -------------------------------------------------------------------------------- /cluster/examples/provider.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | name: rook-infra-dev 5 | --- 6 | apiVersion: v1 7 | kind: Secret 8 | metadata: 9 | name: demo-cluster-creds 10 | namespace: rook-infra-dev 11 | type: Opaque 12 | data: 13 | endpoint: BASE64ENCODED_K8S_ENDPOINT 14 | token: BASE64ENCODED_K8S_TOKEN 15 | clusterCA: BASE64ENCODED_K8S_CLUSTER_CA 16 | --- 17 | apiVersion: kubernetes.crossplane.io/v1alpha1 18 | kind: Provider 19 | metadata: 20 | name: demo-k8s-provider 21 | spec: 22 | credentialsSecretRef: 23 | name: demo-cluster-creds 24 | namespace: rook-infra-dev 25 | -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | -------------------------------------------------------------------------------- /pkg/controller/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controller 18 | -------------------------------------------------------------------------------- /.github/workflows/tag.yml: -------------------------------------------------------------------------------- 1 | name: Tag 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | version: 7 | description: 'Release version (e.g. v0.1.0)' 8 | required: true 9 | message: 10 | description: 'Tag message' 11 | required: true 12 | 13 | jobs: 14 | create-tag: 15 | runs-on: ubuntu-18.04 16 | 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@v2 20 | 21 | - name: Create Tag 22 | uses: negz/create-tag@v1 23 | with: 24 | version: ${{ github.event.inputs.version }} 25 | message: ${{ github.event.inputs.message }} 26 | token: ${{ secrets.GITHUB_TOKEN }} -------------------------------------------------------------------------------- /OWNERS.md: -------------------------------------------------------------------------------- 1 | # OWNERS 2 | 3 | This page lists all maintainers for **this** repository. Each repository in the [Crossplane 4 | organization](https://github.com/crossplane/) will list their repository maintainers in their own 5 | `OWNERS.md` file. 6 | 7 | Please see the Crossplane 8 | [GOVERNANCE.md](https://github.com/crossplane/crossplane/blob/master/GOVERNANCE.md) for governance 9 | guidelines and responsibilities for the steering committee and maintainers. 10 | 11 | ## Maintainers 12 | 13 | * Nic Cope ([negz](https://github.com/negz)) 14 | * Daniel Mangum ([hasheddan](https://github.com/hasheddan)) 15 | * Jared Watts ([jbw976](https://github.com/jbw976)) 16 | -------------------------------------------------------------------------------- /config/package/manifests/resources/yugabyteclusterclass.resource.yaml: -------------------------------------------------------------------------------- 1 | id: yugabyteclusterclass 2 | title: YugabyteDB Cluster Class 3 | titlePlural: YugabyteDB Cluster Classes 4 | category: Database 5 | overviewShort: "A YugabyteClusterClass is a resource class. It defines the desired spec of resource claims that use it to dynamically provision a managed resource." 6 | overview: | 7 | A YugabyteClusterClass is a resource class. It defines the desired spec of resource claims that use it to dynamically provision a managed resource. 8 | readme: | 9 | Full documentation can be found in the Crossplane [API Reference docs](https://doc.crds.dev/github.com/crossplane/provider-rook/database.rook.crossplane.io_yugabyteclusterclasses.yaml). 10 | -------------------------------------------------------------------------------- /apis/database/database.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package database contains Rook database API versions 18 | package database 19 | -------------------------------------------------------------------------------- /config/package/manifests/resources/cockroachclusterclass.resource.yaml: -------------------------------------------------------------------------------- 1 | id: cockroachclusterclass 2 | title: CockroachDB Cluster Class 3 | titlePlural: CockroachDB Cluster Classes 4 | category: Database 5 | overviewShort: "A CockroachClusterClass is a resource class. It defines the desired spec of resource claims that use it to dynamically provision a managed resource." 6 | overview: | 7 | A CockroachClusterClass is a resource class. It defines the desired spec of resource claims that use it to dynamically provision a managed resource. 8 | readme: | 9 | Full documentation can be found in the Crossplane [API Reference docs](https://doc.crds.dev/github.com/crossplane/provider-rook/database.rook.crossplane.io_cockroachclusterclasses.yaml). 10 | 11 | -------------------------------------------------------------------------------- /config/package/manifests/install.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: provider-rook 5 | labels: 6 | core.crossplane.io/name: "provider-rook" 7 | spec: 8 | selector: 9 | matchLabels: 10 | core.crossplane.io/name: "provider-rook" 11 | replicas: 1 12 | template: 13 | metadata: 14 | name: "provider-rook-controller" 15 | labels: 16 | core.crossplane.io/name: "provider-rook" 17 | spec: 18 | containers: 19 | - name: "provider-rook-controller" 20 | env: 21 | - name: POD_NAME 22 | valueFrom: 23 | fieldRef: 24 | fieldPath: metadata.name 25 | - name: POD_NAMESPACE 26 | valueFrom: 27 | fieldRef: 28 | fieldPath: metadata.namespace 29 | -------------------------------------------------------------------------------- /apis/v1beta1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1beta1 contains core Rook resources. 18 | // +kubebuilder:object:generate=true 19 | // +groupName=rook.crossplane.io 20 | // +versionName=v1beta1 21 | package v1beta1 22 | -------------------------------------------------------------------------------- /cluster/examples/cockroach/cockroach.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: database.rook.crossplane.io/v1alpha1 2 | kind: CockroachCluster 3 | metadata: 4 | name: test-cluster 5 | spec: 6 | providerRef: 7 | name: demo-k8s-provider 8 | reclaimPolicy: Delete 9 | forProvider: 10 | name: my-test-cockroach 11 | namespace: rook-cockroachdb 12 | scope: 13 | nodeCount: 3 14 | volumeClaimTemplates: 15 | - metadata: 16 | name: rook-cockroachdb-data 17 | spec: 18 | accessModes: [ "ReadWriteOnce" ] 19 | resources: 20 | requests: 21 | storage: "1Gi" 22 | network: 23 | ports: 24 | - name: http 25 | port: 8080 26 | - name: grpc 27 | port: 26257 28 | secure: false 29 | cachePercent: 25 30 | maxSQLMemoryPercent: 25 31 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Help us make Crossplane more useful 4 | labels: enhancement 5 | --- 6 | 13 | 14 | ### What problem are you facing? 15 | 20 | 21 | ### How could Crossplane help solve your problem? 22 | 25 | -------------------------------------------------------------------------------- /apis/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1alpha1 contains database service resources for Rook 18 | // +kubebuilder:object:generate=true 19 | // +groupName=rook.crossplane.io 20 | // +versionName=v1alpha1 21 | package v1alpha1 22 | -------------------------------------------------------------------------------- /apis/database/v1alpha1/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1alpha1 contains database service resources for Rook 18 | // +kubebuilder:object:generate=true 19 | // +groupName=database.rook.crossplane.io 20 | // +versionName=v1alpha1 21 | package v1alpha1 22 | -------------------------------------------------------------------------------- /cluster/images/provider-rook-controller/Makefile: -------------------------------------------------------------------------------- 1 | # ==================================================================================== 2 | # Setup Project 3 | 4 | PLATFORMS := linux_amd64 linux_arm64 5 | include ../../../build/makelib/common.mk 6 | 7 | # ==================================================================================== 8 | # Options 9 | IMAGE = $(BUILD_REGISTRY)/provider-rook-controller-$(ARCH) 10 | include ../../../build/makelib/image.mk 11 | 12 | # ==================================================================================== 13 | # Targets 14 | 15 | img.build: 16 | @$(INFO) docker build $(IMAGE) 17 | @cp Dockerfile $(IMAGE_TEMP_DIR) || $(FAIL) 18 | @cp $(OUTPUT_DIR)/bin/$(OS)_$(ARCH)/provider $(IMAGE_TEMP_DIR) || $(FAIL) 19 | @cd $(IMAGE_TEMP_DIR) && $(SED_CMD) 's|BASEIMAGE|$(OSBASEIMAGE)|g' Dockerfile || $(FAIL) 20 | @docker build $(BUILD_ARGS) \ 21 | --build-arg ARCH=$(ARCH) \ 22 | --build-arg TINI_VERSION=$(TINI_VERSION) \ 23 | -t $(IMAGE) \ 24 | $(IMAGE_TEMP_DIR) || $(FAIL) 25 | @$(OK) docker build $(IMAGE) 26 | -------------------------------------------------------------------------------- /apis/v1beta1/zz_generated.pculist.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by angryjet. DO NOT EDIT. 18 | 19 | package v1beta1 20 | 21 | import resource "github.com/crossplane/crossplane-runtime/pkg/resource" 22 | 23 | // GetItems of this ProviderConfigUsageList. 24 | func (p *ProviderConfigUsageList) GetItems() []resource.ProviderConfigUsage { 25 | items := make([]resource.ProviderConfigUsage, len(p.Items)) 26 | for i := range p.Items { 27 | items[i] = &p.Items[i] 28 | } 29 | return items 30 | } 31 | -------------------------------------------------------------------------------- /apis/v1alpha1/types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1alpha1 18 | 19 | import ( 20 | v1 "k8s.io/api/core/v1" 21 | ) 22 | 23 | // StorageScopeSpec defines scope or boundaries of storage that the cluster will 24 | // use for its underlying storage. 25 | type StorageScopeSpec struct { 26 | NodeCount int `json:"nodeCount,omitempty"` 27 | // PersistentVolumeClaims to use as storage 28 | VolumeClaimTemplates []v1.PersistentVolumeClaim `json:"volumeClaimTemplates,omitempty"` 29 | } 30 | 31 | // Annotations are a Crossplane representation of Rook Annotations. 32 | type Annotations map[string]string 33 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 8 | 9 | ### Description of your changes 10 | 11 | 20 | Fixes # 21 | 22 | I have: 23 | 24 | - [ ] Read and followed Crossplane's [contribution process]. 25 | - [ ] Run `make reviewable test` to ensure this PR is ready for review. 26 | 27 | ### How has this code been tested 28 | 29 | 34 | 35 | [contribution process]: https://git.io/fj2m9 36 | -------------------------------------------------------------------------------- /config/package/manifests/resources/yugabytecluster.resource.yaml: -------------------------------------------------------------------------------- 1 | id: yugabytecluster 2 | title: YugabyteDB Cluster 3 | titlePlural: YugabyteDB Clusters 4 | category: Database 5 | overviewShort: "A YugabyteCluster configures a Rook 'ybclusters.yugabytedb.rook.io'" 6 | overview: | 7 | YugabyteDB is the open source, high-performance, distributed SQL database for global, internet-scale apps. 8 | readme: | 9 | ## Why YugabyteDB? 10 | 11 | Developers get low latency reads, ACID transactions and globally consistent 12 | secondary indexes and full SQL. Develop both scale-out RDBMS and internet-scale 13 | OLTP apps with ease. 14 | 15 | DBAs & Operations simplify operations with a single database that delivers linear scalability, automatic global data distribution, multi-TB density per node and rebalancing without performance bottlenecks or down time. 16 | 17 | CEOs & Line of Business Owners reign in database sprawl and benefit from 18 | reduced infrastructure and software licensing costs. Deliver new features and enter new markets with more speed and agility. 19 | 20 | ## Learn more 21 | 22 | This content is from https://www.yugabyte.com/yugabytedb/, you can learn more 23 | in the [YugabyteDB documentation](https://docs.yugabyte.com/). 24 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Help us diagnose and fix bugs in Crossplane 4 | labels: bug 5 | --- 6 | 13 | 14 | ### What happened? 15 | 19 | 20 | 21 | ### How can we reproduce it? 22 | 27 | 28 | ### What environment did it happen in? 29 | Crossplane version: 30 | 31 | 41 | -------------------------------------------------------------------------------- /cluster/images/provider-rook/Makefile: -------------------------------------------------------------------------------- 1 | # ==================================================================================== 2 | # Setup Project 3 | 4 | PLATFORMS := linux_amd64 linux_arm64 5 | include ../../../build/makelib/common.mk 6 | 7 | # ==================================================================================== 8 | # Options 9 | IMAGE = $(BUILD_REGISTRY)/provider-rook-$(ARCH) 10 | OSBASEIMAGE = scratch 11 | include ../../../build/makelib/image.mk 12 | 13 | # ==================================================================================== 14 | # Targets 15 | 16 | img.build: 17 | @$(INFO) docker build $(IMAGE) 18 | @cp Dockerfile $(IMAGE_TEMP_DIR) || $(FAIL) 19 | @cp -R ../../../package $(IMAGE_TEMP_DIR) || $(FAIL) 20 | @cd $(IMAGE_TEMP_DIR) && $(SED_CMD) 's|BASEIMAGE|$(OSBASEIMAGE)|g' Dockerfile || $(FAIL) 21 | @cd $(IMAGE_TEMP_DIR) && $(SED_CMD) 's|VERSION|$(VERSION)|g' package/crossplane.yaml || $(FAIL) 22 | @cd $(IMAGE_TEMP_DIR) && find package -type f -name '*.yaml' -exec cat {} >> 'package.yaml' \; -exec printf '\n---\n' \; || $(FAIL) 23 | @docker build $(BUILD_ARGS) \ 24 | --build-arg ARCH=$(ARCH) \ 25 | --build-arg TINI_VERSION=$(TINI_VERSION) \ 26 | -t $(IMAGE) \ 27 | $(IMAGE_TEMP_DIR) || $(FAIL) 28 | @$(OK) docker build $(IMAGE) 29 | -------------------------------------------------------------------------------- /config/package/manifests/resources/cockroachcluster.icon.svg: -------------------------------------------------------------------------------- 1 | CL -------------------------------------------------------------------------------- /config/package/manifests/resources/cockroachclusterclass.icon.svg: -------------------------------------------------------------------------------- 1 | CL -------------------------------------------------------------------------------- /apis/database/v1alpha1/zz_generated.managedlist.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by angryjet. DO NOT EDIT. 18 | 19 | package v1alpha1 20 | 21 | import resource "github.com/crossplane/crossplane-runtime/pkg/resource" 22 | 23 | // GetItems of this CockroachClusterList. 24 | func (l *CockroachClusterList) GetItems() []resource.Managed { 25 | items := make([]resource.Managed, len(l.Items)) 26 | for i := range l.Items { 27 | items[i] = &l.Items[i] 28 | } 29 | return items 30 | } 31 | 32 | // GetItems of this YugabyteClusterList. 33 | func (l *YugabyteClusterList) GetItems() []resource.Managed { 34 | items := make([]resource.Managed, len(l.Items)) 35 | for i := range l.Items { 36 | items[i] = &l.Items[i] 37 | } 38 | return items 39 | } 40 | -------------------------------------------------------------------------------- /apis/v1beta1/zz_generated.pc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by angryjet. DO NOT EDIT. 18 | 19 | package v1beta1 20 | 21 | import xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" 22 | 23 | // GetCondition of this ProviderConfig. 24 | func (p *ProviderConfig) GetCondition(ct xpv1.ConditionType) xpv1.Condition { 25 | return p.Status.GetCondition(ct) 26 | } 27 | 28 | // GetUsers of this ProviderConfig. 29 | func (p *ProviderConfig) GetUsers() int64 { 30 | return p.Status.Users 31 | } 32 | 33 | // SetConditions of this ProviderConfig. 34 | func (p *ProviderConfig) SetConditions(c ...xpv1.Condition) { 35 | p.Status.SetConditions(c...) 36 | } 37 | 38 | // SetUsers of this ProviderConfig. 39 | func (p *ProviderConfig) SetUsers(i int64) { 40 | p.Status.Users = i 41 | } 42 | -------------------------------------------------------------------------------- /pkg/controller/rook.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import ( 20 | ctrl "sigs.k8s.io/controller-runtime" 21 | 22 | "github.com/crossplane/crossplane-runtime/pkg/logging" 23 | 24 | "github.com/crossplane/provider-rook/pkg/controller/config" 25 | "github.com/crossplane/provider-rook/pkg/controller/database/cockroach" 26 | "github.com/crossplane/provider-rook/pkg/controller/database/yugabyte" 27 | ) 28 | 29 | // Setup creates all AWS controllers with the supplied logger and adds them to 30 | // the supplied manager. 31 | func Setup(mgr ctrl.Manager, l logging.Logger) error { 32 | for _, setup := range []func(ctrl.Manager, logging.Logger) error{ 33 | config.Setup, 34 | cockroach.Setup, 35 | yugabyte.Setup, 36 | } { 37 | if err := setup(mgr, l); err != nil { 38 | return err 39 | } 40 | } 41 | 42 | return nil 43 | } 44 | -------------------------------------------------------------------------------- /.github/stale.yml: -------------------------------------------------------------------------------- 1 | # Configuration for probot-stale - https://github.com/probot/stale 2 | 3 | # Number of days of inactivity before an Issue or Pull Request becomes stale 4 | daysUntilStale: 90 5 | 6 | # Number of days of inactivity before a stale Issue or Pull Request is closed. 7 | # Set to false to disable. If disabled, issues still need to be closed manually, but will remain marked as stale. 8 | daysUntilClose: 7 9 | 10 | # Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable 11 | exemptLabels: 12 | - security 13 | 14 | # Set to true to ignore issues in a project (defaults to false) 15 | exemptProjects: false 16 | 17 | # Set to true to ignore issues in a milestone (defaults to false) 18 | exemptMilestones: false 19 | 20 | # Label to use when marking as stale 21 | staleLabel: wontfix 22 | 23 | # Comment to post when marking as stale. Set to `false` to disable 24 | markComment: > 25 | This issue has been automatically marked as stale because it has not had 26 | recent activity. It will be closed if no further activity occurs. Thank you 27 | for your contributions. 28 | 29 | # Comment to post when closing a stale Issue or Pull Request. 30 | closeComment: > 31 | This issue has been automatically closed due to inactivity. Please re-open 32 | if this still requires investigation. 33 | 34 | # Limit the number of actions per hour, from 1-30. Default is 30 35 | limitPerRun: 30 36 | 37 | # Limit to only `issues` or `pulls` 38 | only: issues 39 | -------------------------------------------------------------------------------- /apis/rook.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package apis contains Kubernetes API for Rook. 18 | package apis 19 | 20 | import ( 21 | "k8s.io/apimachinery/pkg/runtime" 22 | 23 | databasev1alpha1 "github.com/crossplane/provider-rook/apis/database/v1alpha1" 24 | rookv1beta1 "github.com/crossplane/provider-rook/apis/v1beta1" 25 | ) 26 | 27 | func init() { 28 | // Register the types with the Scheme so the components can map objects to GroupVersionKinds and back 29 | AddToSchemes = append(AddToSchemes, 30 | databasev1alpha1.SchemeBuilder.AddToScheme, 31 | rookv1beta1.SchemeBuilder.AddToScheme, 32 | ) 33 | } 34 | 35 | // AddToSchemes may be used to add all resources defined in the project to a Scheme 36 | var AddToSchemes runtime.SchemeBuilder 37 | 38 | // AddToScheme adds all Resources to the Scheme 39 | func AddToScheme(s *runtime.Scheme) error { 40 | return AddToSchemes.AddToScheme(s) 41 | } 42 | -------------------------------------------------------------------------------- /apis/v1beta1/zz_generated.pcu.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by angryjet. DO NOT EDIT. 18 | 19 | package v1beta1 20 | 21 | import xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" 22 | 23 | // GetProviderConfigReference of this ProviderConfigUsage. 24 | func (p *ProviderConfigUsage) GetProviderConfigReference() xpv1.Reference { 25 | return p.ProviderConfigReference 26 | } 27 | 28 | // GetResourceReference of this ProviderConfigUsage. 29 | func (p *ProviderConfigUsage) GetResourceReference() xpv1.TypedReference { 30 | return p.ResourceReference 31 | } 32 | 33 | // SetProviderConfigReference of this ProviderConfigUsage. 34 | func (p *ProviderConfigUsage) SetProviderConfigReference(r xpv1.Reference) { 35 | p.ProviderConfigReference = r 36 | } 37 | 38 | // SetResourceReference of this ProviderConfigUsage. 39 | func (p *ProviderConfigUsage) SetResourceReference(r xpv1.TypedReference) { 40 | p.ResourceReference = r 41 | } 42 | -------------------------------------------------------------------------------- /DCO: -------------------------------------------------------------------------------- 1 | Developer Certificate of Origin 2 | Version 1.1 3 | 4 | Copyright (C) 2004, 2006 The Linux Foundation and its contributors. 5 | 660 York Street, Suite 102, 6 | San Francisco, CA 94110 USA 7 | 8 | Everyone is permitted to copy and distribute verbatim copies of this 9 | license document, but changing it is not allowed. 10 | 11 | 12 | Developer's Certificate of Origin 1.1 13 | 14 | By making a contribution to this project, I certify that: 15 | 16 | (a) The contribution was created in whole or in part by me and I 17 | have the right to submit it under the open source license 18 | indicated in the file; or 19 | 20 | (b) The contribution is based upon previous work that, to the best 21 | of my knowledge, is covered under an appropriate open source 22 | license and I have the right under that license to submit that 23 | work with modifications, whether created in whole or in part 24 | by me, under the same open source license (unless I am 25 | permitted to submit under a different license), as indicated 26 | in the file; or 27 | 28 | (c) The contribution was provided directly to me by some other 29 | person who certified (a), (b) or (c) and I have not modified 30 | it. 31 | 32 | (d) I understand and agree that this project and the contribution 33 | are public and that a record of the contribution (including all 34 | personal information I submit with it, including my sign-off) is 35 | maintained indefinitely and may be redistributed consistent with 36 | this project or the open source license(s) involved. 37 | -------------------------------------------------------------------------------- /.github/workflows/promote.yml: -------------------------------------------------------------------------------- 1 | name: Promote 2 | 3 | on: 4 | workflow_dispatch: 5 | inputs: 6 | version: 7 | description: 'Release version (e.g. v0.1.0)' 8 | required: true 9 | channel: 10 | description: 'Release channel' 11 | required: true 12 | default: 'alpha' 13 | 14 | env: 15 | # Common users. We can't run a step 'if secrets.AWS_USR != ""' but we can run 16 | # a step 'if env.AWS_USR' != ""', so we copy these to succinctly test whether 17 | # credentials have been provided before trying to run steps that need them. 18 | DOCKER_USR: ${{ secrets.DOCKER_USR }} 19 | AWS_USR: ${{ secrets.AWS_USR }} 20 | 21 | jobs: 22 | promote-artifacts: 23 | runs-on: ubuntu-18.04 24 | 25 | steps: 26 | - name: Checkout 27 | uses: actions/checkout@v2 28 | with: 29 | submodules: true 30 | 31 | - name: Fetch History 32 | run: git fetch --prune --unshallow 33 | 34 | - name: Login to Docker 35 | uses: docker/login-action@v1 36 | if: env.DOCKER_USR != '' 37 | with: 38 | username: ${{ secrets.DOCKER_USR }} 39 | password: ${{ secrets.DOCKER_PSW }} 40 | 41 | - name: Promote Artifacts in S3 and Docker Hub 42 | if: env.AWS_USR != '' && env.DOCKER_USR != '' 43 | run: make -j2 promote BRANCH_NAME=${GITHUB_REF##*/} 44 | env: 45 | VERSION: ${{ github.event.inputs.version }} 46 | CHANNEL: ${{ github.event.inputs.channel }} 47 | AWS_ACCESS_KEY_ID: ${{ secrets.AWS_USR }} 48 | AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_PSW }} 49 | -------------------------------------------------------------------------------- /apis/generate.go: -------------------------------------------------------------------------------- 1 | // +build generate 2 | 3 | /* 4 | Copyright 2019 The Crossplane 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 | 19 | // NOTE(negz): See the below link for details on what is happening here. 20 | // https://github.com/golang/go/wiki/Modules#how-can-i-track-tool-dependencies-for-a-module 21 | 22 | // Remove existing CRDs 23 | //go:generate rm -rf ../package/crds 24 | 25 | // Generate deepcopy methodsets and CRD manifests 26 | //go:generate go run -tags generate sigs.k8s.io/controller-tools/cmd/controller-gen object:headerFile=../hack/boilerplate.go.txt paths=./... crd:trivialVersions=true,crdVersions=v1 output:artifacts:config=../package/crds 27 | 28 | // Generate crossplane-runtime methodsets (resource.Claim, etc) 29 | //go:generate go run -tags generate github.com/crossplane/crossplane-tools/cmd/angryjet generate-methodsets --header-file=../hack/boilerplate.go.txt ./... 30 | 31 | package apis 32 | 33 | import ( 34 | _ "sigs.k8s.io/controller-tools/cmd/controller-gen" //nolint:typecheck 35 | 36 | _ "github.com/crossplane/crossplane-tools/cmd/angryjet" //nolint:typecheck 37 | ) 38 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | # Building and Installing the Crossplane Rook Provider 2 | 3 | `provider-rook` is composed of a golang project and can be built directly with standard `golang` tools. We currently support two different platforms for building: 4 | 5 | * Linux: most modern distros should work although most testing has been done on Ubuntu 6 | * Mac: macOS 10.6+ is supported 7 | 8 | ## Build Requirements 9 | 10 | An Intel-based machine (recommend 2+ cores, 2+ GB of memory and 128GB of SSD). Inside your build environment (Docker for Mac or a VM), 6+ GB memory is also recommended. 11 | 12 | The following tools are need on the host: 13 | 14 | * curl 15 | * docker (1.12+) or Docker for Mac (17+) 16 | * git 17 | * make 18 | * golang 19 | * rsync (if you're using the build container on mac) 20 | * helm (v2.8.2+) 21 | * kubebuilder (v1.0.4+) 22 | 23 | ## Build 24 | 25 | You can build the Crossplane Rook Provider for the host platform by simply running the command below. 26 | Building in parallel with the `-j` option is recommended. 27 | 28 | ```console 29 | make -j4 30 | ``` 31 | 32 | The first time `make` is run, the build submodule will be synced and 33 | updated. After initial setup, it can be updated by running `make submodules`. 34 | 35 | Run `make help` for more options. 36 | 37 | ## Building inside the cross container 38 | 39 | Official Crossplane builds are done inside a build container. This ensures that we get a consistent build, test and release environment. To run the build inside the cross container run: 40 | 41 | ```console 42 | > build/run make -j4 43 | ``` 44 | 45 | The first run of `build/run` will build the container itself and could take a few minutes to complete, but subsequent builds should go much faster. 46 | 47 | ## Install 48 | 49 | TBD: Steps to install the Rook provider into a Crossplane cluster 50 | -------------------------------------------------------------------------------- /pkg/controller/config/config.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package config 18 | 19 | import ( 20 | ctrl "sigs.k8s.io/controller-runtime" 21 | "sigs.k8s.io/controller-runtime/pkg/source" 22 | 23 | "github.com/crossplane/crossplane-runtime/pkg/event" 24 | "github.com/crossplane/crossplane-runtime/pkg/logging" 25 | "github.com/crossplane/crossplane-runtime/pkg/reconciler/providerconfig" 26 | "github.com/crossplane/crossplane-runtime/pkg/resource" 27 | 28 | "github.com/crossplane/provider-rook/apis/v1beta1" 29 | ) 30 | 31 | // Setup adds a controller that reconciles ProviderConfigs by accounting for 32 | // their current usage. 33 | func Setup(mgr ctrl.Manager, l logging.Logger) error { 34 | name := providerconfig.ControllerName(v1beta1.ProviderConfigGroupKind) 35 | 36 | of := resource.ProviderConfigKinds{ 37 | Config: v1beta1.ProviderConfigGroupVersionKind, 38 | UsageList: v1beta1.ProviderConfigUsageListGroupVersionKind, 39 | } 40 | 41 | return ctrl.NewControllerManagedBy(mgr). 42 | Named(name). 43 | For(&v1beta1.ProviderConfig{}). 44 | Watches(&source.Kind{Type: &v1beta1.ProviderConfigUsage{}}, &resource.EnqueueRequestForProviderConfig{}). 45 | Complete(providerconfig.NewReconciler(mgr, of, 46 | providerconfig.WithLogger(l.WithValues("controller", name)), 47 | providerconfig.WithRecorder(event.NewAPIRecorder(mgr.GetEventRecorderFor(name))))) 48 | } 49 | -------------------------------------------------------------------------------- /config/package/manifests/resources/cockroachcluster.resource.yaml: -------------------------------------------------------------------------------- 1 | id: cockroachcluster 2 | title: CockroachDB Cluster 3 | titlePlural: CockroachDB Clusters 4 | category: Database 5 | overviewShort: "A CockroachCluster configures a Rook 'clusters.cockroachdb.rook.io'" 6 | overview: | 7 | CockroachDB scales horizontally without reconfiguration or need for a massive architectural overhaul. Simply add a new node to the cluster and CockroachDB takes care of the underlying complexity. 8 | readme: | 9 | ## Architect Your Data However You Want 10 | 11 | CockroachDB allows you to deploy a database on-prem, in the cloud or even across clouds, all as a single store. It is a simple and straightforward bridge to your future, cloud-based data architecture. 12 | 13 | * Eliminate risk associated with a single cloud platform 14 | * Deploy on multiple clouds and partition data across them 15 | * Use the right cloud and set of services for the right job 16 | 17 | ## Access Your Data, All The Time & Everywhere 18 | 19 | CockroachDB delivers an always-on and available database designed so that any loss of nodes is consumed without impact to availability. It creates & manages replicates of your data to ensure reliability. 20 | 21 | * Eliminate complex, expensive backup configurations 22 | * Avoid arduous, annoying remediation events (Zero RPO) 23 | * Rolling upgrades eliminate downtime & ease updates/schema changes 24 | 25 | ## Give Your Data A Location 26 | 27 | CockroachDB is the only database in the world that enables you to attach ‘location’ to your data at the row level. This capability allows you to regulate the distance between your users and their data. 28 | 29 | * Ensure low latency to end-users wherever they are. 30 | * Pin data to a locale to comply with data protection laws. 31 | * Tie specific data to specific clouds or datacenters. 32 | 33 | ## Learn more 34 | 35 | This content is from https://www.cockroachlabs.com/product/, you can learn more in the [CockroachDB documentation](https://www.cockroachlabs.com/docs/stable/). -------------------------------------------------------------------------------- /apis/database/v1alpha1/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1alpha1 18 | 19 | import ( 20 | "reflect" 21 | 22 | "k8s.io/apimachinery/pkg/runtime/schema" 23 | "sigs.k8s.io/controller-runtime/pkg/scheme" 24 | ) 25 | 26 | // Package type metadata. 27 | const ( 28 | Group = "database.rook.crossplane.io" 29 | Version = "v1alpha1" 30 | ) 31 | 32 | var ( 33 | // SchemeGroupVersion is group version used to register these objects 34 | SchemeGroupVersion = schema.GroupVersion{Group: Group, Version: Version} 35 | 36 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 37 | SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} 38 | ) 39 | 40 | // YugabyteCluster type metadata. 41 | var ( 42 | YugabyteClusterKind = reflect.TypeOf(YugabyteCluster{}).Name() 43 | YugabyteClusterKindAPIVersion = YugabyteClusterKind + "." + SchemeGroupVersion.String() 44 | YugabyteClusterGroupVersionKind = SchemeGroupVersion.WithKind(YugabyteClusterKind) 45 | ) 46 | 47 | // CockroachCluster type metadata. 48 | var ( 49 | CockroachClusterKind = reflect.TypeOf(CockroachCluster{}).Name() 50 | CockroachClusterKindAPIVersion = CockroachClusterKind + "." + SchemeGroupVersion.String() 51 | CockroachClusterGroupVersionKind = SchemeGroupVersion.WithKind(CockroachClusterKind) 52 | ) 53 | 54 | func init() { 55 | SchemeBuilder.Register(&YugabyteCluster{}, &YugabyteClusterList{}) 56 | SchemeBuilder.Register(&CockroachCluster{}, &CockroachClusterList{}) 57 | } 58 | -------------------------------------------------------------------------------- /apis/v1alpha1/zz_generated.deepcopy.go: -------------------------------------------------------------------------------- 1 | // +build !ignore_autogenerated 2 | 3 | /* 4 | Copyright 2019 The Crossplane 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 | 19 | // Code generated by controller-gen. DO NOT EDIT. 20 | 21 | package v1alpha1 22 | 23 | import ( 24 | "k8s.io/api/core/v1" 25 | ) 26 | 27 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 28 | func (in Annotations) DeepCopyInto(out *Annotations) { 29 | { 30 | in := &in 31 | *out = make(Annotations, len(*in)) 32 | for key, val := range *in { 33 | (*out)[key] = val 34 | } 35 | } 36 | } 37 | 38 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Annotations. 39 | func (in Annotations) DeepCopy() Annotations { 40 | if in == nil { 41 | return nil 42 | } 43 | out := new(Annotations) 44 | in.DeepCopyInto(out) 45 | return *out 46 | } 47 | 48 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 49 | func (in *StorageScopeSpec) DeepCopyInto(out *StorageScopeSpec) { 50 | *out = *in 51 | if in.VolumeClaimTemplates != nil { 52 | in, out := &in.VolumeClaimTemplates, &out.VolumeClaimTemplates 53 | *out = make([]v1.PersistentVolumeClaim, len(*in)) 54 | for i := range *in { 55 | (*in)[i].DeepCopyInto(&(*out)[i]) 56 | } 57 | } 58 | } 59 | 60 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new StorageScopeSpec. 61 | func (in *StorageScopeSpec) DeepCopy() *StorageScopeSpec { 62 | if in == nil { 63 | return nil 64 | } 65 | out := new(StorageScopeSpec) 66 | in.DeepCopyInto(out) 67 | return out 68 | } 69 | -------------------------------------------------------------------------------- /cluster/examples/yugabyte/yugabyte.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: database.rook.crossplane.io/v1alpha1 2 | kind: YugabyteCluster 3 | metadata: 4 | name: test-cluster 5 | spec: 6 | providerRef: 7 | name: demo-k8s-provider 8 | reclaimPolicy: Delete 9 | forProvider: 10 | name: my-test-yugabyte 11 | namespace: rook-yugabytedb 12 | master: 13 | # Replica count for Master. 14 | replicas: 3 15 | # Mentioning network ports is optional. If some or all ports are not specified, then they will be defaulted to below-mentioned values, except for tserver-ui. 16 | network: 17 | ports: 18 | - name: yb-master-ui 19 | port: 7000 # default value 20 | - name: yb-master-rpc 21 | port: 7100 # default value 22 | # Volume claim template for Master 23 | volumeClaimTemplate: 24 | metadata: 25 | name: datadir 26 | spec: 27 | accessModes: [ "ReadWriteOnce" ] 28 | resources: 29 | requests: 30 | storage: 1Gi 31 | storageClassName: standard 32 | tserver: 33 | # Replica count for TServer 34 | replicas: 3 35 | # Mentioning network ports is optional. If some or all ports are not specified, then they will be defaulted to below-mentioned values, except for tserver-ui. 36 | # For tserver-ui a cluster ip service will be created if the yb-tserver-ui port is explicitly mentioned. If it is not specified, only StatefulSet & headless service will be created for TServer. TServer ClusterIP service creation will be skipped. Whereas for Master, all 3 kubernetes objects will always be created. 37 | network: 38 | ports: 39 | - name: yb-tserver-ui 40 | port: 9000 41 | - name: yb-tserver-rpc 42 | port: 9100 # default value 43 | - name: ycql 44 | port: 9042 # default value 45 | - name: yedis 46 | port: 6379 # default value 47 | - name: ysql 48 | port: 5433 # default value 49 | # Volume claim template for TServer 50 | volumeClaimTemplate: 51 | metadata: 52 | name: datadir 53 | spec: 54 | accessModes: [ "ReadWriteOnce" ] 55 | resources: 56 | requests: 57 | storage: 1Gi 58 | storageClassName: standard 59 | -------------------------------------------------------------------------------- /config/package/manifests/app.yaml: -------------------------------------------------------------------------------- 1 | # Human readable title of application. 2 | title: Rook Provider 3 | 4 | overviewShort: The Rook Crossplane provider enables resource management for Rook. 5 | overview: |- 6 | The Rook Crossplane provider adds support for managing Rook resources from a Crossplane Kubernetes cluster. 7 | 8 | YugabyteDB and CockroachDB cluster resources can be provisioned, updated, and deleted by this provider. 9 | 10 | # Markdown description of this entry 11 | readme: | 12 | This `provider-rook` repository is a Crossplane infrastructure provider for [Rook](https://rook.io/). 13 | The provider that is built from the source code in this repository can be installed into a Crossplane control plane and adds the following new functionality: 14 | 15 | * Custom Resource Definitions (CRDs) that model Rook infrastructure and services (e.g. [Yugabyte](https://github.com/yugabyte/yugabyte-db), [CockroachDB](https://github.com/cockroachdb/cockroach), etc.) 16 | * Controllers to provision these resources in a Rook Kubernetes cluster based on the users desired state captured in CRDs they create 17 | * Implementations of Crossplane's portable resource abstractions, enabling Rook resources to fulfill a user's general need for cloud services 18 | 19 | # Maintainer names and emails. 20 | maintainers: 21 | - name: Jared Watts 22 | email: jared@upbound.io 23 | 24 | # Owner names and emails. 25 | owners: 26 | - name: Jared Watts 27 | email: jared@upbound.io 28 | 29 | # Human readable company name 30 | company: Crossplane 31 | 32 | # Primary category describing this package 33 | category: Infrastructure 34 | 35 | # Type of package: Provider, Stack, or Application 36 | packageType: Provider 37 | 38 | # Keywords that describe this application and help search indexing 39 | keywords: 40 | - "rook" 41 | - "infrastructure" 42 | 43 | # Links to more information about the application (about page, source code, etc.) 44 | website: "https://crossplane.io" 45 | source: "https://github.com/crossplane/provider-rook" 46 | 47 | # RBAC ClusterRoles will be generated permitting this package to use all verbs on all 48 | # resources in the groups listed below. 49 | permissionScope: Cluster 50 | dependsOn: 51 | - crd: '*.cache.crossplane.io/v1alpha1' 52 | - crd: '*.compute.crossplane.io/v1alpha1' 53 | - crd: '*.database.crossplane.io/v1alpha1' 54 | - crd: '*.kubernetes.crossplane.io/v1alpha1' 55 | - crd: '*.core.crossplane.io/v1alpha1' 56 | - crd: '*.storage.crossplane.io/v1alpha1' 57 | - crd: '*.workload.crossplane.io/v1alpha1' 58 | 59 | # License SPDX name: https://spdx.org/licenses/ 60 | license: Apache-2.0 61 | -------------------------------------------------------------------------------- /cmd/provider/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "os" 21 | "path/filepath" 22 | 23 | "gopkg.in/alecthomas/kingpin.v2" 24 | ctrl "sigs.k8s.io/controller-runtime" 25 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 26 | 27 | "github.com/crossplane/provider-rook/apis" 28 | "github.com/crossplane/provider-rook/pkg/controller" 29 | 30 | "github.com/crossplane/crossplane-runtime/pkg/logging" 31 | ) 32 | 33 | func main() { 34 | var ( 35 | app = kingpin.New(filepath.Base(os.Args[0]), "Rook support for Crossplane.").DefaultEnvars() 36 | debug = app.Flag("debug", "Run with debug logging.").Short('d').Bool() 37 | syncPeriod = app.Flag("sync", "Controller manager sync period duration such as 300ms, 1.5h or 2h45m").Short('s').Default("1h").Duration() 38 | leaderElection = app.Flag("leader-election", "Use leader election for the conroller manager.").Short('l').Default("false").OverrideDefaultFromEnvar("LEADER_ELECTION").Bool() 39 | ) 40 | kingpin.MustParse(app.Parse(os.Args[1:])) 41 | 42 | zl := zap.New(zap.UseDevMode(*debug)) 43 | log := logging.NewLogrLogger(zl.WithName("provider-rook")) 44 | if *debug { 45 | // The controller-runtime runs with a no-op logger by default. It is 46 | // *very* verbose even at info level, so we only provide it a real 47 | // logger when we're running in debug mode. 48 | ctrl.SetLogger(zl) 49 | } 50 | 51 | log.Debug("Starting", "sync-period", syncPeriod.String()) 52 | 53 | cfg, err := ctrl.GetConfig() 54 | kingpin.FatalIfError(err, "Cannot get API server rest config") 55 | 56 | mgr, err := ctrl.NewManager(cfg, ctrl.Options{ 57 | LeaderElection: *leaderElection, 58 | LeaderElectionID: "crossplane-leader-election-provider-rook", 59 | SyncPeriod: syncPeriod, 60 | }) 61 | kingpin.FatalIfError(err, "Cannot create controller manager") 62 | 63 | kingpin.FatalIfError(apis.AddToScheme(mgr.GetScheme()), "Cannot add AWS APIs to scheme") 64 | kingpin.FatalIfError(controller.Setup(mgr, log), "Cannot setup AWS controllers") 65 | kingpin.FatalIfError(mgr.Start(ctrl.SetupSignalHandler()), "Cannot start controller manager") 66 | } 67 | -------------------------------------------------------------------------------- /apis/v1beta1/register.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta1 18 | 19 | import ( 20 | "reflect" 21 | 22 | "k8s.io/apimachinery/pkg/runtime/schema" 23 | "sigs.k8s.io/controller-runtime/pkg/scheme" 24 | ) 25 | 26 | // Package type metadata. 27 | const ( 28 | Group = "rook.crossplane.io" 29 | Version = "v1beta1" 30 | ) 31 | 32 | var ( 33 | // SchemeGroupVersion is group version used to register these objects 34 | SchemeGroupVersion = schema.GroupVersion{Group: Group, Version: Version} 35 | 36 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 37 | SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} 38 | ) 39 | 40 | // ProviderConfig type metadata. 41 | var ( 42 | ProviderConfigKind = reflect.TypeOf(ProviderConfig{}).Name() 43 | ProviderConfigGroupKind = schema.GroupKind{Group: Group, Kind: ProviderConfigKind}.String() 44 | ProviderConfigKindAPIVersion = ProviderConfigKind + "." + SchemeGroupVersion.String() 45 | ProviderConfigGroupVersionKind = SchemeGroupVersion.WithKind(ProviderConfigKind) 46 | ) 47 | 48 | // ProviderConfigUsage type metadata. 49 | var ( 50 | ProviderConfigUsageKind = reflect.TypeOf(ProviderConfigUsage{}).Name() 51 | ProviderConfigUsageGroupKind = schema.GroupKind{Group: Group, Kind: ProviderConfigUsageKind}.String() 52 | ProviderConfigUsageKindAPIVersion = ProviderConfigUsageKind + "." + SchemeGroupVersion.String() 53 | ProviderConfigUsageGroupVersionKind = SchemeGroupVersion.WithKind(ProviderConfigUsageKind) 54 | 55 | ProviderConfigUsageListKind = reflect.TypeOf(ProviderConfigUsageList{}).Name() 56 | ProviderConfigUsageListGroupKind = schema.GroupKind{Group: Group, Kind: ProviderConfigUsageListKind}.String() 57 | ProviderConfigUsageListKindAPIVersion = ProviderConfigUsageListKind + "." + SchemeGroupVersion.String() 58 | ProviderConfigUsageListGroupVersionKind = SchemeGroupVersion.WithKind(ProviderConfigUsageListKind) 59 | ) 60 | 61 | func init() { 62 | SchemeBuilder.Register(&ProviderConfig{}, &ProviderConfigList{}) 63 | SchemeBuilder.Register(&ProviderConfigUsage{}, &ProviderConfigUsageList{}) 64 | } 65 | -------------------------------------------------------------------------------- /pkg/clients/database/yugabyte/yugabyte.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package yugabyte 18 | 19 | import ( 20 | "reflect" 21 | 22 | rook "github.com/rook/rook/pkg/apis/rook.io/v1alpha2" 23 | rookv1alpha1 "github.com/rook/rook/pkg/apis/yugabytedb.rook.io/v1alpha1" 24 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | 26 | "github.com/crossplane/provider-rook/apis/database/v1alpha1" 27 | ) 28 | 29 | // CrossToRook converts a Crossplane Yugabyte cluster object to a Rook Yugabyte 30 | // cluster object. 31 | func CrossToRook(c *v1alpha1.YugabyteCluster) *rookv1alpha1.YBCluster { 32 | params := c.Spec.YugabyteClusterParameters 33 | return &rookv1alpha1.YBCluster{ 34 | ObjectMeta: metav1.ObjectMeta{ 35 | Name: params.Name, 36 | Namespace: params.Namespace, 37 | }, 38 | Spec: rookv1alpha1.YBClusterSpec{ 39 | Annotations: rook.Annotations(params.Annotations), 40 | Master: convertServer(params.Master), 41 | TServer: convertServer(params.TServer), 42 | }, 43 | } 44 | } 45 | 46 | // NeedsUpdate determines whether the external Rook Yugabyte cluster needs to be 47 | // updated. 48 | func NeedsUpdate(c *v1alpha1.YugabyteCluster, e *rookv1alpha1.YBCluster) bool { 49 | params := c.Spec.YugabyteClusterParameters 50 | if !reflect.DeepEqual(rook.Annotations(params.Annotations), e.Spec.Annotations) { 51 | return true 52 | } 53 | if !reflect.DeepEqual(convertServer(params.Master), e.Spec.Master) { 54 | return true 55 | } 56 | if !reflect.DeepEqual(convertServer(params.TServer), e.Spec.TServer) { 57 | return true 58 | } 59 | return false 60 | } 61 | 62 | func convertServer(server v1alpha1.ServerSpec) rookv1alpha1.ServerSpec { 63 | return rookv1alpha1.ServerSpec{ 64 | Replicas: server.Replicas, 65 | Network: rookv1alpha1.NetworkSpec{ 66 | Ports: convertPorts(server.Network.Ports), 67 | }, 68 | VolumeClaimTemplate: server.VolumeClaimTemplate, 69 | } 70 | } 71 | 72 | func convertPorts(ports []v1alpha1.PortSpec) []rookv1alpha1.PortSpec { 73 | rookports := make([]rookv1alpha1.PortSpec, len(ports)) 74 | for i, p := range ports { 75 | rookports[i] = rookv1alpha1.PortSpec{ 76 | Name: p.Name, 77 | Port: p.Port, 78 | } 79 | } 80 | return rookports 81 | } 82 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # provider-rook 2 | 3 | ## Overview 4 | 5 | This `provider-rook` repository is the Crossplane infrastructure provider for 6 | [Rook](https://rook.io/). The provider that is built from the source code in 7 | this repository can be installed into a Crossplane control plane and adds the 8 | following new functionality: 9 | 10 | * Custom Resource Definitions (CRDs) that model Rook infrastructure and services 11 | (e.g. [Yugabyte](https://github.com/yugabyte/yugabyte-db), 12 | [CockroachDB](https://github.com/cockroachdb/cockroach), etc.) 13 | * Controllers to provision these resources in a Rook Kubernetes cluster based on 14 | the users desired state captured in CRDs they create 15 | * Implementations of Crossplane's portable resource abstractions, enabling Rook 16 | resources to fulfill a user's general need for cloud services 17 | 18 | ## Getting Started and Documentation 19 | 20 | For getting started guides, installation, deployment, and administration, see 21 | our [Documentation](https://crossplane.io/docs/latest). 22 | 23 | ## Contributing 24 | 25 | provider-rook is a community driven project and we welcome contributions. See 26 | the Crossplane 27 | [Contributing](https://github.com/crossplane/crossplane/blob/master/CONTRIBUTING.md) 28 | guidelines to get started. 29 | 30 | ## Report a Bug 31 | 32 | For filing bugs, suggesting improvements, or requesting new features, please 33 | open an [issue](https://github.com/crossplane/provider-rook/issues). 34 | 35 | ## Contact 36 | 37 | Please use the following to reach members of the community: 38 | 39 | - Slack: Join our [slack channel](https://slack.crossplane.io) 40 | - Forums: 41 | [crossplane-dev](https://groups.google.com/forum/#!forum/crossplane-dev) 42 | - Twitter: [@crossplane_io](https://twitter.com/crossplane_io) 43 | - Email: [info@crossplane.io](mailto:info@crossplane.io) 44 | 45 | ## Roadmap 46 | 47 | provider-rook goals and milestones are currently tracked in the Crossplane 48 | repository. More information can be found in 49 | [ROADMAP.md](https://github.com/crossplane/crossplane/blob/master/ROADMAP.md). 50 | 51 | ## Governance and Owners 52 | 53 | provider-rook is run according to the same 54 | [Governance](https://github.com/crossplane/crossplane/blob/master/GOVERNANCE.md) 55 | and [Ownership](https://github.com/crossplane/crossplane/blob/master/OWNERS.md) 56 | structure as the core Crossplane project. 57 | 58 | ## Code of Conduct 59 | 60 | provider-rook adheres to the same [Code of 61 | Conduct](https://github.com/crossplane/crossplane/blob/master/CODE_OF_CONDUCT.md) 62 | as the core Crossplane project. 63 | 64 | ## Licensing 65 | 66 | provider-rook is under the Apache 2.0 license. 67 | 68 | [![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fcrossplane%2Fprovider-rook.svg?type=large)](https://app.fossa.io/projects/git%2Bgithub.com%2Fcrossplane%2Fprovider-rook?ref=badge_large) 69 | -------------------------------------------------------------------------------- /config/crd/rook.crossplane.io_providerconfigs.yaml: -------------------------------------------------------------------------------- 1 | 2 | --- 3 | apiVersion: apiextensions.k8s.io/v1beta1 4 | kind: CustomResourceDefinition 5 | metadata: 6 | annotations: 7 | controller-gen.kubebuilder.io/version: v0.2.4 8 | creationTimestamp: null 9 | name: providerconfigs.rook.crossplane.io 10 | spec: 11 | additionalPrinterColumns: 12 | - JSONPath: .metadata.creationTimestamp 13 | name: AGE 14 | type: date 15 | - JSONPath: .spec.credentialsSecretRef.name 16 | name: SECRET-NAME 17 | priority: 1 18 | type: string 19 | group: rook.crossplane.io 20 | names: 21 | categories: 22 | - crossplane 23 | - provider 24 | - rook 25 | kind: ProviderConfig 26 | listKind: ProviderConfigList 27 | plural: providerconfigs 28 | singular: providerconfig 29 | scope: Cluster 30 | subresources: {} 31 | validation: 32 | openAPIV3Schema: 33 | description: A ProviderConfig configures how AWS controllers will connect to AWS API. 34 | properties: 35 | apiVersion: 36 | description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 37 | type: string 38 | kind: 39 | description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 40 | type: string 41 | metadata: 42 | type: object 43 | spec: 44 | description: A ProviderConfigSpec defines the desired state of a ProviderConfig. 45 | properties: 46 | credentialsSecretRef: 47 | description: CredentialsSecretRef references a specific secret's key that contains the credentials that are used to connect to the provider. 48 | properties: 49 | key: 50 | description: The key to select. 51 | type: string 52 | name: 53 | description: Name of the secret. 54 | type: string 55 | namespace: 56 | description: Namespace of the secret. 57 | type: string 58 | required: 59 | - key 60 | - name 61 | - namespace 62 | type: object 63 | type: object 64 | required: 65 | - spec 66 | type: object 67 | version: v1beta1 68 | versions: 69 | - name: v1beta1 70 | served: true 71 | storage: true 72 | status: 73 | acceptedNames: 74 | kind: "" 75 | plural: "" 76 | conditions: [] 77 | storedVersions: [] 78 | -------------------------------------------------------------------------------- /pkg/clients/database/cockroach/cockroach.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package cockroach 18 | 19 | import ( 20 | "reflect" 21 | 22 | rookv1alpha1 "github.com/rook/rook/pkg/apis/cockroachdb.rook.io/v1alpha1" 23 | rook "github.com/rook/rook/pkg/apis/rook.io/v1alpha2" 24 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | 26 | "github.com/crossplane/provider-rook/apis/database/v1alpha1" 27 | ) 28 | 29 | // CrossToRook converts a Crossplane Yugabyte cluster object to a Rook Yugabyte 30 | // cluster object. 31 | func CrossToRook(c *v1alpha1.CockroachCluster) *rookv1alpha1.Cluster { 32 | params := c.Spec.CockroachClusterParameters 33 | return &rookv1alpha1.Cluster{ 34 | ObjectMeta: metav1.ObjectMeta{ 35 | Name: params.Name, 36 | Namespace: params.Namespace, 37 | }, 38 | Spec: rookv1alpha1.ClusterSpec{ 39 | Annotations: rook.Annotations(params.Annotations), 40 | Storage: rook.StorageScopeSpec{ 41 | NodeCount: params.Storage.NodeCount, 42 | Selection: rook.Selection{ 43 | VolumeClaimTemplates: params.Storage.VolumeClaimTemplates, 44 | }, 45 | }, 46 | Network: rookv1alpha1.NetworkSpec{ 47 | Ports: convertPorts(params.Network.Ports), 48 | }, 49 | Secure: params.Secure, 50 | CachePercent: params.CachePercent, 51 | MaxSQLMemoryPercent: params.MaxSQLMemoryPercent, 52 | }, 53 | } 54 | } 55 | 56 | // NeedsUpdate determines whether the external Rook Cockroach cluster needs to be 57 | // updated. 58 | func NeedsUpdate(c *v1alpha1.CockroachCluster, e *rookv1alpha1.Cluster) bool { 59 | params := c.Spec.CockroachClusterParameters 60 | if !reflect.DeepEqual(rook.Annotations(params.Annotations), e.Spec.Annotations) { 61 | return true 62 | } 63 | if !reflect.DeepEqual(params.Storage.NodeCount, e.Spec.Storage.NodeCount) { 64 | return true 65 | } 66 | if !reflect.DeepEqual(params.Storage.VolumeClaimTemplates, e.Spec.Storage.VolumeClaimTemplates) { 67 | return true 68 | } 69 | if !reflect.DeepEqual(convertPorts(params.Network.Ports), e.Spec.Network.Ports) { 70 | return true 71 | } 72 | if !reflect.DeepEqual(params.CachePercent, e.Spec.CachePercent) { 73 | return true 74 | } 75 | if !reflect.DeepEqual(params.MaxSQLMemoryPercent, e.Spec.MaxSQLMemoryPercent) { 76 | return true 77 | } 78 | return false 79 | } 80 | 81 | func convertPorts(ports []v1alpha1.PortSpec) []rookv1alpha1.PortSpec { 82 | rookports := make([]rookv1alpha1.PortSpec, len(ports)) 83 | for i, p := range ports { 84 | rookports[i] = rookv1alpha1.PortSpec{ 85 | Name: p.Name, 86 | Port: p.Port, 87 | } 88 | } 89 | return rookports 90 | } 91 | -------------------------------------------------------------------------------- /apis/v1beta1/providerconfig_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1beta1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | 22 | xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" 23 | ) 24 | 25 | // A ProviderConfigSpec defines the desired state of a ProviderConfig. 26 | type ProviderConfigSpec struct { 27 | xpv1.ProviderConfigSpec `json:",inline"` 28 | } 29 | 30 | // A ProviderConfigStatus represents the status of a ProviderConfig. 31 | type ProviderConfigStatus struct { 32 | xpv1.ProviderConfigStatus `json:",inline"` 33 | } 34 | 35 | // +kubebuilder:object:root=true 36 | 37 | // A ProviderConfig configures how AWS controllers will connect to AWS API. 38 | // +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" 39 | // +kubebuilder:printcolumn:name="SECRET-NAME",type="string",JSONPath=".spec.credentialsSecretRef.name",priority=1 40 | // +kubebuilder:resource:scope=Cluster,categories={crossplane,provider,rook} 41 | // +kubebuilder:subresource:status 42 | type ProviderConfig struct { 43 | metav1.TypeMeta `json:",inline"` 44 | metav1.ObjectMeta `json:"metadata,omitempty"` 45 | 46 | Spec ProviderConfigSpec `json:"spec"` 47 | Status ProviderConfigStatus `json:"status,omitempty"` 48 | } 49 | 50 | // +kubebuilder:object:root=true 51 | 52 | // ProviderConfigList contains a list of ProviderConfig 53 | type ProviderConfigList struct { 54 | metav1.TypeMeta `json:",inline"` 55 | metav1.ListMeta `json:"metadata,omitempty"` 56 | Items []ProviderConfig `json:"items"` 57 | } 58 | 59 | // +kubebuilder:object:root=true 60 | 61 | // A ProviderConfigUsage indicates that a resource is using a ProviderConfig. 62 | // +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" 63 | // +kubebuilder:printcolumn:name="CONFIG-NAME",type="string",JSONPath=".providerConfigRef.name" 64 | // +kubebuilder:printcolumn:name="RESOURCE-KIND",type="string",JSONPath=".resourceRef.kind" 65 | // +kubebuilder:printcolumn:name="RESOURCE-NAME",type="string",JSONPath=".resourceRef.name" 66 | // +kubebuilder:resource:scope=Cluster,categories={crossplane,provider,rook} 67 | type ProviderConfigUsage struct { 68 | metav1.TypeMeta `json:",inline"` 69 | metav1.ObjectMeta `json:"metadata,omitempty"` 70 | 71 | xpv1.ProviderConfigUsage `json:",inline"` 72 | } 73 | 74 | // +kubebuilder:object:root=true 75 | 76 | // ProviderConfigUsageList contains a list of ProviderConfigUsage 77 | type ProviderConfigUsageList struct { 78 | metav1.TypeMeta `json:",inline"` 79 | metav1.ListMeta `json:"metadata,omitempty"` 80 | Items []ProviderConfigUsage `json:"items"` 81 | } 82 | -------------------------------------------------------------------------------- /package/crds/rook.crossplane.io_providerconfigusages.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | annotations: 5 | controller-gen.kubebuilder.io/version: v0.3.0 6 | creationTimestamp: null 7 | name: providerconfigusages.rook.crossplane.io 8 | spec: 9 | group: rook.crossplane.io 10 | names: 11 | categories: 12 | - crossplane 13 | - provider 14 | - rook 15 | kind: ProviderConfigUsage 16 | listKind: ProviderConfigUsageList 17 | plural: providerconfigusages 18 | singular: providerconfigusage 19 | scope: Cluster 20 | versions: 21 | - additionalPrinterColumns: 22 | - jsonPath: .metadata.creationTimestamp 23 | name: AGE 24 | type: date 25 | - jsonPath: .providerConfigRef.name 26 | name: CONFIG-NAME 27 | type: string 28 | - jsonPath: .resourceRef.kind 29 | name: RESOURCE-KIND 30 | type: string 31 | - jsonPath: .resourceRef.name 32 | name: RESOURCE-NAME 33 | type: string 34 | name: v1beta1 35 | schema: 36 | openAPIV3Schema: 37 | description: A ProviderConfigUsage indicates that a resource is using a ProviderConfig. 38 | properties: 39 | apiVersion: 40 | description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 41 | type: string 42 | kind: 43 | description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 44 | type: string 45 | metadata: 46 | type: object 47 | providerConfigRef: 48 | description: ProviderConfigReference to the provider config being used. 49 | properties: 50 | name: 51 | description: Name of the referenced object. 52 | type: string 53 | required: 54 | - name 55 | type: object 56 | resourceRef: 57 | description: ResourceReference to the managed resource using the provider config. 58 | properties: 59 | apiVersion: 60 | description: APIVersion of the referenced object. 61 | type: string 62 | kind: 63 | description: Kind of the referenced object. 64 | type: string 65 | name: 66 | description: Name of the referenced object. 67 | type: string 68 | uid: 69 | description: UID of the referenced object. 70 | type: string 71 | required: 72 | - apiVersion 73 | - kind 74 | - name 75 | type: object 76 | required: 77 | - providerConfigRef 78 | - resourceRef 79 | type: object 80 | served: true 81 | storage: true 82 | subresources: {} 83 | status: 84 | acceptedNames: 85 | kind: "" 86 | plural: "" 87 | conditions: [] 88 | storedVersions: [] 89 | -------------------------------------------------------------------------------- /pkg/clients/client.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package clients 18 | 19 | import ( 20 | "context" 21 | 22 | "github.com/pkg/errors" 23 | corev1 "k8s.io/api/core/v1" 24 | "k8s.io/apimachinery/pkg/runtime" 25 | "k8s.io/apimachinery/pkg/types" 26 | "k8s.io/client-go/tools/clientcmd" 27 | "sigs.k8s.io/controller-runtime/pkg/client" 28 | 29 | xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" 30 | "github.com/crossplane/crossplane-runtime/pkg/resource" 31 | 32 | "github.com/crossplane/provider-rook/apis/v1beta1" 33 | ) 34 | 35 | const ( 36 | errGetProviderConfig = "cannot get referenced ProviderConfig" 37 | errTrackUsage = "cannot track ProviderConfig usage" 38 | errNoSecretRef = "no connection secret reference was supplied" 39 | errGetSecret = "cannot get referenced credentials secret" 40 | errNoRefGiven = "neither providerConfigRef nor providerRef was supplied" 41 | errConstructClientConfig = "cannot construct a client config from data in the credentials secret" 42 | errConstructRestConfig = "cannot construct a rest config from client config" 43 | errNewClient = "cannot create a new controller-runtime client" 44 | 45 | errFmtUnsupportedCredSource = "unsupported credentials secret source %q" 46 | ) 47 | 48 | // NewClient returns a kubernetes client with the information in provider config 49 | // reference of given managed resource. If the reference is a 50 | // ProviderConfigReference, the Rook ProviderConfig is used. If the reference is 51 | // a ProviderReference, the deprecated core Crossplane Kubernetes Provider is 52 | // used. 53 | func NewClient(ctx context.Context, c client.Client, mg resource.Managed, s *runtime.Scheme) (client.Client, error) { // nolint:gocyclo 54 | switch { 55 | case mg.GetProviderConfigReference() != nil: 56 | return UseProviderConfig(ctx, c, mg, s) 57 | default: 58 | return nil, errors.New(errNoRefGiven) 59 | } 60 | } 61 | 62 | // UseProviderConfig to create a client. 63 | func UseProviderConfig(ctx context.Context, c client.Client, mg resource.Managed, s *runtime.Scheme) (client.Client, error) { 64 | pc := &v1beta1.ProviderConfig{} 65 | if err := c.Get(ctx, types.NamespacedName{Name: mg.GetProviderConfigReference().Name}, pc); err != nil { 66 | return nil, errors.Wrap(err, errGetProviderConfig) 67 | } 68 | 69 | t := resource.NewProviderConfigUsageTracker(c, &v1beta1.ProviderConfigUsage{}) 70 | if err := t.Track(ctx, mg); err != nil { 71 | return nil, errors.Wrap(err, errTrackUsage) 72 | } 73 | 74 | if s := pc.Spec.Credentials.Source; s != xpv1.CredentialsSourceSecret { 75 | return c, errors.Errorf(errFmtUnsupportedCredSource, s) 76 | } 77 | 78 | ref := pc.Spec.Credentials.SecretRef 79 | if ref == nil { 80 | return c, errors.New(errNoSecretRef) 81 | } 82 | 83 | secret := &corev1.Secret{} 84 | if err := c.Get(ctx, types.NamespacedName{Name: ref.Name, Namespace: ref.Namespace}, secret); err != nil { 85 | return nil, errors.Wrap(err, errGetSecret) 86 | } 87 | 88 | cfg, err := clientcmd.NewClientConfigFromBytes(secret.Data[ref.Key]) 89 | if err != nil { 90 | return nil, errors.Wrap(err, errConstructClientConfig) 91 | } 92 | restCfg, err := cfg.ClientConfig() 93 | if err != nil { 94 | return nil, errors.Wrap(err, errConstructRestConfig) 95 | } 96 | 97 | kc, err := client.New(restCfg, client.Options{Scheme: s}) 98 | if err != nil { 99 | return nil, errors.Wrap(err, errNewClient) 100 | } 101 | 102 | return kc, nil 103 | } 104 | -------------------------------------------------------------------------------- /apis/database/v1alpha1/zz_generated.managed.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Code generated by angryjet. DO NOT EDIT. 18 | 19 | package v1alpha1 20 | 21 | import xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" 22 | 23 | // GetCondition of this CockroachCluster. 24 | func (mg *CockroachCluster) GetCondition(ct xpv1.ConditionType) xpv1.Condition { 25 | return mg.Status.GetCondition(ct) 26 | } 27 | 28 | // GetDeletionPolicy of this CockroachCluster. 29 | func (mg *CockroachCluster) GetDeletionPolicy() xpv1.DeletionPolicy { 30 | return mg.Spec.DeletionPolicy 31 | } 32 | 33 | // GetProviderConfigReference of this CockroachCluster. 34 | func (mg *CockroachCluster) GetProviderConfigReference() *xpv1.Reference { 35 | return mg.Spec.ProviderConfigReference 36 | } 37 | 38 | /* 39 | GetProviderReference of this CockroachCluster. 40 | Deprecated: Use GetProviderConfigReference. 41 | */ 42 | func (mg *CockroachCluster) GetProviderReference() *xpv1.Reference { 43 | return mg.Spec.ProviderReference 44 | } 45 | 46 | // GetWriteConnectionSecretToReference of this CockroachCluster. 47 | func (mg *CockroachCluster) GetWriteConnectionSecretToReference() *xpv1.SecretReference { 48 | return mg.Spec.WriteConnectionSecretToReference 49 | } 50 | 51 | // SetConditions of this CockroachCluster. 52 | func (mg *CockroachCluster) SetConditions(c ...xpv1.Condition) { 53 | mg.Status.SetConditions(c...) 54 | } 55 | 56 | // SetDeletionPolicy of this CockroachCluster. 57 | func (mg *CockroachCluster) SetDeletionPolicy(r xpv1.DeletionPolicy) { 58 | mg.Spec.DeletionPolicy = r 59 | } 60 | 61 | // SetProviderConfigReference of this CockroachCluster. 62 | func (mg *CockroachCluster) SetProviderConfigReference(r *xpv1.Reference) { 63 | mg.Spec.ProviderConfigReference = r 64 | } 65 | 66 | /* 67 | SetProviderReference of this CockroachCluster. 68 | Deprecated: Use SetProviderConfigReference. 69 | */ 70 | func (mg *CockroachCluster) SetProviderReference(r *xpv1.Reference) { 71 | mg.Spec.ProviderReference = r 72 | } 73 | 74 | // SetWriteConnectionSecretToReference of this CockroachCluster. 75 | func (mg *CockroachCluster) SetWriteConnectionSecretToReference(r *xpv1.SecretReference) { 76 | mg.Spec.WriteConnectionSecretToReference = r 77 | } 78 | 79 | // GetCondition of this YugabyteCluster. 80 | func (mg *YugabyteCluster) GetCondition(ct xpv1.ConditionType) xpv1.Condition { 81 | return mg.Status.GetCondition(ct) 82 | } 83 | 84 | // GetDeletionPolicy of this YugabyteCluster. 85 | func (mg *YugabyteCluster) GetDeletionPolicy() xpv1.DeletionPolicy { 86 | return mg.Spec.DeletionPolicy 87 | } 88 | 89 | // GetProviderConfigReference of this YugabyteCluster. 90 | func (mg *YugabyteCluster) GetProviderConfigReference() *xpv1.Reference { 91 | return mg.Spec.ProviderConfigReference 92 | } 93 | 94 | /* 95 | GetProviderReference of this YugabyteCluster. 96 | Deprecated: Use GetProviderConfigReference. 97 | */ 98 | func (mg *YugabyteCluster) GetProviderReference() *xpv1.Reference { 99 | return mg.Spec.ProviderReference 100 | } 101 | 102 | // GetWriteConnectionSecretToReference of this YugabyteCluster. 103 | func (mg *YugabyteCluster) GetWriteConnectionSecretToReference() *xpv1.SecretReference { 104 | return mg.Spec.WriteConnectionSecretToReference 105 | } 106 | 107 | // SetConditions of this YugabyteCluster. 108 | func (mg *YugabyteCluster) SetConditions(c ...xpv1.Condition) { 109 | mg.Status.SetConditions(c...) 110 | } 111 | 112 | // SetDeletionPolicy of this YugabyteCluster. 113 | func (mg *YugabyteCluster) SetDeletionPolicy(r xpv1.DeletionPolicy) { 114 | mg.Spec.DeletionPolicy = r 115 | } 116 | 117 | // SetProviderConfigReference of this YugabyteCluster. 118 | func (mg *YugabyteCluster) SetProviderConfigReference(r *xpv1.Reference) { 119 | mg.Spec.ProviderConfigReference = r 120 | } 121 | 122 | /* 123 | SetProviderReference of this YugabyteCluster. 124 | Deprecated: Use SetProviderConfigReference. 125 | */ 126 | func (mg *YugabyteCluster) SetProviderReference(r *xpv1.Reference) { 127 | mg.Spec.ProviderReference = r 128 | } 129 | 130 | // SetWriteConnectionSecretToReference of this YugabyteCluster. 131 | func (mg *YugabyteCluster) SetWriteConnectionSecretToReference(r *xpv1.SecretReference) { 132 | mg.Spec.WriteConnectionSecretToReference = r 133 | } 134 | -------------------------------------------------------------------------------- /config/package/manifests/icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Application Icons/Rook/65x65 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /package/crossplane.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: meta.pkg.crossplane.io/v1alpha1 2 | kind: Provider 3 | metadata: 4 | name: provider-rook 5 | annotations: 6 | company: Crossplane 7 | maintainer: Crossplane Maintainers 8 | source: github.com/crossplane/provider-rook 9 | license: Apache-2.0 10 | descriptionShort: | 11 | The Rook Crossplane provider enables resource management for Rook. 12 | 13 | description: | 14 | The Rook Crossplane provider adds support for managing Rook resources 15 | from a Crossplane Kubernetes cluster. YugabyteDB and CockroachDB cluster 16 | resources can be provisioned, updated, and deleted by this provider. 17 | 18 | readme: | 19 | `provider-rook` is the Crossplane infrastructure provider for 20 | [Rook](https://rook.io/). 21 | 22 | Available resources and their fields can be found in the [CRD 23 | Docs](https://doc.crds.dev/github.com/crossplane/provider-rook). 24 | 25 | If you encounter an issue please reach out on 26 | [slack.crossplane.io](https://slack.crossplane.io) and create an issue in 27 | the [crossplane/provider-rook](https://github.com/crossplane/provider-rook) 28 | repo. 29 | 30 | iconData: CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgd2lkdGg9IjY1IiBoZWlnaHQ9IjY1Ij48ZGVmcz48cGF0aCBpZD0iYSIgZD0iTS4wMDAxMjMxNS40MDM5MzgxNUgzNC43MTg4NzY4VjIzLjcxNDU2ODJILjAwMDEyMzE1eiIvPjxwYXRoIGlkPSJjIiBkPSJNLjAwMDI0NjMuMjcwNzM5NzRoMzQuNzE4NjMwNVYxMi4zMDgyMDcySC4wMDAyNDYzeiIvPjwvZGVmcz48ZyBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPjxyZWN0IHdpZHRoPSI2NSIgaGVpZ2h0PSI2NSIgZmlsbD0iIzE3MzU1RCIgZmlsbC1ydWxlPSJub256ZXJvIiByeD0iMTYiLz48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNSAyOC4yMDMpIj48bWFzayBpZD0iYiIgZmlsbD0iI2ZmZiI+PHVzZSB4bGluazpocmVmPSIjYSIvPjwvbWFzaz48cGF0aCBmaWxsPSIjMkFDNkVBIiBkPSJNMi40MTA3NzE0MiAyLjc4NDUxNTk2VjE1LjM4MjQyNDNjMCAzLjI4MTczMTQgMi43MDMxMjc5NCA1Ljk1MTc0ODYgNi4wMjY5Mjg1NCA1Ljk1MTc0ODZIMjYuMjgxNDIzMWMzLjMyMzE4NDkgMCA2LjAyNjkyODYtMi42NzAwMTcyIDYuMDI2OTI4Ni01Ljk1MTc0ODZWMi43ODQ1MTU5NkgyLjQxMDc3MTQyek0yNi4yODE0MjMxIDIzLjcxNDc1MDdIOC40Mzc2OTk5NmMtNC42NTI1ODE5NCAwLTguNDM3NTc2ODEtMy43MzgzODg5LTguNDM3NTc2ODEtOC4zMzIzMjY0VjEuNTkzOTIzMDJjMC0uNjU3MzE5MTkuNTM5Mzk0MS0xLjE4OTk4NDg3IDEuMjA1MDE2MjYtMS4xODk5ODQ4N0gzMy41MTMzNjc5Yy42NjU2MjIyIDAgMS4yMDU2MzIuNTMyNjY1NjggMS4yMDU2MzIgMS4xODk5ODQ4N1YxNS4zODI0MjQzYzAgNC41OTM5Mzc1LTMuNzg1NjEwNiA4LjMzMjMyNjQtOC40Mzc1NzY4IDguMzMyMzI2NHoiIG1hc2s9InVybCgjYikiLz48L2c+PHBhdGggZmlsbD0iIzJBQzZFQSIgZD0iTTI5LjcwMTY4NDcgNDIuOTU4ODI5NWg1Ljc5NzAyNjF2LTIuODk4NTEzMWMwLTEuNTk3OTEzNC0xLjMwMDU5OTYtMi44OTg1MTMtMi44OTg1MTMtMi44OTg1MTMtMS41OTg1MDU3IDAtMi44OTg1MTMxIDEuMzAwNTk5Ni0yLjg5ODUxMzEgMi44OTg1MTN2Mi44OTg1MTMxem02Ljk1NjA3NiAyLjMxODY5MTloLTguMTE1NzE4MWMtLjY0MDIzMTQgMC0xLjE1OTA0OTgtLjUxODgxODQtMS4xNTkwNDk4LTEuMTU5MDQ5OHYtNC4wNTgxNTUyYzAtMi44NzY1OTk0IDIuMzQwMDEzMi01LjIxNzIwNSA1LjIxNzIwNS01LjIxNzIwNSAyLjg3NjU5OTQgMCA1LjIxNzIwNSAyLjM0MDYwNTYgNS4yMTcyMDUgNS4yMTcyMDV2NC4wNTgxNTUyYzAgLjY0MDIzMTQtLjUxOTQxMDcgMS4xNTkwNDk4LTEuMTU5NjQyMSAxLjE1OTA0OTh6Ii8+PGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTUgMTMuOTc0KSI+PG1hc2sgaWQ9ImQiIGZpbGw9IiNmZmYiPjx1c2UgeGxpbms6aHJlZj0iI2MiLz48L21hc2s+PHBhdGggZmlsbD0iIzJBQzZFQSIgZD0iTTMzLjUxMzQ5MTEgMTIuMzA4MjA3MmgtLjAwMTg0NzNsLTYuNDg5MzU0My0uMDExMDk4NWMtLjY2NjIzNzktLjAwMTIzMzEtMS4yMDUwMTYyLS41NDI1ODkzLTEuMjAzNzg0Ny0xLjIwOTExMDkuMDAxMjMxNS0uNjY1OTA1MS41NDEyNDEzLTEuMjA0Nzk0OTcgMS4yMDU2MzItMS4yMDQ3OTQ5N2guMDAxODQ3Mmw1LjI4MTg3NTEuMDA5MjQ4NjhWMi42ODQ2NDU2NGgtNC4wNTAzODE3djIuMDM5MDI2MDFjMCAuMzIwMDA0MzgtLjEyNzQ1OTYuNjI2NDQ0MDMtLjM1MzQzODYuODUzMzQ1MDItLjIyNTk3OS4yMjYyODQ0MS0uNTMyNjIwOS4zNTMyOTk2NC0uODUyMTkzNC4zNTMyOTk2NGwtNi40NTk3OTg1LS4wMDA2MTY1OGMtLjY2NjIzNzkgMC0xLjIwNTYzMi0uNTQwMTIzMDEtMS4yMDU2MzItMS4yMDY2NDQ2NlYyLjY4NTg3ODhIMTUuMzM2NjQ5djIuMDM3MTc2MjdjMCAuNjY2NTIxNjUtLjUzOTM5NDEgMS4yMDY2NDQ2Ni0xLjIwNTYzMiAxLjIwNjY0NDY2bC02LjQ2NDEwODc0LjAwMDYxNjU4Yy0uMzE5NTcyNTMgMC0uNjI2MjE0MzctLjEyNzAxNTIzLS44NTIxOTM0MS0uMzUzMjk5NjQtLjIyNTk3OTAzLS4yMjY5MDA5OS0uMzUyODIyODUtLjUzMzM0MDY0LS4zNTI4MjI4NS0uODUzMzQ1MDJWMi42ODQ2NDU2NEgyLjQxMDg5NDU3djcuMjA5NjU1NjFoNS4yMjQ2MTA2MWMuNjY1NjIyMTcgMCAxLjIwNTAxNjI2LjU0MDEyMzA1IDEuMjA1MDE2MjYgMS4yMDY2NDQ2NSAwIC42NjcxMzgyLS41MzkzOTQwOSAxLjIwNzI2MTMtMS4yMDUwMTYyNiAxLjIwNzI2MTNIMS4yMDUyNjI1NmMtLjY2NTYyMjE3IDAtMS4yMDUwMTYyNi0uNTQwMTIzMS0xLjIwNTAxNjI2LTEuMjA3MjYxM1YxLjQ3NzM4NDRjMC0uNjY2NTIxNjUuNTM5Mzk0MS0xLjIwNjY0NDY2IDEuMjA1MDE2MjYtMS4yMDY2NDQ2Nmg2LjQ2MTY0NTdjLjY2NTYyMjE3IDAgMS4yMDU2MzIwMS41NDAxMjMgMS4yMDU2MzIwMSAxLjIwNjY0NDY2djIuMDM5MDI2MDFsNC4wNTM0NjA0My0uMDAwNjE2NThWMS40Nzg2MTc1NmMwLS42NjcxMzgyNC41MzkzOTQxLTEuMjA2NjQ0NjYgMS4yMDUwMTYzLTEuMjA2NjQ0NjZoNi40NjEwMjk5Yy42NjU2MjIyIDAgMS4yMDUwMTYzLjUzOTUwNjQyIDEuMjA1MDE2MyAxLjIwNjY0NDY2djIuMDM3MTc2MjdsNC4wNDk3NjU5LjAwMDYxNjU4VjEuNDc3Mzg0NGMwLS42NjY1MjE2NS41MzkzOTQxLTEuMjA2NjQ0NjYgMS4yMDUwMTYzLTEuMjA2NjQ0NjZoNi40NjE2NDU3Yy42NjU2MjIxIDAgMS4yMDU2MzIuNTQwMTIzIDEuMjA1NjMyIDEuMjA2NjQ0NjZ2OS42MjM1NjE1YzAgLjMyMTIzNzYtLjEyNzQ1OTYuNjI4MjkzOC0uMzU0MDU0NC44NTQ1NzgyLS4yMjU5NzkuMjI1NjY3OC0uNTMyMDA1MS4zNTI2ODMxLS44NTE1Nzc2LjM1MjY4MzEiIG1hc2s9InVybCgjZCkiLz48L2c+PC9nPjwvc3ZnPg== 31 | spec: 32 | controller: 33 | image: crossplane/provider-rook-controller:VERSION 34 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # ==================================================================================== 2 | # Setup Project 3 | 4 | PROJECT_NAME := provider-rook 5 | PROJECT_REPO := github.com/crossplane/$(PROJECT_NAME) 6 | 7 | PLATFORMS ?= linux_amd64 linux_arm64 8 | # -include will silently skip missing files, which allows us 9 | # to load those files with a target in the Makefile. If only 10 | # "include" was used, the make command would fail and refuse 11 | # to run a target until the include commands succeeded. 12 | -include build/makelib/common.mk 13 | 14 | # ==================================================================================== 15 | # Setup Output 16 | 17 | -include build/makelib/output.mk 18 | 19 | # ==================================================================================== 20 | # Setup Go 21 | 22 | # Set a sane default so that the nprocs calculation below is less noisy on the initial 23 | # loading of this file 24 | NPROCS ?= 1 25 | 26 | # each of our test suites starts a kube-apiserver and running many test suites in 27 | # parallel can lead to high CPU utilization. by default we reduce the parallelism 28 | # to half the number of CPU cores. 29 | GO_TEST_PARALLEL := $(shell echo $$(( $(NPROCS) / 2 ))) 30 | 31 | GO_STATIC_PACKAGES = $(GO_PROJECT)/cmd/provider 32 | GO_LDFLAGS += -X $(GO_PROJECT)/pkg/version.Version=$(VERSION) 33 | GO_SUBDIRS += cmd pkg apis 34 | GO111MODULE = on 35 | -include build/makelib/golang.mk 36 | 37 | # ==================================================================================== 38 | # Setup Kubernetes tools 39 | 40 | -include build/makelib/k8s_tools.mk 41 | 42 | # ==================================================================================== 43 | # Setup Images 44 | 45 | DOCKER_REGISTRY = crossplane 46 | IMAGES = provider-rook provider-rook-controller 47 | -include build/makelib/image.mk 48 | 49 | # ==================================================================================== 50 | # Targets 51 | 52 | # run `make help` to see the targets and options 53 | 54 | # We want submodules to be set up the first time `make` is run. 55 | # We manage the build/ folder and its Makefiles as a submodule. 56 | # The first time `make` is run, the includes of build/*.mk files will 57 | # all fail, and this target will be run. The next time, the default as defined 58 | # by the includes will be run instead. 59 | fallthrough: submodules 60 | @echo Initial setup complete. Running make again . . . 61 | @make 62 | 63 | go.test.unit: $(KUBEBUILDER) 64 | 65 | # Generate a coverage report for cobertura applying exclusions on 66 | # - generated file 67 | cobertura: 68 | @cat $(GO_TEST_OUTPUT)/coverage.txt | \ 69 | grep -v zz_generated.deepcopy | \ 70 | $(GOCOVER_COBERTURA) > $(GO_TEST_OUTPUT)/cobertura-coverage.xml 71 | 72 | crds.clean: 73 | @$(INFO) cleaning generated CRDs 74 | @find package/crds -name *.yaml -exec sed -i.sed -e '1,2d' {} \; || $(FAIL) 75 | @find package/crds -name *.yaml.sed -delete || $(FAIL) 76 | @$(OK) cleaned generated CRDs 77 | 78 | generate: crds.clean 79 | 80 | # Ensure a PR is ready for review. 81 | reviewable: generate lint 82 | @go mod tidy 83 | 84 | # Ensure branch is clean. 85 | check-diff: reviewable 86 | @$(INFO) checking that branch is clean 87 | @test -z "$$(git status --porcelain)" || $(FAIL) 88 | @$(OK) branch is clean 89 | 90 | # integration tests 91 | e2e.run: test-integration 92 | 93 | # Run integration tests. 94 | test-integration: $(KIND) $(KUBECTL) $(HELM3) 95 | @$(INFO) running integration tests using kind $(KIND_VERSION) 96 | @$(ROOT_DIR)/cluster/local/integration_tests.sh || $(FAIL) 97 | @$(OK) integration tests passed 98 | 99 | # Update the submodules, such as the common build scripts. 100 | submodules: 101 | @git submodule sync 102 | @git submodule update --init --recursive 103 | 104 | # This is for running out-of-cluster locally, and is for convenience. Running 105 | # this make target will print out the command which was used. For more control, 106 | # try running the binary directly with different arguments. 107 | run: go.build 108 | @$(INFO) Running Crossplane locally out-of-cluster . . . 109 | @# To see other arguments that can be provided, run the command with --help instead 110 | $(GO_OUT_DIR)/$(PROJECT_NAME) --debug 111 | 112 | 113 | manifests: 114 | @$(WARN) Deprecated. Please run make generate instead. 115 | 116 | .PHONY: manifests cobertura reviewable submodules fallthrough test-integration run crds.clean 117 | 118 | # ==================================================================================== 119 | # Special Targets 120 | 121 | define CROSSPLANE_MAKE_HELP 122 | Crossplane Targets: 123 | cobertura Generate a coverage report for cobertura applying exclusions on generated files. 124 | reviewable Ensure a PR is ready for review. 125 | submodules Update the submodules, such as the common build scripts. 126 | run Run crossplane locally, out-of-cluster. Useful for development. 127 | 128 | endef 129 | # The reason CROSSPLANE_MAKE_HELP is used instead of CROSSPLANE_HELP is because the crossplane 130 | # binary will try to use CROSSPLANE_HELP if it is set, and this is for something different. 131 | export CROSSPLANE_MAKE_HELP 132 | 133 | crossplane.help: 134 | @echo "$$CROSSPLANE_MAKE_HELP" 135 | 136 | help-special: crossplane.help 137 | 138 | .PHONY: crossplane.help help-special 139 | -------------------------------------------------------------------------------- /package/crds/rook.crossplane.io_providerconfigs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | annotations: 5 | controller-gen.kubebuilder.io/version: v0.3.0 6 | creationTimestamp: null 7 | name: providerconfigs.rook.crossplane.io 8 | spec: 9 | group: rook.crossplane.io 10 | names: 11 | categories: 12 | - crossplane 13 | - provider 14 | - rook 15 | kind: ProviderConfig 16 | listKind: ProviderConfigList 17 | plural: providerconfigs 18 | singular: providerconfig 19 | scope: Cluster 20 | versions: 21 | - additionalPrinterColumns: 22 | - jsonPath: .metadata.creationTimestamp 23 | name: AGE 24 | type: date 25 | - jsonPath: .spec.credentialsSecretRef.name 26 | name: SECRET-NAME 27 | priority: 1 28 | type: string 29 | name: v1beta1 30 | schema: 31 | openAPIV3Schema: 32 | description: A ProviderConfig configures how AWS controllers will connect to AWS API. 33 | properties: 34 | apiVersion: 35 | description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 36 | type: string 37 | kind: 38 | description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 39 | type: string 40 | metadata: 41 | type: object 42 | spec: 43 | description: A ProviderConfigSpec defines the desired state of a ProviderConfig. 44 | properties: 45 | credentials: 46 | description: Credentials required to authenticate to this provider. 47 | properties: 48 | secretRef: 49 | description: A CredentialsSecretRef is a reference to a secret key that contains the credentials that must be used to connect to the provider. 50 | properties: 51 | key: 52 | description: The key to select. 53 | type: string 54 | name: 55 | description: Name of the secret. 56 | type: string 57 | namespace: 58 | description: Namespace of the secret. 59 | type: string 60 | required: 61 | - key 62 | - name 63 | - namespace 64 | type: object 65 | source: 66 | description: Source of the provider credentials. 67 | enum: 68 | - None 69 | - Secret 70 | - InjectedIdentity 71 | type: string 72 | required: 73 | - source 74 | type: object 75 | required: 76 | - credentials 77 | type: object 78 | status: 79 | description: A ProviderConfigStatus represents the status of a ProviderConfig. 80 | properties: 81 | conditions: 82 | description: Conditions of the resource. 83 | items: 84 | description: A Condition that may apply to a resource. 85 | properties: 86 | lastTransitionTime: 87 | description: LastTransitionTime is the last time this condition transitioned from one status to another. 88 | format: date-time 89 | type: string 90 | message: 91 | description: A Message containing details about this condition's last transition from one status to another, if any. 92 | type: string 93 | reason: 94 | description: A Reason for this condition's last transition from one status to another. 95 | type: string 96 | status: 97 | description: Status of this condition; is it currently True, False, or Unknown? 98 | type: string 99 | type: 100 | description: Type of this condition. At most one of each condition type may apply to a resource at any point in time. 101 | type: string 102 | required: 103 | - lastTransitionTime 104 | - reason 105 | - status 106 | - type 107 | type: object 108 | type: array 109 | users: 110 | description: Users of this provider configuration. 111 | format: int64 112 | type: integer 113 | type: object 114 | required: 115 | - spec 116 | type: object 117 | served: true 118 | storage: true 119 | subresources: 120 | status: {} 121 | status: 122 | acceptedNames: 123 | kind: "" 124 | plural: "" 125 | conditions: [] 126 | storedVersions: [] 127 | -------------------------------------------------------------------------------- /apis/database/v1alpha1/types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1alpha1 18 | 19 | import ( 20 | xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" 21 | 22 | corev1 "k8s.io/api/core/v1" 23 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 24 | 25 | "github.com/crossplane/provider-rook/apis/v1alpha1" 26 | ) 27 | 28 | // ServerSpec describes server related settings of the cluster 29 | type ServerSpec struct { 30 | Replicas int32 `json:"replicas,omitempty"` 31 | Network NetworkSpec `json:"network,omitempty"` 32 | VolumeClaimTemplate corev1.PersistentVolumeClaim `json:"volumeClaimTemplate,omitempty"` 33 | } 34 | 35 | // NetworkSpec describes network related settings of the cluster 36 | type NetworkSpec struct { 37 | // Set of named ports that can be configured for this resource 38 | Ports []PortSpec `json:"ports,omitempty"` 39 | } 40 | 41 | // PortSpec is named port 42 | type PortSpec struct { 43 | // Name of port 44 | Name string `json:"name,omitempty"` 45 | // Port number 46 | Port int32 `json:"port,omitempty"` 47 | } 48 | 49 | // A YugabyteClusterParameters defines the desired state of a YugabyteCluster. 50 | type YugabyteClusterParameters struct { 51 | Name string `json:"name"` 52 | Namespace string `json:"namespace"` 53 | Annotations v1alpha1.Annotations `json:"annotations,omitempty"` 54 | Master ServerSpec `json:"master"` 55 | TServer ServerSpec `json:"tserver"` 56 | } 57 | 58 | // A YugabyteClusterSpec defines the desired state of a YugabyteCluster. 59 | type YugabyteClusterSpec struct { 60 | xpv1.ResourceSpec `json:",inline"` 61 | YugabyteClusterParameters `json:"forProvider"` 62 | } 63 | 64 | // A YugabyteClusterStatus defines the current state of a YugabyteCluster. 65 | type YugabyteClusterStatus struct { 66 | xpv1.ResourceStatus `json:",inline"` 67 | } 68 | 69 | // +kubebuilder:object:root=true 70 | 71 | // A YugabyteCluster configures a Rook 'ybclusters.yugabytedb.rook.io' 72 | // +kubebuilder:subresource:status 73 | // +kubebuilder:printcolumn:name="READY",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" 74 | // +kubebuilder:printcolumn:name="SYNCED",type="string",JSONPath=".status.conditions[?(@.type=='Synced')].status" 75 | // +kubebuilder:printcolumn:name="STATE",type="string",JSONPath=".status.state" 76 | // +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" 77 | // +kubebuilder:resource:scope=Cluster,categories={crossplane,managed,rook} 78 | type YugabyteCluster struct { 79 | metav1.TypeMeta `json:",inline"` 80 | metav1.ObjectMeta `json:"metadata,omitempty"` 81 | 82 | Spec YugabyteClusterSpec `json:"spec"` 83 | Status YugabyteClusterStatus `json:"status,omitempty"` 84 | } 85 | 86 | // +kubebuilder:object:root=true 87 | 88 | // YugabyteClusterList contains a list of YugabyteCluster 89 | type YugabyteClusterList struct { 90 | metav1.TypeMeta `json:",inline"` 91 | metav1.ListMeta `json:"metadata,omitempty"` 92 | Items []YugabyteCluster `json:"items"` 93 | } 94 | 95 | // A CockroachClusterParameters defines the desired state of a CockroachCluster. 96 | type CockroachClusterParameters struct { 97 | Name string `json:"name"` 98 | Namespace string `json:"namespace"` 99 | // The annotations-related configuration to add/set on each Pod related object. 100 | Annotations v1alpha1.Annotations `json:"annotations,omitempty"` 101 | Storage v1alpha1.StorageScopeSpec `json:"scope,omitempty"` 102 | Network NetworkSpec `json:"network,omitempty"` 103 | Secure bool `json:"secure,omitempty"` 104 | CachePercent int `json:"cachePercent,omitempty"` 105 | MaxSQLMemoryPercent int `json:"maxSQLMemoryPercent,omitempty"` 106 | } 107 | 108 | // A CockroachClusterSpec defines the desired state of a CockroachCluster. 109 | type CockroachClusterSpec struct { 110 | xpv1.ResourceSpec `json:",inline"` 111 | CockroachClusterParameters `json:"forProvider"` 112 | } 113 | 114 | // A CockroachClusterStatus defines the current state of a CockroachCluster. 115 | type CockroachClusterStatus struct { 116 | xpv1.ResourceStatus `json:",inline"` 117 | } 118 | 119 | // +kubebuilder:object:root=true 120 | 121 | // A CockroachCluster configures a Rook 'clusters.cockroachdb.rook.io' 122 | // +kubebuilder:subresource:status 123 | // +kubebuilder:printcolumn:name="READY",type="string",JSONPath=".status.conditions[?(@.type=='Ready')].status" 124 | // +kubebuilder:printcolumn:name="SYNCED",type="string",JSONPath=".status.conditions[?(@.type=='Synced')].status" 125 | // +kubebuilder:printcolumn:name="STATE",type="string",JSONPath=".status.state" 126 | // +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" 127 | // +kubebuilder:resource:scope=Cluster,categories={crossplane,managed,rook} 128 | type CockroachCluster struct { 129 | metav1.TypeMeta `json:",inline"` 130 | metav1.ObjectMeta `json:"metadata,omitempty"` 131 | 132 | Spec CockroachClusterSpec `json:"spec"` 133 | Status CockroachClusterStatus `json:"status,omitempty"` 134 | } 135 | 136 | // +kubebuilder:object:root=true 137 | 138 | // CockroachClusterList contains a list of CockroachCluster 139 | type CockroachClusterList struct { 140 | metav1.TypeMeta `json:",inline"` 141 | metav1.ListMeta `json:"metadata,omitempty"` 142 | Items []CockroachCluster `json:"items"` 143 | } 144 | -------------------------------------------------------------------------------- /apis/v1beta1/zz_generated.deepcopy.go: -------------------------------------------------------------------------------- 1 | // +build !ignore_autogenerated 2 | 3 | /* 4 | Copyright 2019 The Crossplane 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 | 19 | // Code generated by controller-gen. DO NOT EDIT. 20 | 21 | package v1beta1 22 | 23 | import ( 24 | runtime "k8s.io/apimachinery/pkg/runtime" 25 | ) 26 | 27 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 28 | func (in *ProviderConfig) DeepCopyInto(out *ProviderConfig) { 29 | *out = *in 30 | out.TypeMeta = in.TypeMeta 31 | in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) 32 | in.Spec.DeepCopyInto(&out.Spec) 33 | in.Status.DeepCopyInto(&out.Status) 34 | } 35 | 36 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProviderConfig. 37 | func (in *ProviderConfig) DeepCopy() *ProviderConfig { 38 | if in == nil { 39 | return nil 40 | } 41 | out := new(ProviderConfig) 42 | in.DeepCopyInto(out) 43 | return out 44 | } 45 | 46 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 47 | func (in *ProviderConfig) DeepCopyObject() runtime.Object { 48 | if c := in.DeepCopy(); c != nil { 49 | return c 50 | } 51 | return nil 52 | } 53 | 54 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 55 | func (in *ProviderConfigList) DeepCopyInto(out *ProviderConfigList) { 56 | *out = *in 57 | out.TypeMeta = in.TypeMeta 58 | in.ListMeta.DeepCopyInto(&out.ListMeta) 59 | if in.Items != nil { 60 | in, out := &in.Items, &out.Items 61 | *out = make([]ProviderConfig, len(*in)) 62 | for i := range *in { 63 | (*in)[i].DeepCopyInto(&(*out)[i]) 64 | } 65 | } 66 | } 67 | 68 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProviderConfigList. 69 | func (in *ProviderConfigList) DeepCopy() *ProviderConfigList { 70 | if in == nil { 71 | return nil 72 | } 73 | out := new(ProviderConfigList) 74 | in.DeepCopyInto(out) 75 | return out 76 | } 77 | 78 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 79 | func (in *ProviderConfigList) DeepCopyObject() runtime.Object { 80 | if c := in.DeepCopy(); c != nil { 81 | return c 82 | } 83 | return nil 84 | } 85 | 86 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 87 | func (in *ProviderConfigSpec) DeepCopyInto(out *ProviderConfigSpec) { 88 | *out = *in 89 | in.ProviderConfigSpec.DeepCopyInto(&out.ProviderConfigSpec) 90 | } 91 | 92 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProviderConfigSpec. 93 | func (in *ProviderConfigSpec) DeepCopy() *ProviderConfigSpec { 94 | if in == nil { 95 | return nil 96 | } 97 | out := new(ProviderConfigSpec) 98 | in.DeepCopyInto(out) 99 | return out 100 | } 101 | 102 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 103 | func (in *ProviderConfigStatus) DeepCopyInto(out *ProviderConfigStatus) { 104 | *out = *in 105 | in.ProviderConfigStatus.DeepCopyInto(&out.ProviderConfigStatus) 106 | } 107 | 108 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProviderConfigStatus. 109 | func (in *ProviderConfigStatus) DeepCopy() *ProviderConfigStatus { 110 | if in == nil { 111 | return nil 112 | } 113 | out := new(ProviderConfigStatus) 114 | in.DeepCopyInto(out) 115 | return out 116 | } 117 | 118 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 119 | func (in *ProviderConfigUsage) DeepCopyInto(out *ProviderConfigUsage) { 120 | *out = *in 121 | out.TypeMeta = in.TypeMeta 122 | in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) 123 | out.ProviderConfigUsage = in.ProviderConfigUsage 124 | } 125 | 126 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProviderConfigUsage. 127 | func (in *ProviderConfigUsage) DeepCopy() *ProviderConfigUsage { 128 | if in == nil { 129 | return nil 130 | } 131 | out := new(ProviderConfigUsage) 132 | in.DeepCopyInto(out) 133 | return out 134 | } 135 | 136 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 137 | func (in *ProviderConfigUsage) DeepCopyObject() runtime.Object { 138 | if c := in.DeepCopy(); c != nil { 139 | return c 140 | } 141 | return nil 142 | } 143 | 144 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 145 | func (in *ProviderConfigUsageList) DeepCopyInto(out *ProviderConfigUsageList) { 146 | *out = *in 147 | out.TypeMeta = in.TypeMeta 148 | in.ListMeta.DeepCopyInto(&out.ListMeta) 149 | if in.Items != nil { 150 | in, out := &in.Items, &out.Items 151 | *out = make([]ProviderConfigUsage, len(*in)) 152 | for i := range *in { 153 | (*in)[i].DeepCopyInto(&(*out)[i]) 154 | } 155 | } 156 | } 157 | 158 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ProviderConfigUsageList. 159 | func (in *ProviderConfigUsageList) DeepCopy() *ProviderConfigUsageList { 160 | if in == nil { 161 | return nil 162 | } 163 | out := new(ProviderConfigUsageList) 164 | in.DeepCopyInto(out) 165 | return out 166 | } 167 | 168 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 169 | func (in *ProviderConfigUsageList) DeepCopyObject() runtime.Object { 170 | if c := in.DeepCopy(); c != nil { 171 | return c 172 | } 173 | return nil 174 | } 175 | -------------------------------------------------------------------------------- /pkg/controller/database/yugabyte/yugabyte.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package yugabyte 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | 23 | "github.com/pkg/errors" 24 | rookv1alpha1 "github.com/rook/rook/pkg/apis/yugabytedb.rook.io/v1alpha1" 25 | kerrors "k8s.io/apimachinery/pkg/api/errors" 26 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 | "k8s.io/apimachinery/pkg/runtime" 28 | "k8s.io/apimachinery/pkg/types" 29 | ctrl "sigs.k8s.io/controller-runtime" 30 | "sigs.k8s.io/controller-runtime/pkg/client" 31 | 32 | xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" 33 | "github.com/crossplane/crossplane-runtime/pkg/event" 34 | "github.com/crossplane/crossplane-runtime/pkg/logging" 35 | "github.com/crossplane/crossplane-runtime/pkg/reconciler/managed" 36 | "github.com/crossplane/crossplane-runtime/pkg/resource" 37 | 38 | "github.com/crossplane/provider-rook/apis/database/v1alpha1" 39 | "github.com/crossplane/provider-rook/pkg/clients" 40 | "github.com/crossplane/provider-rook/pkg/clients/database/yugabyte" 41 | ) 42 | 43 | // Error strings. 44 | const ( 45 | errNewYugabyteClient = "cannot create new Kubernetes client" 46 | errNotYugabyteCluster = "managed resource is not an Yugabyte cluster" 47 | errGetYugabyteCluster = "cannot get Yugabyte cluster in target Kubernetes cluster" 48 | errCreateYugabyteCluster = "cannot create Yugabyte cluster in target Kubernetes cluster" 49 | errUpdateYugabyteCluster = "cannot update Yugabyte cluster in target Kubernetes cluster" 50 | errDeleteYugabyteCluster = "cannot delete Yugabyte cluster in target Kubernetes cluster" 51 | ) 52 | 53 | // Setup creates a new YugabyteCluster Controller and adds it to the Manager 54 | // with default RBAC. The Manager will set fields on the Controller and start it 55 | // when the Manager is Started. 56 | func Setup(mgr ctrl.Manager, l logging.Logger) error { 57 | name := managed.ControllerName(fmt.Sprintf("%s.%s", v1alpha1.YugabyteClusterKind, v1alpha1.Group)) 58 | return ctrl.NewControllerManagedBy(mgr). 59 | Named(name). 60 | For(&v1alpha1.YugabyteCluster{}). 61 | Complete(managed.NewReconciler(mgr, 62 | resource.ManagedKind(v1alpha1.YugabyteClusterGroupVersionKind), 63 | managed.WithExternalConnecter(&connecter{client: mgr.GetClient()}), 64 | managed.WithLogger(l.WithValues("controller", name)), 65 | managed.WithRecorder(event.NewAPIRecorder(mgr.GetEventRecorderFor(name))))) 66 | } 67 | 68 | type connecter struct { 69 | client client.Client 70 | } 71 | 72 | func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) { 73 | scheme := runtime.NewScheme() 74 | scheme.AddKnownTypes(rookv1alpha1.SchemeGroupVersion, 75 | &rookv1alpha1.YBCluster{}, 76 | &rookv1alpha1.YBClusterList{}, 77 | ) 78 | 79 | metav1.AddToGroupVersion(scheme, rookv1alpha1.SchemeGroupVersion) 80 | 81 | cl, err := clients.NewClient(ctx, c.client, mg, scheme) 82 | return &external{client: cl}, errors.Wrap(err, errNewYugabyteClient) 83 | } 84 | 85 | type external struct { 86 | client client.Client 87 | } 88 | 89 | func (e *external) Observe(ctx context.Context, mg resource.Managed) (managed.ExternalObservation, error) { 90 | c, ok := mg.(*v1alpha1.YugabyteCluster) 91 | if !ok { 92 | return managed.ExternalObservation{}, errors.New(errNotYugabyteCluster) 93 | } 94 | 95 | key := types.NamespacedName{ 96 | Name: c.Spec.YugabyteClusterParameters.Name, 97 | Namespace: c.Spec.YugabyteClusterParameters.Namespace, 98 | } 99 | 100 | external := &rookv1alpha1.YBCluster{} 101 | 102 | err := e.client.Get(ctx, key, external) 103 | if kerrors.IsNotFound(err) { 104 | return managed.ExternalObservation{ResourceExists: false}, nil 105 | } 106 | if err != nil { 107 | return managed.ExternalObservation{}, errors.Wrap(err, errGetYugabyteCluster) 108 | } 109 | 110 | // If we are able to get the resource YBCluster instance, we will consider 111 | // it available. If a status is added to the YBCluster CRD in the future we 112 | // should check it to set conditions. 113 | c.Status.SetConditions(xpv1.Available()) 114 | 115 | o := managed.ExternalObservation{ 116 | ResourceExists: true, 117 | ConnectionDetails: managed.ConnectionDetails{}, 118 | } 119 | 120 | return o, nil 121 | 122 | } 123 | 124 | func (e *external) Create(ctx context.Context, mg resource.Managed) (managed.ExternalCreation, error) { 125 | c, ok := mg.(*v1alpha1.YugabyteCluster) 126 | if !ok { 127 | return managed.ExternalCreation{}, errors.New(errNotYugabyteCluster) 128 | } 129 | 130 | c.Status.SetConditions(xpv1.Creating()) 131 | 132 | err := e.client.Create(ctx, yugabyte.CrossToRook(c)) 133 | return managed.ExternalCreation{}, errors.Wrap(err, errCreateYugabyteCluster) 134 | } 135 | 136 | func (e *external) Update(ctx context.Context, mg resource.Managed) (managed.ExternalUpdate, error) { 137 | c, ok := mg.(*v1alpha1.YugabyteCluster) 138 | if !ok { 139 | return managed.ExternalUpdate{}, errors.New(errNotYugabyteCluster) 140 | } 141 | 142 | key := types.NamespacedName{ 143 | Name: c.Spec.YugabyteClusterParameters.Name, 144 | Namespace: c.Spec.YugabyteClusterParameters.Namespace, 145 | } 146 | 147 | external := &rookv1alpha1.YBCluster{} 148 | 149 | if err := e.client.Get(ctx, key, external); err != nil { 150 | return managed.ExternalUpdate{}, errors.Wrap(err, errGetYugabyteCluster) 151 | } 152 | 153 | if !yugabyte.NeedsUpdate(c, external) { 154 | return managed.ExternalUpdate{}, nil 155 | } 156 | 157 | update := yugabyte.CrossToRook(c) 158 | update.ResourceVersion = external.ResourceVersion 159 | err := e.client.Update(ctx, update) 160 | return managed.ExternalUpdate{}, errors.Wrap(err, errUpdateYugabyteCluster) 161 | } 162 | 163 | func (e *external) Delete(ctx context.Context, mg resource.Managed) error { 164 | c, ok := mg.(*v1alpha1.YugabyteCluster) 165 | if !ok { 166 | return errors.New(errNotYugabyteCluster) 167 | } 168 | 169 | c.SetConditions(xpv1.Deleting()) 170 | 171 | key := types.NamespacedName{ 172 | Name: c.Spec.YugabyteClusterParameters.Name, 173 | Namespace: c.Spec.YugabyteClusterParameters.Namespace, 174 | } 175 | 176 | external := &rookv1alpha1.YBCluster{} 177 | 178 | if err := e.client.Get(ctx, key, external); err != nil { 179 | if kerrors.IsNotFound(err) { 180 | return nil 181 | } 182 | return errors.Wrap(err, errGetYugabyteCluster) 183 | } 184 | 185 | err := e.client.Delete(ctx, external) 186 | return errors.Wrap(err, errDeleteYugabyteCluster) 187 | } 188 | -------------------------------------------------------------------------------- /pkg/controller/database/cockroach/cockroach.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package cockroach 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | 23 | "github.com/crossplane/provider-rook/pkg/clients" 24 | 25 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 | "k8s.io/apimachinery/pkg/runtime" 27 | 28 | "github.com/pkg/errors" 29 | kerrors "k8s.io/apimachinery/pkg/api/errors" 30 | "k8s.io/apimachinery/pkg/types" 31 | ctrl "sigs.k8s.io/controller-runtime" 32 | "sigs.k8s.io/controller-runtime/pkg/client" 33 | 34 | rookv1alpha1 "github.com/rook/rook/pkg/apis/cockroachdb.rook.io/v1alpha1" 35 | 36 | xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" 37 | "github.com/crossplane/crossplane-runtime/pkg/event" 38 | "github.com/crossplane/crossplane-runtime/pkg/logging" 39 | "github.com/crossplane/crossplane-runtime/pkg/reconciler/managed" 40 | "github.com/crossplane/crossplane-runtime/pkg/resource" 41 | 42 | "github.com/crossplane/provider-rook/apis/database/v1alpha1" 43 | "github.com/crossplane/provider-rook/pkg/clients/database/cockroach" 44 | ) 45 | 46 | // Error strings. 47 | const ( 48 | errNewCockroachClient = "cannot create new Kubernetes client" 49 | errNotCockroachCluster = "managed resource is not an Cockroach cluster" 50 | errGetCockroachCluster = "cannot get Cockroach cluster in target Kubernetes cluster" 51 | errCreateCockroachCluster = "cannot create Cockroach cluster in target Kubernetes cluster" 52 | errUpdateCockroachCluster = "cannot update Cockroach cluster in target Kubernetes cluster" 53 | errDeleteCockroachCluster = "cannot delete Cockroach cluster in target Kubernetes cluster" 54 | ) 55 | 56 | // Setup creates a new CockroachCluster Controller and adds it to the Manager 57 | // with default RBAC. The Manager will set fields on the Controller and start it 58 | // when the Manager is Started. 59 | func Setup(mgr ctrl.Manager, l logging.Logger) error { 60 | name := managed.ControllerName(fmt.Sprintf("%s.%s", v1alpha1.CockroachClusterKind, v1alpha1.Group)) 61 | return ctrl.NewControllerManagedBy(mgr). 62 | Named(name). 63 | For(&v1alpha1.CockroachCluster{}). 64 | Complete(managed.NewReconciler(mgr, 65 | resource.ManagedKind(v1alpha1.CockroachClusterGroupVersionKind), 66 | managed.WithExternalConnecter(&connecter{client: mgr.GetClient()}), 67 | managed.WithLogger(l.WithValues("controller", name)), 68 | managed.WithRecorder(event.NewAPIRecorder(mgr.GetEventRecorderFor(name))))) 69 | } 70 | 71 | type connecter struct { 72 | client client.Client 73 | } 74 | 75 | func (c *connecter) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) { 76 | scheme := runtime.NewScheme() 77 | scheme.AddKnownTypes(rookv1alpha1.SchemeGroupVersion, 78 | &rookv1alpha1.Cluster{}, 79 | &rookv1alpha1.ClusterList{}, 80 | ) 81 | metav1.AddToGroupVersion(scheme, rookv1alpha1.SchemeGroupVersion) 82 | 83 | cl, err := clients.NewClient(ctx, c.client, mg, scheme) 84 | return &external{client: cl}, errors.Wrap(err, errNewCockroachClient) 85 | } 86 | 87 | type external struct { 88 | client client.Client 89 | } 90 | 91 | func (e *external) Observe(ctx context.Context, mg resource.Managed) (managed.ExternalObservation, error) { 92 | c, ok := mg.(*v1alpha1.CockroachCluster) 93 | if !ok { 94 | return managed.ExternalObservation{}, errors.New(errNotCockroachCluster) 95 | } 96 | 97 | key := types.NamespacedName{ 98 | Name: c.Spec.CockroachClusterParameters.Name, 99 | Namespace: c.Spec.CockroachClusterParameters.Namespace, 100 | } 101 | 102 | external := &rookv1alpha1.Cluster{} 103 | 104 | err := e.client.Get(ctx, key, external) 105 | if kerrors.IsNotFound(err) { 106 | return managed.ExternalObservation{ResourceExists: false}, nil 107 | } 108 | if err != nil { 109 | return managed.ExternalObservation{}, errors.Wrap(err, errGetCockroachCluster) 110 | } 111 | 112 | // If we are able to get the resource Cluster instance, we will consider 113 | // it available. If a status is added to the Cluster CRD in the future we 114 | // should check it to set conditions. 115 | c.Status.SetConditions(xpv1.Available()) 116 | 117 | o := managed.ExternalObservation{ 118 | ResourceExists: true, 119 | ConnectionDetails: managed.ConnectionDetails{}, 120 | } 121 | 122 | return o, nil 123 | 124 | } 125 | 126 | func (e *external) Create(ctx context.Context, mg resource.Managed) (managed.ExternalCreation, error) { 127 | c, ok := mg.(*v1alpha1.CockroachCluster) 128 | if !ok { 129 | return managed.ExternalCreation{}, errors.New(errNotCockroachCluster) 130 | } 131 | 132 | c.Status.SetConditions(xpv1.Creating()) 133 | 134 | err := e.client.Create(ctx, cockroach.CrossToRook(c)) 135 | return managed.ExternalCreation{}, errors.Wrap(err, errCreateCockroachCluster) 136 | } 137 | 138 | func (e *external) Update(ctx context.Context, mg resource.Managed) (managed.ExternalUpdate, error) { 139 | c, ok := mg.(*v1alpha1.CockroachCluster) 140 | if !ok { 141 | return managed.ExternalUpdate{}, errors.New(errNotCockroachCluster) 142 | } 143 | 144 | key := types.NamespacedName{ 145 | Name: c.Spec.CockroachClusterParameters.Name, 146 | Namespace: c.Spec.CockroachClusterParameters.Namespace, 147 | } 148 | 149 | external := &rookv1alpha1.Cluster{} 150 | 151 | if err := e.client.Get(ctx, key, external); err != nil { 152 | return managed.ExternalUpdate{}, errors.Wrap(err, errGetCockroachCluster) 153 | } 154 | 155 | if !cockroach.NeedsUpdate(c, external) { 156 | return managed.ExternalUpdate{}, nil 157 | } 158 | 159 | update := cockroach.CrossToRook(c) 160 | update.ResourceVersion = external.ResourceVersion 161 | err := e.client.Update(ctx, update) 162 | return managed.ExternalUpdate{}, errors.Wrap(err, errUpdateCockroachCluster) 163 | } 164 | 165 | func (e *external) Delete(ctx context.Context, mg resource.Managed) error { 166 | c, ok := mg.(*v1alpha1.CockroachCluster) 167 | if !ok { 168 | return errors.New(errNotCockroachCluster) 169 | } 170 | 171 | c.SetConditions(xpv1.Deleting()) 172 | 173 | key := types.NamespacedName{ 174 | Name: c.Spec.CockroachClusterParameters.Name, 175 | Namespace: c.Spec.CockroachClusterParameters.Namespace, 176 | } 177 | 178 | external := &rookv1alpha1.Cluster{} 179 | 180 | if err := e.client.Get(ctx, key, external); err != nil { 181 | if kerrors.IsNotFound(err) { 182 | return nil 183 | } 184 | return errors.Wrap(err, errGetCockroachCluster) 185 | } 186 | 187 | err := e.client.Delete(ctx, external) 188 | return errors.Wrap(err, errDeleteCockroachCluster) 189 | } 190 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | timeout: 10m 3 | 4 | skip-files: 5 | - "zz_generated\\..+\\.go$" 6 | 7 | output: 8 | # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number" 9 | format: colored-line-number 10 | 11 | linters-settings: 12 | errcheck: 13 | # report about not checking of errors in type assetions: `a := b.(MyStruct)`; 14 | # default is false: such cases aren't reported by default. 15 | check-type-assertions: false 16 | 17 | # report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`; 18 | # default is false: such cases aren't reported by default. 19 | check-blank: false 20 | 21 | # [deprecated] comma-separated list of pairs of the form pkg:regex 22 | # the regex is used to ignore names within pkg. (default "fmt:.*"). 23 | # see https://github.com/kisielk/errcheck#the-deprecated-method for details 24 | ignore: fmt:.*,io/ioutil:^Read.* 25 | 26 | govet: 27 | # report about shadowed variables 28 | check-shadowing: false 29 | 30 | golint: 31 | # minimal confidence for issues, default is 0.8 32 | min-confidence: 0.8 33 | 34 | gofmt: 35 | # simplify code: gofmt with `-s` option, true by default 36 | simplify: true 37 | 38 | goimports: 39 | # put imports beginning with prefix after 3rd-party packages; 40 | # it's a comma-separated list of prefixes 41 | local-prefixes: github.com/crossplane/provider-rook 42 | 43 | gocyclo: 44 | # minimal code complexity to report, 30 by default (but we recommend 10-20) 45 | min-complexity: 10 46 | 47 | maligned: 48 | # print struct with more effective memory layout or not, false by default 49 | suggest-new: true 50 | 51 | dupl: 52 | # tokens count to trigger issue, 150 by default 53 | threshold: 100 54 | 55 | goconst: 56 | # minimal length of string constant, 3 by default 57 | min-len: 3 58 | # minimal occurrences count to trigger, 3 by default 59 | min-occurrences: 5 60 | 61 | lll: 62 | # tab width in spaces. Default to 1. 63 | tab-width: 1 64 | 65 | unused: 66 | # treat code as a program (not a library) and report unused exported identifiers; default is false. 67 | # XXX: if you enable this setting, unused will report a lot of false-positives in text editors: 68 | # if it's called for subdir of a project it can't find funcs usages. All text editor integrations 69 | # with golangci-lint call it on a directory with the changed file. 70 | check-exported: false 71 | 72 | unparam: 73 | # Inspect exported functions, default is false. Set to true if no external program/library imports your code. 74 | # XXX: if you enable this setting, unparam will report a lot of false-positives in text editors: 75 | # if it's called for subdir of a project it can't find external interfaces. All text editor integrations 76 | # with golangci-lint call it on a directory with the changed file. 77 | check-exported: false 78 | 79 | nakedret: 80 | # make an issue if func has more lines of code than this setting and it has naked returns; default is 30 81 | max-func-lines: 30 82 | 83 | prealloc: 84 | # XXX: we don't recommend using this linter before doing performance profiling. 85 | # For most programs usage of prealloc will be a premature optimization. 86 | 87 | # Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them. 88 | # True by default. 89 | simple: true 90 | range-loops: true # Report preallocation suggestions on range loops, true by default 91 | for-loops: false # Report preallocation suggestions on for loops, false by default 92 | 93 | gocritic: 94 | # Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint` run to see all tags and checks. 95 | # Empty list by default. See https://github.com/go-critic/go-critic#usage -> section "Tags". 96 | enabled-tags: 97 | - performance 98 | 99 | settings: # settings passed to gocritic 100 | captLocal: # must be valid enabled check name 101 | paramsOnly: true 102 | rangeValCopy: 103 | sizeThreshold: 32 104 | 105 | linters: 106 | enable: 107 | - megacheck 108 | - govet 109 | - gocyclo 110 | - gocritic 111 | - interfacer 112 | - goconst 113 | - goimports 114 | - gofmt # We enable this as well as goimports for its simplify mode. 115 | - prealloc 116 | - golint 117 | - unconvert 118 | - misspell 119 | - nakedret 120 | 121 | presets: 122 | - bugs 123 | - unused 124 | fast: false 125 | 126 | 127 | issues: 128 | # Excluding configuration per-path and per-linter 129 | exclude-rules: 130 | # Exclude some linters from running on tests files. 131 | - path: _test(ing)?\.go 132 | linters: 133 | - gocyclo 134 | - errcheck 135 | - dupl 136 | - gosec 137 | - scopelint 138 | - unparam 139 | 140 | # Ease some gocritic warnings on test files. 141 | - path: _test\.go 142 | text: "(unnamedResult|exitAfterDefer)" 143 | linters: 144 | - gocritic 145 | 146 | # These are performance optimisations rather than style issues per se. 147 | # They warn when function arguments or range values copy a lot of memory 148 | # rather than using a pointer. 149 | - text: "(hugeParam|rangeValCopy):" 150 | linters: 151 | - gocritic 152 | 153 | # This "TestMain should call os.Exit to set exit code" warning is not clever 154 | # enough to notice that we call a helper method that calls os.Exit. 155 | - text: "SA3000:" 156 | linters: 157 | - staticcheck 158 | 159 | - text: "k8s.io/api/core/v1" 160 | linters: 161 | - goimports 162 | 163 | # This is a "potential hardcoded credentials" warning. It's triggered by 164 | # any variable with 'secret' in the same, and thus hits a lot of false 165 | # positives in Kubernetes land where a Secret is an object type. 166 | - text: "G101:" 167 | linters: 168 | - gosec 169 | - gas 170 | 171 | # This is an 'errors unhandled' warning that duplicates errcheck. 172 | - text: "G104:" 173 | linters: 174 | - gosec 175 | - gas 176 | 177 | # Independently from option `exclude` we use default exclude patterns, 178 | # it can be disabled by this option. To list all 179 | # excluded by default patterns execute `golangci-lint run --help`. 180 | # Default value for this option is true. 181 | exclude-use-default: false 182 | 183 | # Show only new issues: if there are unstaged changes or untracked files, 184 | # only those changes are analyzed, else only changes in HEAD~ are analyzed. 185 | # It's a super-useful option for integration of golangci-lint into existing 186 | # large codebase. It's not practical to fix all existing issues at the moment 187 | # of integration: much better don't allow issues in new code. 188 | # Default is false. 189 | new: false 190 | 191 | # Maximum issues count per one linter. Set to 0 to disable. Default is 50. 192 | max-per-linter: 0 193 | 194 | # Maximum count of issues with the same text. Set to 0 to disable. Default is 3. 195 | max-same-issues: 0 196 | -------------------------------------------------------------------------------- /pkg/clients/database/yugabyte/yugabyte_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package yugabyte 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/google/go-cmp/cmp" 23 | rookv1alpha1 "github.com/rook/rook/pkg/apis/yugabytedb.rook.io/v1alpha1" 24 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | 26 | xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" 27 | 28 | "github.com/crossplane/provider-rook/apis/database/v1alpha1" 29 | ) 30 | 31 | const ( 32 | name = "cool-name" 33 | namespace = "cool-namespace" 34 | 35 | providerName = "cool-rook" 36 | 37 | connectionSecretName = "cool-connection-secret" 38 | ) 39 | 40 | type yugabyteClusterModifier func(*v1alpha1.YugabyteCluster) 41 | 42 | func yugabyteWithMasterReplicas(r int32) yugabyteClusterModifier { 43 | return func(i *v1alpha1.YugabyteCluster) { i.Spec.YugabyteClusterParameters.Master.Replicas = r } 44 | } 45 | 46 | func yugabyteCluster(im ...yugabyteClusterModifier) *v1alpha1.YugabyteCluster { 47 | i := &v1alpha1.YugabyteCluster{ 48 | ObjectMeta: metav1.ObjectMeta{ 49 | Name: name, 50 | }, 51 | Spec: v1alpha1.YugabyteClusterSpec{ 52 | ResourceSpec: xpv1.ResourceSpec{ 53 | ProviderReference: &xpv1.Reference{Name: providerName}, 54 | WriteConnectionSecretToReference: &xpv1.SecretReference{Name: connectionSecretName}, 55 | }, 56 | YugabyteClusterParameters: v1alpha1.YugabyteClusterParameters{ 57 | Name: name, 58 | Namespace: namespace, 59 | Master: v1alpha1.ServerSpec{ 60 | Replicas: int32(3), 61 | Network: v1alpha1.NetworkSpec{ 62 | Ports: []v1alpha1.PortSpec{{ 63 | Name: "cool-master-port", 64 | Port: int32(7000), 65 | }}, 66 | }, 67 | }, 68 | TServer: v1alpha1.ServerSpec{ 69 | Replicas: int32(3), 70 | Network: v1alpha1.NetworkSpec{ 71 | Ports: []v1alpha1.PortSpec{{ 72 | Name: "cool-tserver-port", 73 | Port: int32(7001), 74 | }}, 75 | }, 76 | }, 77 | }, 78 | }, 79 | } 80 | 81 | for _, m := range im { 82 | m(i) 83 | } 84 | 85 | return i 86 | } 87 | 88 | type rookYugabyteClusterModifier func(*rookv1alpha1.YBCluster) 89 | 90 | func withMasterReplicas(i int32) rookYugabyteClusterModifier { 91 | return func(c *rookv1alpha1.YBCluster) { c.Spec.Master.Replicas = i } 92 | } 93 | 94 | func rookYugabyteCluster(im ...rookYugabyteClusterModifier) *rookv1alpha1.YBCluster { 95 | i := &rookv1alpha1.YBCluster{ 96 | ObjectMeta: metav1.ObjectMeta{ 97 | Namespace: namespace, 98 | Name: name, 99 | }, 100 | Spec: rookv1alpha1.YBClusterSpec{ 101 | Master: rookv1alpha1.ServerSpec{ 102 | Replicas: int32(3), 103 | Network: rookv1alpha1.NetworkSpec{ 104 | Ports: []rookv1alpha1.PortSpec{{ 105 | Name: "cool-master-port", 106 | Port: int32(7000), 107 | }}, 108 | }, 109 | }, 110 | TServer: rookv1alpha1.ServerSpec{ 111 | Replicas: int32(3), 112 | Network: rookv1alpha1.NetworkSpec{ 113 | Ports: []rookv1alpha1.PortSpec{{ 114 | Name: "cool-tserver-port", 115 | Port: int32(7001), 116 | }}, 117 | }, 118 | }, 119 | }, 120 | } 121 | 122 | for _, m := range im { 123 | m(i) 124 | } 125 | 126 | return i 127 | } 128 | 129 | type crossServerModifier func(v1alpha1.ServerSpec) 130 | 131 | func withCrossServerReplicas(i int32) crossServerModifier { 132 | return func(s v1alpha1.ServerSpec) { s.Replicas = i } 133 | } 134 | 135 | func crossServer(sm ...crossServerModifier) v1alpha1.ServerSpec { 136 | s := v1alpha1.ServerSpec{ 137 | Replicas: int32(3), 138 | Network: v1alpha1.NetworkSpec{ 139 | Ports: []v1alpha1.PortSpec{{ 140 | Name: "cool-tserver-port", 141 | Port: int32(7001), 142 | }}, 143 | }, 144 | } 145 | 146 | for _, m := range sm { 147 | m(s) 148 | } 149 | 150 | return s 151 | } 152 | 153 | type rookServerModifier func(rookv1alpha1.ServerSpec) 154 | 155 | func withRookServerReplicas(i int32) rookServerModifier { 156 | return func(s rookv1alpha1.ServerSpec) { s.Replicas = i } 157 | } 158 | 159 | func rookServer(sm ...rookServerModifier) rookv1alpha1.ServerSpec { 160 | s := rookv1alpha1.ServerSpec{ 161 | Replicas: int32(3), 162 | Network: rookv1alpha1.NetworkSpec{ 163 | Ports: []rookv1alpha1.PortSpec{{ 164 | Name: "cool-tserver-port", 165 | Port: int32(7001), 166 | }}, 167 | }, 168 | } 169 | 170 | for _, m := range sm { 171 | m(s) 172 | } 173 | 174 | return s 175 | } 176 | 177 | func TestCrossToRook(t *testing.T) { 178 | mr := int32(5) 179 | 180 | cases := map[string]struct { 181 | c *v1alpha1.YugabyteCluster 182 | want *rookv1alpha1.YBCluster 183 | }{ 184 | "Successful": { 185 | c: yugabyteCluster(), 186 | want: rookYugabyteCluster(), 187 | }, 188 | "SuccessfulWithModifier": { 189 | c: yugabyteCluster(yugabyteWithMasterReplicas(mr)), 190 | want: rookYugabyteCluster(withMasterReplicas(mr)), 191 | }, 192 | } 193 | 194 | for name, tc := range cases { 195 | t.Run(name, func(t *testing.T) { 196 | got := CrossToRook(tc.c) 197 | if diff := cmp.Diff(tc.want, got); diff != "" { 198 | t.Errorf("CrossToRook(...): -want, +got:\n%s", diff) 199 | } 200 | }) 201 | } 202 | } 203 | 204 | func TestNeedsUpdate(t *testing.T) { 205 | mr := int32(5) 206 | 207 | cases := map[string]struct { 208 | c *v1alpha1.YugabyteCluster 209 | r *rookv1alpha1.YBCluster 210 | want bool 211 | }{ 212 | "NoUpdateNeeded": { 213 | c: yugabyteCluster(), 214 | r: rookYugabyteCluster(), 215 | want: false, 216 | }, 217 | "UpdateNeeded": { 218 | c: yugabyteCluster(), 219 | r: rookYugabyteCluster(withMasterReplicas(mr)), 220 | want: true, 221 | }, 222 | } 223 | 224 | for name, tc := range cases { 225 | t.Run(name, func(t *testing.T) { 226 | got := NeedsUpdate(tc.c, tc.r) 227 | if diff := cmp.Diff(tc.want, got); diff != "" { 228 | t.Errorf("NeedsUpdate(...): -want, +got:\n%s", diff) 229 | } 230 | }) 231 | } 232 | } 233 | 234 | func TestConvertServer(t *testing.T) { 235 | r := int32(5) 236 | 237 | cases := map[string]struct { 238 | c v1alpha1.ServerSpec 239 | want rookv1alpha1.ServerSpec 240 | }{ 241 | "Successful": { 242 | c: crossServer(), 243 | want: rookServer(), 244 | }, 245 | "SuccessfulWithModifier": { 246 | c: crossServer(withCrossServerReplicas(r)), 247 | want: rookServer(withRookServerReplicas(r)), 248 | }, 249 | } 250 | 251 | for name, tc := range cases { 252 | t.Run(name, func(t *testing.T) { 253 | got := convertServer(tc.c) 254 | if diff := cmp.Diff(tc.want, got); diff != "" { 255 | t.Errorf("convertServer(...): -want, +got:\n%s", diff) 256 | } 257 | }) 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /pkg/clients/database/cockroach/cockroach_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Crossplane Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package cockroach 18 | 19 | import ( 20 | "testing" 21 | 22 | "github.com/google/go-cmp/cmp" 23 | rookv1alpha1 "github.com/rook/rook/pkg/apis/cockroachdb.rook.io/v1alpha1" 24 | rook "github.com/rook/rook/pkg/apis/rook.io/v1alpha2" 25 | corev1 "k8s.io/api/core/v1" 26 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 | 28 | xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1" 29 | 30 | "github.com/crossplane/provider-rook/apis/database/v1alpha1" 31 | corev1alpha1 "github.com/crossplane/provider-rook/apis/v1alpha1" 32 | ) 33 | 34 | const ( 35 | name = "cool-name" 36 | namespace = "cool-namespace" 37 | 38 | providerName = "cool-rook" 39 | connectionSecretName = "cool-connection-secret" 40 | ) 41 | 42 | type cockroachClusterModifier func(*v1alpha1.CockroachCluster) 43 | 44 | func withCockroachNodeCount(c int) cockroachClusterModifier { 45 | return func(i *v1alpha1.CockroachCluster) { i.Spec.CockroachClusterParameters.Storage.NodeCount = c } 46 | } 47 | 48 | func cockroachCluster(im ...cockroachClusterModifier) *v1alpha1.CockroachCluster { 49 | i := &v1alpha1.CockroachCluster{ 50 | ObjectMeta: metav1.ObjectMeta{ 51 | Name: name, 52 | }, 53 | Spec: v1alpha1.CockroachClusterSpec{ 54 | ResourceSpec: xpv1.ResourceSpec{ 55 | ProviderReference: &xpv1.Reference{Name: providerName}, 56 | WriteConnectionSecretToReference: &xpv1.SecretReference{Name: connectionSecretName}, 57 | }, 58 | CockroachClusterParameters: v1alpha1.CockroachClusterParameters{ 59 | Name: name, 60 | Namespace: namespace, 61 | Annotations: corev1alpha1.Annotations(map[string]string{"label": "value"}), 62 | Storage: corev1alpha1.StorageScopeSpec{ 63 | NodeCount: 3, 64 | VolumeClaimTemplates: []corev1.PersistentVolumeClaim{ 65 | { 66 | ObjectMeta: metav1.ObjectMeta{ 67 | Name: "rook-cockroachdb-test", 68 | }, 69 | Spec: corev1.PersistentVolumeClaimSpec{ 70 | AccessModes: []corev1.PersistentVolumeAccessMode{"ReadWriteOnce"}, 71 | // Test does not check resource requirements due cmp pkg 72 | // inability to compare unexported fields. 73 | Resources: corev1.ResourceRequirements{}, 74 | }, 75 | }, 76 | }, 77 | }, 78 | Network: v1alpha1.NetworkSpec{ 79 | Ports: []v1alpha1.PortSpec{{ 80 | Name: "cool--port", 81 | Port: int32(7001), 82 | }}, 83 | }, 84 | Secure: false, 85 | CachePercent: 80, 86 | MaxSQLMemoryPercent: 80, 87 | }, 88 | }, 89 | } 90 | 91 | for _, m := range im { 92 | m(i) 93 | } 94 | 95 | return i 96 | } 97 | 98 | type rookCockroachClusterModifier func(*rookv1alpha1.Cluster) 99 | 100 | func withNodeCount(i int) rookCockroachClusterModifier { 101 | return func(c *rookv1alpha1.Cluster) { c.Spec.Storage.NodeCount = i } 102 | } 103 | 104 | func rookCockroachCluster(im ...rookCockroachClusterModifier) *rookv1alpha1.Cluster { 105 | i := &rookv1alpha1.Cluster{ 106 | ObjectMeta: metav1.ObjectMeta{ 107 | Name: name, 108 | Namespace: namespace, 109 | }, 110 | Spec: rookv1alpha1.ClusterSpec{ 111 | Annotations: rook.Annotations(map[string]string{"label": "value"}), 112 | Storage: rook.StorageScopeSpec{ 113 | NodeCount: 3, 114 | Selection: rook.Selection{ 115 | VolumeClaimTemplates: []corev1.PersistentVolumeClaim{ 116 | { 117 | ObjectMeta: metav1.ObjectMeta{ 118 | Name: "rook-cockroachdb-test", 119 | }, 120 | Spec: corev1.PersistentVolumeClaimSpec{ 121 | AccessModes: []corev1.PersistentVolumeAccessMode{"ReadWriteOnce"}, 122 | // Test does not check resource requirements due cmp pkg 123 | // inability to compare unexported fields. 124 | Resources: corev1.ResourceRequirements{}, 125 | }, 126 | }, 127 | }, 128 | }, 129 | }, 130 | Network: rookv1alpha1.NetworkSpec{ 131 | Ports: []rookv1alpha1.PortSpec{{ 132 | Name: "cool--port", 133 | Port: int32(7001), 134 | }}, 135 | }, 136 | Secure: false, 137 | CachePercent: 80, 138 | MaxSQLMemoryPercent: 80, 139 | }, 140 | } 141 | 142 | for _, m := range im { 143 | m(i) 144 | } 145 | 146 | return i 147 | } 148 | 149 | type crossPortsModifier func([]v1alpha1.PortSpec) 150 | 151 | func withCrossPortsName(n string) crossPortsModifier { 152 | return func(p []v1alpha1.PortSpec) { p[0].Name = n } 153 | } 154 | 155 | func crossPorts(pm ...crossPortsModifier) []v1alpha1.PortSpec { 156 | p := []v1alpha1.PortSpec{{ 157 | Name: "cool-tserver-port", 158 | Port: int32(7001), 159 | }} 160 | 161 | for _, m := range pm { 162 | m(p) 163 | } 164 | 165 | return p 166 | } 167 | 168 | type rookPortsModifier func([]rookv1alpha1.PortSpec) 169 | 170 | func withRookPortsName(n string) rookPortsModifier { 171 | return func(p []rookv1alpha1.PortSpec) { p[0].Name = n } 172 | } 173 | 174 | func rookPorts(pm ...rookPortsModifier) []rookv1alpha1.PortSpec { 175 | p := []rookv1alpha1.PortSpec{{ 176 | Name: "cool-tserver-port", 177 | Port: int32(7001), 178 | }} 179 | 180 | for _, m := range pm { 181 | m(p) 182 | } 183 | 184 | return p 185 | } 186 | 187 | func TestCrossToRook(t *testing.T) { 188 | cases := map[string]struct { 189 | c *v1alpha1.CockroachCluster 190 | want *rookv1alpha1.Cluster 191 | }{ 192 | "Successful": { 193 | c: cockroachCluster(), 194 | want: rookCockroachCluster(), 195 | }, 196 | "SuccessfulWithModifier": { 197 | c: cockroachCluster(withCockroachNodeCount(5)), 198 | want: rookCockroachCluster(withNodeCount(5)), 199 | }, 200 | } 201 | 202 | for name, tc := range cases { 203 | t.Run(name, func(t *testing.T) { 204 | got := CrossToRook(tc.c) 205 | if diff := cmp.Diff(tc.want, got); diff != "" { 206 | t.Errorf("CrossToRook(...): -want, +got:\n%s", diff) 207 | } 208 | }) 209 | } 210 | } 211 | 212 | func TestNeedsUpdate(t *testing.T) { 213 | cases := map[string]struct { 214 | c *v1alpha1.CockroachCluster 215 | r *rookv1alpha1.Cluster 216 | want bool 217 | }{ 218 | "NoUpdateNeeded": { 219 | c: cockroachCluster(), 220 | r: rookCockroachCluster(), 221 | want: false, 222 | }, 223 | "UpdateNeeded": { 224 | c: cockroachCluster(), 225 | r: rookCockroachCluster(withNodeCount(5)), 226 | want: true, 227 | }, 228 | } 229 | 230 | for name, tc := range cases { 231 | t.Run(name, func(t *testing.T) { 232 | got := NeedsUpdate(tc.c, tc.r) 233 | if diff := cmp.Diff(tc.want, got); diff != "" { 234 | t.Errorf("NeedsUpdate(...): -want, +got:\n%s", diff) 235 | } 236 | }) 237 | } 238 | } 239 | 240 | func TestConvertPorts(t *testing.T) { 241 | n := "cool-port" 242 | 243 | cases := map[string]struct { 244 | c []v1alpha1.PortSpec 245 | want []rookv1alpha1.PortSpec 246 | }{ 247 | "Successful": { 248 | c: crossPorts(), 249 | want: rookPorts(), 250 | }, 251 | "SuccessfulWithModifier": { 252 | c: crossPorts(withCrossPortsName(n)), 253 | want: rookPorts(withRookPortsName(n)), 254 | }, 255 | } 256 | 257 | for name, tc := range cases { 258 | t.Run(name, func(t *testing.T) { 259 | got := convertPorts(tc.c) 260 | if diff := cmp.Diff(tc.want, got); diff != "" { 261 | t.Errorf("convertPorts(...): -want, +got:\n%s", diff) 262 | } 263 | }) 264 | } 265 | } 266 | -------------------------------------------------------------------------------- /cluster/local/integration_tests.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -e 3 | 4 | # setting up colors 5 | BLU='\033[0;34m' 6 | YLW='\033[0;33m' 7 | GRN='\033[0;32m' 8 | RED='\033[0;31m' 9 | NOC='\033[0m' # No Color 10 | echo_info(){ 11 | printf "\n${BLU}%s${NOC}" "$1" 12 | } 13 | echo_step(){ 14 | printf "\n${BLU}>>>>>>> %s${NOC}\n" "$1" 15 | } 16 | echo_sub_step(){ 17 | printf "\n${BLU}>>> %s${NOC}\n" "$1" 18 | } 19 | 20 | echo_step_completed(){ 21 | printf "${GRN} [✔]${NOC}" 22 | } 23 | 24 | echo_success(){ 25 | printf "\n${GRN}%s${NOC}\n" "$1" 26 | } 27 | echo_warn(){ 28 | printf "\n${YLW}%s${NOC}" "$1" 29 | } 30 | echo_error(){ 31 | printf "\n${RED}%s${NOC}" "$1" 32 | exit 1 33 | } 34 | 35 | # k8s watchers 36 | 37 | wait_for_pods_in_namespace(){ 38 | local timeout=$1 39 | shift 40 | namespace=$1 41 | shift 42 | arr=("$@") 43 | local counter=0 44 | for i in "${arr[@]}"; 45 | do 46 | echo -n "waiting for pod $i in namespace $namespace..." >&2 47 | while ! ("${KUBECTL}" -n $namespace get pod $i) &>/dev/null; do 48 | if [ "$counter" -ge "$timeout" ]; then echo "TIMEOUT"; exit -1; else (( counter+=5 )); fi 49 | echo -n "." >&2 50 | sleep 5 51 | done 52 | echo "FOUND POD!" >&2 53 | done 54 | } 55 | 56 | check_deployments(){ 57 | for name in $1; do 58 | echo_sub_step "inspecting deployment '${name}'" 59 | local dep_stat=$("${KUBECTL}" -n "$2" get deployments/"${name}") 60 | 61 | echo_info "check if is deployed" 62 | if $(echo "$dep_stat" | grep -iq 'No resources found'); then 63 | echo "is not deployed" 64 | exit -1 65 | else 66 | echo_step_completed 67 | fi 68 | 69 | echo_info "check if is ready" 70 | IFS='/' read -ra ready_status_parts <<< "$(echo "$dep_stat" | awk ' FNR > 1 {print $2}')" 71 | if (("${ready_status_parts[0]}" < "${ready_status_parts[1]}")); then 72 | echo "is not Ready" 73 | exit -1 74 | else 75 | echo_step_completed 76 | fi 77 | echo 78 | done 79 | } 80 | 81 | check_pods(){ 82 | pods=$("${KUBECTL}" -n "${CROSSPLANE_NAMESPACE}" get pods) 83 | count=$(echo "$pods" | wc -l) 84 | if (("${count}"-1 != "${1}")); then 85 | sleep 10 86 | "${KUBECTL}" get events -A 87 | sleep 20 88 | echo_error "unexpected number of pods" 89 | exit -1 90 | fi 91 | echo "$pods" 92 | while read -r pod_stat; do 93 | name=$(echo "$pod_stat" | awk '{print $1}') 94 | echo_sub_step "inspecting pod '${name}'" 95 | 96 | if $(echo "$pod_stat" | awk '{print $3}' | grep -ivq 'Completed'); then 97 | echo_info "is not completed, continuing with further checks" 98 | else 99 | echo_info "is completed, foregoing further checks" 100 | echo_step_completed 101 | continue 102 | fi 103 | 104 | echo_info "check if is ready" 105 | IFS='/' read -ra ready_status_parts <<< "$(echo "$pod_stat" | awk '{print $2}')" 106 | if (("${ready_status_parts[0]}" < "${ready_status_parts[1]}")); then 107 | echo_error "is not ready" 108 | exit -1 109 | else 110 | echo_step_completed 111 | fi 112 | 113 | echo_info "check if is running" 114 | if $(echo "$pod_stat" | awk '{print $3}' | grep -ivq 'Running'); then 115 | echo_error "is not running" 116 | exit -1 117 | else 118 | echo_step_completed 119 | fi 120 | 121 | echo_info "check if has restarts" 122 | if (( $(echo "$pod_stat" | awk '{print $4}') > 0 )); then 123 | echo_error "has restarts" 124 | exit -1 125 | else 126 | echo_step_completed 127 | fi 128 | echo 129 | done <<< "$(echo "$pods" | awk 'FNR>1')" 130 | } 131 | 132 | # ------------------------------ 133 | projectdir="$( cd "$( dirname "${BASH_SOURCE[0]}")"/../.. && pwd )" 134 | 135 | # get the build environment variables from the special build.vars target in the main makefile 136 | eval $(make --no-print-directory -C ${projectdir} build.vars) 137 | 138 | # ------------------------------ 139 | 140 | HOSTARCH="${HOSTARCH:-amd64}" 141 | BUILD_IMAGE="${BUILD_REGISTRY}/${PROJECT_NAME}-${HOSTARCH}" 142 | CONTROLLER_IMAGE="${BUILD_REGISTRY}/${PROJECT_NAME}-controller-${HOSTARCH}" 143 | 144 | version_tag="$(cat ${projectdir}/_output/version)" 145 | # tag as latest version to load into kind cluster 146 | PACKAGE_CONTROLLER_IMAGE="${DOCKER_REGISTRY}/${PROJECT_NAME}-controller:${VERSION}" 147 | K8S_CLUSTER="${K8S_CLUSTER:-${BUILD_REGISTRY}-INTTESTS}" 148 | 149 | CROSSPLANE_NAMESPACE="crossplane-system" 150 | PACKAGE_NAME="provider-rook" 151 | 152 | # cleanup on exit 153 | if [ "$skipcleanup" != true ]; then 154 | function cleanup { 155 | echo_step "Cleaning up..." 156 | export KUBECONFIG= 157 | "${KIND}" delete cluster --name="${K8S_CLUSTER}" 158 | } 159 | 160 | trap cleanup EXIT 161 | fi 162 | 163 | # setup package cache 164 | echo_step "setting up local package cache" 165 | CACHE_PATH="${projectdir}/.work/inttest-package-cache" 166 | mkdir -p "${CACHE_PATH}" 167 | echo "created cache dir at ${CACHE_PATH}" 168 | docker save "${BUILD_IMAGE}" -o "${CACHE_PATH}/${PACKAGE_NAME}.xpkg" && chmod 644 "${CACHE_PATH}/${PACKAGE_NAME}.xpkg" 169 | 170 | # create kind cluster with extra mounts 171 | echo_step "creating k8s cluster using kind" 172 | KIND_CONFIG="$( cat <