diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c60050 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +collections \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..886ea3f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,15 @@ +FROM quay.io/operator-framework/ansible-operator:v1.0.1 + +USER 0 +RUN dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-8-x86_64/pgdg-redhat-repo-latest.noarch.rpm +RUN dnf install -y libpq5-devel +RUN pip3 install psycopg2-binary +USER 1001 + +COPY requirements.yml ${HOME}/requirements.yml +RUN ansible-galaxy collection install -r ${HOME}/requirements.yml \ + && chmod -R ug+rwx ${HOME}/.ansible + +COPY watches.yaml ${HOME}/watches.yaml +COPY roles/ ${HOME}/roles/ +COPY playbooks/ ${HOME}/playbooks/ diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..723a654 --- /dev/null +++ b/Makefile @@ -0,0 +1,92 @@ +# Current Operator version +VERSION ?= 0.0.1 +# Default bundle image tag +BUNDLE_IMG ?= controller-bundle:$(VERSION) +# Options for 'bundle-build' +ifneq ($(origin CHANNELS), undefined) +BUNDLE_CHANNELS := --channels=$(CHANNELS) +endif +ifneq ($(origin DEFAULT_CHANNEL), undefined) +BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) +endif +BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) + +# Image URL to use all building/pushing image targets +IMG ?= controller:latest + +all: docker-build + +# Run against the configured Kubernetes cluster in ~/.kube/config +run: ansible-operator + $(ANSIBLE_OPERATOR) run + +# Install CRDs into a cluster +install: kustomize + $(KUSTOMIZE) build config/crd | kubectl apply -f - + +# Uninstall CRDs from a cluster +uninstall: kustomize + $(KUSTOMIZE) build config/crd | kubectl delete -f - + +# Deploy controller in the configured Kubernetes cluster in ~/.kube/config +deploy: kustomize + cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} + $(KUSTOMIZE) build config/default | kubectl apply -f - + +# Undeploy controller in the configured Kubernetes cluster in ~/.kube/config +undeploy: kustomize + $(KUSTOMIZE) build config/default | kubectl delete -f - + +# Build the docker image +docker-build: + docker build . -t ${IMG} + +# Push the docker image +docker-push: + docker push ${IMG} + +PATH := $(PATH):$(PWD)/bin +SHELL := env PATH=$(PATH) /bin/sh +OS = $(shell uname -s | tr '[:upper:]' '[:lower:]') +ARCH = $(shell uname -m | sed 's/x86_64/amd64/') +OSOPER = $(shell uname -s | tr '[:upper:]' '[:lower:]' | sed 's/darwin/apple-darwin/' | sed 's/linux/linux-gnu/') +ARCHOPER = $(shell uname -m ) + +kustomize: +ifeq (, $(shell which kustomize 2>/dev/null)) + @{ \ + set -e ;\ + mkdir -p bin ;\ + curl -sSLo - https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/v3.5.4/kustomize_v3.5.4_$(OS)_$(ARCH).tar.gz | tar xzf - -C bin/ ;\ + } +KUSTOMIZE=$(realpath ./bin/kustomize) +else +KUSTOMIZE=$(shell which kustomize) +endif + +ansible-operator: +ifeq (, $(shell which ansible-operator 2>/dev/null)) + @{ \ + set -e ;\ + mkdir -p bin ;\ + curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.0.1/ansible-operator-v1.0.1-$(ARCHOPER)-$(OSOPER) ;\ + mv ansible-operator-v1.0.1-$(ARCHOPER)-$(OSOPER) ./bin/ansible-operator ;\ + chmod +x ./bin/ansible-operator ;\ + } +ANSIBLE_OPERATOR=$(realpath ./bin/ansible-operator) +else +ANSIBLE_OPERATOR=$(shell which ansible-operator) +endif + +# Generate bundle manifests and metadata, then validate generated files. +.PHONY: bundle +bundle: kustomize + operator-sdk generate kustomize manifests -q + cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) + $(KUSTOMIZE) build config/manifests | operator-sdk generate bundle -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) + operator-sdk bundle validate ./bundle + +# Build the bundle image. +.PHONY: bundle-build +bundle-build: + docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) . diff --git a/PROJECT b/PROJECT new file mode 100644 index 0000000..46813d5 --- /dev/null +++ b/PROJECT @@ -0,0 +1,8 @@ +domain: takeoff.io +layout: ansible.sdk.operatorframework.io/v1 +projectName: pgsql-db-user-manager +resources: +- group: pgsql + kind: ReadOnlyDBUser + version: v1alpha1 +version: 3-alpha diff --git a/README.md b/README.md index f128e48..3be96e4 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,38 @@ -# pgsql-db-user-manager-operator -A Kubernetes operator to manage postgresql users and permissions +# PostgreSQL database user manager operator for kubernetes + +## Features +* Create a user with read-only access to a single database + +## Installation +Unknown at this time + +## CRs + +### ReadOnlyDBUser +```yaml +apiVersion: pgsql.takeoff.io/v1alpha1 +kind: ReadOnlyDBUser +metadata: + name: testdbrouser # name of dbuser to create +spec: + db_name: testdb # name of database to give select, use (readonly) access to + password: + value: string # password value in plaintxt + valueFrom: # get the password from a kubernetes secret object + secretKeyRef: + key: string + name: string + pghost: cloudsql-postgres # host to connect to + pguser: postgres # admin user to connect and create user as + pgpass: donotuseme1234 # password for admin user +``` + +This creates a user called `testdbrouser` with a password of `changeme1234` and is given read-only access to `testdb`. +It performs the same operations as these SQL statements: +1. \connect postgres +2. CREATE USER testdbrouser WITH PASSWORD 'changeme1234' +3. \connect testdb +4. GRANT USAGE ON SCHEMA public TO testdbrouser +5. GRANT SELECT ON ALL TABLES IN SCHEMA public TO testdbrouser +6. ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO testdbrouser +>>>>>>> 3ef00b5... initial working MVP diff --git a/config/crd/bases/pgsql.takeoff.io_readonlydbusers.yaml b/config/crd/bases/pgsql.takeoff.io_readonlydbusers.yaml new file mode 100644 index 0000000..253e4a9 --- /dev/null +++ b/config/crd/bases/pgsql.takeoff.io_readonlydbusers.yaml @@ -0,0 +1,44 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: readonlydbusers.pgsql.takeoff.io +spec: + group: pgsql.takeoff.io + names: + kind: ReadOnlyDBUser + listKind: ReadOnlyDBUserList + plural: readonlydbusers + singular: readonlydbuser + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: ReadOnlyDBUser is the Schema for the readonlydbusers API + properties: + apiVersion: + 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' + type: string + kind: + 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' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of ReadOnlyDBUser + type: object + x-kubernetes-preserve-unknown-fields: true + status: + description: Status defines the observed state of ReadOnlyDBUser + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: true + storage: true + subresources: + status: {} diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml new file mode 100644 index 0000000..a1f60d0 --- /dev/null +++ b/config/crd/kustomization.yaml @@ -0,0 +1,6 @@ +# This kustomization.yaml is not intended to be run by itself, +# since it depends on service name and namespace that are out of this kustomize package. +# It should be run by config/default +resources: +- bases/pgsql.takeoff.io_readonlydbusers.yaml +# +kubebuilder:scaffold:crdkustomizeresource diff --git a/config/default/kustomization.yaml b/config/default/kustomization.yaml new file mode 100644 index 0000000..f38ffa6 --- /dev/null +++ b/config/default/kustomization.yaml @@ -0,0 +1,26 @@ +# Adds namespace to all resources. +namespace: pgsql-db-user-manager-system + +# Value of this field is prepended to the +# names of all resources, e.g. a deployment named +# "wordpress" becomes "alices-wordpress". +# Note that it should also match with the prefix (text before '-') of the namespace +# field above. +namePrefix: pgsql-db-user-manager- + +# Labels to add to all resources and selectors. +#commonLabels: +# someName: someValue + +bases: +- ../crd +- ../rbac +- ../manager +# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. +#- ../prometheus + +patchesStrategicMerge: + # Protect the /metrics endpoint by putting it behind auth. + # If you want your controller-manager to expose the /metrics + # endpoint w/o any authn/z, please comment the following line. +- manager_auth_proxy_patch.yaml diff --git a/config/default/manager_auth_proxy_patch.yaml b/config/default/manager_auth_proxy_patch.yaml new file mode 100644 index 0000000..f04b101 --- /dev/null +++ b/config/default/manager_auth_proxy_patch.yaml @@ -0,0 +1,26 @@ +# This patch inject a sidecar container which is a HTTP proxy for the +# controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: kube-rbac-proxy + image: gcr.io/kubebuilder/kube-rbac-proxy:v0.5.0 + args: + - "--secure-listen-address=0.0.0.0:8443" + - "--upstream=http://127.0.0.1:8080/" + - "--logtostderr=true" + - "--v=10" + ports: + - containerPort: 8443 + name: https + - name: manager + args: + - "--metrics-addr=127.0.0.1:8080" + - "--enable-leader-election" + - "--leader-election-id=pgsql-db-user-manager" diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml new file mode 100644 index 0000000..0af84fc --- /dev/null +++ b/config/manager/kustomization.yaml @@ -0,0 +1,4 @@ +resources: +- manager.yaml +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml new file mode 100644 index 0000000..64dc45b --- /dev/null +++ b/config/manager/manager.yaml @@ -0,0 +1,31 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + control-plane: controller-manager + name: system +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system + labels: + control-plane: controller-manager +spec: + selector: + matchLabels: + control-plane: controller-manager + replicas: 1 + template: + metadata: + labels: + control-plane: controller-manager + spec: + containers: + - name: manager + args: + - "--enable-leader-election" + - "--leader-election-id=pgsql-db-user-manager" + image: controller:latest + terminationGracePeriodSeconds: 10 diff --git a/config/prometheus/kustomization.yaml b/config/prometheus/kustomization.yaml new file mode 100644 index 0000000..ed13716 --- /dev/null +++ b/config/prometheus/kustomization.yaml @@ -0,0 +1,2 @@ +resources: +- monitor.yaml diff --git a/config/prometheus/monitor.yaml b/config/prometheus/monitor.yaml new file mode 100644 index 0000000..1b44d4f --- /dev/null +++ b/config/prometheus/monitor.yaml @@ -0,0 +1,16 @@ +--- +# Prometheus Monitor Service (Metrics) +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + labels: + control-plane: controller-manager + name: controller-manager-metrics-monitor + namespace: system +spec: + endpoints: + - path: /metrics + port: https + selector: + matchLabels: + control-plane: controller-manager diff --git a/config/rbac/auth_proxy_client_clusterrole.yaml b/config/rbac/auth_proxy_client_clusterrole.yaml new file mode 100644 index 0000000..7d62534 --- /dev/null +++ b/config/rbac/auth_proxy_client_clusterrole.yaml @@ -0,0 +1,7 @@ +apiVersion: rbac.authorization.k8s.io/v1beta1 +kind: ClusterRole +metadata: + name: metrics-reader +rules: +- nonResourceURLs: ["/metrics"] + verbs: ["get"] diff --git a/config/rbac/auth_proxy_role.yaml b/config/rbac/auth_proxy_role.yaml new file mode 100644 index 0000000..618f5e4 --- /dev/null +++ b/config/rbac/auth_proxy_role.yaml @@ -0,0 +1,13 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: proxy-role +rules: +- apiGroups: ["authentication.k8s.io"] + resources: + - tokenreviews + verbs: ["create"] +- apiGroups: ["authorization.k8s.io"] + resources: + - subjectaccessreviews + verbs: ["create"] diff --git a/config/rbac/auth_proxy_role_binding.yaml b/config/rbac/auth_proxy_role_binding.yaml new file mode 100644 index 0000000..48ed1e4 --- /dev/null +++ b/config/rbac/auth_proxy_role_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: proxy-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: proxy-role +subjects: +- kind: ServiceAccount + name: default + namespace: system diff --git a/config/rbac/auth_proxy_service.yaml b/config/rbac/auth_proxy_service.yaml new file mode 100644 index 0000000..6cf656b --- /dev/null +++ b/config/rbac/auth_proxy_service.yaml @@ -0,0 +1,14 @@ +apiVersion: v1 +kind: Service +metadata: + labels: + control-plane: controller-manager + name: controller-manager-metrics-service + namespace: system +spec: + ports: + - name: https + port: 8443 + targetPort: https + selector: + control-plane: controller-manager diff --git a/config/rbac/kustomization.yaml b/config/rbac/kustomization.yaml new file mode 100644 index 0000000..66c2833 --- /dev/null +++ b/config/rbac/kustomization.yaml @@ -0,0 +1,12 @@ +resources: +- role.yaml +- role_binding.yaml +- leader_election_role.yaml +- leader_election_role_binding.yaml +# Comment the following 4 lines if you want to disable +# the auth proxy (https://github.com/brancz/kube-rbac-proxy) +# which protects your /metrics endpoint. +- auth_proxy_service.yaml +- auth_proxy_role.yaml +- auth_proxy_role_binding.yaml +- auth_proxy_client_clusterrole.yaml diff --git a/config/rbac/leader_election_role.yaml b/config/rbac/leader_election_role.yaml new file mode 100644 index 0000000..53e9749 --- /dev/null +++ b/config/rbac/leader_election_role.yaml @@ -0,0 +1,25 @@ +# permissions to do leader election. +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: leader-election-role +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch diff --git a/config/rbac/leader_election_role_binding.yaml b/config/rbac/leader_election_role_binding.yaml new file mode 100644 index 0000000..eed1690 --- /dev/null +++ b/config/rbac/leader_election_role_binding.yaml @@ -0,0 +1,12 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: leader-election-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: leader-election-role +subjects: +- kind: ServiceAccount + name: default + namespace: system diff --git a/config/rbac/readonlydbuser_editor_role.yaml b/config/rbac/readonlydbuser_editor_role.yaml new file mode 100644 index 0000000..ce0ba91 --- /dev/null +++ b/config/rbac/readonlydbuser_editor_role.yaml @@ -0,0 +1,24 @@ +# permissions for end users to edit readonlydbusers. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: readonlydbuser-editor-role +rules: +- apiGroups: + - pgsql.takeoff.io + resources: + - readonlydbusers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - pgsql.takeoff.io + resources: + - readonlydbusers/status + verbs: + - get diff --git a/config/rbac/readonlydbuser_viewer_role.yaml b/config/rbac/readonlydbuser_viewer_role.yaml new file mode 100644 index 0000000..78022a6 --- /dev/null +++ b/config/rbac/readonlydbuser_viewer_role.yaml @@ -0,0 +1,20 @@ +# permissions for end users to view readonlydbusers. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: readonlydbuser-viewer-role +rules: +- apiGroups: + - pgsql.takeoff.io + resources: + - readonlydbusers + verbs: + - get + - list + - watch +- apiGroups: + - pgsql.takeoff.io + resources: + - readonlydbusers/status + verbs: + - get diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml new file mode 100644 index 0000000..6c18851 --- /dev/null +++ b/config/rbac/role.yaml @@ -0,0 +1,57 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: manager-role +rules: + ## + ## Base operator rules + ## + - apiGroups: + - "" + resources: + - secrets + - pods + - pods/exec + - pods/log + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resources: + - deployments + - daemonsets + - replicasets + - statefulsets + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + ## + ## Rules for pgsql.takeoff.io/v1alpha1, Kind: ReadOnlyDBUser + ## + - apiGroups: + - pgsql.takeoff.io + resources: + - readonlydbusers + - readonlydbusers/status + - readonlydbusers/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +# +kubebuilder:scaffold:rules diff --git a/config/rbac/role_binding.yaml b/config/rbac/role_binding.yaml new file mode 100644 index 0000000..98f8782 --- /dev/null +++ b/config/rbac/role_binding.yaml @@ -0,0 +1,13 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: manager-role +subjects: +- kind: ServiceAccount + name: default + namespace: system diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml new file mode 100644 index 0000000..36c753c --- /dev/null +++ b/config/samples/kustomization.yaml @@ -0,0 +1,4 @@ +## Append samples you want in your CSV to this file as resources ## +resources: +- pgsql_v1alpha1_readonlydbuser.yaml +# +kubebuilder:scaffold:manifestskustomizesamples diff --git a/config/samples/pgsql_v1alpha1_readonlydbuser.yaml b/config/samples/pgsql_v1alpha1_readonlydbuser.yaml new file mode 100644 index 0000000..d2beb90 --- /dev/null +++ b/config/samples/pgsql_v1alpha1_readonlydbuser.yaml @@ -0,0 +1,17 @@ +apiVersion: pgsql.takeoff.io/v1alpha1 +kind: ReadOnlyDBUser +metadata: + name: testdbrouser + namespace: osdk-test + annotations: + ansible.sdk.operatorframework.io/verbosity: "5" +spec: + db_name: testdb + password: + valueFrom: + secretKeyRef: + key: password + name: testdbrouser-pw-secret + pghost: cloudsql-postgres + pguser: postgresadmin + pgpass: donotuseme1234 \ No newline at end of file diff --git a/config/scorecard/bases/config.yaml b/config/scorecard/bases/config.yaml new file mode 100644 index 0000000..c770478 --- /dev/null +++ b/config/scorecard/bases/config.yaml @@ -0,0 +1,7 @@ +apiVersion: scorecard.operatorframework.io/v1alpha3 +kind: Configuration +metadata: + name: config +stages: +- parallel: true + tests: [] diff --git a/config/scorecard/kustomization.yaml b/config/scorecard/kustomization.yaml new file mode 100644 index 0000000..d73509e --- /dev/null +++ b/config/scorecard/kustomization.yaml @@ -0,0 +1,16 @@ +resources: +- bases/config.yaml +patchesJson6902: +- path: patches/basic.config.yaml + target: + group: scorecard.operatorframework.io + version: v1alpha3 + kind: Configuration + name: config +- path: patches/olm.config.yaml + target: + group: scorecard.operatorframework.io + version: v1alpha3 + kind: Configuration + name: config +# +kubebuilder:scaffold:patchesJson6902 diff --git a/config/scorecard/patches/basic.config.yaml b/config/scorecard/patches/basic.config.yaml new file mode 100644 index 0000000..0016b65 --- /dev/null +++ b/config/scorecard/patches/basic.config.yaml @@ -0,0 +1,10 @@ +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - basic-check-spec + image: quay.io/operator-framework/scorecard-test:v1.0.1 + labels: + suite: basic + test: basic-check-spec-test diff --git a/config/scorecard/patches/olm.config.yaml b/config/scorecard/patches/olm.config.yaml new file mode 100644 index 0000000..a39bfc5 --- /dev/null +++ b/config/scorecard/patches/olm.config.yaml @@ -0,0 +1,50 @@ +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-bundle-validation + image: quay.io/operator-framework/scorecard-test:v1.0.1 + labels: + suite: olm + test: olm-bundle-validation-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-crds-have-validation + image: quay.io/operator-framework/scorecard-test:v1.0.1 + labels: + suite: olm + test: olm-crds-have-validation-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-crds-have-resources + image: quay.io/operator-framework/scorecard-test:v1.0.1 + labels: + suite: olm + test: olm-crds-have-resources-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-spec-descriptors + image: quay.io/operator-framework/scorecard-test:v1.0.1 + labels: + suite: olm + test: olm-spec-descriptors-test +- op: add + path: /stages/0/tests/- + value: + entrypoint: + - scorecard-test + - olm-status-descriptors + image: quay.io/operator-framework/scorecard-test:v1.0.1 + labels: + suite: olm + test: olm-status-descriptors-test diff --git a/config/testing-local/kustomization.yaml b/config/testing-local/kustomization.yaml new file mode 100644 index 0000000..3211e0e --- /dev/null +++ b/config/testing-local/kustomization.yaml @@ -0,0 +1,16 @@ +# Adds namespace to all resources. +namespace: osdk-test + +# Labels to add to all resources and selectors. +#commonLabels: +# someName: someValue + +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- ../testing/prefix + +images: +- name: testing + newName: testing-operator + newTag: latest diff --git a/config/testing/cloudsql/gcp-sql-db.yaml b/config/testing/cloudsql/gcp-sql-db.yaml new file mode 100644 index 0000000..e4baa61 --- /dev/null +++ b/config/testing/cloudsql/gcp-sql-db.yaml @@ -0,0 +1,9 @@ +apiVersion: sql.cnrm.cloud.google.com/v1beta1 +kind: SQLDatabase +metadata: + name: testdb + annotations: + cnrm.cloud.google.com/project-id: takeoff-tgtest-d837 +spec: + instanceRef: + name: molecule-pgsql \ No newline at end of file diff --git a/config/testing/cloudsql/gcp-sql-instance.yaml b/config/testing/cloudsql/gcp-sql-instance.yaml new file mode 100644 index 0000000..8d06a7c --- /dev/null +++ b/config/testing/cloudsql/gcp-sql-instance.yaml @@ -0,0 +1,12 @@ +apiVersion: sql.cnrm.cloud.google.com/v1beta1 +kind: SQLInstance +metadata: + name: molecule-pgsql + annotations: + cnrm.cloud.google.com/project-id: takeoff-tgtest-d837 + cnrm.cloud.google.com/deletion-policy: abandon +spec: + databaseVersion: POSTGRES_11 + region: us-central1 + settings: + tier: db-f1-micro \ No newline at end of file diff --git a/config/testing/cloudsql/gcp-sql-policy-member.yaml b/config/testing/cloudsql/gcp-sql-policy-member.yaml new file mode 100644 index 0000000..fffc275 --- /dev/null +++ b/config/testing/cloudsql/gcp-sql-policy-member.yaml @@ -0,0 +1,11 @@ +apiVersion: iam.cnrm.cloud.google.com/v1beta1 +kind: IAMPolicyMember +metadata: + name: sql-proxy-sa-project-policymember + annotations: + cnrm.cloud.google.com/project-id: takeoff-tgtest-d837 +spec: + member: serviceAccount:sql-proxy-sa@takeoff-tgtest-d837.iam.gserviceaccount.com + role: roles/cloudsql.client + resourceRef: + kind: Project diff --git a/config/testing/cloudsql/gcp-sql-service-account.yaml b/config/testing/cloudsql/gcp-sql-service-account.yaml new file mode 100644 index 0000000..6ae4fa6 --- /dev/null +++ b/config/testing/cloudsql/gcp-sql-service-account.yaml @@ -0,0 +1,8 @@ +apiVersion: iam.cnrm.cloud.google.com/v1beta1 +kind: IAMServiceAccount +metadata: + name: sql-proxy-sa + annotations: + cnrm.cloud.google.com/project-id: takeoff-tgtest-d837 +spec: + displayName: Service Account for cloudsql-proxy service diff --git a/config/testing/cloudsql/gcp-sql-user.yaml b/config/testing/cloudsql/gcp-sql-user.yaml new file mode 100644 index 0000000..0f7a79b --- /dev/null +++ b/config/testing/cloudsql/gcp-sql-user.yaml @@ -0,0 +1,11 @@ +apiVersion: sql.cnrm.cloud.google.com/v1beta1 +kind: SQLUser +metadata: + name: postgresadmin + annotations: + cnrm.cloud.google.com/project-id: takeoff-tgtest-d837 +spec: + instanceRef: + name: molecule-pgsql + password: + value: donotuseme1234 \ No newline at end of file diff --git a/config/testing/cloudsql/gcp-wi-policy.yaml b/config/testing/cloudsql/gcp-wi-policy.yaml new file mode 100644 index 0000000..3c451c2 --- /dev/null +++ b/config/testing/cloudsql/gcp-wi-policy.yaml @@ -0,0 +1,15 @@ +apiVersion: iam.cnrm.cloud.google.com/v1beta1 +kind: IAMPolicy +metadata: + name: sql-wp-sa-wi-policy + annotations: + cnrm.cloud.google.com/project-id: takeoff-tgtest-d837 +spec: + resourceRef: + apiVersion: iam.cnrm.cloud.google.com/v1beta1 + kind: IAMServiceAccount + name: sql-proxy-sa + bindings: + - role: roles/iam.workloadIdentityUser + members: + - serviceAccount:takeoff-tgtest-d837.svc.id.goog[osdk-test/sql-proxy-ksa-wi] diff --git a/config/testing/cloudsql/kustomization.yaml b/config/testing/cloudsql/kustomization.yaml new file mode 100644 index 0000000..d8bb328 --- /dev/null +++ b/config/testing/cloudsql/kustomization.yaml @@ -0,0 +1,9 @@ +resources: + - gcp-sql-db.yaml + - gcp-sql-instance.yaml + - gcp-sql-policy-member.yaml + - gcp-sql-service-account.yaml + - gcp-sql-user.yaml + - gcp-wi-policy.yaml + - proxy_with_workload_identity.yaml + - service_account.yaml \ No newline at end of file diff --git a/config/testing/cloudsql/proxy_with_workload_identity.yaml b/config/testing/cloudsql/proxy_with_workload_identity.yaml new file mode 100644 index 0000000..9799710 --- /dev/null +++ b/config/testing/cloudsql/proxy_with_workload_identity.yaml @@ -0,0 +1,40 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cloudsql-proxy +spec: + selector: + matchLabels: + app: cloudsql-proxy + template: + metadata: + labels: + app: cloudsql-proxy + spec: + serviceAccountName: sql-proxy-ksa-wi + containers: + - name: cloud-sql-proxy + image: gcr.io/cloudsql-docker/gce-proxy:1.17 + command: + - "/cloud_sql_proxy" + - "-instances=takeoff-tgtest-d837:us-central1:molecule-pgsql=tcp:0.0.0.0:5432" + ports: + - containerPort: 5432 + name: sql + protocol: TCP + securityContext: + runAsNonRoot: true +--- +apiVersion: v1 +kind: Service +metadata: + name: cloudsql-postgres +spec: + ports: + - name: sql + port: 5432 + protocol: TCP + targetPort: sql + selector: + app: cloudsql-proxy + type: ClusterIP diff --git a/config/testing/cloudsql/service_account.yaml b/config/testing/cloudsql/service_account.yaml new file mode 100644 index 0000000..5ac8929 --- /dev/null +++ b/config/testing/cloudsql/service_account.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: sql-proxy-ksa-wi + annotations: + iam.gke.io/gcp-service-account: sql-proxy-sa@takeoff-tgtest-d837.iam.gserviceaccount.com \ No newline at end of file diff --git a/config/testing/debug_logs_patch.yaml b/config/testing/debug_logs_patch.yaml new file mode 100644 index 0000000..3e31e2f --- /dev/null +++ b/config/testing/debug_logs_patch.yaml @@ -0,0 +1,14 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + env: + - name: ANSIBLE_DEBUG_LOGS + value: "TRUE" diff --git a/config/testing/kustomization.yaml b/config/testing/kustomization.yaml new file mode 100644 index 0000000..eea8b5f --- /dev/null +++ b/config/testing/kustomization.yaml @@ -0,0 +1,16 @@ +# Adds namespace to all resources. +namespace: osdk-test + +# Labels to add to all resources and selectors. +#commonLabels: +# someName: someValue + +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- cloudsql +- prefix + +images: +- name: testing + newName: testing-operator diff --git a/config/testing/manager_image.yaml b/config/testing/manager_image.yaml new file mode 100644 index 0000000..e44f542 --- /dev/null +++ b/config/testing/manager_image.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + image: testing diff --git a/config/testing/prefix/kustomization.yaml b/config/testing/prefix/kustomization.yaml new file mode 100644 index 0000000..7c786af --- /dev/null +++ b/config/testing/prefix/kustomization.yaml @@ -0,0 +1,15 @@ +namePrefix: osdk- + +patchesStrategicMerge: +- ../manager_image.yaml +- ../debug_logs_patch.yaml +- ../../default/manager_auth_proxy_patch.yaml +- ../pull_policy/Always.yaml + +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: +- namespace.yaml +- ../../crd +- ../../rbac +- ../../manager \ No newline at end of file diff --git a/config/testing/prefix/namespace.yaml b/config/testing/prefix/namespace.yaml new file mode 100644 index 0000000..7fee77b --- /dev/null +++ b/config/testing/prefix/namespace.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Namespace +metadata: + annotations: + cnrm.cloud.google.com/project-id: takeoff-tgtest-d837 + labels: + control-plane: controller-manager + name: test \ No newline at end of file diff --git a/config/testing/pull_policy/Always.yaml b/config/testing/pull_policy/Always.yaml new file mode 100644 index 0000000..6b0a8e2 --- /dev/null +++ b/config/testing/pull_policy/Always.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + imagePullPolicy: Always diff --git a/config/testing/pull_policy/IfNotPresent.yaml b/config/testing/pull_policy/IfNotPresent.yaml new file mode 100644 index 0000000..2f52f49 --- /dev/null +++ b/config/testing/pull_policy/IfNotPresent.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + imagePullPolicy: IfNotPresent diff --git a/config/testing/pull_policy/Never.yaml b/config/testing/pull_policy/Never.yaml new file mode 100644 index 0000000..86f13d8 --- /dev/null +++ b/config/testing/pull_policy/Never.yaml @@ -0,0 +1,12 @@ +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: controller-manager + namespace: system +spec: + template: + spec: + containers: + - name: manager + imagePullPolicy: Never diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml new file mode 100644 index 0000000..0633db9 --- /dev/null +++ b/molecule/default/converge.yml @@ -0,0 +1,18 @@ +--- +- name: Converge + hosts: localhost + connection: local + gather_facts: no + collections: + - community.kubernetes + + tasks: + - name: Create Namespace + k8s: + api_version: v1 + kind: Namespace + name: '{{ namespace }}' + + - import_tasks: kustomize.yml + vars: + state: present diff --git a/molecule/default/create.yml b/molecule/default/create.yml new file mode 100644 index 0000000..e43ff65 --- /dev/null +++ b/molecule/default/create.yml @@ -0,0 +1,17 @@ +--- +- name: Create + hosts: localhost + connection: local + gather_facts: false + tasks: + + - name: Build operator image + docker_image: + build: + path: '{{ project_dir }}' + pull: no + name: '{{ operator_image }}' + tag: '{{ operator_image_tag }}' + push: yes + source: build + force_source: yes diff --git a/molecule/default/destroy.yml b/molecule/default/destroy.yml new file mode 100644 index 0000000..13cf119 --- /dev/null +++ b/molecule/default/destroy.yml @@ -0,0 +1,24 @@ +--- +- name: Destroy + hosts: localhost + connection: local + gather_facts: false + collections: + - community.kubernetes + + tasks: + - import_tasks: kustomize.yml + vars: + state: absent + + - name: Destroy Namespace + k8s: + api_version: v1 + kind: Namespace + name: '{{ namespace }}' + state: absent + + - name: Unset pull policy + command: '{{ kustomize }} edit remove patch pull_policy/{{ operator_pull_policy }}.yaml' + args: + chdir: '{{ config_dir }}' diff --git a/molecule/default/kustomize.yml b/molecule/default/kustomize.yml new file mode 100644 index 0000000..4c8ce42 --- /dev/null +++ b/molecule/default/kustomize.yml @@ -0,0 +1,15 @@ +--- +- name: Build kustomize testing overlay + # load_restrictor must be set to none so we can load patch files from the default overlay + command: '{{ kustomize }} build --load_restrictor none .' + args: + chdir: '{{ config_dir }}' + register: resources + changed_when: false + +- name: Set resources to {{ state }} + k8s: + definition: '{{ item }}' + state: '{{ state }}' + wait: yes + loop: '{{ resources.stdout | from_yaml_all | list }}' diff --git a/molecule/default/molecule.yml b/molecule/default/molecule.yml new file mode 100644 index 0000000..555207c --- /dev/null +++ b/molecule/default/molecule.yml @@ -0,0 +1,38 @@ +--- +dependency: + name: galaxy +driver: + name: delegated +lint: | + set -e + yamllint -d "{extends: relaxed, rules: {line-length: {max: 120}}}" . +platforms: + - name: cluster + groups: + - k8s +provisioner: + name: ansible + lint: | + set -e + ansible-lint + inventory: + group_vars: + all: + namespace: ${TEST_OPERATOR_NAMESPACE:-osdk-test} + host_vars: + localhost: + ansible_python_interpreter: '{{ ansible_playbook_python }}' + config_dir: ${MOLECULE_PROJECT_DIRECTORY}/config/testing + samples_dir: ${MOLECULE_PROJECT_DIRECTORY}/config/samples + operator_image: ${OPERATOR_IMAGE:-"gcr.io/takeoff-204116/pg-db-user-manager"} + operator_image_tag: ${OPERATOR_IMAGE_TAG:-"moleculetest"} + operator_pull_policy: ${OPERATOR_PULL_POLICY:-"Always"} + kustomize: ${KUSTOMIZE_PATH:-kustomize} + project_dir: ${MOLECULE_PROJECT_DIRECTORY} + env: + K8S_AUTH_KUBECONFIG: ${KUBECONFIG:-"~/.kube/config"} +verifier: + name: ansible + lint: | + set -e + ansible-lint diff --git a/molecule/default/prepare.yml b/molecule/default/prepare.yml new file mode 100644 index 0000000..315eced --- /dev/null +++ b/molecule/default/prepare.yml @@ -0,0 +1,28 @@ +--- +- name: Prepare + hosts: localhost + connection: local + gather_facts: false + + tasks: + - name: Ensure operator image is set + fail: + msg: | + You must specify the OPERATOR_IMAGE environment variable in order to run the + 'default' scenario + when: not operator_image + + - name: Set testing image + command: '{{ kustomize }} edit set image testing={{ operator_image }}:{{ operator_image_tag }}' + args: + chdir: '{{ config_dir }}' + + - name: Set pull policy + command: '{{ kustomize }} edit add patch pull_policy/{{ operator_pull_policy }}.yaml' + args: + chdir: '{{ config_dir }}' + + - name: Set testing namespace + command: '{{ kustomize }} edit set namespace {{ namespace }}' + args: + chdir: '{{ config_dir }}' diff --git a/molecule/default/tasks/readonlydbuser_test.yml b/molecule/default/tasks/readonlydbuser_test.yml new file mode 100644 index 0000000..ae6e6bd --- /dev/null +++ b/molecule/default/tasks/readonlydbuser_test.yml @@ -0,0 +1,19 @@ +--- +- name: Create the pgsql.takeoff.io/v1alpha1.ReadOnlyDBUser + k8s: + state: present + namespace: '{{ namespace }}' + definition: "{{ lookup('template', '/'.join([samples_dir, cr_file])) | from_yaml }}" + wait: yes + wait_timeout: 300 + wait_condition: + type: Running + reason: Successful + status: "True" + vars: + cr_file: 'pgsql_v1alpha1_readonlydbuser.yaml' + +- name: Add assertions here + assert: + that: false + fail_msg: FIXME Add real assertions for your operator diff --git a/molecule/default/verify.yml b/molecule/default/verify.yml new file mode 100644 index 0000000..cc28aac --- /dev/null +++ b/molecule/default/verify.yml @@ -0,0 +1,57 @@ +--- +- name: Verify + hosts: localhost + connection: local + gather_facts: no + collections: + - community.kubernetes + + vars: + ctrl_label: control-plane=controller-manager + + tasks: + - block: + - name: Import all test files from tasks/ + include_tasks: '{{ item }}' + with_fileglob: + - tasks/*_test.yml + rescue: + - name: Retrieve relevant resources + k8s_info: + api_version: '{{ item.api_version }}' + kind: '{{ item.kind }}' + namespace: '{{ namespace }}' + loop: + - api_version: v1 + kind: Pod + - api_version: apps/v1 + kind: Deployment + - api_version: v1 + kind: Secret + - api_version: v1 + kind: ConfigMap + register: debug_resources + + - name: Retrieve Pod logs + k8s_log: + name: '{{ item.metadata.name }}' + namespace: '{{ namespace }}' + container: manager + loop: "{{ q('k8s', api_version='v1', kind='Pod', namespace=namespace, label_selector=ctrl_label) }}" + register: debug_logs + + - name: Output gathered resources + debug: + var: debug_resources + + - name: Output gathered logs + debug: + var: item.log_lines + loop: '{{ debug_logs.results }}' + + - name: Re-emit failure + vars: + failed_task: + result: '{{ ansible_failed_result }}' + fail: + msg: '{{ failed_task }}' diff --git a/molecule/kind/converge.yml b/molecule/kind/converge.yml new file mode 100644 index 0000000..a283398 --- /dev/null +++ b/molecule/kind/converge.yml @@ -0,0 +1,24 @@ +--- +- name: Converge + hosts: localhost + connection: local + gather_facts: no + + tasks: + - name: Build operator image + docker_image: + build: + path: '{{ project_dir }}' + pull: no + name: '{{ operator_image }}' + tag: '{{ operator_image_tag }}' + push: no + source: build + force_source: yes + + - name: Load image into kind cluster + command: kind load docker-image --name osdk-test '{{ operator_image }}' + register: result + changed_when: '"not yet present" in result.stdout' + +- import_playbook: ../default/converge.yml diff --git a/molecule/kind/create.yml b/molecule/kind/create.yml new file mode 100644 index 0000000..1b5b42d --- /dev/null +++ b/molecule/kind/create.yml @@ -0,0 +1,12 @@ +--- +- name: Create + hosts: localhost + connection: local + gather_facts: false + tasks: + - name: Create test kind cluster + command: kind create cluster --name osdk-test --kubeconfig {{ kubeconfig }} + + - name: show kubeconfig location + debug: + var: kubeconfig diff --git a/molecule/kind/destroy.yml b/molecule/kind/destroy.yml new file mode 100644 index 0000000..d0d7de2 --- /dev/null +++ b/molecule/kind/destroy.yml @@ -0,0 +1,16 @@ +--- +- name: Destroy + hosts: localhost + connection: local + gather_facts: false + collections: + - community.kubernetes + + tasks: + - name: Destroy test kind cluster + command: kind delete cluster --name osdk-test --kubeconfig {{ kubeconfig }} + + - name: Unset pull policy + command: '{{ kustomize }} edit remove patch pull_policy/{{ operator_pull_policy }}.yaml' + args: + chdir: '{{ config_dir }}' diff --git a/molecule/kind/molecule.yml b/molecule/kind/molecule.yml new file mode 100644 index 0000000..cb6c3c6 --- /dev/null +++ b/molecule/kind/molecule.yml @@ -0,0 +1,43 @@ +--- +dependency: + name: galaxy +driver: + name: delegated +lint: | + set -e + yamllint -d "{extends: relaxed, rules: {line-length: {max: 120}}}" . +platforms: + - name: cluster + groups: + - k8s +provisioner: + name: ansible + playbooks: + prepare: ../default/prepare.yml + verify: ../default/verify.yml + lint: | + set -e + ansible-lint + inventory: + group_vars: + all: + namespace: ${TEST_OPERATOR_NAMESPACE:-osdk-test} + host_vars: + localhost: + ansible_python_interpreter: '{{ ansible_playbook_python }}' + config_dir: ${MOLECULE_PROJECT_DIRECTORY}/config/testing-local + samples_dir: ${MOLECULE_PROJECT_DIRECTORY}/config/samples + project_dir: ${MOLECULE_PROJECT_DIRECTORY} + operator_image: testing-operator + operator_image_tag: latest + operator_pull_policy: "Never" + kubeconfig: "{{ lookup('env', 'KUBECONFIG') }}" + kustomize: ${KUSTOMIZE_PATH:-kustomize} + env: + K8S_AUTH_KUBECONFIG: ${MOLECULE_EPHEMERAL_DIRECTORY}/kubeconfig + KUBECONFIG: ${MOLECULE_EPHEMERAL_DIRECTORY}/kubeconfig +verifier: + name: ansible + lint: | + set -e + ansible-lint diff --git a/playbooks/.placeholder b/playbooks/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..cbf1804 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,6 @@ +ansible +molecule[docker] +google-auth +requests +psycopg2 +openshift diff --git a/requirements.yml b/requirements.yml new file mode 100644 index 0000000..1a8c254 --- /dev/null +++ b/requirements.yml @@ -0,0 +1,7 @@ +--- +collections: + - name: community.kubernetes + version: ">=1.0.0" + - name: community.general + version: ">=1.0.0" + - operator_sdk.util diff --git a/roles/.placeholder b/roles/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/roles/readonlydbuser/README.md b/roles/readonlydbuser/README.md new file mode 100644 index 0000000..c37ca91 --- /dev/null +++ b/roles/readonlydbuser/README.md @@ -0,0 +1,43 @@ +Role Name +========= + +A brief description of the role goes here. + +Requirements +------------ + +Any pre-requisites that may not be covered by Ansible itself or the role should be mentioned here. For instance, +if the role uses the EC2 module, it may be a good idea to mention in this section that the boto package is required. + +Role Variables +-------------- + +A description of the settable variables for this role should go here, including any variables that are in +defaults/main.yml, vars/main.yml, and any variables that can/should be set via parameters to the role. Any variables +that are read from other roles and/or the global scope (ie. hostvars, group vars, etc.) should be mentioned here as well + +Dependencies +------------ + +A list of other roles hosted on Galaxy should go here, plus any details in regards to parameters that may need to be set +for other roles, or variables that are used from other roles. + +Example Playbook +---------------- + +Including an example of how to use your role (for instance, with variables passed in as parameters) is always nice for +users too: + + - hosts: servers + roles: + - { role: username.rolename, x: 42 } + +License +------- + +BSD + +Author Information +------------------ + +An optional section for the role authors to include contact information, or a website (HTML is not allowed). diff --git a/roles/readonlydbuser/defaults/main.yml b/roles/readonlydbuser/defaults/main.yml new file mode 100644 index 0000000..f83e4e5 --- /dev/null +++ b/roles/readonlydbuser/defaults/main.yml @@ -0,0 +1,20 @@ +--- +# defaults file for ReadOnlyDBUser + +required_vars: + - db_name + - password + - pghost + - pguser + - pgpass + +# database name to connect to to create the readonly user +#db_name: "" + +# password for the user +#password: "" + +# postgresql connection +#pghost: "" +pguser: "postgres" +#pgpass: "" diff --git a/roles/readonlydbuser/files/.placeholder b/roles/readonlydbuser/files/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/roles/readonlydbuser/handlers/main.yml b/roles/readonlydbuser/handlers/main.yml new file mode 100644 index 0000000..37b1150 --- /dev/null +++ b/roles/readonlydbuser/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for ReadOnlyDBUser diff --git a/roles/readonlydbuser/meta/main.yml b/roles/readonlydbuser/meta/main.yml new file mode 100644 index 0000000..be34ca4 --- /dev/null +++ b/roles/readonlydbuser/meta/main.yml @@ -0,0 +1,64 @@ +--- +galaxy_info: + author: your name + description: your description + company: your company (optional) + + # If the issue tracker for your role is not on github, uncomment the + # next line and provide a value + # issue_tracker_url: http://example.com/issue/tracker + + # Some suggested licenses: + # - BSD (default) + # - MIT + # - GPLv2 + # - GPLv3 + # - Apache + # - CC-BY + license: license (GPLv2, CC-BY, etc) + + min_ansible_version: 2.9 + + # If this a Container Enabled role, provide the minimum Ansible Container version. + # min_ansible_container_version: + + # Optionally specify the branch Galaxy will use when accessing the GitHub + # repo for this role. During role install, if no tags are available, + # Galaxy will use this branch. During import Galaxy will access files on + # this branch. If Travis integration is configured, only notifications for this + # branch will be accepted. Otherwise, in all cases, the repo's default branch + # (usually master) will be used. + #github_branch: + + # + # Provide a list of supported platforms, and for each platform a list of versions. + # If you don't wish to enumerate all versions for a particular platform, use 'all'. + # To view available platforms and versions (or releases), visit: + # https://galaxy.ansible.com/api/v1/platforms/ + # + # platforms: + # - name: Fedora + # versions: + # - all + # - 25 + # - name: SomePlatform + # versions: + # - all + # - 1.0 + # - 7 + # - 99.99 + + galaxy_tags: [] + # List tags for your role here, one per line. A tag is a keyword that describes + # and categorizes the role. Users find roles by searching for tags. Be sure to + # remove the '[]' above, if you add tags to this list. + # + # NOTE: A tag is limited to a single word comprised of alphanumeric characters. + # Maximum 20 tags per role. + +dependencies: [] + # List your role dependencies here, one per line. Be sure to remove the '[]' above, + # if you add dependencies to this list. +collections: +- operator_sdk.util +- community.kubernetes diff --git a/roles/readonlydbuser/tasks/main.yml b/roles/readonlydbuser/tasks/main.yml new file mode 100644 index 0000000..05fce6b --- /dev/null +++ b/roles/readonlydbuser/tasks/main.yml @@ -0,0 +1,68 @@ +--- +# tasks file for ReadOnlyDBUser + +- name: "Check required variables" + fail: + msg: "Variable '{{ item }}' is not defined" + when: item not in vars + with_items: "{{required_vars}}" + +# password.valueFrom +- name: Get password secret + community.kubernetes.k8s_info: + kind: Secret + namespace: "{{ ansible_operator_meta.namespace }}" + name: "{{ password.value_from.secret_key_ref.name}}" + register: password_secret + when: password.valueFrom is defined + +- name: Set db_user_password fact + set_fact: + db_user_password: "{{ (password_secret.resources[0].data.[password.value_from.secret_key_ref.key]|b64decode) | default(password.value) }}" + +- name: Fetch password from secret + set_fact: + password: "{{ lookup('community.kubernetes.k8s', kind='Secret', namespace=ansible_operator_meta.namespace resource_name={{password.valueFrom.secretKeyRef.name}}) }}" + +# - name: create user +# community.general.postgresql_user: +# db: postgres +# name: '{{ ansible_operator_meta.name }}' +# password: '{{password}}' +# login_host: '{{pghost}}' +# login_user: '{{pguser}}' +# login_password: '{{pgpass}}' + +# - name: GRANT USAGE ON SCHEMA public TO {{ ansible_operator_meta.name }} +# community.general.postgresql_privs: +# db: '{{db_name}}' +# priv: USAGE +# type: schema +# obj: public +# role: '{{ ansible_operator_meta.name }}' +# login_host: '{{pghost}}' +# login_user: '{{pguser}}' +# login_password: '{{pgpass}}' + +# - name: GRANT SELECT ON ALL TABLES IN SCHEMA public TO {{ ansible_operator_meta.name }} +# community.general.postgresql_privs: +# db: '{{db_name}}' +# priv: SELECT +# obj: ALL_IN_SCHEMA +# role: '{{ ansible_operator_meta.name }}' +# schema: public +# login_host: '{{pghost}}' +# login_user: '{{pguser}}' +# login_password: '{{pgpass}}' + +# - name: ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO {{ ansible_operator_meta.name }} +# community.general.postgresql_privs: +# db: '{{db_name}}' +# type: default_privs +# schema: public +# objs: TABLES +# privs: SELECT +# role: '{{ ansible_operator_meta.name }}' +# login_host: '{{pghost}}' +# login_user: '{{pguser}}' +# login_password: '{{pgpass}}' \ No newline at end of file diff --git a/roles/readonlydbuser/templates/.placeholder b/roles/readonlydbuser/templates/.placeholder new file mode 100644 index 0000000..e69de29 diff --git a/roles/readonlydbuser/vars/main.yml b/roles/readonlydbuser/vars/main.yml new file mode 100644 index 0000000..6757cfc --- /dev/null +++ b/roles/readonlydbuser/vars/main.yml @@ -0,0 +1,2 @@ +--- +# vars file for ReadOnlyDBUser diff --git a/watches.yaml b/watches.yaml new file mode 100644 index 0000000..56fb65d --- /dev/null +++ b/watches.yaml @@ -0,0 +1,7 @@ +--- +# Use the 'create api' subcommand to add watches to this file. +- version: v1alpha1 + group: pgsql.takeoff.io + kind: ReadOnlyDBUser + role: readonlydbuser +# +kubebuilder:scaffold:watch