diff --git a/.gitignore b/.gitignore index 0711d342..98fbc1c4 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,9 @@ testbin/* onpremtest/* ords/*zip .gitattributes -.vscode \ No newline at end of file +.vscode +.gitlab-ci.yml + +# development +.idea +.local diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index d5080ff9..00000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,31 +0,0 @@ -build-operator: - stage: build - variables: - IMAGE: "$DOCKER_REPO:$CI_COMMIT_BRANCH" - OP_YAML: oracle-database-operator.yaml - script: - - go version - - echo $CI_COMMIT_SHORT_SHA - - make docker-build IMG="$IMAGE" - - docker push "$IMAGE" - - newimage=$DOCKER_REPO@$(skopeo inspect docker://$IMAGE | jq -r .Digest) - - echo $newimage - - docker rmi "$IMAGE" && docker system prune -f - - make operator-yaml IMG=$newimage - - if [ "$CI_COMMIT_BRANCH" != "master" ]; then sed -i "s/\(replicas.\) 3/\1 1/g" ./$OP_YAML; fi - - curl -s --netrc-file $HOME/.netrc_gitlab $ARTIFACTORY_REPO/$CI_COMMIT_BRANCH/$OP_YAML -T ./$OP_YAML - only: - variables: - - $CI_COMMIT_MESSAGE =~ /\#run-pipeline/ - - $CI_COMMIT_BRANCH =~ /master/ - - $CI_MERGE_REQUEST_ID != "" - except: - variables: - - $CI_COMMIT_MESSAGE =~ /\#skip-pipeline/ - - $CI_COMMIT_TAG != null - -cleanup: - stage: .post - script: - - echo "Clean up downloaded binaries" - - rm -rf bin/ diff --git a/Dockerfile b/Dockerfile index 3c249825..11a56962 100644 --- a/Dockerfile +++ b/Dockerfile @@ -3,7 +3,18 @@ # # Build the manager binary -FROM golang:1.19 as builder +ARG BUILDER_IMG +FROM ${BUILDER_IMG} as builder + +# Download golang if BUILD_INTERNAL is set to true +ARG INSTALL_GO +ARG GOLANG_VERSION +RUN if [ "$INSTALL_GO" = "true" ]; then \ + curl -LJO https://go.dev/dl/go${GOLANG_VERSION}.linux-amd64.tar.gz &&\ + rm -rf /usr/local/go && tar -C /usr/local -xzf go${GOLANG_VERSION}.linux-amd64.tar.gz &&\ + rm go${GOLANG_VERSION}.linux-amd64.tar.gz; \ + fi +ENV PATH=${GOLANG_VERSION:+"${PATH}:/usr/local/go/bin"} WORKDIR /workspace # Copy the Go Modules manifests diff --git a/Makefile b/Makefile index e904262b..88e14843 100644 --- a/Makefile +++ b/Makefile @@ -61,7 +61,7 @@ test: manifests generate fmt vet envtest ## Run unit tests. E2ETEST ?= ./test/e2e/ e2e: manifests generate fmt vet envtest ## Run e2e tests. - KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" ginkgo -v --timeout=2h30m --fail-fast $(E2ETEST) + KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test $(E2ETEST) -test.timeout 0 -test.v --ginkgo.fail-fast ##@ Build @@ -71,12 +71,23 @@ build: generate fmt vet ## Build manager binary. run: manifests generate fmt vet ## Run a controller from your host. go run ./main.go -docker-build: manifests generate fmt vet #test ## Build docker image with the manager. Disable the test but keep the validations to fail fast - docker build --no-cache=true --build-arg http_proxy=${HTTP_PROXY} --build-arg https_proxy=${HTTPS_PROXY} \ - --build-arg CI_COMMIT_SHA=${CI_COMMIT_SHA} --build-arg CI_COMMIT_BRANCH=${CI_COMMIT_BRANCH} . -t ${IMG} +GOLANG_VERSION ?= 1.21.7 +## Download golang in the Dockerfile if BUILD_INTERNAL is set to true. +## Otherwise, use golang image from docker hub as the builder. +ifeq ($(BUILD_INTERNAL), true) +BUILDER_IMG = oraclelinux:8 +BUILD_ARGS = --build-arg BUILDER_IMG=$(BUILDER_IMG) --build-arg GOLANG_VERSION=$(GOLANG_VERSION) --build-arg INSTALL_GO=true +else +BUILDER_IMG = golang:$(GOLANG_VERSION) +BUILD_ARGS = --build-arg BUILDER_IMG=$(BUILDER_IMG) --build-arg INSTALL_GO=false +endif +docker-build: #manifests generate fmt vet #test ## Build docker image with the manager. Disable the test but keep the validations to fail fast + docker build --no-cache=true --build-arg http_proxy=$(HTTP_PROXY) --build-arg https_proxy=$(HTTPS_PROXY) \ + --build-arg CI_COMMIT_SHA=$(CI_COMMIT_SHA) --build-arg CI_COMMIT_BRANCH=$(CI_COMMIT_BRANCH) \ + $(BUILD_ARGS) . -t $(IMG) docker-push: ## Push docker image with the manager. - docker push ${IMG} + docker push $(IMG) ##@ Deployment @@ -87,17 +98,17 @@ uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified $(KUSTOMIZE) build config/crd | kubectl delete -f - deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config. - cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} + cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) $(KUSTOMIZE) build config/default | kubectl apply -f - # Bug:34265574 # Used sed to reposition the controller-manager Deployment after the certificate creation in the OPERATOR_YAML operator-yaml: manifests kustomize - cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} - $(KUSTOMIZE) build config/default > "${OPERATOR_YAML}" - sed -i.bak -e '/^apiVersion: apps\/v1/,/---/d' "${OPERATOR_YAML}" - (echo --- && sed '/^apiVersion: apps\/v1/,/---/!d' "${OPERATOR_YAML}.bak") >> "${OPERATOR_YAML}" - rm "${OPERATOR_YAML}.bak" + cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) + $(KUSTOMIZE) build config/default > "$(OPERATOR_YAML)" + sed -i.bak -e '/^apiVersion: apps\/v1/,/---/d' "$(OPERATOR_YAML)" + (echo --- && sed '/^apiVersion: apps\/v1/,/---/!d' "$(OPERATOR_YAML).bak") >> "$(OPERATOR_YAML)" + rm "$(OPERATOR_YAML).bak" undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. $(KUSTOMIZE) build config/default | kubectl delete -f - diff --git a/PROJECT b/PROJECT index c402ecfd..fbf861db 100644 --- a/PROJECT +++ b/PROJECT @@ -1,3 +1,7 @@ +# Code generated by tool. DO NOT EDIT. +# This file is used to track the info used to scaffold your project +# and allow the plugins properly work. +# More info: https://book.kubebuilder.io/reference/project-config.html domain: oracle.com layout: - go.kubebuilder.io/v2 @@ -67,6 +71,10 @@ resources: kind: ShardingDatabase path: github.com/oracle/oracle-database-operator/apis/database/v1alpha1 version: v1alpha1 + webhooks: + defaulting: true + validation: true + webhookVersion: v1beta1 - api: crdVersion: v1 namespaced: true @@ -136,4 +144,17 @@ resources: defaulting: true validation: true webhookVersion: v1beta1 +- api: + crdVersion: v1beta1 + namespaced: true + controller: true + domain: oracle.com + group: observability + kind: DatabaseObserver + path: github.com/oracle/oracle-database-operator/apis/observability/v1alpha1 + version: v1alpha1 + webhooks: + defaulting: true + validation: true + webhookVersion: v1beta1 version: "3" diff --git a/README.md b/README.md index 66cd62ec..cad25dec 100644 --- a/README.md +++ b/README.md @@ -4,33 +4,51 @@ As part of Oracle's resolution to make Oracle Database Kubernetes native (that is, observable and operable by Kubernetes), Oracle released _Oracle Database Operator for Kubernetes_ (`OraOperator` or the operator). OraOperator extends the Kubernetes API with custom resources and controllers for automating Oracle Database lifecycle management. -In this v1.0.0 production release, `OraOperator` supports the following database configurations and infrastructure: +In this v1.1.0 production release, `OraOperator` supports the following database configurations and infrastructure: * Oracle Autonomous Database: * Oracle Autonomous Database shared Oracle Cloud Infrastructure (OCI) (ADB-S) * Oracle Autonomous Database on dedicated Cloud infrastructure (ADB-D) - * Oracle Autonomous Container Database (ACD) (infrastructure) the infrastructure for provisionning Autonomous Databases. + * Oracle Autonomous Container Database (ACD) (infrastructure) is the infrastructure for provisioning Autonomous Databases. * Containerized Single Instance databases (SIDB) deployed in the Oracle Kubernetes Engine (OKE) and any k8s where OraOperator is deployed * Containerized Sharded databases (SHARDED) deployed in OKE and any k8s where OraOperator is deployed * Oracle Multitenant Databases (CDB/PDBs) * Oracle Base Database Cloud Service (BDBCS) * Oracle Data Guard (Preview status) +* Oracle Database Observability (Preview status) Oracle will continue to extend `OraOperator` to support additional Oracle Database configurations. +## New in V1.1.0 Release +* Namespace scope deployment option +* Enhanced security with namespace scope deployment option +* Support for Oracle Database 23ai Free (with SIDB) +* Automatic Storage Expansion for SIDB and Sharded DB +* User-Defined Sharding +* TCPS support customer provided certs +* Execute custom scripts during DB setup/startup +* Patching for SIDB Primary/Standby in Data Guard +* Long-term backup for Autonomous Databases (ADB): Support for [long-term retention backup](https://docs.oracle.com/en/cloud/paas/autonomous-database/serverless/adbsb/backup-long-term.html) and removed support for the deprecated mandatory backup +* Wallet expiry date for ADB: A user-friendly enhancement to display the wallet expiry date in the status of the associated ADB +* Wait-for-Completion option for ADB: Supports `kubectl wait` command that allows the user to wait for a specific condition on ADB +* OKE workload Identify: Supports OKE workload identity authentication method (i.e., uses OKE credentials). For more details, refer to [Oracle Autonomous Database (ADB) Prerequisites](docs/adb/ADB_PREREQUISITES.md#authorized-with-oke-workload-identity) +* Database Observability (Preview - Metrics) + ## Features Summary This release of Oracle Database Operator for Kubernetes (the operator) supports the following lifecycle operations: -* ADB-S/ADB-D: Provision, Bind, Start, Stop, terminate (soft/hard), scale (up/down), Manual Backup, Manual Restore +* ADB-S/ADB-D: Provision, bind, start, stop, terminate (soft/hard), scale (up/down), long-term backup, manual restore * ACD: provision, bind, restart, terminate (soft/hard) * SIDB: Provision, clone, patch (in-place/out-of-place), update database initialization parameters, update database configuration (Flashback, archiving), Oracle Enterprise Manager (EM) Express (a basic observability console), Oracle REST Data Service (ORDS) to support REST based SQL, PDB management, SQL Developer Web, and Application Express (Apex) * SHARDED: Provision/deploy sharded databases and the shard topology, Add a new shard, Delete an existing shard * Oracle Multitenant Database: Bind to a CDB, Create a  PDB, Plug a  PDB, Unplug a PDB, Delete a PDB, Clone a PDB, Open/Close a PDB * Oracle Base Database Cloud Service (BDBCS): provision, bind, scale shape Up/Down, Scale Storage Up, Terminate and Update License * Oracle Data Guard: Provision a Standby for the SIDB resource, Create a Data Guard Configuration, Perform a Switchover, Patch Primary and Standby databases in Data Guard Configuration +* Oracle Database Observability: create, patch, delete databaseObserver resources +* Watch over a set of namespaces or all the namespaces in the cluster using the "WATCH_NAMESPACE" env variable of the operator deployment -The upcoming releases will support new configurations, operations and capabilities. +The upcoming releases will support new configurations, operations, and capabilities. ## Release Status @@ -55,19 +73,70 @@ Oracle strongly recommends that you ensure your system meets the following [Prer Install the certificate manager with the following command: ```sh - kubectl apply -f https://github.com/jetstack/cert-manager/releases/latest/download/cert-manager.yaml + kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.14.4/cert-manager.yaml ``` -## Quick Install of the Operator +* ### Create Role Bindings for Access Management + + OraOperator supports the following two modes of deployment: + ##### 1. Cluster Scoped Deployment + + This is the default mode, in which OraOperator is deployed to operate in a cluster, and to monitor all the namespaces in the cluster. + + - Grant the `serviceaccount:oracle-database-operator-system:default` cluster wide access for the resources by applying [cluster-role-binding.yaml](./rbac/cluster-role-binding.yaml) + + ```sh + kubectl apply -f rbac/cluster-role-binding.yaml + ``` + + - Next, apply the [oracle-database-operator.yaml](./oracle-database-operator.yaml) to deploy the Operator + + ```sh + kubectl apply -f oracle-database-operator.yaml + ``` + + ##### 2. Namespace Scoped Deployment - To install the operator in the cluster quickly, you can use a single [oracle-database-operator.yaml](https://github.com/oracle/oracle-database-operator/blob/main/oracle-database-operator.yaml) file. + In this mode, OraOperator can be deployed to operate in a namespace, and to monitor one or many namespaces. - Run the following command + - Grant `serviceaccount:oracle-database-operator-system:default` service account with resource access in the required namespaces. For example, to monitor only the default namespace, apply the [default-ns-role-binding.yaml](./rbac/default-ns-role-binding.yaml) + + ```sh + kubectl apply -f rbac/default-ns-role-binding.yaml + ``` + To watch additional namespaces, create different role binding files for each namespace, using [default-ns-role-binding.yaml](./rbac/default-ns-role-binding.yaml) as a template, and changing the `metadata.name` and `metadata.namespace` fields + + - Next, edit the [oracle-database-operator.yaml](./oracle-database-operator.yaml) to add the required namespaces under `WATCH_NAMESPACE`. Use comma-delimited values for multiple namespaces. + + ```sh + - name: WATCH_NAMESPACE + value: "default" + ``` + - Finally, apply the edited [oracle-database-operator.yaml](./oracle-database-operator.yaml) to deploy the Operator + + ```sh + kubectl apply -f oracle-database-operator.yaml + ``` + + +* ### ClusterRole and ClusterRoleBinding for NodePort services + + To expose services on each node's IP and port (the NodePort) apply the [node-rbac.yaml](./rbac/node-rbac.yaml). Note that this step is not required for LoadBalancer services. ```sh - kubectl apply -f https://raw.githubusercontent.com/oracle/oracle-database-operator/main/oracle-database-operator.yaml + kubectl apply -f rbac/node-rbac.yaml ``` +## Install Oracle DB Operator + + After you have completed the preceding prerequisite changes, you can install the operator. To install the operator in the cluster quickly, you can apply the modified `oracle-database-operator.yaml` file from the preceding step. + + Run the following command + + ```sh + kubectl apply -f oracle-database-operator.yaml + ``` + Ensure that the operator pods are up and running. For high availability, Operator pod replicas are set to a default of 3. You can scale this setting up or down. ```sh @@ -88,7 +157,7 @@ For more details, see [Oracle Database Operator Installation Instructions](./doc ## Getting Started with the Operator (Quickstart) -The quickstarts are designed for specific database configurations: +The following quickstarts are designed for specific database configurations: * [Oracle Autonomous Database](./docs/adb/README.md) * [Oracle Autonomous Container Database](./docs/adb/ACD.md) @@ -97,13 +166,17 @@ The quickstarts are designed for specific database configurations: * [Oracle Multitenant Database](./docs/multitenant/README.md) * [Oracle Base Database Cloud Service (BDBCS)](./docs/dbcs/README.md) + +The following quickstart is designed for non-database configurations: +* [Oracle Database Observability](./docs/observability/README.md) + YAML file templates are available under [`/config/samples`](./config/samples/). You can copy and edit these template files to configure them for your use cases. ## Uninstall the Operator To uninstall the operator, the final step consists of deciding whether you want to delete the custom resource definitions (CRDs) and Kubernetes APIServices introduced into the cluster by the operator. Choose one of the following options: -* ### Deleting the CRDs and APIServices +* ### Delete the CRDs and APIServices To delete all the CRD instances deployed to cluster by the operator, run the following commands, where is the namespace of the cluster object: @@ -119,8 +192,17 @@ YAML file templates are available under [`/config/samples`](./config/samples/). kubectl delete cdb.database.oracle.com --all -n kubectl delete pdb.database.oracle.com --all -n kubectl delete dataguardbrokers.database.oracle.com --all -n + kubectl delete databaseobserver.observability.oracle.com --all -n + ``` + +* ### Delete the RBACs + + ```sh + cat rbac/* | kubectl delete -f - ``` +* ### Delete the Deployment + After all CRD instances are deleted, it is safe to remove the CRDs, APIServices and operator deployment. To remove these files, use the following command: ```sh @@ -129,7 +211,7 @@ YAML file templates are available under [`/config/samples`](./config/samples/). Note: If the CRD instances are not deleted, and the operator is deleted by using the preceding command, then operator deployment and instance objects (pods, services, PVCs, and so on) are deleted. However, if that happens, then the CRD deletion stops responding. This is because the CRD instances have properties that prevent their deletion, and that can only be removed by the operator pod, which is deleted when the APIServices are deleted. -## Docs of the supported Oracle Database configurations +## Documentation for the supported Oracle Database configurations * [Oracle Autonomous Database](https://docs.oracle.com/en-us/iaas/Content/Database/Concepts/adboverview.htm) * [Components of Dedicated Autonomous Database](https://docs.oracle.com/en-us/iaas/autonomous-database/doc/components.html) @@ -143,7 +225,7 @@ See [Contributing to this Repository](./CONTRIBUTING.md) ## Support -You can submit a GitHub issue, and/or you file an [Oracle Support service](https://support.oracle.com/portal/) request, using this product ID: 14430. +You can submit a GitHub issue, oir submit an issue and then file an [Oracle Support service](https://support.oracle.com/portal/) request. To file an issue or a service request, use the following product ID: 14430. ## Security @@ -168,5 +250,5 @@ See [Reporting security vulnerabilities](./SECURITY.md) ## License -Copyright (c) 2022, 2023 Oracle and/or its affiliates. +Copyright (c) 2022, 2024 Oracle and/or its affiliates. Released under the Universal Permissive License v1.0 as shown at [https://oss.oracle.com/licenses/upl/](https://oss.oracle.com/licenses/upl/) diff --git a/THIRD_PARTY_LICENSES.txt b/THIRD_PARTY_LICENSES.txt index 74a065b6..d75f3946 100644 --- a/THIRD_PARTY_LICENSES.txt +++ b/THIRD_PARTY_LICENSES.txt @@ -1,5 +1,5 @@ ------------------------------------- -Operator SDK 1.26.1 +Operator SDK 1.32.0 https://github.com/operator-framework/operator-sdk Apache 2.0 @@ -208,7 +208,7 @@ Apache License: limitations under the License. ------------------------------ - GO lang + GO lang 1.21.4 https://github.com/golang @@ -241,18 +241,18 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------- -apimachinery 0.27.2 +apimachinery 0.28.4 https://github.com/kubernetes/apimachinery/tr Apache 2.0 ------------------------- -controller-runtime 0.15.0 -https://github.com/kubernetes-sigs/controller-runtime/tree/v0.14.6 +controller-runtime 0.16.3 +https://github.com/kubernetes-sigs/controller-runtime/releases/tag/v0.16.3 Apache 2.0 ------------------------- -golang 1.20.2 -https://github.com/golang/go/archive/refs/tags/go1.20.2.zip +golang 1.21.4 +https://github.com/golang/go/releases/tag/go1.21.4 BSD 2-clause or 3-clause @@ -1008,14 +1008,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. limitations under the License. -------------------------- -Logr +Logr 1.3.0 https://pkg.go.dev/github.com/go-logr/logr -https://github.com/go-logr/logr/tree/v1.2.4 +https://github.com/go-logr/logr/tree/v1.3.0 Apache 2.0 License ------------------------- -OCI Go SDK -github.com/oracle/oci-go-sdk/v43 +OCI Go SDK 65.53.0 +https://github.com/oracle/oci-go-sdk/releases/tag/v65.53.0 Dual-License: UPL + Apache 2.0 @@ -1065,8 +1065,8 @@ The Universal Permissive License (UPL), Version 1.0 ------------------------- -ginkgo 2.9.7 -https://github.com/onsi/ginkgo/tree/v2.9.7 +ginkgo 2.13.1 +https://github.com/onsi/ginkgo/releases/tag/v2.13.1 MIT ------------------------------------ Gomega @@ -1075,37 +1075,37 @@ MIT License Copyright (c) 2013-2014 Onsi Fakhouri ---------------------------- -gomega 1.27.7 +gomega 1.30.0 http://onsi.github.io/gomega/ MIT ------------------------- -Kubernetes api +Kubernetes api 0.28.4 https://pkg.go.dev/k8s.io/api Apache 2.0 ---------------------------------- -Kubernetes apimachinery +Kubernetes apimachinery 0.28.4 https://pkg.go.dev/k8s.io/apimachinery Apache 2.0 ----------------------------------- -Kubernetes client-go +Kubernetes client-go 0.28.4 https://pkg.go.dev/k8s.io/client-go Apache 2.0 ------------------------------------- -Kubernetes controller-runtime project +Kubernetes controller-runtime project 0.16.3 https://pkg.go.dev/sigs.k8s.io/controller-runtime Apache 2.0 ------------------------------------ -kubernetes-sigs/yaml 1.3.0 +kubernetes-sigs/yaml 1.4.0 https://github.com/kubernetes-sigs/yaml/tree/v1.3.0 MIT ------------------------- -OCI SDK for Go 65.37.1 +OCI SDK for Go 65.53.0 https://github.com/oracle/oci-go-sdk Multiple Licenses: Apache 2.0, UPL @@ -1135,8 +1135,8 @@ https://pkg.go.dev/sigs.k8s.io/yaml Dual license: BSD-3-Clause, MIT ------------------------------------ -zap 1.24.0 -https://github.com/uber-go/zap/tree/v1.24.0 +zap 1.26.0 +https://github.com/uber-go/zap/releases/tag/v1.26.0 MIT ------------------------------------ @@ -1192,7 +1192,7 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------ -Ginkgo +Ginkgo 2.13.1 github.com/onsi/ginkgo MIT License Copyright (c) 2013-2014 Onsi Fakhouri diff --git a/apis/database/v1alpha1/adbfamily_common_utils.go b/apis/database/v1alpha1/adbfamily_common_utils.go index e6691a12..d4d3ae9f 100644 --- a/apis/database/v1alpha1/adbfamily_common_utils.go +++ b/apis/database/v1alpha1/adbfamily_common_utils.go @@ -173,9 +173,9 @@ func traverse(lastSpec interface{}, curSpec interface{}) bool { return changed } -// 1. If the current field is with a zero value, then the field is unchanged. -// 2. If the current field is NOT with a zero value, then we want to comapre it with the last field. -// In this case if the last field is with a zero value, then the field is changed +// 1. If the current field is with a zero value, then the field is unchanged. +// 2. If the current field is NOT with a zero value, then we want to comapre it with the last field. +// In this case if the last field is with a zero value, then the field is changed func hasChanged(lastField reflect.Value, curField reflect.Value) bool { zero := reflect.Zero(lastField.Type()).Interface() lastFieldIsZero := reflect.DeepEqual(lastField.Interface(), zero) diff --git a/apis/database/v1alpha1/autonomouscontainerdatabase_webhook.go b/apis/database/v1alpha1/autonomouscontainerdatabase_webhook.go index 3e9f5e1f..37e1d819 100644 --- a/apis/database/v1alpha1/autonomouscontainerdatabase_webhook.go +++ b/apis/database/v1alpha1/autonomouscontainerdatabase_webhook.go @@ -46,6 +46,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) // log is for logging in this package. @@ -62,15 +63,15 @@ func (r *AutonomousContainerDatabase) SetupWebhookWithManager(mgr ctrl.Manager) var _ webhook.Validator = &AutonomousContainerDatabase{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (r *AutonomousContainerDatabase) ValidateCreate() error { +func (r *AutonomousContainerDatabase) ValidateCreate() (admission.Warnings, error) { autonomouscontainerdatabaselog.Info("validate create", "name", r.Name) // TODO(user): fill in your validation logic upon object creation. - return nil + return nil, nil } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (r *AutonomousContainerDatabase) ValidateUpdate(old runtime.Object) error { +func (r *AutonomousContainerDatabase) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { var allErrs field.ErrorList var oldACD *AutonomousContainerDatabase = old.(*AutonomousContainerDatabase) @@ -78,7 +79,7 @@ func (r *AutonomousContainerDatabase) ValidateUpdate(old runtime.Object) error { // skip the update of adding ADB OCID or binding if oldACD.Status.LifecycleState == "" { - return nil + return nil, nil } // cannot update when the old state is in intermediate state, except for the terminate operatrion @@ -95,17 +96,17 @@ func (r *AutonomousContainerDatabase) ValidateUpdate(old runtime.Object) error { } if len(allErrs) == 0 { - return nil + return nil, nil } - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( schema.GroupKind{Group: "database.oracle.com", Kind: "AutonomousContainerDatabase"}, r.Name, allErrs) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type -func (r *AutonomousContainerDatabase) ValidateDelete() error { +func (r *AutonomousContainerDatabase) ValidateDelete() (admission.Warnings, error) { autonomouscontainerdatabaselog.Info("validate delete", "name", r.Name) // TODO(user): fill in your validation logic upon object deletion. - return nil + return nil, nil } diff --git a/apis/database/v1alpha1/autonomousdatabase_types.go b/apis/database/v1alpha1/autonomousdatabase_types.go index 413c16de..cd23b3f3 100644 --- a/apis/database/v1alpha1/autonomousdatabase_types.go +++ b/apis/database/v1alpha1/autonomousdatabase_types.go @@ -43,14 +43,14 @@ import ( "reflect" "github.com/oracle/oci-go-sdk/v65/database" - metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. // name of our custom finalizer -const ADBFinalizer = "database.oracle.com/adb-finalizer" +const ADB_FINALIZER = "database.oracle.com/adb-finalizer" // AutonomousDatabaseSpec defines the desired state of AutonomousDatabase // Important: Run "make" to regenerate code after modifying this file @@ -159,7 +159,13 @@ type AutonomousDatabaseStatus struct { // Important: Run "make" to regenerate code after modifying this file LifecycleState database.AutonomousDatabaseLifecycleStateEnum `json:"lifecycleState,omitempty"` TimeCreated string `json:"timeCreated,omitempty"` + WalletExpiringDate string `json:"walletExpiringDate,omitempty"` AllConnectionStrings []ConnectionStringProfile `json:"allConnectionStrings,omitempty"` + // +patchMergeKey=type + // +patchStrategy=merge + // +listType=map + // +listMapKey=type + Conditions []metav1.Condition `json:"conditions,omitempty"` } type TLSAuthenticationEnum string @@ -192,8 +198,8 @@ type ConnectionStringSpec struct { // +kubebuilder:printcolumn:JSONPath=".spec.details.dbWorkload",name="Workload Type",type=string // +kubebuilder:printcolumn:JSONPath=".status.timeCreated",name="Created",type=string type AutonomousDatabase struct { - metaV1.TypeMeta `json:",inline"` - metaV1.ObjectMeta `json:"metadata,omitempty"` + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` Spec AutonomousDatabaseSpec `json:"spec,omitempty"` Status AutonomousDatabaseStatus `json:"status,omitempty"` @@ -203,8 +209,8 @@ type AutonomousDatabase struct { // AutonomousDatabaseList contains a list of AutonomousDatabase type AutonomousDatabaseList struct { - metaV1.TypeMeta `json:",inline"` - metaV1.ListMeta `json:"metadata,omitempty"` + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` Items []AutonomousDatabase `json:"items"` } @@ -329,7 +335,7 @@ func (adb *AutonomousDatabase) UpdateFromOCIADB(ociObj database.AutonomousDataba if *ociObj.IsDedicated { adb.Spec.Details.NetworkAccess.AccessType = NetworkAccessTypePrivate } else { - if ociObj.NsgIds != nil { + if ociObj.NsgIds != nil || ociObj.PrivateEndpoint != nil || ociObj.PrivateEndpointIp != nil || ociObj.PrivateEndpointLabel != nil { adb.Spec.Details.NetworkAccess.AccessType = NetworkAccessTypePrivate } else if ociObj.WhitelistedIps != nil { adb.Spec.Details.NetworkAccess.AccessType = NetworkAccessTypeRestricted diff --git a/apis/database/v1alpha1/autonomousdatabase_webhook.go b/apis/database/v1alpha1/autonomousdatabase_webhook.go index 9c01ad95..b25e8104 100644 --- a/apis/database/v1alpha1/autonomousdatabase_webhook.go +++ b/apis/database/v1alpha1/autonomousdatabase_webhook.go @@ -43,6 +43,7 @@ import ( "github.com/oracle/oci-go-sdk/v65/common" "github.com/oracle/oci-go-sdk/v65/database" + dbcommons "github.com/oracle/oracle-database-operator/commons/database" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -50,6 +51,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) // log is for logging in this package. @@ -97,12 +99,24 @@ var _ webhook.Validator = &AutonomousDatabase{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type // ValidateCreate checks if the spec is valid for a provisioning or a binding operation -func (r *AutonomousDatabase) ValidateCreate() error { - +func (r *AutonomousDatabase) ValidateCreate() (admission.Warnings, error) { var allErrs field.ErrorList autonomousdatabaselog.Info("validate create", "name", r.Name) + namespaces := dbcommons.GetWatchNamespaces() + _, hasEmptyString := namespaces[""] + isClusterScoped := len(namespaces) == 1 && hasEmptyString + if !isClusterScoped { + _, containsNamespace := namespaces[r.Namespace] + // Check if the allowed namespaces maps contains the required namespace + if len(namespaces) != 0 && !containsNamespace { + allErrs = append(allErrs, + field.Invalid(field.NewPath("metadata").Child("namespace"), r.Namespace, + "Oracle database operator doesn't watch over this namespace")) + } + } + if r.Spec.Details.AutonomousDatabaseOCID == nil { // provisioning operation allErrs = validateCommon(r, allErrs) allErrs = validateNetworkAccess(r, allErrs) @@ -115,15 +129,15 @@ func (r *AutonomousDatabase) ValidateCreate() error { } if len(allErrs) == 0 { - return nil + return nil, nil } - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( schema.GroupKind{Group: "database.oracle.com", Kind: "AutonomousDatabase"}, r.Name, allErrs) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (r *AutonomousDatabase) ValidateUpdate(old runtime.Object) error { +func (r *AutonomousDatabase) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { var allErrs field.ErrorList var oldADB *AutonomousDatabase = old.(*AutonomousDatabase) @@ -131,7 +145,7 @@ func (r *AutonomousDatabase) ValidateUpdate(old runtime.Object) error { // skip the update of adding ADB OCID or binding if oldADB.Status.LifecycleState == "" { - return nil + return nil, nil } // cannot update when the old state is in intermediate, except for the change to the hardLink or the terminate operatrion during valid lifecycleState @@ -164,7 +178,9 @@ func (r *AutonomousDatabase) ValidateUpdate(old runtime.Object) error { // cannot change lifecycleState with other fields together (except the oci config) var lifecycleChanged, otherFieldsChanged bool - lifecycleChanged = oldADB.Spec.Details.LifecycleState != "" && oldADB.Spec.Details.LifecycleState != r.Spec.Details.LifecycleState + lifecycleChanged = oldADB.Spec.Details.LifecycleState != "" && + r.Spec.Details.LifecycleState != "" && + oldADB.Spec.Details.LifecycleState != r.Spec.Details.LifecycleState var copiedADB *AutonomousDatabaseSpec = r.Spec.DeepCopy() copiedADB.Details.LifecycleState = oldADB.Spec.Details.LifecycleState copiedADB.OCIConfig = oldADB.Spec.OCIConfig @@ -185,9 +201,9 @@ func (r *AutonomousDatabase) ValidateUpdate(old runtime.Object) error { allErrs = validateNetworkAccess(r, allErrs) if len(allErrs) == 0 { - return nil + return nil, nil } - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( schema.GroupKind{Group: "database.oracle.com", Kind: "AutonomousDatabase"}, r.Name, allErrs) } @@ -224,12 +240,13 @@ func validateNetworkAccess(adb *AutonomousDatabase, allErrs field.ErrorList) fie field.Forbidden(field.NewPath("spec").Child("details").Child("networkAccess").Child("privateEndpoint").Child("subnetOCID"), fmt.Sprintf("subnetOCID cannot be empty when the network access type is %s", NetworkAccessTypePrivate))) } + } - if adb.Spec.Details.NetworkAccess.PrivateEndpoint.NsgOCIDs == nil { - allErrs = append(allErrs, - field.Forbidden(field.NewPath("spec").Child("details").Child("networkAccess").Child("privateEndpoint").Child("nsgOCIDs"), - fmt.Sprintf("nsgOCIDs cannot be empty when the network access type is %s", NetworkAccessTypePrivate))) - } + // NsgOCIDs only applies to PRIVATE accessType + if adb.Spec.Details.NetworkAccess.PrivateEndpoint.NsgOCIDs != nil && adb.Spec.Details.NetworkAccess.AccessType != NetworkAccessTypePrivate { + allErrs = append(allErrs, + field.Forbidden(field.NewPath("spec").Child("details").Child("networkAccess").Child("privateEndpoint").Child("nsgOCIDs"), + fmt.Sprintf("NsgOCIDs cannot only be applied when network access type is %s.", NetworkAccessTypePrivate))) } // IsAccessControlEnabled is not applicable to a shared database @@ -261,11 +278,11 @@ func validateNetworkAccess(adb *AutonomousDatabase, allErrs field.ErrorList) fie } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type -func (r *AutonomousDatabase) ValidateDelete() error { +func (r *AutonomousDatabase) ValidateDelete() (admission.Warnings, error) { autonomousdatabaselog.Info("validate delete", "name", r.Name) // TODO(user): fill in your validation logic upon object deletion. - return nil + return nil, nil } // Returns true if AutonomousContainerDatabaseOCID has value. diff --git a/apis/database/v1alpha1/autonomousdatabasebackup_types.go b/apis/database/v1alpha1/autonomousdatabasebackup_types.go index d64e549b..95c77560 100644 --- a/apis/database/v1alpha1/autonomousdatabasebackup_types.go +++ b/apis/database/v1alpha1/autonomousdatabasebackup_types.go @@ -52,11 +52,12 @@ import ( type AutonomousDatabaseBackupSpec struct { // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster // Important: Run "make" to regenerate code after modifying this file - Target TargetSpec `json:"target,omitempty"` - DisplayName *string `json:"displayName,omitempty"` - AutonomousDatabaseBackupOCID *string `json:"autonomousDatabaseBackupOCID,omitempty"` - - OCIConfig OCIConfigSpec `json:"ociConfig,omitempty"` + Target TargetSpec `json:"target,omitempty"` + DisplayName *string `json:"displayName,omitempty"` + AutonomousDatabaseBackupOCID *string `json:"autonomousDatabaseBackupOCID,omitempty"` + IsLongTermBackup *bool `json:"isLongTermBackup,omitempty"` + RetentionPeriodInDays *int `json:"retentionPeriodInDays,omitempty"` + OCIConfig OCIConfigSpec `json:"ociConfig,omitempty"` } // AutonomousDatabaseBackupStatus defines the observed state of AutonomousDatabaseBackup diff --git a/apis/database/v1alpha1/autonomousdatabasebackup_webhook.go b/apis/database/v1alpha1/autonomousdatabasebackup_webhook.go index c08c8c58..99bf3815 100644 --- a/apis/database/v1alpha1/autonomousdatabasebackup_webhook.go +++ b/apis/database/v1alpha1/autonomousdatabasebackup_webhook.go @@ -39,6 +39,7 @@ package v1alpha1 import ( + dbcommons "github.com/oracle/oracle-database-operator/commons/database" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -46,6 +47,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) // log is for logging in this package. @@ -76,11 +78,24 @@ func (r *AutonomousDatabaseBackup) Default() { var _ webhook.Validator = &AutonomousDatabaseBackup{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (r *AutonomousDatabaseBackup) ValidateCreate() error { +func (r *AutonomousDatabaseBackup) ValidateCreate() (admission.Warnings, error) { autonomousdatabasebackuplog.Info("validate create", "name", r.Name) var allErrs field.ErrorList + namespaces := dbcommons.GetWatchNamespaces() + _, hasEmptyString := namespaces[""] + isClusterScoped := len(namespaces) == 1 && hasEmptyString + if !isClusterScoped { + _, containsNamespace := namespaces[r.Namespace] + // Check if the allowed namespaces maps contains the required namespace + if len(namespaces) != 0 && !containsNamespace { + allErrs = append(allErrs, + field.Invalid(field.NewPath("metadata").Child("namespace"), r.Namespace, + "Oracle database operator doesn't watch over this namespace")) + } + } + if r.Spec.Target.K8sADB.Name == nil && r.Spec.Target.OCIADB.OCID == nil { allErrs = append(allErrs, field.Forbidden(field.NewPath("spec").Child("target"), "target ADB is empty")) @@ -92,15 +107,15 @@ func (r *AutonomousDatabaseBackup) ValidateCreate() error { } if len(allErrs) == 0 { - return nil + return nil, nil } - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( schema.GroupKind{Group: "database.oracle.com", Kind: "AutonomousDatabaseBackup"}, r.Name, allErrs) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (r *AutonomousDatabaseBackup) ValidateUpdate(old runtime.Object) error { +func (r *AutonomousDatabaseBackup) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { autonomousdatabasebackuplog.Info("validate update", "name", r.Name) var allErrs field.ErrorList @@ -132,17 +147,17 @@ func (r *AutonomousDatabaseBackup) ValidateUpdate(old runtime.Object) error { } if len(allErrs) == 0 { - return nil + return nil, nil } - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( schema.GroupKind{Group: "database.oracle.com", Kind: "AutonomousDatabaseBackup"}, r.Name, allErrs) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type -func (r *AutonomousDatabaseBackup) ValidateDelete() error { +func (r *AutonomousDatabaseBackup) ValidateDelete() (admission.Warnings, error) { autonomousdatabasebackuplog.Info("validate delete", "name", r.Name) // TODO(user): fill in your validation logic upon object deletion. - return nil + return nil, nil } diff --git a/apis/database/v1alpha1/autonomousdatabaserestore_webhook.go b/apis/database/v1alpha1/autonomousdatabaserestore_webhook.go index 8b4dd974..4f96bd7b 100644 --- a/apis/database/v1alpha1/autonomousdatabaserestore_webhook.go +++ b/apis/database/v1alpha1/autonomousdatabaserestore_webhook.go @@ -39,6 +39,7 @@ package v1alpha1 import ( + dbcommons "github.com/oracle/oracle-database-operator/commons/database" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -46,6 +47,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) // log is for logging in this package. @@ -65,11 +67,24 @@ func (r *AutonomousDatabaseRestore) SetupWebhookWithManager(mgr ctrl.Manager) er var _ webhook.Validator = &AutonomousDatabaseRestore{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (r *AutonomousDatabaseRestore) ValidateCreate() error { +func (r *AutonomousDatabaseRestore) ValidateCreate() (admission.Warnings, error) { autonomousdatabaserestorelog.Info("validate create", "name", r.Name) var allErrs field.ErrorList + namespaces := dbcommons.GetWatchNamespaces() + _, hasEmptyString := namespaces[""] + isClusterScoped := len(namespaces) == 1 && hasEmptyString + if !isClusterScoped { + _, containsNamespace := namespaces[r.Namespace] + // Check if the allowed namespaces maps contains the required namespace + if len(namespaces) != 0 && !containsNamespace { + allErrs = append(allErrs, + field.Invalid(field.NewPath("metadata").Child("namespace"), r.Namespace, + "Oracle database operator doesn't watch over this namespace")) + } + } + // Validate the target ADB if r.Spec.Target.K8sADB.Name == nil && r.Spec.Target.OCIADB.OCID == nil { allErrs = append(allErrs, @@ -104,31 +119,31 @@ func (r *AutonomousDatabaseRestore) ValidateCreate() error { } if len(allErrs) == 0 { - return nil + return nil, nil } - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( schema.GroupKind{Group: "database.oracle.com", Kind: "AutonomousDatabaseRestore"}, r.Name, allErrs) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (r *AutonomousDatabaseRestore) ValidateUpdate(old runtime.Object) error { +func (r *AutonomousDatabaseRestore) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { autonomousdatabaserestorelog.Info("validate update", "name", r.Name) var allErrs field.ErrorList if len(allErrs) == 0 { - return nil + return nil, nil } - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( schema.GroupKind{Group: "database.oracle.com", Kind: "AutonomousDatabaseRestore"}, r.Name, allErrs) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type -func (r *AutonomousDatabaseRestore) ValidateDelete() error { +func (r *AutonomousDatabaseRestore) ValidateDelete() (admission.Warnings, error) { autonomousdatabaserestorelog.Info("validate delete", "name", r.Name) // TODO(user): fill in your validation logic upon object deletion. - return nil + return nil, nil } diff --git a/apis/database/v1alpha1/cdb_types.go b/apis/database/v1alpha1/cdb_types.go index b5f39707..206781b2 100644 --- a/apis/database/v1alpha1/cdb_types.go +++ b/apis/database/v1alpha1/cdb_types.go @@ -52,7 +52,6 @@ type CDBSpec struct { // Name of the CDB Service ServiceName string `json:"serviceName,omitempty"` - // Password for the CDB System Administrator SysAdminPwd CDBSysAdminPassword `json:"sysAdminPwd,omitempty"` // User in the root container with sysdba priviledges to manage PDB lifecycle @@ -86,7 +85,7 @@ type CDBSpec struct { DBPort int `json:"dbPort,omitempty"` // Node Selector for running the Pod NodeSelector map[string]string `json:"nodeSelector,omitempty"` - DBTnsurl string `json:"dbTnsurl,omitempty"` + DBTnsurl string `json:"dbTnsurl,omitempty"` } // CDBSecret defines the secretName @@ -155,6 +154,7 @@ type CDBStatus struct { // +kubebuilder:printcolumn:JSONPath=".spec.replicas",name="Replicas",type="integer",description="Replicas" // +kubebuilder:printcolumn:JSONPath=".status.phase",name="Status",type="string",description="Status of the CDB Resource" // +kubebuilder:printcolumn:JSONPath=".status.msg",name="Message",type="string",description="Error message, if any" +// +kubebuilder:resource:path=cdbs,scope=Namespaced // CDB is the Schema for the cdbs API type CDB struct { diff --git a/apis/database/v1alpha1/cdb_webhook.go b/apis/database/v1alpha1/cdb_webhook.go index 25975092..345b6f75 100644 --- a/apis/database/v1alpha1/cdb_webhook.go +++ b/apis/database/v1alpha1/cdb_webhook.go @@ -49,6 +49,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) // log is for logging in this package. @@ -83,7 +84,7 @@ func (r *CDB) Default() { var _ webhook.Validator = &CDB{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (r *CDB) ValidateCreate() error { +func (r *CDB) ValidateCreate() (admission.Warnings, error) { cdblog.Info("ValidateCreate", "name", r.Name) var allErrs field.ErrorList @@ -92,32 +93,32 @@ func (r *CDB) ValidateCreate() error { allErrs = append(allErrs, field.Required(field.NewPath("spec").Child("serviceName"), "Please specify CDB Service name")) } - - if reflect.ValueOf(r.Spec.CDBTlsKey).IsZero() { - allErrs = append(allErrs, - field.Required(field.NewPath("spec").Child("cdbTlsKey"), "Please specify CDB Tls key(secret)")) - } - if reflect.ValueOf(r.Spec.CDBTlsCrt).IsZero() { - allErrs = append(allErrs, - field.Required(field.NewPath("spec").Child("cdbTlsCrt"), "Please specify CDB Tls Certificate(secret)")) - } + if reflect.ValueOf(r.Spec.CDBTlsKey).IsZero() { + allErrs = append(allErrs, + field.Required(field.NewPath("spec").Child("cdbTlsKey"), "Please specify CDB Tls key(secret)")) + } + + if reflect.ValueOf(r.Spec.CDBTlsCrt).IsZero() { + allErrs = append(allErrs, + field.Required(field.NewPath("spec").Child("cdbTlsCrt"), "Please specify CDB Tls Certificate(secret)")) + } /*if r.Spec.SCANName == "" { allErrs = append(allErrs, field.Required(field.NewPath("spec").Child("scanName"), "Please specify SCAN Name for CDB")) }*/ - if ((r.Spec.DBServer == "" && r.Spec.DBTnsurl == "") || (r.Spec.DBServer != "" && r.Spec.DBTnsurl != "")) { + if (r.Spec.DBServer == "" && r.Spec.DBTnsurl == "") || (r.Spec.DBServer != "" && r.Spec.DBTnsurl != "") { allErrs = append(allErrs, field.Required(field.NewPath("spec").Child("dbServer"), "Please specify Database Server Name/IP Address or tnsalias string")) } - if r.Spec.DBTnsurl != "" && ( r.Spec.DBServer != "" || r.Spec.DBPort != 0 || r.Spec.ServiceName != "" ) { + if r.Spec.DBTnsurl != "" && (r.Spec.DBServer != "" || r.Spec.DBPort != 0 || r.Spec.ServiceName != "") { allErrs = append(allErrs, field.Required(field.NewPath("spec").Child("dbServer"), "DBtnsurl is orthogonal to (DBServer,DBport,Services)")) - } - + } + if r.Spec.DBPort == 0 && r.Spec.DBServer != "" { allErrs = append(allErrs, field.Required(field.NewPath("spec").Child("dbPort"), "Please specify DB Server Port")) @@ -159,20 +160,20 @@ func (r *CDB) ValidateCreate() error { field.Required(field.NewPath("spec").Child("webServerPwd"), "Please specify password for the Web Server User having SQL Administrator role")) } if len(allErrs) == 0 { - return nil + return nil, nil } - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( schema.GroupKind{Group: "database.oracle.com", Kind: "CDB"}, r.Name, allErrs) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (r *CDB) ValidateUpdate(old runtime.Object) error { +func (r *CDB) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { cdblog.Info("validate update", "name", r.Name) isCDBMarkedToBeDeleted := r.GetDeletionTimestamp() != nil if isCDBMarkedToBeDeleted { - return nil + return nil, nil } var allErrs field.ErrorList @@ -180,7 +181,7 @@ func (r *CDB) ValidateUpdate(old runtime.Object) error { // Check for updation errors oldCDB, ok := old.(*CDB) if !ok { - return nil + return nil, nil } if r.Spec.DBPort < 0 { @@ -201,18 +202,18 @@ func (r *CDB) ValidateUpdate(old runtime.Object) error { } if len(allErrs) == 0 { - return nil + return nil, nil } - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( schema.GroupKind{Group: "database.oracle.com", Kind: "CDB"}, r.Name, allErrs) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type -func (r *CDB) ValidateDelete() error { +func (r *CDB) ValidateDelete() (admission.Warnings, error) { cdblog.Info("validate delete", "name", r.Name) // TODO(user): fill in your validation logic upon object deletion. - return nil + return nil, nil } diff --git a/apis/database/v1alpha1/dataguardbroker_types.go b/apis/database/v1alpha1/dataguardbroker_types.go index 138e2bdb..37d71b92 100644 --- a/apis/database/v1alpha1/dataguardbroker_types.go +++ b/apis/database/v1alpha1/dataguardbroker_types.go @@ -50,15 +50,15 @@ type DataguardBrokerSpec struct { // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster // Important: Run "make" to regenerate code after modifying this file - PrimaryDatabaseRef string `json:"primaryDatabaseRef"` - StandbyDatabaseRefs []string `json:"standbyDatabaseRefs"` - SetAsPrimaryDatabase string `json:"setAsPrimaryDatabase,omitempty"` - LoadBalancer bool `json:"loadBalancer,omitempty"` - ServiceAnnotations map[string]string `json:"serviceAnnotations,omitempty"` + PrimaryDatabaseRef string `json:"primaryDatabaseRef"` + StandbyDatabaseRefs []string `json:"standbyDatabaseRefs"` + SetAsPrimaryDatabase string `json:"setAsPrimaryDatabase,omitempty"` + LoadBalancer bool `json:"loadBalancer,omitempty"` + ServiceAnnotations map[string]string `json:"serviceAnnotations,omitempty"` // +kubebuilder:validation:Enum=MaxPerformance;MaxAvailability - ProtectionMode string `json:"protectionMode"` - NodeSelector map[string]string `json:"nodeSelector,omitempty"` - FastStartFailOver DataguardBrokerFastStartFailOver `json:"fastStartFailOver,omitempty"` + ProtectionMode string `json:"protectionMode"` + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + FastStartFailOver DataguardBrokerFastStartFailOver `json:"fastStartFailOver,omitempty"` } type DataguardBrokerFastStartFailOver struct { diff --git a/apis/database/v1alpha1/dataguardbroker_webhook.go b/apis/database/v1alpha1/dataguardbroker_webhook.go index c947f7a3..a9d59286 100644 --- a/apis/database/v1alpha1/dataguardbroker_webhook.go +++ b/apis/database/v1alpha1/dataguardbroker_webhook.go @@ -41,6 +41,7 @@ package v1alpha1 import ( "strings" + dbcommons "github.com/oracle/oracle-database-operator/commons/database" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -48,6 +49,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) // log is for logging in this package. @@ -69,21 +71,21 @@ var _ webhook.Defaulter = &DataguardBroker{} func (r *DataguardBroker) Default() { dataguardbrokerlog.Info("default", "name", r.Name) - if (r.Spec.LoadBalancer) { + if r.Spec.LoadBalancer { if r.Spec.ServiceAnnotations == nil { - r.Spec.ServiceAnnotations= make(map[string]string) + r.Spec.ServiceAnnotations = make(map[string]string) } - // Annotations required for a flexible load balancer on oci + // Annotations required for a flexible load balancer on oci _, ok := r.Spec.ServiceAnnotations["service.beta.kubernetes.io/oci-load-balancer-shape"] - if(!ok) { + if !ok { r.Spec.ServiceAnnotations["service.beta.kubernetes.io/oci-load-balancer-shape"] = "flexible" } - _,ok = r.Spec.ServiceAnnotations["service.beta.kubernetes.io/oci-load-balancer-shape-flex-min"] - if(!ok) { + _, ok = r.Spec.ServiceAnnotations["service.beta.kubernetes.io/oci-load-balancer-shape-flex-min"] + if !ok { r.Spec.ServiceAnnotations["service.beta.kubernetes.io/oci-load-balancer-shape-flex-min"] = "10" } - _,ok = r.Spec.ServiceAnnotations["service.beta.kubernetes.io/oci-load-balancer-shape-flex-max"] - if(!ok) { + _, ok = r.Spec.ServiceAnnotations["service.beta.kubernetes.io/oci-load-balancer-shape-flex-max"] + if !ok { r.Spec.ServiceAnnotations["service.beta.kubernetes.io/oci-load-balancer-shape-flex-max"] = "100" } } @@ -95,38 +97,53 @@ func (r *DataguardBroker) Default() { var _ webhook.Validator = &DataguardBroker{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (r *DataguardBroker) ValidateCreate() error { +func (r *DataguardBroker) ValidateCreate() (admission.Warnings, error) { + dataguardbrokerlog.Info("validate create", "name", r.Name) + var allErrs field.ErrorList + namespaces := dbcommons.GetWatchNamespaces() + _, containsNamespace := namespaces[r.Namespace] + // Check if the allowed namespaces maps contains the required namespace + if len(namespaces) != 0 && !containsNamespace { + allErrs = append(allErrs, + field.Invalid(field.NewPath("metadata").Child("namespace"), r.Namespace, + "Oracle database operator doesn't watch over this namespace")) + } - // TODO(user): fill in your validation logic upon object creation. - return nil + if len(allErrs) == 0 { + return nil, nil + } + + return nil, apierrors.NewInvalid( + schema.GroupKind{Group: "database.oracle.com", Kind: "Dataguard"}, + r.Name, allErrs) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (r *DataguardBroker) ValidateUpdate(old runtime.Object) error { +func (r *DataguardBroker) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { dataguardbrokerlog.Info("validate update", "name", r.Name) dataguardbrokerlog.Info("validate update", "name", r.Name) var allErrs field.ErrorList // check creation validations first - err := r.ValidateCreate() + _, err := r.ValidateCreate() if err != nil { - return err + return nil, err } // Validate Deletion if r.GetDeletionTimestamp() != nil { - err := r.ValidateDelete() + warnings, err := r.ValidateDelete() if err != nil { - return err + return warnings, err } } // Now check for updation errors oldObj, ok := old.(*DataguardBroker) if !ok { - return nil + return nil, nil } if oldObj.Status.ProtectionMode != "" && !strings.EqualFold(r.Spec.ProtectionMode, oldObj.Status.ProtectionMode) { @@ -139,18 +156,18 @@ func (r *DataguardBroker) ValidateUpdate(old runtime.Object) error { } if len(allErrs) == 0 { - return nil + return nil, nil } - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( schema.GroupKind{Group: "database.oracle.com", Kind: "DataguardBroker"}, r.Name, allErrs) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type -func (r *DataguardBroker) ValidateDelete() error { +func (r *DataguardBroker) ValidateDelete() (admission.Warnings, error) { dataguardbrokerlog.Info("validate delete", "name", r.Name) // TODO(user): fill in your validation logic upon object deletion. - return nil + return nil, nil } diff --git a/apis/database/v1alpha1/dbcssystem_types.go b/apis/database/v1alpha1/dbcssystem_types.go index 28773fb2..37e80a6b 100644 --- a/apis/database/v1alpha1/dbcssystem_types.go +++ b/apis/database/v1alpha1/dbcssystem_types.go @@ -156,8 +156,9 @@ type VmNetworkDetails struct { NetworkSG string `json:"networkSG,omitempty"` } -//+kubebuilder:object:root=true -//+kubebuilder:subresource:status +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:path=DbcsSystem,scope=Namespaced // DbcsSystem is the Schema for the dbcssystems API type DbcsSystem struct { diff --git a/apis/database/v1alpha1/groupversion_info.go b/apis/database/v1alpha1/groupversion_info.go index d72ee908..3c4b1804 100644 --- a/apis/database/v1alpha1/groupversion_info.go +++ b/apis/database/v1alpha1/groupversion_info.go @@ -37,8 +37,8 @@ */ // Package v1alpha1 contains API Schema definitions for the database v1alpha1 API group -//+kubebuilder:object:generate=true -//+groupName=database.oracle.com +// +kubebuilder:object:generate=true +// +groupName=database.oracle.com package v1alpha1 import ( diff --git a/apis/database/v1alpha1/oraclerestdataservice_webhook.go b/apis/database/v1alpha1/oraclerestdataservice_webhook.go index be83fffc..bfe3208c 100644 --- a/apis/database/v1alpha1/oraclerestdataservice_webhook.go +++ b/apis/database/v1alpha1/oraclerestdataservice_webhook.go @@ -39,6 +39,7 @@ package v1alpha1 import ( + dbcommons "github.com/oracle/oracle-database-operator/commons/database" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime/schema" @@ -46,6 +47,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) // log is for logging in this package. @@ -86,11 +88,20 @@ func (r *OracleRestDataService) Default() { var _ webhook.Validator = &OracleRestDataService{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (r *OracleRestDataService) ValidateCreate() error { +func (r *OracleRestDataService) ValidateCreate() (admission.Warnings, error) { oraclerestdataservicelog.Info("validate create", "name", r.Name) var allErrs field.ErrorList + namespaces := dbcommons.GetWatchNamespaces() + _, containsNamespace := namespaces[r.Namespace] + // Check if the allowed namespaces maps contains the required namespace + if len(namespaces) != 0 && !containsNamespace { + allErrs = append(allErrs, + field.Invalid(field.NewPath("metadata").Child("namespace"), r.Namespace, + "Oracle database operator doesn't watch over this namespace")) + } + // Persistence spec validation if r.Spec.Persistence.Size == "" && (r.Spec.Persistence.AccessMode != "" || r.Spec.Persistence.StorageClass != "" || r.Spec.Persistence.VolumeName != "") { @@ -116,34 +127,34 @@ func (r *OracleRestDataService) ValidateCreate() error { if r.Spec.DatabaseRef == r.Name { allErrs = append(allErrs, field.Forbidden(field.NewPath("Name"), - "cannot be same as DatabaseRef: " + r.Spec.DatabaseRef)) + "cannot be same as DatabaseRef: "+r.Spec.DatabaseRef)) } if len(allErrs) == 0 { - return nil + return nil, nil } - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( schema.GroupKind{Group: "database.oracle.com", Kind: "OracleRestDataService"}, r.Name, allErrs) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (r *OracleRestDataService) ValidateUpdate(oldRuntimeObject runtime.Object) error { +func (r *OracleRestDataService) ValidateUpdate(oldRuntimeObject runtime.Object) (admission.Warnings, error) { oraclerestdataservicelog.Info("validate update", "name", r.Name) var allErrs field.ErrorList // check creation validations first - err := r.ValidateCreate() + warnings, err := r.ValidateCreate() if err != nil { - return err + return warnings, err } // Now check for updation errors old, ok := oldRuntimeObject.(*OracleRestDataService) if !ok { - return nil + return nil, nil } if old.Status.DatabaseRef != "" && old.Status.DatabaseRef != r.Spec.DatabaseRef { @@ -156,18 +167,18 @@ func (r *OracleRestDataService) ValidateUpdate(oldRuntimeObject runtime.Object) } if len(allErrs) == 0 { - return nil + return nil, nil } - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( schema.GroupKind{Group: "database.oracle.com", Kind: "OracleRestDataService"}, r.Name, allErrs) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type -func (r *OracleRestDataService) ValidateDelete() error { +func (r *OracleRestDataService) ValidateDelete() (admission.Warnings, error) { oraclerestdataservicelog.Info("validate delete", "name", r.Name) // TODO(user): fill in your validation logic upon object deletion. - return nil + return nil, nil } diff --git a/apis/database/v1alpha1/pdb_types.go b/apis/database/v1alpha1/pdb_types.go index a73d3dd8..8de9db52 100644 --- a/apis/database/v1alpha1/pdb_types.go +++ b/apis/database/v1alpha1/pdb_types.go @@ -51,6 +51,8 @@ type PDBSpec struct { PDBTlsCrt PDBTLSCRT `json:"pdbTlsCrt,omitempty"` PDBTlsCat PDBTLSCAT `json:"pdbTlsCat,omitempty"` + // CDB Namespace + CDBNamespace string `json:"cdbNamespace,omitempty"` // Name of the CDB Custom Resource that runs the ORDS container CDBResName string `json:"cdbResName,omitempty"` // Name of the CDB @@ -63,6 +65,10 @@ type PDBSpec struct { AdminName PDBAdminName `json:"adminName,omitempty"` // The administrator password for the new PDB. This property is required when the Action property is Create. AdminPwd PDBAdminPassword `json:"adminPwd,omitempty"` + // Web Server User with SQL Administrator role to allow us to authenticate to the PDB Lifecycle Management REST endpoints + WebServerUsr WebServerUserPDB `json:"webServerUser,omitempty"` + // Password for the Web ServerPDB User + WebServerPwd WebServerPasswordPDB `json:"webServerPwd,omitempty"` // Relevant for Create and Plug operations. As defined in the Oracle Multitenant Database documentation. Values can be a filename convert pattern or NONE. FileNameConversions string `json:"fileNameConversions,omitempty"` // This property is required when the Action property is Plug. As defined in the Oracle Multitenant Database documentation. Values can be a source filename convert pattern or NONE. @@ -108,6 +114,10 @@ type PDBSpec struct { // The target state of the PDB // +kubebuilder:validation:Enum=OPEN;CLOSE PDBState string `json:"pdbState,omitempty"` + // turn on the assertive approach to delete pdb resource + // kubectl delete pdb ..... automatically triggers the pluggable database + // deletion + AssertivePdbDeletion bool `json:"assertivePdbDeletion,omitempty"` } // PDBAdminName defines the secret containing Sys Admin User mapped to key 'adminName' for PDB @@ -130,6 +140,17 @@ type TDESecret struct { Secret PDBSecret `json:"secret"` } +// WebServerUser defines the secret containing Web Server User mapped to key 'webServerUser' to manage PDB lifecycle + +type WebServerUserPDB struct { + Secret PDBSecret `json:"secret"` +} + +// WebServerPassword defines the secret containing password for Web Server User mapped to key 'webServerPwd' to manage PDB lifecycle +type WebServerPasswordPDB struct { + Secret PDBSecret `json:"secret"` +} + // PDBSecret defines the secretName type PDBSecret struct { SecretName string `json:"secretName"` @@ -180,6 +201,8 @@ type PDBStatus struct { // +kubebuilder:printcolumn:JSONPath=".status.totalSize",name="PDB Size",type="string",description="Total Size of the PDB" // +kubebuilder:printcolumn:JSONPath=".status.phase",name="Status",type="string",description="Status of the PDB Resource" // +kubebuilder:printcolumn:JSONPath=".status.msg",name="Message",type="string",description="Error message, if any" +// +kubebuilder:resource:path=pdbs,scope=Namespaced + // PDB is the Schema for the pdbs API type PDB struct { metav1.TypeMeta `json:",inline"` diff --git a/apis/database/v1alpha1/pdb_webhook.go b/apis/database/v1alpha1/pdb_webhook.go index 0e78790a..1577198e 100644 --- a/apis/database/v1alpha1/pdb_webhook.go +++ b/apis/database/v1alpha1/pdb_webhook.go @@ -54,6 +54,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) // log is for logging in this package. @@ -77,8 +78,8 @@ func (r *PDB) Default() { if action == "DELETE" { if r.Spec.DropAction == "" { - r.Spec.DropAction = "KEEP" - pdblog.Info(" - dropAction : KEEP") + r.Spec.DropAction = "INCLUDING" + pdblog.Info(" - dropAction : INCLUDING") } } else if action != "MODIFY" && action != "STATUS" { if r.Spec.ReuseTempFile == nil { @@ -121,7 +122,7 @@ func (r *PDB) Default() { var _ webhook.Validator = &PDB{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (r *PDB) ValidateCreate() error { +func (r *PDB) ValidateCreate() (admission.Warnings, error) { pdblog.Info("ValidateCreate-Validating PDB spec for : " + r.Name) var allErrs field.ErrorList @@ -134,9 +135,9 @@ func (r *PDB) ValidateCreate() error { if len(allErrs) == 0 { pdblog.Info("PDB Resource : " + r.Name + " successfully validated for Action : " + action) - return nil + return nil, nil } - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( schema.GroupKind{Group: "database.oracle.com", Kind: "PDB"}, r.Name, allErrs) } @@ -147,21 +148,21 @@ func (r *PDB) validateAction(allErrs *field.ErrorList) { pdblog.Info("Valdiating PDB Resource Action : " + action) - if reflect.ValueOf(r.Spec.PDBTlsKey).IsZero() { - *allErrs = append(*allErrs, - field.Required(field.NewPath("spec").Child("pdbTlsKey"), "Please specify PDB Tls Key(secret)")) - } - - if reflect.ValueOf(r.Spec.PDBTlsCrt).IsZero() { - *allErrs = append(*allErrs, - field.Required(field.NewPath("spec").Child("pdbTlsCrt"), "Please specify PDB Tls Certificate(secret)")) - } - - if reflect.ValueOf(r.Spec.PDBTlsCat).IsZero() { - *allErrs = append(*allErrs, - field.Required(field.NewPath("spec").Child("pdbTlsCat"), "Please specify PDB Tls Certificate Authority(secret)")) - } - + if reflect.ValueOf(r.Spec.PDBTlsKey).IsZero() { + *allErrs = append(*allErrs, + field.Required(field.NewPath("spec").Child("pdbTlsKey"), "Please specify PDB Tls Key(secret)")) + } + + if reflect.ValueOf(r.Spec.PDBTlsCrt).IsZero() { + *allErrs = append(*allErrs, + field.Required(field.NewPath("spec").Child("pdbTlsCrt"), "Please specify PDB Tls Certificate(secret)")) + } + + if reflect.ValueOf(r.Spec.PDBTlsCat).IsZero() { + *allErrs = append(*allErrs, + field.Required(field.NewPath("spec").Child("pdbTlsCat"), "Please specify PDB Tls Certificate Authority(secret)")) + } + switch action { case "CREATE": if reflect.ValueOf(r.Spec.AdminName).IsZero() { @@ -172,6 +173,15 @@ func (r *PDB) validateAction(allErrs *field.ErrorList) { *allErrs = append(*allErrs, field.Required(field.NewPath("spec").Child("adminPwd"), "Please specify PDB System Administrator Password")) } + if reflect.ValueOf(r.Spec.WebServerUsr).IsZero() { + *allErrs = append(*allErrs, + field.Required(field.NewPath("spec").Child("WebServerUser"), "Please specify the http webServerUser")) + } + if reflect.ValueOf(r.Spec.WebServerPwd).IsZero() { + *allErrs = append(*allErrs, + field.Required(field.NewPath("spec").Child("webServerPwd"), "Please specify the http webserverPassword")) + } + if r.Spec.FileNameConversions == "" { *allErrs = append(*allErrs, field.Required(field.NewPath("spec").Child("fileNameConversions"), "Please specify a value for fileNameConversions. Values can be a filename convert pattern or NONE")) @@ -242,12 +252,12 @@ func (r *PDB) validateAction(allErrs *field.ErrorList) { } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (r *PDB) ValidateUpdate(old runtime.Object) error { +func (r *PDB) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { pdblog.Info("ValidateUpdate-Validating PDB spec for : " + r.Name) isPDBMarkedToBeDeleted := r.GetDeletionTimestamp() != nil if isPDBMarkedToBeDeleted { - return nil + return nil, nil } var allErrs field.ErrorList @@ -272,19 +282,19 @@ func (r *PDB) ValidateUpdate(old runtime.Object) error { } if len(allErrs) == 0 { - return nil + return nil, nil } - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( schema.GroupKind{Group: "database.oracle.com", Kind: "PDB"}, r.Name, allErrs) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type -func (r *PDB) ValidateDelete() error { +func (r *PDB) ValidateDelete() (admission.Warnings, error) { pdblog.Info("ValidateDelete-Validating PDB spec for : " + r.Name) // TODO(user): fill in your validation logic upon object deletion. - return nil + return nil, nil } // Validate common specs needed for all PDB Actions diff --git a/apis/database/v1alpha1/shardingdatabase_types.go b/apis/database/v1alpha1/shardingdatabase_types.go index b2f7142e..ffc17ab0 100644 --- a/apis/database/v1alpha1/shardingdatabase_types.go +++ b/apis/database/v1alpha1/shardingdatabase_types.go @@ -58,26 +58,43 @@ import ( type ShardingDatabaseSpec struct { // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster // Important: Run "make" to regenerate code after modifying this file - Shard []ShardSpec `json:"shard"` - Catalog []CatalogSpec `json:"catalog"` // The catalogSpes accept all the catalog parameters - Gsm []GsmSpec `json:"gsm"` // The GsmSpec will accept all the Gsm parameter - StorageClass string `json:"storageClass,omitempty"` // Optional Accept storage class name - DbImage string `json:"dbImage"` // Accept DB Image name - DbImagePullSecret string `json:"dbImagePullSecret,omitempty"` // Optional The name of an image pull secret in case of a private docker repository. - GsmImage string `json:"gsmImage"` // Acccept the GSM image name - GsmImagePullSecret string `json:"gsmImagePullSecret,omitempty"` // Optional The name of an image pull secret in case of a private docker repository. - Secret string `json:"secret"` // Secret Name to be used with Shard - StagePvcName string `json:"stagePvcName,omitempty"` // the Stagepvc for the backup of cluster - PortMappings []PortMapping `json:"portMappings,omitempty"` // Port mappings for the service that is created. The service is created if there is at least - Namespace string `json:"namespace,omitempty"` // Target namespace of the application. - IsDebug bool `json:"isDebug,omitempty"` // Optional parameter to enable logining - IsExternalSvc bool `json:"isExternalSvc,omitempty"` - IsClone bool `json:"isClone,omitempty"` - IsDataGuard bool `json:"isDataGuard,omitempty"` - ScriptsLocation string `json:"scriptsLocation,omitempty"` - NsConfigMap string `json:"nsConfigMap,omitempty"` - NsSecret string `json:"nsSecret,omitempty"` - IsDeleteOraPvc bool `json:"isDeleteOraPvc,omitempty"` + Shard []ShardSpec `json:"shard"` + Catalog []CatalogSpec `json:"catalog"` // The catalogSpes accept all the catalog parameters + Gsm []GsmSpec `json:"gsm"` // The GsmSpec will accept all the Gsm parameter + StorageClass string `json:"storageClass,omitempty"` // Optional Accept storage class name + DbImage string `json:"dbImage"` // Accept DB Image name + DbImagePullSecret string `json:"dbImagePullSecret,omitempty"` // Optional The name of an image pull secret in case of a private docker repository. + GsmImage string `json:"gsmImage"` // Acccept the GSM image name + GsmImagePullSecret string `json:"gsmImagePullSecret,omitempty"` // Optional The name of an image pull secret in case of a private docker repository. + StagePvcName string `json:"stagePvcName,omitempty"` // the Stagepvc for the backup of cluster + PortMappings []PortMapping `json:"portMappings,omitempty"` // Port mappings for the service that is created. The service is created if there is at least + Namespace string `json:"namespace,omitempty"` // Target namespace of the application. + IsDebug bool `json:"isDebug,omitempty"` // Optional parameter to enable logining + IsExternalSvc bool `json:"isExternalSvc,omitempty"` + IsClone bool `json:"isClone,omitempty"` + IsDataGuard bool `json:"isDataGuard,omitempty"` + ScriptsLocation string `json:"scriptsLocation,omitempty"` + IsDeleteOraPvc bool `json:"isDeleteOraPvc,omitempty"` + ReadinessCheckPeriod int `json:"readinessCheckPeriod,omitempty"` + LivenessCheckPeriod int `json:"liveinessCheckPeriod,omitempty"` + ReplicationType string `json:"replicationType,omitempty"` + IsDownloadScripts bool `json:"isDownloadScripts,omitempty"` + InvitedNodeSubnetFlag string `json:"invitedNodeSubnetFlag,omitempty"` + InvitedNodeSubnet string `json:"InvitedNodeSubnet,omitempty"` + ShardingType string `json:"shardingType,omitempty"` + GsmShardSpace []GsmShardSpaceSpec `json:"gsmShardSpace,omitempty"` + GsmShardGroup []GsmShardGroupSpec `json:"gsmShardGroup,omitempty"` + ShardRegion []string `json:"shardRegion,omitempty"` + ShardBuddyRegion string `json:"shardBuddyRegion,omitempty"` + GsmService []GsmServiceSpec `json:"gsmService,omitempty"` + ShardConfigName string `json:"shardConfigName,omitempty"` + GsmDevMode string `json:"gsmDevMode,omitempty"` + DbSecret *SecretDetails `json:"dbSecret,omitempty"` // Secret Name to be used with Shard + IsTdeWallet string `json:"isTdeWallet,omitempty"` + TdeWalletPvc string `json:"tdeWalletPvc,omitempty"` + FssStorageClass string `json:"fssStorageClass,omitempty"` + TdeWalletPvcMountLocation string `json:"tdeWalletPvcMountLocation,omitempty"` + DbEdition string `json:"dbEdition,omitempty"` } // To understand Metav1.Condition, please refer the link https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1 @@ -88,7 +105,8 @@ type ShardingDatabaseStatus struct { Shard map[string]string `json:"shards,omitempty"` Catalog map[string]string `json:"catalogs,omitempty"` - Gsm GsmStatus `json:"gsm,omitempty"` + + Gsm GsmStatus `json:"gsm,omitempty"` // +patchMergeKey=type // +patchStrategy=merge @@ -106,6 +124,12 @@ type GsmStatus struct { Services string `json:"services,omitempty"` } +type GsmShardDetails struct { + Name string `json:"name,omitempty"` + Available string `json:"available,omitempty"` + State string `json:"State,omitempty"` +} + type GsmStatusDetails struct { Name string `json:"name,omitempty"` K8sInternalSvc string `json:"k8sInternalSvc,omitempty"` @@ -118,8 +142,12 @@ type GsmStatusDetails struct { //+kubebuilder:object:root=true //+kubebuilder:subresource:status +//+kubebuilder:printcolumn:JSONPath=".status.gsm.state",name="Gsm State",type=string +//+kubebuilder:printcolumn:JSONPath=".status.gsm.services",name="Services",type=string +//+kubebuilder:printcolumn:JSONPath=".status.gsm.shards",name="shards",type=string,priority=1 // ShardingDatabase is the Schema for the shardingdatabases API +// +kubebuilder:resource:path=shardingdatabases,scope=Namespaced type ShardingDatabase struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -140,17 +168,22 @@ type ShardingDatabaseList struct { // ShardSpec is a specification of Shards for an application deployment. // +k8s:openapi-gen=true type ShardSpec struct { - Name string `json:"name"` // Shard name that will be used deploy StatefulSet - StorageSizeInGb int32 `json:"storageSizeInGb,omitempty"` // Optional Shard Storage Size - EnvVars []EnvironmentVariable `json:"envVars,omitempty"` //Optional Env variables for Shards - Resources *corev1.ResourceRequirements `json:"resources,omitempty" protobuf:"bytes,1,opt,name=resources"` //Optional resource requirement for the container. - PvcName string `json:"pvcName,omitempty"` - Label string `json:"label,omitempty"` - IsDelete bool `json:"isDelete,omitempty"` - NodeSelector map[string]string `json:"nodeSelector,omitempty"` - PvAnnotations map[string]string `json:"pvAnnotations,omitempty"` - PvMatchLabels map[string]string `json:"pvMatchLabels,omitempty"` - ImagePulllPolicy *corev1.PullPolicy `json:"imagePullPolicy,omitempty"` + Name string `json:"name"` // Shard name that will be used deploy StatefulSet + StorageSizeInGb int32 `json:"storageSizeInGb,omitempty"` // Optional Shard Storage Size + EnvVars []EnvironmentVariable `json:"envVars,omitempty"` //Optional Env variables for Shards + Resources *corev1.ResourceRequirements `json:"resources,omitempty" protobuf:"bytes,1,opt,name=resources"` //Optional resource requirement for the container. + PvcName string `json:"pvcName,omitempty"` + Label string `json:"label,omitempty"` + // +kubebuilder:validation:Enum=enable;disable;failed;force + IsDelete string `json:"isDelete,omitempty"` + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + PvAnnotations map[string]string `json:"pvAnnotations,omitempty"` + PvMatchLabels map[string]string `json:"pvMatchLabels,omitempty"` + ImagePulllPolicy *corev1.PullPolicy `json:"imagePullPolicy,omitempty"` + ShardSpace string `json:"shardSpace,omitempty"` + ShardGroup string `json:"shardGroup,omitempty"` + ShardRegion string `json:"shardRegion,omitempty"` + DeployAs string `json:"deployAs,omitempty"` } // CatalogSpec defines the desired state of CatalogSpec @@ -162,7 +195,7 @@ type CatalogSpec struct { Resources *corev1.ResourceRequirements `json:"resources,omitempty" protobuf:"bytes,1,opt,name=resources"` // Optional resource requirement for the container. PvcName string `json:"pvcName,omitempty"` Label string `json:"label,omitempty"` - IsDelete bool `json:"isDelete,omitempty"` + IsDelete string `json:"isDelete,omitempty"` NodeSelector map[string]string `json:"nodeSelector,omitempty"` PvAnnotations map[string]string `json:"pvAnnotations,omitempty"` PvMatchLabels map[string]string `json:"pvMatchLabels,omitempty"` @@ -174,16 +207,80 @@ type CatalogSpec struct { type GsmSpec struct { Name string `json:"name"` // Gsm name that will be used deploy StatefulSet - Replicas int32 `json:"replicas,omitempty"` // Gsm Replicas. If you set OraGsmPvcName then it is set default to 1. + //Replicas int32 `json:"replicas,omitempty"` // Gsm Replicas. If you set OraGsmPvcName then it is set default to 1. EnvVars []EnvironmentVariable `json:"envVars,omitempty"` //Optional Env variables for GSM StorageSizeInGb int32 `json:"storageSizeInGb,omitempty"` // This parameter will not be used if you use OraGsmPvcName Resources *corev1.ResourceRequirements `json:"resources,omitempty" protobuf:"bytes,1,opt,name=resources"` // Optional resource requirement for the container. PvcName string `json:"pvcName,omitempty"` Label string `json:"label,omitempty"` // Optional GSM Label - IsDelete bool `json:"isDelete,omitempty"` + IsDelete string `json:"isDelete,omitempty"` NodeSelector map[string]string `json:"nodeSelector,omitempty"` PvMatchLabels map[string]string `json:"pvMatchLabels,omitempty"` ImagePulllPolicy *corev1.PullPolicy `json:"imagePullPolicy,omitempty"` + Region string `json:"region,omitempty"` + DirectorName string `json:"directorName,omitempty"` +} + +// ShardGroupSpec Specification + +type GsmShardGroupSpec struct { + Name string `json:"name"` // Name of the shardgroup. + Region string `json:"region,omitempty"` + DeployAs string `json:"deployAs,omitempty"` +} + +// ShardSpace Specs +type GsmShardSpaceSpec struct { + Name string `json:"name"` // Name of the shardSpace. + Chunks int `json:"chunks,omitempty"` //chunks is optional + ProtectionMode string `json:"protectionMode,omitempty"` // Data guard protection mode + ShardGroup string `json:"shardGroup,omitempty"` +} + +// Service Definition +type GsmServiceSpec struct { + Name string `json:"name"` // Name of the shardSpace. + Available string `json:"available,omitempty"` + ClbGoal string `json:"clbGoal,omitempty"` + CommitOutcome string `json:"commitOutcome,omitempty"` + DrainTimeout string `json:"drainTimeout,omitempty"` + Dtp string `json:"dtp,omitempty"` + Edition string `json:"edition,omitempty"` + FailoverPrimary string `json:"failoverPrimary,omitempty"` + FailoverRestore string `json:"failoverRestore,omitempty"` + FailoverDelay string `json:"failoverDelay,omitempty"` + FailoverMethod string `json:"failoverMethod,omitempty"` + FailoverRetry string `json:"failoverRetry,omitempty"` + FailoverType string `json:"failoverType,omitempty"` + GdsPool string `json:"gdsPool,omitempty"` + Role string `json:"role,omitempty"` + SessionState string `json:"sessionState,omitempty"` + Lag int `json:"lag,omitempty"` + Locality string `json:"locality,omitempty"` + Notification string `json:"notification,omitempty"` + PdbName string `json:"pdbName,omitempty"` + Policy string `json:"policy,omitempty"` + Preferrred string `json:"preferred,omitempty"` + PreferredAll string `json:"prferredAll,omitempty"` + RegionFailover string `json:"regionFailover,omitempty"` + StopOption string `json:"stopOption,omitempty"` + SqlTrasactionProfile string `json:"sqlTransactionProfile,omitempty"` + TableFamily string `json:"tableFamily,omitempty"` + Retention string `json:"retention,omitempty"` + TfaPolicy string `json:"tfaPolicy,omitempty"` +} + +// Secret Details +type SecretDetails struct { + Name string `json:"name"` // Name of the secret. + KeyFileName string `json:"keyFileName,omitempty"` // Name of the key. + NsConfigMap string `json:"nsConfigMap,omitempty"` + NsSecret string `json:"nsSecret,omitempty"` + PwdFileName string `json:"pwdFileName"` + PwdFileMountLocation string `json:"pwdFileMountLocation,omitempty"` + KeyFileMountLocation string `json:"keyFileMountLocation,omitempty"` + KeySecretName string `json:"keySecretName,omitempty"` + EncryptionType string `json:"encryptionType,omitempty"` } // EnvironmentVariable represents a named variable accessible for containers. diff --git a/apis/database/v1alpha1/shardingdatabase_webhook.go b/apis/database/v1alpha1/shardingdatabase_webhook.go new file mode 100644 index 00000000..8b91fb0c --- /dev/null +++ b/apis/database/v1alpha1/shardingdatabase_webhook.go @@ -0,0 +1,270 @@ +/* +** Copyright (c) 2022 Oracle and/or its affiliates. +** +** The Universal Permissive License (UPL), Version 1.0 +** +** Subject to the condition set forth below, permission is hereby granted to any +** person obtaining a copy of this software, associated documentation and/or data +** (collectively the "Software"), free of charge and under any and all copyright +** rights in the Software, and any and all patent rights owned or freely +** licensable by each licensor hereunder covering either (i) the unmodified +** Software as contributed to or provided by such licensor, or (ii) the Larger +** Works (as defined below), to deal in both +** +** (a) the Software, and +** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +** one is included with the Software (each a "Larger Work" to which the Software +** is contributed by such licensors), +** +** without restriction, including without limitation the rights to copy, create +** derivative works of, display, perform, and distribute the Software and make, +** use, sell, offer for sale, import, export, have made, and have sold the +** Software and the Larger Work(s), and to sublicense the foregoing rights on +** either these or other terms. +** +** This license is subject to the following condition: +** The above copyright notice and either this complete permission notice or at +** a minimum a reference to the UPL must be included in all copies or +** substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +** SOFTWARE. + */ + +package v1alpha1 + +import ( + "strings" + + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/validation/field" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" +) + +// log is for logging in this package. +var shardingdatabaselog = logf.Log.WithName("shardingdatabase-resource") + +func (r *ShardingDatabase) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! + +//+kubebuilder:webhook:path=/mutate-database-oracle-com-v1alpha1-shardingdatabase,mutating=true,failurePolicy=fail,sideEffects=none,groups=database.oracle.com,resources=shardingdatabases,verbs=create;update,versions=v1alpha1,name=mshardingdatabase.kb.io,admissionReviewVersions={v1} + +var _ webhook.Defaulter = &ShardingDatabase{} + +// Default implements webhook.Defaulter so a webhook will be registered for the type +func (r *ShardingDatabase) Default() { + shardingdatabaselog.Info("default", "name", r.Name) + + // TODO(user): fill in your defaulting logic. + if r.Spec.GsmDevMode != "" { + r.Spec.GsmDevMode = "dev" + } + + if r.Spec.IsTdeWallet == "" { + r.Spec.IsTdeWallet = "disable" + } + for pindex := range r.Spec.Shard { + if strings.ToLower(r.Spec.Shard[pindex].IsDelete) == "" { + r.Spec.Shard[pindex].IsDelete = "disable" + } + } + +} + +// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +//+kubebuilder:webhook:verbs=create;update;delete,path=/validate-database-oracle-com-v1alpha1-shardingdatabase,mutating=false,failurePolicy=fail,sideEffects=None,groups=database.oracle.com,resources=shardingdatabases,versions=v1alpha1,name=vshardingdatabase.kb.io,admissionReviewVersions={v1} + +var _ webhook.Validator = &ShardingDatabase{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *ShardingDatabase) ValidateCreate() (admission.Warnings, error) { + shardingdatabaselog.Info("validate create", "name", r.Name) + + // TODO(user): fill in your validation logic upon object creation. + // Check Secret configuration + var validationErr field.ErrorList + var validationErrs1 field.ErrorList + + //namespaces := db.GetWatchNamespaces() + //_, containsNamespace := namespaces[r.Namespace] + // Check if the allowed namespaces maps contains the required namespace + // if len(namespaces) != 0 && !containsNamespace { + // validationErr = append(validationErr, + // field.Invalid(field.NewPath("metadata").Child("namespace"), r.Namespace, + // "Oracle database operator doesn't watch over this namespace")) + //} + + if r.Spec.DbSecret == nil { + validationErr = append(validationErr, + field.Invalid(field.NewPath("spec").Child("DbSecret"), r.Spec.DbSecret, + "DbSecret cannot be set to nil")) + } else { + if len(r.Spec.DbSecret.Name) == 0 { + validationErr = append(validationErr, + field.Invalid(field.NewPath("spec").Child("DbSecret").Child("Name"), r.Spec.DbSecret.Name, + "Secret name cannot be set empty")) + } + if len(r.Spec.DbSecret.PwdFileName) == 0 { + validationErr = append(validationErr, + field.Invalid(field.NewPath("spec").Child("DbSecret").Child("PwdFileName"), r.Spec.DbSecret.PwdFileName, + "Password file name cannot be set empty")) + } + if strings.ToLower(r.Spec.DbSecret.EncryptionType) != "base64" { + if strings.ToLower(r.Spec.DbSecret.KeyFileName) == "" { + validationErr = append(validationErr, + field.Invalid(field.NewPath("spec").Child("DbSecret").Child("KeyFileName"), r.Spec.DbSecret.KeyFileName, + "Key file name cannot be empty")) + } + } + + /** + if len(r.Spec.DbSecret.PwdFileMountLocation) == 0 { + validationErr = append(validationErr, + field.Invalid(field.NewPath("spec").Child("DbSecret").Child("PwdFileMountLocation"), r.Spec.DbSecret.PwdFileMountLocation, + "Password file mount location cannot be empty")) + } + + if len(r.Spec.DbSecret.KeyFileMountLocation) == 0 { + validationErr = append(validationErr, + field.Invalid(field.NewPath("spec").Child("DbSecret").Child("KeyFileMountLocation"), r.Spec.DbSecret.KeyFileMountLocation, + "KeyFileMountLocation file mount location cannot be empty")) + } + **/ + } + + if r.Spec.IsTdeWallet == "enable" { + if (len(r.Spec.FssStorageClass) == 0) && (len(r.Spec.TdeWalletPvc) == 0) { + validationErr = append(validationErr, + field.Invalid(field.NewPath("spec").Child("FssStorageClass"), r.Spec.FssStorageClass, + "FssStorageClass or TdeWalletPvc cannot be set empty if isTdeWallet set to true")) + + validationErr = append(validationErr, + field.Invalid(field.NewPath("spec").Child("TdeWalletPvc"), r.Spec.TdeWalletPvc, + "FssStorageClass or TdeWalletPvc cannot be set empty if isTdeWallet set to true")) + } + } + + if r.Spec.IsTdeWallet != "" { + if (strings.ToLower(strings.TrimSpace(r.Spec.IsTdeWallet)) != "enable") && (strings.ToLower(strings.TrimSpace(r.Spec.IsTdeWallet)) != "disable") { + validationErr = append(validationErr, + field.Invalid(field.NewPath("spec").Child("isTdeWallet"), r.Spec.IsTdeWallet, + "isTdeWallet can be set to only \"enable\" or \"disable\"")) + } + } + + validationErrs1 = r.validateShardIsDelete() + if validationErrs1 != nil { + validationErr = append(validationErr, validationErrs1...) + } + + validationErrs1 = r.validateFreeEdition() + if validationErrs1 != nil { + validationErr = append(validationErr, validationErrs1...) + } + + // TODO(user): fill in your validation logic upon object creation. + if len(validationErr) == 0 { + return nil, nil + } + + return nil, apierrors.NewInvalid( + schema.GroupKind{Group: "database.oracle.com", Kind: "ShardingDatabase"}, + r.Name, validationErr) +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *ShardingDatabase) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { + shardingdatabaselog.Info("validate update", "name", r.Name) + + // TODO(user): fill in your validation logic upon object update. + return nil, nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *ShardingDatabase) ValidateDelete() (admission.Warnings, error) { + shardingdatabaselog.Info("validate delete", "name", r.Name) + + // TODO(user): fill in your validation logic upon object deletion. + return nil, nil +} + +// ###### Vlaidation Block ################# + +func (r *ShardingDatabase) validateShardIsDelete() field.ErrorList { + + var validationErrs field.ErrorList + + for pindex := range r.Spec.Shard { + if (strings.ToLower(strings.TrimSpace(r.Spec.Shard[pindex].IsDelete)) != "enable") && (strings.ToLower(strings.TrimSpace(r.Spec.Shard[pindex].IsDelete)) != "disable") && (strings.ToLower(strings.TrimSpace(r.Spec.Shard[pindex].IsDelete)) != "failed") { + validationErrs = append(validationErrs, + field.Invalid(field.NewPath("spec").Child("shard").Child("isDelete"), r.Spec.Shard[pindex].IsDelete, + "r.Spec.Shard[pindex].IsDelete can be set to only enable|disable|failed")) + } + } + + if len(validationErrs) > 0 { + return validationErrs + } + return nil +} + +func (r *ShardingDatabase) validateFreeEdition() field.ErrorList { + + var validationErrs field.ErrorList + if strings.ToLower(r.Spec.DbEdition) == "free" { + // Shard Spec Checks + for i := 0; i < len(r.Spec.Shard); i++ { + for index, variable := range r.Spec.Shard[i].EnvVars { + if variable.Name == "ORACLE_SID" { + if strings.ToLower(variable.Value) != "free" { + validationErrs = append(validationErrs, field.Invalid(field.NewPath("spec").Child("shard").Child("EnvVars"), r.Spec.Shard[i].EnvVars[index].Name, + "r.Spec.Shard[i].EnvVars[index].Name ORACLE_SID value can only be set to free")) + } + } + if variable.Name == "ORACLE_PDB" { + if strings.ToLower(variable.Value) != "freepdb" { + validationErrs = append(validationErrs, field.Invalid(field.NewPath("spec").Child("shard").Child("EnvVars"), r.Spec.Shard[i].EnvVars[index].Name, + "r.Spec.Shard[i].EnvVars[index].Name ORACLE_PDB value can only be set to freepdb")) + } + } + } + } + // Catalog Spec Checks + for i := 0; i < len(r.Spec.Catalog); i++ { + for index, variable := range r.Spec.Catalog[i].EnvVars { + if variable.Name == "ORACLE_SID" { + if strings.ToLower(variable.Value) != "free" { + validationErrs = append(validationErrs, field.Invalid(field.NewPath("spec").Child("catalog").Child("EnvVars"), r.Spec.Catalog[i].EnvVars[index].Name, + "r.Spec.Catalog[i].EnvVars[index].Name ORACLE_SID value can only be set to free")) + } + } + if variable.Name == "ORACLE_PDB" { + if strings.ToLower(variable.Value) != "freepdb" { + validationErrs = append(validationErrs, field.Invalid(field.NewPath("spec").Child("catalog").Child("EnvVars"), r.Spec.Catalog[i].EnvVars[index].Name, + "r.Spec.Catalog[i].EnvVars[index].Name ORACLE_PDB value can only be set to freepdb")) + } + } + } + } + } + + if len(validationErrs) > 0 { + return validationErrs + } + return nil +} diff --git a/apis/database/v1alpha1/singleinstancedatabase_types.go b/apis/database/v1alpha1/singleinstancedatabase_types.go index 81290735..7c6c1ea5 100644 --- a/apis/database/v1alpha1/singleinstancedatabase_types.go +++ b/apis/database/v1alpha1/singleinstancedatabase_types.go @@ -64,16 +64,17 @@ type SingleInstanceDatabaseSpec struct { ListenerPort int `json:"listenerPort,omitempty"` TcpsListenerPort int `json:"tcpsListenerPort,omitempty"` ServiceAnnotations map[string]string `json:"serviceAnnotations,omitempty"` - FlashBack bool `json:"flashBack,omitempty"` - ArchiveLog bool `json:"archiveLog,omitempty"` - ForceLogging bool `json:"forceLog,omitempty"` + FlashBack *bool `json:"flashBack,omitempty"` + ArchiveLog *bool `json:"archiveLog,omitempty"` + ForceLogging *bool `json:"forceLog,omitempty"` EnableTCPS bool `json:"enableTCPS,omitempty"` TcpsCertRenewInterval string `json:"tcpsCertRenewInterval,omitempty"` + TcpsTlsSecret string `json:"tcpsTlsSecret,omitempty"` DgBrokerConfigured bool `json:"dgBrokerConfigured,omitempty"` - CloneFrom string `json:"cloneFrom,omitempty"` - PrimaryDatabaseRef string `json:"primaryDatabaseRef,omitempty"` - CreateAsStandby bool `json:"createAsStandby,omitempty"` + PrimaryDatabaseRef string `json:"primaryDatabaseRef,omitempty"` + // +kubebuilder:validation:Enum=primary;standby;clone + CreateAs string `json:"createAs,omitempty"` ReadinessCheckPeriod int `json:"readinessCheckPeriod,omitempty"` ServiceAccountName string `json:"serviceAccountName,omitempty"` @@ -84,7 +85,18 @@ type SingleInstanceDatabaseSpec struct { AdminPassword SingleInstanceDatabaseAdminPassword `json:"adminPassword,omitempty"` Image SingleInstanceDatabaseImage `json:"image"` Persistence SingleInstanceDatabasePersistence `json:"persistence,omitempty"` - InitParams SingleInstanceDatabaseInitParams `json:"initParams,omitempty"` + InitParams *SingleInstanceDatabaseInitParams `json:"initParams,omitempty"` + Resources SingleInstanceDatabaseResources `json:"resources,omitempty"` +} + +type SingleInstanceDatabaseResource struct { + Cpu string `json:"cpu,omitempty"` + Memory string `json:"memory,omitempty"` +} + +type SingleInstanceDatabaseResources struct { + Requests *SingleInstanceDatabaseResource `json:"requests,omitempty"` + Limits *SingleInstanceDatabaseResource `json:"limits,omitempty"` } // SingleInstanceDatabasePersistence defines the storage size and class for PVC @@ -93,8 +105,10 @@ type SingleInstanceDatabasePersistence struct { StorageClass string `json:"storageClass,omitempty"` // +kubebuilder:validation:Enum=ReadWriteOnce;ReadWriteMany AccessMode string `json:"accessMode,omitempty"` - VolumeName string `json:"volumeName,omitempty"` + DatafilesVolumeName string `json:"datafilesVolumeName,omitempty"` + ScriptsVolumeName string `json:"scriptsVolumeName,omitempty"` VolumeClaimAnnotation string `json:"volumeClaimAnnotation,omitempty"` + SetWritePermissions *bool `json:"setWritePermissions,omitempty"` } // SingleInstanceDatabaseInitParams defines the Init Parameters @@ -145,7 +159,7 @@ type SingleInstanceDatabaseStatus struct { Pdbname string `json:"pdbName,omitempty"` InitSgaSize int `json:"initSgaSize,omitempty"` InitPgaSize int `json:"initPgaSize,omitempty"` - CloneFrom string `json:"cloneFrom,omitempty"` + CreatedAs string `json:"createdAs,omitempty"` FlashBack string `json:"flashBack,omitempty"` ArchiveLog string `json:"archiveLog,omitempty"` ForceLogging string `json:"forceLog,omitempty"` @@ -162,6 +176,8 @@ type SingleInstanceDatabaseStatus struct { ClientWalletLoc string `json:"clientWalletLoc,omitempty"` PrimaryDatabase string `json:"primaryDatabase,omitempty"` DgBrokerConfigured bool `json:"dgBrokerConfigured,omitempty"` + // +kubebuilder:default:="" + TcpsTlsSecret string `json:"tcpsTlsSecret"` // +patchMergeKey=type // +patchStrategy=merge diff --git a/apis/database/v1alpha1/singleinstancedatabase_webhook.go b/apis/database/v1alpha1/singleinstancedatabase_webhook.go index 5425d99c..1a47207d 100644 --- a/apis/database/v1alpha1/singleinstancedatabase_webhook.go +++ b/apis/database/v1alpha1/singleinstancedatabase_webhook.go @@ -39,9 +39,9 @@ package v1alpha1 import ( - "strings" - "time" "strconv" + "strings" + "time" dbcommons "github.com/oracle/oracle-database-operator/commons/database" @@ -52,6 +52,7 @@ import ( ctrl "sigs.k8s.io/controller-runtime" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) // log is for logging in this package. @@ -74,20 +75,20 @@ func (r *SingleInstanceDatabase) Default() { singleinstancedatabaselog.Info("default", "name", r.Name) if r.Spec.LoadBalancer { - // Annotations required for a flexible load balancer on oci + // Annotations required for a flexible load balancer on oci if r.Spec.ServiceAnnotations == nil { - r.Spec.ServiceAnnotations= make(map[string]string) + r.Spec.ServiceAnnotations = make(map[string]string) } _, ok := r.Spec.ServiceAnnotations["service.beta.kubernetes.io/oci-load-balancer-shape"] - if(!ok) { + if !ok { r.Spec.ServiceAnnotations["service.beta.kubernetes.io/oci-load-balancer-shape"] = "flexible" } - _,ok = r.Spec.ServiceAnnotations["service.beta.kubernetes.io/oci-load-balancer-shape-flex-min"] - if(!ok) { + _, ok = r.Spec.ServiceAnnotations["service.beta.kubernetes.io/oci-load-balancer-shape-flex-min"] + if !ok { r.Spec.ServiceAnnotations["service.beta.kubernetes.io/oci-load-balancer-shape-flex-min"] = "10" } - _,ok = r.Spec.ServiceAnnotations["service.beta.kubernetes.io/oci-load-balancer-shape-flex-max"] - if(!ok) { + _, ok = r.Spec.ServiceAnnotations["service.beta.kubernetes.io/oci-load-balancer-shape-flex-max"] + if !ok { r.Spec.ServiceAnnotations["service.beta.kubernetes.io/oci-load-balancer-shape-flex-max"] = "100" } } @@ -98,11 +99,15 @@ func (r *SingleInstanceDatabase) Default() { } if r.Spec.Edition == "" { - if r.Spec.CloneFrom == "" && !r.Spec.Image.PrebuiltDB { + if r.Spec.CreateAs == "clone" && !r.Spec.Image.PrebuiltDB { r.Spec.Edition = "enterprise" } } + if r.Spec.CreateAs == "" { + r.Spec.CreateAs = "primary" + } + if r.Spec.Sid == "" { if r.Spec.Edition == "express" { r.Spec.Sid = "XE" @@ -124,14 +129,9 @@ func (r *SingleInstanceDatabase) Default() { } if r.Spec.Edition == "express" || r.Spec.Edition == "free" { - if r.Status.Replicas == 1 { - // default the replicas for XE - r.Spec.Replicas = 1 - } - } - - if r.Spec.PrimaryDatabaseRef != "" && r.Spec.CreateAsStandby { - if r.Spec.Replicas == 0 { + // Allow zero replicas as a means to bounce the DB + if r.Status.Replicas == 1 && r.Spec.Replicas > 1 { + // If not zero, default the replicas to 1 r.Spec.Replicas = 1 } } @@ -143,13 +143,22 @@ func (r *SingleInstanceDatabase) Default() { var _ webhook.Validator = &SingleInstanceDatabase{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (r *SingleInstanceDatabase) ValidateCreate() error { +func (r *SingleInstanceDatabase) ValidateCreate() (admission.Warnings, error) { singleinstancedatabaselog.Info("validate create", "name", r.Name) var allErrs field.ErrorList + namespaces := dbcommons.GetWatchNamespaces() + _, containsNamespace := namespaces[r.Namespace] + // Check if the allowed namespaces maps contains the required namespace + if len(namespaces) != 0 && !containsNamespace { + allErrs = append(allErrs, + field.Invalid(field.NewPath("metadata").Child("namespace"), r.Namespace, + "Oracle database operator doesn't watch over this namespace")) + } + // Persistence spec validation if r.Spec.Persistence.Size == "" && (r.Spec.Persistence.AccessMode != "" || - r.Spec.Persistence.StorageClass != "" || r.Spec.Persistence.VolumeName != "") { + r.Spec.Persistence.StorageClass != "" || r.Spec.Persistence.DatafilesVolumeName != "") { allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("persistence").Child("size"), r.Spec.Persistence, "invalid persistence specification, specify required size")) @@ -168,6 +177,40 @@ func (r *SingleInstanceDatabase) ValidateCreate() error { } } + if r.Spec.CreateAs == "standby" { + if r.Spec.ArchiveLog != nil { + allErrs = append(allErrs, + field.Invalid(field.NewPath("spec").Child("archiveLog"), + r.Spec.ArchiveLog, "archiveLog cannot be specified for standby databases")) + } + if r.Spec.FlashBack != nil { + allErrs = append(allErrs, + field.Invalid(field.NewPath("spec").Child("flashBack"), + r.Spec.FlashBack, "flashBack cannot be specified for standby databases")) + } + if r.Spec.ForceLogging != nil { + allErrs = append(allErrs, + field.Invalid(field.NewPath("spec").Child("forceLog"), + r.Spec.ForceLogging, "forceLog cannot be specified for standby databases")) + } + if r.Spec.InitParams != nil { + allErrs = append(allErrs, + field.Invalid(field.NewPath("spec").Child("initParams"), + r.Spec.InitParams, "initParams cannot be specified for standby databases")) + } + if r.Spec.Persistence.ScriptsVolumeName != "" { + allErrs = append(allErrs, + field.Invalid(field.NewPath("spec").Child("persistence").Child("scriptsVolumeName"), + r.Spec.Persistence.ScriptsVolumeName, "scriptsVolumeName cannot be specified for standby databases")) + } + if r.Spec.EnableTCPS { + allErrs = append(allErrs, + field.Invalid(field.NewPath("spec").Child("enableTCPS"), + r.Spec.EnableTCPS, "enableTCPS cannot be specified for standby databases")) + } + + } + // Replica validation if r.Spec.Replicas > 1 { valMsg := "" @@ -182,17 +225,22 @@ func (r *SingleInstanceDatabase) ValidateCreate() error { field.Invalid(field.NewPath("spec").Child("replicas"), r.Spec.Replicas, valMsg)) } } - + + if (r.Spec.CreateAs == "clone" || r.Spec.CreateAs == "standby") && r.Spec.PrimaryDatabaseRef == "" { + allErrs = append(allErrs, + field.Invalid(field.NewPath("spec").Child("primaryDatabaseRef"), r.Spec.PrimaryDatabaseRef, "Primary Database reference cannot be null for a secondary database")) + } + if r.Spec.Edition == "express" || r.Spec.Edition == "free" { - if r.Spec.CloneFrom != "" { + if r.Spec.CreateAs == "clone" { allErrs = append(allErrs, - field.Invalid(field.NewPath("spec").Child("cloneFrom"), r.Spec.CloneFrom, - "Cloning not supported for " + r.Spec.Edition + " edition")) + field.Invalid(field.NewPath("spec").Child("createAs"), r.Spec.CreateAs, + "Cloning not supported for "+r.Spec.Edition+" edition")) } - if r.Spec.CreateAsStandby { + if r.Spec.CreateAs == "standby" { allErrs = append(allErrs, - field.Invalid(field.NewPath("spec").Child("createAsStandby"), r.Spec.CreateAsStandby, - "Physical Standby Database creation is not supported for " + r.Spec.Edition + " edition")) + field.Invalid(field.NewPath("spec").Child("createAs"), r.Spec.CreateAs, + "Physical Standby Database creation is not supported for "+r.Spec.Edition+" edition")) } if r.Spec.Edition == "express" && strings.ToUpper(r.Spec.Sid) != "XE" { allErrs = append(allErrs, @@ -214,25 +262,10 @@ func (r *SingleInstanceDatabase) ValidateCreate() error { field.Invalid(field.NewPath("spec").Child("pdbName"), r.Spec.Pdbname, "Free edition PDB must be FREEPDB1")) } - if r.Spec.InitParams.CpuCount != 0 { - allErrs = append(allErrs, - field.Invalid(field.NewPath("spec").Child("initParams").Child("cpuCount"), r.Spec.InitParams.CpuCount, - r.Spec.Edition + " edition does not support changing init parameter cpuCount.")) - } - if r.Spec.InitParams.Processes != 0 { + if r.Spec.InitParams != nil { allErrs = append(allErrs, - field.Invalid(field.NewPath("spec").Child("initParams").Child("processes"), r.Spec.InitParams.Processes, - r.Spec.Edition + " edition does not support changing init parameter process.")) - } - if r.Spec.InitParams.SgaTarget != 0 { - allErrs = append(allErrs, - field.Invalid(field.NewPath("spec").Child("initParams").Child("sgaTarget"), r.Spec.InitParams.SgaTarget, - r.Spec.Edition + " edition does not support changing init parameter sgaTarget.")) - } - if r.Spec.InitParams.PgaAggregateTarget != 0 { - allErrs = append(allErrs, - field.Invalid(field.NewPath("spec").Child("initParams").Child("pgaAggregateTarget"), r.Spec.InitParams.PgaAggregateTarget, - r.Spec.Edition + " edition does not support changing init parameter pgaAggregateTarget.")) + field.Invalid(field.NewPath("spec").Child("initParams"), *r.Spec.InitParams, + r.Spec.Edition+" edition does not support changing init parameters")) } } else { if r.Spec.Sid == "XE" { @@ -247,29 +280,29 @@ func (r *SingleInstanceDatabase) ValidateCreate() error { } } - if r.Spec.CloneFrom != "" { + if r.Spec.CreateAs == "clone" { if r.Spec.Image.PrebuiltDB { allErrs = append(allErrs, - field.Invalid(field.NewPath("spec").Child("cloneFrom"), r.Spec.CloneFrom, + field.Invalid(field.NewPath("spec").Child("createAs"), r.Spec.CreateAs, "cannot clone to create a prebuilt db")) - } else if strings.Contains(r.Spec.CloneFrom, ":") && strings.Contains(r.Spec.CloneFrom, "/") && r.Spec.Edition == "" { + } else if strings.Contains(r.Spec.PrimaryDatabaseRef, ":") && strings.Contains(r.Spec.PrimaryDatabaseRef, "/") && r.Spec.Edition == "" { //Edition must be passed when cloning from a source database other than same k8s cluster allErrs = append(allErrs, - field.Invalid(field.NewPath("spec").Child("edition"), r.Spec.CloneFrom, + field.Invalid(field.NewPath("spec").Child("edition"), r.Spec.CreateAs, "Edition must be passed when cloning from a source database other than same k8s cluster")) } } - if r.Status.FlashBack == "true" && r.Spec.FlashBack { - if !r.Spec.ArchiveLog { + if r.Status.FlashBack == "true" && r.Spec.FlashBack != nil && *r.Spec.FlashBack { + if r.Spec.ArchiveLog != nil && !*r.Spec.ArchiveLog { allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("archiveLog"), r.Spec.ArchiveLog, "Cannot disable Archivelog. Please disable Flashback first.")) } } - if r.Status.ArchiveLog == "false" && !r.Spec.ArchiveLog { - if r.Spec.FlashBack { + if r.Status.ArchiveLog == "false" && r.Spec.ArchiveLog != nil && !*r.Spec.ArchiveLog { + if *r.Spec.FlashBack { allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("flashBack"), r.Spec.FlashBack, "Cannot enable Flashback. Please enable Archivelog first.")) @@ -306,6 +339,7 @@ func (r *SingleInstanceDatabase) ValidateCreate() error { "listenerPort can not be 2484 as the default port for tcpsListenerPort is 2484.")) } } + if r.Spec.EnableTCPS && r.Spec.ListenerPort != 0 && r.Spec.TcpsListenerPort != 0 && r.Spec.ListenerPort == r.Spec.TcpsListenerPort { allErrs = append(allErrs, field.Invalid(field.NewPath("spec").Child("tcpsListenerPort"), r.Spec.TcpsListenerPort, @@ -328,87 +362,128 @@ func (r *SingleInstanceDatabase) ValidateCreate() error { "Please specify tcpsCertRenewInterval in the range: 24h to 8760h")) } } + + // tcpsTlsSecret validations + if !r.Spec.EnableTCPS && r.Spec.TcpsTlsSecret != "" { + allErrs = append(allErrs, + field.Forbidden(field.NewPath("spec").Child("tcpsTlsSecret"), + " is allowed only if enableTCPS is true")) + } + if r.Spec.TcpsTlsSecret != "" && r.Spec.TcpsCertRenewInterval != "" { + allErrs = append(allErrs, + field.Forbidden(field.NewPath("spec").Child("tcpsCertRenewInterval"), + " is applicable only for self signed certs")) + } + + if r.Spec.InitParams != nil { + if (r.Spec.InitParams.PgaAggregateTarget != 0 && r.Spec.InitParams.SgaTarget == 0) || (r.Spec.InitParams.PgaAggregateTarget == 0 && r.Spec.InitParams.SgaTarget != 0) { + allErrs = append(allErrs, + field.Invalid(field.NewPath("spec").Child("initParams"), + r.Spec.InitParams, "initParams value invalid : Provide values for both pgaAggregateTarget and SgaTarget")) + } + } + if len(allErrs) == 0 { - return nil + return nil, nil } - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( schema.GroupKind{Group: "database.oracle.com", Kind: "SingleInstanceDatabase"}, r.Name, allErrs) } // ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (r *SingleInstanceDatabase) ValidateUpdate(oldRuntimeObject runtime.Object) error { +func (r *SingleInstanceDatabase) ValidateUpdate(oldRuntimeObject runtime.Object) (admission.Warnings, error) { singleinstancedatabaselog.Info("validate update", "name", r.Name) var allErrs field.ErrorList // check creation validations first - err := r.ValidateCreate() + warnings, err := r.ValidateCreate() if err != nil { - return err + return warnings, err } // Validate Deletion if r.GetDeletionTimestamp() != nil { - err := r.ValidateDelete() + warnings, err := r.ValidateDelete() if err != nil { - return err + return warnings, err } } // Now check for updation errors old, ok := oldRuntimeObject.(*SingleInstanceDatabase) if !ok { - return nil + return nil, nil + } + + if old.Status.CreatedAs == "clone" { + if r.Spec.Edition != "" && old.Status.Edition != "" && !strings.EqualFold(old.Status.Edition, r.Spec.Edition) { + allErrs = append(allErrs, + field.Forbidden(field.NewPath("spec").Child("edition"), "Edition of a cloned singleinstancedatabase cannot be changed post creation")) + } + + if !strings.EqualFold(old.Status.PrimaryDatabase, r.Spec.PrimaryDatabaseRef) { + allErrs = append(allErrs, + field.Forbidden(field.NewPath("spec").Child("primaryDatabaseRef"), "Primary database of a cloned singleinstancedatabase cannot be changed post creation")) + } } - if (old.Status.Role != dbcommons.ValueUnavailable && old.Status.Role != "PRIMARY") { + if old.Status.Role != dbcommons.ValueUnavailable && old.Status.Role != "PRIMARY" { // Restriciting Patching of secondary databases archiveLog, forceLog, flashBack statusArchiveLog, _ := strconv.ParseBool(old.Status.ArchiveLog) - if statusArchiveLog != r.Spec.ArchiveLog { + if r.Spec.ArchiveLog != nil && (statusArchiveLog != *r.Spec.ArchiveLog) { allErrs = append(allErrs, field.Forbidden(field.NewPath("spec").Child("archiveLog"), "cannot be changed")) } statusFlashBack, _ := strconv.ParseBool(old.Status.FlashBack) - if statusFlashBack != r.Spec.FlashBack { + if r.Spec.FlashBack != nil && (statusFlashBack != *r.Spec.FlashBack) { allErrs = append(allErrs, field.Forbidden(field.NewPath("spec").Child("flashBack"), "cannot be changed")) } statusForceLogging, _ := strconv.ParseBool(old.Status.ForceLogging) - if statusForceLogging != r.Spec.ForceLogging { + if r.Spec.ForceLogging != nil && (statusForceLogging != *r.Spec.ForceLogging) { allErrs = append(allErrs, field.Forbidden(field.NewPath("spec").Child("forceLog"), "cannot be changed")) } + // Restriciting Patching of secondary databases InitParams - if old.Status.InitParams.SgaTarget != r.Spec.InitParams.SgaTarget { - allErrs = append(allErrs, - field.Forbidden(field.NewPath("spec").Child("InitParams").Child("sgaTarget"), "cannot be changed")) + if r.Spec.InitParams != nil { + if old.Status.InitParams.SgaTarget != r.Spec.InitParams.SgaTarget { + allErrs = append(allErrs, + field.Forbidden(field.NewPath("spec").Child("initParams").Child("sgaTarget"), "cannot be changed")) + } + if old.Status.InitParams.PgaAggregateTarget != r.Spec.InitParams.PgaAggregateTarget { + allErrs = append(allErrs, + field.Forbidden(field.NewPath("spec").Child("initParams").Child("pgaAggregateTarget"), "cannot be changed")) + } + if old.Status.InitParams.CpuCount != r.Spec.InitParams.CpuCount { + allErrs = append(allErrs, + field.Forbidden(field.NewPath("spec").Child("initParams").Child("cpuCount"), "cannot be changed")) + } + if old.Status.InitParams.Processes != r.Spec.InitParams.Processes { + allErrs = append(allErrs, + field.Forbidden(field.NewPath("spec").Child("initParams").Child("processes"), "cannot be changed")) + } } - if old.Status.InitParams.PgaAggregateTarget != r.Spec.InitParams.PgaAggregateTarget { - allErrs = append(allErrs, - field.Forbidden(field.NewPath("spec").Child("InitParams").Child("pgaAggregateTarget"), "cannot be changed")) - } - if old.Status.InitParams.CpuCount != r.Spec.InitParams.CpuCount { + } + + // if Db is in a dataguard configuration or referred by Standby databases then Restrict enabling Tcps on the Primary DB + if r.Spec.EnableTCPS { + if old.Status.DgBrokerConfigured { allErrs = append(allErrs, - field.Forbidden(field.NewPath("spec").Child("InitParams").Child("cpuCount"), "cannot be changed")) - } - if old.Status.InitParams.Processes != r.Spec.InitParams.Processes { + field.Forbidden(field.NewPath("spec").Child("enableTCPS"), "cannot enable tcps as database is in a dataguard configuration")) + } else if len(old.Status.StandbyDatabases) != 0 { allErrs = append(allErrs, - field.Forbidden(field.NewPath("spec").Child("InitParams").Child("processes"), "cannot be changed")) + field.Forbidden(field.NewPath("spec").Child("enableTCPS"), "cannot enable tcps as database is referred by one or more standby databases")) } } - // if Db is in a dataguard configuration. Restrict enabling Tcps on the Primary DB - if old.Status.DgBrokerConfigured && r.Spec.EnableTCPS { - allErrs = append(allErrs, - field.Forbidden(field.NewPath("spec").Child("enableTCPS"), "cannot enable tcps as database is in a dataguard configuration")) - } - if old.Status.DatafilesCreated == "true" && (old.Status.PrebuiltDB != r.Spec.Image.PrebuiltDB) { allErrs = append(allErrs, field.Forbidden(field.NewPath("spec").Child("image").Child("prebuiltDB"), "cannot be changed")) } - if r.Spec.CloneFrom == "" && old.Status.Edition != "" && !strings.EqualFold(old.Status.Edition, r.Spec.Edition) { + if r.Spec.Edition != "" && old.Status.Edition != "" && !strings.EqualFold(old.Status.Edition, r.Spec.Edition) { allErrs = append(allErrs, field.Forbidden(field.NewPath("spec").Child("edition"), "cannot be changed")) } @@ -424,27 +499,27 @@ func (r *SingleInstanceDatabase) ValidateUpdate(oldRuntimeObject runtime.Object) allErrs = append(allErrs, field.Forbidden(field.NewPath("spec").Child("pdbname"), "cannot be changed")) } - if old.Status.CloneFrom != "" && - (old.Status.CloneFrom == dbcommons.NoCloneRef && r.Spec.CloneFrom != "" || - old.Status.CloneFrom != dbcommons.NoCloneRef && old.Status.CloneFrom != r.Spec.CloneFrom) { + if old.Status.CreatedAs == "clone" && + (old.Status.PrimaryDatabase == dbcommons.ValueUnavailable && r.Spec.PrimaryDatabaseRef != "" || + old.Status.PrimaryDatabase != dbcommons.ValueUnavailable && old.Status.PrimaryDatabase != r.Spec.PrimaryDatabaseRef) { allErrs = append(allErrs, - field.Forbidden(field.NewPath("spec").Child("cloneFrom"), "cannot be changed")) + field.Forbidden(field.NewPath("spec").Child("primaryDatabaseRef"), "cannot be changed")) } if old.Status.OrdsReference != "" && r.Status.Persistence != r.Spec.Persistence { allErrs = append(allErrs, field.Forbidden(field.NewPath("spec").Child("persistence"), "uninstall ORDS to change Persistence")) } if len(allErrs) == 0 { - return nil + return nil, nil } - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( schema.GroupKind{Group: "database.oracle.com", Kind: "SingleInstanceDatabase"}, r.Name, allErrs) } // ValidateDelete implements webhook.Validator so a webhook will be registered for the type -func (r *SingleInstanceDatabase) ValidateDelete() error { +func (r *SingleInstanceDatabase) ValidateDelete() (admission.Warnings, error) { singleinstancedatabaselog.Info("validate delete", "name", r.Name) var allErrs field.ErrorList if r.Status.OrdsReference != "" { @@ -452,9 +527,9 @@ func (r *SingleInstanceDatabase) ValidateDelete() error { field.Forbidden(field.NewPath("status").Child("ordsReference"), "delete "+r.Status.OrdsReference+" to cleanup this SIDB")) } if len(allErrs) == 0 { - return nil + return nil, nil } - return apierrors.NewInvalid( + return nil, apierrors.NewInvalid( schema.GroupKind{Group: "database.oracle.com", Kind: "SingleInstanceDatabase"}, r.Name, allErrs) } diff --git a/apis/database/v1alpha1/webhook_suite_test.go b/apis/database/v1alpha1/webhook_suite_test.go index 343f279c..e28925e6 100644 --- a/apis/database/v1alpha1/webhook_suite_test.go +++ b/apis/database/v1alpha1/webhook_suite_test.go @@ -61,6 +61,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/envtest" logf "sigs.k8s.io/controller-runtime/pkg/log" "sigs.k8s.io/controller-runtime/pkg/log/zap" + metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/webhook" ) // To avoid dot import @@ -135,12 +137,16 @@ var _ = BeforeSuite(func() { // start webhook server using Manager webhookInstallOptions := &testEnv.WebhookInstallOptions mgr, err := ctrl.NewManager(cfg, ctrl.Options{ - Scheme: scheme, - Host: webhookInstallOptions.LocalServingHost, - Port: webhookInstallOptions.LocalServingPort, - CertDir: webhookInstallOptions.LocalServingCertDir, - LeaderElection: false, - MetricsBindAddress: "0", + Scheme: scheme, + WebhookServer: webhook.NewServer(webhook.Options{ + Port: webhookInstallOptions.LocalServingPort, + Host: webhookInstallOptions.LocalServingHost, + CertDir: webhookInstallOptions.LocalServingCertDir, + }), + LeaderElection: false, + Metrics: metricsserver.Options{ + BindAddress: "0", + }, }) Expect(err).NotTo(HaveOccurred()) diff --git a/apis/database/v1alpha1/zz_generated.deepcopy.go b/apis/database/v1alpha1/zz_generated.deepcopy.go index b6601b6b..10b34ca7 100644 --- a/apis/database/v1alpha1/zz_generated.deepcopy.go +++ b/apis/database/v1alpha1/zz_generated.deepcopy.go @@ -288,6 +288,16 @@ func (in *AutonomousDatabaseBackupSpec) DeepCopyInto(out *AutonomousDatabaseBack *out = new(string) **out = **in } + if in.IsLongTermBackup != nil { + in, out := &in.IsLongTermBackup, &out.IsLongTermBackup + *out = new(bool) + **out = **in + } + if in.RetentionPeriodInDays != nil { + in, out := &in.RetentionPeriodInDays, &out.RetentionPeriodInDays + *out = new(int) + **out = **in + } in.OCIConfig.DeepCopyInto(&out.OCIConfig) } @@ -543,6 +553,13 @@ func (in *AutonomousDatabaseStatus) DeepCopyInto(out *AutonomousDatabaseStatus) (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AutonomousDatabaseStatus. @@ -962,6 +979,13 @@ func (in *DataguardBrokerSpec) DeepCopyInto(out *DataguardBrokerSpec) { *out = make([]string, len(*in)) copy(*out, *in) } + if in.ServiceAnnotations != nil { + in, out := &in.ServiceAnnotations, &out.ServiceAnnotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } if in.NodeSelector != nil { in, out := &in.NodeSelector, &out.NodeSelector *out = make(map[string]string, len(*in)) @@ -1245,6 +1269,66 @@ func (in *EnvironmentVariable) DeepCopy() *EnvironmentVariable { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GsmServiceSpec) DeepCopyInto(out *GsmServiceSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GsmServiceSpec. +func (in *GsmServiceSpec) DeepCopy() *GsmServiceSpec { + if in == nil { + return nil + } + out := new(GsmServiceSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GsmShardDetails) DeepCopyInto(out *GsmShardDetails) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GsmShardDetails. +func (in *GsmShardDetails) DeepCopy() *GsmShardDetails { + if in == nil { + return nil + } + out := new(GsmShardDetails) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GsmShardGroupSpec) DeepCopyInto(out *GsmShardGroupSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GsmShardGroupSpec. +func (in *GsmShardGroupSpec) DeepCopy() *GsmShardGroupSpec { + if in == nil { + return nil + } + out := new(GsmShardGroupSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GsmShardSpaceSpec) DeepCopyInto(out *GsmShardSpaceSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GsmShardSpaceSpec. +func (in *GsmShardSpaceSpec) DeepCopy() *GsmShardSpaceSpec { + if in == nil { + return nil + } + out := new(GsmShardSpaceSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *GsmSpec) DeepCopyInto(out *GsmSpec) { *out = *in @@ -1838,6 +1922,8 @@ func (in *PDBSpec) DeepCopyInto(out *PDBSpec) { out.PDBTlsCat = in.PDBTlsCat out.AdminName = in.AdminName out.AdminPwd = in.AdminPwd + out.WebServerUsr = in.WebServerUsr + out.WebServerPwd = in.WebServerPwd if in.ReuseTempFile != nil { in, out := &in.ReuseTempFile, &out.ReuseTempFile *out = new(bool) @@ -2027,6 +2113,21 @@ func (in *PrivateEndpointSpec) DeepCopy() *PrivateEndpointSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretDetails) DeepCopyInto(out *SecretDetails) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretDetails. +func (in *SecretDetails) DeepCopy() *SecretDetails { + if in == nil { + return nil + } + out := new(SecretDetails) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ShardSpec) DeepCopyInto(out *ShardSpec) { *out = *in @@ -2166,6 +2267,31 @@ func (in *ShardingDatabaseSpec) DeepCopyInto(out *ShardingDatabaseSpec) { *out = make([]PortMapping, len(*in)) copy(*out, *in) } + if in.GsmShardSpace != nil { + in, out := &in.GsmShardSpace, &out.GsmShardSpace + *out = make([]GsmShardSpaceSpec, len(*in)) + copy(*out, *in) + } + if in.GsmShardGroup != nil { + in, out := &in.GsmShardGroup, &out.GsmShardGroup + *out = make([]GsmShardGroupSpec, len(*in)) + copy(*out, *in) + } + if in.ShardRegion != nil { + in, out := &in.ShardRegion, &out.ShardRegion + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.GsmService != nil { + in, out := &in.GsmService, &out.GsmService + *out = make([]GsmServiceSpec, len(*in)) + copy(*out, *in) + } + if in.DbSecret != nil { + in, out := &in.DbSecret, &out.DbSecret + *out = new(SecretDetails) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ShardingDatabaseSpec. @@ -2327,6 +2453,11 @@ func (in *SingleInstanceDatabaseList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SingleInstanceDatabasePersistence) DeepCopyInto(out *SingleInstanceDatabasePersistence) { *out = *in + if in.SetWritePermissions != nil { + in, out := &in.SetWritePermissions, &out.SetWritePermissions + *out = new(bool) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SingleInstanceDatabasePersistence. @@ -2339,6 +2470,46 @@ func (in *SingleInstanceDatabasePersistence) DeepCopy() *SingleInstanceDatabaseP return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SingleInstanceDatabaseResource) DeepCopyInto(out *SingleInstanceDatabaseResource) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SingleInstanceDatabaseResource. +func (in *SingleInstanceDatabaseResource) DeepCopy() *SingleInstanceDatabaseResource { + if in == nil { + return nil + } + out := new(SingleInstanceDatabaseResource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SingleInstanceDatabaseResources) DeepCopyInto(out *SingleInstanceDatabaseResources) { + *out = *in + if in.Requests != nil { + in, out := &in.Requests, &out.Requests + *out = new(SingleInstanceDatabaseResource) + **out = **in + } + if in.Limits != nil { + in, out := &in.Limits, &out.Limits + *out = new(SingleInstanceDatabaseResource) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SingleInstanceDatabaseResources. +func (in *SingleInstanceDatabaseResources) DeepCopy() *SingleInstanceDatabaseResources { + if in == nil { + return nil + } + out := new(SingleInstanceDatabaseResources) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *SingleInstanceDatabaseSpec) DeepCopyInto(out *SingleInstanceDatabaseSpec) { *out = *in @@ -2349,6 +2520,21 @@ func (in *SingleInstanceDatabaseSpec) DeepCopyInto(out *SingleInstanceDatabaseSp (*out)[key] = val } } + if in.FlashBack != nil { + in, out := &in.FlashBack, &out.FlashBack + *out = new(bool) + **out = **in + } + if in.ArchiveLog != nil { + in, out := &in.ArchiveLog, &out.ArchiveLog + *out = new(bool) + **out = **in + } + if in.ForceLogging != nil { + in, out := &in.ForceLogging, &out.ForceLogging + *out = new(bool) + **out = **in + } if in.NodeSelector != nil { in, out := &in.NodeSelector, &out.NodeSelector *out = make(map[string]string, len(*in)) @@ -2358,8 +2544,13 @@ func (in *SingleInstanceDatabaseSpec) DeepCopyInto(out *SingleInstanceDatabaseSp } in.AdminPassword.DeepCopyInto(&out.AdminPassword) out.Image = in.Image - out.Persistence = in.Persistence - out.InitParams = in.InitParams + in.Persistence.DeepCopyInto(&out.Persistence) + if in.InitParams != nil { + in, out := &in.InitParams, &out.InitParams + *out = new(SingleInstanceDatabaseInitParams) + **out = **in + } + in.Resources.DeepCopyInto(&out.Resources) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SingleInstanceDatabaseSpec. @@ -2395,7 +2586,7 @@ func (in *SingleInstanceDatabaseStatus) DeepCopyInto(out *SingleInstanceDatabase } } out.InitParams = in.InitParams - out.Persistence = in.Persistence + in.Persistence.DeepCopyInto(&out.Persistence) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SingleInstanceDatabaseStatus. @@ -2546,6 +2737,22 @@ func (in *WebServerPassword) DeepCopy() *WebServerPassword { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WebServerPasswordPDB) DeepCopyInto(out *WebServerPasswordPDB) { + *out = *in + out.Secret = in.Secret +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebServerPasswordPDB. +func (in *WebServerPasswordPDB) DeepCopy() *WebServerPasswordPDB { + if in == nil { + return nil + } + out := new(WebServerPasswordPDB) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *WebServerUser) DeepCopyInto(out *WebServerUser) { *out = *in @@ -2561,3 +2768,19 @@ func (in *WebServerUser) DeepCopy() *WebServerUser { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WebServerUserPDB) DeepCopyInto(out *WebServerUserPDB) { + *out = *in + out.Secret = in.Secret +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WebServerUserPDB. +func (in *WebServerUserPDB) DeepCopy() *WebServerUserPDB { + if in == nil { + return nil + } + out := new(WebServerUserPDB) + in.DeepCopyInto(out) + return out +} diff --git a/apis/observability/v1alpha1/databaseobserver_types.go b/apis/observability/v1alpha1/databaseobserver_types.go new file mode 100644 index 00000000..97827d17 --- /dev/null +++ b/apis/observability/v1alpha1/databaseobserver_types.go @@ -0,0 +1,144 @@ +/* +** Copyright (c) 2022 Oracle and/or its affiliates. +** +** The Universal Permissive License (UPL), Version 1.0 +** +** Subject to the condition set forth below, permission is hereby granted to any +** person obtaining a copy of this software, associated documentation and/or data +** (collectively the "Software"), free of charge and under any and all copyright +** rights in the Software, and any and all patent rights owned or freely +** licensable by each licensor hereunder covering either (i) the unmodified +** Software as contributed to or provided by such licensor, or (ii) the Larger +** Works (as defined below), to deal in both +** +** (a) the Software, and +** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +** one is included with the Software (each a "Larger Work" to which the Software +** is contributed by such licensors), +** +** without restriction, including without limitation the rights to copy, create +** derivative works of, display, perform, and distribute the Software and make, +** use, sell, offer for sale, import, export, have made, and have sold the +** Software and the Larger Work(s), and to sublicense the foregoing rights on +** either these or other terms. +** +** This license is subject to the following condition: +** The above copyright notice and either this complete permission notice or at +** a minimum a reference to the UPL must be included in all copies or +** substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +** SOFTWARE. + */ + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +type StatusEnum string + +// DatabaseObserverSpec defines the desired state of DatabaseObserver +type DatabaseObserverSpec struct { + Database DatabaseObserverDatabase `json:"database,omitempty"` + Exporter DatabaseObserverExporterConfig `json:"exporter,omitempty"` + Prometheus PrometheusConfig `json:"prometheus,omitempty"` + OCIConfig OCIConfigSpec `json:"ociConfig,omitempty"` + Replicas int32 `json:"replicas,omitempty"` +} + +// DatabaseObserverDatabase defines the database details used for DatabaseObserver +type DatabaseObserverDatabase struct { + DBUser DBSecret `json:"dbUser,omitempty"` + DBPassword DBSecretWithVault `json:"dbPassword,omitempty"` + DBWallet DBSecret `json:"dbWallet,omitempty"` + DBConnectionString DBSecret `json:"dbConnectionString,omitempty"` +} + +// DatabaseObserverExporterConfig defines the configuration details related to the exporters of DatabaseObserver +type DatabaseObserverExporterConfig struct { + ExporterImage string `json:"image,omitempty"` + ExporterConfig DatabaseObserverConfigMap `json:"configuration,omitempty"` + Service DatabaseObserverService `json:"service,omitempty"` +} + +// DatabaseObserverService defines the exporter service component of DatabaseObserver +type DatabaseObserverService struct { + Port int32 `json:"port,omitempty"` +} + +// PrometheusConfig defines the generated resources for Prometheus +type PrometheusConfig struct { + Labels map[string]string `json:"labels,omitempty"` + Port string `json:"port,omitempty"` +} + +type DBSecret struct { + Key string `json:"key,omitempty"` + SecretName string `json:"secret,omitempty"` +} + +type DBSecretWithVault struct { + Key string `json:"key,omitempty"` + SecretName string `json:"secret,omitempty"` + VaultOCID string `json:"vaultOCID,omitempty"` + VaultSecretName string `json:"vaultSecretName,omitempty"` +} + +type DatabaseObserverConfigMap struct { + Configmap ConfigMapDetails `json:"configmap,omitempty"` +} + +// ConfigMapDetails defines the configmap name +type ConfigMapDetails struct { + Key string `json:"key,omitempty"` + Name string `json:"configmapName,omitempty"` +} + +type OCIConfigSpec struct { + ConfigMapName string `json:"configMapName,omitempty"` + SecretName string `json:"secretName,omitempty"` +} + +// DatabaseObserverStatus defines the observed state of DatabaseObserver +type DatabaseObserverStatus struct { + // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster + // Important: Run "make" to regenerate code after modifying this file + Conditions []metav1.Condition `json:"conditions"` + Status string `json:"status,omitempty"` + ExporterConfig string `json:"exporterConfig"` + Replicas int `json:"replicas,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status + +// DatabaseObserver is the Schema for the databaseobservers API +// +kubebuilder:printcolumn:JSONPath=".status.exporterConfig",name="ExporterConfig",type=string +// +kubebuilder:printcolumn:JSONPath=".status.status",name="Status",type=string +type DatabaseObserver struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec DatabaseObserverSpec `json:"spec,omitempty"` + Status DatabaseObserverStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// DatabaseObserverList contains a list of DatabaseObserver +type DatabaseObserverList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []DatabaseObserver `json:"items"` +} + +func init() { + SchemeBuilder.Register(&DatabaseObserver{}, &DatabaseObserverList{}) +} diff --git a/apis/observability/v1alpha1/databaseobserver_webhook.go b/apis/observability/v1alpha1/databaseobserver_webhook.go new file mode 100644 index 00000000..2ab9b732 --- /dev/null +++ b/apis/observability/v1alpha1/databaseobserver_webhook.go @@ -0,0 +1,185 @@ +/* +** Copyright (c) 2022 Oracle and/or its affiliates. +** +** The Universal Permissive License (UPL), Version 1.0 +** +** Subject to the condition set forth below, permission is hereby granted to any +** person obtaining a copy of this software, associated documentation and/or data +** (collectively the "Software"), free of charge and under any and all copyright +** rights in the Software, and any and all patent rights owned or freely +** licensable by each licensor hereunder covering either (i) the unmodified +** Software as contributed to or provided by such licensor, or (ii) the Larger +** Works (as defined below), to deal in both +** +** (a) the Software, and +** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +** one is included with the Software (each a "Larger Work" to which the Software +** is contributed by such licensors), +** +** without restriction, including without limitation the rights to copy, create +** derivative works of, display, perform, and distribute the Software and make, +** use, sell, offer for sale, import, export, have made, and have sold the +** Software and the Larger Work(s), and to sublicense the foregoing rights on +** either these or other terms. +** +** This license is subject to the following condition: +** The above copyright notice and either this complete permission notice or at +** a minimum a reference to the UPL must be included in all copies or +** substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +** SOFTWARE. + */ + +package v1alpha1 + +import ( + dbcommons "github.com/oracle/oracle-database-operator/commons/database" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/validation/field" + ctrl "sigs.k8s.io/controller-runtime" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + "strings" +) + +// log is for logging in this package. +var databaseobserverlog = logf.Log.WithName("databaseobserver-resource") + +const ( + AllowedExporterImage = "container-registry.oracle.com/database/observability-exporter" + ErrorSpecValidationMissingConnString = "a required field for database connection string secret is missing or does not have a value" + ErrorSpecValidationMissingDBUser = "a required field for database user secret is missing or does not have a value" + ErrorSpecValidationMissingDBVaultField = "a field for the OCI vault has a value but the other required field is missing or does not have a value" + ErrorSpecValidationMissingOCIConfig = "a field(s) for the OCI Config is missing or does not have a value when fields for the OCI vault has values" + ErrorSpecValidationMissingDBPasswordSecret = "a required field for the database password secret is missing or does not have a value" + ErrorSpecExporterImageNotAllowed = "a different exporter image was found, only official database exporter container images are currently supported" +) + +func (r *DatabaseObserver) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(r). + Complete() +} + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! + +//+kubebuilder:webhook:path=/mutate-observability-oracle-com-v1alpha1-databaseobserver,mutating=true,sideEffects=none,failurePolicy=fail,groups=observability.oracle.com,resources=databaseobservers,verbs=create;update,versions=v1alpha1,name=mdatabaseobserver.kb.io,admissionReviewVersions=v1 + +var _ webhook.Defaulter = &DatabaseObserver{} + +// Default implements webhook.Defaulter so a webhook will be registered for the type +func (r *DatabaseObserver) Default() { + databaseobserverlog.Info("default", "name", r.Name) + + // TODO(user): fill in your defaulting logic. +} + +// TODO(user): change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +//+kubebuilder:webhook:verbs=create;update,path=/validate-observability-oracle-com-v1alpha1-databaseobserver,mutating=false,sideEffects=none,failurePolicy=fail,groups=observability.oracle.com,resources=databaseobservers,versions=v1alpha1,name=vdatabaseobserver.kb.io,admissionReviewVersions=v1 + +var _ webhook.Validator = &DatabaseObserver{} + +// ValidateCreate implements webhook.Validator so a webhook will be registered for the type +func (r *DatabaseObserver) ValidateCreate() (admission.Warnings, error) { + databaseobserverlog.Info("validate create", "name", r.Name) + + var e field.ErrorList + ns := dbcommons.GetWatchNamespaces() + + // Check for namespace/cluster scope access + if _, isDesiredNamespaceWithinScope := ns[r.Namespace]; !isDesiredNamespaceWithinScope && len(ns) > 0 { + e = append(e, + field.Invalid(field.NewPath("metadata").Child("namespace"), r.Namespace, + "Oracle database operator doesn't watch over this namespace")) + } + + // Check required secret for db user has value + if r.Spec.Database.DBUser.SecretName == "" { + e = append(e, + field.Invalid(field.NewPath("spec").Child("database").Child("dbUser").Child("secret"), r.Spec.Database.DBUser.SecretName, + ErrorSpecValidationMissingDBUser)) + } + + // Check required secret for db connection string has value + if r.Spec.Database.DBConnectionString.SecretName == "" { + e = append(e, + field.Invalid(field.NewPath("spec").Child("database").Child("dbConnectionString").Child("secret"), r.Spec.Database.DBConnectionString.SecretName, + ErrorSpecValidationMissingConnString)) + } + + // The other vault field must have value if one does + if (r.Spec.Database.DBPassword.VaultOCID != "" && r.Spec.Database.DBPassword.VaultSecretName == "") || + (r.Spec.Database.DBPassword.VaultSecretName != "" && r.Spec.Database.DBPassword.VaultOCID == "") { + + e = append(e, + field.Invalid(field.NewPath("spec").Child("database").Child("dbPassword"), r.Spec.Database.DBPassword, + ErrorSpecValidationMissingDBVaultField)) + } + + // if vault fields have value, ociConfig must have values + if r.Spec.Database.DBPassword.VaultOCID != "" && r.Spec.Database.DBPassword.VaultSecretName != "" && + (r.Spec.OCIConfig.SecretName == "" || r.Spec.OCIConfig.ConfigMapName == "") { + + e = append(e, + field.Invalid(field.NewPath("spec").Child("ociConfig"), r.Spec.OCIConfig, + ErrorSpecValidationMissingOCIConfig)) + } + + // If all of {DB Password Secret Name and vaultOCID+vaultSecretName} have no value, then error out + if r.Spec.Database.DBPassword.SecretName == "" && + r.Spec.Database.DBPassword.VaultOCID == "" && + r.Spec.Database.DBPassword.VaultSecretName == "" { + + e = append(e, + field.Invalid(field.NewPath("spec").Child("database").Child("dbPassword").Child("secret"), r.Spec.Database.DBPassword.SecretName, + ErrorSpecValidationMissingDBPasswordSecret)) + } + + // disallow usage of any other image than the observability-exporter + if r.Spec.Exporter.ExporterImage != "" && !strings.HasPrefix(r.Spec.Exporter.ExporterImage, AllowedExporterImage) { + e = append(e, + field.Invalid(field.NewPath("spec").Child("exporter").Child("image"), r.Spec.Exporter.ExporterImage, + ErrorSpecExporterImageNotAllowed)) + } + + // Return if any errors + if len(e) > 0 { + return nil, apierrors.NewInvalid(schema.GroupKind{Group: "observability.oracle.com", Kind: "DatabaseObserver"}, r.Name, e) + } + return nil, nil + +} + +// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type +func (r *DatabaseObserver) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { + databaseobserverlog.Info("validate update", "name", r.Name) + var e field.ErrorList + + // disallow usage of any other image than the observability-exporter + if r.Spec.Exporter.ExporterImage != "" && !strings.HasPrefix(r.Spec.Exporter.ExporterImage, AllowedExporterImage) { + e = append(e, + field.Invalid(field.NewPath("spec").Child("exporter").Child("image"), r.Spec.Exporter.ExporterImage, + ErrorSpecExporterImageNotAllowed)) + } + // Return if any errors + if len(e) > 0 { + return nil, apierrors.NewInvalid(schema.GroupKind{Group: "observability.oracle.com", Kind: "DatabaseObserver"}, r.Name, e) + } + return nil, nil +} + +// ValidateDelete implements webhook.Validator so a webhook will be registered for the type +func (r *DatabaseObserver) ValidateDelete() (admission.Warnings, error) { + databaseobserverlog.Info("validate delete", "name", r.Name) + + return nil, nil +} diff --git a/apis/observability/v1alpha1/groupversion_info.go b/apis/observability/v1alpha1/groupversion_info.go new file mode 100644 index 00000000..304840f4 --- /dev/null +++ b/apis/observability/v1alpha1/groupversion_info.go @@ -0,0 +1,58 @@ +/* +** Copyright (c) 2022 Oracle and/or its affiliates. +** +** The Universal Permissive License (UPL), Version 1.0 +** +** Subject to the condition set forth below, permission is hereby granted to any +** person obtaining a copy of this software, associated documentation and/or data +** (collectively the "Software"), free of charge and under any and all copyright +** rights in the Software, and any and all patent rights owned or freely +** licensable by each licensor hereunder covering either (i) the unmodified +** Software as contributed to or provided by such licensor, or (ii) the Larger +** Works (as defined below), to deal in both +** +** (a) the Software, and +** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +** one is included with the Software (each a "Larger Work" to which the Software +** is contributed by such licensors), +** +** without restriction, including without limitation the rights to copy, create +** derivative works of, display, perform, and distribute the Software and make, +** use, sell, offer for sale, import, export, have made, and have sold the +** Software and the Larger Work(s), and to sublicense the foregoing rights on +** either these or other terms. +** +** This license is subject to the following condition: +** The above copyright notice and either this complete permission notice or at +** a minimum a reference to the UPL must be included in all copies or +** substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +** SOFTWARE. + */ + +// Package v1alpha1 contains API Schema definitions for the observability v1alpha1 API group +// +kubebuilder:object:generate=true +// +groupName=observability.oracle.com +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "observability.oracle.com", Version: "v1alpha1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/apis/observability/v1alpha1/zz_generated.deepcopy.go b/apis/observability/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 00000000..39b438eb --- /dev/null +++ b/apis/observability/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,298 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +** Copyright (c) 2022 Oracle and/or its affiliates. +** +** The Universal Permissive License (UPL), Version 1.0 +** +** Subject to the condition set forth below, permission is hereby granted to any +** person obtaining a copy of this software, associated documentation and/or data +** (collectively the "Software"), free of charge and under any and all copyright +** rights in the Software, and any and all patent rights owned or freely +** licensable by each licensor hereunder covering either (i) the unmodified +** Software as contributed to or provided by such licensor, or (ii) the Larger +** Works (as defined below), to deal in both +** +** (a) the Software, and +** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +** one is included with the Software (each a "Larger Work" to which the Software +** is contributed by such licensors), +** +** without restriction, including without limitation the rights to copy, create +** derivative works of, display, perform, and distribute the Software and make, +** use, sell, offer for sale, import, export, have made, and have sold the +** Software and the Larger Work(s), and to sublicense the foregoing rights on +** either these or other terms. +** +** This license is subject to the following condition: +** The above copyright notice and either this complete permission notice or at +** a minimum a reference to the UPL must be included in all copies or +** substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +** SOFTWARE. + */ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ConfigMapDetails) DeepCopyInto(out *ConfigMapDetails) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConfigMapDetails. +func (in *ConfigMapDetails) DeepCopy() *ConfigMapDetails { + if in == nil { + return nil + } + out := new(ConfigMapDetails) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DBSecret) DeepCopyInto(out *DBSecret) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DBSecret. +func (in *DBSecret) DeepCopy() *DBSecret { + if in == nil { + return nil + } + out := new(DBSecret) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DBSecretWithVault) DeepCopyInto(out *DBSecretWithVault) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DBSecretWithVault. +func (in *DBSecretWithVault) DeepCopy() *DBSecretWithVault { + if in == nil { + return nil + } + out := new(DBSecretWithVault) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DatabaseObserver) DeepCopyInto(out *DatabaseObserver) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatabaseObserver. +func (in *DatabaseObserver) DeepCopy() *DatabaseObserver { + if in == nil { + return nil + } + out := new(DatabaseObserver) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DatabaseObserver) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DatabaseObserverConfigMap) DeepCopyInto(out *DatabaseObserverConfigMap) { + *out = *in + out.Configmap = in.Configmap +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatabaseObserverConfigMap. +func (in *DatabaseObserverConfigMap) DeepCopy() *DatabaseObserverConfigMap { + if in == nil { + return nil + } + out := new(DatabaseObserverConfigMap) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DatabaseObserverDatabase) DeepCopyInto(out *DatabaseObserverDatabase) { + *out = *in + out.DBUser = in.DBUser + out.DBPassword = in.DBPassword + out.DBWallet = in.DBWallet + out.DBConnectionString = in.DBConnectionString +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatabaseObserverDatabase. +func (in *DatabaseObserverDatabase) DeepCopy() *DatabaseObserverDatabase { + if in == nil { + return nil + } + out := new(DatabaseObserverDatabase) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DatabaseObserverExporterConfig) DeepCopyInto(out *DatabaseObserverExporterConfig) { + *out = *in + out.ExporterConfig = in.ExporterConfig + out.Service = in.Service +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatabaseObserverExporterConfig. +func (in *DatabaseObserverExporterConfig) DeepCopy() *DatabaseObserverExporterConfig { + if in == nil { + return nil + } + out := new(DatabaseObserverExporterConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DatabaseObserverList) DeepCopyInto(out *DatabaseObserverList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]DatabaseObserver, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatabaseObserverList. +func (in *DatabaseObserverList) DeepCopy() *DatabaseObserverList { + if in == nil { + return nil + } + out := new(DatabaseObserverList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DatabaseObserverList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DatabaseObserverService) DeepCopyInto(out *DatabaseObserverService) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatabaseObserverService. +func (in *DatabaseObserverService) DeepCopy() *DatabaseObserverService { + if in == nil { + return nil + } + out := new(DatabaseObserverService) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DatabaseObserverSpec) DeepCopyInto(out *DatabaseObserverSpec) { + *out = *in + out.Database = in.Database + out.Exporter = in.Exporter + in.Prometheus.DeepCopyInto(&out.Prometheus) + out.OCIConfig = in.OCIConfig +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatabaseObserverSpec. +func (in *DatabaseObserverSpec) DeepCopy() *DatabaseObserverSpec { + if in == nil { + return nil + } + out := new(DatabaseObserverSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DatabaseObserverStatus) DeepCopyInto(out *DatabaseObserverStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DatabaseObserverStatus. +func (in *DatabaseObserverStatus) DeepCopy() *DatabaseObserverStatus { + if in == nil { + return nil + } + out := new(DatabaseObserverStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OCIConfigSpec) DeepCopyInto(out *OCIConfigSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OCIConfigSpec. +func (in *OCIConfigSpec) DeepCopy() *OCIConfigSpec { + if in == nil { + return nil + } + out := new(OCIConfigSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PrometheusConfig) DeepCopyInto(out *PrometheusConfig) { + *out = *in + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PrometheusConfig. +func (in *PrometheusConfig) DeepCopy() *PrometheusConfig { + if in == nil { + return nil + } + out := new(PrometheusConfig) + in.DeepCopyInto(out) + return out +} diff --git a/commons/database/constants.go b/commons/database/constants.go index 33dce251..6f27750d 100644 --- a/commons/database/constants.go +++ b/commons/database/constants.go @@ -50,8 +50,6 @@ const DBA_GUID int64 = 54322 const SQLPlusCLI string = "sqlplus -s / as sysdba" -const NoCloneRef string = "Unavailable" - const GetVersionSQL string = "SELECT VERSION_FULL FROM V\\$INSTANCE;" const CheckModesSQL string = "SELECT 'log_mode:' || log_mode AS log_mode ,'flashback_on:' || flashback_on AS flashback_on ,'force_logging:' || force_logging AS force_logging FROM v\\$database;" @@ -102,6 +100,8 @@ const StandbyDatabasePrerequisitesSQL string = "ALTER SYSTEM SET db_create_file_ "\nALTER DATABASE ADD STANDBY LOGFILE THREAD 1 SIZE 200M;" + "\nALTER DATABASE ADD STANDBY LOGFILE THREAD 1 SIZE 200M;" + "\nALTER SYSTEM SET STANDBY_FILE_MANAGEMENT=AUTO;" + + "\nALTER SYSTEM SET dg_broker_config_file1='/opt/oracle/oradata/dbconfig/dr1${ORACLE_SID}.dat' scope=both;" + + "\nALTER SYSTEM SET dg_broker_config_file2='/opt/oracle/oradata/dbconfig/dr2${ORACLE_SID}.dat';" + "\nALTER SYSTEM SET dg_broker_start=TRUE;" const GetDBOpenMode string = "select open_mode from v\\$database;" @@ -212,8 +212,8 @@ const DataguardBrokerAddDBMaxAvailabilityCMD string = "ADD DATABASE ${ORACLE_SID "(CONNECT_DATA=(SERVICE_NAME=${ORACLE_SID}_DGMGRL)(INSTANCE_NAME=${ORACLE_SID})(SERVER=DEDICATED)))';" + "\nENABLE CONFIGURATION;" -const RemoveStandbyDBFromDGConfgCMD string = "DISABLE DATABASE ${ORACLE_SID};" + - "\nREMOVE DATABASE ${ORACLE_SID};" +const RemoveStandbyDBFromDGConfgCMD string = "DISABLE DATABASE ${ORACLE_SID};" + + "\nREMOVE DATABASE ${ORACLE_SID};" const DBShowConfigCMD string = "SHOW CONFIGURATION;" @@ -422,13 +422,16 @@ const InitWalletCMD string = "if [ ! -f $ORACLE_BASE/oradata/.${ORACLE_SID}${CHE const InitPrebuiltDbCMD string = "if [ ! -d /mnt/oradata/${ORACLE_SID} -a -d $ORACLE_BASE/oradata/${ORACLE_SID} ]; then cp -v $ORACLE_BASE/oradata/.${ORACLE_SID}$CHECKPOINT_FILE_EXTN /mnt/oradata && " + " cp -vr $ORACLE_BASE/oradata/${ORACLE_SID} /mnt/oradata && cp -vr $ORACLE_BASE/oradata/dbconfig /mnt/oradata; fi " -const AlterSgaPgaCpuCMD string = "echo -e \"alter system set sga_target=%dM scope=both; \n alter system set pga_aggregate_target=%dM scope=both; \n alter system set cpu_count=%d; \" | %s " - +const AlterSgaPgaCMD string = "echo -e \"alter system set sga_target=%dM scope=both; \n alter system set pga_aggregate_target=%dM scope=both; \" | %s " +const AlterCpuCountCMD string = "echo -e \"alter system set cpu_count=%d; \" | %s" const AlterProcessesCMD string = "echo -e \"alter system set processes=%d scope=spfile; \" | %s && " + CreateChkFileCMD + " && " + "echo -e \"SHUTDOWN IMMEDIATE; \n STARTUP MOUNT; \n ALTER DATABASE OPEN; \n ALTER PLUGGABLE DATABASE ALL OPEN; \n ALTER SYSTEM REGISTER;\" | %s && " + RemoveChkFileCMD -const GetInitParamsSQL string = "echo -e \"select name,display_value from v\\$parameter where name in ('sga_target','pga_aggregate_target','cpu_count','processes') order by name asc;\" | %s" +const GetInitParamsSQL string = "column name format a20;" + + "\ncolumn display_value format a20;" + + "\nset linesize 100 pagesize 50;" + + "\nselect name,display_value from v\\$parameter where name in ('sga_target','pga_aggregate_target','cpu_count','processes') order by name asc;" const UnzipApexOnSIDBPod string = "if [ -f /opt/oracle/oradata/apex-latest.zip ]; then unzip -o /opt/oracle/oradata/apex-latest.zip -d /opt/oracle/oradata/${ORACLE_SID^^}; else echo \"apex-latest.zip not found\"; fi;" @@ -506,7 +509,7 @@ const SetApexUsers string = "\numask 177" + "\numask 022" // Get Sid, Pdbname, Edition for prebuilt db -const GetSidPdbEditionCMD string = "echo $ORACLE_SID,$ORACLE_PDB,$ORACLE_EDITION,Edition;" +const GetSidPdbEditionCMD string = "echo $ORACLE_SID,$ORACLE_PDB,$ORACLE_EDITION;" // Command to enable TCPS as a formatted string. The parameter would be the port at which TCPS is enabled. const EnableTcpsCMD string = "$ORACLE_BASE/$CONFIG_TCPS_FILE" @@ -517,6 +520,12 @@ const RenewCertsCMD string = EnableTcpsCMD // Command to disable TCPS const DisableTcpsCMD string = "$ORACLE_BASE/$CONFIG_TCPS_FILE disable" +// Location of tls certs +const TlsCertsLocation string = "/run/secrets/tls_secret" + +// Check Mount in pods +const PodMountsCmd string = "awk '$2 == \"%s\" {print}' /proc/mounts" + // TCPS clientWallet update command const ClientWalletUpdate string = "sed -i -e 's/HOST.*$/HOST=%s)/g' -e 's/PORT.*$/PORT=%d)/g' ${ORACLE_BASE}/oradata/clientWallet/${ORACLE_SID}/tnsnames.ora" diff --git a/commons/database/utils.go b/commons/database/utils.go index c1ecd680..1723bc90 100644 --- a/commons/database/utils.go +++ b/commons/database/utils.go @@ -45,6 +45,8 @@ import ( "errors" "fmt" "math/rand" + "os" + "strconv" "strings" "time" "unicode" @@ -70,6 +72,8 @@ import ( var requeueY ctrl.Result = ctrl.Result{Requeue: true, RequeueAfter: 15 * time.Second} var requeueN ctrl.Result = ctrl.Result{} +var ErrNoReadyPod = errors.New("SingleInstanceDatabase has no ready pod currently") + // Filter events that trigger reconcilation func ResourceEventHandler() predicate.Predicate { return predicate.Funcs{ @@ -400,6 +404,74 @@ func CheckDBConfig(readyPod corev1.Pod, r client.Reader, config *rest.Config, return flashBackStatus, archiveLogStatus, forceLoggingStatus, requeueN } +func CheckDBInitParams(sidbReadyPod corev1.Pod, r client.Reader, config *rest.Config, + ctx context.Context, req ctrl.Request) (int, int, int, int, error) { + log := ctrllog.FromContext(ctx).WithValues("CheckDBParams", req.NamespacedName) + + if sidbReadyPod.Name == "" { + log.Info("No Pod is Ready") + // As No pod is ready now , turn on mode when pod is ready . so requeue the request + return -1, -1, -1, -1, fmt.Errorf("no pod is ready") + } + + log.Info("Check database init params") + + out, err := ExecCommand(r, config, sidbReadyPod.Name, sidbReadyPod.Namespace, "", + ctx, req, false, "bash", "-c", fmt.Sprintf("echo -e \"%s\" | sqlplus -s / as sysdba", GetInitParamsSQL)) + if err != nil { + log.Error(err, err.Error()) + return -1, -1, -1, -1, err + } + if strings.Contains(out, "no rows selected") { + return -1, -1, -1, -1, errors.New("cannot fetch values for database init params") + } + if strings.Contains(out, "ORA-") { + return -1, -1, -1, -1, fmt.Errorf("error while getting database init params\n%s", out) + } + log.Info(fmt.Sprintf("Database initParams are \n%s", out)) + initParams := strings.Split(out, "\n") + initParams = initParams[3:] + log.Info(fmt.Sprintf("%v", initParams)) + log.Info(fmt.Sprintf("length of initParams is %v", len(initParams))) + log.Info("After parsing init param are " + strings.Join(initParams, ",")) + + log.Info("Parsing cpuCount") + log.Info(strings.Fields(initParams[0])[1]) + cpu_count, err := strconv.Atoi(strings.Fields(initParams[0])[1]) + if err != nil { + return -1, -1, -1, -1, err + } + log.Info("After parsing cpuCount", "cpuCount", cpu_count) + + log.Info("Parsing pga_aggregate_target_value") + log.Info(strings.Fields(initParams[1])[1]) + pga_aggregate_target_value := strings.Fields(initParams[1])[1] + pga_aggregate_target, err := strconv.Atoi(pga_aggregate_target_value[0 : len(pga_aggregate_target_value)-1]) + if err != nil { + return -1, -1, -1, -1, err + } + log.Info("After parsing pga_aggregate_target_value", "pga_aggregate_target_value", pga_aggregate_target) + + log.Info("Parsing processes") + log.Info(strings.Fields(initParams[2])[1]) + processes, err := strconv.Atoi(strings.Fields(initParams[2])[1]) + if err != nil { + return -1, -1, -1, -1, err + } + log.Info("After parsing processes", "processes", processes) + + log.Info("parsing sga_target_value") + log.Info(strings.Fields(initParams[3])[1]) + sga_target_value := strings.Fields(initParams[3])[1] + sga_target, err := strconv.Atoi(sga_target_value[0 : len(sga_target_value)-1]) + if err != nil { + return -1, -1, -1, -1, err + } + log.Info("After parsing sgaTarget", "sgaTarget", sga_target) + + return cpu_count, pga_aggregate_target, processes, sga_target, nil +} + // CHECKS IF SID IN DATABASES SLICE , AND ITS DGROLE func IsDatabaseFound(sid string, databases []string, dgrole string) (bool, bool) { found := false @@ -458,34 +530,37 @@ func GetDatabasesInDgConfig(readyPod corev1.Pod, r client.Reader, // Returns Database version func GetDatabaseVersion(readyPod corev1.Pod, r client.Reader, - config *rest.Config, ctx context.Context, req ctrl.Request, edition string) (string, string, error) { + config *rest.Config, ctx context.Context, req ctrl.Request) (string, error) { + log := ctrllog.FromContext(ctx).WithValues("GetDatabaseVersion", req.NamespacedName) // ## FIND DATABASES PRESENT IN DG CONFIGURATION out, err := ExecCommand(r, config, readyPod.Name, readyPod.Namespace, "", ctx, req, false, "bash", "-c", fmt.Sprintf("echo -e \"%s\" | %s", GetVersionSQL, SQLPlusCLI)) if err != nil { - return "", "", err + return "", err } log.Info("GetDatabaseVersion Output") log.Info(out) - - if !strings.Contains(out, "no rows selected") && !strings.Contains(out, "ORA-") { - out1 := strings.Replace(out, " ", "_", -1) - // filtering output and storing databses in dg configuration in "databases" slice - out2 := strings.Fields(out1) - - // first 2 values in the slice will be column name(VERSION) and a seperator(--------------) . so the version would be out2[2] - version := out2[2] - return version, out, nil + if strings.Contains(out, "no rows selected") { + return "", errors.New("cannot fetch database version") + } + if strings.Contains(out, "ORA-") { + return "", errors.New("error while trying to get the database version " + out) } - return "", out, errors.New("database version is nil") + out1 := strings.Replace(out, " ", "_", -1) + // filtering output and storing databses in dg configuration in "databases" slice + out2 := strings.Fields(out1) + // first 2 values in the slice will be column name(VERSION) and a seperator(--------------) . so the version would be out2[2] + version := out2[2] + return version, nil } // Fetch role by quering the DB func GetDatabaseRole(readyPod corev1.Pod, r client.Reader, - config *rest.Config, ctx context.Context, req ctrl.Request, edition string) (string, error) { + config *rest.Config, ctx context.Context, req ctrl.Request) (string, error) { + log := ctrllog.FromContext(ctx).WithValues("GetDatabaseRole", req.NamespacedName) out, err := ExecCommand(r, config, readyPod.Name, readyPod.Namespace, "", ctx, req, false, "bash", "-c", @@ -497,7 +572,7 @@ func GetDatabaseRole(readyPod corev1.Pod, r client.Reader, if !strings.Contains(out, "no rows selected") && !strings.Contains(out, "ORA-") { out = strings.Replace(out, " ", "_", -1) // filtering output and storing databse_role in "database_role" - databaseRole := strings.Fields(out)[2] + databaseRole := strings.ToUpper(strings.Fields(out)[2]) // first 2 values in the slice will be column name(DATABASE_ROLE) and a seperator(--------------) . return databaseRole, nil @@ -507,23 +582,23 @@ func GetDatabaseRole(readyPod corev1.Pod, r client.Reader, func GetDatabaseOpenMode(readyPod corev1.Pod, r client.Reader, config *rest.Config, ctx context.Context, req ctrl.Request, edition string) (string, error) { - log := ctrllog.FromContext(ctx).WithValues("GetDatabaseOpenMode",req.NamespacedName) + log := ctrllog.FromContext(ctx).WithValues("GetDatabaseOpenMode", req.NamespacedName) - out,err := ExecCommand(r, config, readyPod.Name, readyPod.Namespace, "", ctx, req, false, "bash", "-c", - fmt.Sprintf("echo -e \"%s\" | %s",GetDBOpenMode,SQLPlusCLI)) - if err != nil { - return "",err - } - log.Info(out) - if !strings.Contains(out, "no rows selected") && !strings.Contains(out, "ORA-") { - out1 := strings.Replace(out, " ", "_", -1) - // filtering output and storing databse_role in "database_role" - databaseOpenMode := strings.Fields(out1)[2] - // first 2 values in the slice will be column name(DATABASE_ROLE) and a seperator(--------------) . - return databaseOpenMode, nil - } - return "", errors.New("database open mode is nil") + out, err := ExecCommand(r, config, readyPod.Name, readyPod.Namespace, "", ctx, req, false, "bash", "-c", + fmt.Sprintf("echo -e \"%s\" | %s", GetDBOpenMode, SQLPlusCLI)) + if err != nil { + return "", err + } + log.Info(out) + if !strings.Contains(out, "no rows selected") && !strings.Contains(out, "ORA-") { + out1 := strings.Replace(out, " ", "_", -1) + // filtering output and storing databse_role in "database_role" + databaseOpenMode := strings.Fields(out1)[2] + // first 2 values in the slice will be column name(DATABASE_ROLE) and a seperator(--------------) . + return databaseOpenMode, nil } + return "", errors.New("database open mode is nil") +} // Returns true if any of the pod in 'pods' is with pod.Status.Phase == phase func IsAnyPodWithStatus(pods []corev1.Pod, phase corev1.PodPhase) (bool, corev1.Pod) { @@ -590,29 +665,29 @@ func GetNodeIp(r client.Reader, ctx context.Context, req ctrl.Request) string { } // GetSidPdbEdition to display sid, pdbname, edition in ConnectionString -func GetSidPdbEdition(r client.Reader, config *rest.Config, ctx context.Context, req ctrl.Request) (string, string, string) { +func GetSidPdbEdition(r client.Reader, config *rest.Config, ctx context.Context, req ctrl.Request) (string, string, string, error) { - log := ctrllog.FromContext(ctx).WithValues("GetNodeIp", req.NamespacedName) + log := ctrllog.FromContext(ctx).WithValues("GetSidbPdbEdition", req.NamespacedName) readyPod, _, _, _, err := FindPods(r, "", "", req.Name, req.Namespace, ctx, req) if err != nil { log.Error(err, err.Error()) - return "", "", "" + return "", "", "", fmt.Errorf("error while fetching ready pod %s : \n %s", readyPod.Name, err.Error()) } if readyPod.Name != "" { out, err := ExecCommand(r, config, readyPod.Name, readyPod.Namespace, "", ctx, req, false, "bash", "-c", GetSidPdbEditionCMD) if err != nil { log.Error(err, err.Error()) - return "", "", "" - } - splitstr := strings.Split(out, ",") - if len(splitstr) == 4 { - return splitstr[0], splitstr[1], splitstr[2] + return "", "", "", err } + log.Info("GetSidPdbEditionCMD output \n" + out) + splitstr := strings.Split((strings.TrimSpace(out)), ",") + return splitstr[0], splitstr[1], splitstr[2], nil } - - return "", "", "" + // err = errors.New("ready pod name is nil") + log.Error(err, ErrNoReadyPod.Error()) + return "", "", "", ErrNoReadyPod } // Get Datapatch Status @@ -713,3 +788,20 @@ func PatchService(config *rest.Config, namespace string, ctx context.Context, re _, err = client.CoreV1().Services(namespace).Patch(ctx, svcName, types.MergePatchType, []byte(payload), metav1.PatchOptions{}) return err } + +func GetWatchNamespaces() map[string]bool { + // Fetching the allowed namespaces from env variables + var watchNamespaceEnvVar = "WATCH_NAMESPACE" + ns, _ := os.LookupEnv(watchNamespaceEnvVar) + ns = strings.TrimSpace(ns) + namespaces := make(map[string]bool) + if len(ns) == 0 { + return namespaces + } + namespacesArr := strings.Split(ns, ",") + // put slice values into map + for _, s := range namespacesArr { + namespaces[s] = true + } + return namespaces +} diff --git a/commons/dbcssystem/dbcs_reconciler.go b/commons/dbcssystem/dbcs_reconciler.go index d4df1ab4..60905c76 100644 --- a/commons/dbcssystem/dbcs_reconciler.go +++ b/commons/dbcssystem/dbcs_reconciler.go @@ -94,6 +94,7 @@ func CreateAndGetDbcsId(logger logr.Logger, kubeClient client.Client, dbClient d dbcsDetails.CompartmentId = common.String(dbcs.Spec.DbSystem.CompartmentId) dbcsDetails.SubnetId = common.String(dbcs.Spec.DbSystem.SubnetId) dbcsDetails.Shape = common.String(dbcs.Spec.DbSystem.Shape) + dbcsDetails.Domain = common.String(dbcs.Spec.DbSystem.Domain) if dbcs.Spec.DbSystem.DisplayName != "" { dbcsDetails.DisplayName = common.String(dbcs.Spec.DbSystem.DisplayName) } @@ -535,6 +536,11 @@ func GetResourceState(logger logr.Logger, dbClient database.DatabaseClient, Id s func SetDBCSStatus(dbClient database.DatabaseClient, dbcs *databasev1alpha1.DbcsSystem, nwClient core.VirtualNetworkClient, wrClient workrequests.WorkRequestClient) error { + if dbcs.Spec.Id == nil { + dbcs.Status.State = "FAILED" + return nil + } + dbcsId := *dbcs.Spec.Id dbcsReq := database.GetDbSystemRequest{ diff --git a/commons/observability/constants.go b/commons/observability/constants.go new file mode 100644 index 00000000..89ecb946 --- /dev/null +++ b/commons/observability/constants.go @@ -0,0 +1,173 @@ +package observability + +import "github.com/oracle/oracle-database-operator/apis/observability/v1alpha1" + +const ( + UnknownValue = "UNKNOWN" + DefaultValue = "DEFAULT" +) + +// Observability Status +const ( + StatusObservabilityPending v1alpha1.StatusEnum = "PENDING" + StatusObservabilityError v1alpha1.StatusEnum = "ERROR" + StatusObservabilityReady v1alpha1.StatusEnum = "READY" +) + +// Log Names +const ( + LogReconcile = "ObservabilityExporterLogger" + LogExportersDeploy = "ObservabilityExporterDeploymentLogger" + LogExportersSVC = "ObservabilityExporterServiceLogger" + LogExportersServiceMonitor = "ObservabilityExporterServiceMonitorLogger" +) + +// Defaults +const ( + DefaultDbUserKey = "username" + DefaultDBPasswordKey = "password" + DefaultDBConnectionStringKey = "connection" + DefaultLabelKey = "app" + DefaultConfigVolumeString = "config-volume" + DefaultWalletVolumeString = "creds" + DefaultOCIPrivateKeyVolumeString = "ocikey" + DefaultOCIConfigFingerprintKey = "fingerprint" + DefaultOCIConfigRegionKey = "region" + DefaultOCIConfigTenancyKey = "tenancy" + DefaultOCIConfigUserKey = "user" + + DefaultExporterImage = "container-registry.oracle.com/database/observability-exporter:1.1.0" + DefaultServicePort = 9161 + DefaultServiceTargetPort = 9161 + DefaultPrometheusPort = "metrics" + DefaultReplicaCount = 1 + DefaultExporterConfigMountRootPath = "/oracle/observability" + DefaultOracleHome = "/lib/oracle/21/client64/lib" + DefaultOracleTNSAdmin = DefaultOracleHome + "/network/admin" + DefaultExporterConfigmapFilename = "config.toml" + DefaultVaultPrivateKeyRootPath = "/oracle/config" + DefaultPrivateKeyFileKey = "privatekey" + DefaultPrivateKeyFileName = "private.pem" + DefaultVaultPrivateKeyAbsolutePath = DefaultVaultPrivateKeyRootPath + "/" + DefaultPrivateKeyFileName + DefaultExporterConfigmapAbsolutePath = DefaultExporterConfigMountRootPath + "/" + DefaultExporterConfigmapFilename +) + +// default resource prefixes +const ( + DefaultServiceMonitorPrefix = "obs-servicemonitor-" + DefaultLabelPrefix = "obs-" + DefaultExporterDeploymentPrefix = "obs-deploy-" + DefaultExporterContainerName = "observability-exporter" +) + +// Known environment variables +const ( + EnvVarOracleHome = "ORACLE_HOME" + EnvVarDataSourceUser = "DB_USERNAME" + EnvVarDataSourcePassword = "DB_PASSWORD" + EnvVarDataSourceConnectString = "DB_CONNECT_STRING" + EnvVarDataSourcePwdVaultSecretName = "VAULT_SECRET_NAME" + EnvVarDataSourcePwdVaultId = "VAULT_ID" + EnvVarCustomConfigmap = "CUSTOM_METRICS" + EnvVarTNSAdmin = "TNS_ADMIN" + EnvVarVaultTenancyOCID = "vault_tenancy_ocid" + EnvVarVaultUserOCID = "vault_user_ocid" + EnvVarVaultFingerprint = "vault_fingerprint" + EnvVarVaultPrivateKeyPath = "vault_private_key_path" + EnvVarVaultRegion = "vault_region" +) + +// Positive ConditionTypes +const ( + IsCRAvailable = "ExporterReady" + IsExporterDeploymentReady = "DeploymentReady" + IsExporterServiceReady = "ServiceReady" + IsExporterServiceMonitorReady = "ServiceMonitorReady" +) + +// Reason +const ( + ReasonInitStart = "InitializationStarted" + ReasonReadyValidated = "ReadinessValidated" + ReasonValidationInProgress = "ReadinessValidationInProgress" + ReasonReadyFailed = "ReadinessValidationFailed" + ReasonDeploymentSpecValidationFailed = "SpecValidationFailed" + + ReasonDeploymentSuccessful = "ResourceDeployed" + ReasonDeploymentUpdated = "ResourceDeploymentUpdated" + ReasonDeploymentUpdateFailed = "ResourceDeploymentUpdateFailed" + ReasonDeploymentFailed = "ResourceDeploymentFailed" + ReasonDeploymentPending = "ResourceDeploymentInProgress" + + ReasonGeneralResourceGenerationFailed = "ResourceGenerationFailed" + ReasonGeneralResourceCreated = "ResourceCreated" + ReasonGeneralResourceCreationFailed = "ResourceCreationFailed" + ReasonGeneralResourceValidationCompleted = "ResourceDeployed" + ReasonGeneralResourceValidationFailureDueToError = "ResourceCouldNotBeValidated" +) + +// Log Errors +const ( + ErrorCRRetrieve = "an error occurred with retrieving the cr" + ErrorStatusUpdate = "an error occurred with updating the cr status" + ErrorSpecValidationFailedDueToAnError = "an error occurred with validating the exporter deployment spec" + ErrorDeploymentPodsFailure = "an error occurred with deploying exporter deployment pods" + ErrorDeploymentUpdate = "an error occurred with updating exporter deployment" + ErrorResourceCreationFailure = "an error occurred with creating databaseobserver resource" + ErrorResourceRetrievalFailureDueToAnError = "an error occurred with retrieving databaseobserver resource" +) + +// Log Infos +const ( + LogCRStart = "Started DatabaseObserver instance reconciliation" + LogCREnd = "Ended DatabaseObserver instance reconciliation, resource must have been deleted." + LogResourceCreated = "Created DatabaseObserver resource successfully" + LogResourceUpdated = "Updated DatabaseObserver resource successfully" + LogResourceFound = "Validated DatabaseObserver resource readiness" +) + +// Messages +const ( + MessageCRInitializationStarted = "Started initialization of custom resource" + MessageCRValidated = "Completed validation of custom resource readiness successfully" + MessageCRValidationFailed = "Failed to validate readiness of custom resource due to an error" + MessageCRValidationWaiting = "Waiting for other resources to be ready to fully validate readiness" + + MessageResourceCreated = "Completed creation of resource successfully" + MessageResourceCreationFailed = "Failed to create resource due to an error" + MessageResourceReadinessValidated = "Completed validation of resource readiness" + MessageResourceReadinessValidationFailed = "Failed to validate resource due to an error retrieving resource" + MessageResourceGenerationFailed = "Failed to generate resource due to an error" + + MessageExporterDeploymentSpecValidationFailed = "Failed to validate export deployment spec due to an error with the spec" + MessageExporterDeploymentImageUpdated = "Completed updating exporter deployment image successfully" + MessageExporterDeploymentEnvironmentUpdated = "Completed updating exporter deployment environment values successfully" + MessageExporterDeploymentReplicaUpdated = "Completed updating exporter deployment replicaCount successfully" + MessageExporterDeploymentVolumesUpdated = "Completed updating exporter deployment volumes successfully" + MessageExporterDeploymentUpdateFailed = "Failed to update exporter deployment due to an error" + MessageExporterDeploymentValidationFailed = "Failed to validate exporter deployment due to an error retrieving resource" + MessageExporterDeploymentSuccessful = "Completed validation of exporter deployment readiness" + MessageExporterDeploymentFailed = "Failed to deploy exporter deployment due to PodFailure" + MessageExporterDeploymentListingFailed = "Failed to list exporter deployment pods" + MessageExporterDeploymentPending = "Waiting for exporter deployment pods to be ready" +) + +// Event Recorder Outputs +const ( + EventReasonFailedCRRetrieval = "ExporterRetrievalFailed" + EventMessageFailedCRRetrieval = "Encountered error retrieving databaseObserver instance" + + EventReasonSpecError = "DeploymentSpecValidationFailed" + EventMessageSpecErrorDBPasswordMissing = "Spec validation failed due to missing dbPassword field values" + EventMessageSpecErrorDBPasswordSecretMissing = "Spec validation failed due to required dbPassword secret not found" + EventMessageSpecErrorDBConnectionStringSecretMissing = "Spec validation failed due to required dbConnectionString secret not found" + EventMessageSpecErrorDBPUserSecretMissing = "Spec validation failed due to dbUser secret not found" + EventMessageSpecErrorConfigmapMissing = "Spec validation failed due to custom config configmap not found" + EventMessageSpecErrorDBWalletSecretMissing = "Spec validation failed due to provided dbWallet secret not found" + + EventReasonUpdateSucceeded = "ExporterDeploymentUpdated" + EventMessageUpdatedImageSucceeded = "Exporter deployment image updated successfully" + EventMessageUpdatedEnvironmentSucceeded = "Exporter deployment environment values updated successfully" + EventMessageUpdatedVolumesSucceeded = "Exporter deployment volumes updated successfully" + EventMessageUpdatedReplicaSucceeded = "Exporter deployment replicaCount updated successfully" +) diff --git a/commons/observability/utils.go b/commons/observability/utils.go new file mode 100644 index 00000000..f396b95a --- /dev/null +++ b/commons/observability/utils.go @@ -0,0 +1,402 @@ +package observability + +import ( + apiv1 "github.com/oracle/oracle-database-operator/apis/observability/v1alpha1" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" +) + +// GetExporterLabels function retrieves exporter labels from api or provides default +func GetExporterLabels(api *apiv1.DatabaseObserver) map[string]string { + var l = make(map[string]string) + + if labels := api.Spec.Prometheus.Labels; labels != nil && len(labels) > 0 { + for k, v := range labels { + l[k] = v + } + l["release"] = "stable" + return l + } + return map[string]string{ + DefaultLabelKey: DefaultLabelPrefix + api.Name, + "release": "stable", + } + +} + +// GetExporterServicePort function retrieves exporter service port from api or provides default +func GetExporterServicePort(api *apiv1.DatabaseObserver) int32 { + if rPort := api.Spec.Exporter.Service.Port; rPort != 0 { + return rPort + } + return int32(DefaultServicePort) +} + +// GetExporterServiceMonitorPort function retrieves exporter service monitor port from api or provides default +func GetExporterServiceMonitorPort(api *apiv1.DatabaseObserver) string { + if rPort := api.Spec.Prometheus.Port; rPort != "" { + return rPort + } + return DefaultPrometheusPort + +} + +// GetExporterDeploymentVolumeMounts function retrieves volume mounts from api or provides default +func GetExporterDeploymentVolumeMounts(api *apiv1.DatabaseObserver) []corev1.VolumeMount { + + volM := make([]corev1.VolumeMount, 0) + + if cVolumeSourceName := api.Spec.Exporter.ExporterConfig.Configmap.Name; cVolumeSourceName != "" { + volM = append(volM, corev1.VolumeMount{ + Name: DefaultConfigVolumeString, + MountPath: DefaultExporterConfigMountRootPath, + }) + } + + // api.Spec.Database.DBWallet.SecretName optional + // if null, consider the database NON-ADB and connect as such + if secretName := api.Spec.Database.DBWallet.SecretName; secretName != "" { + volM = append(volM, corev1.VolumeMount{ + Name: DefaultWalletVolumeString, + MountPath: DefaultOracleTNSAdmin, + }) + } + + // api.Spec.OCIConfig.SecretName required if vault is used + if secretName := api.Spec.OCIConfig.SecretName; secretName != "" { + volM = append(volM, corev1.VolumeMount{ + Name: DefaultOCIPrivateKeyVolumeString, + MountPath: DefaultVaultPrivateKeyRootPath, + }) + } + return volM +} + +// GetExporterDeploymentVolumes function retrieves volumes from api or provides default +func GetExporterDeploymentVolumes(api *apiv1.DatabaseObserver) []corev1.Volume { + + vol := make([]corev1.Volume, 0) + + // config-volume Volume + // if null, the exporter uses the default built-in config + if cVolumeSourceName := api.Spec.Exporter.ExporterConfig.Configmap.Name; cVolumeSourceName != "" { + + cVolumeSourceKey := api.Spec.Exporter.ExporterConfig.Configmap.Key + cMSource := &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: cVolumeSourceName, + }, + Items: []corev1.KeyToPath{{ + Key: cVolumeSourceKey, + Path: DefaultExporterConfigmapFilename, + }}, + } + + vol = append(vol, corev1.Volume{Name: DefaultConfigVolumeString, VolumeSource: corev1.VolumeSource{ConfigMap: cMSource}}) + } + + // creds Volume + // api.Spec.Database.DBWallet.SecretName optional + // if null, consider the database NON-ADB and connect as such + if secretName := api.Spec.Database.DBWallet.SecretName; secretName != "" { + + vol = append(vol, corev1.Volume{ + Name: DefaultWalletVolumeString, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: secretName, + }, + }, + }) + } + + // ocikey Volume + // api.Spec.Database.DBWallet.SecretName optional + if secretName := api.Spec.OCIConfig.SecretName; secretName != "" { + + OCIConfigSource := &corev1.SecretVolumeSource{ + SecretName: secretName, + Items: []corev1.KeyToPath{{ + Key: DefaultPrivateKeyFileKey, + Path: DefaultPrivateKeyFileName, + }}, + } + + vol = append(vol, corev1.Volume{ + Name: DefaultOCIPrivateKeyVolumeString, + VolumeSource: corev1.VolumeSource{Secret: OCIConfigSource}, + }) + } + return vol +} + +// GetExporterSelector function retrieves labels from api or provides default +func GetExporterSelector(api *apiv1.DatabaseObserver) map[string]string { + var s = make(map[string]string) + if labels := api.Spec.Prometheus.Labels; labels != nil && len(labels) > 0 { + for k, v := range labels { + s[k] = v + } + return s + + } + return map[string]string{DefaultLabelKey: DefaultLabelPrefix + api.Name} + +} + +// GetExporterEnvs function retrieves env from api or provides default +func GetExporterEnvs(api *apiv1.DatabaseObserver) []corev1.EnvVar { + + optional := true + rDBPasswordKey := api.Spec.Database.DBPassword.Key + rDBPasswordName := api.Spec.Database.DBPassword.SecretName + rDBConnectStrKey := api.Spec.Database.DBConnectionString.Key + rDBConnectStrName := api.Spec.Database.DBConnectionString.SecretName + rDBVaultSecretName := api.Spec.Database.DBPassword.VaultSecretName + rDBVaultOCID := api.Spec.Database.DBPassword.VaultOCID + rDBUserSKey := api.Spec.Database.DBUser.Key + rDBUserSName := api.Spec.Database.DBUser.SecretName + rOCIConfigCMName := api.Spec.OCIConfig.ConfigMapName + + var env = make([]corev1.EnvVar, 0) + + // DB_USERNAME environment variable + if rDBUserSKey == "" { // overwrite + rDBUserSKey = DefaultDbUserKey + } + envUser := &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + Key: rDBUserSKey, + LocalObjectReference: corev1.LocalObjectReference{Name: rDBUserSName}, + Optional: &optional, + }} + env = append(env, corev1.EnvVar{Name: EnvVarDataSourceUser, ValueFrom: envUser}) + + // DB_CONNECT_STRING environment variable + if rDBConnectStrKey == "" { + rDBConnectStrKey = DefaultDBConnectionStringKey + } + envConnectStr := &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + Key: rDBConnectStrKey, + LocalObjectReference: corev1.LocalObjectReference{Name: rDBConnectStrName}, + Optional: &optional, + }} + env = append(env, corev1.EnvVar{Name: EnvVarDataSourceConnectString, ValueFrom: envConnectStr}) + + // DB_PASSWORD environment variable + // if useVault, add environment variables for Vault ID and Vault Secret Name + useVault := rDBVaultSecretName != "" && rDBVaultOCID != "" + if useVault { + + env = append(env, corev1.EnvVar{Name: EnvVarDataSourcePwdVaultSecretName, Value: rDBVaultSecretName}) + env = append(env, corev1.EnvVar{Name: EnvVarDataSourcePwdVaultId, Value: rDBVaultOCID}) + + // Configuring the configProvider prefixed with vault_ + // https://github.com/oracle/oracle-db-appdev-monitoring/blob/main/vault/vault.go + configSourceFingerprintValue := &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + Key: DefaultOCIConfigFingerprintKey, + LocalObjectReference: corev1.LocalObjectReference{Name: rOCIConfigCMName}, + Optional: &optional, + }, + } + configSourceRegionValue := &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + Key: DefaultOCIConfigRegionKey, + LocalObjectReference: corev1.LocalObjectReference{Name: rOCIConfigCMName}, + Optional: &optional, + }, + } + configSourceTenancyValue := &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + Key: DefaultOCIConfigTenancyKey, + LocalObjectReference: corev1.LocalObjectReference{Name: rOCIConfigCMName}, + Optional: &optional, + }, + } + configSourceUserValue := &corev1.EnvVarSource{ + ConfigMapKeyRef: &corev1.ConfigMapKeySelector{ + Key: DefaultOCIConfigUserKey, + LocalObjectReference: corev1.LocalObjectReference{Name: rOCIConfigCMName}, + Optional: &optional, + }, + } + + env = append(env, corev1.EnvVar{Name: EnvVarVaultFingerprint, ValueFrom: configSourceFingerprintValue}) + env = append(env, corev1.EnvVar{Name: EnvVarVaultUserOCID, ValueFrom: configSourceUserValue}) + env = append(env, corev1.EnvVar{Name: EnvVarVaultTenancyOCID, ValueFrom: configSourceTenancyValue}) + env = append(env, corev1.EnvVar{Name: EnvVarVaultRegion, ValueFrom: configSourceRegionValue}) + env = append(env, corev1.EnvVar{Name: EnvVarVaultPrivateKeyPath, Value: DefaultVaultPrivateKeyAbsolutePath}) + + } else { + + if rDBPasswordKey == "" { // overwrite + rDBPasswordKey = DefaultDBPasswordKey + } + dbPassword := &corev1.EnvVarSource{ + SecretKeyRef: &corev1.SecretKeySelector{ + Key: rDBPasswordKey, + LocalObjectReference: corev1.LocalObjectReference{Name: rDBPasswordName}, + Optional: &optional, + }} + + env = append(env, corev1.EnvVar{Name: EnvVarDataSourcePassword, ValueFrom: dbPassword}) + + } + + // CUSTOM_METRICS environment variable + if customMetricsName := api.Spec.Exporter.ExporterConfig.Configmap.Name; customMetricsName != "" { + customMetrics := DefaultExporterConfigmapAbsolutePath + env = append(env, corev1.EnvVar{Name: EnvVarCustomConfigmap, Value: customMetrics}) + } + + env = append(env, corev1.EnvVar{Name: EnvVarOracleHome, Value: DefaultOracleHome}) + env = append(env, corev1.EnvVar{Name: EnvVarTNSAdmin, Value: DefaultOracleTNSAdmin}) + return env +} + +// GetExporterReplicas function retrieves replicaCount from api or provides default +func GetExporterReplicas(api *apiv1.DatabaseObserver) int32 { + if rc := api.Spec.Replicas; rc != 0 { + return rc + } + return int32(DefaultReplicaCount) +} + +// GetExporterImage function retrieves image from api or provides default +func GetExporterImage(api *apiv1.DatabaseObserver) string { + if img := api.Spec.Exporter.ExporterImage; img != "" { + return img + } + return DefaultExporterImage + +} + +func IsUpdateRequiredForContainerImage(desired *appsv1.Deployment, found *appsv1.Deployment) bool { + foundImage := found.Spec.Template.Spec.Containers[0].Image + desiredImage := desired.Spec.Template.Spec.Containers[0].Image + + return foundImage != desiredImage +} + +func IsUpdateRequiredForEnvironmentVars(desired *appsv1.Deployment, found *appsv1.Deployment) bool { + var updateEnvsRequired bool + desiredEnvValues := make(map[string]string) + + foundEnvs := found.Spec.Template.Spec.Containers[0].Env + desiredEnvs := desired.Spec.Template.Spec.Containers[0].Env + if len(foundEnvs) != len(desiredEnvs) { + updateEnvsRequired = true + } else { + for _, v := range desiredEnvs { + + if v.Name == EnvVarDataSourceUser || + v.Name == EnvVarDataSourceConnectString || + v.Name == EnvVarDataSourcePassword { + + ref := *(*v.ValueFrom).SecretKeyRef + desiredEnvValues[v.Name] = ref.Key + "-" + ref.Name + + } else if v.Name == EnvVarVaultFingerprint || + v.Name == EnvVarVaultRegion || + v.Name == EnvVarVaultTenancyOCID || + v.Name == EnvVarVaultUserOCID { + + ref := *(*v.ValueFrom).ConfigMapKeyRef + desiredEnvValues[v.Name] = ref.Key + "-" + ref.Name + + } else if v.Name == EnvVarDataSourcePwdVaultId || + v.Name == EnvVarDataSourcePwdVaultSecretName || + v.Name == EnvVarCustomConfigmap { + + desiredEnvValues[v.Name] = v.Value + } + } + + for _, v := range foundEnvs { + var foundValue string + + if v.Name == EnvVarDataSourceUser || + v.Name == EnvVarDataSourceConnectString || + v.Name == EnvVarDataSourcePassword { + + ref := *(*v.ValueFrom).SecretKeyRef + foundValue = ref.Key + "-" + ref.Name + + } else if v.Name == EnvVarVaultFingerprint || + v.Name == EnvVarVaultRegion || + v.Name == EnvVarVaultTenancyOCID || + v.Name == EnvVarVaultUserOCID { + + ref := *(*v.ValueFrom).ConfigMapKeyRef + foundValue = ref.Key + "-" + ref.Name + + } else if v.Name == EnvVarDataSourcePwdVaultId || + v.Name == EnvVarDataSourcePwdVaultSecretName || + v.Name == EnvVarCustomConfigmap { + + foundValue = v.Value + } + + if desiredEnvValues[v.Name] != foundValue { + updateEnvsRequired = true + } + } + } + return updateEnvsRequired +} + +func IsUpdateRequiredForVolumes(desired *appsv1.Deployment, found *appsv1.Deployment) bool { + var updateVolumesRequired bool + var foundConfigmap, desiredConfigmap string + var foundWalletSecret, desiredWalletSecret string + var foundOCIConfig, desiredOCIConfig string + + desiredVolumes := desired.Spec.Template.Spec.Volumes + foundVolumes := found.Spec.Template.Spec.Volumes + + if len(desiredVolumes) != len(foundVolumes) { + updateVolumesRequired = true + } else { + for _, v := range desiredVolumes { + if v.Name == DefaultConfigVolumeString { + desiredConfigmap = v.ConfigMap.Name + for _, key := range v.ConfigMap.Items { + desiredConfigmap += key.Key + } + } else if v.Name == DefaultWalletVolumeString { + desiredWalletSecret = v.VolumeSource.Secret.SecretName + + } else if v.Name == DefaultOCIPrivateKeyVolumeString { + desiredOCIConfig = v.VolumeSource.Secret.SecretName + } + } + + for _, v := range foundVolumes { + if v.Name == DefaultConfigVolumeString { + foundConfigmap = v.ConfigMap.Name + for _, key := range v.ConfigMap.Items { + foundConfigmap += key.Key + } + } else if v.Name == DefaultWalletVolumeString { + foundWalletSecret = v.VolumeSource.Secret.SecretName + + } else if v.Name == DefaultOCIPrivateKeyVolumeString { + foundOCIConfig = v.VolumeSource.Secret.SecretName + } + } + } + + return updateVolumesRequired || + desiredConfigmap != foundConfigmap || + desiredWalletSecret != foundWalletSecret || + desiredOCIConfig != foundOCIConfig +} + +func IsUpdateRequiredForReplicas(desired *appsv1.Deployment, found *appsv1.Deployment) bool { + foundReplicas := *found.Spec.Replicas + desiredReplicas := *desired.Spec.Replicas + + return desiredReplicas != foundReplicas +} diff --git a/commons/oci/database.go b/commons/oci/database.go index 10d6c8ff..9c3cd4d8 100644 --- a/commons/oci/database.go +++ b/commons/oci/database.go @@ -407,7 +407,9 @@ func (d *databaseService) ListAutonomousDatabaseBackups(adbOCID string) (databas func (d *databaseService) CreateAutonomousDatabaseBackup(adbBackup *dbv1alpha1.AutonomousDatabaseBackup, adbOCID string) (database.CreateAutonomousDatabaseBackupResponse, error) { createBackupRequest := database.CreateAutonomousDatabaseBackupRequest{ CreateAutonomousDatabaseBackupDetails: database.CreateAutonomousDatabaseBackupDetails{ - AutonomousDatabaseId: common.String(adbOCID), + AutonomousDatabaseId: common.String(adbOCID), + IsLongTermBackup: adbBackup.Spec.IsLongTermBackup, + RetentionPeriodInDays: adbBackup.Spec.RetentionPeriodInDays, }, } diff --git a/commons/oci/provider.go b/commons/oci/provider.go index e875969c..152f1efd 100644 --- a/commons/oci/provider.go +++ b/commons/oci/provider.go @@ -1,5 +1,5 @@ /* -** Copyright (c) 2022 Oracle and/or its affiliates. +** Copyright (c) 2022, 2024 Oracle and/or its affiliates. ** ** The Universal Permissive License (UPL), Version 1.0 ** @@ -40,6 +40,8 @@ package oci import ( "errors" + "fmt" + "os" "github.com/oracle/oci-go-sdk/v65/common" "github.com/oracle/oci-go-sdk/v65/common/auth" @@ -65,7 +67,9 @@ type APIKeyAuth struct { } func GetOCIProvider(kubeClient client.Client, authData APIKeyAuth) (common.ConfigurationProvider, error) { - if authData.ConfigMapName != nil && authData.SecretName != nil { + if authData.ConfigMapName != nil && authData.SecretName == nil { + return getWorkloadIdentityProvider(kubeClient, authData) + } else if authData.ConfigMapName != nil && authData.SecretName != nil { provider, err := getProviderWithAPIKey(kubeClient, authData) if err != nil { return nil, err @@ -80,6 +84,30 @@ func GetOCIProvider(kubeClient client.Client, authData APIKeyAuth) (common.Confi } } +func getWorkloadIdentityProvider(kubeClient client.Client, authData APIKeyAuth) (common.ConfigurationProvider, error) { + ociConfigMap, err := k8s.FetchConfigMap(kubeClient, authData.Namespace, *authData.ConfigMapName) + if err != nil { + return nil, err + } + // Ensure configmap is set with proper data + if len(ociConfigMap.Data) == 0 { + return nil, fmt.Errorf("OCI ConfigMap %s has no data", ociConfigMap.Name) + } + region, ok := ociConfigMap.Data[regionKey] + if !ok || len(region) == 0 { + return nil, fmt.Errorf("OCI Region Key %s missing from OCI ConfigMap %s", regionKey, ociConfigMap.Name) + } + // OCI SDK requires specific, dynamic environment variables for workload identity. + if err = os.Setenv(auth.ResourcePrincipalVersionEnvVar, auth.ResourcePrincipalVersion2_2); err != nil { + + return nil, fmt.Errorf("unable to set OCI SDK environment variable %s: %v", auth.ResourcePrincipalVersionEnvVar, err) + } + if err = os.Setenv(auth.ResourcePrincipalRegionEnvVar, region); err != nil { + return nil, fmt.Errorf("unable to set OCI SDK environment variable %s: %v", auth.ResourcePrincipalRegionEnvVar, err) + } + return auth.OkeWorkloadIdentityConfigurationProvider() +} + func getProviderWithAPIKey(kubeClient client.Client, authData APIKeyAuth) (common.ConfigurationProvider, error) { var region, fingerprint, user, tenancy, passphrase, privatekeyValue string diff --git a/commons/oci/wallet.go b/commons/oci/wallet.go index 27ebb150..076460b1 100644 --- a/commons/oci/wallet.go +++ b/commons/oci/wallet.go @@ -42,6 +42,7 @@ import ( "archive/zip" "io" "io/ioutil" + "strings" ) // ExtractWallet extracts the wallet and returns a map object which holds the byte values of the unzipped files. @@ -76,27 +77,34 @@ func saveWalletZip(content io.ReadCloser) (string, error) { } func unzipWallet(path string) (map[string][]byte, error) { - data := map[string][]byte{} + files := map[string][]byte{} reader, err := zip.OpenReader(path) if err != nil { - return data, err + return files, err } defer reader.Close() for _, file := range reader.File { reader, err := file.Open() if err != nil { - return data, err + return files, err } content, err := ioutil.ReadAll(reader) if err != nil { - return data, err + return files, err } - data[file.Name] = content + files[file.Name] = content } - return data, nil + return files, nil +} + +func WalletExpiringDate(files map[string][]byte) string { + data := string(files["README"]) + + line := data[strings.Index(data, "this wallet will expire on"):strings.Index(data, ".\nIn order to avoid")] + return strings.TrimSpace(strings.TrimPrefix(line, "this wallet will expire on")) } diff --git a/commons/sharding/catalog.go b/commons/sharding/catalog.go index f87efea8..58f07490 100644 --- a/commons/sharding/catalog.go +++ b/commons/sharding/catalog.go @@ -43,9 +43,8 @@ import ( "reflect" "strconv" - databasev1alpha1 "github.com/oracle/oracle-database-operator/apis/database/v1alpha1" - "github.com/go-logr/logr" + databasev1alpha1 "github.com/oracle/oracle-database-operator/apis/database/v1alpha1" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/resource" @@ -141,10 +140,14 @@ func buildPodSpecForCatalog(instance *databasev1alpha1.ShardingDatabase, OraCata RunAsUser: &user, FSGroup: &group, }, - InitContainers: buildInitContainerSpecForCatalog(instance, OraCatalogSpex), - Containers: buildContainerSpecForCatalog(instance, OraCatalogSpex), - Volumes: buildVolumeSpecForCatalog(instance, OraCatalogSpex), + Containers: buildContainerSpecForCatalog(instance, OraCatalogSpex), + Volumes: buildVolumeSpecForCatalog(instance, OraCatalogSpex), + } + + if (instance.Spec.IsDownloadScripts) && (instance.Spec.ScriptsLocation != "") { + spec.InitContainers = buildInitContainerSpecForCatalog(instance, OraCatalogSpex) } + if len(instance.Spec.DbImagePullSecret) > 0 { spec.ImagePullSecrets = []corev1.LocalObjectReference{ { @@ -170,16 +173,10 @@ func buildVolumeSpecForCatalog(instance *databasev1alpha1.ShardingDatabase, OraC Name: OraCatalogSpex.Name + "secretmap-vol3", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: instance.Spec.Secret, + SecretName: instance.Spec.DbSecret.Name, }, }, }, - { - Name: OraCatalogSpex.Name + "orascript-vol5", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, { Name: OraCatalogSpex.Name + "oradshm-vol6", VolumeSource: corev1.VolumeSource{ @@ -196,6 +193,16 @@ func buildVolumeSpecForCatalog(instance *databasev1alpha1.ShardingDatabase, OraC result = append(result, corev1.Volume{Name: OraCatalogSpex.Name + "orastage-vol7", VolumeSource: corev1.VolumeSource{PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ClaimName: instance.Spec.StagePvcName}}}) } + if instance.Spec.IsDownloadScripts { + result = append(result, corev1.Volume{Name: OraCatalogSpex.Name + "orascript-vol5", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}}) + } + + if checkTdeWalletFlag(instance) { + if len(instance.Spec.FssStorageClass) == 0 && len(instance.Spec.TdeWalletPvc) > 0 { + result = append(result, corev1.Volume{Name: OraCatalogSpex.Name + "shared-storage-vol8", VolumeSource: corev1.VolumeSource{PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ClaimName: instance.Spec.TdeWalletPvc}}}) + } + } + return result } @@ -208,7 +215,7 @@ func buildContainerSpecForCatalog(instance *databasev1alpha1.ShardingDatabase, O Image: instance.Spec.DbImage, SecurityContext: &corev1.SecurityContext{ Capabilities: &corev1.Capabilities{ - Add: []corev1.Capability{"NET_RAW"}, + Add: []corev1.Capability{corev1.Capability("NET_ADMIN"), corev1.Capability("SYS_NICE")}, }, }, Resources: corev1.ResourceRequirements{ @@ -217,29 +224,49 @@ func buildContainerSpecForCatalog(instance *databasev1alpha1.ShardingDatabase, O VolumeMounts: buildVolumeMountSpecForCatalog(instance, OraCatalogSpex), LivenessProbe: &corev1.Probe{ // TODO: Investigate if it's ok to call status every 10 seconds - FailureThreshold: int32(30), - PeriodSeconds: int32(240), - InitialDelaySeconds: int32(300), - TimeoutSeconds: int32(60), + FailureThreshold: int32(3), + InitialDelaySeconds: int32(30), + PeriodSeconds: func() int32 { + if instance.Spec.LivenessCheckPeriod > 0 { + return int32(instance.Spec.LivenessCheckPeriod) + } + return 60 + }(), + TimeoutSeconds: int32(30), ProbeHandler: corev1.ProbeHandler{ Exec: &corev1.ExecAction{ - Command: getLivenessCmd("CATALOG"), + Command: []string{"/bin/sh", "-c", "if [ -f $ORACLE_BASE/checkDBLockStatus.sh ]; then $ORACLE_BASE/checkDBLockStatus.sh ; else $ORACLE_BASE/checkDBStatus.sh; fi "}, }, }, }, /** - // Disabling this because the pod is not reachable till the time startup probe completes and without network pod configuration cannot be completed. - StartupProbe: &corev1.Probe{ - // Initial delay should be big, because shard setup takes time - FailureThreshold: int32(30), - PeriodSeconds: int32(120), - Handler: corev1.Handler{ + ReadinessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ Exec: &corev1.ExecAction{ - Command: getLivenessCmd("CATALOG"), + //Command: getReadinessCmd("CATALOG"), + Command: []string{"/bin/sh", "-c", "if [ -f $ORACLE_BASE/checkDBLockStatus.sh ]; then $ORACLE_BASE/checkDBLockStatus.sh ; else $ORACLE_BASE/checkDBStatus.sh; fi "}, }, }, + InitialDelaySeconds: 20, + TimeoutSeconds: 20, + PeriodSeconds: func() int32 { + if instance.Spec.ReadinessCheckPeriod > 0 { + return int32(instance.Spec.ReadinessCheckPeriod) + } + return 60 + }(), }, **/ + StartupProbe: &corev1.Probe{ + FailureThreshold: int32(120), + PeriodSeconds: int32(40), + InitialDelaySeconds: int32(30), + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"/bin/sh", "-c", "if [ -f $ORACLE_BASE/checkDBLockStatus.sh ]; then $ORACLE_BASE/checkDBLockStatus.sh ; else $ORACLE_BASE/checkDBStatus.sh; fi "}, + }, + }, + }, Env: buildEnvVarsSpec(instance, OraCatalogSpex.EnvVars, OraCatalogSpex.Name, "CATALOG", false, ""), } if instance.Spec.IsClone { @@ -256,7 +283,7 @@ func buildContainerSpecForCatalog(instance *databasev1alpha1.ShardingDatabase, O return result } -//Function to build the init Container Spec +// Function to build the init Container Spec func buildInitContainerSpecForCatalog(instance *databasev1alpha1.ShardingDatabase, OraCatalogSpex databasev1alpha1.CatalogSpec) []corev1.Container { var result []corev1.Container // building the init Container Spec @@ -297,13 +324,24 @@ func buildVolumeMountSpecForCatalog(instance *databasev1alpha1.ShardingDatabase, var result []corev1.VolumeMount result = append(result, corev1.VolumeMount{Name: OraCatalogSpex.Name + "secretmap-vol3", MountPath: oraSecretMount, ReadOnly: true}) result = append(result, corev1.VolumeMount{Name: OraCatalogSpex.Name + "-oradata-vol4", MountPath: oraDataMount}) - result = append(result, corev1.VolumeMount{Name: OraCatalogSpex.Name + "orascript-vol5", MountPath: oraScriptMount}) + if instance.Spec.IsDownloadScripts { + result = append(result, corev1.VolumeMount{Name: OraCatalogSpex.Name + "orascript-vol5", MountPath: oraDbScriptMount}) + } result = append(result, corev1.VolumeMount{Name: OraCatalogSpex.Name + "oradshm-vol6", MountPath: oraShm}) if len(instance.Spec.StagePvcName) != 0 { result = append(result, corev1.VolumeMount{Name: OraCatalogSpex.Name + "orastage-vol7", MountPath: oraStage}) } + if checkTdeWalletFlag(instance) { + if len(instance.Spec.FssStorageClass) > 0 && len(instance.Spec.TdeWalletPvc) == 0 { + result = append(result, corev1.VolumeMount{Name: instance.Name + "shared-storage", MountPath: getTdeWalletMountLoc(instance)}) + } else { + if len(instance.Spec.FssStorageClass) == 0 && len(instance.Spec.TdeWalletPvc) > 0 { + result = append(result, corev1.VolumeMount{Name: OraCatalogSpex.Name + "shared-storage-vol8", MountPath: getTdeWalletMountLoc(instance)}) + } + } + } return result } @@ -328,7 +366,7 @@ func volumeClaimTemplatesForCatalog(instance *databasev1alpha1.ShardingDatabase, corev1.ReadWriteOnce, }, StorageClassName: &instance.Spec.StorageClass, - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceStorage: resource.MustParse(strconv.FormatInt(int64(OraCatalogSpex.StorageSizeInGb), 10) + "Gi"), }, @@ -348,6 +386,34 @@ func volumeClaimTemplatesForCatalog(instance *databasev1alpha1.ShardingDatabase, claims[0].Spec.Selector = &metav1.LabelSelector{MatchLabels: OraCatalogSpex.PvMatchLabels} } + if checkTdeWalletFlag(instance) { + if len(instance.Spec.FssStorageClass) > 0 && len(instance.Spec.TdeWalletPvc) == 0 { + { + pvcClaim := corev1.PersistentVolumeClaim{ + ObjectMeta: metav1.ObjectMeta{ + Name: instance.Name + "shared-storage", + Namespace: instance.Spec.Namespace, + OwnerReferences: getOwnerRef(instance), + Labels: buildLabelsForCatalog(instance, "sharding"), + }, + Spec: corev1.PersistentVolumeClaimSpec{ + AccessModes: []corev1.PersistentVolumeAccessMode{ + corev1.ReadWriteMany, + }, + StorageClassName: &instance.Spec.FssStorageClass, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse(strconv.FormatInt(int64(OraCatalogSpex.StorageSizeInGb), 10) + "Gi"), + }, + }, + }, + } + + claims = append(claims, pvcClaim) + } + } + } + return claims } @@ -430,7 +496,7 @@ func UpdateProvForCatalog(instance *databasev1alpha1.ShardingDatabase, oraSpexRes := OraCatalogSpex.Resources if !reflect.DeepEqual(shardContaineRes, oraSpexRes) { - isUpdate = true + isUpdate = false } } } diff --git a/commons/sharding/exec.go b/commons/sharding/exec.go index 48fc18cf..44f91e51 100644 --- a/commons/sharding/exec.go +++ b/commons/sharding/exec.go @@ -40,27 +40,56 @@ package commons import ( "bytes" + "fmt" "net/http" + "time" databasealphav1 "github.com/oracle/oracle-database-operator/apis/database/v1alpha1" "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/runtime/serializer" + "k8s.io/cli-runtime/pkg/genericclioptions" "k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" "k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/remotecommand" + "k8s.io/kubectl/pkg/cmd/cp" + "k8s.io/kubectl/pkg/cmd/util" ) // ExecCMDInContainer execute command in first container of a pod func ExecCommand(podName string, cmd []string, kubeClient kubernetes.Interface, kubeConfig clientcmd.ClientConfig, instance *databasealphav1.ShardingDatabase, logger logr.Logger) (string, string, error) { + var err1 error = nil var msg string var ( execOut bytes.Buffer execErr bytes.Buffer ) + for i := 0; i < 5; i++ { + if scheme.Scheme == nil { + time.Sleep(time.Second * 40) + } else { + break + } + } + + if kubeClient == nil { + msg = "ExecCommand() : kubeClient is nil" + err1 = fmt.Errorf(msg) + return "Error:","kubeClient is nil",err1 + } + if kubeConfig == nil { + msg = "ExecCommand() : kubeConfig is nil" + err1 = fmt.Errorf(msg) + return "Error:","kubeConfig is nil",err1 + } + + msg = "" req := kubeClient.CoreV1().RESTClient(). Post(). Namespace(instance.Spec.Namespace). @@ -106,3 +135,68 @@ func ExecCommand(podName string, cmd []string, kubeClient kubernetes.Interface, return execOut.String(), execErr.String(), nil } + +func GetPodCopyConfig(kubeClient kubernetes.Interface, kubeConfig clientcmd.ClientConfig, instance *databasealphav1.ShardingDatabase, logger logr.Logger) (*rest.Config, *kubernetes.Clientset, error) { + + var clientSet *kubernetes.Clientset + config, err := kubeConfig.ClientConfig() + if err != nil { + return config, clientSet, err + } + clientSet, err = kubernetes.NewForConfig(config) + config.APIPath = "/api" + config.GroupVersion = &schema.GroupVersion{Version: "v1"} + config.NegotiatedSerializer = serializer.WithoutConversionCodecFactory{CodecFactory: scheme.Codecs} + + return config, clientSet, err + +} + +func KctlCopyFile(kubeClient kubernetes.Interface, kubeConfig clientcmd.ClientConfig, instance *databasealphav1.ShardingDatabase, restConfig *rest.Config, kclientset *kubernetes.Clientset, logger logr.Logger, src string, dst string, containername string) (*bytes.Buffer, *bytes.Buffer, *bytes.Buffer, error) { + + var in, out, errOut *bytes.Buffer + var ioStreams genericclioptions.IOStreams + for count := 0; ; count++ { + ioStreams, in, out, errOut = genericclioptions.NewTestIOStreams() + copyOptions := cp.NewCopyOptions(ioStreams) + copyOptions.ClientConfig = restConfig + if len(containername) != 0 { + copyOptions.Container = containername + } + configFlags := genericclioptions.NewConfigFlags(false) + f := util.NewFactory(configFlags) + cmd := cp.NewCmdCp(f, ioStreams) + err := copyOptions.Complete(f, cmd, []string{src, dst}) + if err != nil { + return nil, nil, nil, err + } + + c := rest.CopyConfig(restConfig) + cs, err := kubernetes.NewForConfig(c) + if err != nil { + return nil, nil, nil, err + } + + copyOptions.ClientConfig = c + copyOptions.Clientset = cs + + err = copyOptions.Run() + if err != nil { + if !shouldRetry(count, err) { + return nil, nil, nil, fmt.Errorf("could not run copy operation: %v. Stdout: %v, Stderr: %v", err, out.String(), errOut.String()) + } + time.Sleep(10 * time.Second) + continue + } + break + } + return in, out, errOut, nil + +} + +func shouldRetry(count int, err error) bool { + if count < connectFailureMaxTries { + return err.Error() == errorDialingBackendEOF + } + return false +} diff --git a/commons/sharding/gsm.go b/commons/sharding/gsm.go index b6c1f0a8..bcdc8866 100644 --- a/commons/sharding/gsm.go +++ b/commons/sharding/gsm.go @@ -121,6 +121,7 @@ func buildStatefulSpecForGsm(instance *databasev1alpha1.ShardingDatabase, OraGsm }, VolumeClaimTemplates: volumeClaimTemplatesForGsm(instance, OraGsmSpex), } + /** if OraGsmSpex.Replicas == 0 { OraGsmSpex.Replicas = 1 sfsetspec.Replicas = &OraGsmSpex.Replicas @@ -128,6 +129,7 @@ func buildStatefulSpecForGsm(instance *databasev1alpha1.ShardingDatabase, OraGsm OraGsmSpex.Replicas = 1 sfsetspec.Replicas = &OraGsmSpex.Replicas } + **/ return sfsetspec } @@ -143,10 +145,14 @@ func buildPodSpecForGsm(instance *databasev1alpha1.ShardingDatabase, OraGsmSpex RunAsUser: &user, FSGroup: &group, }, - InitContainers: buildInitContainerSpecForGsm(instance, OraGsmSpex), - Containers: buildContainerSpecForGsm(instance, OraGsmSpex), - Volumes: buildVolumeSpecForGsm(instance, OraGsmSpex), + Containers: buildContainerSpecForGsm(instance, OraGsmSpex), + Volumes: buildVolumeSpecForGsm(instance, OraGsmSpex), + } + + if (instance.Spec.IsDownloadScripts) && (instance.Spec.ScriptsLocation != "") { + spec.InitContainers = buildInitContainerSpecForGsm(instance, OraGsmSpex) } + if len(instance.Spec.GsmImagePullSecret) > 0 { spec.ImagePullSecrets = []corev1.LocalObjectReference{ { @@ -171,16 +177,10 @@ func buildVolumeSpecForGsm(instance *databasev1alpha1.ShardingDatabase, OraGsmSp Name: OraGsmSpex.Name + "secretmap-vol3", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: instance.Spec.Secret, + SecretName: instance.Spec.DbSecret.Name, }, }, }, - { - Name: OraGsmSpex.Name + "orascript-vol5", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, { Name: OraGsmSpex.Name + "oradshm-vol6", VolumeSource: corev1.VolumeSource{ @@ -197,6 +197,9 @@ func buildVolumeSpecForGsm(instance *databasev1alpha1.ShardingDatabase, OraGsmSp result = append(result, corev1.Volume{Name: OraGsmSpex.Name + "orastage-vol7", VolumeSource: corev1.VolumeSource{PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ClaimName: instance.Spec.StagePvcName}}}) } + if instance.Spec.IsDownloadScripts { + result = append(result, corev1.Volume{Name: OraGsmSpex.Name + "orascript-vol5", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}}) + } return result } @@ -230,10 +233,15 @@ func buildContainerSpecForGsm(instance *databasev1alpha1.ShardingDatabase, OraGs VolumeMounts: buildVolumeMountSpecForGsm(instance, OraGsmSpex), LivenessProbe: &corev1.Probe{ // TODO: Investigate if it's ok to call status every 10 seconds - FailureThreshold: int32(30), - PeriodSeconds: int32(240), - InitialDelaySeconds: int32(300), - TimeoutSeconds: int32(60), + FailureThreshold: int32(3), + InitialDelaySeconds: int32(30), + PeriodSeconds: func() int32 { + if instance.Spec.LivenessCheckPeriod > 0 { + return int32(instance.Spec.LivenessCheckPeriod) + } + return 60 + }(), + TimeoutSeconds: int32(20), ProbeHandler: corev1.ProbeHandler{ Exec: &corev1.ExecAction{ Command: getLivenessCmd("GSM"), @@ -263,7 +271,7 @@ func buildContainerSpecForGsm(instance *databasev1alpha1.ShardingDatabase, OraGs return result } -//Function to build the init Container Spec +// Function to build the init Container Spec func buildInitContainerSpecForGsm(instance *databasev1alpha1.ShardingDatabase, OraGsmSpex databasev1alpha1.GsmSpec) []corev1.Container { var result []corev1.Container // building the init Container Spec @@ -305,7 +313,9 @@ func buildVolumeMountSpecForGsm(instance *databasev1alpha1.ShardingDatabase, Ora var result []corev1.VolumeMount result = append(result, corev1.VolumeMount{Name: OraGsmSpex.Name + "secretmap-vol3", MountPath: oraSecretMount, ReadOnly: true}) result = append(result, corev1.VolumeMount{Name: OraGsmSpex.Name + "-oradata-vol4", MountPath: oraGsmDataMount}) - result = append(result, corev1.VolumeMount{Name: OraGsmSpex.Name + "orascript-vol5", MountPath: oraScriptMount}) + if instance.Spec.IsDownloadScripts { + result = append(result, corev1.VolumeMount{Name: OraGsmSpex.Name + "orascript-vol5", MountPath: oraScriptMount}) + } result = append(result, corev1.VolumeMount{Name: OraGsmSpex.Name + "oradshm-vol6", MountPath: oraShm}) if len(instance.Spec.StagePvcName) != 0 { @@ -336,7 +346,7 @@ func volumeClaimTemplatesForGsm(instance *databasev1alpha1.ShardingDatabase, Ora corev1.ReadWriteOnce, }, StorageClassName: &instance.Spec.StorageClass, - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceStorage: resource.MustParse(strconv.FormatInt(int64(OraGsmSpex.StorageSizeInGb), 10) + "Gi"), }, @@ -443,7 +453,7 @@ func UpdateProvForGsm(instance *databasev1alpha1.ShardingDatabase, // Ensure deployment replicas match the desired state if sfSet.Spec.Replicas != nil { if *sfSet.Spec.Replicas != size { - msg = "Current StatefulSet replicas do not match configured Shard Replicas. Gsm is configured with only 1 but current replicas is set with " + strconv.FormatInt(int64(*sfSet.Spec.Replicas), 10) + msg = "Current StatefulSet replicas do not match configured GSM Replicas. Gsm is configured with only 1 but current replicas is set with " + strconv.FormatInt(int64(*sfSet.Spec.Replicas), 10) LogMessages("DEBUG", msg, nil, instance, logger) isUpdate = true } @@ -456,7 +466,7 @@ func UpdateProvForGsm(instance *databasev1alpha1.ShardingDatabase, oraSpexRes := OraGsmSpex.Resources if !reflect.DeepEqual(shardContaineRes, oraSpexRes) { - isUpdate = true + isUpdate = false } } } diff --git a/commons/sharding/provstatus.go b/commons/sharding/provstatus.go index 6c34b007..87796553 100644 --- a/commons/sharding/provstatus.go +++ b/commons/sharding/provstatus.go @@ -78,7 +78,7 @@ func UpdateGsmStatusData(instance *databasealphav1.ShardingDatabase, Specidx int K8sInternalSvcName := svcName + "." + getInstanceNs(instance) + ".svc.cluster.local" _, K8sInternalSvcIP, _ := GetSvcIp(instance.Spec.Gsm[Specidx].Name+"-0", K8sInternalSvcName, instance, kubeClient, kubeConfig, logger) _, K8sExternalSvcIP, _ := GetSvcIp(instance.Spec.Gsm[Specidx].Name+"-0", k8sExternalSvcName, instance, kubeClient, kubeConfig, logger) - DbPasswordSecret := instance.Spec.Secret + DbPasswordSecret := instance.Spec.DbSecret.Name instance.Status.Gsm.Services = GetGsmServices(instance.Spec.Gsm[Specidx].Name+"-0", instance, kubeClient, kubeConfig, logger) // externIp := strings.Replace(K8sInternalSvcIP, "/r/n", "", -1) @@ -125,7 +125,7 @@ func UpdateCatalogStatusData(instance *databasealphav1.ShardingDatabase, Specidx K8sInternalSvcName := svcName + "." + getInstanceNs(instance) + ".svc.cluster.local" _, K8sInternalSvcIP, _ := GetSvcIp(instance.Spec.Catalog[Specidx].Name+"-0", K8sInternalSvcName, instance, kubeClient, kubeConfig, logger) _, K8sExternalSvcIP, _ := GetSvcIp(instance.Spec.Catalog[Specidx].Name+"-0", k8sExternalSvcName, instance, kubeClient, kubeConfig, logger) - DbPasswordSecret := instance.Spec.Secret + DbPasswordSecret := instance.Spec.DbSecret.Name oracleSid := GetSidName(instance.Spec.Catalog[Specidx].EnvVars, instance.Spec.Catalog[Specidx].Name) oraclePdb := GetPdbName(instance.Spec.Catalog[Specidx].EnvVars, instance.Spec.Catalog[Specidx].Name) role := GetDbRole(instance.Spec.Catalog[Specidx].Name+"-0", instance, kubeClient, kubeConfig, logger) @@ -185,7 +185,7 @@ func UpdateShardStatusData(instance *databasealphav1.ShardingDatabase, Specidx i K8sInternalSvcName := svcName + "." + getInstanceNs(instance) + ".svc.cluster.local" _, K8sInternalSvcIP, _ := GetSvcIp(instance.Spec.Shard[Specidx].Name+"-0", K8sInternalSvcName, instance, kubeClient, kubeConfig, logger) _, K8sExternalSvcIP, _ := GetSvcIp(instance.Spec.Shard[Specidx].Name+"-0", k8sExternalSvcName, instance, kubeClient, kubeConfig, logger) - DbPasswordSecret := instance.Spec.Secret + DbPasswordSecret := instance.Spec.DbSecret.Name oracleSid := GetSidName(instance.Spec.Shard[Specidx].EnvVars, instance.Spec.Shard[Specidx].Name) oraclePdb := GetPdbName(instance.Spec.Shard[Specidx].EnvVars, instance.Spec.Shard[Specidx].Name) role := GetDbRole(instance.Spec.Shard[Specidx].Name+"-0", instance, kubeClient, kubeConfig, logger) @@ -347,7 +347,7 @@ func CheckGsmStatus(gname string, instance *databasealphav1.ShardingDatabase, ku return nil } -//============ Functiont o check the status of the Shard and catalog ========= +// ============ Functiont o check the status of the Shard and catalog ========= // ================================ Validate shard =========================== func ValidateDbSetup(podName string, instance *databasealphav1.ShardingDatabase, kubeClient kubernetes.Interface, kubeconfig clientcmd.ClientConfig, logger logr.Logger, ) error { diff --git a/commons/sharding/scommon.go b/commons/sharding/scommon.go index 5a25a78d..99987661 100644 --- a/commons/sharding/scommon.go +++ b/commons/sharding/scommon.go @@ -40,14 +40,19 @@ package commons import ( "context" + "encoding/json" "fmt" + "slices" databasealphav1 "github.com/oracle/oracle-database-operator/apis/database/v1alpha1" + databasev1alpha1 "github.com/oracle/oracle-database-operator/apis/database/v1alpha1" "regexp" "strconv" "strings" + "os" + "github.com/go-logr/logr" "github.com/oracle/oci-go-sdk/v65/common" "github.com/oracle/oci-go-sdk/v65/ons" @@ -77,6 +82,7 @@ const ( oraRunAsUser = int64(54321) oraFsGroup = int64(54321) oraScriptMount = "/opt/oracle/scripts/sharding/scripts" + oraDbScriptMount = "/opt/oracle/scripts/sharding" oraDataMount = "/opt/oracle/oradata" oraGsmDataMount = "/opt/oracle/gsmdata" oraConfigMapMount = "/mnt/config-map" @@ -91,6 +97,9 @@ const ( oraLocalOnsPort = 6123 oraAgentPort = 8080 ShardingDatabaseFinalizer = "Shardingdb.oracle.com" + TmpLoc = "/var/tmp" + connectFailureMaxTries = 5 + errorDialingBackendEOF = "error dialing backend: EOF" ) // Function to build the env var specification @@ -98,34 +107,28 @@ func buildEnvVarsSpec(instance *databasealphav1.ShardingDatabase, variables []da var result []corev1.EnvVar var varinfo string var sidFlag bool = false - var secretFlag bool = false - var pwdFileFLag bool = false - var pwdKeyFlag bool = false + //var sidValue string + var pdbValue string var pdbFlag bool = false var sDirectParam bool = false var sGroup1Params bool = false - var sGroup2Params bool = false + //var sGroup2Params bool = false var catalogParams bool = false var oldPdbFlag bool = false var oldSidFlag bool = false var archiveLogFlag bool = false var shardSetupFlag bool = false + var dbUnameFlag bool = false + var ofreePdbFlag bool = false for _, variable := range variables { if variable.Name == "ORACLE_SID" { sidFlag = true - } - if variable.Name == "SECRET_VOLUME" { - secretFlag = true - } - if variable.Name == "COMMON_OS_PWD_FILE" { - pwdFileFLag = true - } - if variable.Name == "PWD_KEY" { - pwdKeyFlag = true + //sidValue = variable.Value } if variable.Name == "ORACLE_PDB" { pdbFlag = true + pdbValue = variable.Value } if variable.Name == "SHARD_DIRECTOR_PARAMS" { sDirectParam = true @@ -133,9 +136,6 @@ func buildEnvVarsSpec(instance *databasealphav1.ShardingDatabase, variables []da if variable.Name == "SHARD1_GROUP_PARAMS" { sGroup1Params = true } - if variable.Name == "SHARD2_GROUP_PARAMS" { - sGroup2Params = true - } if variable.Name == "CATALOG_PARAMS" { catalogParams = true } @@ -151,8 +151,32 @@ func buildEnvVarsSpec(instance *databasealphav1.ShardingDatabase, variables []da if variable.Name == "OLD_ORACLE_PDB" { archiveLogFlag = true } + if variable.Name == "DB_UNIQUE_NAME" { + dbUnameFlag = true + } + if variable.Name == "ORACLE_FREE_PDB" { + ofreePdbFlag = true + } + result = append(result, corev1.EnvVar{Name: variable.Name, Value: variable.Value}) } + + if !dbUnameFlag { + if strings.ToLower(instance.Spec.DbEdition) == "free" { + result = append(result, corev1.EnvVar{Name: "DB_UNIQUE_NAME", Value: strings.ToUpper(name)}) + } + } + + if !ofreePdbFlag { + if strings.ToLower(instance.Spec.DbEdition) == "free" { + if pdbFlag { + result = append(result, corev1.EnvVar{Name: "ORACLE_FREE_PDB", Value: pdbValue}) + } else { + result = append(result, corev1.EnvVar{Name: "ORACLE_FREE_PDB", Value: strings.ToUpper(name) + "PDB"}) + } + } + } + if !shardSetupFlag { if restype == "SHARD" { result = append(result, corev1.EnvVar{Name: "SHARD_SETUP", Value: "true"}) @@ -172,46 +196,112 @@ func buildEnvVarsSpec(instance *databasealphav1.ShardingDatabase, variables []da result = append(result, corev1.EnvVar{Name: "ENABLE_ARCHIVELOG", Value: "true"}) } } - if !sidFlag { - if restype == "SHARD" { - result = append(result, corev1.EnvVar{Name: "ORACLE_SID", Value: strings.ToUpper(name)}) - } - if restype == "CATALOG" { - result = append(result, corev1.EnvVar{Name: "ORACLE_SID", Value: strings.ToUpper(name)}) + if strings.ToLower(instance.Spec.DbEdition) == "free" { + result = append(result, corev1.EnvVar{Name: "ORACLE_SID", Value: "FREE"}) + } else { + if restype == "SHARD" { + result = append(result, corev1.EnvVar{Name: "ORACLE_SID", Value: strings.ToUpper(name)}) + } + if restype == "CATALOG" { + result = append(result, corev1.EnvVar{Name: "ORACLE_SID", Value: strings.ToUpper(name)}) + } } } if !pdbFlag { - if restype == "SHARD" { - result = append(result, corev1.EnvVar{Name: "ORACLE_PDB", Value: strings.ToUpper(name) + "PDB"}) - } - if restype == "CATALOG" { - result = append(result, corev1.EnvVar{Name: "ORACLE_PDB", Value: strings.ToUpper(name) + "PDB"}) + if strings.ToLower(instance.Spec.DbEdition) == "free" { + result = append(result, corev1.EnvVar{Name: "ORACLE_PDB", Value: "FREEPDB"}) + } else { + if restype == "SHARD" { + result = append(result, corev1.EnvVar{Name: "ORACLE_PDB", Value: strings.ToUpper(name) + "PDB"}) + } + if restype == "CATALOG" { + result = append(result, corev1.EnvVar{Name: "ORACLE_PDB", Value: strings.ToUpper(name) + "PDB"}) + } } } - if !secretFlag { - result = append(result, corev1.EnvVar{Name: "SECRET_VOLUME", Value: "/mnt/secrets"}) + // Secret Settings + + if strings.ToLower(instance.Spec.DbSecret.EncryptionType) != "base64" { + result = append(result, corev1.EnvVar{Name: "PWD_KEY", Value: instance.Spec.DbSecret.KeyFileName}) + result = append(result, corev1.EnvVar{Name: "COMMON_OS_PWD_FILE", Value: instance.Spec.DbSecret.PwdFileName}) + } else { + result = append(result, corev1.EnvVar{Name: "PASSWORD_FILE", Value: instance.Spec.DbSecret.PwdFileName}) } - if !pwdFileFLag { - result = append(result, corev1.EnvVar{Name: "COMMON_OS_PWD_FILE", Value: "common_os_pwdfile.enc"}) + if len(instance.Spec.DbSecret.PwdFileMountLocation) != 0 { + result = append(result, corev1.EnvVar{Name: "SECRET_VOLUME", Value: instance.Spec.DbSecret.PwdFileMountLocation}) + } else { + result = append(result, corev1.EnvVar{Name: "SECRET_VOLUME", Value: oraSecretMount}) } - if !pwdKeyFlag { - result = append(result, corev1.EnvVar{Name: "PWD_KEY", Value: "pwd.key"}) + if len(instance.Spec.DbSecret.KeyFileMountLocation) != 0 { + result = append(result, corev1.EnvVar{Name: "KEY_SECRET_VOLUME", Value: instance.Spec.DbSecret.KeyFileMountLocation}) + } else { + result = append(result, corev1.EnvVar{Name: "KEY_SECRET_VOLUME", Value: oraSecretMount}) } + if restype == "GSM" { if !sDirectParam { - // varinfo = "director_name=sharddirector" + sDirectorCounter + ";director_region=primary;director_port=1521" + //varinfo = "director_name=sharddirector" + sDirectorCounter + ";director_region=primary;director_port=1521" varinfo = directorParams result = append(result, corev1.EnvVar{Name: "SHARD_DIRECTOR_PARAMS", Value: varinfo}) } - if !sGroup1Params { - varinfo = "group_name=shardgroup1;deploy_as=primary;group_region=primary" - result = append(result, corev1.EnvVar{Name: "SHARD1_GROUP_PARAMS", Value: varinfo}) + if strings.ToUpper(instance.Spec.ShardingType) != "USER" { + if !sGroup1Params { + if len(instance.Spec.GsmShardGroup) > 0 { + for i := 0; i < len(instance.Spec.GsmShardGroup); i++ { + if strings.ToUpper(instance.Spec.GsmShardGroup[i].DeployAs) == "PRIMARY" { + group_name := instance.Spec.GsmShardGroup[i].Name + //deploy_as := instance.Spec.ShardGroup[i].DeployAs + region := instance.Spec.GsmShardGroup[i].Region + varinfo = "group_name=" + group_name + ";" + "deploy_as=primary;" + "group_region=" + region + result = append(result, corev1.EnvVar{Name: "SHARD1_GROUP_PARAMS", Value: varinfo}) + } + if strings.ToUpper(instance.Spec.GsmShardGroup[i].DeployAs) == "STANDBY" { + group_name := instance.Spec.GsmShardGroup[i].Name + //deploy_as := instance.Spec.ShardGroup[i].DeployAs + region := instance.Spec.GsmShardGroup[i].Region + varinfo = "group_name=" + group_name + ";" + "deploy_as=standby;" + "group_region=" + region + result = append(result, corev1.EnvVar{Name: "SHARD2_GROUP_PARAMS", Value: varinfo}) + } + } + } + } else { + varinfo = "group_name=shardgroup1;deploy_as=primary;group_region=primary" + result = append(result, corev1.EnvVar{Name: "SHARD1_GROUP_PARAMS", Value: varinfo}) + } + } + + if strings.ToUpper(instance.Spec.ShardingType) == "USER" { + result = append(result, corev1.EnvVar{Name: "SHARDING_TYPE", Value: "USER"}) + } + // SERVICE Params setting + var svc string + if len(instance.Spec.GsmService) > 0 { + svc = "" + for i := 0; i < len(instance.Spec.GsmService); i++ { + svc = svc + "service_name=" + instance.Spec.GsmService[i].Name + ";" + if len(instance.Spec.GsmService[i].Role) != 0 { + svc = svc + "service_role=" + instance.Spec.GsmService[i].Role + } else { + svc = svc + "service_role=primary" + } + result = append(result, corev1.EnvVar{Name: "SERVICE" + fmt.Sprint(i) + "_PARAMS", Value: svc}) + svc = "" + } + } + + if strings.ToUpper(instance.Spec.GsmDevMode) != "FALSE" { + result = append(result, corev1.EnvVar{Name: "DEV_MODE", Value: "TRUE"}) + } + + if instance.Spec.InvitedNodeSubnetFlag == "" { + instance.Spec.InvitedNodeSubnetFlag = "FALSE" + } - if instance.Spec.IsDataGuard { - if !sGroup2Params { - varinfo = "group_name=shardgroup2;deploy_as=standby;group_region=standby" - result = append(result, corev1.EnvVar{Name: "SHARD2_GROUP_PARAMS", Value: varinfo}) + if strings.ToUpper(instance.Spec.InvitedNodeSubnetFlag) != "FALSE" { + result = append(result, corev1.EnvVar{Name: "INVITED_NODE_SUBNET_FLAG", Value: "TRUE"}) + if instance.Spec.InvitedNodeSubnet != "" { + result = append(result, corev1.EnvVar{Name: "INVITED_NODE_SUBNET", Value: instance.Spec.InvitedNodeSubnet}) } } if !catalogParams { @@ -625,34 +715,85 @@ func buildCatalogParams(instance *databasealphav1.ShardingDatabase) string { var sidFlag bool = false var pdbFlag bool = false var portFlag bool = false - var regionFlag bool = false var cnameFlag bool = false var chunksFlag bool = false var sidName string var pdbName string var cport string - var cregion string var cname string var catchunks string + var catalog_region, shard_space string result = "catalog_host=" + instance.Spec.Catalog[0].Name + "-0" + "." + instance.Spec.Catalog[0].Name + ";" + + //Checking if replcia type set to native + var sspace_arr []string + if strings.ToUpper(instance.Spec.ShardingType) == "USER" { + shard_space = "" + result = result + "sharding_type=user;" + for i := 0; i < len(instance.Spec.Shard); i++ { + sspace_arr = append(sspace_arr, instance.Spec.Shard[i].ShardSpace) + } + slices.Sort(sspace_arr) + sspace_arr = slices.Compact(sspace_arr) //[a b c d] + for i := 0; i < len(sspace_arr); i++ { + shard_space = shard_space + sspace_arr[i] + "," + } + shard_space = strings.TrimSuffix(shard_space, ",") + result = result + "shard_space=" + shard_space + ";" + } else if strings.ToUpper(instance.Spec.ReplicationType) == "NATIVE" { + result = result + "repl_type=native;" + } else { + fmt.Fprintln(os.Stdout, []any{""}...) + } + + var region_arr []string + for i := 0; i < len(instance.Spec.Shard); i++ { + region_arr = append(region_arr, instance.Spec.Shard[i].ShardRegion) + } + + for i := 0; i < len(instance.Spec.Gsm); i++ { + region_arr = append(region_arr, instance.Spec.Gsm[i].Region) + } + + slices.Sort(region_arr) + region_arr = slices.Compact(region_arr) //[a b c d] + for i := 0; i < len(region_arr); i++ { + catalog_region = catalog_region + region_arr[i] + "," + } + catalog_region = strings.TrimSuffix(catalog_region, ",") + result = result + "catalog_region=" + catalog_region + ";" + + if len(instance.Spec.ShardConfigName) != 0 { + result = result + "shard_configname=" + instance.Spec.ShardConfigName + ";" + } + for _, variable := range variables { - if variable.Name == "ORACLE_SID" { + if variable.Name == "DB_UNIQUE_NAME" { sidFlag = true sidName = variable.Value + } else { + if variable.Name == "ORACLE_SID" { + sidFlag = true + sidName = variable.Value + } } - if variable.Name == "ORACLE_PDB" { - pdbFlag = true - pdbName = variable.Value + if variable.Name == "ORACLE_FREE_PDB" { + if strings.ToLower(instance.Spec.DbEdition) == "free" { + pdbFlag = true + pdbName = variable.Value + } + } + if strings.ToLower(instance.Spec.DbEdition) != "free" { + if variable.Name == "ORACLE_PDB" { + pdbFlag = true + pdbName = variable.Value + } } if variable.Name == "CATALOG_PORT" { portFlag = true cport = variable.Value } - if variable.Name == "CATALOG_REGION" { - regionFlag = true - cregion = variable.Value - } if variable.Name == "CATALOG_NAME" { cnameFlag = true cname = variable.Value @@ -661,22 +802,33 @@ func buildCatalogParams(instance *databasealphav1.ShardingDatabase) string { chunksFlag = true catchunks = variable.Value } + } if !sidFlag { varinfo = "catalog_db=" + strings.ToUpper(instance.Spec.Catalog[0].Name) + ";" result = result + varinfo } else { - varinfo = "catalog_db=" + strings.ToUpper(sidName) + ";" - result = result + varinfo + if strings.ToLower(instance.Spec.DbEdition) == "free" { + varinfo = "catalog_db=" + strings.ToUpper(instance.Spec.Catalog[0].Name) + ";" + result = result + varinfo + } else { + varinfo = "catalog_db=" + strings.ToUpper(sidName) + ";" + result = result + varinfo + } } if !pdbFlag { varinfo = "catalog_pdb=" + strings.ToUpper(instance.Spec.Catalog[0].Name) + "PDB" + ";" result = result + varinfo } else { - varinfo = "catalog_pdb=" + strings.ToUpper(pdbName) + ";" - result = result + varinfo + if strings.ToLower(instance.Spec.DbEdition) == "free" { + varinfo = "catalog_pdb=" + strings.ToUpper(instance.Spec.Catalog[0].Name) + "PDB" + ";" + result = result + varinfo + } else { + varinfo = "catalog_pdb=" + strings.ToUpper(pdbName) + ";" + result = result + varinfo + } } if !portFlag { @@ -694,18 +846,15 @@ func buildCatalogParams(instance *databasealphav1.ShardingDatabase) string { varinfo = "catalog_name=" + strings.ToUpper(cname) + ";" result = result + varinfo } + if chunksFlag { result = result + "catalog_chunks=" + catchunks + ";" - } - - if !regionFlag { - varinfo = "catalog_region=primary,standby" - result = result + varinfo } else { - varinfo = "catalog_region=" + cregion - result = result + varinfo + if strings.ToLower(instance.Spec.DbEdition) == "free" && strings.ToUpper(instance.Spec.ShardingType) != "USER" && strings.ToUpper(instance.Spec.ShardingType) != "NATIVE" { + result = result + "catalog_chunks=12;" + } } - + result = strings.TrimSuffix(result, ";") return result } @@ -731,64 +880,137 @@ func buildDirectorParams(instance *databasealphav1.ShardingDatabase, oraGsmSpex result = result + varinfo } - switch idx { - case 0: - varinfo = "director_region=primary;" + if oraGsmSpex.Region != "" { + varinfo = "director_region=" + oraGsmSpex.Region + ";" result = result + varinfo - case 1: - varinfo = "director_region=standby;" + } else { + switch idx { + case 0: + varinfo = "director_region=primary;" + result = result + varinfo + case 1: + varinfo = "director_region=standby;" + result = result + varinfo + default: + // Do nothing + } result = result + varinfo - default: - // Do nothing } if !dportFlag { varinfo = "director_port=1522" result = result + varinfo } - + result = strings.TrimSuffix(result, ";") return result } -func BuildShardParams(sfSet *appsv1.StatefulSet) string { +func BuildShardParams(instance *databasealphav1.ShardingDatabase, sfSet *appsv1.StatefulSet, OraShardSpex databasev1alpha1.ShardSpec) string { var variables []corev1.EnvVar = sfSet.Spec.Template.Spec.Containers[0].Env var result string var varinfo string var isShardPort bool = false - var isShardGrp bool = false + var freePdbFlag bool = false + var freePdbValue string + var pdbFlag bool = false + var pdbValue string + var dbUnameFlag bool = false + var sidFlag bool = false + var dbUname string + var sidName string + + //var isShardGrp bool = false + //var i int32 + //var isShardSpace bool = false + //var isShardRegion bool = false result = "shard_host=" + sfSet.Name + "-0" + "." + sfSet.Name + ";" for _, variable := range variables { - if variable.Name == "ORACLE_SID" { - varinfo = "shard_db=" + variable.Value + ";" - result = result + varinfo + if variable.Name == "DB_UNIQUE_NAME" { + dbUnameFlag = true + dbUname = variable.Value + } else { + if variable.Name == "ORACLE_SID" { + sidFlag = true + sidName = variable.Value + } + } + if variable.Name == "ORACLE_FREE_PDB" { + freePdbFlag = true + freePdbValue = variable.Value } + if variable.Name == "ORACLE_PDB" { - varinfo = "shard_pdb=" + variable.Value + ";" - result = result + varinfo + pdbFlag = true + pdbValue = variable.Value } + if variable.Name == "SHARD_PORT" { varinfo = "shard_port=" + variable.Value + ";" result = result + varinfo isShardPort = true } - if variable.Name == "SHARD_GROUP" { - varinfo = "shard_group=" + variable.Value + ";" + + } + + if dbUnameFlag { + varinfo = "shard_db=" + dbUname + ";" + result = result + varinfo + } + + if sidFlag && !dbUnameFlag { + if strings.ToLower(instance.Spec.DbEdition) != "free" { + varinfo = "shard_db=" + sidName + ";" + result = result + varinfo + } else { + varinfo = "shard_db=" + sfSet.Name + ";" result = result + varinfo - isShardGrp = true } } - if !isShardPort { - varinfo = "shard_port=" + "1521" + ";" + if !sidFlag && !dbUnameFlag { + if strings.ToLower(instance.Spec.DbEdition) != "free" { + varinfo = "shard_db=" + sfSet.Name + ";" + result = result + varinfo + } + } + + if freePdbFlag { + if strings.ToLower(instance.Spec.DbEdition) == "free" { + varinfo = "shard_pdb=" + freePdbValue + ";" + result = result + varinfo + } + } else { + if pdbFlag { + varinfo = "shard_pdb=" + pdbValue + ";" + result = result + varinfo + } + } + + if OraShardSpex.ShardGroup != "" { + varinfo = "shard_group=" + OraShardSpex.ShardGroup + ";" + result = result + varinfo + } + + if OraShardSpex.ShardSpace != "" { + varinfo = "shard_space=" + OraShardSpex.ShardSpace + ";" + result = result + varinfo + } + if OraShardSpex.ShardRegion != "" { + varinfo = "shard_region=" + OraShardSpex.ShardRegion + ";" result = result + varinfo } - if !isShardGrp { - varinfo = "shard_group=" + "shardgroup1" + if OraShardSpex.DeployAs != "" { + varinfo = "deploy_as=" + OraShardSpex.DeployAs + ";" result = result + varinfo } + if !isShardPort { + varinfo = "shard_port=" + "1521" + ";" + result = result + varinfo + } + result = strings.TrimSuffix(result, ";") return result } @@ -858,7 +1080,7 @@ func getNoChunksCmd(sparamStr string) []string { func shardValidationCmd() []string { - var oraShardValidateCmd = []string{oraScriptMount + "/cmdExec", "/bin/python", oraScriptMount + "/main.py ", "--checkliveness=true ", "--optype=primaryshard"} + var oraShardValidateCmd = []string{oraDbScriptMount + "/cmdExec", "/bin/python", oraDbScriptMount + "/main.py ", "--checkliveness=true ", "--optype=primaryshard"} return oraShardValidateCmd } @@ -884,25 +1106,47 @@ func getShardDelCmd(sparams string) []string { func getLivenessCmd(resType string) []string { var livenessCmd []string if resType == "SHARD" { - livenessCmd = []string{oraScriptMount + "/cmdExec", "/bin/python", oraScriptMount + "/main.py ", "--checkliveness=true", "--optype=primaryshard"} + livenessCmd = []string{oraDbScriptMount + "/cmdExec", "/bin/python", oraDbScriptMount + "/main.py ", "--checkliveness=true", "--optype=primaryshard"} } if resType == "CATALOG" { - livenessCmd = []string{oraScriptMount + "/cmdExec", "/bin/python", oraScriptMount + "/main.py ", "--checkliveness=true", "--optype=catalog"} + livenessCmd = []string{oraDbScriptMount + "/cmdExec", "/bin/python", oraDbScriptMount + "/main.py ", "--checkliveness=true", "--optype=catalog"} } if resType == "GSM" { livenessCmd = []string{oraScriptMount + "/cmdExec", "/bin/python", oraScriptMount + "/main.py ", "--checkliveness=true", "--optype=gsm"} } if resType == "STANDBY" { - livenessCmd = []string{oraScriptMount + "/cmdExec", "/bin/python", oraScriptMount + "/main.py ", "--checkliveness=true", "--optype=standbyshard"} + livenessCmd = []string{oraDbScriptMount + "/cmdExec", "/bin/python", oraDbScriptMount + "/main.py ", "--checkliveness=true", "--optype=standbyshard"} } return livenessCmd } +func getReadinessCmd(resType string) []string { + var readynessCmd []string + if resType == "SHARD" { + readynessCmd = []string{oraDbScriptMount + "/cmdExec", "/bin/python", oraDbScriptMount + "/main.py ", "--checkreadyness=true", "--optype=primaryshard"} + } + if resType == "CATALOG" { + readynessCmd = []string{oraDbScriptMount + "/cmdExec", "/bin/python", oraDbScriptMount + "/main.py ", "--checkreadyness=true", "--optype=catalog"} + } + if resType == "GSM" { + readynessCmd = []string{oraScriptMount + "/cmdExec", "/bin/python", oraScriptMount + "/main.py ", "--checkreadyness=true", "--optype=gsm"} + } + if resType == "STANDBY" { + readynessCmd = []string{oraDbScriptMount + "/cmdExec", "/bin/python", oraDbScriptMount + "/main.py ", "--checkreadyness=true", "--optype=standbyshard"} + } + return readynessCmd +} + func getGsmShardValidateCmd(shardName string) []string { var validateCmd []string = []string{oraScriptMount + "/cmdExec", "/bin/python", oraScriptMount + "/main.py ", "--validateshard=" + strconv.Quote(shardName), "--optype=gsm"} return validateCmd } +func GetTdeKeyLocCmd() []string { + var tdeKeyCmd []string = []string{oraScriptMount + "/cmdExec", "/bin/python", oraScriptMount + "/main.py ", "--gettdekey=true", "--optype=gsm"} + return tdeKeyCmd +} + func getOnlineShardCmd(sparamStr string) []string { var onlineCmd []string = []string{oraScriptMount + "/cmdExec", "/bin/python", oraScriptMount + "/main.py ", "--checkonlineshard=" + strconv.Quote(sparamStr), "--optype=gsm"} return onlineCmd @@ -927,9 +1171,9 @@ func getInitContainerCmd(resType string, name string, ) string { var initCmd string if resType == "WEB" { - initCmd = "chown -R 54321:54321 " + oraScriptMount + ";chmod 755 " + oraScriptMount + "/*;chown -R 54321:54321 /opt/oracle/oradata;chmod 750 /opt/oracle/oradata" + initCmd = "chown -R 54321:54321 " + oraDbScriptMount + ";chmod 755 " + oraDbScriptMount + "/*;chown -R 54321:54321 /opt/oracle/oradata;chmod 750 /opt/oracle/oradata" } else { - initCmd = resType + ";chown -R 54321:54321 " + oraScriptMount + ";chmod 755 " + oraScriptMount + "/*;chown -R 54321:54321 /opt/oracle/oradata;chmod 750 /opt/oracle/oradata" + initCmd = resType + ";chown -R 54321:54321 " + oraDbScriptMount + ";chmod 755 " + oraDbScriptMount + "/*;chown -R 54321:54321 /opt/oracle/oradata;chmod 750 /opt/oracle/oradata" } return initCmd } @@ -945,6 +1189,11 @@ func getGsmInitContainerCmd(resType string, name string, return initCmd } +func getResetPasswdCmd(sparamStr string) []string { + var resetPasswdCmd []string = []string{oraScriptMount + "/cmdExec", "/bin/python", oraScriptMount + "/main.py ", "--resetpassword=true"} + return resetPasswdCmd +} + func GetFmtStr(pstr string, ) string { return "[" + pstr + "]" @@ -1081,7 +1330,7 @@ func CheckOnlineShardInGsm(gsmPodName string, sparams string, instance *database _, _, err := ExecCommand(gsmPodName, getOnlineShardCmd(sparams), kubeClient, kubeconfig, instance, logger) if err != nil { - msg := "Shard: " + GetFmtStr(sparams) + " is not onine in GSM." + msg := "Shard: " + GetFmtStr(sparams) + " is not online in GSM." LogMessages("INFO", msg, nil, instance, logger) return err } @@ -1231,6 +1480,28 @@ func SfsetLabelPatch(sfSetFound *appsv1.StatefulSet, sfSetPod *corev1.Pod, insta return nil } +func InstanceShardPatch(obj client.Object, instance *databasealphav1.ShardingDatabase, kClient client.Client, id int32, field string, value string, +) error { + + var err error + instSpec := instance.Spec + instSpec.Shard[id].IsDelete = "failed" + instshardM, _ := json.Marshal(struct { + Spec *databasealphav1.ShardingDatabaseSpec `json:"spec":` + }{ + Spec: &instSpec, + }) + + patch1 := client.RawPatch(types.MergePatchType, instshardM) + err = kClient.Patch(context.TODO(), obj, patch1) + + if err != nil { + return err + } + + return err +} + // Send Notification func SendNotification(title string, body string, instance *databasealphav1.ShardingDatabase, topicId string, rclient ons.NotificationDataPlaneClient, logger logr.Logger, @@ -1249,3 +1520,31 @@ func SendNotification(title string, body string, instance *databasealphav1.Shard LogMessages("DEBUG", msg, nil, instance, logger) } } + +func GetSecretMount() string { + return oraSecretMount +} + +func checkTdeWalletFlag(instance *databasev1alpha1.ShardingDatabase) bool { + if strings.ToLower(instance.Spec.IsTdeWallet) == "enable" { + return true + } + return false +} + +func CheckIsDeleteFlag(delStr string, instance *databasealphav1.ShardingDatabase, logger logr.Logger) bool { + if strings.ToLower(delStr) == "enable" { + return true + } + if strings.ToLower(delStr) == "failed" { + // LogMessages("INFO", "manual intervention required", nil, instance, logger) + } + return false +} + +func getTdeWalletMountLoc(instance *databasev1alpha1.ShardingDatabase) string { + if len(instance.Spec.TdeWalletPvcMountLocation) > 0 { + return instance.Spec.TdeWalletPvcMountLocation + } + return "/tdewallet/" + instance.Name +} diff --git a/commons/sharding/shard.go b/commons/sharding/shard.go index ecebf606..c76fc0e5 100644 --- a/commons/sharding/shard.go +++ b/commons/sharding/shard.go @@ -141,10 +141,14 @@ func buildPodSpecForShard(instance *databasev1alpha1.ShardingDatabase, OraShardS RunAsUser: &user, FSGroup: &group, }, - InitContainers: buildInitContainerSpecForShard(instance, OraShardSpex), - Containers: buildContainerSpecForShard(instance, OraShardSpex), - Volumes: buildVolumeSpecForShard(instance, OraShardSpex), + Containers: buildContainerSpecForShard(instance, OraShardSpex), + Volumes: buildVolumeSpecForShard(instance, OraShardSpex), } + + if (instance.Spec.IsDownloadScripts) && (instance.Spec.ScriptsLocation != "") { + spec.InitContainers = buildInitContainerSpecForShard(instance, OraShardSpex) + } + if len(instance.Spec.DbImagePullSecret) > 0 { spec.ImagePullSecrets = []corev1.LocalObjectReference{ { @@ -171,16 +175,10 @@ func buildVolumeSpecForShard(instance *databasev1alpha1.ShardingDatabase, OraSha Name: OraShardSpex.Name + "secretmap-vol3", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: instance.Spec.Secret, + SecretName: instance.Spec.DbSecret.Name, }, }, }, - { - Name: OraShardSpex.Name + "orascript-vol5", - VolumeSource: corev1.VolumeSource{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, - }, { Name: OraShardSpex.Name + "oradshm-vol6", VolumeSource: corev1.VolumeSource{ @@ -196,6 +194,15 @@ func buildVolumeSpecForShard(instance *databasev1alpha1.ShardingDatabase, OraSha if len(instance.Spec.StagePvcName) != 0 { result = append(result, corev1.Volume{Name: OraShardSpex.Name + "orastage-vol7", VolumeSource: corev1.VolumeSource{PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ClaimName: instance.Spec.StagePvcName}}}) } + if instance.Spec.IsDownloadScripts { + result = append(result, corev1.Volume{Name: OraShardSpex.Name + "orascript-vol5", VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}}}) + } + + if checkTdeWalletFlag(instance) { + if len(instance.Spec.FssStorageClass) == 0 && len(instance.Spec.TdeWalletPvc) > 0 { + result = append(result, corev1.Volume{Name: OraShardSpex.Name + "shared-storage-vol8", VolumeSource: corev1.VolumeSource{PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ClaimName: instance.Spec.TdeWalletPvc}}}) + } + } return result } @@ -209,7 +216,7 @@ func buildContainerSpecForShard(instance *databasev1alpha1.ShardingDatabase, Ora Image: instance.Spec.DbImage, SecurityContext: &corev1.SecurityContext{ Capabilities: &corev1.Capabilities{ - Add: []corev1.Capability{"NET_RAW"}, + Add: []corev1.Capability{corev1.Capability("NET_ADMIN"), corev1.Capability("SYS_NICE")}, }, }, Resources: corev1.ResourceRequirements{ @@ -218,28 +225,50 @@ func buildContainerSpecForShard(instance *databasev1alpha1.ShardingDatabase, Ora VolumeMounts: buildVolumeMountSpecForShard(instance, OraShardSpex), LivenessProbe: &corev1.Probe{ // TODO: Investigate if it's ok to call status every 10 seconds - FailureThreshold: int32(30), - PeriodSeconds: int32(240), - InitialDelaySeconds: int32(300), - TimeoutSeconds: int32(120), + FailureThreshold: int32(3), + InitialDelaySeconds: int32(30), + PeriodSeconds: func() int32 { + if instance.Spec.LivenessCheckPeriod > 0 { + return int32(instance.Spec.LivenessCheckPeriod) + } + return 60 + }(), + TimeoutSeconds: int32(30), ProbeHandler: corev1.ProbeHandler{ Exec: &corev1.ExecAction{ - Command: getLivenessCmd("SHARD"), + Command: []string{"/bin/sh", "-c", "if [ -f $ORACLE_BASE/checkDBLockStatus.sh ]; then $ORACLE_BASE/checkDBLockStatus.sh ; else $ORACLE_BASE/checkDBStatus.sh; fi "}, }, }, }, /** + ReadinessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + //Command: getReadinessCmd("SHARD"), + Command: []string{"/bin/sh", "-c", "if [ -f $ORACLE_BASE/checkDBLockStatus.sh ]; then $ORACLE_BASE/checkDBLockStatus.sh ; else $ORACLE_BASE/checkDBStatus.sh; fi "}, + }, + }, + InitialDelaySeconds: 20, + TimeoutSeconds: 20, + PeriodSeconds: func() int32 { + if instance.Spec.ReadinessCheckPeriod > 0 { + return int32(instance.Spec.ReadinessCheckPeriod) + } + return 60 + }(), + }, + **/ // Disabling this because ping stop working and sharding topologu never gets configured. StartupProbe: &corev1.Probe{ - FailureThreshold: int32(30), - PeriodSeconds: int32(180), - Handler: corev1.Handler{ + FailureThreshold: int32(30), + PeriodSeconds: int32(180), + InitialDelaySeconds: int32(30), + ProbeHandler: corev1.ProbeHandler{ Exec: &corev1.ExecAction{ - Command: getLivenessCmd("SHARD"), + Command: []string{"/bin/sh", "-c", "if [ -f $ORACLE_BASE/checkDBLockStatus.sh ]; then $ORACLE_BASE/checkDBLockStatus.sh ; else $ORACLE_BASE/checkDBStatus.sh; fi "}, }, }, }, - **/ Env: buildEnvVarsSpec(instance, OraShardSpex.EnvVars, OraShardSpex.Name, "SHARD", false, "NONE"), } @@ -257,10 +286,10 @@ func buildContainerSpecForShard(instance *databasev1alpha1.ShardingDatabase, Ora return result } -//Function to build the init Container Spec +// Function to build the init Container Spec func buildInitContainerSpecForShard(instance *databasev1alpha1.ShardingDatabase, OraShardSpex databasev1alpha1.ShardSpec) []corev1.Container { var result []corev1.Container - privFlag := true + privFlag := false var uid int64 = 0 // building the init Container Spec @@ -300,13 +329,25 @@ func buildVolumeMountSpecForShard(instance *databasev1alpha1.ShardingDatabase, O var result []corev1.VolumeMount result = append(result, corev1.VolumeMount{Name: OraShardSpex.Name + "secretmap-vol3", MountPath: oraSecretMount, ReadOnly: true}) result = append(result, corev1.VolumeMount{Name: OraShardSpex.Name + "-oradata-vol4", MountPath: oraDataMount}) - result = append(result, corev1.VolumeMount{Name: OraShardSpex.Name + "orascript-vol5", MountPath: oraScriptMount}) + if instance.Spec.IsDownloadScripts { + result = append(result, corev1.VolumeMount{Name: OraShardSpex.Name + "orascript-vol5", MountPath: oraDbScriptMount}) + } result = append(result, corev1.VolumeMount{Name: OraShardSpex.Name + "oradshm-vol6", MountPath: oraShm}) if len(instance.Spec.StagePvcName) != 0 { result = append(result, corev1.VolumeMount{Name: OraShardSpex.Name + "orastage-vol7", MountPath: oraStage}) } + if checkTdeWalletFlag(instance) { + if len(instance.Spec.FssStorageClass) > 0 && len(instance.Spec.TdeWalletPvc) == 0 { + result = append(result, corev1.VolumeMount{Name: instance.Name + "shared-storage" + instance.Spec.Catalog[0].Name + "-0", MountPath: getTdeWalletMountLoc(instance)}) + } else { + if len(instance.Spec.FssStorageClass) == 0 && len(instance.Spec.TdeWalletPvc) > 0 { + result = append(result, corev1.VolumeMount{Name: OraShardSpex.Name + "shared-storage-vol8", MountPath: getTdeWalletMountLoc(instance)}) + } + } + } + return result } @@ -331,7 +372,7 @@ func volumeClaimTemplatesForShard(instance *databasev1alpha1.ShardingDatabase, O corev1.ReadWriteOnce, }, StorageClassName: &instance.Spec.StorageClass, - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: corev1.ResourceList{ corev1.ResourceStorage: resource.MustParse(strconv.FormatInt(int64(OraShardSpex.StorageSizeInGb), 10) + "Gi"), }, @@ -439,7 +480,7 @@ func UpdateProvForShard(instance *databasev1alpha1.ShardingDatabase, OraShardSpe oraSpexRes := OraShardSpex.Resources if !reflect.DeepEqual(shardContaineRes, oraSpexRes) { - isUpdate = true + isUpdate = false } } } diff --git a/config/crd/bases/database.oracle.com_DbcsSystem.yaml b/config/crd/bases/database.oracle.com_DbcsSystem.yaml new file mode 100644 index 00000000..e933d5a4 --- /dev/null +++ b/config/crd/bases/database.oracle.com_DbcsSystem.yaml @@ -0,0 +1,240 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.1 + creationTimestamp: null + name: DbcsSystem.database.oracle.com +spec: + group: database.oracle.com + names: + kind: DbcsSystem + listKind: DbcsSystemList + plural: DbcsSystem + singular: dbcssystem + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: DbcsSystem is the Schema for the dbcssystems 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: DbcsSystemSpec defines the desired state of DbcsSystem + properties: + dbSystem: + properties: + availabilityDomain: + type: string + backupSubnetId: + type: string + clusterName: + type: string + compartmentId: + type: string + cpuCoreCount: + type: integer + dbAdminPaswordSecret: + type: string + dbBackupConfig: + description: DB Backup COnfig Network Struct + properties: + autoBackupEnabled: + type: boolean + autoBackupWindow: + type: string + backupDestinationDetails: + type: string + recoveryWindowsInDays: + type: integer + type: object + dbDomain: + type: string + dbEdition: + type: string + dbName: + type: string + dbUniqueName: + type: string + dbVersion: + type: string + dbWorkload: + type: string + diskRedundancy: + type: string + displayName: + type: string + domain: + type: string + faultDomains: + items: + type: string + type: array + hostName: + type: string + initialDataStorageSizeInGB: + type: integer + kmsKeyId: + type: string + kmsKeyVersionId: + type: string + licenseModel: + type: string + nodeCount: + type: integer + pdbName: + type: string + privateIp: + type: string + shape: + type: string + sshPublicKeys: + items: + type: string + type: array + storageManagement: + type: string + subnetId: + type: string + tags: + additionalProperties: + type: string + type: object + tdeWalletPasswordSecret: + type: string + timeZone: + type: string + required: + - availabilityDomain + - compartmentId + - dbAdminPaswordSecret + - hostName + - shape + - sshPublicKeys + - subnetId + type: object + hardLink: + type: boolean + id: + type: string + ociConfigMap: + type: string + ociSecret: + type: string + required: + - ociConfigMap + type: object + status: + description: DbcsSystemStatus defines the observed state of DbcsSystem + properties: + availabilityDomain: + type: string + cpuCoreCount: + type: integer + dataStoragePercentage: + type: integer + dataStorageSizeInGBs: + type: integer + dbEdition: + type: string + dbInfo: + items: + description: DbcsSystemStatus defines the observed state of DbcsSystem + properties: + dbHomeId: + type: string + dbName: + type: string + dbUniqueName: + type: string + dbWorkload: + type: string + id: + type: string + type: object + type: array + displayName: + type: string + id: + type: string + licenseModel: + type: string + network: + properties: + clientSubnet: + type: string + domainName: + type: string + hostName: + type: string + listenerPort: + type: integer + networkSG: + type: string + scanDnsName: + type: string + vcnName: + type: string + type: object + nodeCount: + type: integer + recoStorageSizeInGB: + type: integer + shape: + type: string + state: + type: string + storageManagement: + type: string + subnetId: + type: string + timeZone: + type: string + workRequests: + items: + properties: + operationId: + type: string + operationType: + type: string + percentComplete: + type: string + timeAccepted: + type: string + timeFinished: + type: string + timeStarted: + type: string + required: + - operationId + - operationType + type: object + type: array + required: + - state + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crd/bases/database.oracle.com_autonomousdatabasebackups.yaml b/config/crd/bases/database.oracle.com_autonomousdatabasebackups.yaml index 0541b985..a5c37507 100644 --- a/config/crd/bases/database.oracle.com_autonomousdatabasebackups.yaml +++ b/config/crd/bases/database.oracle.com_autonomousdatabasebackups.yaml @@ -61,6 +61,8 @@ spec: type: string displayName: type: string + isLongTermBackup: + type: boolean ociConfig: description: "*********************** *\tOCI config ***********************" properties: @@ -69,6 +71,8 @@ spec: secretName: type: string type: object + retentionPeriodInDays: + type: integer target: description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster Important: Run "make" to regenerate code after modifying this file' diff --git a/config/crd/bases/database.oracle.com_autonomousdatabases.yaml b/config/crd/bases/database.oracle.com_autonomousdatabases.yaml index c70b9dd6..f77407f3 100644 --- a/config/crd/bases/database.oracle.com_autonomousdatabases.yaml +++ b/config/crd/bases/database.oracle.com_autonomousdatabases.yaml @@ -228,6 +228,79 @@ spec: - connectionStrings type: object type: array + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n \ttype FooStatus struct{ \t // Represents the observations + of a foo's current state. \t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\" \t // + +patchMergeKey=type \t // +patchStrategy=merge \t // +listType=map + \t // +listMapKey=type \t Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n \t // other fields + \t}" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map lifecycleState: description: 'INSERT ADDITIONAL STATUS FIELD - define observed state of cluster Important: Run "make" to regenerate code after modifying @@ -235,6 +308,8 @@ spec: type: string timeCreated: type: string + walletExpiringDate: + type: string type: object type: object served: true diff --git a/config/crd/bases/database.oracle.com_dataguardbrokers.yaml b/config/crd/bases/database.oracle.com_dataguardbrokers.yaml index b5fc87c4..f19a3e22 100644 --- a/config/crd/bases/database.oracle.com_dataguardbrokers.yaml +++ b/config/crd/bases/database.oracle.com_dataguardbrokers.yaml @@ -88,6 +88,10 @@ spec: - MaxPerformance - MaxAvailability type: string + serviceAnnotations: + additionalProperties: + type: string + type: object setAsPrimaryDatabase: type: string standbyDatabaseRefs: diff --git a/config/crd/bases/database.oracle.com_pdbs.yaml b/config/crd/bases/database.oracle.com_pdbs.yaml index 1bc8d905..85af8c1b 100644 --- a/config/crd/bases/database.oracle.com_pdbs.yaml +++ b/config/crd/bases/database.oracle.com_pdbs.yaml @@ -119,9 +119,17 @@ spec: to plug in a PDB. This property is applicable when the Action property is PLUG but not required. type: boolean + assertivePdbDeletion: + description: turn on the assertive approach to delete pdb resource + kubectl delete pdb ..... automatically triggers the pluggable database + deletion + type: boolean cdbName: description: Name of the CDB type: string + cdbNamespace: + description: CDB Namespace + type: string cdbResName: description: Name of the CDB Custom Resource that runs the ORDS container type: string @@ -290,6 +298,41 @@ spec: storage. Even when set to true, totalSize and tempSize MUST be specified in the request if Action is Create. type: boolean + webServerPwd: + description: Password for the Web ServerPDB User + properties: + secret: + description: PDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object + webServerUser: + description: Web Server User with SQL Administrator role to allow + us to authenticate to the PDB Lifecycle Management REST endpoints + properties: + secret: + description: PDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object xmlFileName: description: XML metadata filename to be used for Plug or Unplug operations type: string diff --git a/config/crd/bases/database.oracle.com_shardingdatabases.yaml b/config/crd/bases/database.oracle.com_shardingdatabases.yaml index 47432123..641629a0 100644 --- a/config/crd/bases/database.oracle.com_shardingdatabases.yaml +++ b/config/crd/bases/database.oracle.com_shardingdatabases.yaml @@ -16,7 +16,18 @@ spec: singular: shardingdatabase scope: Namespaced versions: - - name: v1alpha1 + - additionalPrinterColumns: + - jsonPath: .status.gsm.state + name: Gsm State + type: string + - jsonPath: .status.gsm.services + name: Services + type: string + - jsonPath: .status.gsm.shards + name: shards + priority: 1 + type: string + name: v1alpha1 schema: openAPIV3Schema: description: ShardingDatabase is the Schema for the shardingdatabases API @@ -36,6 +47,8 @@ spec: spec: description: ShardingDatabaseSpec defines the desired state of ShardingDatabase properties: + InvitedNodeSubnet: + type: string catalog: items: description: CatalogSpec defines the desired state of CatalogSpec @@ -59,7 +72,7 @@ spec: a container image type: string isDelete: - type: boolean + type: string label: type: string name: @@ -82,6 +95,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -102,8 +137,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. More info: - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object storageSizeInGb: @@ -113,15 +148,49 @@ spec: - name type: object type: array + dbEdition: + type: string dbImage: type: string dbImagePullSecret: type: string + dbSecret: + description: Secret Details + properties: + encryptionType: + type: string + keyFileMountLocation: + type: string + keyFileName: + type: string + keySecretName: + type: string + name: + type: string + nsConfigMap: + type: string + nsSecret: + type: string + pwdFileMountLocation: + type: string + pwdFileName: + type: string + required: + - name + - pwdFileName + type: object + fssStorageClass: + type: string gsm: items: description: GsmSpec defines the desired state of GsmSpec properties: + directorName: + type: string envVars: + description: Replicas int32 `json:"replicas,omitempty"` // + Gsm Replicas. If you set OraGsmPvcName then it is set default + to 1. items: description: EnvironmentVariable represents a named variable accessible for containers. @@ -140,7 +209,7 @@ spec: a container image type: string isDelete: - type: boolean + type: string label: type: string name: @@ -155,13 +224,34 @@ spec: type: object pvcName: type: string - replicas: - format: int32 - type: integer + region: + type: string resources: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -182,8 +272,8 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. More info: - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object storageSizeInGb: @@ -193,10 +283,109 @@ spec: - name type: object type: array + gsmDevMode: + type: string gsmImage: type: string gsmImagePullSecret: type: string + gsmService: + items: + description: Service Definition + properties: + available: + type: string + clbGoal: + type: string + commitOutcome: + type: string + drainTimeout: + type: string + dtp: + type: string + edition: + type: string + failoverDelay: + type: string + failoverMethod: + type: string + failoverPrimary: + type: string + failoverRestore: + type: string + failoverRetry: + type: string + failoverType: + type: string + gdsPool: + type: string + lag: + type: integer + locality: + type: string + name: + type: string + notification: + type: string + pdbName: + type: string + policy: + type: string + preferred: + type: string + prferredAll: + type: string + regionFailover: + type: string + retention: + type: string + role: + type: string + sessionState: + type: string + sqlTransactionProfile: + type: string + stopOption: + type: string + tableFamily: + type: string + tfaPolicy: + type: string + required: + - name + type: object + type: array + gsmShardGroup: + items: + properties: + deployAs: + type: string + name: + type: string + region: + type: string + required: + - name + type: object + type: array + gsmShardSpace: + items: + description: ShardSpace Specs + properties: + chunks: + type: integer + name: + type: string + protectionMode: + type: string + shardGroup: + type: string + required: + - name + type: object + type: array + invitedNodeSubnetFlag: + type: string isClone: type: boolean isDataGuard: @@ -205,13 +394,15 @@ spec: type: boolean isDeleteOraPvc: type: boolean + isDownloadScripts: + type: boolean isExternalSvc: type: boolean - namespace: + isTdeWallet: type: string - nsConfigMap: - type: string - nsSecret: + liveinessCheckPeriod: + type: integer + namespace: type: string portMappings: items: @@ -233,9 +424,11 @@ spec: - targetPort type: object type: array - scriptsLocation: + readinessCheckPeriod: + type: integer + replicationType: type: string - secret: + scriptsLocation: type: string shard: description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster @@ -244,6 +437,8 @@ spec: description: ShardSpec is a specification of Shards for an application deployment. properties: + deployAs: + type: string envVars: items: description: EnvironmentVariable represents a named variable @@ -263,7 +458,12 @@ spec: a container image type: string isDelete: - type: boolean + enum: + - enable + - disable + - failed + - force + type: string label: type: string name: @@ -286,6 +486,28 @@ spec: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -306,10 +528,16 @@ spec: description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. More info: - https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + shardGroup: + type: string + shardRegion: + type: string + shardSpace: + type: string storageSizeInGb: format: int32 type: integer @@ -317,16 +545,29 @@ spec: - name type: object type: array + shardBuddyRegion: + type: string + shardConfigName: + type: string + shardRegion: + items: + type: string + type: array + shardingType: + type: string stagePvcName: type: string storageClass: type: string + tdeWalletPvc: + type: string + tdeWalletPvcMountLocation: + type: string required: - catalog - dbImage - gsm - gsmImage - - secret - shard type: object status: diff --git a/config/crd/bases/database.oracle.com_singleinstancedatabases.yaml b/config/crd/bases/database.oracle.com_singleinstancedatabases.yaml index 83f6b3cf..1c011e17 100644 --- a/config/crd/bases/database.oracle.com_singleinstancedatabases.yaml +++ b/config/crd/bases/database.oracle.com_singleinstancedatabases.yaml @@ -89,10 +89,12 @@ spec: type: boolean charset: type: string - cloneFrom: + createAs: + enum: + - primary + - standby + - clone type: string - createAsStandby: - type: boolean dgBrokerConfigured: type: boolean edition: @@ -100,6 +102,7 @@ spec: - standard - enterprise - express + - free type: string enableTCPS: type: boolean @@ -153,14 +156,18 @@ spec: - ReadWriteOnce - ReadWriteMany type: string + datafilesVolumeName: + type: string + scriptsVolumeName: + type: string + setWritePermissions: + type: boolean size: type: string storageClass: type: string volumeClaimAnnotation: type: string - volumeName: - type: string type: object primaryDatabaseRef: type: string @@ -168,6 +175,23 @@ spec: type: integer replicas: type: integer + resources: + properties: + limits: + properties: + cpu: + type: string + memory: + type: string + type: object + requests: + properties: + cpu: + type: string + memory: + type: string + type: object + type: object serviceAccountName: type: string serviceAnnotations: @@ -184,6 +208,8 @@ spec: type: string tcpsListenerPort: type: integer + tcpsTlsSecret: + type: string required: - image type: object @@ -203,8 +229,6 @@ spec: type: string clientWalletLoc: type: string - cloneFrom: - type: string clusterConnectString: type: string conditions: @@ -282,6 +306,8 @@ spec: x-kubernetes-list-type: map connectString: type: string + createdAs: + type: string datafilesCreated: default: "false" type: string @@ -336,14 +362,18 @@ spec: - ReadWriteOnce - ReadWriteMany type: string + datafilesVolumeName: + type: string + scriptsVolumeName: + type: string + setWritePermissions: + type: boolean size: type: string storageClass: type: string volumeClaimAnnotation: type: string - volumeName: - type: string type: object prebuiltDB: type: boolean @@ -367,9 +397,13 @@ spec: type: string tcpsPdbConnectString: type: string + tcpsTlsSecret: + default: "" + type: string required: - isTcpsEnabled - persistence + - tcpsTlsSecret type: object type: object served: true diff --git a/config/crd/bases/observability.oracle.com_databaseobservers.yaml b/config/crd/bases/observability.oracle.com_databaseobservers.yaml new file mode 100644 index 00000000..b0801738 --- /dev/null +++ b/config/crd/bases/observability.oracle.com_databaseobservers.yaml @@ -0,0 +1,227 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.1 + creationTimestamp: null + name: databaseobservers.observability.oracle.com +spec: + group: observability.oracle.com + names: + kind: DatabaseObserver + listKind: DatabaseObserverList + plural: databaseobservers + singular: databaseobserver + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.exporterConfig + name: ExporterConfig + type: string + - jsonPath: .status.status + name: Status + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: DatabaseObserver is the Schema for the databaseobservers 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: DatabaseObserverSpec defines the desired state of DatabaseObserver + properties: + database: + description: DatabaseObserverDatabase defines the database details + used for DatabaseObserver + properties: + dbConnectionString: + properties: + key: + type: string + secret: + type: string + type: object + dbPassword: + properties: + key: + type: string + secret: + type: string + vaultOCID: + type: string + vaultSecretName: + type: string + type: object + dbUser: + properties: + key: + type: string + secret: + type: string + type: object + dbWallet: + properties: + key: + type: string + secret: + type: string + type: object + type: object + exporter: + description: DatabaseObserverExporterConfig defines the configuration + details related to the exporters of DatabaseObserver + properties: + configuration: + properties: + configmap: + description: ConfigMapDetails defines the configmap name + properties: + configmapName: + type: string + key: + type: string + type: object + type: object + image: + type: string + service: + description: DatabaseObserverService defines the exporter service + component of DatabaseObserver + properties: + port: + format: int32 + type: integer + type: object + type: object + ociConfig: + properties: + configMapName: + type: string + secretName: + type: string + type: object + prometheus: + description: PrometheusConfig defines the generated resources for + Prometheus + properties: + labels: + additionalProperties: + type: string + type: object + port: + type: string + type: object + replicas: + format: int32 + type: integer + type: object + status: + description: DatabaseObserverStatus defines the observed state of DatabaseObserver + properties: + conditions: + description: 'INSERT ADDITIONAL STATUS FIELD - define observed state + of cluster Important: Run "make" to regenerate code after modifying + this file' + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n \ttype FooStatus struct{ \t // Represents the observations + of a foo's current state. \t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\" \t // + +patchMergeKey=type \t // +patchStrategy=merge \t // +listType=map + \t // +listMapKey=type \t Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n \t // other fields + \t}" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + exporterConfig: + type: string + replicas: + type: integer + status: + type: string + required: + - conditions + - exporterConfig + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index c411e3ed..b9f3aa8c 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -17,6 +17,7 @@ resources: - bases/database.oracle.com_autonomouscontainerdatabases.yaml - bases/database.oracle.com_dbcssystems.yaml - bases/database.oracle.com_dataguardbrokers.yaml +- bases/observability.oracle.com_databaseobservers.yaml # +kubebuilder:scaffold:crdkustomizeresource patchesStrategicMerge: @@ -32,6 +33,7 @@ patchesStrategicMerge: #- patches/webhook_in_autonomouscontainerdatabases.yaml #- patches/webhook_in_dbcssystems.yaml #- patches/webhook_in_dataguardbrokers.yaml +#- patches/webhook_in_databaseobservers.yaml # +kubebuilder:scaffold:crdkustomizewebhookpatch # [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. @@ -46,6 +48,7 @@ patchesStrategicMerge: #- patches/cainjection_in_autonomouscontainerdatabases.yaml #- patches/cainjection_in_dbcssystems.yaml #- patches/cainjection_in_dataguardbrokers.yaml +#- patches/cainjection_in_databaseobservers.yaml # +kubebuilder:scaffold:crdkustomizecainjectionpatch # the following config is for teaching kustomize how to do kustomization for CRDs. diff --git a/config/crd/patches/cainjenction_in_databaseobservers.yaml b/config/crd/patches/cainjenction_in_databaseobservers.yaml new file mode 100644 index 00000000..278ea7fa --- /dev/null +++ b/config/crd/patches/cainjenction_in_databaseobservers.yaml @@ -0,0 +1,8 @@ +# The following patch adds a directive for certmanager to inject CA into the CRD +# CRD conversion requires k8s 1.13 or later. +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) + name: databaseobservers.observability.oracle.com \ No newline at end of file diff --git a/config/crd/patches/webhook_in_databaseobservers.yaml b/config/crd/patches/webhook_in_databaseobservers.yaml new file mode 100644 index 00000000..e61411df --- /dev/null +++ b/config/crd/patches/webhook_in_databaseobservers.yaml @@ -0,0 +1,17 @@ +# The following patch enables conversion webhook for CRD +# CRD conversion requires k8s 1.13 or later. +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + name: databaseobservers.observability.oracle.com +spec: + conversion: + strategy: Webhook + webhookClientConfig: + # this is "\n" used as a placeholder, otherwise it will be rejected by the apiserver for being blank, + # but we're going to set it later using the cert-manager (or potentially a patch if not using cert-manager) + caBundle: Cg== + service: + namespace: system + name: webhook-service + path: /convert \ No newline at end of file diff --git a/config/database.oracle.com_DbcsSystem.yaml b/config/database.oracle.com_DbcsSystem.yaml new file mode 100644 index 00000000..e933d5a4 --- /dev/null +++ b/config/database.oracle.com_DbcsSystem.yaml @@ -0,0 +1,240 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.1 + creationTimestamp: null + name: DbcsSystem.database.oracle.com +spec: + group: database.oracle.com + names: + kind: DbcsSystem + listKind: DbcsSystemList + plural: DbcsSystem + singular: dbcssystem + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: DbcsSystem is the Schema for the dbcssystems 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: DbcsSystemSpec defines the desired state of DbcsSystem + properties: + dbSystem: + properties: + availabilityDomain: + type: string + backupSubnetId: + type: string + clusterName: + type: string + compartmentId: + type: string + cpuCoreCount: + type: integer + dbAdminPaswordSecret: + type: string + dbBackupConfig: + description: DB Backup COnfig Network Struct + properties: + autoBackupEnabled: + type: boolean + autoBackupWindow: + type: string + backupDestinationDetails: + type: string + recoveryWindowsInDays: + type: integer + type: object + dbDomain: + type: string + dbEdition: + type: string + dbName: + type: string + dbUniqueName: + type: string + dbVersion: + type: string + dbWorkload: + type: string + diskRedundancy: + type: string + displayName: + type: string + domain: + type: string + faultDomains: + items: + type: string + type: array + hostName: + type: string + initialDataStorageSizeInGB: + type: integer + kmsKeyId: + type: string + kmsKeyVersionId: + type: string + licenseModel: + type: string + nodeCount: + type: integer + pdbName: + type: string + privateIp: + type: string + shape: + type: string + sshPublicKeys: + items: + type: string + type: array + storageManagement: + type: string + subnetId: + type: string + tags: + additionalProperties: + type: string + type: object + tdeWalletPasswordSecret: + type: string + timeZone: + type: string + required: + - availabilityDomain + - compartmentId + - dbAdminPaswordSecret + - hostName + - shape + - sshPublicKeys + - subnetId + type: object + hardLink: + type: boolean + id: + type: string + ociConfigMap: + type: string + ociSecret: + type: string + required: + - ociConfigMap + type: object + status: + description: DbcsSystemStatus defines the observed state of DbcsSystem + properties: + availabilityDomain: + type: string + cpuCoreCount: + type: integer + dataStoragePercentage: + type: integer + dataStorageSizeInGBs: + type: integer + dbEdition: + type: string + dbInfo: + items: + description: DbcsSystemStatus defines the observed state of DbcsSystem + properties: + dbHomeId: + type: string + dbName: + type: string + dbUniqueName: + type: string + dbWorkload: + type: string + id: + type: string + type: object + type: array + displayName: + type: string + id: + type: string + licenseModel: + type: string + network: + properties: + clientSubnet: + type: string + domainName: + type: string + hostName: + type: string + listenerPort: + type: integer + networkSG: + type: string + scanDnsName: + type: string + vcnName: + type: string + type: object + nodeCount: + type: integer + recoStorageSizeInGB: + type: integer + shape: + type: string + state: + type: string + storageManagement: + type: string + subnetId: + type: string + timeZone: + type: string + workRequests: + items: + properties: + operationId: + type: string + operationType: + type: string + percentComplete: + type: string + timeAccepted: + type: string + timeFinished: + type: string + timeStarted: + type: string + required: + - operationId + - operationType + type: object + type: array + required: + - state + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/database.oracle.com_autonomouscontainerdatabases.yaml b/config/database.oracle.com_autonomouscontainerdatabases.yaml new file mode 100644 index 00000000..bac3a28c --- /dev/null +++ b/config/database.oracle.com_autonomouscontainerdatabases.yaml @@ -0,0 +1,117 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.1 + creationTimestamp: null + name: autonomouscontainerdatabases.database.oracle.com +spec: + group: database.oracle.com + names: + kind: AutonomousContainerDatabase + listKind: AutonomousContainerDatabaseList + plural: autonomouscontainerdatabases + shortNames: + - acd + - acds + singular: autonomouscontainerdatabase + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.displayName + name: DisplayName + type: string + - jsonPath: .status.lifecycleState + name: State + type: string + - jsonPath: .status.timeCreated + name: Created + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: AutonomousContainerDatabase is the Schema for the autonomouscontainerdatabases + 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: AutonomousContainerDatabaseSpec defines the desired state + of AutonomousContainerDatabase + properties: + action: + enum: + - SYNC + - RESTART + - TERMINATE + type: string + autonomousContainerDatabaseOCID: + description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + Important: Run "make" to regenerate code after modifying this file' + type: string + autonomousExadataVMClusterOCID: + type: string + compartmentOCID: + type: string + displayName: + type: string + freeformTags: + additionalProperties: + type: string + type: object + hardLink: + default: false + type: boolean + ociConfig: + description: "*********************** *\tOCI config ***********************" + properties: + configMapName: + type: string + secretName: + type: string + type: object + patchModel: + description: 'AutonomousContainerDatabasePatchModelEnum Enum with + underlying type: string' + enum: + - RELEASE_UPDATES + - RELEASE_UPDATE_REVISIONS + type: string + type: object + status: + description: AutonomousContainerDatabaseStatus defines the observed state + of AutonomousContainerDatabase + properties: + lifecycleState: + description: 'INSERT ADDITIONAL STATUS FIELD - define observed state + of cluster Important: Run "make" to regenerate code after modifying + this file' + type: string + timeCreated: + type: string + required: + - lifecycleState + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/database.oracle.com_autonomousdatabasebackups.yaml b/config/database.oracle.com_autonomousdatabasebackups.yaml new file mode 100644 index 00000000..a5c37507 --- /dev/null +++ b/config/database.oracle.com_autonomousdatabasebackups.yaml @@ -0,0 +1,138 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.1 + creationTimestamp: null + name: autonomousdatabasebackups.database.oracle.com +spec: + group: database.oracle.com + names: + kind: AutonomousDatabaseBackup + listKind: AutonomousDatabaseBackupList + plural: autonomousdatabasebackups + shortNames: + - adbbu + - adbbus + singular: autonomousdatabasebackup + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.lifecycleState + name: State + type: string + - jsonPath: .status.dbDisplayName + name: DB DisplayName + type: string + - jsonPath: .status.type + name: Type + type: string + - jsonPath: .status.timeStarted + name: Started + type: string + - jsonPath: .status.timeEnded + name: Ended + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: AutonomousDatabaseBackup is the Schema for the autonomousdatabasebackups + 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: AutonomousDatabaseBackupSpec defines the desired state of + AutonomousDatabaseBackup + properties: + autonomousDatabaseBackupOCID: + type: string + displayName: + type: string + isLongTermBackup: + type: boolean + ociConfig: + description: "*********************** *\tOCI config ***********************" + properties: + configMapName: + type: string + secretName: + type: string + type: object + retentionPeriodInDays: + type: integer + target: + description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + Important: Run "make" to regenerate code after modifying this file' + properties: + k8sADB: + description: "*********************** *\tADB spec ***********************" + properties: + name: + type: string + type: object + ociADB: + properties: + ocid: + type: string + type: object + type: object + type: object + status: + description: AutonomousDatabaseBackupStatus defines the observed state + of AutonomousDatabaseBackup + properties: + autonomousDatabaseOCID: + type: string + compartmentOCID: + type: string + dbDisplayName: + type: string + dbName: + type: string + isAutomatic: + type: boolean + lifecycleState: + description: 'AutonomousDatabaseBackupLifecycleStateEnum Enum with + underlying type: string' + type: string + timeEnded: + type: string + timeStarted: + type: string + type: + description: 'AutonomousDatabaseBackupTypeEnum Enum with underlying + type: string' + type: string + required: + - autonomousDatabaseOCID + - compartmentOCID + - dbDisplayName + - dbName + - isAutomatic + - lifecycleState + - type + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/database.oracle.com_autonomousdatabaserestores.yaml b/config/database.oracle.com_autonomousdatabaserestores.yaml new file mode 100644 index 00000000..5e9f2c73 --- /dev/null +++ b/config/database.oracle.com_autonomousdatabaserestores.yaml @@ -0,0 +1,138 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.1 + creationTimestamp: null + name: autonomousdatabaserestores.database.oracle.com +spec: + group: database.oracle.com + names: + kind: AutonomousDatabaseRestore + listKind: AutonomousDatabaseRestoreList + plural: autonomousdatabaserestores + shortNames: + - adbr + - adbrs + singular: autonomousdatabaserestore + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.status + name: Status + type: string + - jsonPath: .status.displayName + name: DbDisplayName + type: string + - jsonPath: .status.dbName + name: DbName + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: AutonomousDatabaseRestore is the Schema for the autonomousdatabaserestores + 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: AutonomousDatabaseRestoreSpec defines the desired state of + AutonomousDatabaseRestore + properties: + ociConfig: + description: "*********************** *\tOCI config ***********************" + properties: + configMapName: + type: string + secretName: + type: string + type: object + source: + properties: + k8sADBBackup: + description: 'EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO + OWN! NOTE: json tags are required. Any new fields you add must + have json tags for the fields to be serialized.' + properties: + name: + type: string + type: object + pointInTime: + properties: + timestamp: + description: 'The timestamp must follow this format: YYYY-MM-DD + HH:MM:SS GMT' + type: string + type: object + type: object + target: + description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + Important: Run "make" to regenerate code after modifying this file' + properties: + k8sADB: + description: "*********************** *\tADB spec ***********************" + properties: + name: + type: string + type: object + ociADB: + properties: + ocid: + type: string + type: object + type: object + required: + - source + - target + type: object + status: + description: AutonomousDatabaseRestoreStatus defines the observed state + of AutonomousDatabaseRestore + properties: + dbName: + type: string + displayName: + description: 'INSERT ADDITIONAL STATUS FIELD - define observed state + of cluster Important: Run "make" to regenerate code after modifying + this file' + type: string + status: + description: 'WorkRequestStatusEnum Enum with underlying type: string' + type: string + timeAccepted: + type: string + timeEnded: + type: string + timeStarted: + type: string + workRequestOCID: + type: string + required: + - dbName + - displayName + - status + - workRequestOCID + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/database.oracle.com_autonomousdatabases.yaml b/config/database.oracle.com_autonomousdatabases.yaml new file mode 100644 index 00000000..f77407f3 --- /dev/null +++ b/config/database.oracle.com_autonomousdatabases.yaml @@ -0,0 +1,324 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.1 + creationTimestamp: null + name: autonomousdatabases.database.oracle.com +spec: + group: database.oracle.com + names: + kind: AutonomousDatabase + listKind: AutonomousDatabaseList + plural: autonomousdatabases + shortNames: + - adb + - adbs + singular: autonomousdatabase + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.details.displayName + name: Display Name + type: string + - jsonPath: .spec.details.dbName + name: Db Name + type: string + - jsonPath: .status.lifecycleState + name: State + type: string + - jsonPath: .spec.details.isDedicated + name: Dedicated + type: string + - jsonPath: .spec.details.cpuCoreCount + name: OCPUs + type: integer + - jsonPath: .spec.details.dataStorageSizeInTBs + name: Storage (TB) + type: integer + - jsonPath: .spec.details.dbWorkload + name: Workload Type + type: string + - jsonPath: .status.timeCreated + name: Created + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: AutonomousDatabase is the Schema for the autonomousdatabases + 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: 'AutonomousDatabaseSpec defines the desired state of AutonomousDatabase + Important: Run "make" to regenerate code after modifying this file' + properties: + details: + description: AutonomousDatabaseDetails defines the detail information + of AutonomousDatabase, corresponding to oci-go-sdk/database/AutonomousDatabase + properties: + adminPassword: + properties: + k8sSecret: + description: "*********************** *\tSecret specs ***********************" + properties: + name: + type: string + type: object + ociSecret: + properties: + ocid: + type: string + type: object + type: object + autonomousContainerDatabase: + description: ACDSpec defines the spec of the target for backup/restore + runs. The name could be the name of an AutonomousDatabase or + an AutonomousDatabaseBackup + properties: + k8sACD: + description: "*********************** *\tACD specs ***********************" + properties: + name: + type: string + type: object + ociACD: + properties: + ocid: + type: string + type: object + type: object + autonomousDatabaseOCID: + type: string + compartmentOCID: + type: string + cpuCoreCount: + type: integer + dataStorageSizeInTBs: + type: integer + dbName: + type: string + dbVersion: + type: string + dbWorkload: + description: 'AutonomousDatabaseDbWorkloadEnum Enum with underlying + type: string' + enum: + - OLTP + - DW + - AJD + - APEX + type: string + displayName: + type: string + freeformTags: + additionalProperties: + type: string + type: object + isAutoScalingEnabled: + type: boolean + isDedicated: + type: boolean + licenseModel: + description: 'AutonomousDatabaseLicenseModelEnum Enum with underlying + type: string' + enum: + - LICENSE_INCLUDED + - BRING_YOUR_OWN_LICENSE + type: string + lifecycleState: + description: 'AutonomousDatabaseLifecycleStateEnum Enum with underlying + type: string' + type: string + networkAccess: + properties: + accessControlList: + items: + type: string + type: array + accessType: + enum: + - "" + - PUBLIC + - RESTRICTED + - PRIVATE + type: string + isAccessControlEnabled: + type: boolean + isMTLSConnectionRequired: + type: boolean + privateEndpoint: + properties: + hostnamePrefix: + type: string + nsgOCIDs: + items: + type: string + type: array + subnetOCID: + type: string + type: object + type: object + wallet: + properties: + name: + type: string + password: + properties: + k8sSecret: + description: "*********************** *\tSecret specs + ***********************" + properties: + name: + type: string + type: object + ociSecret: + properties: + ocid: + type: string + type: object + type: object + type: object + type: object + hardLink: + default: false + type: boolean + ociConfig: + description: "*********************** *\tOCI config ***********************" + properties: + configMapName: + type: string + secretName: + type: string + type: object + required: + - details + type: object + status: + description: AutonomousDatabaseStatus defines the observed state of AutonomousDatabase + properties: + allConnectionStrings: + items: + properties: + connectionStrings: + items: + properties: + connectionString: + type: string + tnsName: + type: string + type: object + type: array + tlsAuthentication: + type: string + required: + - connectionStrings + type: object + type: array + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n \ttype FooStatus struct{ \t // Represents the observations + of a foo's current state. \t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\" \t // + +patchMergeKey=type \t // +patchStrategy=merge \t // +listType=map + \t // +listMapKey=type \t Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n \t // other fields + \t}" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + lifecycleState: + description: 'INSERT ADDITIONAL STATUS FIELD - define observed state + of cluster Important: Run "make" to regenerate code after modifying + this file' + type: string + timeCreated: + type: string + walletExpiringDate: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/database.oracle.com_cdbs.yaml b/config/database.oracle.com_cdbs.yaml new file mode 100644 index 00000000..6b1c350c --- /dev/null +++ b/config/database.oracle.com_cdbs.yaml @@ -0,0 +1,270 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.1 + creationTimestamp: null + name: cdbs.database.oracle.com +spec: + group: database.oracle.com + names: + kind: CDB + listKind: CDBList + plural: cdbs + singular: cdb + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: Name of the CDB + jsonPath: .spec.cdbName + name: CDB Name + type: string + - description: ' Name of the DB Server' + jsonPath: .spec.dbServer + name: DB Server + type: string + - description: DB server port + jsonPath: .spec.dbPort + name: DB Port + type: integer + - description: ' string of the tnsalias' + jsonPath: .spec.dbTnsurl + name: TNS STRING + type: string + - description: Replicas + jsonPath: .spec.replicas + name: Replicas + type: integer + - description: Status of the CDB Resource + jsonPath: .status.phase + name: Status + type: string + - description: Error message, if any + jsonPath: .status.msg + name: Message + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: CDB is the Schema for the cdbs 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: CDBSpec defines the desired state of CDB + properties: + cdbAdminPwd: + description: Password for the CDB Administrator to manage PDB lifecycle + properties: + secret: + description: CDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object + cdbAdminUser: + description: User in the root container with sysdba priviledges to + manage PDB lifecycle + properties: + secret: + description: CDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object + cdbName: + description: Name of the CDB + type: string + cdbTlsCrt: + properties: + secret: + description: CDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object + cdbTlsKey: + properties: + secret: + description: CDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object + dbPort: + description: DB server port + type: integer + dbServer: + description: Name of the DB server + type: string + dbTnsurl: + type: string + nodeSelector: + additionalProperties: + type: string + description: Node Selector for running the Pod + type: object + ordsImage: + description: ORDS Image Name + type: string + ordsImagePullPolicy: + description: ORDS Image Pull Policy + enum: + - Always + - Never + type: string + ordsImagePullSecret: + description: The name of the image pull secret in case of a private + docker repository. + type: string + ordsPort: + description: ORDS server port. For now, keep it as 8888. TO BE USED + IN FUTURE RELEASE. + type: integer + ordsPwd: + description: Password for user ORDS_PUBLIC_USER + properties: + secret: + description: CDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object + replicas: + description: Number of ORDS Containers to create + type: integer + serviceName: + description: Name of the CDB Service + type: string + sysAdminPwd: + description: Password for the CDB System Administrator + properties: + secret: + description: CDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object + webServerPwd: + description: Password for the Web Server User + properties: + secret: + description: CDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object + webServerUser: + description: Web Server User with SQL Administrator role to allow + us to authenticate to the PDB Lifecycle Management REST endpoints + properties: + secret: + description: CDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object + type: object + status: + description: CDBStatus defines the observed state of CDB + properties: + msg: + description: Message + type: string + phase: + description: Phase of the CDB Resource + type: string + status: + description: CDB Resource Status + type: boolean + required: + - phase + - status + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/database.oracle.com_dataguardbrokers.yaml b/config/database.oracle.com_dataguardbrokers.yaml new file mode 100644 index 00000000..f19a3e22 --- /dev/null +++ b/config/database.oracle.com_dataguardbrokers.yaml @@ -0,0 +1,134 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.1 + creationTimestamp: null + name: dataguardbrokers.database.oracle.com +spec: + group: database.oracle.com + names: + kind: DataguardBroker + listKind: DataguardBrokerList + plural: dataguardbrokers + singular: dataguardbroker + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.primaryDatabase + name: Primary + type: string + - jsonPath: .status.standbyDatabases + name: Standbys + type: string + - jsonPath: .spec.protectionMode + name: Protection Mode + type: string + - jsonPath: .status.clusterConnectString + name: Cluster Connect Str + priority: 1 + type: string + - jsonPath: .status.externalConnectString + name: Connect Str + type: string + - jsonPath: .spec.primaryDatabaseRef + name: Primary Database + priority: 1 + type: string + - jsonPath: .status.status + name: Status + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: DataguardBroker is the Schema for the dataguardbrokers 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: DataguardBrokerSpec defines the desired state of DataguardBroker + properties: + fastStartFailOver: + properties: + enable: + type: boolean + strategy: + items: + description: FSFO strategy + properties: + sourceDatabaseRef: + type: string + targetDatabaseRefs: + type: string + type: object + type: array + type: object + loadBalancer: + type: boolean + nodeSelector: + additionalProperties: + type: string + type: object + primaryDatabaseRef: + type: string + protectionMode: + enum: + - MaxPerformance + - MaxAvailability + type: string + serviceAnnotations: + additionalProperties: + type: string + type: object + setAsPrimaryDatabase: + type: string + standbyDatabaseRefs: + items: + type: string + type: array + required: + - primaryDatabaseRef + - protectionMode + - standbyDatabaseRefs + type: object + status: + description: DataguardBrokerStatus defines the observed state of DataguardBroker + properties: + clusterConnectString: + type: string + externalConnectString: + type: string + primaryDatabase: + type: string + primaryDatabaseRef: + type: string + protectionMode: + type: string + standbyDatabases: + type: string + status: + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/database.oracle.com_oraclerestdataservices.yaml b/config/database.oracle.com_oraclerestdataservices.yaml new file mode 100644 index 00000000..121383fd --- /dev/null +++ b/config/database.oracle.com_oraclerestdataservices.yaml @@ -0,0 +1,224 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.1 + creationTimestamp: null + name: oraclerestdataservices.database.oracle.com +spec: + group: database.oracle.com + names: + kind: OracleRestDataService + listKind: OracleRestDataServiceList + plural: oraclerestdataservices + singular: oraclerestdataservice + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.status + name: Status + type: string + - jsonPath: .spec.databaseRef + name: Database + type: string + - jsonPath: .status.databaseApiUrl + name: Database API URL + type: string + - jsonPath: .status.databaseActionsUrl + name: Database Actions URL + type: string + - jsonPath: .status.apexUrl + name: Apex URL + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: OracleRestDataService is the Schema for the oraclerestdataservices + 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: OracleRestDataServiceSpec defines the desired state of OracleRestDataService + properties: + adminPassword: + description: OracleRestDataServicePassword defines the secret containing + Password mapped to secretKey + properties: + keepSecret: + type: boolean + secretKey: + default: oracle_pwd + type: string + secretName: + type: string + required: + - secretName + type: object + apexPassword: + description: OracleRestDataServicePassword defines the secret containing + Password mapped to secretKey + properties: + keepSecret: + type: boolean + secretKey: + default: oracle_pwd + type: string + secretName: + type: string + required: + - secretName + type: object + databaseRef: + type: string + image: + description: OracleRestDataServiceImage defines the Image source and + pullSecrets for POD + properties: + pullFrom: + type: string + pullSecrets: + type: string + version: + type: string + required: + - pullFrom + type: object + loadBalancer: + type: boolean + nodeSelector: + additionalProperties: + type: string + type: object + oracleService: + type: string + ordsPassword: + description: OracleRestDataServicePassword defines the secret containing + Password mapped to secretKey + properties: + keepSecret: + type: boolean + secretKey: + default: oracle_pwd + type: string + secretName: + type: string + required: + - secretName + type: object + ordsUser: + type: string + persistence: + description: OracleRestDataServicePersistence defines the storage + releated params + properties: + accessMode: + enum: + - ReadWriteOnce + - ReadWriteMany + type: string + size: + type: string + storageClass: + type: string + volumeName: + type: string + type: object + replicas: + minimum: 1 + type: integer + restEnableSchemas: + items: + description: OracleRestDataServicePDBSchemas defines the PDB Schemas + to be ORDS Enabled + properties: + enable: + type: boolean + pdbName: + type: string + schemaName: + type: string + urlMapping: + type: string + required: + - enable + - schemaName + type: object + type: array + serviceAccountName: + type: string + serviceAnnotations: + additionalProperties: + type: string + type: object + required: + - adminPassword + - databaseRef + - ordsPassword + type: object + status: + description: OracleRestDataServiceStatus defines the observed state of + OracleRestDataService + properties: + apexConfigured: + type: boolean + apexUrl: + type: string + commonUsersCreated: + type: boolean + databaseActionsUrl: + type: string + databaseApiUrl: + type: string + databaseRef: + type: string + image: + description: OracleRestDataServiceImage defines the Image source and + pullSecrets for POD + properties: + pullFrom: + type: string + pullSecrets: + type: string + version: + type: string + required: + - pullFrom + type: object + loadBalancer: + type: string + ordsInstalled: + type: boolean + replicas: + type: integer + serviceIP: + type: string + status: + description: 'INSERT ADDITIONAL STATUS FIELD - define observed state + of cluster Important: Run "make" to regenerate code after modifying + this file' + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/database.oracle.com_pdbs.yaml b/config/database.oracle.com_pdbs.yaml new file mode 100644 index 00000000..85af8c1b --- /dev/null +++ b/config/database.oracle.com_pdbs.yaml @@ -0,0 +1,383 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.1 + creationTimestamp: null + name: pdbs.database.oracle.com +spec: + group: database.oracle.com + names: + kind: PDB + listKind: PDBList + plural: pdbs + singular: pdb + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: The connect string to be used + jsonPath: .status.connString + name: Connect_String + type: string + - description: Name of the CDB + jsonPath: .spec.cdbName + name: CDB Name + type: string + - description: Name of the PDB + jsonPath: .spec.pdbName + name: PDB Name + type: string + - description: PDB Open Mode + jsonPath: .status.openMode + name: PDB State + type: string + - description: Total Size of the PDB + jsonPath: .status.totalSize + name: PDB Size + type: string + - description: Status of the PDB Resource + jsonPath: .status.phase + name: Status + type: string + - description: Error message, if any + jsonPath: .status.msg + name: Message + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: PDB is the Schema for the pdbs 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: PDBSpec defines the desired state of PDB + properties: + action: + description: 'Action to be taken: Create/Clone/Plug/Unplug/Delete/Modify/Status/Map. + Map is used to map a Databse PDB to a Kubernetes PDB CR.' + enum: + - Create + - Clone + - Plug + - Unplug + - Delete + - Modify + - Status + - Map + type: string + adminName: + description: The administrator username for the new PDB. This property + is required when the Action property is Create. + properties: + secret: + description: PDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object + adminPwd: + description: The administrator password for the new PDB. This property + is required when the Action property is Create. + properties: + secret: + description: PDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object + asClone: + description: Indicate if 'AS CLONE' option should be used in the command + to plug in a PDB. This property is applicable when the Action property + is PLUG but not required. + type: boolean + assertivePdbDeletion: + description: turn on the assertive approach to delete pdb resource + kubectl delete pdb ..... automatically triggers the pluggable database + deletion + type: boolean + cdbName: + description: Name of the CDB + type: string + cdbNamespace: + description: CDB Namespace + type: string + cdbResName: + description: Name of the CDB Custom Resource that runs the ORDS container + type: string + copyAction: + description: To copy files or not while cloning a PDB + enum: + - COPY + - NOCOPY + - MOVE + type: string + dropAction: + description: Specify if datafiles should be removed or not. The value + can be INCLUDING or KEEP (default). + enum: + - INCLUDING + - KEEP + type: string + fileNameConversions: + description: Relevant for Create and Plug operations. As defined in + the Oracle Multitenant Database documentation. Values can be a + filename convert pattern or NONE. + type: string + getScript: + description: Whether you need the script only or execute the script + type: boolean + modifyOption: + description: Extra options for opening and closing a PDB + enum: + - IMMEDIATE + - NORMAL + - READ ONLY + - READ WRITE + - RESTRICTED + type: string + pdbName: + description: The name of the new PDB. Relevant for both Create and + Plug Actions. + type: string + pdbState: + description: The target state of the PDB + enum: + - OPEN + - CLOSE + type: string + pdbTlsCat: + properties: + secret: + description: PDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object + pdbTlsCrt: + properties: + secret: + description: PDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object + pdbTlsKey: + properties: + secret: + description: PDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object + reuseTempFile: + description: Whether to reuse temp file + type: boolean + sourceFileNameConversions: + description: This property is required when the Action property is + Plug. As defined in the Oracle Multitenant Database documentation. + Values can be a source filename convert pattern or NONE. + type: string + sparseClonePath: + description: A Path specified for sparse clone snapshot copy. (Optional) + type: string + srcPdbName: + description: Name of the Source PDB from which to clone + type: string + tdeExport: + description: TDE export for unplug operations + type: boolean + tdeImport: + description: TDE import for plug operations + type: boolean + tdeKeystorePath: + description: TDE keystore path is required if the tdeImport or tdeExport + flag is set to true. Can be used in plug or unplug operations. + type: string + tdePassword: + description: TDE password if the tdeImport or tdeExport flag is set + to true. Can be used in create, plug or unplug operations + properties: + secret: + description: PDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object + tdeSecret: + description: TDE secret is required if the tdeImport or tdeExport + flag is set to true. Can be used in plug or unplug operations. + properties: + secret: + description: PDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object + tempSize: + description: Relevant for Create and Clone operations. Total size + for temporary tablespace as defined in the Oracle Multitenant Database + documentation. See size_clause description in Database SQL Language + Reference documentation. + type: string + totalSize: + description: Relevant for create and plug operations. Total size as + defined in the Oracle Multitenant Database documentation. See size_clause + description in Database SQL Language Reference documentation. + type: string + unlimitedStorage: + description: Relevant for Create and Plug operations. True for unlimited + storage. Even when set to true, totalSize and tempSize MUST be specified + in the request if Action is Create. + type: boolean + webServerPwd: + description: Password for the Web ServerPDB User + properties: + secret: + description: PDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object + webServerUser: + description: Web Server User with SQL Administrator role to allow + us to authenticate to the PDB Lifecycle Management REST endpoints + properties: + secret: + description: PDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object + xmlFileName: + description: XML metadata filename to be used for Plug or Unplug operations + type: string + required: + - action + type: object + status: + description: PDBStatus defines the observed state of PDB + properties: + action: + description: Last Completed Action + type: string + connString: + description: PDB Connect String + type: string + modifyOption: + description: Modify Option of the PDB + type: string + msg: + description: Message + type: string + openMode: + description: Open mode of the PDB + type: string + phase: + description: Phase of the PDB Resource + type: string + status: + description: PDB Resource Status + type: boolean + totalSize: + description: Total size of the PDB + type: string + required: + - phase + - status + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/database.oracle.com_shardingdatabases.yaml b/config/database.oracle.com_shardingdatabases.yaml new file mode 100644 index 00000000..641629a0 --- /dev/null +++ b/config/database.oracle.com_shardingdatabases.yaml @@ -0,0 +1,688 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.1 + creationTimestamp: null + name: shardingdatabases.database.oracle.com +spec: + group: database.oracle.com + names: + kind: ShardingDatabase + listKind: ShardingDatabaseList + plural: shardingdatabases + singular: shardingdatabase + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.gsm.state + name: Gsm State + type: string + - jsonPath: .status.gsm.services + name: Services + type: string + - jsonPath: .status.gsm.shards + name: shards + priority: 1 + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: ShardingDatabase is the Schema for the shardingdatabases 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: ShardingDatabaseSpec defines the desired state of ShardingDatabase + properties: + InvitedNodeSubnet: + type: string + catalog: + items: + description: CatalogSpec defines the desired state of CatalogSpec + properties: + envVars: + items: + description: EnvironmentVariable represents a named variable + accessible for containers. + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + isDelete: + type: string + label: + type: string + name: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + pvAnnotations: + additionalProperties: + type: string + type: object + pvMatchLabels: + additionalProperties: + type: string + type: object + pvcName: + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + storageSizeInGb: + format: int32 + type: integer + required: + - name + type: object + type: array + dbEdition: + type: string + dbImage: + type: string + dbImagePullSecret: + type: string + dbSecret: + description: Secret Details + properties: + encryptionType: + type: string + keyFileMountLocation: + type: string + keyFileName: + type: string + keySecretName: + type: string + name: + type: string + nsConfigMap: + type: string + nsSecret: + type: string + pwdFileMountLocation: + type: string + pwdFileName: + type: string + required: + - name + - pwdFileName + type: object + fssStorageClass: + type: string + gsm: + items: + description: GsmSpec defines the desired state of GsmSpec + properties: + directorName: + type: string + envVars: + description: Replicas int32 `json:"replicas,omitempty"` // + Gsm Replicas. If you set OraGsmPvcName then it is set default + to 1. + items: + description: EnvironmentVariable represents a named variable + accessible for containers. + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + isDelete: + type: string + label: + type: string + name: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + pvMatchLabels: + additionalProperties: + type: string + type: object + pvcName: + type: string + region: + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + storageSizeInGb: + format: int32 + type: integer + required: + - name + type: object + type: array + gsmDevMode: + type: string + gsmImage: + type: string + gsmImagePullSecret: + type: string + gsmService: + items: + description: Service Definition + properties: + available: + type: string + clbGoal: + type: string + commitOutcome: + type: string + drainTimeout: + type: string + dtp: + type: string + edition: + type: string + failoverDelay: + type: string + failoverMethod: + type: string + failoverPrimary: + type: string + failoverRestore: + type: string + failoverRetry: + type: string + failoverType: + type: string + gdsPool: + type: string + lag: + type: integer + locality: + type: string + name: + type: string + notification: + type: string + pdbName: + type: string + policy: + type: string + preferred: + type: string + prferredAll: + type: string + regionFailover: + type: string + retention: + type: string + role: + type: string + sessionState: + type: string + sqlTransactionProfile: + type: string + stopOption: + type: string + tableFamily: + type: string + tfaPolicy: + type: string + required: + - name + type: object + type: array + gsmShardGroup: + items: + properties: + deployAs: + type: string + name: + type: string + region: + type: string + required: + - name + type: object + type: array + gsmShardSpace: + items: + description: ShardSpace Specs + properties: + chunks: + type: integer + name: + type: string + protectionMode: + type: string + shardGroup: + type: string + required: + - name + type: object + type: array + invitedNodeSubnetFlag: + type: string + isClone: + type: boolean + isDataGuard: + type: boolean + isDebug: + type: boolean + isDeleteOraPvc: + type: boolean + isDownloadScripts: + type: boolean + isExternalSvc: + type: boolean + isTdeWallet: + type: string + liveinessCheckPeriod: + type: integer + namespace: + type: string + portMappings: + items: + description: PortMapping is a specification of port mapping for + an application deployment. + properties: + port: + format: int32 + type: integer + protocol: + default: TCP + type: string + targetPort: + format: int32 + type: integer + required: + - port + - protocol + - targetPort + type: object + type: array + readinessCheckPeriod: + type: integer + replicationType: + type: string + scriptsLocation: + type: string + shard: + description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + Important: Run "make" to regenerate code after modifying this file' + items: + description: ShardSpec is a specification of Shards for an application + deployment. + properties: + deployAs: + type: string + envVars: + items: + description: EnvironmentVariable represents a named variable + accessible for containers. + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + imagePullPolicy: + description: PullPolicy describes a policy for if/when to pull + a container image + type: string + isDelete: + enum: + - enable + - disable + - failed + - force + type: string + label: + type: string + name: + type: string + nodeSelector: + additionalProperties: + type: string + type: object + pvAnnotations: + additionalProperties: + type: string + type: object + pvMatchLabels: + additionalProperties: + type: string + type: object + pvcName: + type: string + resources: + description: ResourceRequirements describes the compute resource + requirements. + properties: + claims: + description: "Claims lists the names of resources, defined + in spec.resourceClaims, that are used by this container. + \n This is an alpha field and requires enabling the DynamicResourceAllocation + feature gate. \n This field is immutable. It can only + be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry + in pod.spec.resourceClaims of the Pod where this + field is used. It makes that resource available + inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Limits describes the maximum amount of compute + resources allowed. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: 'Requests describes the minimum amount of compute + resources required. If Requests is omitted for a container, + it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests + cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + type: object + type: object + shardGroup: + type: string + shardRegion: + type: string + shardSpace: + type: string + storageSizeInGb: + format: int32 + type: integer + required: + - name + type: object + type: array + shardBuddyRegion: + type: string + shardConfigName: + type: string + shardRegion: + items: + type: string + type: array + shardingType: + type: string + stagePvcName: + type: string + storageClass: + type: string + tdeWalletPvc: + type: string + tdeWalletPvcMountLocation: + type: string + required: + - catalog + - dbImage + - gsm + - gsmImage + - shard + type: object + status: + description: To understand Metav1.Condition, please refer the link https://pkg.go.dev/k8s.io/apimachinery/pkg/apis/meta/v1 + ShardingDatabaseStatus defines the observed state of ShardingDatabase + properties: + catalogs: + additionalProperties: + type: string + type: object + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n \ttype FooStatus struct{ \t // Represents the observations + of a foo's current state. \t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\" \t // + +patchMergeKey=type \t // +patchStrategy=merge \t // +listType=map + \t // +listMapKey=type \t Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n \t // other fields + \t}" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + gsm: + properties: + details: + additionalProperties: + type: string + type: object + externalConnectStr: + type: string + internalConnectStr: + type: string + services: + type: string + shards: + additionalProperties: + type: string + type: object + state: + type: string + type: object + shards: + additionalProperties: + type: string + type: object + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/database.oracle.com_singleinstancedatabases.yaml b/config/database.oracle.com_singleinstancedatabases.yaml new file mode 100644 index 00000000..1c011e17 --- /dev/null +++ b/config/database.oracle.com_singleinstancedatabases.yaml @@ -0,0 +1,421 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.1 + creationTimestamp: null + name: singleinstancedatabases.database.oracle.com +spec: + group: database.oracle.com + names: + kind: SingleInstanceDatabase + listKind: SingleInstanceDatabaseList + plural: singleinstancedatabases + singular: singleinstancedatabase + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.edition + name: Edition + type: string + - jsonPath: .status.sid + name: Sid + priority: 1 + type: string + - jsonPath: .status.status + name: Status + type: string + - jsonPath: .status.role + name: Role + type: string + - jsonPath: .status.releaseUpdate + name: Version + type: string + - jsonPath: .status.connectString + name: Connect Str + type: string + - jsonPath: .status.pdbConnectString + name: Pdb Connect Str + priority: 1 + type: string + - jsonPath: .status.tcpsConnectString + name: TCPS Connect Str + type: string + - jsonPath: .status.tcpsPdbConnectString + name: TCPS Pdb Connect Str + priority: 1 + type: string + - jsonPath: .status.oemExpressUrl + name: Oem Express Url + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: SingleInstanceDatabase is the Schema for the singleinstancedatabases + 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: SingleInstanceDatabaseSpec defines the desired state of SingleInstanceDatabase + properties: + adminPassword: + description: SingleInsatnceAdminPassword defines the secret containing + Admin Password mapped to secretKey for Database + properties: + keepSecret: + type: boolean + secretKey: + default: oracle_pwd + type: string + secretName: + type: string + required: + - secretName + type: object + archiveLog: + type: boolean + charset: + type: string + createAs: + enum: + - primary + - standby + - clone + type: string + dgBrokerConfigured: + type: boolean + edition: + enum: + - standard + - enterprise + - express + - free + type: string + enableTCPS: + type: boolean + flashBack: + type: boolean + forceLog: + type: boolean + image: + description: SingleInstanceDatabaseImage defines the Image source + and pullSecrets for POD + properties: + prebuiltDB: + type: boolean + pullFrom: + type: string + pullSecrets: + type: string + version: + type: string + required: + - pullFrom + type: object + initParams: + description: SingleInstanceDatabaseInitParams defines the Init Parameters + properties: + cpuCount: + type: integer + pgaAggregateTarget: + type: integer + processes: + type: integer + sgaTarget: + type: integer + type: object + listenerPort: + type: integer + loadBalancer: + type: boolean + nodeSelector: + additionalProperties: + type: string + type: object + pdbName: + type: string + persistence: + description: SingleInstanceDatabasePersistence defines the storage + size and class for PVC + properties: + accessMode: + enum: + - ReadWriteOnce + - ReadWriteMany + type: string + datafilesVolumeName: + type: string + scriptsVolumeName: + type: string + setWritePermissions: + type: boolean + size: + type: string + storageClass: + type: string + volumeClaimAnnotation: + type: string + type: object + primaryDatabaseRef: + type: string + readinessCheckPeriod: + type: integer + replicas: + type: integer + resources: + properties: + limits: + properties: + cpu: + type: string + memory: + type: string + type: object + requests: + properties: + cpu: + type: string + memory: + type: string + type: object + type: object + serviceAccountName: + type: string + serviceAnnotations: + additionalProperties: + type: string + type: object + sid: + description: SID must be alphanumeric (no special characters, only + a-z, A-Z, 0-9), and no longer than 12 characters. + maxLength: 12 + pattern: ^[a-zA-Z0-9]+$ + type: string + tcpsCertRenewInterval: + type: string + tcpsListenerPort: + type: integer + tcpsTlsSecret: + type: string + required: + - image + type: object + status: + description: SingleInstanceDatabaseStatus defines the observed state of + SingleInstanceDatabase + properties: + apexInstalled: + type: boolean + archiveLog: + type: string + certCreationTimestamp: + type: string + certRenewInterval: + type: string + charset: + type: string + clientWalletLoc: + type: string + clusterConnectString: + type: string + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n \ttype FooStatus struct{ \t // Represents the observations + of a foo's current state. \t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\" \t // + +patchMergeKey=type \t // +patchStrategy=merge \t // +listType=map + \t // +listMapKey=type \t Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n \t // other fields + \t}" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + connectString: + type: string + createdAs: + type: string + datafilesCreated: + default: "false" + type: string + datafilesPatched: + default: "false" + type: string + dgBrokerConfigured: + type: boolean + edition: + type: string + flashBack: + type: string + forceLog: + type: string + initParams: + description: SingleInstanceDatabaseInitParams defines the Init Parameters + properties: + cpuCount: + type: integer + pgaAggregateTarget: + type: integer + processes: + type: integer + sgaTarget: + type: integer + type: object + initPgaSize: + type: integer + initSgaSize: + type: integer + isTcpsEnabled: + default: false + type: boolean + nodes: + items: + type: string + type: array + oemExpressUrl: + type: string + ordsReference: + type: string + pdbConnectString: + type: string + pdbName: + type: string + persistence: + description: SingleInstanceDatabasePersistence defines the storage + size and class for PVC + properties: + accessMode: + enum: + - ReadWriteOnce + - ReadWriteMany + type: string + datafilesVolumeName: + type: string + scriptsVolumeName: + type: string + setWritePermissions: + type: boolean + size: + type: string + storageClass: + type: string + volumeClaimAnnotation: + type: string + type: object + prebuiltDB: + type: boolean + primaryDatabase: + type: string + releaseUpdate: + type: string + replicas: + type: integer + role: + type: string + sid: + type: string + standbyDatabases: + additionalProperties: + type: string + type: object + status: + type: string + tcpsConnectString: + type: string + tcpsPdbConnectString: + type: string + tcpsTlsSecret: + default: "" + type: string + required: + - isTcpsEnabled + - persistence + - tcpsTlsSecret + type: object + type: object + served: true + storage: true + subresources: + scale: + specReplicasPath: .spec.replicas + statusReplicasPath: .status.replicas + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/manager/kustomization.yaml b/config/manager/kustomization.yaml index b8ec1f58..2aed83d4 100644 --- a/config/manager/kustomization.yaml +++ b/config/manager/kustomization.yaml @@ -9,4 +9,4 @@ kind: Kustomization images: - name: controller newName: container-registry.oracle.com/database/operator - newTag: 0.1.0 + newTag: latest diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index 90df4158..54340faf 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -41,4 +41,7 @@ spec: requests: cpu: 400m memory: 400Mi + env: + - name : WATCH_NAMESPACE + value : "" terminationGracePeriodSeconds: 10 diff --git a/config/manifests/bases/oracle-database-operator.clusterserviceversion.yaml b/config/manifests/bases/oracle-database-operator.clusterserviceversion.yaml index 6ec37dd1..23cd7c00 100644 --- a/config/manifests/bases/oracle-database-operator.clusterserviceversion.yaml +++ b/config/manifests/bases/oracle-database-operator.clusterserviceversion.yaml @@ -3,25 +3,98 @@ kind: ClusterServiceVersion metadata: annotations: alm-examples: '[]' - capabilities: Basic Install + capabilities: Seamless Upgrades operators.operatorframework.io/builder: operator-sdk-v1.2.0 operators.operatorframework.io/project_layout: go.kubebuilder.io/v2 - name: oracle-database-operator.v0.0.0 - namespace: placeholder + name: oracle-database-operator.v1.1.0 + namespace: oracle-database-operator-system spec: apiservicedefinitions: {} customresourcedefinitions: owned: + - description: DbcsSystem is the Schema for the dbcssystems API + displayName: Dbcs System + kind: DbcsSystem + name: DbcsSystem.database.oracle.com + version: v1alpha1 + - description: AutonomousContainerDatabase is the Schema for the autonomouscontainerdatabases + API + displayName: Autonomous Container Database + kind: AutonomousContainerDatabase + name: autonomouscontainerdatabases.database.oracle.com + version: v1alpha1 + - description: AutonomousDatabaseBackup is the Schema for the autonomousdatabasebackups + API + displayName: Autonomous Database Backup + kind: AutonomousDatabaseBackup + name: autonomousdatabasebackups.database.oracle.com + version: v1alpha1 + - description: AutonomousDatabaseRestore is the Schema for the autonomousdatabaserestores + API + displayName: Autonomous Database Restore + kind: AutonomousDatabaseRestore + name: autonomousdatabaserestores.database.oracle.com + version: v1alpha1 - description: AutonomousDatabase is the Schema for the autonomousdatabases API displayName: Autonomous Database kind: AutonomousDatabase name: autonomousdatabases.database.oracle.com version: v1alpha1 - description: Operator to manage Oracle sharding - displayName: Oracle Sharding DB Operator + - description: CDB is the Schema for the cdbs API + displayName: CDB + kind: CDB + name: cdbs.database.oracle.com + version: v1alpha1 + - description: DatabaseObserver is the Schema for the databaseobservers API + displayName: Database Observer + kind: DatabaseObserver + name: databaseobservers.observability.oracle.com + version: v1alpha1 + - description: DataguardBroker is the Schema for the dataguardbrokers API + displayName: Dataguard Broker + kind: DataguardBroker + name: dataguardbrokers.database.oracle.com + version: v1alpha1 + - description: OracleRestDataService is the Schema for the oraclerestdataservices + API + displayName: Oracle Rest Data Service + kind: OracleRestDataService + name: oraclerestdataservices.database.oracle.com + version: v1alpha1 + - description: PDB is the Schema for the pdbs API + displayName: PDB + kind: PDB + name: pdbs.database.oracle.com + version: v1alpha1 + - description: ShardingDatabase is the Schema for the shardingdatabases API + displayName: Sharding Database + kind: ShardingDatabase + name: shardingdatabases.database.oracle.com + version: v1alpha1 + - description: SingleInstanceDatabase is the Schema for the singleinstancedatabases + API + displayName: Single Instance Database + kind: SingleInstanceDatabase + name: singleinstancedatabases.database.oracle.com + version: v1alpha1 + description: | + As part of Oracle's resolution to make Oracle Database Kubernetes native (that is, observable and operable by Kubernetes), Oracle released Oracle Database Operator for Kubernetes (OraOperator or the operator). OraOperator extends the Kubernetes API with custom resources and controllers for automating Oracle Database lifecycle management. + In this v1.1.0 production release, OraOperator supports the following database configurations and infrastructure: + ## Oracle Autonomous Database: + * Oracle Autonomous Database shared Oracle Cloud Infrastructure (OCI) (ADB-S) + * Oracle Autonomous Database on dedicated Cloud infrastructure (ADB-D) + * Oracle Autonomous Container Database (ACD) (infrastructure) is the infrastructure for provisioning Autonomous Databases. + * Containerized Single Instance databases (SIDB) deployed in the Oracle Kubernetes Engine (OKE) and any k8s where OraOperator is deployed + * Containerized Sharded databases (SHARDED) deployed in OKE and any k8s where OraOperator is deployed + * Oracle Multitenant Databases (CDB/PDBs) + * Oracle Base Database Cloud Service (BDBCS) + * Oracle Data Guard (Preview status) + * Oracle Database Observability (Preview status) + * Oracle will continue to extend OraOperator to support additional Oracle Database configurations. + displayName: Oracle Database Operator icon: - - base64data: "" - mediatype: "" + - base64data: iVBORw0KGgoAAAANSUhEUgAAALQAAAC0CAYAAAA9zQYyAAAABGdBTUEAALGPC/xhBQAAACBjSFJNAAB6JgAAgIQAAPoAAACA6AAAdTAAAOpgAAA6mAAAF3CculE8AAAABmJLR0QAAAAAAAD5Q7t/AAAJjUlEQVR42u3cfcwcRQHH8S9PH0BokZfCVBgpOgjyFjRoQIQQkLeA0PLWqgQMFDVgja9AChIKKCEKSgQEQVsQJGKxtNCAvAi2vJiCqAQMUpQRMKM4vFiCQEUo/jH7kOt19m7vbveK8fdJLukzMzuzczc7OzszWxAREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREZH/X2tVSRStmwi8B5gErN1nWS8DAVhmgl9ZsdwpVc+xoteKc/iTCf7VujKN1o0A+xef5cDPTfCP1XjeY+VsAWwFTATGDZjdPSb4F6J1U9sjTPA31n3uXeq1MfBe4F30376ADo0lWjcBOAa4EHhHzXW4FzgDuNsE/2aHc3gJmFBz2WMuBc4ywT87SCbRunWAB4APtEV92gR/zaAnGa2bBJwInFVz/SeY4F+O1q32/Zvg6+xEyuq1PnA08F1gg7ryHSkpbDrwEnAZ9TdmgD2BxcDj0bptG8i/is8DMVq394D5zGb1xgxwdbRum34zjdaNi9adAjxD/Y15PxP8yzXn2UvdDiPdsX9IjY0ZOHOVKzFaNw64Apgx5DoelrvNNdxDt9rDBP/rXg+K1u0EPNIhyWPADp3uQiX5bggsIX+hDOp6E/z0lrKG1kMXQ7OLgJkNZL8SWO+tHjpatxbwM4bfmAEWRuuOWAPljrmvGGJVVlz8d3ZJth1wXI/5jgeW0UxjhnRnGrqifV1FM40ZYDcT/GujLQGnAUd2OGAu6Qd8oY/CxgGTgWOB3UvSzI/W7WiCf7RLXgcNUOnJwOUlcScCF/SQ10mAqZBubrTuVhP837sljNZB6lQmdUh2AbCUdMvu1Ssm+Of6OK4OXyb9/mV+DNxOf+0LE/yDUDwURuu2A/5YknYWcLEJ/pU6ahWt2wq4FtgjE/08YMZmQUqGHHua4O8boPx1gNuAvTPRI1WGB0UdnsxEPQzsnAm/HTjQBN8t36nAwpLoTwDzTfBv9Fv3kjIbH3JE6xzwREn0bOA7dY3px4Ycl5bEH2CC/1ZdjRnABP8UsBfwg0z0RODgusoqKf810uxNzsbdjm/pRXOOIP1A7Q4ADu2S7yjljXl7E/y8uhvzEF1YEj7FBH9OnQ+oI9G6zYF9MnEzTfB3NFG7ogf+ApDrsr7XRJlt/lYSvmGFY6cDu2XCZ5ngnwC+XXLcTcXDXpmyodheTcxpD0u0bjNgSibqZBP8orrLGyH1HjlXNFnRorc5KhPlioWcJo2WhL/e6aBo3abke+eVFL2QCX4F+eEMpDnXMsdnwu4ywd/T8HfRtLLv4pImChsFDsmEn2aCf73XzPrwUEn4+4Gep9F68LGS8G4PTN8vCf9oMZQBwAS/JFp3PTCtLd2MaN3ckmeAXIP+ZoPfwbCUDSFXFMO3Om03QlrkaLd4GDUtHsByPd7WTZUZrdsLuDUTdX+n5fBo3b6k4Ua7K0zw92fCy6an7o3WVV2seqRiurez3QfPopI5Jvhlo+SniPqaOunT05mwjmPZaN2WwKPAmy0fOvw99u/NOmR7aofyxgO/7OU4E/yz0brjSHOv7c4oPt3U9jC+Bk0aPItKvgZpDJ27zVZ5OKrLFpmwlzodYIL/K2k+egPgncX5bghsRJqp2KT4TAQ2LT6dGvONJvi7O8R/oyR8qgn+xQ7HXUP+wffrxSpjN+v195W+rQxj3vuQsd9hhDRJ326P3vLrTzGGOjoT9Zdux5rg7yWtxA3qsZJzGDvHXYCvZKIWAzd1OceVlE/X3VmsNnayfQ31W9MeaDj/W0zwN4/9MQosYvUv/YJo3UVVt3kOYAfyO/4qTVOZ4JcVu9EeAjbvo/xLSNNH/85FRuvWBsp67guBKRUfbM4jrcSucvqk1caxp/3rgE+2pfkqaWfi/7JfkO8w1m5i4mGUtGrWbhzwKdKKXiOKtf0rM1HPAbFqPib4GK17H2lRYv8Kh7xIWkj6kQned0n7JWB8JnwmaSfiFgzm4mjdomKxaQ6rN+jDo3UfMsH/dsBy1qSy/S4zaGBqeMQE/zTwu0zcT6J1u/WaYRVFr3YOsGsmema3JeJ2xUrmQcDFHZKdU9R3IxP86d0ac7Rua+D8XBRpP0iVi6eKecXFXXYneDBaN7mmsoau2MOyJBN1eTHjVKuxpe/PlMQvjdadUGGsV1mxcjSP8qf8Bf3ka4J/wwT/RdImmJwzSbv6uj5oFQ1sYUn0fkVZjwJn1/CV7ApM77Ik/1S0rq4LaE0o2+G3JFp3UjG0q8Vb49do3fnAyR3SngvcQ3rFqFfjAEtaaJjWId2uJvjftJxTX5uTonWHAzeURQMf7LT7LVp3LHB1Jup8E/ypLenWBVb08X3kbEbanLWU/J0L0uzP2aQ76qBTeq+a4B/ObU4CPlJTnVodTOpUypxH6smXD1JIa4MeBX5FfqFlGGaY4FcZUw+y264YLi3tkGQXE/zvM8dNIr0lkjO+faNWtG5n0sXai1syYfNN8EdF6zYhNeymHWmCv6GkQdftKtIo4GbgwCYLan9jZV1gPvDxIVSy1fEm+KvaAwfdPlqMg//cIcnhJviFbccsIr8dYD8TfLcN/ZVE6y4HPpeJOsAEf0dxUf2BNH/ehMXAPiZ4htSgNzbBLy+27l5Lfg9PLVZ5p7CYvjqU4b3V8B/gw7nGXIdi99umlO/FXRCtmzU29RatO4h8Y15QV2MuzCoJvz1aN8EE/w9gS3p74aAXx/T64D2AKSb45fDW1t1plD+zDWrf1V6SNcG/aYK/jDSmm917npU8Tdo7vH7TU1Im+OeBnShfBDkP+Gm0bgPyQwFIb7PUeU7/pHwx59wizQoT/CmAI793vF+fNcGHlr+P7zun7m4jrXO01h0T/BzSKu7pNZZ1nQn+rqr/L8dkYFvSvGu/T6T/Ap4CHjfBV9orEq07IRN8pwn+yV4LL17Q7PTj3UV+F95zTfw/FcVMSvb9zeIHz53/1sA2pEWZfmeermxfMIvW7Uh6EB3pL8tSN5vgn+mWqNibsw3wbvpvXwuqtisREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREWnxX2ox1/vZSvwPAAAAJXRFWHRkYXRlOmNyZWF0ZQAyMDI0LTA4LTEzVDE5OjUyOjMxKzAwOjAwsDIMcAAAACV0RVh0ZGF0ZTptb2RpZnkAMjAyNC0wOC0xM1QxOTo1MjozMSswMDowMMFvtMwAAABVdEVYdHN2Zzpjb21tZW50ACBVcGxvYWRlZCB0bzogU1ZHIFJlcG8sIHd3dy5zdmdyZXBvLmNvbSwgR2VuZXJhdG9yOiBTVkcgUmVwbyBNaXhlciBUb29scyBFB1wTAAAAAElFTkSuQmCC + mediatype: png install: spec: deployments: null @@ -37,12 +110,12 @@ spec: type: AllNamespaces keywords: - Oracle - - sharding - - db + - Database + - Operator links: - name: Oracle Database Operator - url: https://oracle-database-operator.domain + url: https://github.com/oracle/oracle-database-operator maturity: alpha provider: - name: ShardingDatabase - version: 0.0.0 + name: Oracle + version: 1.2.0 diff --git a/config/observability.oracle.com_databaseobservers.yaml b/config/observability.oracle.com_databaseobservers.yaml new file mode 100644 index 00000000..b0801738 --- /dev/null +++ b/config/observability.oracle.com_databaseobservers.yaml @@ -0,0 +1,227 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.1 + creationTimestamp: null + name: databaseobservers.observability.oracle.com +spec: + group: observability.oracle.com + names: + kind: DatabaseObserver + listKind: DatabaseObserverList + plural: databaseobservers + singular: databaseobserver + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.exporterConfig + name: ExporterConfig + type: string + - jsonPath: .status.status + name: Status + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: DatabaseObserver is the Schema for the databaseobservers 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: DatabaseObserverSpec defines the desired state of DatabaseObserver + properties: + database: + description: DatabaseObserverDatabase defines the database details + used for DatabaseObserver + properties: + dbConnectionString: + properties: + key: + type: string + secret: + type: string + type: object + dbPassword: + properties: + key: + type: string + secret: + type: string + vaultOCID: + type: string + vaultSecretName: + type: string + type: object + dbUser: + properties: + key: + type: string + secret: + type: string + type: object + dbWallet: + properties: + key: + type: string + secret: + type: string + type: object + type: object + exporter: + description: DatabaseObserverExporterConfig defines the configuration + details related to the exporters of DatabaseObserver + properties: + configuration: + properties: + configmap: + description: ConfigMapDetails defines the configmap name + properties: + configmapName: + type: string + key: + type: string + type: object + type: object + image: + type: string + service: + description: DatabaseObserverService defines the exporter service + component of DatabaseObserver + properties: + port: + format: int32 + type: integer + type: object + type: object + ociConfig: + properties: + configMapName: + type: string + secretName: + type: string + type: object + prometheus: + description: PrometheusConfig defines the generated resources for + Prometheus + properties: + labels: + additionalProperties: + type: string + type: object + port: + type: string + type: object + replicas: + format: int32 + type: integer + type: object + status: + description: DatabaseObserverStatus defines the observed state of DatabaseObserver + properties: + conditions: + description: 'INSERT ADDITIONAL STATUS FIELD - define observed state + of cluster Important: Run "make" to regenerate code after modifying + this file' + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n \ttype FooStatus struct{ \t // Represents the observations + of a foo's current state. \t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\" \t // + +patchMergeKey=type \t // +patchStrategy=merge \t // +listType=map + \t // +listMapKey=type \t Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n \t // other fields + \t}" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + exporterConfig: + type: string + replicas: + type: integer + status: + type: string + required: + - conditions + - exporterConfig + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/rbac/auth_proxy_role_binding.yaml b/config/rbac/auth_proxy_role_binding.yaml index 55665e32..6a702753 100644 --- a/config/rbac/auth_proxy_role_binding.yaml +++ b/config/rbac/auth_proxy_role_binding.yaml @@ -5,11 +5,11 @@ apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: oracle-database-operator-proxy-rolebinding + name: proxy-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: proxy-role + name: oracle-database-operator-proxy-role subjects: - kind: ServiceAccount name: default diff --git a/config/rbac/databaseobserver_editor_role.yaml b/config/rbac/databaseobserver_editor_role.yaml new file mode 100644 index 00000000..900c4b88 --- /dev/null +++ b/config/rbac/databaseobserver_editor_role.yaml @@ -0,0 +1,24 @@ +# permissions for end users to edit databaseobservers. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: databaseobserver-editor-role +rules: + - apiGroups: + - observability.oracle.com + resources: + - databaseobservers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - observability.oracle.com + resources: + - databaseobservers/status + verbs: + - get \ No newline at end of file diff --git a/config/rbac/databaseobserver_viewer_role.yaml b/config/rbac/databaseobserver_viewer_role.yaml new file mode 100644 index 00000000..ef447b21 --- /dev/null +++ b/config/rbac/databaseobserver_viewer_role.yaml @@ -0,0 +1,20 @@ +# permissions for end users to view databaseobservers. +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: databaseobserver-viewer-role +rules: + - apiGroups: + - observability.oracle.com + resources: + - databaseobservers + verbs: + - get + - list + - watch + - apiGroups: + - observability.oracle.com + resources: + - databaseobservers/status + verbs: + - get \ No newline at end of file diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 89b630dd..2f33c915 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -54,8 +54,28 @@ rules: - apiGroups: - "" resources: + - deployments - events - - nodes + - pods + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +- apiGroups: + - "" + resources: - persistentvolumeclaims - pods - pods/exec @@ -69,6 +89,14 @@ rules: - patch - update - watch +- apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - get + - list + - watch - apiGroups: - '''''' resources: @@ -81,6 +109,27 @@ rules: - patch - update - watch +- apiGroups: + - apps + resources: + - configmaps + verbs: + - get + - list +- apiGroups: + - apps + resources: + - deployments + - pods + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - apps resources: @@ -118,9 +167,9 @@ rules: - "" resources: - configmaps + - containers - events - namespaces - - nodes - persistentvolumeclaims - pods - pods/exec @@ -135,6 +184,26 @@ rules: - patch - update - watch +- apiGroups: + - "" + resources: + - configmaps + - containers + - events + - namespaces + - pods + - pods/exec + - pods/log + - secrets + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - "" resources: @@ -428,3 +497,49 @@ rules: - get - patch - update +- apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - observability.oracle.com + resources: + - databaseobservers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - observability.oracle.com + resources: + - databaseobservers/finalizers + verbs: + - update +- apiGroups: + - observability.oracle.com + resources: + - databaseobservers/status + verbs: + - get + - patch + - update +- apiGroups: + - storage.k8s.io + resources: + - storageclasses + verbs: + - get + - list + - watch diff --git a/config/rbac/role_binding.yaml b/config/rbac/role_binding.yaml index 1abe0ec7..f2ccb566 100644 --- a/config/rbac/role_binding.yaml +++ b/config/rbac/role_binding.yaml @@ -3,7 +3,7 @@ # Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. # apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding +kind: RoleBinding metadata: name: oracle-database-operator-manager-rolebinding roleRef: diff --git a/config/samples/adb/autonomousdatabase_backup.yaml b/config/samples/adb/autonomousdatabase_backup.yaml index ac3fb779..0099a347 100644 --- a/config/samples/adb/autonomousdatabase_backup.yaml +++ b/config/samples/adb/autonomousdatabase_backup.yaml @@ -7,7 +7,7 @@ kind: AutonomousDatabaseBackup metadata: name: autonomousdatabasebackup-sample spec: - # Before you can create manual backups, you must have an Object Storage bucket and your database must be configured to connect to it. This is a one-time operation. + # Before you can create on-demand backups, you must have an Object Storage bucket and your database must be configured to connect to it. This is a one-time operation. # See https://docs.oracle.com/en-us/iaas/Content/Database/Tasks/adbbackingup.htm#creatingbucket target: k8sADB: @@ -16,6 +16,8 @@ spec: # ociADB: # ocid: ocid1.autonomousdatabase... displayName: autonomousdatabasebackup-sample + isLongTermBackup: true + retentionPeriodInDays: 90 # minimum retention period is 90 days # Authorize the operator with API signing key pair. Comment out the ociConfig fields if your nodes are already authorized with instance principal. ociConfig: diff --git a/config/samples/adb/autonomousdatabase_create.yaml b/config/samples/adb/autonomousdatabase_create.yaml index 3ecf966f..aa77a94c 100644 --- a/config/samples/adb/autonomousdatabase_create.yaml +++ b/config/samples/adb/autonomousdatabase_create.yaml @@ -1,5 +1,5 @@ # -# Copyright (c) 2022, Oracle and/or its affiliates. +# Copyright (c) 2022, 2024, Oracle and/or its affiliates. # Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. # apiVersion: database.oracle.com/v1alpha1 @@ -30,7 +30,7 @@ spec: # # Uncomment this block to configure the network access type with the RESTRICTED option. # # This option lets you restrict access by defining access control rules in an Access Control List (ACL). - # # By specifying an ACL, the database will be accessible from a whitelisted set of IP addresses, CIDR (Classless Inter-Domain Routing) blocks, or VCNs. + # # By specifying an ACL, the database will be accessible from a whitelisted set of IP addresses, CIDR (Classless Inter-Domain Routing) blocks, or VCNs. # # Use a semicolon (;) as a deliminator between the VCN-specific subnets or IPs. # accessType: RESTRICTED # accessControlList: @@ -42,7 +42,7 @@ spec: # isMTLSConnectionRequired: true # # Uncomment this block to configure the network access type with the PRIVATE option. - # # This option assigns a private endpoint, private IP, and hostname to your database. + # # This option assigns a private endpoint, private IP, and hostname to your database. # # Specifying this option allows traffic only from the VCN you specify. # # This allows you to define security rules, ingress/egress, at the Network Security Group (NSG) level and to control traffic to your Autonomous Database. # accessType: PRIVATE @@ -61,4 +61,5 @@ spec: # Authorize the operator with API signing key pair. Comment out the ociConfig fields if your nodes are already authorized with instance principal. ociConfig: configMapName: oci-cred + # Comment out secretName if using OKE workload identity secretName: oci-privatekey \ No newline at end of file diff --git a/config/samples/adb/autonomousdatabase_update_network_access.yaml b/config/samples/adb/autonomousdatabase_update_network_access.yaml index 0762efcb..f0e98806 100644 --- a/config/samples/adb/autonomousdatabase_update_network_access.yaml +++ b/config/samples/adb/autonomousdatabase_update_network_access.yaml @@ -32,7 +32,7 @@ spec: # accessType: PRIVATE # privateEndpoint: # subnetOCID: ocid1.subnet... - # nsgOCIDs: + # nsgOCIDs: # Optional # - ocid1.networksecuritygroup... # # Uncomment this block to configure the network access of an dedicated Autonomous Database (ADB-D) with an access control list. diff --git a/config/samples/kustomization.yaml b/config/samples/kustomization.yaml index 0ad50fcf..ac5e158f 100644 --- a/config/samples/kustomization.yaml +++ b/config/samples/kustomization.yaml @@ -5,16 +5,29 @@ ## Append samples you want in your CSV to this file as resources ## resources: - - onpremdb/pdb.yaml - - onpremdb/cdb.yaml - - adb/autonomousdatabase_create.yaml + - multitenant/pdb_plug.yaml + - multitenant/cdb_secret.yaml + - multitenant/pdb_secret.yaml + - multitenant/pdb_clone.yaml + - multitenant/cdb.yaml + - sidb/singleinstancedatabase_patch.yaml + - sidb/oraclerestdataservice_apex.yaml + - sidb/singleinstancedatabase_express.yaml + - sidb/singleinstancedatabase_secrets.yaml + - sidb/singleinstancedatabase_clone.yaml + - sidb/singleinstancedatabase_prebuiltdb.yaml + - sidb/dataguardbroker.yaml + - sidb/oraclerestdataservice_secrets.yaml + - sidb/singleinstancedatabase_free.yaml + - sidb/singleinstancedatabase_standby.yaml + - sidb/openshift_rbac.yaml + - sharding/sharding_v1alpha1_provshard_clonespec1.yaml + - sharding/shardingdatabase.yaml + - sharding/sharding_v1alpha1_provshard_clonespec.yaml + - observability/databaseobserver_vault.yaml + - observability/databaseobserver_minimal.yaml - adb/autonomousdatabase_bind.yaml - adb/autonomousdatabase_backup.yaml - adb/autonomousdatabase_restore.yaml - - acd/autonomouscontainerdatabase_create.yaml - - sidb/singleinstancedatabase.yaml - - sharding/shardingdatabase.yaml - - sharding/sharding_v1alpha1_provshard.yaml - - dbcs/database_v1alpha1_dbcssystem.yaml -- database_v1alpha1_dataguardbroker.yaml + - acd/autonomouscontainerdatabase_restart_terminate.yaml # +kubebuilder:scaffold:manifestskustomizesamples diff --git a/config/samples/observability/databaseobserver.yaml b/config/samples/observability/databaseobserver.yaml new file mode 100644 index 00000000..b3140549 --- /dev/null +++ b/config/samples/observability/databaseobserver.yaml @@ -0,0 +1,44 @@ +# example +apiVersion: observability.oracle.com/v1alpha1 +kind: DatabaseObserver +metadata: + name: obs-sample +spec: + database: + dbUser: + key: "username" + secret: db-secret + + dbPassword: + key: "password" + secret: db-secret + + dbConnectionString: + key: "connection" + secret: db-secret + + dbWallet: + secret: instance-wallet + + exporter: + image: "container-registry.oracle.com/database/observability-exporter:latest" + configuration: + configmap: + key: "config.toml" + configmapName: "devcm-oradevdb-config" + + service: + port: 9161 + + prometheus: + port: metrics + labels: + app: app-sample-label + + replicas: 1 + + ociConfig: + configMapName: oci-cred + secretName: oci-privatekey + + diff --git a/config/samples/observability/databaseobserver_custom_config.yaml b/config/samples/observability/databaseobserver_custom_config.yaml new file mode 100644 index 00000000..1e9fff47 --- /dev/null +++ b/config/samples/observability/databaseobserver_custom_config.yaml @@ -0,0 +1,28 @@ +# example +apiVersion: observability.oracle.com/v1alpha1 +kind: DatabaseObserver +metadata: + name: obs-sample + namespace: observer +spec: + database: + dbUser: + key: "username" + secret: db-secret + + dbPassword: + key: "password" + secret: db-secret + + dbConnectionString: + key: "connection" + secret: db-secret + + dbWallet: + secret: instance-wallet + + exporter: + configuration: + configmap: + key: "config.toml" + configmapName: "devcm-oradevdb-config" \ No newline at end of file diff --git a/config/samples/observability/databaseobserver_minimal.yaml b/config/samples/observability/databaseobserver_minimal.yaml new file mode 100644 index 00000000..2eeaf3ab --- /dev/null +++ b/config/samples/observability/databaseobserver_minimal.yaml @@ -0,0 +1,22 @@ +# example +apiVersion: observability.oracle.com/v1alpha1 +kind: DatabaseObserver +metadata: + name: obs-sample + namespace: observer +spec: + database: + dbUser: + key: "username" + secret: db-secret + + dbPassword: + key: "password" + secret: db-secret + + dbConnectionString: + key: "connection" + secret: db-secret + + dbWallet: + secret: instance-wallets \ No newline at end of file diff --git a/config/samples/observability/databaseobserver_vault.yaml b/config/samples/observability/databaseobserver_vault.yaml new file mode 100644 index 00000000..fa2e09d4 --- /dev/null +++ b/config/samples/observability/databaseobserver_vault.yaml @@ -0,0 +1,25 @@ +# example +apiVersion: observability.oracle.com/v1alpha1 +kind: DatabaseObserver +metadata: + name: obs-sample +spec: + database: + dbUser: + key: "username" + secret: db-secret + + dbPassword: + vaultSecretName: sample_secret + vaultOCID: ocid1.vault.oc1.. + + dbConnectionString: + key: "connection" + secret: db-secret + + dbWallet: + secret: instance-wallet + + ociConfig: + configMapName: oci-cred + secretName: oci-privatekey \ No newline at end of file diff --git a/config/samples/observability/sample-dashboard.json b/config/samples/observability/sample-dashboard.json new file mode 100644 index 00000000..5b05b05c --- /dev/null +++ b/config/samples/observability/sample-dashboard.json @@ -0,0 +1,1414 @@ +{ + "__inputs": [ + { + "name": "Prometheus", + "label": "prometheus", + "description": "", + "type": "datasource", + "pluginId": "prometheus", + "pluginName": "Prometheus" + } + ], + "__requires": [ + { + "type": "grafana", + "id": "grafana", + "name": "Grafana", + "version": "4.5.1" + }, + { + "type": "panel", + "id": "graph", + "name": "Graph", + "version": "" + }, + { + "type": "datasource", + "id": "prometheus", + "name": "Prometheus", + "version": "1.0.0" + }, + { + "type": "panel", + "id": "singlestat", + "name": "Singlestat", + "version": "" + } + ], + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 5, + "links": [], + "liveNow": false, + "panels": [ + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 0 + }, + "id": 3, + "panels": [], + "title": "Oracle Database Details", + "type": "row" + }, + { + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [ + { + "options": { + "0": { + "index": 1, + "text": "DEAD" + }, + "1": { + "index": 0, + "text": "ALIVE" + } + }, + "type": "value" + } + ], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 4, + "x": 0, + "y": 1 + }, + "id": 10, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.5.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "builder", + "exemplar": false, + "expr": "oracledb_up", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "A" + } + ], + "title": "Database Status", + "type": "stat" + }, + { + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 3, + "x": 4, + "y": 1 + }, + "id": 5, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.5.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "builder", + "exemplar": false, + "expr": "oracledb_obaas_db_system_value{name=\"sga_max_size\"}", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "A" + } + ], + "title": "SGA Max Size", + "type": "stat" + }, + { + "datasource": "Prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "decbytes" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 3, + "x": 7, + "y": 1 + }, + "id": 6, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.5.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "builder", + "exemplar": false, + "expr": "oracledb_obaas_db_system_value{name=\"pga_aggregate_limit\"}", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "A" + } + ], + "title": "PGA Aggregate Limit", + "type": "stat" + }, + { + "datasource": "Prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 5, + "x": 10, + "y": 1 + }, + "id": 11, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.5.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "builder", + "expr": "oracledb_sessions_value{status=\"ACTIVE\"}", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Active Sessions", + "type": "stat" + }, + { + "datasource": "Prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 3, + "x": 15, + "y": 1 + }, + "id": 12, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.5.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "builder", + "expr": "oracledb_activity_user_commits", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "User commits", + "type": "stat" + }, + { + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "none" + }, + "overrides": [] + }, + "gridPos": { + "h": 6, + "w": 3, + "x": 18, + "y": 1 + }, + "id": 13, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.5.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "builder", + "expr": "oracledb_activity_execute_count", + "legendFormat": "__auto", + "range": true, + "refId": "A" + } + ], + "title": "Execute count", + "type": "stat" + }, + { + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 21, + "y": 1 + }, + "id": 7, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": false + }, + "pluginVersion": "9.5.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": false, + "expr": "max(oracledb_obaas_db_platform_value) by (platform_name)", + "format": "table", + "instant": true, + "legendFormat": "{{platform_name}}", + "range": false, + "refId": "A" + } + ], + "title": "Database Platform", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true, + "Value": true + }, + "indexByName": {}, + "renameByName": {} + } + } + ], + "type": "table" + }, + { + "datasource": "Prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [] + }, + "gridPos": { + "h": 3, + "w": 3, + "x": 21, + "y": 4 + }, + "id": 2, + "options": { + "colorMode": "value", + "graphMode": "area", + "justifyMode": "auto", + "orientation": "auto", + "reduceOptions": { + "calcs": [ + "lastNotNull" + ], + "fields": "", + "values": false + }, + "textMode": "auto" + }, + "pluginVersion": "9.5.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "builder", + "exemplar": false, + "expr": "oracledb_obaas_db_system_value{name=\"cpu_count\"}", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "A" + } + ], + "title": "CPU Count", + "type": "stat" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 7 + }, + "id": 8, + "panels": [], + "title": "Top SQL", + "type": "row" + }, + { + "datasource": "Prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "thresholds" + }, + "custom": { + "align": "auto", + "cellOptions": { + "type": "auto" + }, + "inspect": false + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + } + }, + "overrides": [ + { + "matcher": { + "id": "byName", + "options": "SQL ID" + }, + "properties": [ + { + "id": "custom.width", + "value": 226 + } + ] + }, + { + "matcher": { + "id": "byName", + "options": "SQL Text (extract)" + }, + "properties": [ + { + "id": "custom.width", + "value": 1311 + } + ] + } + ] + }, + "gridPos": { + "h": 9, + "w": 24, + "x": 0, + "y": 8 + }, + "id": 9, + "options": { + "cellHeight": "sm", + "footer": { + "countRows": false, + "fields": "", + "reducer": [ + "sum" + ], + "show": false + }, + "showHeader": true, + "sortBy": [] + }, + "pluginVersion": "9.5.2", + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "code", + "exemplar": false, + "expr": "max(oracledb_obaas_top_sql_elapsed) by (sql_id, sql_text)", + "format": "table", + "instant": true, + "legendFormat": "__auto", + "range": false, + "refId": "A" + } + ], + "title": "Top SQL by elapsed time running", + "transformations": [ + { + "id": "organize", + "options": { + "excludeByName": { + "Time": true + }, + "indexByName": {}, + "renameByName": { + "Value": "Elapsed Time", + "sql_id": "SQL ID", + "sql_text": "SQL Text (extract)" + } + } + }, + { + "id": "sortBy", + "options": { + "fields": {}, + "sort": [ + { + "desc": true, + "field": "Elapsed Time" + } + ] + } + } + ], + "type": "table" + }, + { + "collapsed": false, + "gridPos": { + "h": 1, + "w": 24, + "x": 0, + "y": 17 + }, + "id": 4, + "panels": [], + "title": "System Wait Classes", + "type": "row" + }, + { + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 19, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "µs" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 18 + }, + "id": 14, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "builder", + "expr": "oracledb_wait_time_concurrency", + "interval": "$interval", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Wait time - Concurrency", + "type": "timeseries" + }, + { + "datasource": "Prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "µs" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 18 + }, + "id": 15, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "builder", + "expr": "oracledb_wait_time_commit", + "interval": "$interval", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Wait time - Commit", + "type": "timeseries" + }, + { + "datasource": "Prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "µs" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 26 + }, + "id": 16, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "builder", + "expr": "oracledb_wait_time_system_io", + "interval": "$interval", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Wait time - System I/O", + "type": "timeseries" + }, + { + "datasource": "Prometheus", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "µs" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 26 + }, + "id": 17, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "builder", + "expr": "oracledb_wait_time_user_io", + "interval": "$interval", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Wait time - User I/O", + "type": "timeseries" + }, + { + "datasource": "Prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "µs" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 34 + }, + "id": 18, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "builder", + "expr": "oracledb_wait_time_application", + "interval": "$interval", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Wait time - Application", + "type": "timeseries" + }, + { + "datasource": "Prometheus", + "description": "", + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 20, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green" + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unit": "µs" + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 12, + "y": 34 + }, + "id": 19, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": false + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "PBFA97CFB590B2093" + }, + "editorMode": "builder", + "expr": "oracledb_wait_time_network", + "interval": "$interval", + "legendFormat": "", + "range": true, + "refId": "A" + } + ], + "title": "Wait time - Network", + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 38, + "style": "dark", + "tags": [], + "templating": { + "list": [ + { + "auto": true, + "auto_count": 200, + "auto_min": "10s", + "current": { + "selected": false, + "text": "auto", + "value": "$__auto_interval_interval" + }, + "hide": 0, + "label": "Interval", + "name": "interval", + "options": [ + { + "selected": true, + "text": "auto", + "value": "$__auto_interval_interval" + }, + { + "selected": false, + "text": "1m", + "value": "1m" + }, + { + "selected": false, + "text": "10m", + "value": "10m" + }, + { + "selected": false, + "text": "30m", + "value": "30m" + }, + { + "selected": false, + "text": "1h", + "value": "1h" + }, + { + "selected": false, + "text": "6h", + "value": "6h" + }, + { + "selected": false, + "text": "12h", + "value": "12h" + }, + { + "selected": false, + "text": "1d", + "value": "1d" + }, + { + "selected": false, + "text": "7d", + "value": "7d" + }, + { + "selected": false, + "text": "14d", + "value": "14d" + }, + { + "selected": false, + "text": "30d", + "value": "30d" + } + ], + "query": "1m,10m,30m,1h,6h,12h,1d,7d,14d,30d", + "refresh": 2, + "skipUrlSync": false, + "type": "interval" + } + ] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "Oracle Dashboard", + "uid": "obaas_oracle_dashboard", + "version": 20, + "weekStart": "" +} \ No newline at end of file diff --git a/config/samples/observability/sample_config.toml b/config/samples/observability/sample_config.toml new file mode 100644 index 00000000..0989d769 --- /dev/null +++ b/config/samples/observability/sample_config.toml @@ -0,0 +1,29 @@ +[[metric]] +context = "obaas_db_system" +labels = [ "name" ] +metricsdesc = { value = "Database system resources metric" } +request = ''' +select name, value +from v$parameter +where name in ('cpu_count', 'sga_max_size', 'pga_aggregate_limit') +''' + +[[metric]] +context = "obaas_db_platform" +labels = [ "platform_name" ] +metricsdesc = { value = "Database platform" } +request = ''' +SELECT platform_name, 1 as value FROM v$database +''' + +[[metric]] +context = "obaas_top_sql" +labels = [ "sql_id", "sql_text" ] +metricsdesc = { elapsed = "SQL statement elapsed time running" } +request = ''' +select * from ( +select sql_id, elapsed_time / 1000000 as elapsed, SUBSTRB(REPLACE(sql_text,'',' '),1,55) as sql_text +from V$SQLSTATS +order by elapsed_time desc +) where ROWNUM <= 15 +''' diff --git a/config/samples/sidb/dataguardbroker.yaml b/config/samples/sidb/dataguardbroker.yaml index 26ab9d79..5425afb7 100644 --- a/config/samples/sidb/dataguardbroker.yaml +++ b/config/samples/sidb/dataguardbroker.yaml @@ -10,7 +10,7 @@ metadata: namespace: default spec: - ## Primary DB ref. This can be of kind SingleInstanceDatabase or CloneDB + ## Primary DB ref. This is of kind SingleInstanceDatabase primaryDatabaseRef: "sidb-sample" ## Standby DB pod CRD Metadata Name to add this DB to DG config diff --git a/config/samples/sidb/openshift_rbac.yaml b/config/samples/sidb/openshift_rbac.yaml index 8c88f78e..6dddb80d 100644 --- a/config/samples/sidb/openshift_rbac.yaml +++ b/config/samples/sidb/openshift_rbac.yaml @@ -1,73 +1,94 @@ # -# Copyright (c) 2023, Oracle and/or its affiliates. +# Copyright (c) 2024, Oracle and/or its affiliates. # Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. # - --- -# Create a Security Context Contraint - kind: SecurityContextConstraints - apiVersion: v1 - metadata: - name: sidb-scc - namespace: default - allowPrivilegedContainer: false - users: - - system:serviceaccount:default:sidb-sa - - system:serviceaccount:default:oracle-database-operator - runAsUser: - type: MustRunAsRange - uidRangeMin: 0 - uidRangeMax: 60000 - seLinuxContext: - type: RunAsAny - fsGroup: - type: MustRunAs - ranges: - - min: 0 - max: 60000 - supplementalGroups: +# Create a Security Context Contraint +kind: SecurityContextConstraints +apiVersion: security.openshift.io/v1 +metadata: + name: sidb-oracle-user-scc +allowPrivilegedContainer: false +allowedCapabilities: + - SYS_NICE +runAsUser: + type: MustRunAs + uid: 54321 +seLinuxContext: + type: RunAsAny +fsGroup: + type: MustRunAs + ranges: + - min: 54321 + max: 54321 +supplementalGroups: type: MustRunAs ranges: - - min: 0 - max: 60000 + - min: 54321 + max: 54321 +--- +# Create a Security Context Contraint +kind: SecurityContextConstraints +apiVersion: security.openshift.io/v1 +metadata: + name: sidb-oracle-root-user-scc +allowPrivilegedContainer: false +allowedCapabilities: + - SYS_NICE +runAsUser: + type: MustRunAsRange + uidRangeMin: 0 + uidRangeMax: 54321 +seLinuxContext: + type: RunAsAny +fsGroup: + type: MustRunAs + ranges: + - min: 0 + max: 54321 +supplementalGroups: + type: MustRunAs + ranges: + - min: 0 + max: 5432 --- -# Create Service Account apiVersion: v1 kind: ServiceAccount metadata: name: sidb-sa - namespace: default - + namespace: sidb-ns --- -# Create a rbac role - - kind: Role - apiVersion: rbac.authorization.k8s.io/v1 - metadata: - name: use-sidb-scc - namespace: default - rules: - - apiGroups: ["security.openshift.io"] - resources: ["securitycontextconstraints"] - resourceNames: ["sidb-scc"] - verbs: ["use"] +kind: Role +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: use-sidb-scc + namespace: sidb-ns +rules: + - apiGroups: + - security.openshift.io + verbs: + - use + resources: + - securitycontextconstraints + resourceNames: + - sidb-oracle-user-scc + - sidb-oracle-root-user-scc --- -# Create a rbac role binding - kind: RoleBinding - apiVersion: rbac.authorization.k8s.io/v1 - metadata: - name: use-sidb-scc - namespace: default - subjects: - - kind: ServiceAccount - name: sidb-sa - roleRef: - kind: Role - name: use-sidb-scc - apiGroup: rbac.authorization.k8s.io - \ No newline at end of file +kind: RoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: use-sidb-scc + namespace: sidb-ns +subjects: + - kind: ServiceAccount + name: sidb-sa + namespace: sidb-ns +roleRef: + kind: Role + name: use-sidb-scc + apiGroup: rbac.authorization.k8s.io diff --git a/config/samples/sidb/oraclerestdataservice.yaml b/config/samples/sidb/oraclerestdataservice.yaml index cef0276f..911a9b1e 100644 --- a/config/samples/sidb/oraclerestdataservice.yaml +++ b/config/samples/sidb/oraclerestdataservice.yaml @@ -41,10 +41,9 @@ spec: keepSecret: true ## ORDS image details - ## Build the ORDS image following instructions at - ## https://github.com/oracle/docker-images/tree/main/OracleRestDataServices + ## Supported ORDS image is container-registry.oracle.com/database/ords:21.4.2-gh image: - pullFrom: + pullFrom: container-registry.oracle.com/database/ords:21.4.2-gh pullSecrets: ## Dedicated persistent storage is optional. If not specified, ORDS will use persistent storage from .spec.databaseRef diff --git a/config/samples/sidb/singleinstancedatabase.yaml b/config/samples/sidb/singleinstancedatabase.yaml index 407223fa..4425acea 100644 --- a/config/samples/sidb/singleinstancedatabase.yaml +++ b/config/samples/sidb/singleinstancedatabase.yaml @@ -11,36 +11,33 @@ spec: ## Use only alphanumeric characters for sid up to a maximum of 8 characters sid: ORCL1 - - ## Specify a source database ref to copy/clone from any SIDB in current K8s cluster instead of creating a fresh one - ## If cloning from an external containerized DB which could be either standalone or in any K8s cluster, - ## specify connect string as `:/` instead of source database ref - cloneFrom: "" - - ## Reference to a source primary database from which - ## Format: 1. Intra-cluster: you can give name of the primary database or the database connect string in `:/` format - ## 2. Inter-cluster: Database connect string in `:/` format - primaryDatabaseRef: "" - ## Enable this flag for creating Physical Standby Database - createAsStandby: false - - ## DB edition. N/A if cloning from a Source DB in current K8s cluster (if cloneFrom is set to a database ref) - ## Valid values for edition are enterprise, standard or express + ## DB edition. N/A for createAs clone or standby + ## Valid values for edition are enterprise, standard, express or free edition: enterprise + + ## Type of database. + ## Valid values for createAs are primary, clone or standby + ## Valid only for enterprise and standard editions + createAs: primary + + ## Reference to a source primary database. + ## Valid only for createAs clone or standby + ## The name of a source primary database resource from the same namespace + primaryDatabaseRef: "" ## Secret containing SIDB password mapped to secretKey. secretKey defaults to oracle_pwd - ## Should refer to adminPassword of Source DB if cloning from a Source DB (i.e if cloneFrom is set) + ## Should refer to adminPassword of Source DB if createAs is clone or standby ## This secret will be deleted after creation of the database unless keepSecret is set to true which is the default adminPassword: secretName: secretKey: keepSecret: true - ## DB character set. N/A if cloning from a Source DB (if cloneFrom is set) + ## DB character set. N/A for createAs clone or standby charset: AL32UTF8 - ## PDB name. N/A if cloning from a Source DB (if cloneFrom is set) + ## PDB name. N/A for createAs clone or standby pdbName: orclpdb1 ## Enable/Disable Flashback @@ -53,18 +50,23 @@ spec: forceLog: false ## Enable TCPS - enableTCPS: false + enableTCPS: - ## TCPS Certificate Renewal Interval: The time after which TCPS certificate will be renewed if TCPS connections are enabled. + ## User specified TLS-Cert Secret + ## The following specified TLS certs will be used instead of self-signed + tcpsTlsSecret: + + ## TCPS Certificate Renewal Interval: (Valid for Self-Signed Certificates) + ## The time after which TCPS certificate will be renewed if TCPS connections are enabled. ## tcpsCertRenewInterval can be in hours(h), minutes(m) and seconds(s); e.g. 4380h, 8760h etc. ## Maximum value is 8760h (1 year), Minimum value is 24h; Default value is 8760h (1 year) ## If this field is commented out/removed from the yaml, it will disable the auto-renewal feature for TCPS certificate tcpsCertRenewInterval: 8760h - ## NA if cloning from a SourceDB (cloneFrom is set) - ## Specify both sgaSize and pgaSize (in MB) or dont specify both + ## N/A for createAs clone or standby ## Specify Non-Zero value to use - ## You cannot change these initParams for Oracle Database Express (XE) edition + ## sgaTarget and pgaAggregateTarget must be in MB + ## You cannot change these initParams for Oracle Database Express (XE) and Oracle Database Free edition initParams: cpuCount: 0 processes: 0 @@ -82,16 +84,39 @@ spec: pullSecrets: prebuiltDB: false + + ## Database storage details ## size is the required minimum size of the persistent volume - ## storageClass is specified for automatic volume provisioning - ## accessMode can only accept one of ReadWriteOnce, ReadWriteMany - ## volumeName is optional. Specify for binding to a specific PV and set storageClass to an empty string to disable automatic volume provisioning + ## storageClass is specified for dynamic volume provisioning and datafilesVolumeName for static provisioning persistence: + ## if the storageClass supports volume expansion, patch the size attribute to expand the volume + ## Shrinking volumes is not allowed size: 100Gi - ## oci-bv applies to OCI block volumes. Use "standard" storageClass for dynamic provisioning in Minikube. Update as appropriate for other cloud service providers + ## set ownership/permissions for writing to datafiles volume. This is usually needed for NFS volumes. + setWritePermissions: true + ## oci-bv applies to OCI block volumes. Use "standard" storageClass for dynamic provisioning in Minikube. Update as appropriate for other cloud services storageClass: "oci-bv" + ## accessMode can only accept one of ReadWriteOnce, ReadWriteMany accessMode: "ReadWriteOnce" - volumeName: "" + ## datafilesVolumeName is optional. Specify for binding to a specific PV and set storageClass to an empty string to disable automatic volume provisioning + datafilesVolumeName: "" + ## Optionally specify a volume containing scripts in 'setup' and 'startup' folders to be executed during database setup and startup respectively. + scriptsVolumeName: "" + + ## Database pod resource details + ## cpu can be expressed in terms of cpu units and can be a plain integer or fractional value + ## memory is measured in bytes and can be expressed in plain integer or as a fixed-point number + ## using one of these quantity suffixes: E, P, T, G, M, k. + ## You can also use the power-of-two equivalents: Ei, Pi, Ti, Gi, Mi, Ki. + resources: + ## requests denotes minimum node resources required/to be utilized by the database pod + requests: + cpu: + memory: + ## limits specifies the maximum node resources that can be utilized by the database pod + limits: + cpu: + memory: ## Type of service . Applicable on cloud enviroments only ## if loadBalService : false, service type = "NodePort" else "LoadBalancer" diff --git a/config/samples/sidb/singleinstancedatabase_clone.yaml b/config/samples/sidb/singleinstancedatabase_clone.yaml index c0e1eace..f25484d9 100644 --- a/config/samples/sidb/singleinstancedatabase_clone.yaml +++ b/config/samples/sidb/singleinstancedatabase_clone.yaml @@ -13,9 +13,12 @@ spec: ## Use only alphanumeric characters for sid sid: ORCL2 - ## A source database ref to clone from. + ## The name of a source primary database resource to clone from the same namespace ## Make sure the source database has been created by applying singeinstancedatabase_create.yaml - cloneFrom: sidb-sample + primaryDatabaseRef: sidb-sample + + ## Intended type of database. + createAs: clone ## Should refer to SourceDB secret ## Secret containing SIDB password mapped to secretKey diff --git a/config/samples/sidb/singleinstancedatabase_free.yaml b/config/samples/sidb/singleinstancedatabase_free.yaml index 558bd8f4..6dd0aa39 100644 --- a/config/samples/sidb/singleinstancedatabase_free.yaml +++ b/config/samples/sidb/singleinstancedatabase_free.yaml @@ -35,5 +35,5 @@ spec: storageClass: "oci-bv" accessMode: "ReadWriteOnce" - ## Count of Database Pods. Should be 1 for express edition. + ## Count of Database Pods. Should be 1 for free edition. replicas: 1 \ No newline at end of file diff --git a/config/samples/sidb/singleinstancedatabase_standby.yaml b/config/samples/sidb/singleinstancedatabase_standby.yaml index e93cc5e4..644438b4 100644 --- a/config/samples/sidb/singleinstancedatabase_standby.yaml +++ b/config/samples/sidb/singleinstancedatabase_standby.yaml @@ -15,11 +15,11 @@ spec: ## Use only alphanumeric characters for sid sid: ORCLS - ## Reference to a source primary database name + ## The name of a source primary database resource from the same namespace primaryDatabaseRef: "sidb-sample" - ## Enable this flag for creating Physical Standby Database - createAsStandby: true + ## Intended type of database. + createAs: standby ## Secret containing SIDB password mapped to secretKey adminPassword: @@ -43,3 +43,5 @@ spec: ## if loadBalService : false, service type = "NodePort" else "LoadBalancer" loadBalancer: false + replicas: 1 + \ No newline at end of file diff --git a/config/samples/sidb/singleinstancedatabase_tcps.yaml b/config/samples/sidb/singleinstancedatabase_tcps.yaml index d11a0d2a..06389f96 100644 --- a/config/samples/sidb/singleinstancedatabase_tcps.yaml +++ b/config/samples/sidb/singleinstancedatabase_tcps.yaml @@ -34,7 +34,12 @@ spec: ## Enable TCPS enableTCPS: true - ## TCPS Certificate Renewal Interval: The time after which TCPS certificate will be renewed if TCPS connections are enabled. + ## User specified TLS-Cert Secret + ## The following specified TLS certs will be used instead of self-signed + tcpsTlsSecret: my-tls-secret + + ## TCPS Certificate Renewal Interval: (Valid for Self-Signed Certificates) + ## The time after which TCPS certificate will be renewed if TCPS connections are enabled. ## tcpsCertRenewInterval can be in hours(h), minutes(m) and seconds(s); e.g. 4380h, 8760h etc. ## Maximum value is 8760h (1 year), Minimum value is 24h; Default value is 8760h (1 year) ## If this field is commented out/removed from the yaml, it will disable the auto-renewal feature for TCPS certificate diff --git a/config/webhook/manifests.yaml b/config/webhook/manifests.yaml index 28f50b79..c150867f 100644 --- a/config/webhook/manifests.yaml +++ b/config/webhook/manifests.yaml @@ -130,6 +130,26 @@ webhooks: resources: - pdbs sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-database-oracle-com-v1alpha1-shardingdatabase + failurePolicy: Fail + name: mshardingdatabase.kb.io + rules: + - apiGroups: + - database.oracle.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - shardingdatabases + sideEffects: None - admissionReviewVersions: - v1 - v1beta1 @@ -151,6 +171,26 @@ webhooks: resources: - singleinstancedatabases sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /mutate-observability-oracle-com-v1alpha1-databaseobserver + failurePolicy: Fail + name: mdatabaseobserver.kb.io + rules: + - apiGroups: + - observability.oracle.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - databaseobservers + sideEffects: None --- apiVersion: admissionregistration.k8s.io/v1 @@ -323,6 +363,27 @@ webhooks: resources: - pdbs sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-database-oracle-com-v1alpha1-shardingdatabase + failurePolicy: Fail + name: vshardingdatabase.kb.io + rules: + - apiGroups: + - database.oracle.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + - DELETE + resources: + - shardingdatabases + sideEffects: None - admissionReviewVersions: - v1 - v1beta1 @@ -345,3 +406,23 @@ webhooks: resources: - singleinstancedatabases sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: webhook-service + namespace: system + path: /validate-observability-oracle-com-v1alpha1-databaseobserver + failurePolicy: Fail + name: vdatabaseobserver.kb.io + rules: + - apiGroups: + - observability.oracle.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - databaseobservers + sideEffects: None diff --git a/controllers/database/autonomousdatabase_controller.go b/controllers/database/autonomousdatabase_controller.go index 379ab86b..bf56bfe0 100644 --- a/controllers/database/autonomousdatabase_controller.go +++ b/controllers/database/autonomousdatabase_controller.go @@ -52,8 +52,9 @@ import ( "github.com/oracle/oci-go-sdk/v65/common" "github.com/oracle/oci-go-sdk/v65/database" - corev1 "k8s.io/api/core/v1" apiErrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" @@ -66,7 +67,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" - "sigs.k8s.io/controller-runtime/pkg/source" dbv1alpha1 "github.com/oracle/oracle-database-operator/apis/database/v1alpha1" "github.com/oracle/oracle-database-operator/commons/annotations" @@ -92,33 +92,30 @@ func (r *AutonomousDatabaseReconciler) SetupWithManager(mgr ctrl.Manager) error return ctrl.NewControllerManagedBy(mgr). For(&dbv1alpha1.AutonomousDatabase{}). Watches( - &source.Kind{Type: &dbv1alpha1.AutonomousDatabaseBackup{}}, - handler.EnqueueRequestsFromMapFunc(r.enqueueMapFn()), + &dbv1alpha1.AutonomousDatabaseBackup{}, + handler.EnqueueRequestsFromMapFunc(r.enqueueMapFn), ). Watches( - &source.Kind{Type: &dbv1alpha1.AutonomousDatabaseRestore{}}, - handler.EnqueueRequestsFromMapFunc(r.enqueueMapFn()), + &dbv1alpha1.AutonomousDatabaseRestore{}, + handler.EnqueueRequestsFromMapFunc(r.enqueueMapFn), ). WithEventFilter(predicate.And(r.eventFilterPredicate(), r.watchPredicate())). WithOptions(controller.Options{MaxConcurrentReconciles: 50}). // ReconcileHandler is never invoked concurrently with the same object. Complete(r) } +func (r *AutonomousDatabaseReconciler) enqueueMapFn(ctx context.Context, o client.Object) []reconcile.Request { + reqs := make([]reconcile.Request, len(o.GetOwnerReferences())) -func (r *AutonomousDatabaseReconciler) enqueueMapFn() handler.MapFunc { - return func(o client.Object) []reconcile.Request { - reqs := make([]reconcile.Request, len(o.GetOwnerReferences())) - - for _, owner := range o.GetOwnerReferences() { - reqs = append(reqs, reconcile.Request{ - NamespacedName: types.NamespacedName{ - Name: owner.Name, - Namespace: o.GetNamespace(), - }, - }) - } - - return reqs + for _, owner := range o.GetOwnerReferences() { + reqs = append(reqs, reconcile.Request{ + NamespacedName: types.NamespacedName{ + Name: owner.Name, + Namespace: o.GetNamespace(), + }, + }) } + + return reqs } func (r *AutonomousDatabaseReconciler) watchPredicate() predicate.Predicate { @@ -157,10 +154,17 @@ func (r *AutonomousDatabaseReconciler) eventFilterPredicate() predicate.Predicat if adbOk { oldADB := e.ObjectOld.(*dbv1alpha1.AutonomousDatabase) - if !reflect.DeepEqual(oldADB.Status, desiredADB.Status) || - (controllerutil.ContainsFinalizer(oldADB, dbv1alpha1.LastSuccessfulSpec) != controllerutil.ContainsFinalizer(desiredADB, dbv1alpha1.LastSuccessfulSpec)) || - (controllerutil.ContainsFinalizer(oldADB, dbv1alpha1.ADBFinalizer) != controllerutil.ContainsFinalizer(desiredADB, dbv1alpha1.ADBFinalizer)) { - // Don't enqueue if the status, lastSucSpec, or the finalizler changes + specChanged := !reflect.DeepEqual(oldADB.Spec, desiredADB.Spec) + statusChanged := !reflect.DeepEqual(oldADB.Status, desiredADB.Status) + + oldLastSucSpec := oldADB.GetAnnotations()[dbv1alpha1.LastSuccessfulSpec] + desiredLastSucSpec := desiredADB.GetAnnotations()[dbv1alpha1.LastSuccessfulSpec] + lastSucSpecChanged := oldLastSucSpec != desiredLastSucSpec + + if (!specChanged && statusChanged) || lastSucSpecChanged || + (controllerutil.ContainsFinalizer(oldADB, dbv1alpha1.ADB_FINALIZER) != controllerutil.ContainsFinalizer(desiredADB, dbv1alpha1.ADB_FINALIZER)) { + // Don't enqueue in the folowing condition: + // 1. only status changes 2. lastSucSpec changes 3. ADB_FINALIZER changes return false } @@ -183,6 +187,7 @@ func (r *AutonomousDatabaseReconciler) eventFilterPredicate() predicate.Predicat // +kubebuilder:rbac:groups=database.oracle.com,resources=autonomouscontainerdatabases,verbs=get;list // +kubebuilder:rbac:groups=coordination.k8s.io,resources=leases,verbs=create;get;list;update // +kubebuilder:rbac:groups="",resources=configmaps;secrets,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups="",resources=events,verbs=create;patch // Reconcile is the funtion that the operator calls every time when the reconciliation loop is triggered. // It go to the beggining of the reconcile if an error is returned. We won't return a error if it is related @@ -271,33 +276,42 @@ func (r *AutonomousDatabaseReconciler) Reconcile(ctx context.Context, req ctrl.R } /****************************************************************** - * Requeue if it's in an intermediate state. Update the status right before - * exiting the reconcile, otherwise the modifiedADB will be overwritten - * by the object returned from the cluster. + * Update the resource if the spec has been changed. + * This will trigger another reconcile, so returns with an empty + * result. ******************************************************************/ - if dbv1alpha1.IsADBIntermediateState(modifiedADB.Status.LifecycleState) { - logger.WithName("IsADBIntermediateState").Info("LifecycleState is " + string(modifiedADB.Status.LifecycleState) + "; reconcile queued") - - if err := r.KubeClient.Status().Update(context.TODO(), modifiedADB); err != nil { - return r.manageError(logger.WithName("IsADBIntermediateState"), modifiedADB, err) + if !reflect.DeepEqual(modifiedADB.Spec, desiredADB.Spec) { + if err := r.KubeClient.Update(context.TODO(), modifiedADB); err != nil { + return r.manageError(logger.WithName("updateSpec"), modifiedADB, err) } + return emptyResult, nil + } + + /****************************************************************** + * Update the status at the end of every reconcile. + ******************************************************************/ + copiedADB := modifiedADB.DeepCopy() + updateCondition(modifiedADB, nil) + if err := r.KubeClient.Status().Update(context.TODO(), modifiedADB); err != nil { + return r.manageError(logger.WithName("Status().Update"), modifiedADB, err) + } + modifiedADB.Spec = copiedADB.Spec + + if dbv1alpha1.IsADBIntermediateState(modifiedADB.Status.LifecycleState) { + logger.WithName("IsADBIntermediateState").Info("LifecycleState is " + string(modifiedADB.Status.LifecycleState) + "; reconcile queued") return requeueResult, nil } /****************************************************************** - * Update the lastSucSpec and the status, and then finish the reconcile. - * Requeue if it's in an intermediate state or the modifiedADB - * doesn't match the desiredADB. + * Update the lastSucSpec, and then finish the reconcile. + * Requeue if the ADB is terminated, but the finalizer is not yet + * removed. ******************************************************************/ - // Do the comparison before updating the status to avoid being overwritten - var requeue bool = false - if !reflect.DeepEqual(modifiedADB.Spec, desiredADB.Spec) { - requeue = true - } + var requeue bool = false if modifiedADB.GetDeletionTimestamp() != nil && - controllerutil.ContainsFinalizer(modifiedADB, dbv1alpha1.ADBFinalizer) && + controllerutil.ContainsFinalizer(modifiedADB, dbv1alpha1.ADB_FINALIZER) && modifiedADB.Status.LifecycleState == database.AutonomousDatabaseLifecycleStateTerminated { logger.Info("The ADB is TERMINATED. The CR is to be deleted but finalizer is not yet removed; reconcile queued") requeue = true @@ -307,10 +321,6 @@ func (r *AutonomousDatabaseReconciler) Reconcile(ctx context.Context, req ctrl.R return r.manageError(logger.WithName("patchLastSuccessfulSpec"), modifiedADB, err) } - if err := r.KubeClient.Status().Update(context.TODO(), modifiedADB); err != nil { - return r.manageError(logger.WithName("Status().Update"), modifiedADB, err) - } - if requeue { logger.Info("Reconcile queued") return requeueResult, nil @@ -343,20 +353,24 @@ func (r *AutonomousDatabaseReconciler) setupOCIClients(logger logr.Logger, adb * return nil } -func (r *AutonomousDatabaseReconciler) manageError(logger logr.Logger, adb *dbv1alpha1.AutonomousDatabase, issue error) (ctrl.Result, error) { +func (r *AutonomousDatabaseReconciler) manageError(logger logr.Logger, adb *dbv1alpha1.AutonomousDatabase, err error) (ctrl.Result, error) { l := logger.WithName("manageError") - // Has synced at least once - if adb.Status.LifecycleState != "" { - // Send event - r.Recorder.Event(adb, corev1.EventTypeWarning, "UpdateFailed", issue.Error()) + if adb.Status.LifecycleState == "" { + // First time entering reconcile + updateCondition(adb, err) + + l.Error(err, "CreateFailed") - var finalIssue = issue + return emptyResult, nil + } else { + // Has synced at least once + var finalError = err // Roll back ociADB := adb.DeepCopy() specChanged, err := r.getADB(l, ociADB) if err != nil { - finalIssue = k8s.CombineErrors(finalIssue, err) + finalError = k8s.CombineErrors(finalError, err) } // Will exit the Reconcile anyway after the manageError is called. @@ -364,25 +378,72 @@ func (r *AutonomousDatabaseReconciler) manageError(logger logr.Logger, adb *dbv1 // Clear the lifecycleState first to avoid the webhook error when update during an intermediate state adb.Status.LifecycleState = "" if err := r.KubeClient.Status().Update(context.TODO(), adb); err != nil { - finalIssue = k8s.CombineErrors(finalIssue, err) + finalError = k8s.CombineErrors(finalError, err) } adb.Spec = ociADB.Spec if err := r.KubeClient.Update(context.TODO(), adb); err != nil { - finalIssue = k8s.CombineErrors(finalIssue, err) + finalError = k8s.CombineErrors(finalError, err) } } - l.Error(finalIssue, "UpdateFailed") + updateCondition(adb, err) + + l.Error(finalError, "UpdateFailed") return emptyResult, nil + } +} + +const CONDITION_TYPE_COMPLETE = "Complete" +const CONDITION_REASON_COMPLETE = "ReconcileComplete" + +func updateCondition(adb *dbv1alpha1.AutonomousDatabase, err error) { + var condition metav1.Condition + + errMsg := func() string { + if err != nil { + return err.Error() + } + return "no reconcile errors" + }() + + // If error occurs, ReconcileComplete will be marked as true and the error message will still be listed + // If the ADB lifecycleState is intermediate, then ReconcileComplete will be marked as false + if err != nil { + condition = metav1.Condition{ + Type: CONDITION_TYPE_COMPLETE, + LastTransitionTime: metav1.Now(), + ObservedGeneration: adb.GetGeneration(), + Reason: CONDITION_REASON_COMPLETE, + Message: errMsg, + Status: metav1.ConditionTrue, + } + } else if dbv1alpha1.IsADBIntermediateState(adb.Status.LifecycleState) { + condition = metav1.Condition{ + Type: CONDITION_TYPE_COMPLETE, + LastTransitionTime: metav1.Now(), + ObservedGeneration: adb.GetGeneration(), + Reason: CONDITION_REASON_COMPLETE, + Message: errMsg, + Status: metav1.ConditionFalse, + } } else { - // Send event - r.Recorder.Event(adb, corev1.EventTypeWarning, "CreateFailed", issue.Error()) + condition = metav1.Condition{ + Type: CONDITION_TYPE_COMPLETE, + LastTransitionTime: metav1.Now(), + ObservedGeneration: adb.GetGeneration(), + Reason: CONDITION_REASON_COMPLETE, + Message: errMsg, + Status: metav1.ConditionTrue, + } + } - return emptyResult, issue + if len(adb.Status.Conditions) > 0 { + meta.RemoveStatusCondition(&adb.Status.Conditions, condition.Type) } + meta.SetStatusCondition(&adb.Status.Conditions, condition) } func (r *AutonomousDatabaseReconciler) validateOperation( @@ -390,7 +451,7 @@ func (r *AutonomousDatabaseReconciler) validateOperation( adb *dbv1alpha1.AutonomousDatabase, ociADB *dbv1alpha1.AutonomousDatabase) (exit bool, result ctrl.Result, err error) { - lastSpec, err := adb.GetLastSuccessfulSpec() + lastSucSpec, err := adb.GetLastSuccessfulSpec() if err != nil { return false, emptyResult, err } @@ -398,7 +459,7 @@ func (r *AutonomousDatabaseReconciler) validateOperation( l := logger.WithName("validateOperation") // If lastSucSpec is nil, then it's CREATE or BIND opertaion - if lastSpec == nil { + if lastSucSpec == nil { if adb.Spec.Details.AutonomousDatabaseOCID == nil { l.Info("Create operation") err := r.createADB(logger, adb) @@ -436,7 +497,7 @@ func (r *AutonomousDatabaseReconciler) validateOperation( // the user updates the spec (UPDATE operation), otherwise it's a SYNC operation. lastDifADB := adb.DeepCopy() - lastDetailsChanged, err := lastDifADB.RemoveUnchangedDetails(*lastSpec) + lastDetailsChanged, err := lastDifADB.RemoveUnchangedDetails(*lastSucSpec) if err != nil { return false, emptyResult, err } @@ -458,8 +519,6 @@ func (r *AutonomousDatabaseReconciler) validateOperation( } else { l.Info("No operation specified; sync the resource") - testOldADB := adb.DeepCopy() - // The user doesn't change the spec and the controller should pull the spec from the OCI. specChanged, err := r.getADB(logger, adb) if err != nil { @@ -470,12 +529,12 @@ func (r *AutonomousDatabaseReconciler) validateOperation( l.Info("The local spec doesn't match the oci's spec; update the CR") // Erase the status.lifecycleState temporarily to avoid the webhook error. - oldADB := adb.DeepCopy() + tmpADB := adb.DeepCopy() adb.Status.LifecycleState = "" - r.KubeClient.Status().Update(context.TODO(), adb) - adb.Spec = oldADB.Spec - - adb.DeepCopy().RemoveUnchangedDetails(testOldADB.Spec) + if err := r.KubeClient.Status().Update(context.TODO(), adb); err != nil { + return false, emptyResult, err + } + adb.Spec = tmpADB.Spec if err := r.updateCR(adb); err != nil { return false, emptyResult, err @@ -496,7 +555,7 @@ func (r *AutonomousDatabaseReconciler) validateCleanup(logger logr.Logger, adb * return false, nil } - if controllerutil.ContainsFinalizer(adb, dbv1alpha1.ADBFinalizer) { + if controllerutil.ContainsFinalizer(adb, dbv1alpha1.ADB_FINALIZER) { if adb.Status.LifecycleState == database.AutonomousDatabaseLifecycleStateTerminating { // Delete in progress, continue with the reconcile logic return false, nil @@ -506,7 +565,7 @@ func (r *AutonomousDatabaseReconciler) validateCleanup(logger logr.Logger, adb * // The adb has been deleted. Remove the finalizer and exit the reconcile. // Once all finalizers have been removed, the object will be deleted. l.Info("Resource is in TERMINATED state; remove the finalizer") - if err := k8s.RemoveFinalizerAndPatch(r.KubeClient, adb, dbv1alpha1.ADBFinalizer); err != nil { + if err := k8s.RemoveFinalizerAndPatch(r.KubeClient, adb, dbv1alpha1.ADB_FINALIZER); err != nil { return false, err } return true, nil @@ -515,7 +574,7 @@ func (r *AutonomousDatabaseReconciler) validateCleanup(logger logr.Logger, adb * if adb.Spec.Details.AutonomousDatabaseOCID == nil { l.Info("Missing AutonomousDatabaseOCID to terminate Autonomous Database; remove the finalizer anyway", "Name", adb.Name, "Namespace", adb.Namespace) // Remove finalizer anyway. - if err := k8s.RemoveFinalizerAndPatch(r.KubeClient, adb, dbv1alpha1.ADBFinalizer); err != nil { + if err := k8s.RemoveFinalizerAndPatch(r.KubeClient, adb, dbv1alpha1.ADB_FINALIZER); err != nil { return false, err } return true, nil @@ -547,18 +606,18 @@ func (r *AutonomousDatabaseReconciler) validateFinalizer(logger logr.Logger, adb // Delete is not schduled. Update the finalizer for this CR if hardLink is present var finalizerChanged = false if adb.Spec.HardLink != nil { - if *adb.Spec.HardLink && !controllerutil.ContainsFinalizer(adb, dbv1alpha1.ADBFinalizer) { + if *adb.Spec.HardLink && !controllerutil.ContainsFinalizer(adb, dbv1alpha1.ADB_FINALIZER) { l.Info("Finalizer added") - if err := k8s.AddFinalizerAndPatch(r.KubeClient, adb, dbv1alpha1.ADBFinalizer); err != nil { + if err := k8s.AddFinalizerAndPatch(r.KubeClient, adb, dbv1alpha1.ADB_FINALIZER); err != nil { return false, err } finalizerChanged = true - } else if !*adb.Spec.HardLink && controllerutil.ContainsFinalizer(adb, dbv1alpha1.ADBFinalizer) { + } else if !*adb.Spec.HardLink && controllerutil.ContainsFinalizer(adb, dbv1alpha1.ADB_FINALIZER) { l.Info("Finalizer removed") - if err := k8s.RemoveFinalizerAndPatch(r.KubeClient, adb, dbv1alpha1.ADBFinalizer); err != nil { + if err := k8s.RemoveFinalizerAndPatch(r.KubeClient, adb, dbv1alpha1.ADB_FINALIZER); err != nil { return false, err } @@ -580,7 +639,9 @@ func (r *AutonomousDatabaseReconciler) validateFinalizer(logger logr.Logger, adb // updateCR updates the lastSucSpec and the CR func (r *AutonomousDatabaseReconciler) updateCR(adb *dbv1alpha1.AutonomousDatabase) error { // Update the lastSucSpec - if err := adb.UpdateLastSuccessfulSpec(); err != nil { + // Should patch the lastSuccessfulSpec first, otherwise, the update event will be + // filtered out by predicate since the lastSuccessfulSpec is changed. + if err := r.patchLastSuccessfulSpec(adb); err != nil { return err } @@ -933,22 +994,24 @@ func (r *AutonomousDatabaseReconciler) validateDesiredLifecycleState( } // The logic of updating the network access configurations is as follows: -// 1. Shared databases: -// If the network access type changes -// a. to PUBLIC: +// +// 1. Shared databases: +// If the network access type changes +// a. to PUBLIC: // was RESTRICTED: re-enable IsMTLSConnectionRequired if its not. Then set WhitelistedIps to an array with a single empty string entry. // was PRIVATE: re-enable IsMTLSConnectionRequired if its not. Then set PrivateEndpointLabel to an emtpy string. -// b. to RESTRICTED: +// b. to RESTRICTED: // was PUBLIC: set WhitelistedIps to desired IPs/CIDR blocks/VCN OCID. Configure the IsMTLSConnectionRequired settings if it is set to disabled. // was PRIVATE: re-enable IsMTLSConnectionRequired if its not. Set the type to PUBLIC first, and then configure the WhitelistedIps. Finally resume the IsMTLSConnectionRequired settings if it was, or is configured as disabled. -// c. to PRIVATE: +// c. to PRIVATE: // was PUBLIC: set subnetOCID and nsgOCIDs. Configure the IsMTLSConnectionRequired settings if it is set. // was RESTRICTED: set subnetOCID and nsgOCIDs. Configure the IsMTLSConnectionRequired settings if it is set. +// *Note: OCI requires nsgOCIDs to be an empty string rather than nil when we don't want the adb to be included in any network security group. // -// Otherwise, if the network access type remains the same, apply the network configuration, and then set the IsMTLSConnectionRequired. +// Otherwise, if the network access type remains the same, apply the network configuration, and then set the IsMTLSConnectionRequired. // -// 2. Dedicated databases: -// Apply the configs directly +// 2. Dedicated databases: +// Apply the configs directly func (r *AutonomousDatabaseReconciler) validateGeneralNetworkAccess( logger logr.Logger, adb *dbv1alpha1.AutonomousDatabase, @@ -1158,6 +1221,12 @@ func (r *AutonomousDatabaseReconciler) validateNetworkAccess( l.Info("Sending request to OCI to configure network access options") + // When the network access type is set to PRIVATE, any nil type of nsgOCIDs needs to be set to an empty string, otherwise, OCI SDK returns a 400 error + if difADB.Spec.Details.NetworkAccess.AccessType == dbv1alpha1.NetworkAccessTypePrivate && + difADB.Spec.Details.NetworkAccess.PrivateEndpoint.NsgOCIDs == nil { + difADB.Spec.Details.NetworkAccess.PrivateEndpoint.NsgOCIDs = []string{} + } + resp, err := r.dbService.UpdateNetworkAccess(*adb.Spec.Details.AutonomousDatabaseOCID, difADB) if err != nil { return false, err @@ -1213,6 +1282,8 @@ func (r *AutonomousDatabaseReconciler) validateWallet(logger logr.Logger, adb *d return err } + adb.Status.WalletExpiringDate = oci.WalletExpiringDate(data) + label := map[string]string{"app": adb.GetName()} if err := k8s.CreateSecret(r.KubeClient, adb.Namespace, walletName, data, adb, label); err != nil { diff --git a/controllers/database/cdb_controller.go b/controllers/database/cdb_controller.go index 50778ccd..5e6c0aca 100644 --- a/controllers/database/cdb_controller.go +++ b/controllers/database/cdb_controller.go @@ -41,6 +41,7 @@ package controllers import ( "context" "errors" + //"fmt" "strconv" "strings" @@ -220,9 +221,11 @@ func (r *CDBReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R return requeueN, nil } -/********************************************************** - * Create a ReplicaSet for pods based on the ORDS container - /********************************************************/ +/* +********************************************************* + - Create a ReplicaSet for pods based on the ORDS container + /******************************************************* +*/ func (r *CDBReconciler) createORDSInstances(ctx context.Context, req ctrl.Request, cdb *dbapi.CDB) error { log := r.Log.WithValues("createORDSInstances", req.NamespacedName) @@ -251,9 +254,11 @@ func (r *CDBReconciler) createORDSInstances(ctx context.Context, req ctrl.Reques return nil } -/************************************************* - * Validate ORDS Pod. Check if there are any errors - /************************************************/ +/* +************************************************ + - Validate ORDS Pod. Check if there are any errors + /*********************************************** +*/ func (r *CDBReconciler) validateORDSPods(ctx context.Context, req ctrl.Request, cdb *dbapi.CDB) error { log := r.Log.WithValues("validateORDSPod", req.NamespacedName) @@ -277,7 +282,8 @@ func (r *CDBReconciler) validateORDSPods(ctx context.Context, req ctrl.Request, return errors.New("Waiting for ORDS pods to start") } - getORDSStatus := " curl -sSkv -k -X GET https://localhost:" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/stable/metadata-catalog/ || curl -sSkv -X GET http://localhost:" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/stable/metadata-catalog/ " + /* /opt/oracle/ords/secrets/$TLSKEY /opt/oracle/ords/secrets/$TLSCRT */ + getORDSStatus := " curl --cert /opt/oracle/ords/secrets/tls.crt --key /opt/oracle/ords/secrets/tls.key -sSkv -k -X GET https://localhost:" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/stable/metadata-catalog/ || curl --cert /opt/oracle/ords/secrets/tls.crt --key /opt/oracle/ords/secrets/tls.key -sSkv -X GET http://localhost:" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/stable/metadata-catalog/ " readyPods := 0 for _, pod := range podList.Items { if pod.Status.Phase == corev1.PodRunning { @@ -311,9 +317,12 @@ func (r *CDBReconciler) validateORDSPods(ctx context.Context, req ctrl.Request, return nil } -/************************ - * Create Pod spec -/************************/ +/* +*********************** + - Create Pod spec + +/*********************** +*/ func (r *CDBReconciler) createPodSpec(cdb *dbapi.CDB) corev1.PodSpec { podSpec := corev1.PodSpec{ @@ -531,9 +540,12 @@ func (r *CDBReconciler) createPodSpec(cdb *dbapi.CDB) corev1.PodSpec { return podSpec } -/************************ - * Create ReplicaSet spec -/************************/ +/* +*********************** + - Create ReplicaSet spec + +/*********************** +*/ func (r *CDBReconciler) createReplicaSetSpec(cdb *dbapi.CDB) *appsv1.ReplicaSet { replicas := int32(cdb.Spec.Replicas) @@ -570,9 +582,11 @@ func (r *CDBReconciler) createReplicaSetSpec(cdb *dbapi.CDB) *appsv1.ReplicaSet return replicaSet } -/********************************************************** - * Evaluate change in Spec post creation and instantiation - /********************************************************/ +/* +********************************************************* + - Evaluate change in Spec post creation and instantiation + /******************************************************* +*/ func (r *CDBReconciler) deleteReplicaSet(ctx context.Context, req ctrl.Request, cdb *dbapi.CDB) error { log := r.Log.WithValues("deleteReplicaSet", req.NamespacedName) @@ -596,9 +610,11 @@ func (r *CDBReconciler) deleteReplicaSet(ctx context.Context, req ctrl.Request, return nil } -/********************************************************** - * Evaluate change in Spec post creation and instantiation - /********************************************************/ +/* +********************************************************* + - Evaluate change in Spec post creation and instantiation + /******************************************************* +*/ func (r *CDBReconciler) evaluateSpecChange(ctx context.Context, req ctrl.Request, cdb *dbapi.CDB) error { log := r.Log.WithValues("evaluateSpecChange", req.NamespacedName) @@ -673,9 +689,11 @@ func (r *CDBReconciler) evaluateSpecChange(ctx context.Context, req ctrl.Request return nil } -/************************************************* - * Create a Cluster Service for ORDS CDB Pod - /************************************************/ +/* +************************************************ + - Create a Cluster Service for ORDS CDB Pod + /*********************************************** +*/ func (r *CDBReconciler) createORDSSVC(ctx context.Context, req ctrl.Request, cdb *dbapi.CDB) error { log := r.Log.WithValues("createORDSSVC", req.NamespacedName) @@ -701,9 +719,11 @@ func (r *CDBReconciler) createORDSSVC(ctx context.Context, req ctrl.Request, cdb return nil } -/************************ - * Create Service spec - /************************/ +/* +*********************** + - Create Service spec + /*********************** +*/ func (r *CDBReconciler) createSvcSpec(cdb *dbapi.CDB) *corev1.Service { svc := &corev1.Service{ @@ -726,9 +746,11 @@ func (r *CDBReconciler) createSvcSpec(cdb *dbapi.CDB) *corev1.Service { return svc } -/************************************************* - * Check CDB deletion - /************************************************/ +/* +************************************************ + - Check CDB deletion + /*********************************************** +*/ func (r *CDBReconciler) manageCDBDeletion(ctx context.Context, req ctrl.Request, cdb *dbapi.CDB) error { log := r.Log.WithValues("manageCDBDeletion", req.NamespacedName) @@ -781,9 +803,12 @@ func (r *CDBReconciler) manageCDBDeletion(ctx context.Context, req ctrl.Request, return nil } -/************************************************* - * Delete CDB Resource -/************************************************/ +/* +************************************************ + - Delete CDB Resource + +/*********************************************** +*/ func (r *CDBReconciler) deleteCDBInstance(ctx context.Context, req ctrl.Request, cdb *dbapi.CDB) error { log := r.Log.WithValues("deleteCDBInstance", req.NamespacedName) @@ -824,9 +849,11 @@ func (r *CDBReconciler) deleteCDBInstance(ctx context.Context, req ctrl.Request, return nil } -/************************************************* - * Get Secret Key for a Secret Name - /************************************************/ +/* +************************************************ + - Get Secret Key for a Secret Name + /*********************************************** +*/ func (r *CDBReconciler) verifySecrets(ctx context.Context, req ctrl.Request, cdb *dbapi.CDB) error { log := r.Log.WithValues("verifySecrets", req.NamespacedName) @@ -855,9 +882,11 @@ func (r *CDBReconciler) verifySecrets(ctx context.Context, req ctrl.Request, cdb return nil } -/************************************************* - * Get Secret Key for a Secret Name - /************************************************/ +/* +************************************************ + - Get Secret Key for a Secret Name + /*********************************************** +*/ func (r *CDBReconciler) checkSecret(ctx context.Context, req ctrl.Request, cdb *dbapi.CDB, secretName string) error { log := r.Log.WithValues("checkSecret", req.NamespacedName) @@ -877,9 +906,11 @@ func (r *CDBReconciler) checkSecret(ctx context.Context, req ctrl.Request, cdb * return nil } -/************************************************* - * Delete Secrets - /************************************************/ +/* +************************************************ + - Delete Secrets + /*********************************************** +*/ func (r *CDBReconciler) deleteSecrets(ctx context.Context, req ctrl.Request, cdb *dbapi.CDB) { log := r.Log.WithValues("deleteSecrets", req.NamespacedName) @@ -935,9 +966,11 @@ func (r *CDBReconciler) deleteSecrets(ctx context.Context, req ctrl.Request, cdb } } -/************************************************************** - * SetupWithManager sets up the controller with the Manager. - /*************************************************************/ +/* +************************************************************* + - SetupWithManager sets up the controller with the Manager. + /************************************************************ +*/ func (r *CDBReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&dbapi.CDB{}). diff --git a/controllers/database/dataguardbroker_controller.go b/controllers/database/dataguardbroker_controller.go index 183a1445..9faaefd2 100644 --- a/controllers/database/dataguardbroker_controller.go +++ b/controllers/database/dataguardbroker_controller.go @@ -76,7 +76,8 @@ const dataguardBrokerFinalizer = "database.oracle.com/dataguardbrokerfinalizer" //+kubebuilder:rbac:groups=database.oracle.com,resources=dataguardbrokers,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=database.oracle.com,resources=dataguardbrokers/status,verbs=get;update;patch //+kubebuilder:rbac:groups=database.oracle.com,resources=dataguardbrokers/finalizers,verbs=update -//+kubebuilder:rbac:groups="",resources=pods;pods/log;pods/exec;persistentvolumeclaims;services;nodes;events,verbs=create;delete;get;list;patch;update;watch +//+kubebuilder:rbac:groups="",resources=pods;pods/log;pods/exec;persistentvolumeclaims;services,verbs=create;delete;get;list;patch;update;watch +//+kubebuilder:rbac:groups="",resources=events,verbs=create;patch // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. @@ -397,18 +398,18 @@ func (r *DataguardBrokerReconciler) setupDataguardBrokerConfiguration(m *dbapi.D log.Error(err, err.Error()) return requeueY } - _, ok := dbSet[standbyDatabase.Status.Sid] - if ok { - log.Info("A database with the same SID is already configured in the DG") - r.Recorder.Eventf(m, corev1.EventTypeWarning, "Spec Error", "A database with the same SID "+standbyDatabase.Status.Sid+" is already configured in the DG") - continue - } // Check if dataguard broker is already configured for the standby database if standbyDatabase.Status.DgBrokerConfigured { log.Info("Dataguard broker for standbyDatabase : " + standbyDatabase.Name + " is already configured") continue } + _, ok := dbSet[standbyDatabase.Status.Sid] + if ok { + log.Info("A database with the same SID is already configured in the DG") + r.Recorder.Eventf(m, corev1.EventTypeWarning, "Spec Error", "A database with the same SID "+standbyDatabase.Status.Sid+" is already configured in the DG") + continue + } m.Status.Status = dbcommons.StatusCreating r.Status().Update(ctx, m) @@ -834,6 +835,22 @@ func (r *DataguardBrokerReconciler) SetAsPrimaryDatabase(sidbSid string, targetS return requeueY } + dbInDgConfig := false + for i := 0; i < len(databases); i++ { + splitstr := strings.Split(databases[i], ":") + if strings.ToUpper(splitstr[0]) == strings.ToUpper(targetSid) { + dbInDgConfig = true + break + } + } + + if !dbInDgConfig { + eventReason := "Cannot Switchover" + eventMsg := fmt.Sprintf("Database %s not a part of the dataguard configuration", targetSid) + r.Recorder.Eventf(m, corev1.EventTypeWarning, eventReason, eventMsg) + return requeueN + } + // Fetch the current Primary database primarySid := dbcommons.GetPrimaryDatabase(databases) if strings.EqualFold(primarySid, targetSid) { @@ -961,7 +978,7 @@ func (r *DataguardBrokerReconciler) SetAsPrimaryDatabase(sidbSid string, targetS if err != nil { return requeueN } - out, err := dbcommons.GetDatabaseRole(primaryReadyPod, r, r.Config, ctx, primaryReq, n.Spec.Edition) + out, err := dbcommons.GetDatabaseRole(primaryReadyPod, r, r.Config, ctx, primaryReq) if err == nil { standbyDatabase.Status.Role = strings.ToUpper(out) } @@ -974,7 +991,7 @@ func (r *DataguardBrokerReconciler) SetAsPrimaryDatabase(sidbSid string, targetS Name: n.Name, }, } - out, err := dbcommons.GetDatabaseRole(sidbReadyPod, r, r.Config, ctx, sidbReq, n.Spec.Edition) + out, err := dbcommons.GetDatabaseRole(sidbReadyPod, r, r.Config, ctx, sidbReq) if err == nil { n.Status.Role = strings.ToUpper(out) } @@ -989,7 +1006,7 @@ func (r *DataguardBrokerReconciler) SetAsPrimaryDatabase(sidbSid string, targetS if err != nil { return requeueN } - out, err := dbcommons.GetDatabaseRole(targetReadyPod, r, r.Config, ctx, targetReq, n.Spec.Edition) + out, err := dbcommons.GetDatabaseRole(targetReadyPod, r, r.Config, ctx, targetReq) if err == nil { standbyDatabase.Status.Role = strings.ToUpper(out) } @@ -1002,7 +1019,7 @@ func (r *DataguardBrokerReconciler) SetAsPrimaryDatabase(sidbSid string, targetS Name: n.Name, }, } - out, err := dbcommons.GetDatabaseRole(sidbReadyPod, r, r.Config, ctx, sidbReq, n.Spec.Edition) + out, err := dbcommons.GetDatabaseRole(sidbReadyPod, r, r.Config, ctx, sidbReq) if err == nil { n.Status.Role = strings.ToUpper(out) } @@ -1125,20 +1142,6 @@ func (r *DataguardBrokerReconciler) cleanupDataguardBroker(req ctrl.Request, ctx return result, nil } - // Get its Role - out, err := dbcommons.GetDatabaseRole(sidbReadyPod, r, r.Config, ctx, req, singleInstanceDatabase.Spec.Edition) - if err != nil { - log.Error(err, err.Error()) - return requeueY, err - } - // check if its PRIMARY database - if strings.ToUpper(out) != "PRIMARY" { - eventReason := "Deletion" - eventMsg := "DataGuard Broker cannot be deleted since primaryDatabaseRef is not in PRIMARY role" - r.Recorder.Eventf(m, corev1.EventTypeWarning, eventReason, eventMsg) - return requeueY, errors.New(eventMsg) - } - // Get Primary database to remove dataguard configuration _, _, err = dbcommons.GetDatabasesInDgConfig(sidbReadyPod, r, r.Config, ctx, req) if err != nil { @@ -1148,7 +1151,7 @@ func (r *DataguardBrokerReconciler) cleanupDataguardBroker(req ctrl.Request, ctx //primarySid := dbcommons.GetPrimaryDatabase(databases) - out, err = dbcommons.ExecCommand(r, r.Config, sidbReadyPod.Name, sidbReadyPod.Namespace, "", ctx, req, false, "bash", "-c", + out, err := dbcommons.ExecCommand(r, r.Config, sidbReadyPod.Name, sidbReadyPod.Namespace, "", ctx, req, false, "bash", "-c", fmt.Sprintf("echo -e \"%s\" | dgmgrl / as sysdba ", dbcommons.RemoveDataguardConfiguration)) if err != nil { log.Error(err, err.Error()) diff --git a/controllers/database/oraclerestdataservice_controller.go b/controllers/database/oraclerestdataservice_controller.go index 1a3359f7..783ae70c 100644 --- a/controllers/database/oraclerestdataservice_controller.go +++ b/controllers/database/oraclerestdataservice_controller.go @@ -80,7 +80,8 @@ type OracleRestDataServiceReconciler struct { //+kubebuilder:rbac:groups=database.oracle.com,resources=oraclerestdataservices,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=database.oracle.com,resources=oraclerestdataservices/status,verbs=get;update;patch //+kubebuilder:rbac:groups=database.oracle.com,resources=oraclerestdataservices/finalizers,verbs=update -//+kubebuilder:rbac:groups="",resources=pods;pods/log;pods/exec;persistentvolumeclaims;services;nodes;events,verbs=create;delete;get;list;patch;update;watch +//+kubebuilder:rbac:groups="",resources=pods;pods/log;pods/exec;persistentvolumeclaims;services,verbs=create;delete;get;list;patch;update;watch +//+kubebuilder:rbac:groups="",resources=events,verbs=create;patch // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. @@ -785,7 +786,7 @@ func (r *OracleRestDataServiceReconciler) instantiatePVCSpec(m *dbapi.OracleRest accessMode = append(accessMode, corev1.PersistentVolumeAccessMode(m.Spec.Persistence.AccessMode)) return accessMode }(), - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: map[corev1.ResourceName]resource.Quantity{ // Requests describes the minimum amount of compute resources required "storage": resource.MustParse(m.Spec.Persistence.Size), diff --git a/controllers/database/pdb_controller.go b/controllers/database/pdb_controller.go index 735deaf7..4f12ca31 100644 --- a/controllers/database/pdb_controller.go +++ b/controllers/database/pdb_controller.go @@ -44,6 +44,7 @@ import ( "crypto/tls" "crypto/x509" "encoding/json" + //"encoding/pem" "errors" "fmt" @@ -59,6 +60,7 @@ import ( "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" + //metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/types" @@ -119,15 +121,27 @@ var ( ) const PDBFinalizer = "database.oracle.com/PDBfinalizer" +const ONE = 1 +const ZERO = 0 var tdePassword string var tdeSecret string var floodcontrol bool = false +var assertivePdbDeletion bool = false /* Global variable for assertive pdb deletion */ //+kubebuilder:rbac:groups=database.oracle.com,resources=pdbs,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=database.oracle.com,resources=pdbs/status,verbs=get;update;patch //+kubebuilder:rbac:groups=database.oracle.com,resources=pdbs/finalizers,verbs=get;create;update;patch;delete +// +kubebuilder:rbac:groups=core,resources=pods;pods/log;pods/exec;secrets;containers;services;events;configmaps;namespaces,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=core,resources=pods/exec,verbs=create +// +kubebuilder:rbac:groups=apps,resources=statefulsets,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups='',resources=statefulsets/finalizers,verbs=get;list;watch;create;update;patch;delete + +<<<<<<< HEAD + +======= +>>>>>>> gitlab-origin/master // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. // TODO(user): Modify the Reconcile function to compare the state specified by @@ -137,6 +151,7 @@ var floodcontrol bool = false // // For more details, check Reconcile and its Result here: // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.9.2/pkg/reconcile + func (r *PDBReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := r.Log.WithValues("multitenantoperator", req.NamespacedName) log.Info("Reconcile requested") @@ -176,9 +191,9 @@ func (r *PDBReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R } // Finalizer section - err = r.managePDBDeletion(ctx, req, pdb) + err = r.managePDBDeletion2(ctx, req, pdb) if err != nil { - log.Info("Reconcile queued") + log.Info("managePDBDeletion2 Error Deleting resource ") return requeueY, nil } @@ -249,9 +264,11 @@ func (r *PDBReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R return requeueY, nil } -/************************************************* - * Validate the PDB Spec - /************************************************/ +/* +************************************************ + - Validate the PDB Spec + /*********************************************** +*/ func (r *PDBReconciler) validatePhase(ctx context.Context, req ctrl.Request, pdb *dbapi.PDB) { log := r.Log.WithValues("validatePhase", req.NamespacedName) @@ -282,28 +299,27 @@ func (r *PDBReconciler) validatePhase(ctx context.Context, req ctrl.Request, pdb log.Info("Validation complete") } -/**************************************************************** - * Check for Duplicate PDB. Same PDB name on the same CDB resource. - /***************************************************************/ +/* +*************************************************************** + - Check for Duplicate PDB. Same PDB name on the same CDB resource. + /************************************************************** +*/ func (r *PDBReconciler) checkDuplicatePDB(ctx context.Context, req ctrl.Request, pdb *dbapi.PDB) error { - log := r.Log.WithValues("checkDuplicatePDB", req.NamespacedName) - // Name of the CDB CR that holds the ORDS container cdbResName := pdb.Spec.CDBResName - //cdbame := pdb.Spec.CDBName - // Name of the PDB resource + log := r.Log.WithValues("checkDuplicatePDB", pdb.Spec.CDBNamespace) pdbResName := pdb.Spec.PDBName pdbList := &dbapi.PDBList{} - listOpts := []client.ListOption{client.InNamespace(req.Namespace), client.MatchingFields{"spec.pdbName": pdbResName}} + listOpts := []client.ListOption{client.InNamespace(pdb.Spec.CDBNamespace), client.MatchingFields{"spec.pdbName": pdbResName}} // List retrieves list of objects for a given namespace and list options. err := r.List(ctx, pdbList, listOpts...) if err != nil { - log.Info("Failed to list pdbs", "Namespace", req.Namespace, "Error", err) + log.Info("Failed to list pdbs", "Namespace", pdb.Spec.CDBNamespace, "Error", err) return err } @@ -325,9 +341,11 @@ func (r *PDBReconciler) checkDuplicatePDB(ctx context.Context, req ctrl.Request, return nil } -/**************************************************************** - * Get the Custom Resource for the CDB mentioned in the PDB Spec - /***************************************************************/ +/* +*************************************************************** + - Get the Custom Resource for the CDB mentioned in the PDB Spec + /************************************************************** +*/ func (r *PDBReconciler) getCDBResource(ctx context.Context, req ctrl.Request, pdb *dbapi.PDB) (dbapi.CDB, error) { log := r.Log.WithValues("getCDBResource", req.NamespacedName) @@ -336,15 +354,16 @@ func (r *PDBReconciler) getCDBResource(ctx context.Context, req ctrl.Request, pd // Name of the CDB CR that holds the ORDS container cdbResName := pdb.Spec.CDBResName + cdbNamespace := pdb.Spec.CDBNamespace // Get CDB CR corresponding to the CDB name specified in the PDB spec err := r.Get(context.Background(), client.ObjectKey{ - Namespace: req.Namespace, + Namespace: cdbNamespace, Name: cdbResName, }, &cdb) if err != nil { - log.Info("Failed to get CRD for CDB", "Name", cdbResName, "Namespace", req.Namespace, "Error", err.Error()) + log.Info("Failed to get CRD for CDB", "Name", cdbResName, "Namespace", pdb.Spec.CDBNamespace, "Error", err.Error()) pdb.Status.Msg = "Unable to get CRD for CDB : " + cdbResName r.Status().Update(ctx, pdb) return cdb, err @@ -354,9 +373,11 @@ func (r *PDBReconciler) getCDBResource(ctx context.Context, req ctrl.Request, pd return cdb, nil } -/**************************************************************** - * Get the ORDS Pod for the CDB mentioned in the PDB Spec - /***************************************************************/ +/* +*************************************************************** + - Get the ORDS Pod for the CDB mentioned in the PDB Spec + /************************************************************** +*/ func (r *PDBReconciler) getORDSPod(ctx context.Context, req ctrl.Request, pdb *dbapi.PDB) (corev1.Pod, error) { log := r.Log.WithValues("getORDSPod", req.NamespacedName) @@ -368,12 +389,12 @@ func (r *PDBReconciler) getORDSPod(ctx context.Context, req ctrl.Request, pdb *d // Get ORDS Pod associated with the CDB Name specified in the PDB Spec err := r.Get(context.Background(), client.ObjectKey{ - Namespace: req.Namespace, + Namespace: pdb.Spec.CDBNamespace, Name: cdbResName + "-ords", }, &cdbPod) if err != nil { - log.Info("Failed to get Pod for CDB", "Name", cdbResName, "Namespace", req.Namespace, "Error", err.Error()) + log.Info("Failed to get Pod for CDB", "Name", cdbResName, "Namespace", pdb.Spec.CDBNamespace, "Error", err.Error()) pdb.Status.Msg = "Unable to get ORDS Pod for CDB : " + cdbResName return cdbPod, err } @@ -382,9 +403,11 @@ func (r *PDBReconciler) getORDSPod(ctx context.Context, req ctrl.Request, pdb *d return cdbPod, nil } -/************************************************* - * Get Secret Key for a Secret Name - /************************************************/ +/* +************************************************ + - Get Secret Key for a Secret Name + /*********************************************** +*/ func (r *PDBReconciler) getSecret(ctx context.Context, req ctrl.Request, pdb *dbapi.PDB, secretName string, keyName string) (string, error) { log := r.Log.WithValues("getSecret", req.NamespacedName) @@ -404,9 +427,11 @@ func (r *PDBReconciler) getSecret(ctx context.Context, req ctrl.Request, pdb *db return string(secret.Data[keyName]), nil } -/************************************************* - * Issue a REST API Call to the ORDS container - /************************************************/ +/* +************************************************ + - Issue a REST API Call to the ORDS container + /*********************************************** +*/ func (r *PDBReconciler) callAPI(ctx context.Context, req ctrl.Request, pdb *dbapi.PDB, url string, payload map[string]string, action string) (string, error) { log := r.Log.WithValues("callAPI", req.NamespacedName) @@ -474,37 +499,37 @@ func (r *PDBReconciler) callAPI(ctx context.Context, req ctrl.Request, pdb *dbap log.Info("Issuing REST call", "URL", url, "Action", action) - cdb, err := r.getCDBResource(ctx, req, pdb) - if err != nil { - return "", err - } + /* + cdb, err := r.getCDBResource(ctx, req, pdb) + if err != nil { + return "", err + } + */ - // Get Web Server User - //secret := &corev1.Secret{} - err = r.Get(ctx, types.NamespacedName{Name: cdb.Spec.WebServerUser.Secret.SecretName, Namespace: cdb.Namespace}, secret) + err = r.Get(ctx, types.NamespacedName{Name: pdb.Spec.WebServerUsr.Secret.SecretName, Namespace: pdb.Namespace}, secret) if err != nil { if apierrors.IsNotFound(err) { - log.Info("Secret not found:" + cdb.Spec.WebServerUser.Secret.SecretName) + log.Info("Secret not found:" + pdb.Spec.WebServerUsr.Secret.SecretName) return "", err } log.Error(err, "Unable to get the secret.") return "", err } - webUser := string(secret.Data[cdb.Spec.WebServerUser.Secret.Key]) + + webUser := string(secret.Data[pdb.Spec.WebServerUsr.Secret.Key]) webUser = strings.TrimSpace(webUser) - // Get Web Server User Password secret = &corev1.Secret{} - err = r.Get(ctx, types.NamespacedName{Name: cdb.Spec.WebServerPwd.Secret.SecretName, Namespace: cdb.Namespace}, secret) + err = r.Get(ctx, types.NamespacedName{Name: pdb.Spec.WebServerPwd.Secret.SecretName, Namespace: pdb.Namespace}, secret) if err != nil { if apierrors.IsNotFound(err) { - log.Info("Secret not found:" + cdb.Spec.WebServerPwd.Secret.SecretName) + log.Info("Secret not found:" + pdb.Spec.WebServerPwd.Secret.SecretName) return "", err } log.Error(err, "Unable to get the secret.") return "", err } - webUserPwd := string(secret.Data[cdb.Spec.WebServerPwd.Secret.Key]) + webUserPwd := string(secret.Data[pdb.Spec.WebServerPwd.Secret.Key]) webUserPwd = strings.TrimSpace(webUserPwd) var httpreq *http.Request @@ -596,9 +621,11 @@ func (r *PDBReconciler) callAPI(ctx context.Context, req ctrl.Request, pdb *dbap return respData, nil } -/************************************************* - * Create a PDB - /************************************************/ +/* +************************************************ + - Create a PDB + /*********************************************** +*/ func (r *PDBReconciler) createPDB(ctx context.Context, req ctrl.Request, pdb *dbapi.PDB) error { log := r.Log.WithValues("createPDB", req.NamespacedName) @@ -633,6 +660,9 @@ func (r *PDBReconciler) createPDB(ctx context.Context, req ctrl.Request, pdb *db return nil } + pdbAdminName = strings.TrimSuffix(pdbAdminName, "\n") + pdbAdminPwd = strings.TrimSuffix(pdbAdminPwd, "\n") + values := map[string]string{ "method": "CREATE", "pdb_name": pdb.Spec.PDBName, @@ -662,7 +692,7 @@ func (r *PDBReconciler) createPDB(ctx context.Context, req ctrl.Request, pdb *db values["tdeSecret"] = tdeSecret } - url := "https://" + pdb.Spec.CDBResName + "-ords:" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" + url := "https://" + pdb.Spec.CDBResName + "-ords." + pdb.Spec.CDBNamespace + ":" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" pdb.Status.TotalSize = pdb.Spec.TotalSize pdb.Status.Phase = pdbPhaseCreate @@ -672,7 +702,7 @@ func (r *PDBReconciler) createPDB(ctx context.Context, req ctrl.Request, pdb *db } _, err = r.callAPI(ctx, req, pdb, url, values, "POST") if err != nil { - log.Error(err, "callAPI error", err.Error()) + log.Error(err, "callAPI error", "err", err.Error()) return err } @@ -681,19 +711,25 @@ func (r *PDBReconciler) createPDB(ctx context.Context, req ctrl.Request, pdb *db if cdb.Spec.DBServer != "" { pdb.Status.ConnString = cdb.Spec.DBServer + ":" + strconv.Itoa(cdb.Spec.DBPort) + "/" + pdb.Spec.PDBName } else { - ParseTnsAlias(&(cdb.Spec.DBTnsurl), &(pdb.Spec.PDBName)) pdb.Status.ConnString = cdb.Spec.DBTnsurl + ParseTnsAlias(&(pdb.Status.ConnString), &(pdb.Spec.PDBName)) } + assertivePdbDeletion = pdb.Spec.AssertivePdbDeletion + if pdb.Spec.AssertivePdbDeletion == true { + r.Recorder.Eventf(pdb, corev1.EventTypeNormal, "Created", "PDB '%s' assertive pdb deletion turned on", pdb.Spec.PDBName) + } log.Info("New connect strinng", "tnsurl", cdb.Spec.DBTnsurl) log.Info("Created PDB Resource", "PDB Name", pdb.Spec.PDBName) r.getPDBState(ctx, req, pdb) return nil } -/************************************************* - * Clone a PDB - /************************************************/ +/* +************************************************ + - Clone a PDB + /*********************************************** +*/ func (r *PDBReconciler) clonePDB(ctx context.Context, req ctrl.Request, pdb *dbapi.PDB) error { if pdb.Spec.PDBName == pdb.Spec.SrcPDBName { @@ -741,7 +777,9 @@ func (r *PDBReconciler) clonePDB(ctx context.Context, req ctrl.Request, pdb *dba values["tempSize"] = pdb.Spec.TempSize } - url := "https://" + pdb.Spec.CDBResName + "-ords:" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" + pdb.Spec.SrcPDBName + "/" + //url := "https://"+ pdb.Spec.CDBNamespace + "." + pdb.Spec.CDBResName + "-ords:" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" + pdb.Spec.SrcPDBName + "/" + //url := "https://" + pdb.Spec.CDBResName + "-ords:" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" + pdb.Spec.SrcPDBName + "/" + url := "https://" + pdb.Spec.CDBResName + "-ords." + pdb.Spec.CDBNamespace + ":" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" + pdb.Spec.SrcPDBName + "/" pdb.Status.Phase = pdbPhaseClone pdb.Status.Msg = "Waiting for PDB to be cloned" @@ -758,8 +796,13 @@ func (r *PDBReconciler) clonePDB(ctx context.Context, req ctrl.Request, pdb *dba if cdb.Spec.DBServer != "" { pdb.Status.ConnString = cdb.Spec.DBServer + ":" + strconv.Itoa(cdb.Spec.DBPort) + "/" + pdb.Spec.PDBName } else { - ParseTnsAlias(&(cdb.Spec.DBTnsurl), &(pdb.Spec.PDBName)) pdb.Status.ConnString = cdb.Spec.DBTnsurl + ParseTnsAlias(&(pdb.Status.ConnString), &(pdb.Spec.PDBName)) + } + + assertivePdbDeletion = pdb.Spec.AssertivePdbDeletion + if pdb.Spec.AssertivePdbDeletion == true { + r.Recorder.Eventf(pdb, corev1.EventTypeNormal, "Clone", "PDB '%s' assertive pdb deletion turned on", pdb.Spec.PDBName) } log.Info("Cloned PDB successfully", "Source PDB Name", pdb.Spec.SrcPDBName, "Clone PDB Name", pdb.Spec.PDBName) @@ -767,9 +810,11 @@ func (r *PDBReconciler) clonePDB(ctx context.Context, req ctrl.Request, pdb *dba return nil } -/************************************************* - * Plug a PDB - /************************************************/ +/* +************************************************ + - Plug a PDB + /*********************************************** +*/ func (r *PDBReconciler) plugPDB(ctx context.Context, req ctrl.Request, pdb *dbapi.PDB) error { log := r.Log.WithValues("plugPDB", req.NamespacedName) @@ -819,7 +864,7 @@ func (r *PDBReconciler) plugPDB(ctx context.Context, req ctrl.Request, pdb *dbap values["asClone"] = strconv.FormatBool(*(pdb.Spec.AsClone)) } - url := "https://" + pdb.Spec.CDBResName + "-ords:" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" + url := "https://" + pdb.Spec.CDBResName + "-ords." + pdb.Spec.CDBNamespace + ":" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" pdb.Status.TotalSize = pdb.Spec.TotalSize pdb.Status.Phase = pdbPhasePlug @@ -840,14 +885,21 @@ func (r *PDBReconciler) plugPDB(ctx context.Context, req ctrl.Request, pdb *dbap pdb.Status.ConnString = cdb.Spec.DBTnsurl } + assertivePdbDeletion = pdb.Spec.AssertivePdbDeletion + if pdb.Spec.AssertivePdbDeletion == true { + r.Recorder.Eventf(pdb, corev1.EventTypeNormal, "Plugged", "PDB '%s' assertive pdb deletion turned on", pdb.Spec.PDBName) + } + log.Info("Successfully plugged PDB", "PDB Name", pdb.Spec.PDBName) r.getPDBState(ctx, req, pdb) return nil } -/************************************************* - * Unplug a PDB - /************************************************/ +/* +************************************************ + - Unplug a PDB + /*********************************************** +*/ func (r *PDBReconciler) unplugPDB(ctx context.Context, req ctrl.Request, pdb *dbapi.PDB) error { log := r.Log.WithValues("unplugPDB", req.NamespacedName) @@ -885,7 +937,8 @@ func (r *PDBReconciler) unplugPDB(ctx context.Context, req ctrl.Request, pdb *db values["tdeExport"] = strconv.FormatBool(*(pdb.Spec.TDEExport)) } - url := "https://" + pdb.Spec.CDBResName + "-ords:" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" + pdb.Spec.PDBName + "/" + url := "https://" + pdb.Spec.CDBResName + "-ords." + pdb.Spec.CDBNamespace + ":" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" + pdb.Spec.PDBName + "/" + log.Info("CallAPI(url)", "url", url) pdb.Status.Phase = pdbPhaseUnplug @@ -894,8 +947,8 @@ func (r *PDBReconciler) unplugPDB(ctx context.Context, req ctrl.Request, pdb *db if cdb.Spec.DBServer != "" { pdb.Status.ConnString = cdb.Spec.DBServer + ":" + strconv.Itoa(cdb.Spec.DBPort) + "/" + pdb.Spec.PDBName } else { - ParseTnsAlias(&(cdb.Spec.DBTnsurl), &(pdb.Spec.PDBName)) pdb.Status.ConnString = cdb.Spec.DBTnsurl + ParseTnsAlias(&(pdb.Status.ConnString), &(pdb.Spec.PDBName)) } if err := r.Status().Update(ctx, pdb); err != nil { @@ -928,9 +981,11 @@ func (r *PDBReconciler) unplugPDB(ctx context.Context, req ctrl.Request, pdb *db return nil } -/************************************************* - * Modify a PDB state - /************************************************/ +/* +************************************************ + - Modify a PDB state + /*********************************************** +*/ func (r *PDBReconciler) modifyPDB(ctx context.Context, req ctrl.Request, pdb *dbapi.PDB) error { log := r.Log.WithValues("modifyPDB", req.NamespacedName) @@ -977,7 +1032,7 @@ func (r *PDBReconciler) modifyPDB(ctx context.Context, req ctrl.Request, pdb *db log.Info("PDB STATUS OPENMODE", "pdb.Status.OpenMode=", pdb.Status.OpenMode) pdbName := pdb.Spec.PDBName - url := "https://" + pdb.Spec.CDBResName + "-ords:" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" + pdbName + "/status" + url := "https://" + pdb.Spec.CDBResName + "-ords." + pdb.Spec.CDBNamespace + ":" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" + pdbName + "/status" pdb.Status.Phase = pdbPhaseModify pdb.Status.ModifyOption = pdb.Spec.PDBState + "-" + pdb.Spec.ModifyOption @@ -1003,9 +1058,11 @@ func (r *PDBReconciler) modifyPDB(ctx context.Context, req ctrl.Request, pdb *db return nil } -/************************************************* - * Get PDB State - /************************************************/ +/* +************************************************ + - Get PDB State + /*********************************************** +*/ func (r *PDBReconciler) getPDBState(ctx context.Context, req ctrl.Request, pdb *dbapi.PDB) error { log := r.Log.WithValues("getPDBState", req.NamespacedName) @@ -1018,7 +1075,7 @@ func (r *PDBReconciler) getPDBState(ctx context.Context, req ctrl.Request, pdb * } pdbName := pdb.Spec.PDBName - url := "https://" + pdb.Spec.CDBResName + "-ords:" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" + pdbName + "/status" + url := "https://" + pdb.Spec.CDBResName + "-ords." + pdb.Spec.CDBNamespace + ":" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" + pdbName + "/status" pdb.Status.Msg = "Getting PDB state" if err := r.Status().Update(ctx, pdb); err != nil { @@ -1052,9 +1109,11 @@ func (r *PDBReconciler) getPDBState(ctx context.Context, req ctrl.Request, pdb * return nil } -/************************************************* - * Map Database PDB to Kubernetes PDB CR - /************************************************/ +/* +************************************************ + - Map Database PDB to Kubernetes PDB CR + /*********************************************** +*/ func (r *PDBReconciler) mapPDB(ctx context.Context, req ctrl.Request, pdb *dbapi.PDB) error { log := r.Log.WithValues("mapPDB", req.NamespacedName) @@ -1067,7 +1126,7 @@ func (r *PDBReconciler) mapPDB(ctx context.Context, req ctrl.Request, pdb *dbapi } pdbName := pdb.Spec.PDBName - url := "https://" + pdb.Spec.CDBResName + "-ords:" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" + pdbName + "/" + url := "https://" + pdb.Spec.CDBResName + "-ords." + pdb.Spec.CDBNamespace + ":" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" + pdbName + "/" pdb.Status.Msg = "Mapping PDB" if err := r.Status().Update(ctx, pdb); err != nil { @@ -1086,18 +1145,21 @@ func (r *PDBReconciler) mapPDB(ctx context.Context, req ctrl.Request, pdb *dbapi log.Error(err, "Failed to get state of PDB :"+pdbName, "err", err.Error()) } - //fmt.Printf("%+v\n", objmap) totSizeInBytes := objmap["total_size"].(float64) totSizeInGB := totSizeInBytes / 1024 / 1024 / 1024 pdb.Status.OpenMode = objmap["open_mode"].(string) pdb.Status.TotalSize = fmt.Sprintf("%.2f", totSizeInGB) + "G" + assertivePdbDeletion = pdb.Spec.AssertivePdbDeletion + if pdb.Spec.AssertivePdbDeletion == true { + r.Recorder.Eventf(pdb, corev1.EventTypeNormal, "Mapped", "PDB '%s' assertive pdb deletion turned on", pdb.Spec.PDBName) + } if cdb.Spec.DBServer != "" { pdb.Status.ConnString = cdb.Spec.DBServer + ":" + strconv.Itoa(cdb.Spec.DBPort) + "/" + pdb.Spec.PDBName } else { - ParseTnsAlias(&(cdb.Spec.DBTnsurl), &(pdb.Spec.PDBName)) pdb.Status.ConnString = cdb.Spec.DBTnsurl + ParseTnsAlias(&(pdb.Status.ConnString), &(pdb.Spec.PDBName)) } if err := r.Status().Update(ctx, pdb); err != nil { @@ -1108,9 +1170,11 @@ func (r *PDBReconciler) mapPDB(ctx context.Context, req ctrl.Request, pdb *dbapi return nil } -/************************************************* - * Delete a PDB - /************************************************/ +/* +************************************************ + - Delete a PDB + /*********************************************** +*/ func (r *PDBReconciler) deletePDB(ctx context.Context, req ctrl.Request, pdb *dbapi.PDB) error { log := r.Log.WithValues("deletePDB", req.NamespacedName) @@ -1144,52 +1208,79 @@ func (r *PDBReconciler) deletePDB(ctx context.Context, req ctrl.Request, pdb *db } /************************************************* - * Check PDB deletion - /************************************************/ -func (r *PDBReconciler) managePDBDeletion(ctx context.Context, req ctrl.Request, pdb *dbapi.PDB) error { - log := r.Log.WithValues("managePDBDeletion", req.NamespacedName) - - // Check if the PDB instance is marked to be deleted, which is - // indicated by the deletion timestamp being set. - isPDBMarkedToBeDeleted := pdb.GetDeletionTimestamp() != nil - if isPDBMarkedToBeDeleted { - log.Info("Marked to be deleted") - pdb.Status.Phase = pdbPhaseDelete - pdb.Status.Status = true - r.Status().Update(ctx, pdb) + - Check PDB deletion +**************************************************/ +func (r *PDBReconciler) managePDBDeletion2(ctx context.Context, req ctrl.Request, pdb *dbapi.PDB) error { + log := r.Log.WithValues("managePDBDeletion", req.NamespacedName) + if pdb.ObjectMeta.DeletionTimestamp.IsZero() { + if !controllerutil.ContainsFinalizer(pdb, PDBFinalizer) { + controllerutil.AddFinalizer(pdb, PDBFinalizer) + if err := r.Update(ctx, pdb); err != nil { + return err + } + } + } else { + log.Info("Pdb marked to be delted") if controllerutil.ContainsFinalizer(pdb, PDBFinalizer) { - // Remove PDBFinalizer. Once all finalizers have been - // removed, the object will be deleted. - log.Info("Removing finalizer") + if assertivePdbDeletion == true { + log.Info("Deleting pdb CRD: Assertive approach is turned on ") + cdb, err := r.getCDBResource(ctx, req, pdb) + if err != nil { + log.Error(err, "Cannont find cdb resource ", "err", err.Error()) + return err + } + + pdbName := pdb.Spec.PDBName + if pdb.Status.OpenMode == "READ WRITE" { + valuesclose := map[string]string{ + "state": "CLOSE", + "modifyOption": "IMMEDIATE", + "getScript": "FALSE"} + url := "https://" + pdb.Spec.CDBResName + "-ords." + pdb.Spec.CDBNamespace + ":" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" + pdbName + "/status" + _, errclose := r.callAPI(ctx, req, pdb, url, valuesclose, "POST") + if errclose != nil { + log.Info("Warning error closing pdb continue anyway") + } + } + + valuesdrop := map[string]string{ + "action": "INCLUDING", + "getScript": "FALSE"} + url := "https://" + pdb.Spec.CDBResName + "-ords." + pdb.Spec.CDBNamespace + ":" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" + pdbName + "/" + + log.Info("Call Delete()") + _, errdelete := r.callAPI(ctx, req, pdb, url, valuesdrop, "DELETE") + if errdelete != nil { + log.Error(errdelete, "Fail to delete pdb :"+pdb.Name, "err", err.Error()) + return errdelete + } + } /* END OF ASSERTIVE SECTION */ + + log.Info("Marked to be deleted") + pdb.Status.Phase = pdbPhaseDelete + pdb.Status.Status = true + r.Status().Update(ctx, pdb) + controllerutil.RemoveFinalizer(pdb, PDBFinalizer) - err := r.Update(ctx, pdb) - if err != nil { - log.Info("Could not remove finalizer", "err", err.Error()) + if err := r.Update(ctx, pdb); err != nil { + log.Info("Cannot remove finalizer") return err } - log.Info("Successfully removed PDB resource") - return nil - } - } - // Add finalizer for this CR - if !controllerutil.ContainsFinalizer(pdb, PDBFinalizer) { - log.Info("Adding finalizer") - controllerutil.AddFinalizer(pdb, PDBFinalizer) - err := r.Update(ctx, pdb) - if err != nil { - log.Info("Could not add finalizer", "err", err.Error()) - return err } - pdb.Status.Status = false + + return nil } + return nil } -/************************************************* - * Finalization logic for PDBFinalizer - /************************************************/ +/* +************************************************ + - Finalization logic for PDBFinalizer + /*********************************************** +*/ func (r *PDBReconciler) deletePDBInstance(req ctrl.Request, ctx context.Context, pdb *dbapi.PDB) error { log := r.Log.WithValues("deletePDBInstance", req.NamespacedName) @@ -1210,7 +1301,7 @@ func (r *PDBReconciler) deletePDBInstance(req ctrl.Request, ctx context.Context, } pdbName := pdb.Spec.PDBName - url := "https://" + pdb.Spec.CDBResName + "-ords:" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" + pdbName + "/" + url := "https://" + pdb.Spec.CDBResName + "-ords." + pdb.Spec.CDBNamespace + ":" + strconv.Itoa(cdb.Spec.ORDSPort) + "/ords/_/db-api/latest/database/pdbs/" + pdbName + "/" pdb.Status.Phase = pdbPhaseDelete pdb.Status.Msg = "Waiting for PDB to be deleted" @@ -1227,9 +1318,11 @@ func (r *PDBReconciler) deletePDBInstance(req ctrl.Request, ctx context.Context, return nil } -/************************************************************** - * SetupWithManager sets up the controller with the Manager. - /*************************************************************/ +/* +************************************************************* + - SetupWithManager sets up the controller with the Manager. + /************************************************************ +*/ func (r *PDBReconciler) SetupWithManager(mgr ctrl.Manager) error { return ctrl.NewControllerManagedBy(mgr). For(&dbapi.PDB{}). @@ -1253,6 +1346,7 @@ Enh 35357707 - PROVIDE THE PDB TNSALIAS INFORMATION **************************************************************/ func ParseTnsAlias(tns *string, pdbsrv *string) { + var swaptns string fmt.Printf("Analyzing string [%s]\n", *tns) fmt.Printf("Relacing srv [%s]\n", *pdbsrv) @@ -1266,9 +1360,9 @@ func ParseTnsAlias(tns *string, pdbsrv *string) { return } - *pdbsrv = fmt.Sprintf("SERVICE_NAME=%s", *pdbsrv) + swaptns = fmt.Sprintf("SERVICE_NAME=%s", *pdbsrv) tnsreg := regexp.MustCompile(`SERVICE_NAME=\w+`) - *tns = tnsreg.ReplaceAllString(*tns, *pdbsrv) + *tns = tnsreg.ReplaceAllString(*tns, swaptns) fmt.Printf("Newstring [%s]\n", *tns) diff --git a/controllers/database/shardingdatabase_controller.go b/controllers/database/shardingdatabase_controller.go index c76b7f45..7fcaac2b 100644 --- a/controllers/database/shardingdatabase_controller.go +++ b/controllers/database/shardingdatabase_controller.go @@ -44,6 +44,7 @@ import ( "fmt" "reflect" "strconv" + "strings" "time" "github.com/go-logr/logr" @@ -70,7 +71,7 @@ import ( shardingv1 "github.com/oracle/oracle-database-operator/commons/sharding" ) -//Sharding Topology +// Sharding Topology type ShardingTopology struct { topicid string Instance *databasev1alpha1.ShardingDatabase @@ -89,12 +90,17 @@ type ShardingDatabaseReconciler struct { kubeConfig clientcmd.ClientConfig Recorder record.EventRecorder osh []*ShardingTopology + InCluster bool + Namespace string } +var sentFailMsg = make(map[string]bool) +var sentCompleteMsg = make(map[string]bool) + // +kubebuilder:rbac:groups=database.oracle.com,resources=shardingdatabases,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=database.oracle.com,resources=shardingdatabases/status,verbs=get;update;patch // +kubebuilder:rbac:groups=database.oracle.com,resources=shardingdatabases/finalizers,verbs=get;create;update;patch;delete -// +kubebuilder:rbac:groups=core,resources=pods;pods/log;pods/exec;secrets;services;events;nodes;configmaps;persistentvolumeclaims;namespaces,verbs=get;list;watch;create;update;patch;delete +// +kubebuilder:rbac:groups=core,resources=pods;pods/log;pods/exec;secrets;containers;services;events;configmaps;persistentvolumeclaims;namespaces,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups=core,resources=pods/exec,verbs=create // +kubebuilder:rbac:groups=apps,resources=statefulsets,verbs=get;list;watch;create;update;patch;delete // +kubebuilder:rbac:groups='',resources=statefulsets/finalizers,verbs=get;list;watch;create;update;patch;delete @@ -163,6 +169,7 @@ func (r *ShardingDatabaseReconciler) Reconcile(ctx context.Context, req ctrl.Req r.osh = append(r.osh, osh) } defer r.setCrdLifeCycleState(instance, &result, &err, &stateType) + defer r.updateShardTopologyStatus(instance) // =============================== Check Deletion TimeStamp======== // Check if the ProvOShard instance is marked to be deleted, which is // // indicated by the deletion timestamp being set. @@ -184,21 +191,21 @@ func (r *ShardingDatabaseReconciler) Reconcile(ctx context.Context, req ctrl.Req if !instFlag { //r.setCrdLifeCycleState(instance, &result, &err, stateType) result = resultNq - return result, fmt.Errorf("DId not fid the instance in checkProvInstance") + return result, fmt.Errorf("DId not find the instance in checkProvInstance") } // ================================ OCI Notification Provider =========== r.getOnsConfigProvider(instance, idx) // =============================== Checking Namespace ============== - if instance.Spec.Namespace != "" { - err = shardingv1.AddNamespace(instance, r.Client, r.Log) - if err != nil { - //r.setCrdLifeCycleState(instance, &result, &err, stateType) - result = resultNq - return result, err - } - } else { + if instance.Spec.Namespace == "" { + ///err = shardingv1.AddNamespace(instance, r.Client, r.Log) + //if err != nil { + // //r.setCrdLifeCycleState(instance, &result, &err, stateType) + // result = resultNq + // return result, err + // } + // } else { instance.Spec.Namespace = "default" } @@ -283,7 +290,7 @@ func (r *ShardingDatabaseReconciler) Reconcile(ctx context.Context, req ctrl.Req // if user set replicasize greater than 1 but also set instance.Spec.OraDbPvcName then only one service will be created and one pod for i = 0; i < int32(len(instance.Spec.Shard)); i++ { OraShardSpex = instance.Spec.Shard[i] - if OraShardSpex.IsDelete != true { + if !shardingv1.CheckIsDeleteFlag(OraShardSpex.IsDelete, instance, r.Log) { result, err = r.createService(instance, shardingv1.BuildServiceDefForShard(instance, 0, OraShardSpex, "local")) if err != nil { result = resultNq @@ -303,7 +310,7 @@ func (r *ShardingDatabaseReconciler) Reconcile(ctx context.Context, req ctrl.Req if len(instance.Spec.Shard) > 0 { for i = 0; i < int32(len(instance.Spec.Shard)); i++ { OraShardSpex = instance.Spec.Shard[i] - if OraShardSpex.IsDelete != true { + if !shardingv1.CheckIsDeleteFlag(OraShardSpex.IsDelete, instance, r.Log) { result, err = r.deployStatefulSet(instance, shardingv1.BuildStatefulSetForShard(instance, OraShardSpex), "SHARD") if err != nil { result = resultNq @@ -324,6 +331,13 @@ func (r *ShardingDatabaseReconciler) Reconcile(ctx context.Context, req ctrl.Req return result, err } + err = r.checkShardState(instance) + if err != nil { + err = nilErr + result = resultQ + return result, err + } + //set the Waiting state for Reconcile loop // Loop will be requeued only if Shard Statefulset is not ready or not configured. // Till that time Reconcilation loop will remain in blocked state @@ -377,7 +391,7 @@ func (r *ShardingDatabaseReconciler) Reconcile(ctx context.Context, req ctrl.Req // ====================== Update Setup for Shard ============================== for i = 0; i < int32(len(instance.Spec.Shard)); i++ { OraShardSpex = instance.Spec.Shard[i] - if OraShardSpex.IsDelete != true { + if !shardingv1.CheckIsDeleteFlag(OraShardSpex.IsDelete, instance, r.Log) { sfSet, shardPod, err := r.validateShard(instance, OraShardSpex, int(i)) if err != nil { shardingv1.LogMessages("INFO", "Shard "+sfSet.Name+" is not in available state.", nil, instance, r.Log) @@ -410,18 +424,6 @@ func (r *ShardingDatabaseReconciler) Reconcile(ctx context.Context, req ctrl.Req } } - // Calling updateShardTopology to update the entire sharding topology - // This is required because we just executed updateShard,updateCatalog and UpdateGsm - // If some state has changed it will update the topology - - err = r.updateShardTopologyStatus(instance) - if err != nil { - // time.Sleep(30 * time.Second) - result = resultQ - err = nilErr - return result, err - } - stateType = string(databasev1alpha1.CrdReconcileCompeleteState) // r.setCrdLifeCycleState(instance, &result, &err, stateType) // Set error to ni to avoid reconcilation state reconcilation error as we are passing err to setCrdLifeCycleState @@ -441,6 +443,7 @@ func (r *ShardingDatabaseReconciler) SetupWithManager(mgr ctrl.Manager) error { Owns(&appsv1.StatefulSet{}). Owns(&corev1.Service{}). Owns(&corev1.Pod{}). + Owns(&corev1.Secret{}). WithEventFilter(r.eventFilterPredicate()). WithOptions(controller.Options{MaxConcurrentReconciles: 50}). //MaxConcurrentReconciles is the maximum number of concurrent Reconciles which can be run. Defaults to 1 Complete(r) @@ -454,6 +457,22 @@ func (r *ShardingDatabaseReconciler) eventFilterPredicate() predicate.Predicate return true }, UpdateFunc: func(e event.UpdateEvent) bool { + if old, ok := e.ObjectOld.(*corev1.Secret); ok { + if new, ok := e.ObjectNew.(*corev1.Secret); ok { + for i := 0; i < len(r.osh); i++ { + oshInst := r.osh[i] + if (new.Name == oshInst.Instance.Spec.DbSecret.Name) && (new.Name == old.Name) { + _, ok := old.Data[oshInst.Instance.Spec.DbSecret.PwdFileName] + if ok { + if !reflect.DeepEqual(old.Data[oshInst.Instance.Spec.DbSecret.PwdFileName], new.Data[oshInst.Instance.Spec.DbSecret.PwdFileName]) { + shardingv1.LogMessages("INFO", "Secret Changed", nil, oshInst.Instance, r.Log) + } + } + shardingv1.LogMessages("INFO", "Secret update block", nil, oshInst.Instance, r.Log) + } + } + } + } return true }, DeleteFunc: func(e event.DeleteEvent) bool { @@ -495,13 +514,32 @@ func (r *ShardingDatabaseReconciler) eventFilterPredicate() predicate.Predicate } } +// ================ Function to check secret update============= +func (r *ShardingDatabaseReconciler) UpdateSecret(instance *databasev1alpha1.ShardingDatabase, kClient client.Client, logger logr.Logger) (ctrl.Result, error) { + + sc := &corev1.Secret{} + //var err error + + // Reading a Secret + var err error = kClient.Get(context.TODO(), types.NamespacedName{ + Name: instance.Spec.DbSecret.Name, + Namespace: instance.Spec.Namespace, + }, sc) + + if err != nil { + return ctrl.Result{}, nil + } + + return ctrl.Result{}, nil +} + // ================== Function to get the Notification controller ============== func (r *ShardingDatabaseReconciler) getOnsConfigProvider(instance *databasev1alpha1.ShardingDatabase, idx int, ) { var err error - if instance.Spec.NsConfigMap != "" && instance.Spec.NsSecret != "" && r.osh[idx].onsProviderFlag != true { - cmName := instance.Spec.NsConfigMap - secName := instance.Spec.NsSecret + if instance.Spec.DbSecret.NsConfigMap != "" && instance.Spec.DbSecret.NsSecret != "" && r.osh[idx].onsProviderFlag != true { + cmName := instance.Spec.DbSecret.NsConfigMap + secName := instance.Spec.DbSecret.NsSecret shardingv1.LogMessages("DEBUG", "Received parameters are "+shardingv1.GetFmtStr(cmName)+","+shardingv1.GetFmtStr(secName), nil, instance, r.Log) region, user, tenancy, passphrase, fingerprint, topicid := shardingv1.ReadConfigMap(cmName, instance, r.Client, r.Log) privatekey := shardingv1.ReadSecret(secName, instance, r.Client, r.Log) @@ -831,6 +869,7 @@ func (r *ShardingDatabaseReconciler) validateSpex(instance *databasev1alpha1.Sha var eventMsg string var eventErr string = "Spec Error" + var i int32 lastSuccSpec, err := instance.GetLastSuccessfulSpec() if err != nil { @@ -841,6 +880,27 @@ func (r *ShardingDatabaseReconciler) validateSpex(instance *databasev1alpha1.Sha if lastSuccSpec == nil { // Logic to check if inital Spec is good or not + err = r.checkShardingType(instance, idx) + if err != nil { + return err + } + + if len(instance.Spec.Shard) > 0 { + for i = 0; i < int32(len(instance.Spec.Shard)); i++ { + OraShardSpex := instance.Spec.Shard[i] + if !shardingv1.CheckIsDeleteFlag(OraShardSpex.IsDelete, instance, r.Log) { + err = r.checkShardSpace(instance, OraShardSpex) + if err != nil { + return err + } + err = r.checkShardGroup(instance, OraShardSpex) + if err != nil { + return err + } + } + } + } + // Once the initial Spec is been validated then update the last Sucessful Spec err = instance.UpdateLastSuccessfulSpec(r.Client) if err != nil { @@ -890,6 +950,65 @@ func (r *ShardingDatabaseReconciler) validateSpex(instance *databasev1alpha1.Sha return nil } +func (r *ShardingDatabaseReconciler) checkShardingType(instance *databasev1alpha1.ShardingDatabase, idx int) error { + var i, k int32 + var regionFlag bool + + for k = 0; k < int32(len(instance.Spec.Gsm)); k++ { + regionFlag = false + for i = 0; i < int32(len(instance.Spec.Shard)); i++ { + if instance.Spec.Gsm[k].Region == instance.Spec.Shard[i].ShardRegion { + regionFlag = true + } + } + if !regionFlag { + msg := instance.Spec.Gsm[k].Region + " does not match with any region with Shard region. Region will be created during shard director provisioning" + shardingv1.LogMessages("INFO", msg, nil, instance, r.Log) + } + } + + return nil +} + +// Check the ShardGroups/ Shard Space and Shard group Name +// checkShrdGSR is Shardgroup/ShardSpace/ShardRegion + +func (r *ShardingDatabaseReconciler) checkShardSpace(instance *databasev1alpha1.ShardingDatabase, OraShardSpex databasev1alpha1.ShardSpec) error { + + if instance.Spec.ShardingType != "" { + // Check for the Sharding Type and if it is USER do following + if strings.TrimSpace(strings.ToUpper(instance.Spec.ShardingType)) == "USER" { + if len(OraShardSpex.ShardRegion) == 0 { + return fmt.Errorf("Shard region cannot be empty! ") + } + if len(OraShardSpex.ShardSpace) == 0 { + return fmt.Errorf("Shard Space in " + OraShardSpex.Name + " cannot be empty") + } + } + } + return nil +} + +// Check the ShardGroups/ Shard Space and Shard group Name +// checkShrdGSR is Shardgroup/ShardSpace/ShardRegion + +func (r *ShardingDatabaseReconciler) checkShardGroup(instance *databasev1alpha1.ShardingDatabase, OraShardSpex databasev1alpha1.ShardSpec) error { + + // We need to check Shard Region and Shard Group for ShardingType='SYSTEM' and 'NATIVE' + if strings.TrimSpace(strings.ToUpper(instance.Spec.ShardingType)) != "USER" { + if len(OraShardSpex.ShardRegion) == 0 { + return fmt.Errorf("Shard region cannot be empty! in " + OraShardSpex.Name) + } + if len(OraShardSpex.ShardGroup) == 0 { + return fmt.Errorf("Shard group in " + OraShardSpex.Name + " cannot be empty") + } + + // + + } + return nil +} + // Compare GSM Env Variables func (r *ShardingDatabaseReconciler) comapreGsmEnvVariables(instance *databasev1alpha1.ShardingDatabase, lastSuccSpec *databasev1alpha1.ShardingDatabaseSpec) bool { @@ -1029,6 +1148,7 @@ func (r *ShardingDatabaseReconciler) validateGsm(instance *databasev1alpha1.Shar if availableFlag != true { gsmSfSet = gsmSfSet1 gsmPod = gsmPod1 + // availableFlag = true availableFlag = true } } @@ -1102,6 +1222,7 @@ func (r *ShardingDatabaseReconciler) validateCatalog(instance *databasev1alpha1. if availlableFlag != true { catalogSfSet = catalogSfSet1 catalogPod = catalogPod1 + // availlableFlag = true availlableFlag = true } } @@ -1202,24 +1323,21 @@ func (r *ShardingDatabaseReconciler) validateShard(instance *databasev1alpha1.Sh } // This function updates the shard topology over all -// -func (r *ShardingDatabaseReconciler) updateShardTopologyStatus(instance *databasev1alpha1.ShardingDatabase) error { +func (r *ShardingDatabaseReconciler) updateShardTopologyStatus(instance *databasev1alpha1.ShardingDatabase) { //shardPod := &corev1.Pod{} //gsmSfSet := &appsv1.StatefulSet{} gsmPod := &corev1.Pod{} var err error _, _, err = r.validateCatalog(instance) if err != nil { - return err + } _, gsmPod, err = r.validateGsm(instance) if err != nil { - return err + } r.updateShardTopologyShardsInGsm(instance, gsmPod) - return nil - } func (r *ShardingDatabaseReconciler) updateShardTopologyShardsInGsm(instance *databasev1alpha1.ShardingDatabase, gsmPod *corev1.Pod) { @@ -1231,13 +1349,16 @@ func (r *ShardingDatabaseReconciler) updateShardTopologyShardsInGsm(instance *da if len(instance.Spec.Shard) > 0 { for i = 0; i < int32(len(instance.Spec.Shard)); i++ { OraShardSpex := instance.Spec.Shard[i] + if strings.ToLower(OraShardSpex.IsDelete) == "failed" { + continue + } // stateStr := shardingv1.GetGsmShardStatus(instance, OraShardSpex.Name) - if OraShardSpex.IsDelete != true { + if !shardingv1.CheckIsDeleteFlag(OraShardSpex.IsDelete, instance, r.Log) { shardSfSet, _, err = r.validateShard(instance, OraShardSpex, int(i)) if err != nil { continue } else { - _ = r.verifyShards(instance, gsmPod, shardSfSet) + _ = r.verifyShards(instance, gsmPod, shardSfSet, OraShardSpex) } } @@ -1369,7 +1490,7 @@ func (r *ShardingDatabaseReconciler) addPrimaryShards(instance *databasev1alpha1 //gsmSfSet := &appsv1.StatefulSet{} gsmPod := &corev1.Pod{} var sparams1 string - var deployFlag = false + var deployFlag = true var errStr = false //var msg string @@ -1383,8 +1504,9 @@ func (r *ShardingDatabaseReconciler) addPrimaryShards(instance *databasev1alpha1 for i = 0; i < int32(len(instance.Spec.Shard)); i++ { OraShardSpex := instance.Spec.Shard[i] // stateStr := shardingv1.GetGsmShardStatus(instance, OraShardSpex.Name) - // !strings.Contains(stateStr, "DELETE") - if OraShardSpex.IsDelete != true { + // strings.Contains(stateStr, "DELETE") + + if !shardingv1.CheckIsDeleteFlag(OraShardSpex.IsDelete, instance, r.Log) { if setLifeCycleFlag != true { setLifeCycleFlag = true stateType := string(databasev1alpha1.CrdReconcileWaitingState) @@ -1395,52 +1517,96 @@ func (r *ShardingDatabaseReconciler) addPrimaryShards(instance *databasev1alpha1 shardSfSet, _, err = r.validateShard(instance, OraShardSpex, int(i)) if err != nil { errStr = true + deployFlag = false continue } // 2nd Step is to check if GSM is in good state if not then just return because you can't do anything _, gsmPod, err = r.validateGsm(instance) if err != nil { + deployFlag = false return err } // 3rd step to check if shard is in GSM if not then continue - sparams := shardingv1.BuildShardParams(shardSfSet) + sparams := shardingv1.BuildShardParams(instance, shardSfSet, OraShardSpex) sparams1 = sparams err = shardingv1.CheckShardInGsm(gsmPod.Name, sparams, instance, r.kubeClient, r.kubeConfig, r.Log) if err == nil { // if you are in this block then it means that shard already exist in the GSM and we do not need to anything continue } + + /** + // Copy file from pod to FS + configrest, kclientset, err := shardingv1.GetPodCopyConfig(r.kubeClient, r.kubeConfig, instance, r.Log) + if err != nil { + return fmt.Errorf("Error occurred in getting KubeConfig, cannot perform copy operation from the pod") + } + + _, _, err = shardingv1.ExecCommand(gsmPod.Name, shardingv1.GetTdeKeyLocCmd(), r.kubeClient, r.kubeConfig, instance, r.Log) + if err != nil { + fmt.Printf("Error occurred during the while getting the TDE key from the pod " + gsmPod.Name) + //return err + } + fileName := "/tmp/tde_key" + last := fileName[strings.LastIndex(fileName, "/")+1:] + fileName1 := last + fsLoc := shardingv1.TmpLoc + "/" + fileName1 + _, _, _, err = shardingv1.KctlCopyFile(r.kubeClient, r.kubeConfig, instance, configrest, kclientset, r.Log, fmt.Sprintf("%s/%s:/%s", instance.Spec.Namespace, gsmPod.Name, fileName), fsLoc, "") + if err != nil { + fmt.Printf("failed to copy file") + //return err + } + + // Copying it to Shard Pod + _, _, _, err = shardingv1.KctlCopyFile(r.kubeClient, r.kubeConfig, instance, configrest, kclientset, r.Log, fsLoc, fmt.Sprintf("%s/%s:/%s", instance.Spec.Namespace, OraShardSpex.Name+"-0", fsLoc), "") + if err != nil { + fmt.Printf("failed to copy file") + //return err + } + + **/ + // If the shard doesn't exist in GSM then just add the shard statefulset and update GSM shard status // ADD Shard in GSM + r.updateGsmShardStatus(instance, OraShardSpex.Name, string(databasev1alpha1.AddingShardState)) - err := shardingv1.AddShardInGsm(gsmPod.Name, sparams, instance, r.kubeClient, r.kubeConfig, r.Log) + err = shardingv1.AddShardInGsm(gsmPod.Name, sparams, instance, r.kubeClient, r.kubeConfig, r.Log) if err != nil { r.updateGsmShardStatus(instance, OraShardSpex.Name, string(databasev1alpha1.AddingShardErrorState)) title = "Shard Addition Failure" message = "Error occurred during shard " + shardingv1.GetFmtStr(OraShardSpex.Name) + " addition." - r.sendMessage(instance, title, message) - } else { - deployFlag = true + shardingv1.LogMessages("INFO", title+":"+message, nil, instance, r.Log) + if sentFailMsg[OraShardSpex.Name] != true { + r.sendMessage(instance, title, message) + } + sentFailMsg[OraShardSpex.Name] = true + sentCompleteMsg[OraShardSpex.Name] = false + deployFlag = false } } } + if errStr == true { + shardingv1.LogMessages("INFO", "Some shards are still pending for addition. Requeue the reconcile loop.", nil, instance, r.Log) + return fmt.Errorf("shards are not ready for addition.") + } + // ======= Deploy Shard Logic ========= if deployFlag == true { _ = shardingv1.DeployShardInGsm(gsmPod.Name, sparams1, instance, r.kubeClient, r.kubeConfig, r.Log) r.updateShardTopologyShardsInGsm(instance, gsmPod) + } else { + shardingv1.LogMessages("INFO", "Shards are not added in GSM. Deploy operation will happen after shard addition. Requeue the reconcile loop.", nil, instance, r.Log) + return fmt.Errorf("shards addition are pending.") } } - if errStr == true { - shardingv1.LogMessages("INFO", "Some shards are still pending for addition. Requeue the reconcile loop.", nil, instance, r.Log) - return fmt.Errorf("Shard Addition is pending.") - } + shardingv1.LogMessages("INFO", "Completed the shard addition operation. For details, check the CRD resource status for GSM and Shards.", nil, instance, r.Log) return nil } // This function Check the online shard -func (r *ShardingDatabaseReconciler) verifyShards(instance *databasev1alpha1.ShardingDatabase, gsmPod *corev1.Pod, shardSfSet *appsv1.StatefulSet) error { +func (r *ShardingDatabaseReconciler) verifyShards(instance *databasev1alpha1.ShardingDatabase, gsmPod *corev1.Pod, shardSfSet *appsv1.StatefulSet, OraShardSpex databasev1alpha1.ShardSpec) error { //var result ctrl.Result //var i int32 var err error @@ -1448,13 +1614,15 @@ func (r *ShardingDatabaseReconciler) verifyShards(instance *databasev1alpha1.Sha var message string // ================================ Check Shards ================== //veryify shard make shard state online and it must be executed to check shard state after every CRUD operation - sparams := shardingv1.BuildShardParams(shardSfSet) + sparams := shardingv1.BuildShardParams(instance, shardSfSet, OraShardSpex) err = shardingv1.CheckOnlineShardInGsm(gsmPod.Name, sparams, instance, r.kubeClient, r.kubeConfig, r.Log) if err != nil { // If the shard doesn't exist in GSM then just delete the shard statefulset and update GSM shard status /// Terminate state means we will remove teh shard entry from GSM shard status r.updateGsmShardStatus(instance, shardSfSet.Name, string(databasev1alpha1.ShardOnlineErrorState)) - shardingv1.CancelChunksInGsm(gsmPod.Name, sparams, instance, r.kubeClient, r.kubeConfig, r.Log) + if strings.ToUpper(instance.Spec.ReplicationType) != "NATIVE" { + shardingv1.CancelChunksInGsm(gsmPod.Name, sparams, instance, r.kubeClient, r.kubeConfig, r.Log) + } return err } oldStateStr := shardingv1.GetGsmShardStatus(instance, shardSfSet.Name) @@ -1463,7 +1631,13 @@ func (r *ShardingDatabaseReconciler) verifyShards(instance *databasev1alpha1.Sha if oldStateStr != string(databasev1alpha1.ShardOnlineState) { title = "Shard Addition Completed" message = "Shard addition completed for shard " + shardingv1.GetFmtStr(shardSfSet.Name) + " in GSM." - r.sendMessage(instance, title, message) + shardingv1.LogMessages("INFO", title+":"+message, nil, instance, r.Log) + if sentCompleteMsg[shardSfSet.Name] != true { + r.sendMessage(instance, title, message) + } + + sentCompleteMsg[shardSfSet.Name] = true + sentFailMsg[shardSfSet.Name] = false } return nil } @@ -1490,10 +1664,11 @@ func (r *ShardingDatabaseReconciler) delGsmShard(instance *databasev1alpha1.Shar shardingv1.LogMessages("DEBUG", "Starting shard deletion operation.", nil, instance, r.Log) // ================================ Shard Delete Logic =================== + if len(instance.Spec.Shard) > 0 { for i = 0; i < int32(len(instance.Spec.Shard)); i++ { OraShardSpex := instance.Spec.Shard[i] - if OraShardSpex.IsDelete == true { + if shardingv1.CheckIsDeleteFlag(OraShardSpex.IsDelete, instance, r.Log) { if setLifeCycleFlag != true { setLifeCycleFlag = true stateType := string(databasev1alpha1.CrdReconcileWaitingState) @@ -1518,7 +1693,7 @@ func (r *ShardingDatabaseReconciler) delGsmShard(instance *databasev1alpha1.Shar continue } // 3rd step to check if shard is in GSM if not then continue - sparams := shardingv1.BuildShardParams(shardSfSet) + sparams := shardingv1.BuildShardParams(instance, shardSfSet, OraShardSpex) err = shardingv1.CheckShardInGsm(gsmPod.Name, sparams, instance, r.kubeClient, r.kubeConfig, r.Log) if err != nil { // If the shard doesn't exist in GSM then just delete the shard statefulset and update GSM shard status @@ -1541,28 +1716,53 @@ func (r *ShardingDatabaseReconciler) delGsmShard(instance *databasev1alpha1.Shar // 5th Step // Move the chunks before performing any Delete // If you are in this block then it means that shard is ONline and can be deleted - err = shardingv1.MoveChunks(gsmPod.Name, sparams, instance, r.kubeClient, r.kubeConfig, r.Log) - if err != nil { - r.updateGsmShardStatus(instance, OraShardSpex.Name, string(databasev1alpha1.ChunkMoveError)) - title = "Chunk Movement Failure" - message = "Error occurred during chunk movement in shard " + shardingv1.GetFmtStr(OraShardSpex.Name) + " deletion." - r.sendMessage(instance, title, message) - continue - } - // 6th Step - // Check if Chunks has moved before performing actual delete - // This is a loop and will check unless there is a error or chunks has moved - // Validate if the chunks has moved before performing shard deletion - for { - err = shardingv1.VerifyChunks(gsmPod.Name, sparams, instance, r.kubeClient, r.kubeConfig, r.Log) - if err == nil { - break - } else { - msg = "Sleeping for 120 seconds and will check status again of chunks movement in gsm for shard: " + shardingv1.GetFmtStr(OraShardSpex.Name) - shardingv1.LogMessages("INFO", msg, nil, instance, r.Log) - time.Sleep(120 * time.Second) + if strings.ToUpper(instance.Spec.ReplicationType) != "NATIVE" { + if len(instance.Spec.ReplicationType) == 0 { + err = shardingv1.MoveChunks(gsmPod.Name, sparams, instance, r.kubeClient, r.kubeConfig, r.Log) + if err != nil { + r.updateGsmShardStatus(instance, OraShardSpex.Name, string(databasev1alpha1.ChunkMoveError)) + title = "Chunk Movement Failure" + message = "Error occurred during chunk movement in shard " + shardingv1.GetFmtStr(OraShardSpex.Name) + " deletion." + r.sendMessage(instance, title, message) + instance.Spec.Shard[i].IsDelete = "failed" + err = shardingv1.InstanceShardPatch(instance, instance, r.Client, i, "isDelete", "failed") + if err != nil { + msg = "Error occurred while changing the isDelete value to failed in Spec struct" + shardingv1.LogMessages("INFO", msg, nil, instance, r.Log) + return err + } + continue + } + // 6th Step + // Check if Chunks has moved before performing actual delete + // This is a loop and will check unless there is a error or chunks has moved + // Validate if the chunks has moved before performing shard deletion + for { + msg = "Sleeping for 120 seconds and will check status again of chunks movement in gsm for shard: " + shardingv1.GetFmtStr(OraShardSpex.Name) + "ShardType=" + strings.TrimSpace(strings.ToUpper(instance.Spec.ShardingType)) + shardingv1.LogMessages("INFO", msg, nil, instance, r.Log) + time.Sleep(120 * time.Second) + err = shardingv1.VerifyChunks(gsmPod.Name, sparams, instance, r.kubeClient, r.kubeConfig, r.Log) + if err == nil { + break + } else { + if strings.TrimSpace(strings.ToUpper(instance.Spec.ShardingType)) != "USER" { + // If ShardingType is not "USER", do not perform the patching.. continue + continue + } + instance.Spec.Shard[i].IsDelete = "failed" + err = shardingv1.InstanceShardPatch(instance, instance, r.Client, i, "isDelete", "failed") + if err != nil { + // r.updateGsmShardStatus(instance, OraShardSpex.Name, string(databasev1alpha1.ChunkMoveError)) + msg = "Error occurred while changing the isDelete value to failed in Spec struct" + shardingv1.LogMessages("INFO", msg, nil, instance, r.Log) + // return err + } + return err + } + } } } + // 7th Step remove the shards from the GSM // This steps will delete the shard entry from the GSM // It will delete CDB from catalog @@ -1572,8 +1772,10 @@ func (r *ShardingDatabaseReconciler) delGsmShard(instance *databasev1alpha1.Shar msg = "Error occurred during shard" + shardingv1.GetFmtStr(OraShardSpex.Name) + "removal from Gsm" shardingv1.LogMessages("Error", msg, nil, instance, r.Log) r.updateShardStatus(instance, int(i), string(databasev1alpha1.ShardRemoveError)) + instance.Spec.Shard[i].IsDelete = "failed" continue } + // 8th Step // Delete the Statefulset as all the chunks has moved and Shard can be phyiscally deleted r.delShard(instance, shardSfSet.Name, shardSfSet, shardPod, int(i)) @@ -1645,7 +1847,7 @@ func (r *ShardingDatabaseReconciler) delShard(instance *databasev1alpha1.Shardin } } -//======== GSM Invited Node ========== +// ======== GSM Invited Node ========== // Remove and add GSM invited node func (r *ShardingDatabaseReconciler) gsmInvitedNodeOp(instance *databasev1alpha1.ShardingDatabase, objName string, ) { @@ -1746,6 +1948,15 @@ func (r *ShardingDatabaseReconciler) deployStatefulSet(instance *databasev1alpha message := "Inside the deployStatefulSet function" shardingv1.LogMessages("DEBUG", message, nil, instance, r.Log) // See if StatefulSets already exists and create if it doesn't + // Error : invalid memory address or nil pointer dereference" (runtime error: invalid memory address or nil pointer dereference) + // This happens during unit test cases + for i := 0; i < 5; i++ { + if r.Scheme == nil { + time.Sleep(time.Second * 40) + } else { + break + } + } controllerutil.SetControllerReference(instance, dep, r.Scheme) found := &appsv1.StatefulSet{} err := r.Client.Get(context.TODO(), types.NamespacedName{ @@ -1781,3 +1992,58 @@ func (r *ShardingDatabaseReconciler) deployStatefulSet(instance *databasev1alpha return ctrl.Result{}, nil } + +func (r *ShardingDatabaseReconciler) checkShardState(instance *databasev1alpha1.ShardingDatabase) error { + + var i int32 + var err error = nil + var OraShardSpex databasev1alpha1.ShardSpec + var currState string + var eventMsg string + var msg string + + currState = "" + eventMsg = "" + + msg = "checkShardState():ShardType=" + strings.TrimSpace(strings.ToUpper(instance.Spec.ShardingType)) + shardingv1.LogMessages("INFO", msg, nil, instance, r.Log) + if strings.TrimSpace(strings.ToUpper(instance.Spec.ShardingType)) != "USER" { + // ShardingType is not "USER", so return + return err + } + + if len(instance.Status.Gsm.Shards) > 0 { + for i = 0; i < int32(len(instance.Spec.Shard)); i++ { + OraShardSpex = instance.Spec.Shard[i] + currState = shardingv1.GetGsmShardStatus(instance, OraShardSpex.Name) + if currState == string(databasev1alpha1.AddingShardState) { + eventMsg = "Shard Addition in progress. Requeuing" + err = fmt.Errorf(eventMsg) + break + } else if currState == string(databasev1alpha1.DeletingState) { + eventMsg = "Shard Deletion in progress. Requeuing" + err = fmt.Errorf(eventMsg) + err = nil + break + } else if OraShardSpex.IsDelete == "failed" { + eventMsg = "Shard Deletion failed. Manual intervention required. Requeuing" + err = fmt.Errorf(eventMsg) + break + } else if currState == string(databasev1alpha1.DeleteErrorState) { + eventMsg = "Shard Deletion Error. Manual intervention required. Requeuing" + err = fmt.Errorf(eventMsg) + break + } else if currState == string(databasev1alpha1.ShardRemoveError) { + eventMsg = "Shard Deletion Error. Manual intervention required. Requeuing" + err = fmt.Errorf(eventMsg) + break + } else { + eventMsg = "checkShardState() : Shard State=[" + currState + "]" + shardingv1.LogMessages("INFO", eventMsg, nil, instance, r.Log) + err = nil + } + } + r.publishEvents(instance, eventMsg, currState) + } + return err +} diff --git a/controllers/database/singleinstancedatabase_controller.go b/controllers/database/singleinstancedatabase_controller.go index a4baf0a9..a20fa1fd 100644 --- a/controllers/database/singleinstancedatabase_controller.go +++ b/controllers/database/singleinstancedatabase_controller.go @@ -53,6 +53,7 @@ import ( "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" + storagev1 "k8s.io/api/storage/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/resource" @@ -92,7 +93,10 @@ var oemExpressUrl string //+kubebuilder:rbac:groups=database.oracle.com,resources=singleinstancedatabases,verbs=get;list;watch;create;update;patch;delete //+kubebuilder:rbac:groups=database.oracle.com,resources=singleinstancedatabases/status,verbs=get;update;patch //+kubebuilder:rbac:groups=database.oracle.com,resources=singleinstancedatabases/finalizers,verbs=update -//+kubebuilder:rbac:groups="",resources=pods;pods/log;pods/exec;persistentvolumeclaims;services;nodes;events,verbs=create;delete;get;list;patch;update;watch +//+kubebuilder:rbac:groups="",resources=pods;pods/log;pods/exec;persistentvolumeclaims;services,verbs=create;delete;get;list;patch;update;watch +//+kubebuilder:rbac:groups="",resources=persistentvolumes,verbs=get;list;watch +//+kubebuilder:rbac:groups="",resources=events,verbs=create;patch +//+kubebuilder:rbac:groups=storage.k8s.io,resources=storageclasses,verbs=get;list;watch // Reconcile is part of the main kubernetes reconciliation loop which aims to // move the current state of the cluster closer to the desired state. @@ -167,15 +171,15 @@ func (r *SingleInstanceDatabaseReconciler) Reconcile(ctx context.Context, req ct return result, nil } - // Service creation - result, err = r.createOrReplaceSVC(ctx, req, singleInstanceDatabase) + // PVC Creation for Datafiles Volume + result, err = r.createOrReplacePVCforDatafilesVol(ctx, req, singleInstanceDatabase) if result.Requeue { r.Log.Info("Reconcile queued") return result, nil } - // PVC Creation - result, err = r.createOrReplacePVC(ctx, req, singleInstanceDatabase) + // PVC Creation for customScripts Volume + result, err = r.createOrReplacePVCforCustomScriptsVol(ctx, req, singleInstanceDatabase) if result.Requeue { r.Log.Info("Reconcile queued") return result, nil @@ -188,9 +192,15 @@ func (r *SingleInstanceDatabaseReconciler) Reconcile(ctx context.Context, req ct return result, nil } + // Service creation + result, err = r.createOrReplaceSVC(ctx, req, singleInstanceDatabase) + if result.Requeue { + r.Log.Info("Reconcile queued") + return result, nil + } + // Validate readiness - var readyPod corev1.Pod - result, readyPod, err = r.validateDBReadiness(singleInstanceDatabase, ctx, req) + result, readyPod, err := r.validateDBReadiness(singleInstanceDatabase, ctx, req) if result.Requeue { r.Log.Info("Reconcile queued") return result, nil @@ -207,7 +217,9 @@ func (r *SingleInstanceDatabaseReconciler) Reconcile(ctx context.Context, req ct } } - if strings.ToUpper(singleInstanceDatabase.Status.Role) == "PRIMARY" { + sidbRole, err := dbcommons.GetDatabaseRole(readyPod, r, r.Config, ctx, req) + + if sidbRole == "PRIMARY" { // Update DB config result, err = r.updateDBConfig(singleInstanceDatabase, readyPod, ctx, req) @@ -232,9 +244,11 @@ func (r *SingleInstanceDatabaseReconciler) Reconcile(ctx context.Context, req ct } else { // Database is in role of standby - err = SetupStandbyDatabase(r, singleInstanceDatabase, referredPrimaryDatabase, ctx, req) - if err != nil { - return requeueY, err + if !singleInstanceDatabase.Status.DgBrokerConfigured { + err = SetupStandbyDatabase(r, singleInstanceDatabase, referredPrimaryDatabase, ctx, req) + if err != nil { + return requeueY, err + } } databaseOpenMode, err := dbcommons.GetDatabaseOpenMode(readyPod, r, r.Config, ctx, req, singleInstanceDatabase.Spec.Edition) @@ -245,7 +259,8 @@ func (r *SingleInstanceDatabaseReconciler) Reconcile(ctx context.Context, req ct } r.Log.Info("DB openMode Output") r.Log.Info(databaseOpenMode) - if databaseOpenMode == "READ_ONLY" { + if databaseOpenMode == "READ_ONLY" || databaseOpenMode == "MOUNTED" { + // Changing the open mode for sidb to "READ ONLY WITH APPLY" out, err := dbcommons.ExecCommand(r, r.Config, readyPod.Name, readyPod.Namespace, "", ctx, req, false, "bash", "-c", fmt.Sprintf("echo -e \"%s\" | %s", dbcommons.ModifyStdbyDBOpenMode, dbcommons.SQLPlusCLI)) if err != nil { r.Log.Error(err, err.Error()) @@ -280,11 +295,15 @@ func (r *SingleInstanceDatabaseReconciler) Reconcile(ctx context.Context, req ct // If LoadBalancer = true , ensure Connect String is updated if singleInstanceDatabase.Status.ConnectString == dbcommons.ValueUnavailable { + r.Log.Info("Connect string not available for the database " + singleInstanceDatabase.Name) return requeueY, nil } - // update status to Ready after all operations succeed - singleInstanceDatabase.Status.Status = dbcommons.StatusReady + // updating singleinstancedatabase Status + err = r.updateSidbStatus(singleInstanceDatabase, readyPod, ctx, req) + if err != nil { + return requeueY, err + } r.updateORDSStatus(singleInstanceDatabase, ctx, req) completed = true @@ -407,26 +426,12 @@ func (r *SingleInstanceDatabaseReconciler) validate(m *dbapi.SingleInstanceDatab if m.Status.Sid != "" && !strings.EqualFold(m.Spec.Sid, m.Status.Sid) { eventMsgs = append(eventMsgs, "sid cannot be updated") } - if m.Spec.CloneFrom == "" && m.Spec.Edition != "" && m.Status.Edition != "" && !strings.EqualFold(m.Status.Edition, m.Spec.Edition) { - eventMsgs = append(eventMsgs, "edition cannot be updated") - } if m.Status.Charset != "" && !strings.EqualFold(m.Status.Charset, m.Spec.Charset) { eventMsgs = append(eventMsgs, "charset cannot be updated") } if m.Status.Pdbname != "" && !strings.EqualFold(m.Status.Pdbname, m.Spec.Pdbname) { eventMsgs = append(eventMsgs, "pdbName cannot be updated") } - if m.Status.CloneFrom != "" && - (m.Status.CloneFrom == dbcommons.NoCloneRef && m.Spec.CloneFrom != "" || - m.Status.CloneFrom != dbcommons.NoCloneRef && m.Status.CloneFrom != m.Spec.CloneFrom) { - eventMsgs = append(eventMsgs, "cloneFrom cannot be updated") - } - if (m.Spec.Edition == "express" || m.Spec.Edition == "free") && m.Spec.CloneFrom != "" { - eventMsgs = append(eventMsgs, "cloning not supported for "+m.Spec.Edition+" edition") - } - if (m.Spec.Edition == "express" || m.Spec.Edition == "free") && m.Spec.PrimaryDatabaseRef != "" && m.Spec.CreateAsStandby { - eventMsgs = append(eventMsgs, "Standby database creation is not supported for "+m.Spec.Edition+" edition") - } if m.Status.OrdsReference != "" && m.Status.Persistence.Size != "" && m.Status.Persistence != m.Spec.Persistence { eventMsgs = append(eventMsgs, "uninstall ORDS to change Peristence") } @@ -461,20 +466,16 @@ func (r *SingleInstanceDatabaseReconciler) validate(m *dbapi.SingleInstanceDatab m.Status.Pdbname = m.Spec.Pdbname m.Status.Persistence = m.Spec.Persistence m.Status.PrebuiltDB = m.Spec.Image.PrebuiltDB - if m.Spec.CloneFrom == "" { - m.Status.CloneFrom = dbcommons.NoCloneRef - } else { - m.Status.CloneFrom = m.Spec.CloneFrom - } - if m.Spec.CloneFrom != "" { + + if m.Spec.CreateAs == "clone" { // Once a clone database has created , it has no link with its reference if m.Status.DatafilesCreated == "true" || - !dbcommons.IsSourceDatabaseOnCluster(m.Spec.CloneFrom) { + !dbcommons.IsSourceDatabaseOnCluster(m.Spec.PrimaryDatabaseRef) { return requeueN, nil } // Fetch the Clone database reference - err = r.Get(ctx, types.NamespacedName{Namespace: req.Namespace, Name: m.Spec.CloneFrom}, n) + err = r.Get(ctx, types.NamespacedName{Namespace: req.Namespace, Name: m.Spec.PrimaryDatabaseRef}, n) if err != nil { if apierrors.IsNotFound(err) { r.Recorder.Eventf(m, corev1.EventTypeWarning, eventReason, err.Error()) @@ -487,13 +488,13 @@ func (r *SingleInstanceDatabaseReconciler) validate(m *dbapi.SingleInstanceDatab if n.Status.Status != dbcommons.StatusReady { m.Status.Status = dbcommons.StatusPending eventReason := "Source Database Pending" - eventMsg := "status of database " + m.Spec.CloneFrom + " is not ready, retrying..." + eventMsg := "status of database " + n.Name + " is not ready, retrying..." r.Recorder.Eventf(m, corev1.EventTypeNormal, eventReason, eventMsg) err = errors.New(eventMsg) return requeueY, err } - if !n.Spec.ArchiveLog { + if !*n.Spec.ArchiveLog { m.Status.Status = dbcommons.StatusPending eventReason := "Source Database Check" eventMsg := "enable ArchiveLog for database " + n.Name @@ -504,10 +505,10 @@ func (r *SingleInstanceDatabaseReconciler) validate(m *dbapi.SingleInstanceDatab } m.Status.Edition = n.Status.Edition - + m.Status.PrimaryDatabase = n.Name } - if m.Spec.PrimaryDatabaseRef != "" && m.Spec.CreateAsStandby { + if m.Spec.CreateAs == "standby" && m.Status.Role != "PRIMARY" { // Fetch the Primary database reference, required for all iterations err = r.Get(ctx, types.NamespacedName{Namespace: req.Namespace, Name: m.Spec.PrimaryDatabaseRef}, rp) @@ -544,7 +545,7 @@ func (r *SingleInstanceDatabaseReconciler) validate(m *dbapi.SingleInstanceDatab return requeueY, err } - r.Log.Info("Settingup Primary Database for standby creation...") + r.Log.Info("Setting up Primary Database for standby creation...") err = SetupPrimaryDatabase(r, m, rp, ctx, req) if err != nil { return requeueY, err @@ -635,7 +636,7 @@ func (r *SingleInstanceDatabaseReconciler) instantiatePodSpec(m *dbapi.SingleIns } }(), Volumes: []corev1.Volume{{ - Name: "datamount", + Name: "datafiles-vol", VolumeSource: func() corev1.VolumeSource { if m.Spec.Persistence.Size == "" { return corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}} @@ -660,10 +661,48 @@ func (r *SingleInstanceDatabaseReconciler) instantiatePodSpec(m *dbapi.SingleIns }}, }, }, + }, { + Name: "tls-secret-vol", + VolumeSource: func() corev1.VolumeSource { + if m.Spec.TcpsTlsSecret == "" { + return corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}} + } + /* tls-secret is specified */ + return corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: m.Spec.TcpsTlsSecret, + Optional: func() *bool { i := true; return &i }(), + Items: []corev1.KeyToPath{ + { + Key: "tls.crt", // Mount the certificate + Path: "cert.crt", // Mount path inside the container + }, + { + Key: "tls.key", // Mount the private key + Path: "client.key", // Mount path inside the container + }, + }, + }, + } + }(), + }, { + Name: "custom-scripts-vol", + VolumeSource: func() corev1.VolumeSource { + if m.Spec.Persistence.ScriptsVolumeName == "" || m.Spec.Persistence.ScriptsVolumeName == m.Spec.Persistence.DatafilesVolumeName { + return corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{}} + } + /* Persistence.ScriptsVolumeName is specified */ + return corev1.VolumeSource{ + PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{ + ClaimName: m.Name + "-" + m.Spec.Persistence.ScriptsVolumeName, + ReadOnly: false, + }, + } + }(), }}, InitContainers: func() []corev1.Container { initContainers := []corev1.Container{} - if m.Spec.Persistence.Size != "" { + if m.Spec.Persistence.Size != "" && m.Spec.Persistence.SetWritePermissions != nil && *m.Spec.Persistence.SetWritePermissions { initContainers = append(initContainers, corev1.Container{ Name: "init-permissions", Image: m.Spec.Image.PullFrom, @@ -674,30 +713,30 @@ func (r *SingleInstanceDatabaseReconciler) instantiatePodSpec(m *dbapi.SingleIns }, VolumeMounts: []corev1.VolumeMount{{ MountPath: "/opt/oracle/oradata", - Name: "datamount", + Name: "datafiles-vol", }}, }) - if m.Spec.Image.PrebuiltDB { - initContainers = append(initContainers, corev1.Container{ - Name: "init-prebuiltdb", - Image: m.Spec.Image.PullFrom, - Command: []string{"/bin/sh", "-c", dbcommons.InitPrebuiltDbCMD}, - SecurityContext: &corev1.SecurityContext{ - RunAsUser: func() *int64 { i := int64(dbcommons.ORACLE_UID); return &i }(), - RunAsGroup: func() *int64 { i := int64(dbcommons.ORACLE_GUID); return &i }(), - }, - VolumeMounts: []corev1.VolumeMount{{ - MountPath: "/mnt/oradata", - Name: "datamount", - }}, - Env: []corev1.EnvVar{ - { - Name: "ORACLE_SID", - Value: strings.ToUpper(m.Spec.Sid), - }, + } + if m.Spec.Image.PrebuiltDB { + initContainers = append(initContainers, corev1.Container{ + Name: "init-prebuiltdb", + Image: m.Spec.Image.PullFrom, + Command: []string{"/bin/sh", "-c", dbcommons.InitPrebuiltDbCMD}, + SecurityContext: &corev1.SecurityContext{ + RunAsUser: func() *int64 { i := int64(dbcommons.ORACLE_UID); return &i }(), + RunAsGroup: func() *int64 { i := int64(dbcommons.ORACLE_GUID); return &i }(), + }, + VolumeMounts: []corev1.VolumeMount{{ + MountPath: "/mnt/oradata", + Name: "datafiles-vol", + }}, + Env: []corev1.EnvVar{ + { + Name: "ORACLE_SID", + Value: strings.ToUpper(m.Spec.Sid), }, - }) - } + }, + }) } /* Wallet only for edition barring express and free editions, non-prebuiltDB */ if (m.Spec.Edition != "express" && m.Spec.Edition != "free") && !m.Spec.Image.PrebuiltDB { @@ -715,19 +754,19 @@ func (r *SingleInstanceDatabaseReconciler) instantiatePodSpec(m *dbapi.SingleIns }, { Name: "WALLET_DIR", - Value: "/opt/oracle/oradata/dbconfig/$(ORACLE_SID)/.wallet", + Value: "/opt/oracle/oradata/dbconfig/${ORACLE_SID}/.wallet", }, }, Command: []string{"/bin/sh"}, Args: func() []string { edition := "" - if m.Spec.CloneFrom == "" { + if m.Spec.CreateAs != "clone" { edition = m.Spec.Edition if m.Spec.Edition == "" { edition = "enterprise" } } else { - if !dbcommons.IsSourceDatabaseOnCluster(m.Spec.CloneFrom) { + if !dbcommons.IsSourceDatabaseOnCluster(m.Spec.PrimaryDatabaseRef) { edition = m.Spec.Edition } else { edition = n.Spec.Edition @@ -744,7 +783,7 @@ func (r *SingleInstanceDatabaseReconciler) instantiatePodSpec(m *dbapi.SingleIns }, VolumeMounts: []corev1.VolumeMount{{ MountPath: "/opt/oracle/oradata", - Name: "datamount", + Name: "datafiles-vol", }}, }) } @@ -753,42 +792,75 @@ func (r *SingleInstanceDatabaseReconciler) instantiatePodSpec(m *dbapi.SingleIns Containers: []corev1.Container{{ Name: m.Name, Image: m.Spec.Image.PullFrom, + SecurityContext: &corev1.SecurityContext{ + Capabilities: &corev1.Capabilities{ + // Allow priority elevation for DB processes + Add: []corev1.Capability{"SYS_NICE"}, + }, + }, Lifecycle: &corev1.Lifecycle{ PreStop: &corev1.LifecycleHandler{ Exec: &corev1.ExecAction{ - Command: []string{"/bin/sh", "-c", "/bin/echo -en 'shutdown abort;\n' | env ORACLE_SID=${ORACLE_SID^^} sqlplus -S / as sysdba"}, + Command: func() []string { + // For patching use cases shutdown immediate is needed especially for standby databases + shutdown_mode := "immediate" + if m.Spec.Edition == "express" || m.Spec.Edition == "free" { + // express/free do not support patching + // To terminate any zombie instances left over due to forced termination + shutdown_mode = "abort" + } + return []string{"/bin/sh", "-c", "/bin/echo -en 'shutdown " + shutdown_mode + ";\n' | env ORACLE_SID=${ORACLE_SID^^} sqlplus -S / as sysdba"} + }(), }, }, }, Ports: []corev1.ContainerPort{{ContainerPort: dbcommons.CONTAINER_LISTENER_PORT}, {ContainerPort: 5500}}, - ReadinessProbe: &corev1.Probe{ - ProbeHandler: corev1.ProbeHandler{ - Exec: &corev1.ExecAction{ - Command: []string{"/bin/sh", "-c", "if [ -f $ORACLE_BASE/checkDBLockStatus.sh ]; then $ORACLE_BASE/checkDBLockStatus.sh ; else $ORACLE_BASE/checkDBStatus.sh; fi "}, - }, - }, - InitialDelaySeconds: 20, - TimeoutSeconds: 20, - PeriodSeconds: func() int32 { - if m.Spec.ReadinessCheckPeriod > 0 { - return int32(m.Spec.ReadinessCheckPeriod) + ReadinessProbe: func() *corev1.Probe { + if m.Spec.CreateAs == "primary" { + return &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"/bin/sh", "-c", "if [ -f $ORACLE_BASE/checkDBLockStatus.sh ]; then $ORACLE_BASE/checkDBLockStatus.sh ; else $ORACLE_BASE/checkDBStatus.sh; fi "}, + }, + }, + InitialDelaySeconds: 20, + TimeoutSeconds: 20, + PeriodSeconds: func() int32 { + if m.Spec.ReadinessCheckPeriod > 0 { + return int32(m.Spec.ReadinessCheckPeriod) + } + return 60 + }(), } - return 60 - }(), - }, - + } else { + return &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"/bin/sh", "-c", "if [ -f $ORACLE_BASE/oradata/.$ORACLE_SID$CHECKPOINT_FILE_EXTN ]; then if [ -f $ORACLE_BASE/checkDBLockStatus.sh ]; then $ORACLE_BASE/checkDBLockStatus.sh ; else $ORACLE_BASE/checkDBStatus.sh; fi else true; fi "}, + }, + }, + InitialDelaySeconds: 0, + TimeoutSeconds: 20, + PeriodSeconds: func() int32 { + if m.Spec.ReadinessCheckPeriod > 0 { + return int32(m.Spec.ReadinessCheckPeriod) + } + return 60 + }(), + } + } + }(), VolumeMounts: func() []corev1.VolumeMount { mounts := []corev1.VolumeMount{} if m.Spec.Persistence.Size != "" { mounts = append(mounts, corev1.VolumeMount{ MountPath: "/opt/oracle/oradata", - Name: "datamount", + Name: "datafiles-vol", }) } if m.Spec.Edition == "express" || m.Spec.Edition == "free" || m.Spec.Image.PrebuiltDB { - // mounts pwd as secrets for express edition - // or prebuilt db + // mounts pwd as secrets for express edition or prebuilt db mounts = append(mounts, corev1.VolumeMount{ MountPath: "/run/secrets/oracle_pwd", ReadOnly: true, @@ -796,6 +868,39 @@ func (r *SingleInstanceDatabaseReconciler) instantiatePodSpec(m *dbapi.SingleIns SubPath: "oracle_pwd", }) } + if m.Spec.TcpsTlsSecret != "" { + mounts = append(mounts, corev1.VolumeMount{ + MountPath: dbcommons.TlsCertsLocation, + ReadOnly: true, + Name: "tls-secret-vol", + }) + } + if m.Spec.Persistence.ScriptsVolumeName != "" { + mounts = append(mounts, corev1.VolumeMount{ + MountPath: "/opt/oracle/scripts/startup/", + ReadOnly: true, + Name: func() string { + if m.Spec.Persistence.ScriptsVolumeName != m.Spec.Persistence.DatafilesVolumeName { + return "custom-scripts-vol" + } else { + return "datafiles-vol" + } + }(), + SubPath: "startup", + }) + mounts = append(mounts, corev1.VolumeMount{ + MountPath: "/opt/oracle/scripts/setup/", + ReadOnly: true, + Name: func() string { + if m.Spec.Persistence.ScriptsVolumeName != m.Spec.Persistence.DatafilesVolumeName { + return "custom-scripts-vol" + } else { + return "datafiles-vol" + } + }(), + SubPath: "setup", + }) + } return mounts }(), Env: func() []corev1.EnvVar { @@ -820,7 +925,7 @@ func (r *SingleInstanceDatabaseReconciler) instantiatePodSpec(m *dbapi.SingleIns }, } } - if m.Spec.CloneFrom != "" { + if m.Spec.CreateAs == "clone" { // Clone DB use-case return []corev1.EnvVar{ { @@ -837,25 +942,18 @@ func (r *SingleInstanceDatabaseReconciler) instantiatePodSpec(m *dbapi.SingleIns }, { Name: "WALLET_DIR", - Value: "/opt/oracle/oradata/dbconfig/$(ORACLE_SID)/.wallet", + Value: "/opt/oracle/oradata/dbconfig/${ORACLE_SID}/.wallet", }, { Name: "PRIMARY_DB_CONN_STR", Value: func() string { - if dbcommons.IsSourceDatabaseOnCluster(m.Spec.CloneFrom) { + if dbcommons.IsSourceDatabaseOnCluster(m.Spec.PrimaryDatabaseRef) { return n.Name + ":" + strconv.Itoa(int(dbcommons.CONTAINER_LISTENER_PORT)) + "/" + n.Spec.Sid } - return m.Spec.CloneFrom + return m.Spec.PrimaryDatabaseRef }(), }, - { - Name: "ORACLE_HOSTNAME", - ValueFrom: &corev1.EnvVarSource{ - FieldRef: &corev1.ObjectFieldSelector{ - FieldPath: "status.podIP", - }, - }, - }, + CreateOracleHostnameEnvVarObj(m, n), { Name: "CLONE_DB", Value: "true", @@ -866,7 +964,7 @@ func (r *SingleInstanceDatabaseReconciler) instantiatePodSpec(m *dbapi.SingleIns }, } - } else if m.Spec.PrimaryDatabaseRef != "" && m.Spec.CreateAsStandby { + } else if m.Spec.CreateAs == "standby" { //Standby DB Usecase return []corev1.EnvVar{ { @@ -883,7 +981,7 @@ func (r *SingleInstanceDatabaseReconciler) instantiatePodSpec(m *dbapi.SingleIns }, { Name: "WALLET_DIR", - Value: "/opt/oracle/oradata/dbconfig/$(ORACLE_SID)/.wallet", + Value: "/opt/oracle/oradata/dbconfig/${ORACLE_SID}/.wallet", }, { Name: "PRIMARY_DB_CONN_STR", @@ -958,7 +1056,7 @@ func (r *SingleInstanceDatabaseReconciler) instantiatePodSpec(m *dbapi.SingleIns if m.Spec.Image.PrebuiltDB { return "" // No wallets for prebuilt DB } - return "/opt/oracle/oradata/dbconfig/$(ORACLE_SID)/.wallet" + return "/opt/oracle/oradata/dbconfig/${ORACLE_SID}/.wallet" }(), }, { @@ -976,7 +1074,7 @@ func (r *SingleInstanceDatabaseReconciler) instantiatePodSpec(m *dbapi.SingleIns { Name: "INIT_SGA_SIZE", Value: func() string { - if m.Spec.InitParams.SgaTarget > 0 && m.Spec.InitParams.PgaAggregateTarget > 0 { + if m.Spec.InitParams != nil && m.Spec.InitParams.SgaTarget > 0 && m.Spec.InitParams.PgaAggregateTarget > 0 { return strconv.Itoa(m.Spec.InitParams.SgaTarget) } return "" @@ -985,7 +1083,7 @@ func (r *SingleInstanceDatabaseReconciler) instantiatePodSpec(m *dbapi.SingleIns { Name: "INIT_PGA_SIZE", Value: func() string { - if m.Spec.InitParams.SgaTarget > 0 && m.Spec.InitParams.PgaAggregateTarget > 0 { + if m.Spec.InitParams != nil && m.Spec.InitParams.SgaTarget > 0 && m.Spec.InitParams.PgaAggregateTarget > 0 { return strconv.Itoa(m.Spec.InitParams.SgaTarget) } return "" @@ -998,6 +1096,38 @@ func (r *SingleInstanceDatabaseReconciler) instantiatePodSpec(m *dbapi.SingleIns } }(), + + Resources: func() corev1.ResourceRequirements { + if m.Spec.Resources.Requests != nil && m.Spec.Resources.Limits != nil { + return corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + "cpu": resource.MustParse(m.Spec.Resources.Requests.Cpu), + "memory": resource.MustParse(m.Spec.Resources.Requests.Memory), + }, + Limits: corev1.ResourceList{ + "cpu": resource.MustParse(m.Spec.Resources.Limits.Cpu), + "memory": resource.MustParse(m.Spec.Resources.Requests.Memory), + }, + } + } else if m.Spec.Resources.Requests != nil { + return corev1.ResourceRequirements{ + Requests: corev1.ResourceList{ + "cpu": resource.MustParse(m.Spec.Resources.Requests.Cpu), + "memory": resource.MustParse(m.Spec.Resources.Requests.Memory), + }, + } + } else if m.Spec.Resources.Limits != nil { + return corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + "cpu": resource.MustParse(m.Spec.Resources.Limits.Cpu), + "memory": resource.MustParse(m.Spec.Resources.Requests.Memory), + }, + } + } else { + return corev1.ResourceRequirements{} + } + + }(), }}, TerminationGracePeriodSeconds: func() *int64 { i := int64(30); return &i }(), @@ -1031,11 +1161,12 @@ func (r *SingleInstanceDatabaseReconciler) instantiatePodSpec(m *dbapi.SingleIns Name: m.Spec.Image.PullSecrets, }, }, + ServiceAccountName: m.Spec.ServiceAccountName, }, } // Adding pod anti-affinity for standby cases - if m.Spec.PrimaryDatabaseRef != "" && m.Spec.CreateAsStandby { + if m.Spec.CreateAs == "standby" { weightedPodAffinityTerm := corev1.WeightedPodAffinityTerm{ Weight: 100, PodAffinityTerm: corev1.PodAffinityTerm{ @@ -1142,14 +1273,14 @@ func (r *SingleInstanceDatabaseReconciler) instantiatePVCSpec(m *dbapi.SingleIns accessMode = append(accessMode, corev1.PersistentVolumeAccessMode(m.Spec.Persistence.AccessMode)) return accessMode }(), - Resources: corev1.ResourceRequirements{ + Resources: corev1.VolumeResourceRequirements{ Requests: map[corev1.ResourceName]resource.Quantity{ // Requests describes the minimum amount of compute resources required "storage": resource.MustParse(m.Spec.Persistence.Size), }, }, StorageClassName: &m.Spec.Persistence.StorageClass, - VolumeName: m.Spec.Persistence.VolumeName, + VolumeName: m.Spec.Persistence.DatafilesVolumeName, Selector: func() *metav1.LabelSelector { if m.Spec.Persistence.StorageClass != "oci" { return nil @@ -1175,34 +1306,152 @@ func (r *SingleInstanceDatabaseReconciler) instantiatePVCSpec(m *dbapi.SingleIns // ############################################################################# // -// Stake a claim for Persistent Volume +// Stake a claim for Persistent Volume for customScript Volume +// +// ############################################################################# + +func (r *SingleInstanceDatabaseReconciler) createOrReplacePVCforCustomScriptsVol(ctx context.Context, req ctrl.Request, + m *dbapi.SingleInstanceDatabase) (ctrl.Result, error) { + + log := r.Log.WithValues("createPVC CustomScripts Vol", req.NamespacedName) + + // if customScriptsVolumeName is not present or it is same than DatafilesVolumeName + if m.Spec.Persistence.ScriptsVolumeName == "" || m.Spec.Persistence.ScriptsVolumeName == m.Spec.Persistence.DatafilesVolumeName { + return requeueN, nil + } + + pvcDeleted := false + pvcName := string(m.Name) + "-" + string(m.Spec.Persistence.ScriptsVolumeName) + // Check if the PVC already exists using r.Get, if not create a new one using r.Create + pvc := &corev1.PersistentVolumeClaim{} + // Get retrieves an obj ( a struct pointer ) for the given object key from the Kubernetes Cluster. + err := r.Get(ctx, types.NamespacedName{Name: pvcName, Namespace: m.Namespace}, pvc) + + if err == nil { + if m.Spec.Persistence.ScriptsVolumeName != "" && pvc.Spec.VolumeName != m.Spec.Persistence.ScriptsVolumeName { + // call deletePods() with zero pods in avaiable and nil readyPod to delete all pods + result, err := r.deletePods(ctx, req, m, []corev1.Pod{}, corev1.Pod{}, 0, 0) + if result.Requeue { + return result, err + } + + log.Info("Deleting PVC", " name ", pvc.Name) + err = r.Delete(ctx, pvc) + if err != nil { + r.Log.Error(err, "Failed to delete Pvc", "Pvc.Name", pvc.Name) + return requeueN, err + } + pvcDeleted = true + } else { + log.Info("Found Existing PVC", "Name", pvc.Name) + return requeueN, nil + } + } + if pvcDeleted || err != nil && apierrors.IsNotFound(err) { + // Define a new PVC + + // get accessMode and storage of pv mentioned to be used in pvc spec + pv := &corev1.PersistentVolume{} + pvName := m.Spec.Persistence.ScriptsVolumeName + // Get retrieves an obj ( a struct pointer ) for the given object key from the Kubernetes Cluster. + pvErr := r.Get(ctx, types.NamespacedName{Name: pvName, Namespace: m.Namespace}, pv) + if pvErr != nil { + log.Error(pvErr, "Failed to get PV") + return requeueY, pvErr + } + + volumeQty := pv.Spec.Capacity[corev1.ResourceStorage] + + AccessMode := pv.Spec.AccessModes[0] + Storage := int(volumeQty.Value()) + StorageClass := "" + + log.Info(fmt.Sprintf("PV storage: %v\n", Storage)) + log.Info(fmt.Sprintf("PV AccessMode: %v\n", AccessMode)) + + pvc := &corev1.PersistentVolumeClaim{ + TypeMeta: metav1.TypeMeta{ + Kind: "PersistentVolumeClaim", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: pvcName, + Namespace: m.Namespace, + Labels: map[string]string{ + "app": m.Name, + }, + }, + Spec: corev1.PersistentVolumeClaimSpec{ + AccessModes: func() []corev1.PersistentVolumeAccessMode { + var accessMode []corev1.PersistentVolumeAccessMode + accessMode = append(accessMode, corev1.PersistentVolumeAccessMode(AccessMode)) + return accessMode + }(), + Resources: corev1.VolumeResourceRequirements{ + Requests: map[corev1.ResourceName]resource.Quantity{ + // Requests describes the minimum amount of compute resources required + "storage": *resource.NewQuantity(int64(Storage), resource.BinarySI), + }, + }, + StorageClassName: &StorageClass, + VolumeName: pvName, + }, + } + + // Set SingleInstanceDatabase instance as the owner and controller + ctrl.SetControllerReference(m, pvc, r.Scheme) + + log.Info("Creating a new PVC", "PVC.Namespace", pvc.Namespace, "PVC.Name", pvc.Name) + err = r.Create(ctx, pvc) + if err != nil { + log.Error(err, "Failed to create new PVC", "PVC.Namespace", pvc.Namespace, "PVC.Name", pvc.Name) + return requeueY, err + } + return requeueN, nil + } else if err != nil { + log.Error(err, "Failed to get PVC") + return requeueY, err + } + + return requeueN, nil +} + +// ############################################################################# +// +// Stake a claim for Persistent Volume for Datafiles Volume // // ############################################################################# -func (r *SingleInstanceDatabaseReconciler) createOrReplacePVC(ctx context.Context, req ctrl.Request, +func (r *SingleInstanceDatabaseReconciler) createOrReplacePVCforDatafilesVol(ctx context.Context, req ctrl.Request, m *dbapi.SingleInstanceDatabase) (ctrl.Result, error) { + log := r.Log.WithValues("createPVC Datafiles-Vol", req.NamespacedName) + // Don't create PVC if persistence is not chosen if m.Spec.Persistence.Size == "" { return requeueN, nil } - log := r.Log.WithValues("createPVC", req.NamespacedName) pvcDeleted := false // Check if the PVC already exists using r.Get, if not create a new one using r.Create pvc := &corev1.PersistentVolumeClaim{} // Get retrieves an obj ( a struct pointer ) for the given object key from the Kubernetes Cluster. err := r.Get(ctx, types.NamespacedName{Name: m.Name, Namespace: m.Namespace}, pvc) + if err == nil { if *pvc.Spec.StorageClassName != m.Spec.Persistence.StorageClass || - pvc.Spec.Resources.Requests["storage"] != resource.MustParse(m.Spec.Persistence.Size) || - (m.Spec.Persistence.VolumeName != "" && pvc.Spec.VolumeName != m.Spec.Persistence.VolumeName) || + (m.Spec.Persistence.DatafilesVolumeName != "" && pvc.Spec.VolumeName != m.Spec.Persistence.DatafilesVolumeName) || pvc.Spec.AccessModes[0] != corev1.PersistentVolumeAccessMode(m.Spec.Persistence.AccessMode) { - // call deletePods() with zero pods in avaiable and nil readyPod to delete all pods + // PV change use cases which would trigger recreation of SIDB pods are :- + // 1. Change in storage class + // 2. Change in volume name + // 3. Change in volume access mode + + // deleting singleinstancedatabase resource result, err := r.deletePods(ctx, req, m, []corev1.Pod{}, corev1.Pod{}, 0, 0) if result.Requeue { return result, err } + // deleting persistent volume claim log.Info("Deleting PVC", " name ", pvc.Name) err = r.Delete(ctx, pvc) if err != nil { @@ -1210,11 +1459,52 @@ func (r *SingleInstanceDatabaseReconciler) createOrReplacePVC(ctx context.Contex return requeueN, err } pvcDeleted = true + + } else if pvc.Spec.Resources.Requests["storage"] != resource.MustParse(m.Spec.Persistence.Size) { + // check the storage class of the pvc + // if the storage class doesn't support resize the throw an error event and try expanding via deleting and recreating the pv and pods + if pvc.Spec.StorageClassName == nil || *pvc.Spec.StorageClassName == "" { + r.Recorder.Eventf(m, corev1.EventTypeWarning, "PVC not resizable", "Cannot resize pvc as storage class is either nil or default") + return requeueN, fmt.Errorf("cannot resize pvc as storage class is either nil or default") + } + + storageClassName := *pvc.Spec.StorageClassName + storageClass := &storagev1.StorageClass{} + err := r.Get(ctx, types.NamespacedName{Name: storageClassName}, storageClass) + if err != nil { + return requeueY, fmt.Errorf("error while fetching the storage class") + } + + if storageClass.AllowVolumeExpansion == nil || !*storageClass.AllowVolumeExpansion { + r.Recorder.Eventf(m, corev1.EventTypeWarning, "PVC not resizable", "The storage class doesn't support volume expansion") + return requeueN, fmt.Errorf("the storage class %s doesn't support volume expansion", storageClassName) + } + + newPVCSize := resource.MustParse(m.Spec.Persistence.Size) + newPVCSizeAdd := &newPVCSize + if newPVCSizeAdd.Cmp(pvc.Spec.Resources.Requests["storage"]) < 0 { + r.Recorder.Eventf(m, corev1.EventTypeWarning, "Cannot Resize PVC", "Forbidden: field can not be less than previous value") + return requeueN, fmt.Errorf("Resizing PVC to lower size volume not allowed") + } + + // Expanding the persistent volume claim + pvc.Spec.Resources.Requests["storage"] = resource.MustParse(m.Spec.Persistence.Size) + log.Info("Updating PVC", "pvc", pvc.Name, "volume", pvc.Spec.VolumeName) + r.Recorder.Eventf(m, corev1.EventTypeNormal, "Updating PVC - volume expansion", "Resizing the pvc for storage expansion") + err = r.Update(ctx, pvc) + if err != nil { + log.Error(err, "Error while updating the PVCs") + return requeueY, fmt.Errorf("error while updating the PVCs") + } + } else { + log.Info("Found Existing PVC", "Name", pvc.Name) return requeueN, nil + } } + if pvcDeleted || err != nil && apierrors.IsNotFound(err) { // Define a new PVC pvc = r.instantiatePVCSpec(m) @@ -1494,17 +1784,27 @@ func (r *SingleInstanceDatabaseReconciler) createOrReplaceSVC(ctx context.Contex extSvc = svc } - pdbName := strings.ToUpper(m.Spec.Pdbname) - sid := m.Spec.Sid + var sid, pdbName string + var getSidPdbEditionErr error if m.Spec.Image.PrebuiltDB { - edition := "" - sid, pdbName, edition = dbcommons.GetSidPdbEdition(r, r.Config, ctx, req) - if sid == "" || pdbName == "" || edition == "" { + r.Log.Info("Initiliazing database sid, pdb, edition for prebuilt database") + var edition string + sid, pdbName, edition, getSidPdbEditionErr = dbcommons.GetSidPdbEdition(r, r.Config, ctx, ctrl.Request{NamespacedName: types.NamespacedName{Namespace: m.Namespace, Name: m.Name}}) + if errors.Is(getSidPdbEditionErr, dbcommons.ErrNoReadyPod) { return requeueN, nil } + if getSidPdbEditionErr != nil { + return requeueY, getSidPdbEditionErr + } + r.Log.Info(fmt.Sprintf("Prebuilt database: %s has SID : %s, PDB : %s, EDITION: %s", m.Name, sid, pdbName, edition)) m.Status.Edition = cases.Title(language.English).String(edition) } - + if sid == "" { + sid = strings.ToUpper(m.Spec.Sid) + } + if pdbName == "" { + pdbName = strings.ToUpper(m.Spec.Pdbname) + } if m.Spec.LoadBalancer { m.Status.ClusterConnectString = extSvc.Name + "." + extSvc.Namespace + ":" + fmt.Sprint(extSvc.Spec.Ports[1].Port) + "/" + strings.ToUpper(sid) if len(extSvc.Status.LoadBalancer.Ingress) > 0 { @@ -1792,7 +2092,7 @@ func (r *SingleInstanceDatabaseReconciler) createWallet(m *dbapi.SingleInstanceD return requeueY, nil } - if m.Spec.CloneFrom == "" && m.Spec.Edition != "express" { + if m.Spec.CreateAs != "clone" && m.Spec.Edition != "express" { //Check if Edition of m.Spec.Sid is same as m.Spec.Edition getEditionFile := dbcommons.GetEnterpriseEditionFileCMD eventReason := m.Spec.Sid + " is a enterprise edition" @@ -1976,107 +2276,96 @@ func (r *SingleInstanceDatabaseReconciler) deletePods(ctx context.Context, req c // ValidateDBReadiness and return the ready POD // // ############################################################################# -func (r *SingleInstanceDatabaseReconciler) validateDBReadiness(m *dbapi.SingleInstanceDatabase, +func (r *SingleInstanceDatabaseReconciler) validateDBReadiness(sidb *dbapi.SingleInstanceDatabase, ctx context.Context, req ctrl.Request) (ctrl.Result, corev1.Pod, error) { - readyPod, _, available, _, err := dbcommons.FindPods(r, m.Spec.Image.Version, - m.Spec.Image.PullFrom, m.Name, m.Namespace, ctx, req) + log := r.Log.WithValues("validateDBReadiness", req.NamespacedName) + + log.Info("Validating readiness for database") + + sidbReadyPod, _, available, _, err := dbcommons.FindPods(r, sidb.Spec.Image.Version, + sidb.Spec.Image.PullFrom, sidb.Name, sidb.Namespace, ctx, req) if err != nil { r.Log.Error(err, err.Error()) - return requeueY, readyPod, err + return requeueY, sidbReadyPod, err } - if readyPod.Name == "" { - m.Status.Status = dbcommons.StatusPending + + if sidbReadyPod.Name == "" { + sidb.Status.Status = dbcommons.StatusPending + log.Info("no pod currently in ready state") if ok, _ := dbcommons.IsAnyPodWithStatus(available, corev1.PodFailed); ok { eventReason := "Database Failed" eventMsg := "pod creation failed" - r.Recorder.Eventf(m, corev1.EventTypeNormal, eventReason, eventMsg) - } else if ok, runningPod := dbcommons.IsAnyPodWithStatus(available, corev1.PodRunning); ok { - r.Log.Info("Database Creating...", "Name", m.Name) - m.Status.Status = dbcommons.StatusCreating - if m.Spec.CloneFrom != "" { - // Required since clone creates the datafiles under primary database SID folder - r.Log.Info("Creating the SID directory link for clone database", "name", m.Spec.Sid) - _, err := dbcommons.ExecCommand(r, r.Config, runningPod.Name, runningPod.Namespace, "", - ctx, req, false, "bash", "-c", dbcommons.CreateSIDlinkCMD) - if err != nil { - r.Log.Info(err.Error()) - } - } - out, err := dbcommons.ExecCommand(r, r.Config, runningPod.Name, runningPod.Namespace, "", + r.Recorder.Eventf(sidb, corev1.EventTypeNormal, eventReason, eventMsg) + } else if ok, _ := dbcommons.IsAnyPodWithStatus(available, corev1.PodRunning); ok { + + out, err := dbcommons.ExecCommand(r, r.Config, available[0].Name, sidb.Namespace, "", ctx, req, false, "bash", "-c", dbcommons.GetCheckpointFileCMD) if err != nil { r.Log.Info(err.Error()) } - r.Log.Info("GetCheckpointFileCMD Output : \n" + out) if out != "" { + log.Info("Database initialzied") eventReason := "Database Unhealthy" eventMsg := "datafiles exists" - r.Recorder.Eventf(m, corev1.EventTypeNormal, eventReason, eventMsg) - m.Status.DatafilesCreated = "true" - m.Status.Status = dbcommons.StatusNotReady - r.updateORDSStatus(m, ctx, req) + r.Recorder.Eventf(sidb, corev1.EventTypeNormal, eventReason, eventMsg) + sidb.Status.DatafilesCreated = "true" + sidb.Status.Status = dbcommons.StatusNotReady + r.updateORDSStatus(sidb, ctx, req) + } else { + log.Info("Database Creating....", "Name", sidb.Name) + sidb.Status.Status = dbcommons.StatusCreating } } else { - r.Log.Info("Database Pending...", "Name", m.Name) + log.Info("Database Pending....", "Name", sidb.Name) } - - // As No pod is ready now , turn on mode when pod is ready . so requeue the request - return requeueY, readyPod, errors.New("no pod is ready currently") + log.Info("no pod currently in ready state") + return requeueY, sidbReadyPod, nil } - available = append(available, readyPod) - podNamesFinal := dbcommons.GetPodNames(available) - r.Log.Info("Final "+m.Name+" Pods After Deleting (or) Adding Extra Pods ( Including The Ready Pod ) ", "Pod Names", podNamesFinal) - r.Log.Info(m.Name+" Replicas Available", "Count", len(podNamesFinal)) - r.Log.Info(m.Name+" Replicas Required", "Count", m.Spec.Replicas) - - eventReason := "Database Ready" - eventMsg := "database open on pod " + readyPod.Name + " scheduled on node " + readyPod.Status.HostIP - r.Recorder.Eventf(m, corev1.EventTypeNormal, eventReason, eventMsg) - - m.Status.DatafilesCreated = "true" - - // DB is ready, fetch and update other info - out, err := dbcommons.GetDatabaseRole(readyPod, r, r.Config, ctx, req, m.Spec.Edition) - if err == nil { - m.Status.Role = strings.ToUpper(out) - } - version, out, err := dbcommons.GetDatabaseVersion(readyPod, r, r.Config, ctx, req, m.Spec.Edition) - if err == nil { - if !strings.Contains(out, "ORA-") { - m.Status.ReleaseUpdate = version + if sidb.Spec.CreateAs == "clone" { + // Required since clone creates the datafiles under primary database SID folder + r.Log.Info("Creating the SID directory link for clone database", "name", sidb.Spec.Sid) + _, err := dbcommons.ExecCommand(r, r.Config, sidbReadyPod.Name, sidbReadyPod.Namespace, "", + ctx, req, false, "bash", "-c", dbcommons.CreateSIDlinkCMD) + if err != nil { + r.Log.Info(err.Error()) } } - dbMajorVersion, err := strconv.Atoi(strings.Split(m.Status.ReleaseUpdate, ".")[0]) + + version, err := dbcommons.GetDatabaseVersion(sidbReadyPod, r, r.Config, ctx, req) + if err != nil { + return requeueY, sidbReadyPod, err + } + dbMajorVersion, err := strconv.Atoi(strings.Split(version, ".")[0]) if err != nil { r.Log.Error(err, err.Error()) - return requeueY, readyPod, err + return requeueY, sidbReadyPod, err } r.Log.Info("DB Major Version is " + strconv.Itoa(dbMajorVersion)) // Validating that free edition of the database is only supported from database 23c onwards - if m.Spec.Edition == "free" && dbMajorVersion < 23 { + if sidb.Spec.Edition == "free" && dbMajorVersion < 23 { errMsg := "the Oracle Database Free is only available from version 23c onwards" - r.Recorder.Eventf(m, corev1.EventTypeWarning, "Spec Error", errMsg) - m.Status.Status = dbcommons.StatusError - return requeueN, readyPod, errors.New(errMsg) - } - // Checking if OEM is supported in the provided Database version - if dbMajorVersion >= 23 { - m.Status.OemExpressUrl = dbcommons.ValueUnavailable - } else { - m.Status.OemExpressUrl = oemExpressUrl + r.Recorder.Eventf(sidb, corev1.EventTypeWarning, "Spec Error", errMsg) + sidb.Status.Status = dbcommons.StatusError + return requeueY, sidbReadyPod, errors.New(errMsg) } - if strings.ToUpper(m.Status.Role) == "PRIMARY" && m.Status.DatafilesPatched != "true" { - eventReason := "Datapatch Pending" - eventMsg := "datapatch execution pending" - r.Recorder.Eventf(m, corev1.EventTypeNormal, eventReason, eventMsg) - } + available = append(available, sidbReadyPod) + podNamesFinal := dbcommons.GetPodNames(available) + r.Log.Info("Final "+sidb.Name+" Pods After Deleting (or) Adding Extra Pods ( Including The Ready Pod ) ", "Pod Names", podNamesFinal) + r.Log.Info(sidb.Name+" Replicas Available", "Count", len(podNamesFinal)) + r.Log.Info(sidb.Name+" Replicas Required", "Count", sidb.Spec.Replicas) + + eventReason := "Database Ready" + eventMsg := "database open on pod " + sidbReadyPod.Name + " scheduled on node " + sidbReadyPod.Status.HostIP + r.Recorder.Eventf(sidb, corev1.EventTypeNormal, eventReason, eventMsg) - return requeueN, readyPod, nil + sidb.Status.CreatedAs = sidb.Spec.CreateAs + + return requeueN, sidbReadyPod, nil } @@ -2183,20 +2472,56 @@ func (r *SingleInstanceDatabaseReconciler) updateClientWallet(m *dbapi.SingleIns func (r *SingleInstanceDatabaseReconciler) configTcps(m *dbapi.SingleInstanceDatabase, readyPod corev1.Pod, ctx context.Context, req ctrl.Request) (ctrl.Result, error) { eventReason := "Configuring TCPS" - if m.Spec.EnableTCPS && !m.Status.IsTcpsEnabled { - // Enable TCPS - m.Status.Status = dbcommons.StatusUpdating + + if (m.Spec.EnableTCPS) && + ((!m.Status.IsTcpsEnabled) || // TCPS Enabled from a TCP state + (m.Spec.TcpsTlsSecret != "" && m.Status.TcpsTlsSecret == "") || // TCPS Secret is added in spec + (m.Spec.TcpsTlsSecret == "" && m.Status.TcpsTlsSecret != "") || // TCPS Secret is removed in spec + (m.Spec.TcpsTlsSecret != "" && m.Status.TcpsTlsSecret != "" && m.Spec.TcpsTlsSecret != m.Status.TcpsTlsSecret)) { //TCPS secret is changed + + // Set status to Updating, except when an error has been thrown from configTCPS script + if m.Status.Status != dbcommons.StatusError { + m.Status.Status = dbcommons.StatusUpdating + } r.Status().Update(ctx, m) eventMsg := "Enabling TCPS in the database..." r.Recorder.Eventf(m, corev1.EventTypeNormal, eventReason, eventMsg) + var TcpsCommand = dbcommons.EnableTcpsCMD + if m.Spec.TcpsTlsSecret != "" { // case when tls secret is either added or changed + TcpsCommand = "export TCPS_CERTS_LOCATION=" + dbcommons.TlsCertsLocation + " && " + dbcommons.EnableTcpsCMD + + // Checking for tls-secret mount in pods + out, err := dbcommons.ExecCommand(r, r.Config, readyPod.Name, readyPod.Namespace, "", + ctx, req, false, "bash", "-c", fmt.Sprintf(dbcommons.PodMountsCmd, dbcommons.TlsCertsLocation)) + r.Log.Info("Mount Check Output") + r.Log.Info(out) + if err != nil { + r.Log.Error(err, err.Error()) + return requeueY, nil + } + + if (m.Status.TcpsTlsSecret != "") || // case when TCPS Secret is changed + (!strings.Contains(out, dbcommons.TlsCertsLocation)) { // if mount is not there in pod + // call deletePods() with zero pods in avaiable and nil readyPod to delete all pods + result, err := r.deletePods(ctx, req, m, []corev1.Pod{}, corev1.Pod{}, 0, 0) + if result.Requeue { + return result, err + } + m.Status.TcpsTlsSecret = "" // to avoid reconciled pod deletions, in case of TCPS secret change and it fails + } + } + + // Enable TCPS out, err := dbcommons.ExecCommand(r, r.Config, readyPod.Name, readyPod.Namespace, "", - ctx, req, false, "bash", "-c", dbcommons.EnableTcpsCMD) + ctx, req, false, "bash", "-c", TcpsCommand) if err != nil { r.Log.Error(err, err.Error()) eventMsg = "Error encountered in enabling TCPS!" r.Recorder.Eventf(m, corev1.EventTypeNormal, eventReason, eventMsg) + m.Status.Status = dbcommons.StatusError + r.Status().Update(ctx, m) return requeueY, nil } r.Log.Info("enableTcps Output : \n" + out) @@ -2204,6 +2529,14 @@ func (r *SingleInstanceDatabaseReconciler) configTcps(m *dbapi.SingleInstanceDat m.Status.CertCreationTimestamp = time.Now().Format(time.RFC3339) m.Status.IsTcpsEnabled = true m.Status.ClientWalletLoc = fmt.Sprintf(dbcommons.ClientWalletLocation, m.Spec.Sid) + // m.Spec.TcpsTlsSecret can be empty or non-empty + // Store secret name in case of tls-secret addition or change, otherwise would be "" + if m.Spec.TcpsTlsSecret != "" { + m.Status.TcpsTlsSecret = m.Spec.TcpsTlsSecret + } else { + m.Status.TcpsTlsSecret = "" + } + r.Status().Update(ctx, m) eventMsg = "TCPS Enabled." @@ -2238,6 +2571,8 @@ func (r *SingleInstanceDatabaseReconciler) configTcps(m *dbapi.SingleInstanceDat m.Status.CertCreationTimestamp = "" m.Status.IsTcpsEnabled = false m.Status.ClientWalletLoc = "" + m.Status.TcpsTlsSecret = "" + r.Status().Update(ctx, m) eventMsg = "TCPS Disabled." @@ -2368,26 +2703,49 @@ func (r *SingleInstanceDatabaseReconciler) updateInitParameters(m *dbapi.SingleI readyPod corev1.Pod, ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := r.Log.WithValues("updateInitParameters", req.NamespacedName) - if m.Status.InitParams == m.Spec.InitParams { + if m.Spec.InitParams == nil { + return requeueN, nil + } + if m.Status.InitParams == *m.Spec.InitParams { return requeueN, nil } - out, err := dbcommons.ExecCommand(r, r.Config, readyPod.Name, readyPod.Namespace, "", - ctx, req, false, "bash", "-c", fmt.Sprintf(dbcommons.AlterSgaPgaCpuCMD, m.Spec.InitParams.SgaTarget, - m.Spec.InitParams.PgaAggregateTarget, m.Spec.InitParams.CpuCount, dbcommons.SQLPlusCLI)) - if err != nil { - log.Error(err, err.Error()) - return requeueY, err + if (m.Spec.InitParams.PgaAggregateTarget != 0 && (m.Spec.InitParams.PgaAggregateTarget != m.Status.InitParams.PgaAggregateTarget)) || (m.Spec.InitParams.SgaTarget != 0 && (m.Spec.InitParams.SgaTarget != m.Status.InitParams.SgaTarget)) { + log.Info("Executing alter sga pga command", "pga_size", m.Spec.InitParams.PgaAggregateTarget, "sga_size", m.Spec.InitParams.SgaTarget) + out, err := dbcommons.ExecCommand(r, r.Config, readyPod.Name, readyPod.Namespace, "", + ctx, req, false, "bash", "-c", fmt.Sprintf(dbcommons.AlterSgaPgaCMD, m.Spec.InitParams.SgaTarget, + m.Spec.InitParams.PgaAggregateTarget, dbcommons.SQLPlusCLI)) + if err != nil { + log.Error(err, err.Error()) + return requeueY, err + } + // Notify the user about unsucessfull init-parameter value change + if strings.Contains(out, "ORA-") { + eventReason := "Invalid init-param value" + eventMsg := "Unable to change the init-param as specified. Error log: \n" + out + r.Recorder.Eventf(m, corev1.EventTypeWarning, eventReason, eventMsg) + } + log.Info("AlterSgaPgaCpuCMD Output:" + out) } - // Notify the user about unsucessfull init-parameter value change - if strings.Contains(out, "ORA-") { - eventReason := "Invalid init-param value" - eventMsg := "Unable to change the init-param as specified. Error log: \n" + out - r.Recorder.Eventf(m, corev1.EventTypeWarning, eventReason, eventMsg) + + if (m.Spec.InitParams.CpuCount != 0) && (m.Status.InitParams.CpuCount != m.Spec.InitParams.CpuCount) { + log.Info("Executing alter cpu count command", "cpuCount", m.Spec.InitParams.CpuCount) + out, err := dbcommons.ExecCommand(r, r.Config, readyPod.Name, readyPod.Namespace, "", ctx, req, false, + "bash", "-c", fmt.Sprintf(dbcommons.AlterCpuCountCMD, m.Spec.InitParams.CpuCount, dbcommons.SQLPlusCLI)) + if err != nil { + log.Error(err, err.Error()) + return requeueY, err + } + if strings.Contains(out, "ORA-") { + eventReason := "Invalid init-param value" + eventMsg := "Unable to change the init-param as specified. Error log: \n" + out + r.Recorder.Eventf(m, corev1.EventTypeWarning, eventReason, eventMsg) + } + log.Info("AlterCpuCountCMD Output:" + out) } - log.Info("AlterSgaPgaCpuCMD Output:" + out) - if m.Status.InitParams.Processes != m.Spec.InitParams.Processes { + if (m.Spec.InitParams.Processes != 0) && (m.Status.InitParams.Processes != m.Spec.InitParams.Processes) { + log.Info("Executing alter processes command", "processes", m.Spec.InitParams.Processes) // Altering 'Processes' needs database to be restarted out, err := dbcommons.ExecCommand(r, r.Config, readyPod.Name, readyPod.Namespace, "", ctx, req, false, "bash", "-c", fmt.Sprintf(dbcommons.AlterProcessesCMD, m.Spec.InitParams.Processes, dbcommons.SQLPlusCLI, @@ -2398,16 +2756,6 @@ func (r *SingleInstanceDatabaseReconciler) updateInitParameters(m *dbapi.SingleI } log.Info("AlterProcessesCMD Output:" + out) } - - out, err = dbcommons.ExecCommand(r, r.Config, readyPod.Name, readyPod.Namespace, "", - ctx, req, false, "bash", "-c", fmt.Sprintf(dbcommons.GetInitParamsSQL, dbcommons.SQLPlusCLI)) - if err != nil { - log.Error(err, err.Error()) - return requeueY, err - } - log.Info("GetInitParamsSQL Output:" + out) - - m.Status.InitParams = m.Spec.InitParams return requeueN, nil } @@ -2437,19 +2785,12 @@ func (r *SingleInstanceDatabaseReconciler) updateDBConfig(m *dbapi.SingleInstanc m.Status.Status = dbcommons.StatusNotReady return result, nil } - m.Status.ArchiveLog = strconv.FormatBool(archiveLogStatus) - m.Status.ForceLogging = strconv.FormatBool(forceLoggingStatus) - m.Status.FlashBack = strconv.FormatBool(flashBackStatus) - - log.Info("Flashback", "Status :", flashBackStatus) - log.Info("ArchiveLog", "Status :", archiveLogStatus) - log.Info("ForceLog", "Status :", forceLoggingStatus) //################################################################################################# // TURNING FLASHBACK , ARCHIVELOG , FORCELOGGING TO TRUE //################################################################################################# - if m.Spec.ArchiveLog && !archiveLogStatus { + if m.Spec.ArchiveLog != nil && *m.Spec.ArchiveLog && !archiveLogStatus { out, err := dbcommons.ExecCommand(r, r.Config, readyPod.Name, readyPod.Namespace, "", ctx, req, false, "bash", "-c", dbcommons.CreateDBRecoveryDestCMD) @@ -2480,7 +2821,7 @@ func (r *SingleInstanceDatabaseReconciler) updateDBConfig(m *dbapi.SingleInstanc } - if m.Spec.ForceLogging && !forceLoggingStatus { + if m.Spec.ForceLogging != nil && *m.Spec.ForceLogging && !forceLoggingStatus { out, err := dbcommons.ExecCommand(r, r.Config, readyPod.Name, readyPod.Namespace, "", ctx, req, false, "bash", "-c", fmt.Sprintf("echo -e \"%s\" | %s", dbcommons.ForceLoggingTrueSQL, dbcommons.SQLPlusCLI)) if err != nil { @@ -2491,7 +2832,7 @@ func (r *SingleInstanceDatabaseReconciler) updateDBConfig(m *dbapi.SingleInstanc log.Info(out) } - if m.Spec.FlashBack && !flashBackStatus { + if m.Spec.FlashBack != nil && *m.Spec.FlashBack && !flashBackStatus { _, archiveLogStatus, _, result := dbcommons.CheckDBConfig(readyPod, r, r.Config, ctx, req, m.Spec.Edition) if result.Requeue { m.Status.Status = dbcommons.StatusNotReady @@ -2523,7 +2864,7 @@ func (r *SingleInstanceDatabaseReconciler) updateDBConfig(m *dbapi.SingleInstanc // TURNING FLASHBACK , ARCHIVELOG , FORCELOGGING TO FALSE //################################################################################################# - if !m.Spec.FlashBack && flashBackStatus { + if m.Spec.FlashBack != nil && !*m.Spec.FlashBack && flashBackStatus { out, err := dbcommons.ExecCommand(r, r.Config, readyPod.Name, readyPod.Namespace, "", ctx, req, false, "bash", "-c", fmt.Sprintf("echo -e \"%s\" | %s", dbcommons.FlashBackFalseSQL, dbcommons.SQLPlusCLI)) if err != nil { @@ -2533,7 +2874,7 @@ func (r *SingleInstanceDatabaseReconciler) updateDBConfig(m *dbapi.SingleInstanc log.Info("FlashBackFalse Output") log.Info(out) } - if !m.Spec.ArchiveLog && archiveLogStatus { + if m.Spec.ArchiveLog != nil && !*m.Spec.ArchiveLog && archiveLogStatus { flashBackStatus, _, _, result := dbcommons.CheckDBConfig(readyPod, r, r.Config, ctx, req, m.Spec.Edition) if result.Requeue { m.Status.Status = dbcommons.StatusNotReady @@ -2561,7 +2902,7 @@ func (r *SingleInstanceDatabaseReconciler) updateDBConfig(m *dbapi.SingleInstanc changeArchiveLog = true } } - if !m.Spec.ForceLogging && forceLoggingStatus { + if m.Spec.ForceLogging != nil && !*m.Spec.ForceLogging && forceLoggingStatus { out, err := dbcommons.ExecCommand(r, r.Config, readyPod.Name, readyPod.Namespace, "", ctx, req, false, "bash", "-c", fmt.Sprintf("echo -e \"%s\" | %s", dbcommons.ForceLoggingFalseSQL, dbcommons.SQLPlusCLI)) if err != nil { @@ -2593,26 +2934,112 @@ func (r *SingleInstanceDatabaseReconciler) updateDBConfig(m *dbapi.SingleInstanc // Needs to restart the Non Ready Pods ( Delete old ones and create new ones ) if m.Status.FlashBack == strconv.FormatBool(false) && flashBackStatus { - // call FindPods() to fetch pods all version/images of the same SIDB kind + // // call FindPods() to fetch pods all version/images of the same SIDB kind readyPod, replicasFound, available, _, err := dbcommons.FindPods(r, "", "", m.Name, m.Namespace, ctx, req) if err != nil { log.Error(err, err.Error()) return requeueY, err } - // delete non ready Pods as flashback needs restart of pods + // delete non ready Pods as flashback needs restart of pods to make sure failover works in sidbs with multiple replicas _, err = r.deletePods(ctx, req, m, available, readyPod, replicasFound, 1) - return requeueY, err + if err != nil { + log.Error(err, err.Error()) + return requeueY, err + } + return requeueN, err } m.Status.FlashBack = strconv.FormatBool(flashBackStatus) - if !changeArchiveLog && (flashBackStatus != m.Spec.FlashBack || - archiveLogStatus != m.Spec.ArchiveLog || forceLoggingStatus != m.Spec.ForceLogging) { + if !changeArchiveLog && ((m.Spec.FlashBack != nil && (flashBackStatus != *m.Spec.FlashBack)) || + (m.Spec.ArchiveLog != nil && (archiveLogStatus != *m.Spec.ArchiveLog)) || (m.Spec.ForceLogging != nil && (forceLoggingStatus != *m.Spec.ForceLogging))) { return requeueY, nil } return requeueN, nil } +// ############################################################################# +// +// # Update Single instance database resource status +// +// ############################################################################# +func (r *SingleInstanceDatabaseReconciler) updateSidbStatus(sidb *dbapi.SingleInstanceDatabase, sidbReadyPod corev1.Pod, ctx context.Context, req ctrl.Request) error { + + log := r.Log.WithValues("updateSidbStatus", req.NamespacedName) + + flashBackStatus, archiveLogStatus, forceLoggingStatus, result := dbcommons.CheckDBConfig(sidbReadyPod, r, r.Config, ctx, req, sidb.Spec.Edition) + if result.Requeue { + sidb.Status.Status = dbcommons.StatusNotReady + return fmt.Errorf("could not check the database conifg of %s", sidb.Name) + } + + log.Info("flashBack", "Status :", flashBackStatus, "Reconcile Step : ", "updateSidbStatus") + log.Info("ArchiveLog", "Status :", archiveLogStatus, "Reconcile Step : ", "updateSidbStatus") + log.Info("forceLogging", "Status :", forceLoggingStatus, "Reconcile Step : ", "updateSidbStatus") + + sidb.Status.ArchiveLog = strconv.FormatBool(archiveLogStatus) + sidb.Status.ForceLogging = strconv.FormatBool(forceLoggingStatus) + sidb.Status.FlashBack = strconv.FormatBool(flashBackStatus) + + cpu_count, pga_aggregate_target, processes, sga_target, err := dbcommons.CheckDBInitParams(sidbReadyPod, r, r.Config, ctx, req) + if err != nil { + return err + } + sidbInitParams := dbapi.SingleInstanceDatabaseInitParams{ + SgaTarget: sga_target, + PgaAggregateTarget: pga_aggregate_target, + Processes: processes, + CpuCount: cpu_count, + } + // log.Info("GetInitParamsSQL Output:" + out) + + sidb.Status.InitParams = sidbInitParams + // sidb.Status.InitParams = sidb.Spec.InitParams + + // Get database role and update the status + sidbRole, err := dbcommons.GetDatabaseRole(sidbReadyPod, r, r.Config, ctx, req) + if err != nil { + return err + } + log.Info("Database "+sidb.Name, "Database Role : ", sidbRole) + sidb.Status.Role = sidbRole + + // Get database version and update the status + version, err := dbcommons.GetDatabaseVersion(sidbReadyPod, r, r.Config, ctx, req) + if err != nil { + return err + } + log.Info("Database "+sidb.Name, "Database Version : ", version) + sidb.Status.ReleaseUpdate = version + + dbMajorVersion, err := strconv.Atoi(strings.Split(sidb.Status.ReleaseUpdate, ".")[0]) + if err != nil { + r.Log.Error(err, err.Error()) + return err + } + log.Info("Database "+sidb.Name, "Database Major Version : ", dbMajorVersion) + + // Checking if OEM is supported in the provided Database version + if dbMajorVersion >= 23 { + sidb.Status.OemExpressUrl = dbcommons.ValueUnavailable + } else { + sidb.Status.OemExpressUrl = oemExpressUrl + } + + if sidb.Status.Role == "PRIMARY" && sidb.Status.DatafilesPatched != "true" { + eventReason := "Datapatch Pending" + eventMsg := "datapatch execution pending" + r.Recorder.Eventf(sidb, corev1.EventTypeNormal, eventReason, eventMsg) + } + + // update status to Ready after all operations succeed + sidb.Status.Status = dbcommons.StatusReady + + r.Status().Update(ctx, sidb) + + return nil +} + // ############################################################################# // // Update ORDS Status @@ -2750,8 +3177,11 @@ func (r *SingleInstanceDatabaseReconciler) SetupWithManager(mgr ctrl.Manager) er Complete(r) } -// StandbyDatabase functions -// Primary DB Validation +// ############################################################################# +// +// Check primary database status +// +// ############################################################################# func CheckPrimaryDatabaseStatus(p *dbapi.SingleInstanceDatabase) error { if p.Status.Status != dbcommons.StatusReady { @@ -2760,6 +3190,11 @@ func CheckPrimaryDatabaseStatus(p *dbapi.SingleInstanceDatabase) error { return nil } +// ############################################################################# +// +// Check if refered database is the primary database +// +// ############################################################################# func CheckDatabaseRoleAsPrimary(p *dbapi.SingleInstanceDatabase) error { if strings.ToUpper(p.Status.Role) != "PRIMARY" { @@ -2768,6 +3203,11 @@ func CheckDatabaseRoleAsPrimary(p *dbapi.SingleInstanceDatabase) error { return nil } +// ############################################################################# +// +// Get ready pod for the singleinstancedatabase resource +// +// ############################################################################# func GetDatabaseReadyPod(r client.Reader, d *dbapi.SingleInstanceDatabase, ctx context.Context, req ctrl.Request) (corev1.Pod, error) { dbReadyPod, _, _, _, err := dbcommons.FindPods(r, d.Spec.Image.Version, @@ -2776,6 +3216,11 @@ func GetDatabaseReadyPod(r client.Reader, d *dbapi.SingleInstanceDatabase, ctx c return dbReadyPod, err } +// ############################################################################# +// +// Get admin password for singleinstancedatabase +// +// ############################################################################# func GetDatabaseAdminPassword(r client.Reader, d *dbapi.SingleInstanceDatabase, ctx context.Context) (string, error) { adminPasswordSecret := &corev1.Secret{} @@ -2788,6 +3233,11 @@ func GetDatabaseAdminPassword(r client.Reader, d *dbapi.SingleInstanceDatabase, return adminPassword, nil } +// ############################################################################# +// +// Validate primary singleinstancedatabase admin password +// +// ############################################################################# func ValidatePrimaryDatabaseAdminPassword(r *SingleInstanceDatabaseReconciler, p *dbapi.SingleInstanceDatabase, adminPassword string, ctx context.Context, req ctrl.Request) error { @@ -2814,13 +3264,33 @@ func ValidatePrimaryDatabaseAdminPassword(r *SingleInstanceDatabaseReconciler, p return nil } +// ############################################################################# +// +// Validate refered primary database db params are all enabled +// +// ############################################################################# func ValidateDatabaseConfiguration(p *dbapi.SingleInstanceDatabase) error { + var missingModes []string + if p.Status.ArchiveLog == "false" { + missingModes = append(missingModes, "ArchiveLog") + } + if p.Status.FlashBack == "false" { + missingModes = append(missingModes, "FlashBack") + } + if p.Status.ForceLogging == "false" { + missingModes = append(missingModes, "ForceLogging") + } if p.Status.ArchiveLog == "false" || p.Status.FlashBack == "false" || p.Status.ForceLogging == "false" { - return fmt.Errorf("all of Archivelog, Flashback and ForceLogging modes are not enabled in the primary database %v", p.Name) + return fmt.Errorf("%v modes are not enabled in the primary database %v", strings.Join(missingModes, ","), p.Name) } return nil } +// ############################################################################# +// +// Validate refered primary database for standby sidb creation +// +// ############################################################################# func ValidatePrimaryDatabaseForStandbyCreation(r *SingleInstanceDatabaseReconciler, stdby *dbapi.SingleInstanceDatabase, primary *dbapi.SingleInstanceDatabase, ctx context.Context, req ctrl.Request) error { @@ -2862,7 +3332,7 @@ func ValidatePrimaryDatabaseForStandbyCreation(r *SingleInstanceDatabaseReconcil log.Info(fmt.Sprintf("Validating primary database %s configuration...", primary.Name)) err = ValidateDatabaseConfiguration(primary) if err != nil { - r.Recorder.Eventf(stdby, corev1.EventTypeWarning, "Spec Error", "all of Archivelog, Flashback and ForceLogging modes are not enabled in the primary database "+primary.Name) + r.Recorder.Eventf(stdby, corev1.EventTypeWarning, "Spec Error", err.Error()) stdby.Status.Status = dbcommons.StatusError return err } @@ -2872,7 +3342,11 @@ func ValidatePrimaryDatabaseForStandbyCreation(r *SingleInstanceDatabaseReconcil return nil } -// Primary DB Setup +// ############################################################################# +// +// Get total database pods for singleinstancedatabase +// +// ############################################################################# func GetTotalDatabasePods(r client.Reader, d *dbapi.SingleInstanceDatabase, ctx context.Context, req ctrl.Request) (int, error) { _, totalPods, _, _, err := dbcommons.FindPods(r, d.Spec.Image.Version, d.Spec.Image.PullFrom, d.Name, d.Namespace, ctx, req) @@ -2880,6 +3354,11 @@ func GetTotalDatabasePods(r client.Reader, d *dbapi.SingleInstanceDatabase, ctx return totalPods, err } +// ############################################################################# +// +// Set tns names for primary database for dataguard configuraion +// +// ############################################################################# func SetupTnsNamesPrimaryForDG(r *SingleInstanceDatabaseReconciler, p *dbapi.SingleInstanceDatabase, s *dbapi.SingleInstanceDatabase, primaryReadyPod corev1.Pod, ctx context.Context, req ctrl.Request) error { @@ -2910,6 +3389,11 @@ func SetupTnsNamesPrimaryForDG(r *SingleInstanceDatabaseReconciler, p *dbapi.Sin return nil } +// ############################################################################# +// +// Restarting listners in database +// +// ############################################################################# func RestartListenerInDatabase(r *SingleInstanceDatabaseReconciler, primaryReadyPod corev1.Pod, ctx context.Context, req ctrl.Request) error { r.Log.Info("Restarting listener in the database through pod", "primary database pod name", primaryReadyPod.Name) out, err := dbcommons.ExecCommand(r, r.Config, primaryReadyPod.Name, primaryReadyPod.Namespace, "", @@ -2922,6 +3406,11 @@ func RestartListenerInDatabase(r *SingleInstanceDatabaseReconciler, primaryReady return nil } +// ############################################################################# +// +// Setup primary listener for dataguard configuration +// +// ############################################################################# func SetupListenerPrimaryForDG(r *SingleInstanceDatabaseReconciler, p *dbapi.SingleInstanceDatabase, s *dbapi.SingleInstanceDatabase, primaryReadyPod corev1.Pod, ctx context.Context, req ctrl.Request) error { @@ -2953,10 +3442,15 @@ func SetupListenerPrimaryForDG(r *SingleInstanceDatabaseReconciler, p *dbapi.Sin return nil } +// ############################################################################# +// +// Setup init parameters of primary database for dataguard configuration +// +// ############################################################################# func SetupInitParamsPrimaryForDG(r *SingleInstanceDatabaseReconciler, primaryReadyPod corev1.Pod, ctx context.Context, req ctrl.Request) error { r.Log.Info("Running StandbyDatabasePrerequisitesSQL in the primary database") out, err := dbcommons.ExecCommand(r, r.Config, primaryReadyPod.Name, primaryReadyPod.Namespace, "", ctx, req, false, "bash", "-c", - fmt.Sprintf("echo -e \"%s\" | sqlplus -s / as sysdba", dbcommons.StandbyDatabasePrerequisitesSQL)) + fmt.Sprintf("echo -e \"%s\" | %s", dbcommons.StandbyDatabasePrerequisitesSQL, dbcommons.SQLPlusCLI)) if err != nil { return fmt.Errorf("unable to run StandbyDatabasePrerequisitesSQL in primary database") } @@ -2965,6 +3459,11 @@ func SetupInitParamsPrimaryForDG(r *SingleInstanceDatabaseReconciler, primaryRea return nil } +// ############################################################################# +// +// Setup primary database for standby singleinstancedatabase +// +// ############################################################################# func SetupPrimaryDatabase(r *SingleInstanceDatabaseReconciler, stdby *dbapi.SingleInstanceDatabase, primary *dbapi.SingleInstanceDatabase, ctx context.Context, req ctrl.Request) error { @@ -3006,12 +3505,17 @@ func SetupPrimaryDatabase(r *SingleInstanceDatabaseReconciler, stdby *dbapi.Sing } -// Standby DB Setup +// ############################################################################# +// +// Get all pdbs in a singleinstancedatabase +// +// ############################################################################# func GetAllPdbInDatabase(r *SingleInstanceDatabaseReconciler, dbReadyPod corev1.Pod, ctx context.Context, req ctrl.Request) ([]string, error) { var pdbs []string out, err := dbcommons.ExecCommand(r, r.Config, dbReadyPod.Name, dbReadyPod.Namespace, "", ctx, req, false, "bash", "-c", fmt.Sprintf("echo -e \"%s\" | sqlplus -s / as sysdba", dbcommons.GetPdbsSQL)) if err != nil { + r.Log.Error(err, err.Error()) return pdbs, err } r.Log.Info("GetPdbsSQL Output") @@ -3021,6 +3525,11 @@ func GetAllPdbInDatabase(r *SingleInstanceDatabaseReconciler, dbReadyPod corev1. return pdbs, nil } +// ############################################################################# +// +// Setup tnsnames.ora for all the pdb list in the singleinstancedatabase +// +// ############################################################################# func SetupTnsNamesForPDBListInDatabase(r *SingleInstanceDatabaseReconciler, d *dbapi.SingleInstanceDatabase, dbReadyPod corev1.Pod, ctx context.Context, req ctrl.Request, pdbList []string) error { for _, pdb := range pdbList { @@ -3058,6 +3567,11 @@ func SetupTnsNamesForPDBListInDatabase(r *SingleInstanceDatabaseReconciler, d *d return nil } +// ############################################################################# +// +// Setup tnsnames.ora in standby database for primary singleinstancedatabase +// +// ############################################################################# func SetupPrimaryDBTnsNamesInStandby(r *SingleInstanceDatabaseReconciler, s *dbapi.SingleInstanceDatabase, dbReadyPod corev1.Pod, ctx context.Context, req ctrl.Request) error { @@ -3072,6 +3586,11 @@ func SetupPrimaryDBTnsNamesInStandby(r *SingleInstanceDatabaseReconciler, s *dba return nil } +// ############################################################################# +// +// Enabling flashback in singleinstancedatabase +// +// ############################################################################# func EnableFlashbackInDatabase(r *SingleInstanceDatabaseReconciler, dbReadyPod corev1.Pod, ctx context.Context, req ctrl.Request) error { out, err := dbcommons.ExecCommand(r, r.Config, dbReadyPod.Name, dbReadyPod.Namespace, "", ctx, req, false, "bash", "-c", fmt.Sprintf("echo -e \"%s\" | %s", dbcommons.FlashBackTrueSQL, dbcommons.GetSqlClient("enterprise"))) @@ -3083,6 +3602,11 @@ func EnableFlashbackInDatabase(r *SingleInstanceDatabaseReconciler, dbReadyPod c return nil } +// ############################################################################# +// +// setup standby database +// +// ############################################################################# func SetupStandbyDatabase(r *SingleInstanceDatabaseReconciler, stdby *dbapi.SingleInstanceDatabase, primary *dbapi.SingleInstanceDatabase, ctx context.Context, req ctrl.Request) error { @@ -3135,3 +3659,34 @@ func SetupStandbyDatabase(r *SingleInstanceDatabaseReconciler, stdby *dbapi.Sing return nil } + +// ############################################################################# +// +// Create oracle hostname environment variable object to be passed to sidb +// +// ############################################################################# +func CreateOracleHostnameEnvVarObj(sidb *dbapi.SingleInstanceDatabase, referedPrimaryDatabase *dbapi.SingleInstanceDatabase) corev1.EnvVar { + dbMajorVersion, err := strconv.Atoi(strings.Split(referedPrimaryDatabase.Status.ReleaseUpdate, ".")[0]) + if err != nil { + // r.Log.Error(err, err.Error()) + return corev1.EnvVar{ + Name: "ORACLE_HOSTNAME", + Value: "", + } + } + if dbMajorVersion >= 23 { + return corev1.EnvVar{ + Name: "ORACLE_HOSTNAME", + Value: sidb.Name, + } + } else { + return corev1.EnvVar{ + Name: "ORACLE_HOSTNAME", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "status.podIP", + }, + }, + } + } +} diff --git a/controllers/observability/databaseobserver_controller.go b/controllers/observability/databaseobserver_controller.go new file mode 100644 index 00000000..bd58e71e --- /dev/null +++ b/controllers/observability/databaseobserver_controller.go @@ -0,0 +1,547 @@ +/* +** Copyright (c) 2022 Oracle and/or its affiliates. +** +** The Universal Permissive License (UPL), Version 1.0 +** +** Subject to the condition set forth below, permission is hereby granted to any +** person obtaining a copy of this software, associated documentation and/or data +** (collectively the "Software"), free of charge and under any and all copyright +** rights in the Software, and any and all patent rights owned or freely +** licensable by each licensor hereunder covering either (i) the unmodified +** Software as contributed to or provided by such licensor, or (ii) the Larger +** Works (as defined below), to deal in both +** +** (a) the Software, and +** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +** one is included with the Software (each a "Larger Work" to which the Software +** is contributed by such licensors), +** +** without restriction, including without limitation the rights to copy, create +** derivative works of, display, perform, and distribute the Software and make, +** use, sell, offer for sale, import, export, have made, and have sold the +** Software and the Larger Work(s), and to sublicense the foregoing rights on +** either these or other terms. +** +** This license is subject to the following condition: +** The above copyright notice and either this complete permission notice or at +** a minimum a reference to the UPL must be included in all copies or +** substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +** SOFTWARE. + */ + +package controllers + +import ( + "context" + "errors" + "github.com/go-logr/logr" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + apiError "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/tools/record" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "time" + + apiv1 "github.com/oracle/oracle-database-operator/apis/observability/v1alpha1" + constants "github.com/oracle/oracle-database-operator/commons/observability" +) + +// DatabaseObserverReconciler reconciles a DatabaseObserver object +type DatabaseObserverReconciler struct { + client.Client + Log logr.Logger + Scheme *runtime.Scheme + Recorder record.EventRecorder +} + +//+kubebuilder:rbac:groups=observability.oracle.com,resources=databaseobservers,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=observability.oracle.com,resources=databaseobservers/status,verbs=get;update;patch +//+kubebuilder:rbac:groups=observability.oracle.com,resources=databaseobservers/finalizers,verbs=update +//+kubebuilder:rbac:groups=apps,resources=pods;deployments;services,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups=apps,resources=configmaps,verbs=get;list +//+kubebuilder:rbac:groups="",resources=pods;deployments;services;events,verbs=get;list;watch;create;update;patch;delete +//+kubebuilder:rbac:groups="",resources=secrets;configmaps,verbs=get;list +//+kubebuilder:rbac:groups=monitoring.coreos.com,resources=servicemonitors,verbs=get;list;watch;create;update;patch;delete + +// Reconcile is part of the main kubernetes reconciliation loop which aims to +// move the current state of the cluster closer to the desired state. +// TODO(user): Modify the Reconcile function to compare the state specified by +// the DatabaseObserver object against the actual cluster state, and then +// perform operations to make the cluster state reflect the state specified by +// the user. +// +// For more details, check Reconcile and its Result here: +// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.6.4/pkg/reconcile +func (r *DatabaseObserverReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + + r.Log.WithName(constants.LogReconcile).Info(constants.LogCRStart, "NamespacedName", req.NamespacedName) + + // fetch databaseObserver + api := &apiv1.DatabaseObserver{} + if e := r.Get(context.TODO(), req.NamespacedName, api); e != nil { + + // if CR is not found or does not exist then + // consider either CR has been deleted + if apiError.IsNotFound(e) { + r.Log.WithName(constants.LogReconcile).Info(constants.LogCREnd) + return ctrl.Result{}, nil + } + + r.Log.WithName(constants.LogReconcile).Error(e, constants.ErrorCRRetrieve) + r.Recorder.Event(api, corev1.EventTypeWarning, constants.EventReasonFailedCRRetrieval, constants.EventMessageFailedCRRetrieval) + return ctrl.Result{}, e + + } + + // evaluate overall custom resource readiness at the end of the stack + defer r.validateCustomResourceReadiness(ctx, req) + + // initialize databaseObserver custom resource + if e := r.initialize(ctx, api, req); e != nil { + return ctrl.Result{}, e + } + + // validate specs + if e := r.validateSpecs(api); e != nil { + meta.SetStatusCondition(&api.Status.Conditions, metav1.Condition{ + Type: constants.IsExporterDeploymentReady, + Status: metav1.ConditionFalse, + Reason: constants.ReasonDeploymentSpecValidationFailed, + Message: constants.MessageExporterDeploymentSpecValidationFailed, + }) + if e := r.Status().Update(ctx, api); e != nil { + r.Log.WithName(constants.LogReconcile).Error(e, constants.ErrorStatusUpdate) + } + r.Log.WithName(constants.LogExportersDeploy).Error(e, constants.ErrorSpecValidationFailedDueToAnError) + return ctrl.Result{}, e + } + + // create resource if they do not exist + exporterDeployment := &ObservabilityDeploymentResource{} + if res, e := r.createResourceIfNotExists(exporterDeployment, api, ctx, req); e != nil { + return res, e + } + + if res, e := r.checkDeploymentForUpdates(exporterDeployment, api, ctx, req); e != nil { + meta.SetStatusCondition(&api.Status.Conditions, metav1.Condition{ + Type: constants.IsExporterDeploymentReady, + Status: metav1.ConditionFalse, + Reason: constants.ReasonDeploymentUpdateFailed, + Message: constants.MessageExporterDeploymentUpdateFailed, + }) + return res, e + } + + exporterService := &ObservabilityServiceResource{} + if res, e := r.createResourceIfNotExists(exporterService, api, ctx, req); e != nil { + return res, e + } + + exporterServiceMonitor := &ObservabilityServiceMonitorResource{} + if res, e := r.createResourceIfNotExists(exporterServiceMonitor, api, ctx, req); e != nil { + return res, e + } + + // check if deployment pods are ready + return r.validateDeploymentReadiness(api, ctx, req) +} + +// initialize method sets the initial status to PENDING, exporterConfig and sets the base condition +func (r *DatabaseObserverReconciler) initialize(ctx context.Context, api *apiv1.DatabaseObserver, req ctrl.Request) error { + + if api.Status.Conditions == nil || len(api.Status.Conditions) == 0 { + + // set condition + meta.SetStatusCondition(&api.Status.Conditions, metav1.Condition{ + Type: constants.IsCRAvailable, + Status: metav1.ConditionFalse, + Reason: constants.ReasonInitStart, + Message: constants.MessageCRInitializationStarted, + }) + + api.Status.Status = string(constants.StatusObservabilityPending) + api.Status.ExporterConfig = constants.UnknownValue + if e := r.Status().Update(ctx, api); e != nil { + r.Log.WithName(constants.LogReconcile).Error(e, constants.ErrorStatusUpdate) + return e + } + + } + + return nil +} + +// validateSpecs method checks the values and secrets passed in the spec +func (r *DatabaseObserverReconciler) validateSpecs(api *apiv1.DatabaseObserver) error { + + // If either Vault Fields are empty, then assume a DBPassword secret is supplied. If the DBPassword secret not found, then error out + if api.Spec.Database.DBPassword.VaultOCID == "" || api.Spec.Database.DBPassword.VaultSecretName == "" { + dbSecret := &corev1.Secret{} + if e := r.Get(context.TODO(), types.NamespacedName{Name: api.Spec.Database.DBPassword.SecretName, Namespace: api.Namespace}, dbSecret); e != nil { + r.Recorder.Event(api, corev1.EventTypeWarning, constants.EventReasonSpecError, constants.EventMessageSpecErrorDBPasswordSecretMissing) + return e + } + } + + // Does DB Connection String Secret Name actually exist + dbConnectSecret := &corev1.Secret{} + if e := r.Get(context.TODO(), types.NamespacedName{Name: api.Spec.Database.DBConnectionString.SecretName, Namespace: api.Namespace}, dbConnectSecret); e != nil { + r.Recorder.Event(api, corev1.EventTypeWarning, constants.EventReasonSpecError, constants.EventMessageSpecErrorDBConnectionStringSecretMissing) + return e + } + + // Does DB User String Secret Name actually exist + dbUserSecret := &corev1.Secret{} + if e := r.Get(context.TODO(), types.NamespacedName{Name: api.Spec.Database.DBUser.SecretName, Namespace: api.Namespace}, dbUserSecret); e != nil { + r.Recorder.Event(api, corev1.EventTypeWarning, constants.EventReasonSpecError, constants.EventMessageSpecErrorDBPUserSecretMissing) + return e + } + + // Does a custom configuration configmap actually exist, if provided + if configurationCMName := api.Spec.Exporter.ExporterConfig.Configmap.Name; configurationCMName != "" { + configurationCM := &corev1.ConfigMap{} + if e := r.Get(context.TODO(), types.NamespacedName{Name: configurationCMName, Namespace: api.Namespace}, configurationCM); e != nil { + r.Recorder.Event(api, corev1.EventTypeWarning, constants.EventReasonSpecError, constants.EventMessageSpecErrorConfigmapMissing) + return e + } + } + + // Does DBWallet actually exist, if provided + if dbWalletSecretName := api.Spec.Database.DBWallet.SecretName; dbWalletSecretName != "" { + dbWalletSecret := &corev1.Secret{} + if e := r.Get(context.TODO(), types.NamespacedName{Name: dbWalletSecretName, Namespace: api.Namespace}, dbWalletSecret); e != nil { + r.Recorder.Event(api, corev1.EventTypeWarning, constants.EventReasonSpecError, constants.EventMessageSpecErrorDBWalletSecretMissing) + return e + } + } + + return nil // valid, did not encounter any errors +} + +// createResourceIfNotExists method creates an ObserverResource if they have not yet been created +func (r *DatabaseObserverReconciler) createResourceIfNotExists(or ObserverResource, api *apiv1.DatabaseObserver, ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + + conditionType, logger, groupVersionKind := or.identify() + + // update after + defer r.Status().Update(ctx, api) + + // generate desired object based on api.Spec + desiredObj, genErr := or.generate(api, r.Scheme) + if genErr != nil { + meta.SetStatusCondition(&api.Status.Conditions, metav1.Condition{ + Type: conditionType, + Status: metav1.ConditionFalse, + Reason: constants.ReasonGeneralResourceGenerationFailed, + Message: constants.MessageResourceGenerationFailed, + }) + return ctrl.Result{}, genErr + } + + // if resource exists, retrieve the resource + foundObj := &unstructured.Unstructured{} + foundObj.SetGroupVersionKind(groupVersionKind) + getErr := r.Get(context.TODO(), types.NamespacedName{Name: desiredObj.GetName(), Namespace: req.Namespace}, foundObj) + + // if resource not found, create resource then return + if getErr != nil && apiError.IsNotFound(getErr) { + + if e := r.Create(context.TODO(), desiredObj); e != nil { // create + meta.SetStatusCondition(&api.Status.Conditions, metav1.Condition{ + Type: conditionType, + Status: metav1.ConditionFalse, + Reason: constants.ReasonGeneralResourceCreationFailed, + Message: constants.MessageResourceCreationFailed, + }) + r.Log.WithName(logger).Error(e, constants.ErrorResourceCreationFailure, "ResourceName", desiredObj.GetName(), "Kind", groupVersionKind, "Namespace", req.Namespace) + return ctrl.Result{}, e + } + + // mark ready if created + meta.SetStatusCondition(&api.Status.Conditions, metav1.Condition{ + Type: conditionType, + Status: metav1.ConditionTrue, + Reason: constants.ReasonGeneralResourceCreated, + Message: constants.MessageResourceCreated, + }) + r.Log.WithName(logger).Info(constants.LogResourceCreated, "ResourceName", desiredObj.GetName(), "Kind", groupVersionKind, "Namespace", req.Namespace) + + } else if getErr != nil { // if an error occurred + meta.SetStatusCondition(&api.Status.Conditions, metav1.Condition{ + Type: conditionType, + Status: metav1.ConditionFalse, + Reason: constants.ReasonGeneralResourceValidationFailureDueToError, + Message: constants.MessageResourceReadinessValidationFailed, + }) + r.Log.WithName(logger).Error(getErr, constants.ErrorResourceRetrievalFailureDueToAnError, "ResourceName", desiredObj.GetName(), "Kind", groupVersionKind, "Namespace", req.Namespace) + return ctrl.Result{}, getErr + + } else if getErr == nil && conditionType != constants.IsExporterDeploymentReady { // exclude deployment + meta.SetStatusCondition(&api.Status.Conditions, metav1.Condition{ + Type: conditionType, + Status: metav1.ConditionTrue, + Reason: constants.ReasonGeneralResourceValidationCompleted, + Message: constants.MessageResourceReadinessValidated, + }) + r.Log.WithName(logger).Info(constants.LogResourceFound, "ResourceName", desiredObj.GetName(), "Kind", groupVersionKind, "Namespace", req.Namespace) + + } + + // if no other error and resource, other than Deployments, have already been created before, end validation and return + return ctrl.Result{}, nil +} + +// checkDeploymentForUpdates method checks the deployment if it needs to be updated +func (r *DatabaseObserverReconciler) checkDeploymentForUpdates(or ObserverResource, api *apiv1.DatabaseObserver, ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + + // declare + foundDeployment := &appsv1.Deployment{} + + // generate object + desiredObj, genErr := or.generate(api, r.Scheme) + if genErr != nil { + return ctrl.Result{}, genErr + } + + // convert + desiredDeployment := &appsv1.Deployment{} + if e := r.Scheme.Convert(desiredObj, desiredDeployment, nil); e != nil { + return ctrl.Result{}, e + } + + // retrieve latest deployment + if e := r.Get(context.TODO(), types.NamespacedName{Name: desiredObj.GetName(), Namespace: req.Namespace}, foundDeployment); e != nil { + return ctrl.Result{}, e + } + // check for containerImage + if constants.IsUpdateRequiredForContainerImage(desiredDeployment, foundDeployment) { + foundDeployment.Spec.Template.Spec.Containers[0].Image = constants.GetExporterImage(api) + + if e := r.updateDeployment(api, ctx, req, foundDeployment, constants.MessageExporterDeploymentImageUpdated, constants.EventMessageUpdatedImageSucceeded); e != nil { + return ctrl.Result{}, e + } + } + + // retrieve latest deployment + if e := r.Get(context.TODO(), types.NamespacedName{Name: desiredObj.GetName(), Namespace: req.Namespace}, foundDeployment); e != nil { + return ctrl.Result{}, e + } + // check environment variables + if constants.IsUpdateRequiredForEnvironmentVars(desiredDeployment, foundDeployment) { + foundDeployment.Spec.Template.Spec.Containers[0].Env = constants.GetExporterEnvs(api) + + if e := r.updateDeployment(api, ctx, req, foundDeployment, constants.MessageExporterDeploymentEnvironmentUpdated, constants.EventMessageUpdatedEnvironmentSucceeded); e != nil { + return ctrl.Result{}, e + } + } + + // retrieve latest deployment + foundDeployment = &appsv1.Deployment{} + if e := r.Get(context.TODO(), types.NamespacedName{Name: desiredObj.GetName(), Namespace: req.Namespace}, foundDeployment); e != nil { + return ctrl.Result{}, e + } + // check config-volume, creds and ocikey + if constants.IsUpdateRequiredForVolumes(desiredDeployment, foundDeployment) { + foundDeployment.Spec.Template.Spec.Volumes = constants.GetExporterDeploymentVolumes(api) + foundDeployment.Spec.Template.Spec.Containers[0].VolumeMounts = constants.GetExporterDeploymentVolumeMounts(api) + + if e := r.updateDeployment(api, ctx, req, foundDeployment, constants.MessageExporterDeploymentVolumesUpdated, constants.EventMessageUpdatedVolumesSucceeded); e != nil { + return ctrl.Result{}, e + } + } + + // update status for exporter config + var setConfigmapNameStatus string + for _, v := range desiredDeployment.Spec.Template.Spec.Volumes { + if v.Name == constants.DefaultConfigVolumeString { + setConfigmapNameStatus = v.ConfigMap.Name + api.Status.ExporterConfig = setConfigmapNameStatus + } + } + if api.Status.ExporterConfig != setConfigmapNameStatus { + api.Status.ExporterConfig = constants.DefaultValue + } + r.Status().Update(ctx, api) + + // retrieve latest deployment + foundDeployment = &appsv1.Deployment{} + if e := r.Get(context.TODO(), types.NamespacedName{Name: desiredObj.GetName(), Namespace: req.Namespace}, foundDeployment); e != nil { + return ctrl.Result{}, e + } + // check replicateCount + if constants.IsUpdateRequiredForReplicas(desiredDeployment, foundDeployment) { + desiredReplicaCount := constants.GetExporterReplicas(api) + foundDeployment.Spec.Replicas = &desiredReplicaCount + + if e := r.updateDeployment(api, ctx, req, foundDeployment, constants.MessageExporterDeploymentReplicaUpdated, constants.EventMessageUpdatedReplicaSucceeded); e != nil { + return ctrl.Result{}, e + } + } + + return ctrl.Result{}, nil +} + +// updateDeployment method updates the deployment and sets the condition +func (r *DatabaseObserverReconciler) updateDeployment(api *apiv1.DatabaseObserver, ctx context.Context, req ctrl.Request, d *appsv1.Deployment, updateMessage string, recorderMessage string) error { + + // make update + defer r.Status().Update(ctx, api) + + if e := r.Update(context.TODO(), d); e != nil { + meta.SetStatusCondition(&api.Status.Conditions, metav1.Condition{ + Type: constants.IsExporterDeploymentReady, + Status: metav1.ConditionFalse, + Reason: constants.ReasonDeploymentUpdateFailed, + Message: constants.MessageExporterDeploymentUpdateFailed, + }) + r.Log.WithName(constants.LogExportersDeploy).Error(e, constants.ErrorDeploymentUpdate, "ResourceName", d.GetName(), "Kind", "Deployment", "Namespace", req.Namespace) + return e + } + + // update completed, however the pods needs to be validated for readiness + meta.SetStatusCondition(&api.Status.Conditions, metav1.Condition{ + Type: constants.IsExporterDeploymentReady, + Status: metav1.ConditionFalse, + Reason: constants.ReasonDeploymentUpdated, + Message: updateMessage, + }) + r.Log.WithName(constants.LogExportersDeploy).Info(constants.LogResourceUpdated, "ResourceName", d.GetName(), "Kind", "Deployment", "Namespace", req.Namespace) + r.Recorder.Event(api, corev1.EventTypeNormal, constants.EventReasonUpdateSucceeded, recorderMessage) + + return nil +} + +// validateDeploymentReadiness method evaluates deployment readiness by checking the status of all deployment pods +func (r *DatabaseObserverReconciler) validateDeploymentReadiness(api *apiv1.DatabaseObserver, ctx context.Context, req ctrl.Request) (ctrl.Result, error) { + + d := &appsv1.Deployment{} + rName := constants.DefaultExporterDeploymentPrefix + api.Name + + // update after + defer r.Status().Update(ctx, api) + + // get latest deployment + if e := r.Get(context.TODO(), types.NamespacedName{Name: rName, Namespace: api.Namespace}, d); e != nil { + meta.SetStatusCondition(&api.Status.Conditions, metav1.Condition{ + Type: constants.IsExporterDeploymentReady, + Status: metav1.ConditionFalse, + Reason: constants.ReasonGeneralResourceValidationFailureDueToError, + Message: constants.MessageExporterDeploymentValidationFailed, + }) + return ctrl.Result{}, e + } + + // get deployment labels + labels := d.Spec.Template.Labels + cLabels := client.MatchingLabels{} + for k, v := range labels { + cLabels[k] = v + } + + // list pods + pods := &corev1.PodList{} + if e := r.List(context.TODO(), pods, []client.ListOption{cLabels}...); e != nil { + meta.SetStatusCondition(&api.Status.Conditions, metav1.Condition{ + Type: constants.IsExporterDeploymentReady, + Status: metav1.ConditionFalse, + Reason: constants.ReasonDeploymentFailed, + Message: constants.MessageExporterDeploymentListingFailed, + }) + return ctrl.Result{}, e + } + + // check each pod phase + for _, pod := range pods.Items { + if pod.Status.Phase == corev1.PodFailed { + meta.SetStatusCondition(&api.Status.Conditions, metav1.Condition{ + Type: constants.IsExporterDeploymentReady, + Status: metav1.ConditionFalse, + Reason: constants.ReasonDeploymentFailed, + Message: constants.MessageExporterDeploymentFailed, + }) + return ctrl.Result{}, errors.New(constants.ErrorDeploymentPodsFailure) + + } else if pod.Status.Phase != corev1.PodRunning { // pod could be creating, + meta.SetStatusCondition(&api.Status.Conditions, metav1.Condition{ + Type: constants.IsExporterDeploymentReady, + Status: metav1.ConditionUnknown, + Reason: constants.ReasonDeploymentPending, + Message: constants.MessageExporterDeploymentPending, + }) + return ctrl.Result{Requeue: true, RequeueAfter: 15 * time.Second}, nil + } + } + + // once all pods are found to be running, mark deployment as ready and the exporter as ready + meta.SetStatusCondition(&api.Status.Conditions, metav1.Condition{ + Type: constants.IsExporterDeploymentReady, + Status: metav1.ConditionTrue, + Reason: constants.ReasonDeploymentSuccessful, + Message: constants.MessageExporterDeploymentSuccessful, + }) + return ctrl.Result{}, nil +} + +// validateCustomResourceReadiness method evaluates CR readiness by cycling through all conditions and checking for any condition with False Status +func (r *DatabaseObserverReconciler) validateCustomResourceReadiness(ctx context.Context, req ctrl.Request) { + + // get latest object + api := &apiv1.DatabaseObserver{} + if e := r.Get(context.TODO(), req.NamespacedName, api); e != nil { + r.Log.WithName(constants.LogReconcile).Error(e, constants.ErrorCRRetrieve) + return + } + + // make update + defer r.Status().Update(ctx, api) + + if meta.IsStatusConditionPresentAndEqual(api.Status.Conditions, constants.IsExporterDeploymentReady, metav1.ConditionUnknown) { + meta.SetStatusCondition(&api.Status.Conditions, metav1.Condition{ + Type: constants.IsCRAvailable, + Status: metav1.ConditionFalse, + Reason: constants.ReasonValidationInProgress, + Message: constants.MessageCRValidationWaiting, + }) + api.Status.Status = string(constants.StatusObservabilityPending) + } else if meta.IsStatusConditionFalse(api.Status.Conditions, constants.IsExporterDeploymentReady) || + meta.IsStatusConditionFalse(api.Status.Conditions, constants.IsExporterServiceReady) || + meta.IsStatusConditionFalse(api.Status.Conditions, constants.IsExporterServiceMonitorReady) { + meta.SetStatusCondition(&api.Status.Conditions, metav1.Condition{ + Type: constants.IsCRAvailable, + Status: metav1.ConditionFalse, + Reason: constants.ReasonReadyFailed, + Message: constants.MessageCRValidationFailed, + }) + api.Status.Status = string(constants.StatusObservabilityError) + } else { + meta.SetStatusCondition(&api.Status.Conditions, metav1.Condition{ + Type: constants.IsCRAvailable, + Status: metav1.ConditionTrue, + Reason: constants.ReasonReadyValidated, + Message: constants.MessageCRValidated, + }) + api.Status.Status = string(constants.StatusObservabilityReady) + } +} + +// SetupWithManager sets up the controller with the Manager. +func (r *DatabaseObserverReconciler) SetupWithManager(mgr ctrl.Manager) error { + return ctrl.NewControllerManagedBy(mgr). + For(&apiv1.DatabaseObserver{}). + Owns(&appsv1.Deployment{}). + Owns(&corev1.Service{}). + Complete(r) +} diff --git a/controllers/observability/databaseobserver_resource.go b/controllers/observability/databaseobserver_resource.go new file mode 100644 index 00000000..8c20ebe5 --- /dev/null +++ b/controllers/observability/databaseobserver_resource.go @@ -0,0 +1,183 @@ +package controllers + +import ( + apiv1 "github.com/oracle/oracle-database-operator/apis/observability/v1alpha1" + constants "github.com/oracle/oracle-database-operator/commons/observability" + monitorv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" + appsv1 "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/apimachinery/pkg/util/intstr" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +/* +This handler file contains all the methods that +retrieve/find and create all related resources +on Kubernetes. +*/ + +type ObservabilityDeploymentResource struct{} +type ObservabilityServiceResource struct{} +type ObservabilityServiceMonitorResource struct{} + +type ObserverResource interface { + generate(*apiv1.DatabaseObserver, *runtime.Scheme) (*unstructured.Unstructured, error) + identify() (string, string, schema.GroupVersionKind) +} + +func (resource *ObservabilityDeploymentResource) generate(api *apiv1.DatabaseObserver, scheme *runtime.Scheme) (*unstructured.Unstructured, error) { + rName := constants.DefaultExporterDeploymentPrefix + api.Name + rContainerName := constants.DefaultExporterContainerName + rContainerImage := constants.GetExporterImage(api) + rVolumes := constants.GetExporterDeploymentVolumes(api) + rVolumeMounts := constants.GetExporterDeploymentVolumeMounts(api) + rSelectors := constants.GetExporterSelector(api) + rReplicas := constants.GetExporterReplicas(api) + rEnvs := constants.GetExporterEnvs(api) + + rPort := []corev1.ContainerPort{ + {ContainerPort: 8080}, + } + + obj := &appsv1.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: rName, + Namespace: api.Namespace, + }, + Spec: appsv1.DeploymentSpec{ + Replicas: &rReplicas, + Selector: &metav1.LabelSelector{ + MatchLabels: rSelectors, + }, + Template: corev1.PodTemplateSpec{ + ObjectMeta: metav1.ObjectMeta{ + Labels: rSelectors, + }, + Spec: corev1.PodSpec{ + Containers: []corev1.Container{{ + Image: rContainerImage, + ImagePullPolicy: corev1.PullAlways, + Name: rContainerName, + Env: rEnvs, + VolumeMounts: rVolumeMounts, + Ports: rPort, + }}, + RestartPolicy: corev1.RestartPolicyAlways, + Volumes: rVolumes, + }, + }, + }, + } + + if err := controllerutil.SetControllerReference(api, obj, scheme); err != nil { + return nil, err + } + + var u = &unstructured.Unstructured{} + if err := scheme.Convert(obj, u, nil); err != nil { + return nil, err + } + return u, nil +} + +func (resource *ObservabilityServiceResource) generate(api *apiv1.DatabaseObserver, scheme *runtime.Scheme) (*unstructured.Unstructured, error) { + rServiceName := "obs-svc-" + api.Name + rLabels := constants.GetExporterLabels(api) + rPort := constants.GetExporterServicePort(api) + rSelector := constants.GetExporterSelector(api) + + obj := &corev1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Name: rServiceName, + Labels: rLabels, + Namespace: api.Namespace, + }, + Spec: corev1.ServiceSpec{ + Type: "ClusterIP", + Selector: rSelector, + Ports: []corev1.ServicePort{ + { + Name: "metrics", + Port: rPort, + TargetPort: intstr.FromInt32(constants.DefaultServiceTargetPort), + }, + }, + }, + } + + if err := controllerutil.SetControllerReference(api, obj, scheme); err != nil { + return nil, err + } + + var u = &unstructured.Unstructured{} + if err := scheme.Convert(obj, u, nil); err != nil { + return nil, err + } + return u, nil +} + +func (resource *ObservabilityServiceMonitorResource) generate(api *apiv1.DatabaseObserver, scheme *runtime.Scheme) (*unstructured.Unstructured, error) { + rName := constants.DefaultServiceMonitorPrefix + api.Name + rLabels := constants.GetExporterLabels(api) + rSelector := constants.GetExporterSelector(api) + rPort := constants.GetExporterServiceMonitorPort(api) + rInterval := "20s" + + obj := &monitorv1.ServiceMonitor{ + ObjectMeta: metav1.ObjectMeta{ + Name: rName, + Labels: rLabels, + Namespace: api.Namespace, + }, + Spec: monitorv1.ServiceMonitorSpec{ + Endpoints: []monitorv1.Endpoint{{ + Interval: monitorv1.Duration(rInterval), + Port: rPort, + }}, + Selector: metav1.LabelSelector{ + MatchLabels: rSelector, + }, + }, + } + + // set reference + if e := controllerutil.SetControllerReference(api, obj, scheme); e != nil { + return nil, e + } + + // convert + var u = &unstructured.Unstructured{} + if e := scheme.Convert(obj, u, nil); e != nil { + return nil, e + } + + return u, nil +} + +func (resource *ObservabilityDeploymentResource) identify() (string, string, schema.GroupVersionKind) { + return constants.IsExporterDeploymentReady, constants.LogExportersDeploy, schema.GroupVersionKind{ + Group: "apps", + Version: "v1", + Kind: "Deployment", + } +} + +func (resource *ObservabilityServiceResource) identify() (string, string, schema.GroupVersionKind) { + return constants.IsExporterServiceReady, constants.LogExportersSVC, schema.GroupVersionKind{ + Group: "", + Version: "v1", + Kind: "Service", + } +} + +func (resource *ObservabilityServiceMonitorResource) identify() (string, string, schema.GroupVersionKind) { + return constants.IsExporterServiceMonitorReady, constants.LogExportersServiceMonitor, schema.GroupVersionKind{ + Group: "monitoring.coreos.com", + Version: "v1", + Kind: "ServiceMonitor", + } +} diff --git a/controllers/observability/suite_test.go b/controllers/observability/suite_test.go new file mode 100644 index 00000000..4500ff5a --- /dev/null +++ b/controllers/observability/suite_test.go @@ -0,0 +1,100 @@ +/* +** Copyright (c) 2022 Oracle and/or its affiliates. +** +** The Universal Permissive License (UPL), Version 1.0 +** +** Subject to the condition set forth below, permission is hereby granted to any +** person obtaining a copy of this software, associated documentation and/or data +** (collectively the "Software"), free of charge and under any and all copyright +** rights in the Software, and any and all patent rights owned or freely +** licensable by each licensor hereunder covering either (i) the unmodified +** Software as contributed to or provided by such licensor, or (ii) the Larger +** Works (as defined below), to deal in both +** +** (a) the Software, and +** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +** one is included with the Software (each a "Larger Work" to which the Software +** is contributed by such licensors), +** +** without restriction, including without limitation the rights to copy, create +** derivative works of, display, perform, and distribute the Software and make, +** use, sell, offer for sale, import, export, have made, and have sold the +** Software and the Larger Work(s), and to sublicense the foregoing rights on +** either these or other terms. +** +** This license is subject to the following condition: +** The above copyright notice and either this complete permission notice or at +** a minimum a reference to the UPL must be included in all copies or +** substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +** SOFTWARE. + */ + +package controllers + +import ( + "path/filepath" + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + + observabilityv1alpha1 "github.com/oracle/oracle-database-operator/apis/observability/v1alpha1" + //+kubebuilder:scaffold:imports +) + +// These tests use Ginkgo (BDD-style Go testing framework). Refer to +// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. + +var cfg *rest.Config +var k8sClient client.Client +var testEnv *envtest.Environment + +func TestAPIs(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecs(t, "Controller Suite") +} + +var _ = BeforeSuite(func(done Done) { + logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) + + By("bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, + } + + var err error + cfg, err = testEnv.Start() + Expect(err).ToNot(HaveOccurred()) + Expect(cfg).ToNot(BeNil()) + + err = observabilityv1alpha1.AddToScheme(scheme.Scheme) + Expect(err).NotTo(HaveOccurred()) + + //+kubebuilder:scaffold:scheme + + k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) + Expect(err).ToNot(HaveOccurred()) + Expect(k8sClient).ToNot(BeNil()) + + close(done) +}, 60) + +var _ = AfterSuite(func() { + By("tearing down the test environment") + err := testEnv.Stop() + Expect(err).ToNot(HaveOccurred()) +}) diff --git a/docs/adb/ACD.md b/docs/adb/ACD.md index ffd09116..81ee1a65 100644 --- a/docs/adb/ACD.md +++ b/docs/adb/ACD.md @@ -8,7 +8,7 @@ As indicated in the prerequisites (see above), to interact with OCI services, ei ## Required Permissions -The opeartor must be given the required type of access in a policy written by an administrator to manage the Autonomous Container Databases. See [Create an Autonomous Container Database](https://docs.oracle.com/en-us/iaas/autonomous-database/doc/create-acd.html) for the required policies. +The operator must be given the required type of access in a policy written by an administrator to manage the Autonomous Container Databases. See [Create an Autonomous Container Database](https://docs.oracle.com/en-us/iaas/autonomous-database/doc/create-acd.html) for the required policies. The permission to view the workrequests is also required, so that the operator will update the resources when the work is done. See [Viewing Work Requests](https://docs.oracle.com/en-us/iaas/Content/ContEng/Tasks/contengviewingworkrequests.htm#contengviewingworkrequests) for sample work request policies. @@ -172,7 +172,7 @@ Here's a list of the values you can set for `action`: * `RESTART`: to restart the database * `TERMINATE`: to terminate the database -* `SYNC`: to sync the database, will describe in the next section +* `SYNC`: to sync the local database with the remote one 1. A sample .yaml file is available here: [config/samples/acd/autonomouscontainerdatabase_restart_terminate.yaml](./../../config/samples/acd/autonomouscontainerdatabase_restart_terminate.yaml) diff --git a/docs/adb/ADB_MANUAL_BACKUP.md b/docs/adb/ADB_LONG_TERM_BACKUP.md similarity index 70% rename from docs/adb/ADB_MANUAL_BACKUP.md rename to docs/adb/ADB_LONG_TERM_BACKUP.md index 2adec8e4..4720697d 100644 --- a/docs/adb/ADB_MANUAL_BACKUP.md +++ b/docs/adb/ADB_LONG_TERM_BACKUP.md @@ -1,23 +1,21 @@ -# Backing up an Oracle Autonomous Database Manually +# Creating Long-Term Backups of an Oracle Autonomous Database -To create manual backups of Autonomous Databases, use this procedure. +To create long-term backups of Autonomous Databases, use this procedure. -Oracle Cloud Infrastructure (OCI) automatically backs up your Autonomous Databases, and retains these backups for 60 days. You can restore and recover your database to any point-in-time in this retention period. Automatic backups are full backups taken every 60 days, with daily incremental backups. You can also create manual backups for your database. Manual backups are stored in an Object Storage bucket that you create, and are retained for 60 days. Note that Oracle doesn not recommend create or use manual backups. For more information, please visit [Backing Up and Restoring Autonomous Database](https://docs.oracle.com/en-us/iaas/Content/Database/Tasks/adbbackingup.htm) and [Backup and Restore Notes](https://docs.oracle.com/en-us/iaas/autonomous-database-shared/doc/backup-restore-notes.html). +Oracle Cloud Infrastructure (OCI) automatically backs up your Autonomous Databases, and retains these backups for 60 days. You can restore and recover your database to any point-in-time in this retention period. Automatic backups are full backups taken every 60 days, with daily incremental backups. You can also create long-term backups for your database with a retention period between 3 months and up to 10 years. For more information, please visit [Create Long-Term Backups on Autonomous Database](https://docs.oracle.com/en/cloud/paas/autonomous-database/serverless/adbsb/backup-long-term.html) and [Backup and Restore Notes](https://docs.oracle.com/en-us/iaas/autonomous-database-serverless/doc/backup-restore-notes.html). -## Prerequisites - -To hold your Autonomous Database manual backups, you must create an Oracle Cloud Infrastructure Object Storage bucket, and configure your database to connect to it. To finish setting up manual backup storage, follow the steps in this page: [Setting Up a Bucket to Store Manual Backups](https://docs.oracle.com/en-us/iaas/Content/Database/Tasks/adbbackingup.htm#creatingbucket). Creating an Autonomous Database manual backup object storage bucket is a one-time operation. - -## Create Manual Backup +## Create Long-Term Backup To back up an Autonomous Database, complete this procedure. 1. Add the following fields to the AutonomousDatabaseBackup resource definition. An example `.yaml` file is available here: [`config/samples/adb/autonomousdatabase_backup.yaml`](./../../config/samples/adb/autonomousdatabase_backup.yaml) | Attribute | Type | Description | Required? | |----|----|----|----| + | `spec.displayName` | string | The user-friendly name for the backup. This name does not have to be unique. | Yes | + | `spec.isLongTermBackup` | boolean | Indicates whether the backup is long-term. | Yes | + | `spec.retentionPeriodInDays` | string | Retention period, in days, for long-term backups. Minimum retention period is 90 days. | Yes | | `spec.target.k8sADB.name` | string | The name of custom resource of the target Autonomous Database. Choose either the `spec.target.k8sADB.name` or the `spec.target.ociADB.ocid`, but not both. | Conditional | | `spec.target.ociADB.ocid` | string | The [OCID](https://docs.cloud.oracle.com/Content/General/Concepts/identifiers.htm) of the target AutonomousDatabase. Choose either the `spec.target.k8sADB.name` or the `spec.target.ociADB.ocid`, but not both. | Conditional | - | `spec.displayName` | string | The user-friendly name for the backup. This name does not have to be unique. | Yes | | `spec.ociConfig` | dictionary | Not required when the Operator is authorized with [Instance Principal](./ADB_PREREQUISITES.md#authorized-with-instance-principal). Otherwise, you will need the values from this section: [Authorized with API Key Authentication](./ADB_PREREQUISITES.md#authorized-with-api-key-authentication). | Conditional | | `spec.ociConfig.configMapName` | string | Name of the ConfigMap that holds the local OCI configuration | Conditional | | `spec.ociConfig.secretName`| string | Name of the Kubernetes (K8s) Secret that holds the private key value | Conditional | @@ -36,6 +34,8 @@ To back up an Autonomous Database, complete this procedure. # ociADB: # ocid: ocid1.autonomousdatabase... displayName: autonomousdatabasebackup-sample + isLongTermBackup: true + retentionPeriodInDays: 90 ociConfig: configMapName: oci-cred secretName: oci-privatekey diff --git a/docs/adb/ADB_PREREQUISITES.md b/docs/adb/ADB_PREREQUISITES.md index 3eaf5b4a..f8c04c4b 100644 --- a/docs/adb/ADB_PREREQUISITES.md +++ b/docs/adb/ADB_PREREQUISITES.md @@ -12,7 +12,7 @@ To provide access, choose **one of the following approaches**: ## Authorized with API Key Authentication -API keys are supplied by users to authenticate the operator accessing Oracle Cloud Infrastructure (OCI) services. The operator reads the credintials of the OCI user from a ConfigMap and a Secret. If you're using Oracle Container Engine for Kubernetes (OKE), you may alternatively use [Instance Principal](#authorized-with-instance-principal) to avoid the need to configure user credentails or a configuration file. If the operator is deployed in a third-party Kubernetes cluster, then the credentials or a configuration file are needed, since Instance principal authorization applies only to instances that are running in the OCI. +API keys are supplied by users to authenticate the operator accessing Oracle Cloud Infrastructure (OCI) services. The operator reads the credentials of the OCI user from a ConfigMap and a Secret. If you're using Oracle Container Engine for Kubernetes (OKE), you may alternatively use [Instance Principal](#authorized-with-instance-principal) to avoid the need to configure user credentials or a configuration file. If the operator is deployed in a third-party Kubernetes cluster, then the credentials or a configuration file are needed, since Instance principal authorization applies only to instances that are running in the OCI. Oracle recommends using the helper script `set_ocicredentials.sh` in the root directory of the repository; this script will generate a ConfigMap and a Secret with the OCI credentials. By default, the script parses the **DEFAULT** profile in `~/.oci/config`. The default names of the ConfigMap and the Secret are, respectively: `oci-cred` and `oci-privatekey`. @@ -46,9 +46,9 @@ After creating the ConfigMap and the Secret, use their names as the values of `o ## Authorized with Instance Principal -Instance principal authorization enables the operator to make API calls from an instance (that is, a node) without requiring the `ociConfigMap`, and `ociSecret` attributes in the `.yaml` file. This approach applies only to instances that are running in the Oracle Cloud Infrastructure (OCI). In addition, this approach grants permissions to the nodes that matche the rules, which means that all the pods in the nodes can make the service calls. +Instance principal authorization enables the operator to make API calls from an instance (that is, a node) without requiring the `ociConfigMap`, and `ociSecret` attributes in the `.yaml` file. This approach applies only to instances that are running in the Oracle Cloud Infrastructure (OCI). In addition, this approach grants permissions to the nodes that match the rules, which means that all the pods in the nodes can make the service calls. -To set up the instance princials, you will have to: +To set up the instance principals, you will have to: * [Define dynamic group that includes the nodes in which the operator runs](#define-dynamic-group) * [Define policies that grant to the dynamic group the required permissions for the operator to its OCI interactions](#define-policies) @@ -111,7 +111,7 @@ To set up the instance princials, you will have to: Allow dynamic-group to manage all-resources in tenancy ``` - Example 3: enable a particular resouce access for the dynamic group to manage Oracle Autonomous Database in a given compartment + Example 3: enable a particular resource access for the dynamic group to manage Oracle Autonomous Database in a given compartment ```sh Allow dynamic-group to manage autonomous-database-family in compartment @@ -120,3 +120,31 @@ To set up the instance princials, you will have to: 3. To apply the policy, click Create. At this stage, the instances where the operator deploys have been granted sufficient permissions to call OCI services. You can now proceed to the installation. + +### Authorized with OKE Workload Identity + +OKE Workload Identity grants the operator pods policy-driven access to OCI resources using OCI Identity and Access Management (IAM). +When using OKE Workload Identity, only the region must be specified in the ConfigMap corresponding to the `ociConfigMap` attribute. The `ociSecret` attribute should not be specified in the `.yaml` file. + +To set up the OKE Workload Identity, you will have to: + +### Configure Cluster Region + +The operator reads the OCI region from a ConfigMap. + +```sh +kubectl create configmap oci-cred \ +--from-literal=region= +``` + +### Define Policies + +1. Get the compartment name where the database resides/will be created. +2. Get the OCID of the OKE Cluster where the Oracle Database Operator is running. +3. Create the following policy in OCI IAM, supplying your compartment name and OKE Cluster OCID: + +``` +Allow any-user to manage all-resources in compartment where all {request.principal.namespace='oracle-database-operator-system',request.principal.type='workload',request.principal.cluster_id='',request.principal.service_account='default'} +``` + +After creating the policy, operator pods will be granted sufficient permissions to call OCI services. You can now proceed to the installation. \ No newline at end of file diff --git a/docs/adb/ADB_RESTORE.md b/docs/adb/ADB_RESTORE.md index a7f67888..7a80090a 100644 --- a/docs/adb/ADB_RESTORE.md +++ b/docs/adb/ADB_RESTORE.md @@ -2,7 +2,7 @@ To restore an Autonomous Database from a backup, use this document. -You can either use any existing manual or automatic backup to restore your database, or you can restore and recover your database to any point in time in the 60-day retention period of your automatic backups. For point-in-time restores, you specify a timestamp. Your Autonomous Database identifies which backup to use for the fastest restore. +You can either use any existing on-demand or automatic backup to restore your database, or you can restore and recover your database to any point in time in the 60-day retention period of your automatic backups. For point-in-time restores, you specify a timestamp. Your Autonomous Database identifies which backup to use for the fastest restore. ## Restore an Autonomous Database diff --git a/docs/adb/README.md b/docs/adb/README.md index 144f9d41..1b59c4d6 100644 --- a/docs/adb/README.md +++ b/docs/adb/README.md @@ -111,7 +111,7 @@ Follow these steps to provision an Autonomous Database that will map objects in 5. Choose the type of network access (optional): - By default, the network access type is set to PUBLIC, which allows secure connections from anywhere. Uncomment the code block if you want configure the network acess. See [Configuring Network Access of Autonomous Database](./NETWORK_ACCESS_OPTIONS.md) for more information. + By default, the network access type is set to PUBLIC, which allows secure connections from anywhere. Uncomment the code block if you want configure the network access. See [Configuring Network Access of Autonomous Database](./NETWORK_ACCESS_OPTIONS.md) for more information. 6. Apply the YAML: @@ -411,6 +411,18 @@ To delete the resource and terminate the Autonomous Database, complete these ste Now, you can verify that the database is in TERMINATING state on the Cloud Console. +## Roles and Privileges requirements for Oracle Autonomous Database Controller + +Autonomous Database controller uses Kubernetes objects such as: + + | Resources | Verbs | + | --- | --- | + | Configmaps | get list watch create update patch delete | + | Secrets | get list watch create update patch delete | + | Events | create patch | + +The defintion of all the Kubernetes Objects, which are to be used by the Oracle Autonomous Database Controller, comes from the `oracle-database-operator.yaml` file which is applied to deploy the **Oracle Database Operator**. + ## Debugging and troubleshooting ### Show the details of the resource diff --git a/docs/dbcs/provisioning/database_connection.md b/docs/dbcs/provisioning/database_connection.md index e69de29b..66ac2b5d 100644 --- a/docs/dbcs/provisioning/database_connection.md +++ b/docs/dbcs/provisioning/database_connection.md @@ -0,0 +1,53 @@ +## Database connection + +In order to retrieve the database connection use the kubectl describe command + +```sh +kubectl describe dbcssystems.database.oracle.com dbcssystem-create +``` + +You can use the following script (tnsalias.awk) to get a simple tnsalias + +```awk +!#/usr/bin/awk +( $0 ~ / Db Unique Name:/ ) { DB_UNIQUE_NAME=$4 } +( $0 ~ /Domain Name:/ ) { DB_DOMAIN=$3 } +( $0 ~ /Host Name:/ ) { HOSTNAME=$3 } +( $0 ~ /Listener Port:/ ) { PORT=$3 } + +END { + printf ("db_unique_name=%s\n",DB_UNIQUE_NAME); + printf ("db_domain=%s\n",DB_DOMAIN); + printf ("hostname=%s\n",HOSTNAME); + printf ("port=%s\n",PORT); + printf ("====== TNSALIAS ======\n"); + printf ("(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=%s)(PORT=%s))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=%s.%s)))\n", + HOSTNAME,PORT,DB_UNIQUE_NAME,DB_DOMAIN); +``` + +```text +kubectl describe dbcssystems.database.oracle.com dbcssystem-create |awk -f tnsalias.awk +db_unique_name=testdb_fg4_lin +db_domain=vcndns.oraclevcn.com +hostname=host1205 +port=1521 +====== TNSALIAS ====== +(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=host1205)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=testdb_fg4_lin.vcndns.oraclevcn.com))) + +sqlplus scott@"(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=host1205)(PORT=1521))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=testdb_fg4_lin.vcndns.oraclevcn.com)))" + + +SQL*Plus: Release 19.0.0.0.0 - Production on Fri Dec 15 14:16:42 2023 +Version 19.15.0.0.0 + +Copyright (c) 1982, 2022, Oracle. All rights reserved. + +Enter password: +Last Successful login time: Fri Dec 15 2023 14:14:07 +00:00 + +Connected to: +Oracle Database 19c EE High Perf Release 19.0.0.0.0 - Production +Version 19.18.0.0.0 + +SQL> +``` diff --git a/docs/dbcs/provisioning/dbcs_service_with_minimal_parameters.md b/docs/dbcs/provisioning/dbcs_service_with_minimal_parameters.md index f91370ca..f6bc8185 100644 --- a/docs/dbcs/provisioning/dbcs_service_with_minimal_parameters.md +++ b/docs/dbcs/provisioning/dbcs_service_with_minimal_parameters.md @@ -8,16 +8,17 @@ This example uses `dbcs_service_with_minimal_parameters.yaml` to deploy a Single - OCI Configmap as `oci-cred` - OCI Secret as `oci-privatekey` -- Availability Domain for the DBCS VMDB as `OLou:PHX-AD-1` -- Compartment OCID as `ocid1.compartment.oc1..aaaaaaaa4hecw2shffuuc4fcatpin4x3rdkesmmf4he67osupo7g6f7i6eya` +- Availability Domain for the DBCS VMDB as `OLou:EU-MILAN-1-AD-1` +- Compartment OCID as `ocid1.compartment.oc1..aaaaaaaaks5baeqlvv4kyj2jiwnrbxgzm3gsumcfy4c6ntj2ro5i3a5gzhhq` - Database Admin Credential as `admin-password` -- Database Name as `db0130` -- Oracle Database Software Image Version as `21c` +- Database Name as `dbsystem0130` +- Oracle Database Software Image Version as `19c` - Database Workload Type as Transaction Processing i.e. `OLTP` -- Database Hostname Prefix as `host0130` +- Database Hostname Prefix as `host1205` - Oracle VMDB Shape as `VM.Standard2.1` - SSH Public key for the DBCS system being deployed as `oci-publickey` -- OCID of the Subnet as `ocid1.subnet.oc1.phx.aaaaaaaauso243tymnzeh6zbz5vkejgyu4ugujul5okpa5xbaq3275izbc7a` +- domain `vcndns.oraclevcn.com` +- OCID of the Subnet as `ocid1.subnet.oc1.eu-milan-1.aaaaaaaaeiy3tvcsnyg6upfp3ydtu7jmfnmoyifq2ax6y45b5qpdbpide5xa` **NOTE:** For the details of the parameters to be used in the .yaml file, please refer [here](./dbcs_controller_parameters.md). diff --git a/docs/dbcs/provisioning/dbcs_service_with_minimal_parameters.yaml b/docs/dbcs/provisioning/dbcs_service_with_minimal_parameters.yaml index 9e4a5f3d..dc02cfa3 100644 --- a/docs/dbcs/provisioning/dbcs_service_with_minimal_parameters.yaml +++ b/docs/dbcs/provisioning/dbcs_service_with_minimal_parameters.yaml @@ -6,14 +6,20 @@ spec: ociConfigMap: "oci-cred" ociSecret: "oci-privatekey" dbSystem: - availabilityDomain: "OLou:PHX-AD-1" - compartmentId: "ocid1.compartment.oc1..aaaaaaaa4hecw2shffuuc4fcatpin4x3rdkesmmf4he67osupo7g6f7i6eya" + availabilityDomain: "OLou:EU-MILAN-1-AD-1" + compartmentId: "ocid1.compartment.oc1..aaaaaaaaks5baeqlvv4kyj2jiwnrbxgzm3gsumcfy4c6ntj2ro5i3a5gzhhq" dbAdminPaswordSecret: "admin-password" - dbName: "db0130" - dbVersion: "21c" + dbEdition: "ENTERPRISE_EDITION_HIGH_PERFORMANCE" + dbName: "testdb" + displayName: "dbsystem0130" + licenseModel: "BRING_YOUR_OWN_LICENSE" + dbVersion: "19c" dbWorkload: "OLTP" - hostName: "host0130" + hostName: "host1205" shape: "VM.Standard2.1" - sshPublicKeys: - - "oci-publickey" - subnetId: "ocid1.subnet.oc1.phx.aaaaaaaauso243tymnzeh6zbz5vkejgyu4ugujul5okpa5xbaq3275izbc7a" + domain: "vcndns.oraclevcn.com" + sshPublicKeys: + - "oci-publickey" + subnetId: "ocid1.subnet.oc1.eu-milan-1.aaaaaaaaeiy3tvcsnyg6upfp3ydtu7jmfnmoyifq2ax6y45b5qpdbpide5xa" + + diff --git a/docs/dbcs/provisioning/dbcs_service_with_minimal_parameters_sample_output.log b/docs/dbcs/provisioning/dbcs_service_with_minimal_parameters_sample_output.log index ddf1d81a..133f109c 100644 --- a/docs/dbcs/provisioning/dbcs_service_with_minimal_parameters_sample_output.log +++ b/docs/dbcs/provisioning/dbcs_service_with_minimal_parameters_sample_output.log @@ -1,257 +1,135 @@ -[root@docker-test-server test]# cat dbcs_service_with_minimal_parameters.yaml -apiVersion: database.oracle.com/v1alpha1 -kind: DbcsSystem -metadata: - name: dbcssystem-create -spec: - ociConfigMap: "oci-cred" - ociSecret: "oci-privatekey" - dbSystem: - availabilityDomain: "OLou:PHX-AD-1" - compartmentId: "ocid1.compartment.oc1..aaaaaaaa4hecw2shffuuc4fcatpin4x3rdkesmmf4he67osupo7g6f7i6eya" - dbAdminPaswordSecret: "admin-password" - dbName: "db0130" - dbVersion: "21c" - dbWorkload: "OLTP" - hostName: "host0130" - shape: "VM.Standard2.1" - sshPublicKeys: - - "oci-publickey" - subnetId: "ocid1.subnet.oc1.phx.aaaaaaaauso243tymnzeh6zbz5vkejgyu4ugujul5okpa5xbaq3275izbc7a" -[root@docker-test-server test]# -[root@docker-test-server test]# kubectl apply -f dbcs_service_with_minimal_parameters.yaml -dbcssystem.database.oracle.com/dbcssystem-create created - - -[root@docker-test-server test]# kubectl get ns - -kubectl get allNAME STATUS AGE -cert-manager Active 13d -default Active 139d -kube-node-lease Active 139d -kube-public Active 139d -kube-system Active 139d -oracle-database-operator-system Active 13d -shns Active 88d -[root@docker-test-server test]# -[root@docker-test-server test]# kubectl get all -n oracle-database-operator-system -NAME READY STATUS RESTARTS AGE -pod/oracle-database-operator-controller-manager-665874bd57-dlhls 1/1 Running 3 13d -pod/oracle-database-operator-controller-manager-665874bd57-g2cgw 1/1 Running 3 13d -pod/oracle-database-operator-controller-manager-665874bd57-q42f8 1/1 Running 4 13d - -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -service/oracle-database-operator-controller-manager-metrics-service ClusterIP 10.96.130.124 8443/TCP 13d -service/oracle-database-operator-webhook-service ClusterIP 10.96.4.104 443/TCP 13d - -NAME READY UP-TO-DATE AVAILABLE AGE -deployment.apps/oracle-database-operator-controller-manager 3/3 3 3 13d - -NAME DESIRED CURRENT READY AGE -replicaset.apps/oracle-database-operator-controller-manager-665874bd57 3 3 3 13d -[root@docker-test-server test]# -[root@docker-test-server test]# -[root@docker-test-server test]# kubectl logs -f pod/oracle-database-operator-controller-manager-665874bd57-dlhls -n oracle-database-operator-system -. -. -2022-03-08T22:12:57.414Z INFO controller-runtime.manager.controller.dbcssystem OCI provider configured succesfully {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:12:58.013Z INFO controller-runtime.manager.controller.dbcssystem DbcsSystem DBSystem provisioning {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:13:05.772Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:14:06.499Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:15:07.256Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:16:07.877Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:17:08.237Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:18:08.852Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:19:09.184Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:20:10.253Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:21:10.576Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:22:10.948Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:23:11.443Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:24:11.872Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:25:12.206Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:26:12.543Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:27:13.053Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:28:13.582Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:29:13.927Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:30:14.415Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:31:14.712Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:32:15.236Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:33:16.113Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:34:16.397Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:35:16.723Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:36:17.178Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:37:17.454Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:38:17.849Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:39:18.305Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:40:18.724Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:41:19.050Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:42:19.570Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:43:19.836Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:44:20.258Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:45:20.592Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:46:20.917Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:47:21.225Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:48:21.587Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:49:21.841Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:50:22.214Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:51:22.519Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:52:22.875Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:53:23.324Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:54:23.755Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:55:24.273Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:56:24.672Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:57:25.518Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:58:26.113Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T22:59:26.373Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T23:00:26.650Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T23:01:26.895Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T23:02:27.437Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T23:03:27.835Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T23:04:28.231Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T23:05:28.653Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T23:06:29.286Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T23:07:29.637Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T23:08:30.061Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T23:09:30.327Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T23:10:30.838Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T23:11:31.312Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T23:12:31.755Z INFO controller-runtime.manager.controller.dbcssystem DB System current state is still:PROVISIONING. Sleeping for 60 seconds. {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T23:13:32.075Z INFO controller-runtime.manager.controller.dbcssystem DbcsSystem system provisioned succesfully {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-existing", "namespace": "default"} -2022-03-08T23:13:34.641Z INFO controller-runtime.manager.controller.dbcssystem OCI provider configured succesfully {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} -2022-03-08T23:13:45.117Z INFO controller-runtime.manager.controller.dbcssystem OCI provider configured succesfully {"reconciler group": "database.oracle.com", "reconciler kind": "DbcsSystem", "name": "dbcssystem-create", "namespace": "default"} - - -[root@docker-test-server test]# kubectl describe dbcssystems.database.oracle.com dbcssystem-create +/usr/bin/kubectl describe dbcssystems.database.oracle.com dbcssystem-create Name: dbcssystem-create Namespace: default Labels: -Annotations: lastSuccessfulSpec: - {"dbSystem":{"compartmentId":"ocid1.compartment.oc1..aaaaaaaa4hecw2shffuuc4fcatpin4x3rdkesmmf4he67osupo7g6f7i6eya","availabilityDomain":"O... +Annotations: kubectl.kubernetes.io/last-applied-configuration: + {"apiVersion":"database.oracle.com/v1alpha1","kind":"DbcsSystem","metadata":{"annotations":{},"name":"dbcssystem-create","namespace":"defa... API Version: database.oracle.com/v1alpha1 Kind: DbcsSystem Metadata: - Creation Timestamp: 2022-03-08T22:12:57Z + Creation Timestamp: 2023-12-12T12:59:58Z Generation: 1 Managed Fields: API Version: database.oracle.com/v1alpha1 Fields Type: FieldsV1 - fieldsV1: - f:metadata: - f:annotations: + Fields V 1: + F : Metadata: + F : Annotations: .: - f:kubectl.kubernetes.io/last-applied-configuration: - f:spec: + F : Kubectl . Kubernetes . Io / Last - Applied - Configuration: + F : Spec: .: - f:dbSystem: + F : Db System: .: - f:availabilityDomain: - f:compartmentId: - f:dbAdminPaswordSecret: - f:dbName: - f:dbVersion: - f:dbWorkload: - f:hostName: - f:shape: - f:sshPublicKeys: - f:subnetId: - f:ociConfigMap: - f:ociSecret: - Manager: kubectl-client-side-apply + F : Availability Domain: + F : Compartment Id: + F : Db Admin Pasword Secret: + F : Db Edition: + F : Db Name: + F : Db Version: + F : Db Workload: + F : Display Name: + F : Domain: + F : Host Name: + F : License Model: + F : Shape: + F : Ssh Public Keys: + F : Subnet Id: + F : Oci Config Map: + F : Oci Secret: + Manager: kubectl Operation: Update - Time: 2022-03-08T22:12:57Z + Time: 2023-12-12T12:59:58Z API Version: database.oracle.com/v1alpha1 Fields Type: FieldsV1 - fieldsV1: - f:metadata: - f:annotations: - f:lastSuccessfulSpec: - f:spec: - f:dbSystem: - f:dbBackupConfig: - f:id: - f:status: + Fields V 1: + F : Status: .: - f:availabilityDomain: - f:cpuCoreCount: - f:dataStoragePercentage: - f:dataStorageSizeInGBs: - f:dbEdition: - f:dbInfo: - f:displayName: - f:id: - f:licenseModel: - f:network: + F : Availability Domain: + F : Cpu Core Count: + F : Data Storage Percentage: + F : Data Storage Size In G Bs: + F : Db Edition: + F : Db Info: + F : Display Name: + F : Id: + F : License Model: + F : Network: .: - f:clientSubnet: - f:domainName: - f:hostName: - f:listenerPort: - f:scanDnsName: - f:vcnName: - f:nodeCount: - f:recoStorageSizeInGB: - f:shape: - f:state: - f:storageManagement: - f:subnetId: - f:timeZone: - f:workRequests: + F : Client Subnet: + F : Domain Name: + F : Host Name: + F : Listener Port: + F : Vcn Name: + F : Node Count: + F : Reco Storage Size In GB: + F : Shape: + F : State: + F : Storage Management: + F : Subnet Id: + F : Time Zone: + F : Work Requests: Manager: manager Operation: Update - Time: 2022-03-08T23:13:34Z - Resource Version: 55187354 - UID: 0cdbebc0-3aeb-43b1-ae7f-eb36e6c56000 + Subresource: status + Time: 2023-12-12T14:12:36Z + Resource Version: 1571919 + UID: e11353f3-1334-4ca8-af31-4b638442f429 Spec: Db System: - Availability Domain: OLou:PHX-AD-1 - Compartment Id: ocid1.compartment.oc1..aaaaaaaa4hecw2shffuuc4fcatpin4x3rdkesmmf4he67osupo7g6f7i6eya + Availability Domain: OLou:EU-MILAN-1-AD-1 + Compartment Id: ocid1.compartment.oc1..aaaaaaaaks5baeqlvv4kyj2jiwnrbxgzm3gsumcfy4c6ntj2ro5i3a5gzhhq Db Admin Pasword Secret: admin-password - Db Name: db0130 - Db Version: 21c -apiVersion: database.oracle.com/v1alpha1 + Db Edition: ENTERPRISE_EDITION_HIGH_PERFORMANCE + Db Name: testdb + Db Version: 19c Db Workload: OLTP - Host Name: host0130 + Display Name: dbsystem0130 + Domain: vcndns.oraclevcn.com + Host Name: host1205 + License Model: BRING_YOUR_OWN_LICENSE Shape: VM.Standard2.1 Ssh Public Keys: oci-publickey - Subnet Id: ocid1.subnet.oc1.phx.aaaaaaaauso243tymnzeh6zbz5vkejgyu4ugujul5okpa5xbaq3275izbc7a + Subnet Id: ocid1.subnet.oc1.eu-milan-1.aaaaaaaaeiy3tvcsnyg6upfp3ydtu7jmfnmoyifq2ax6y45b5qpdbpide5xa Oci Config Map: oci-cred Oci Secret: oci-privatekey Status: - Availability Domain: OLou:PHX-AD-1 + Availability Domain: OLou:EU-MILAN-1-AD-1 Cpu Core Count: 1 Data Storage Percentage: 80 Data Storage Size In G Bs: 256 - Db Edition: ENTERPRISE_EDITION + Db Edition: ENTERPRISE_EDITION_HIGH_PERFORMANCE Db Info: - Db Home Id: ocid1.dbhome.oc1.phx.anyhqljr5gy3jhqat52milqwt3gq6lwohhacwg5yi4mtzq7c7hag53lrkugq - Db Name: db0130 - Db Unique Name: db0130_phx1zn + Db Home Id: ocid1.dbhome.oc1.eu-milan-1.anwgsljrx2vveliazumnbyvudq3rwkbc4brtamgqzyrjuwfbtx5k7hlqwx2a + Db Name: testdb + Db Unique Name: testdb_fg4_lin Db Workload: OLTP - Id: ocid1.database.oc1.phx.anyhqljrabf7htyackgmsaqjfexoqgrzuuk33ju2q25z2al43tnd5mhhvkra - Display Name: dbsystem20220308221302 - Id: ocid1.dbsystem.oc1.phx.anyhqljrabf7htyanr3lnp6wtu5ld7qwszohiteodvwahonr2yymrftarkqa - License Model: LICENSE_INCLUDED + Id: ocid1.database.oc1.eu-milan-1.anwgsljrabf7htyasoe7b7mtfecc7tdfkp6w5knvvufxmk3phztxfktf6naq + Display Name: dbsystem0130 + Id: ocid1.dbsystem.oc1.eu-milan-1.anwgsljrabf7htyat3fsgcftfilt45bgbrfgawroa2oasamavsluwqyr5aya + License Model: BRING_YOUR_OWN_LICENSE Network: - Client Subnet: k8test-pubvcn - Domain Name: k8testpubvcn.k8test.oraclevcn.com - Host Name: host0130 + Client Subnet: vcnsbn + Domain Name: vcndns.oraclevcn.com + Host Name: host1205 Listener Port: 1521 - Scan Dns Name: host0130-scan.k8testpubvcn.k8test.oraclevcn.com - Vcn Name: k8test + Vcn Name: vcnnet Node Count: 1 Reco Storage Size In GB: 256 Shape: VM.Standard2.1 - State: AVAILABLE + State: PROVISIONING Storage Management: ASM - Subnet Id: ocid1.subnet.oc1.phx.aaaaaaaauso243tymnzeh6zbz5vkejgyu4ugujul5okpa5xbaq3275izbc7a + Subnet Id: ocid1.subnet.oc1.eu-milan-1.aaaaaaaaeiy3tvcsnyg6upfp3ydtu7jmfnmoyifq2ax6y45b5qpdbpide5xa Time Zone: UTC Work Requests: - Operation Id: ocid1.coreservicesworkrequest.oc1.phx.abyhqljrxivzvgzel47zuoyke5yk36o7mrgjl27vscd5z3bqptmyh3rxwbqq + Operation Id: ocid1.coreservicesworkrequest.oc1.eu-milan-1.abwgsljrkv6jwqtepnxyhnxgtzolw74bqfh5oqlwskq72dqgjpfs5rxu66wa Operation Type: Create DB System - Percent Complete: 100 - Time Accepted: 2022-03-08 22:13:02.999 +0000 UTC - Time Finished: 2022-03-08 23:11:50.46 +0000 UTC - Time Started: 2022-03-08 22:13:16.995 +0000 UTC + Percent Complete: 0 + Time Accepted: 2023-12-12 13:00:03.156 +0000 UTC + Operation Id: ocid1.coreservicesworkrequest.oc1.eu-milan-1.abwgsljrxudjz2qivun6ypupqhytam4axv4wago7nuauceqyapbceysjukfq + Operation Type: Create DB System + Percent Complete: 0 + Time Accepted: 2023-12-12 14:12:36.047 +0000 UTC Events: -[root@docker-test-server test]# + diff --git a/docs/dbcs/usecase01/README.md b/docs/dbcs/usecase01/README.md new file mode 100644 index 00000000..4349e211 --- /dev/null +++ b/docs/dbcs/usecase01/README.md @@ -0,0 +1,199 @@ + +# Makefile for the dbcs automation creation + +This [makefile](#makefile) helps to speed up the **DBCS** creation. Edit all the credentials related to your tenancy in the configmap target section and update the **NAMESPACE** variable. Specify the oci pem key that you have created during ocicli configuration **OCIPEM** + +```makefile +[...] +ONAMESPACE=oracle-database-operator-system +NAMESPACE=[MY_NAMESPACE] +OCIPEN=[PATH_TO_OCI_API_KEY_PEM] +[...] +configmap: + $(KUBECTL) create configmap oci-cred \ + --from-literal=tenancy=[MY_TENANCY_ID] + --from-literal=user=[MY_USER_ID] \ + --from-literal=fingerprint=[MY_FINGER_PRINT] \ + --from-literal=region=[MY_REGION] -n $(NAMESPACE) + +[...] +``` +Specify the admin password and the tde password in adminpass and tdepass + +```makefile +adminpass: + echo "[SPECIFY_PASSWORD_HERE]" > ./admin-password + $(KUBECTL) create secret generic admin-password --from-file=./admin-password -n $(NAMESPACE) + $(RM) ./admin-password + +tdepass: + echo "[SPECIFY_PASSWORD_HERE]" > ./tde-password + $(KUBECTL) create secret generic tde-password --from-file=./tde-password -n $(NAMESPACE) + $(RM) ./tde-password +``` + +Execute the following targets step1 step2 step3 step4 step5 to setup secrets and certificates. + +```bash +make step1 +make step2 +make step3 +make step4 +make step5 +``` + +Create the file **dbcs_service_with_minimal_parameters.yaml** + +```yaml +apiVersion: database.oracle.com/v1alpha1 +kind: DbcsSystem +metadata: + name: dbcssystem-create + namespace: [MY_NAMESPACE] +spec: + ociConfigMap: "oci-cred" + ociSecret: "oci-privatekey" + dbSystem: + availabilityDomain: "OLou:EU-MILAN-1-AD-1" + compartmentId: "[MY_COMPARTMENT_ID]" + dbAdminPaswordSecret: "admin-password" + dbEdition: "ENTERPRISE_EDITION_HIGH_PERFORMANCE" + dbName: "testdb" + displayName: "dbsystem_example" + licenseModel: "BRING_YOUR_OWN_LICENSE" + dbVersion: "19c" + dbWorkload: "OLTP" + hostName: "host_example_1205" + shape: "VM.Standard2.1" + domain: "example.com" + sshPublicKeys: + - "oci-publickey" + subnetId: "[MY_SUBNET_ID]" + +``` + +Execute the target make file create **make create** or apply directly the above yaml file **kubectl apply -f dbcs_service_with_minimal_parameters.yaml** to create DBCS . Verify the DBCS creation by executing **kubectl get DbcsSystem -n [MY_NAMESPACE]** + +``` +kubectl get DbcsSystem -n [MY_NAMESPACE] +NAME AGE +dbcssystem-create 52m +``` +Use the describe command to verify the status and the attributes of the dbcs system created + +```bash +kubectl describe DbcsSystem dbcssystem-create -n [...] +``` +```text +Name: dbcssystem-create +Namespace: pdbnamespace +Labels: +Annotations: kubectl.kubernetes.io/last-applied-configuration: + {"apiVersion":"database.oracle.com/v1alpha1","kind":"DbcsSystem","metadata":{"annotations":{},"name":"dbcssystem-create","namespace":"pdbn...}} + +API Version: database.oracle.com/v1alpha1 +Kind: DbcsSystem +Metadata: + Creation Timestamp: 2024-03-15T14:53:02Z + + Db System: + Availability Domain: OLou:EU-MILAN-1-AD-1 + Compartment Id: [MY_COMPARTMENT_ID] + Db Admin Pasword Secret: admin-password + Db Edition: ENTERPRISE_EDITION_HIGH_PERFORMANCE + Db Name: testdb + Db Version: 19c + Db Workload: OLTP + Display Name: "dbsystem_example" + Domain: example.com + Host Name: host_example_1205 + License Model: BRING_YOUR_OWN_LICENSE + Shape: VM.Standard2.1 + Ssh Public Keys: + oci-publickey + Subnet Id: [MY_SUBNET_ID] + Oci Config Map: oci-cred + Oci Secret: oci-privatekey +Status: + Availability Domain: OLou:EU-MILAN-1-AD-1 + Cpu Core Count: 1 +``` +## makefile + +```Makefile +ONAMESPACE=oracle-database-operator-system +NAMESPACE=[MY_NAMESPACE] +OCIPEN=[PATH_TO_OCI_API_KEY_PEM] +KUBECTL=/usr/bin/kubectl +CERTMANAGER=https://github.com/jetstack/cert-manager/releases/latest/download/cert-manager.yaml +RM=/usr/bin/rm + +certmanager: + $(KUBECTL) apply -f $(CERTMANAGER) + +prereq: step1 step2 step3 step4 step5 + +step1: configmap +step2: ociprivkey +step3: adminpass +step4: tdepass +step5: ocipubkey + + +configmap: + $(KUBECTL) create configmap oci-cred \ + --from-literal=tenancy=[MY_TENANCY_ID] + --from-literal=user=[MY_USER_ID] \ + --from-literal=fingerprint=[MY_FINGER_PRINT] \ + --from-literal=region=[MY_REGION] -n $(NAMESPACE) + +ociprivkey: + $(KUBECTL) create secret generic oci-privatekey --from-file=privatekey=[PATH_TO_OCI_API_KEY_PEM] -n $(NAMESPACE) + +adminpass: + echo "WElcome_12##" > ./admin-password + $(KUBECTL) create secret generic admin-password --from-file=./admin-password -n $(NAMESPACE) + $(RM) ./admin-password + +tdepass: + echo "WElcome_12##" > ./tde-password + $(KUBECTL) create secret generic tde-password --from-file=./tde-password -n $(NAMESPACE) + $(RM) ./tde-password + +ocipubkey: + #ssh-keygen -N "" -C "DBCS_System"-`date +%Y%m` -P "" + $(KUBECTL) create secret generic oci-publickey --from-file=publickey=/home/oracle/.ssh/id_rsa.pub -n $(NAMESPACE) + +clean: delprivkey delpubkey deladminpass delconfigmap deltdepass + +delconfigmap: + $(KUBECTL) delete configmap oci-cred -n $(NAMESPACE) +delprivkey: + $(KUBECTL) delete secret oci-privatekey -n $(NAMESPACE) +delpubkey: + $(KUBECTL) delete secret oci-publickey -n $(NAMESPACE) +deltdepass: + $(KUBECTL) delete secret tde-password -n $(NAMESPACE) +deladminpass: + $(KUBECTL) delete secret admin-password -n $(NAMESPACE) +checkmap: + $(KUBECTL) get configmaps oci-cred -o yaml -n $(NAMESPACE) |grep -A 5 -B 2 "^data:" +checkdbcs: + $(KUBECTL) describe dbcssystems.database.oracle.com dbcssystem-create -n $(NAMESPACE) +getall: + $(KUBECTL) get all -n $(NAMESPACE) +getmaps: + $(KUBECTL) get configmaps oci-cred -n $(NAMESPACE) -o yaml +descdbcss: + $(KUBECTL) describe dbcssystems.database.oracle.com dbcssystem-create -n $(NAMESPACE) +getdbcs: + $(KUBECTL) get DbcsSystem -n $(NAMESPACE) +create: + $(KUBECTL) apply -f dbcs_service_with_minimal_parameters.yaml -n $(NAMESPACE) +xlog1: + $(KUBECTL) logs -f pod/`$(KUBECTL) get pods -n $(ONAMESPACE)|grep oracle-database-operator-controller|head -1|cut -d ' ' -f 1` -n $(ONAMESPACE) +xlog2: + $(KUBECTL) logs -f pod/`$(KUBECTL) get pods -n $(ONAMESPACE)|grep oracle-database-operator-controller|head -2|tail -1|cut -d ' ' -f 1` -n $(ONAMESPACE) +xlog3: + $(KUBECTL) logs -f pod/`$(KUBECTL) get pods -n $(ONAMESPACE)|grep oracle-database-operator-controller|tail -1|cut -d ' ' -f 1` -n $(ONAMESPACE) +``` \ No newline at end of file diff --git a/docs/multitenant/NamespaceSeg.md b/docs/multitenant/NamespaceSeg.md new file mode 100644 index 00000000..6738fe56 --- /dev/null +++ b/docs/multitenant/NamespaceSeg.md @@ -0,0 +1,14 @@ + + +# Namespace segregation + +With the namespace segregation pdb controller and cdb controller run in different namespaces. The new functionality introduces a new parameter (the cdb namespace) in pdb crd definition. In case you don't need the namespace segregation you have to sepcify the namespace name that you are using for yours crd and pods anyway. Refer to usercase01 and usecase02 to see single namespace configuration. Refer to usecase03 to see examples of namespace segregation. + +# Secrets + +In order to use multiple namespace we need to create approriate secrets in each namespace. Tls certificate secrets must be created in all namespaces (db-ca db-tls). + +![general_schema](./images/K8S_NAMESPACE_SEG.png) + + + diff --git a/docs/multitenant/README.md b/docs/multitenant/README.md index 724c39e6..6c9a6756 100644 --- a/docs/multitenant/README.md +++ b/docs/multitenant/README.md @@ -1,24 +1,37 @@ +# Oracle Multitenant Database Controllers +The Oracle Database Operator for kubernetes uses two controllers to manage [Pluggable Database life cycle][oradocpdb] -# Oracle Multitenant Database Controller +- CDB controller +- PDB controller -> WARNING: Examples with https are located in the use case directories +By usigng CDB/PDB controllers you can perform the following actions **CREATE**,**MODIFY(OPEN/COSE)**,**DELETE**,**CLONE**,**PLUG** and **UNPLUG** -CDBs and PDBs are part of the Oracle Database [Multitenant Architecture](https://docs.oracle.com/en/database/oracle/oracle-database/21/multi/introduction-to-the-multitenant-architecture.html#GUID-AB84D6C9-4BBE-4D36-992F-2BB85739329F). The Multitenant Database Controller is a feature of Oracle DB Operator for Kubernetes (`OraOperator`), which helps to manage the lifecycle of Pluggable Databases (PDBs) in an Oracle Container Database (CDB). +This file examplains how to setup CDB and PDB controllers, additional details can be found in the README files under usecases directories.. -The target CDB for which PDB lifecycle management is needed can be running on a machine on-premises. To manage the PDBs of that target CDB, you can run the Oracle DB Operator on a Kubernetes system on-premises (For Example: [Oracle Linux Cloud Native Environment or OLCNE](https://docs.oracle.com/en/operating-systems/olcne/)). +- [Usecase01][uc01] pdb crd and cdb pod are running in the same namesaoce +- [Usecase02][uc02] unplug and plug operation examples +- [Usecase03][uc03] multiple namespace example cdb pod ,pdb crd and pod operator are running in different namespaces. -NOTE: The target CDB can also run in a Cloud environment, such as an OCI [Oracle Base Database Service](https://docs.oracle.com/en-us/iaas/dbcs/doc/bare-metal-and-virtual-machine-db-systems.html)). To manage PDBs on the target CDB, the Oracle DB Operator can run on a Kubernetes Cluster running in the cloud, such as OCI's [Container Engine for Kubernetes or OKE](https://docs.oracle.com/en-us/iaas/Content/ContEng/Concepts/contengoverview.htm#Overview_of_Container_Engine_for_Kubernetes)) +> **NOTE** that there is no controller for Container Database Operations +## Macro steps for setup +- Deply the Oracle Database Operator +- Create Ords based image for CDB pod +- Container DB user creation +- Create secrets for credentials +- Create certificates for https connection +- Create CDB pod -# Oracle DB Operator Multitenant Database Controller Deployment +## Oracle DB Operator Multitenant Database Controller Deployment To deploy OraOperator, use this [Oracle Database Operator for Kubernetes](https://github.com/oracle/oracle-database-operator/blob/main/README.md) step-by-step procedure. After the Oracle Database Operator is deployed, you can see the DB Operator Pods running in the Kubernetes Cluster. As part of the `OraOperator` deployment, the multitenant Database Controller is deployed. You can see the CRDs (Custom Resource Definition) for the CDB and PDBs in the list of CRDs. The following output is an example of such a deployment: + ```bash [root@test-server oracle-database-operator]# kubectl get ns NAME STATUS AGE @@ -29,7 +42,6 @@ kube-public Active 245d kube-system Active 245d oracle-database-operator-system Active 24h <<<< namespace to deploy the Oracle Database Operator - [root@test-server oracle-database-operator]# kubectl get all -n oracle-database-operator-system NAME READY STATUS RESTARTS AGE pod/oracle-database-operator-controller-manager-665874bd57-dlhls 1/1 Running 0 28s @@ -47,7 +59,6 @@ NAME DESIRED replicaset.apps/oracle-database-operator-controller-manager-665874bd57 3 3 3 29s [root@docker-test-server oracle-database-operator]# - [root@test-server oracle-database-operator]# kubectl get crd NAME CREATED AT autonomouscontainerdatabases.database.oracle.com 2022-06-22T01:21:36Z @@ -68,23 +79,18 @@ shardingdatabases.database.oracle.com 2022-06-22T01:21:39Z singleinstancedatabases.database.oracle.com 2022-06-22T01:21:40Z ``` -The following sections explain the setup and functionality of this controller. +## Prerequsites to manage PDB Life Cycle using Oracle DB Operator Multitenant Database Controller -# Prerequsites to manage PDB Life Cycle using Oracle DB Operator Multitenant Database Controller - -**CAUTION :** You must complete the following steps before managing the lifecycle of a PDB in a CDB using the Oracle DB Operator Multitenant Database Controller. - -* [Prepare CDB for PDB Lifecycle Management or PDB-LM](#prepare-cdb-for-pdb-lifecycle-management-pdb-lm) +* [Prepare the container database for PDB Lifecycle Management or PDB-LM](#prepare-cdb-for-pdb-lifecycle-management-pdb-lm) * [Oracle REST Data Service or ORDS Image](#oracle-rest-data-service-ords-image) * [Kubernetes Secrets](#kubernetes-secrets) * [Kubernetes CRD for CDB](#kubernetes-crd-for-cdb) * [Kubernetes CRD for PDB](#kubernetes-crd-for-pdb) +## Prepare the container database for PDB Lifecycle Management (PDB-LM) -+ ## Prepare CDB for PDB Lifecycle Management (PDB-LM) - -Pluggable Database (PDB) management operations are performed in the Container Database (CDB). These operations include create, clone, plug, unplug, delete, modify and map operations. +Pluggable Database (PDB) management operations are performed in the Container Database (CDB). These operations include create, clone, plug, unplug, delete, modify and map pdb. You cannot have an ORDS-enabled schema in the container database. To perform the PDB lifecycle management operations, you must first use the following steps to define the default CDB administrator credentials on target CDBs: @@ -110,27 +116,31 @@ col account_status for a30 select username, account_status from dba_users where username in ('ORDS_PUBLIC_USER','C##DBAPI_CDB_ADMIN','APEX_PUBLIC_USER','APEX_REST_PUBLIC_USER'); ``` -### Reference Setup: Example of a setup using OCI OKE(Kubernetes Cluster) and a CDB in Cloud (OCI Exadata Database Cluster) +## OCI OKE(Kubernetes Cluster) -See this [provisioning example setup](./provisioning/example_setup_using_oci_oke_cluster.md) for steps to configure a Kubernetes Cluster and a CDB. This example uses an OCI OKE Cluster as the Kubernetes Cluster and a CDB in OCI Exadata Database service. +You can use an [OKE in Oracle Cloud Infrastructure][okelink] to configure the operator for PDB lifecycle management. **Note that there is no restriction about container database location; it can be anywhere (on cloud or premises , on any supported platform).** +To quickly create an OKE cluster in your OCI cloud environment you can use the following [link](./provisioning/quickOKEcreation.md). +In this setup example [provisioning example setup](./provisioning/example_setup_using_oci_oke_cluster.md), the Container database is running on a OCI Exadata Database Cluster. -+ ## Oracle REST Data Service (ORDS) Image + +## Oracle REST Data Service (ORDS) Image - Oracle DB Operator Multitenant Database controller requires that the Oracle REST Data Services (ORDS) image for PDB Lifecycle Management is present in the target CDB. - - You can build this image by using the ORDS [Dockerfile](../../../ords/Dockerfile) + The PDB Database controllers require a pod running a dedicated rest server image based on [ORDS][ordsdoc]. Read the following [link](./provisioning/ords_image.md) to build the ords images. - For the steps to build the ORDS Docker image, see [ORDS_image](./provisioning/ords_image.md) +## Kubernetes Secrets + + Multitenant Controllers use Kubernetes Secrets to store the required credential. The https certificates are stored in Kubernetes Secrets as well. + **Note** In multi namespace enviroment you have to create specific secrets for each namespaces -+ ## Kubernetes Secrets + **Note** In multi namespace enviroment you have to create specific secrets for each namespaces - Oracle DB Operator Multitenant Database Controller uses Kubernetes Secrets to store usernames and passwords that you must have to manage the lifecycle operations of a PDB in the target CDB. In addition, to use https protocol, all certificates need to be stored using Kubernetes Secret. + **Note** In multi namespace enviroment you have to create specific secrets for each namespaces ### Secrets for CDB CRD - Create a secret file as shown here: [config/samples/multitenant/cdb_secret.yaml](../../config/samples/multitenant/cdb_secret.yaml). Modify this file with the `base64` encoded values of the required passwords for CDB, and use this file to create the required secrets. + Create a secret file as shown here: [config/samples/multitenant/cdb_secret.yaml](../multitenant/provisioning/singlenamespace/cdb_create.yaml). Modify this file with the `base64` encoded values of the required passwords for CDB, and use this file to create the required secrets. ```bash kubectl apply -f cdb_secret.yaml @@ -141,17 +151,16 @@ See this [provisioning example setup](./provisioning/example_setup_using_oci_oke ```bash echo -n "" | base64 ``` - The value that is returned is the base64-encoded value for that password string. **Note:** After successful creation of the CDB Resource, the CDB secrets are deleted from the Kubernetes system . ### Secrets for PDB CRD - Create a secret file as shown here: [config/samples/multitenant/pdb_secret.yaml](../../config/samples/multitenant/pdb_secret.yaml). Modify this file with the `base64` encoded values of the required passwords for PDB and use it to create the required secrets. + + Create a secret file as shown here: [pdb_secret.yaml](../multitenant/provisioning/singlenamespace/pdb_secret.yaml). Edit the file using your base64 credential and apply it. ```bash kubectl apply -f pdb_secret.yaml ``` - **NOTE:** To encode the password using `base64`, see the command example in the preceding **Secrets for CDB CRD** section. **NOTE:** Don't leave plaintext files containing sensitive data on disk. After loading the Secret, remove the plaintext file or move it to secure storage. @@ -159,11 +168,11 @@ See this [provisioning example setup](./provisioning/example_setup_using_oci_oke Create the certificates and key on your local host, and use them to create the Kubernetes secret. -```bash -genrsa -out ca.key 2048 -openssl req -new -x509 -days 365 -key ca.key -subj "/C=CN/ST=GD/L=SZ/O=oracle, Inc./CN=oracle Root CA" -out ca.crt -openssl req -newkey rsa:2048 -nodes -keyout tls.key -subj "/C=CN/ST=GD/L=SZ/O=oracle, Inc./CN=cdb-dev-ords" -out server.csr -/usr/bin/echo "subjectAltName=DNS:cdb-dev-ords,DNS:www.example.com" > extfile.txt +```bash +openssl genrsa -out ca.key 2048 +openssl req -new -x509 -days 365 -key ca.key -subj "/C=US/ST=California/L=SanFrancisco/O=oracle /CN=cdb-dev-ords /CN=localhost Root CA " -out ca.crt +openssl req -newkey rsa:2048 -nodes -keyout tls.key -subj "/C=US/ST=California/L=SanFrancisco/O=oracle /CN=cdb-dev-ords /CN=localhost" -out server.csr +echo "subjectAltName=DNS:cdb-dev-ords,DNS:www.example.com" > extfile.txt openssl x509 -req -extfile extfile.txt -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out tls.crt ``` @@ -173,43 +182,73 @@ kubectl create secret generic db-ca --from-file=ca.crt -n oracle-database-operat ``` image_not_found + **Note:** On successful creation of the certificates secret creation remove files or move to secure storage . -+ ## Kubernetes CRD for CDB +## Kubernetes CRD for CDB -The Oracle Database Operator Multitenant Controller creates the CDB kind as a custom resource that models a target CDB as a native Kubernetes object. This kind is used only to create Pods to connect to the target CDB to perform PDB-LM operations. These CDB resources can be scaled, based on the expected load, using replicas. Each CDB resource follows the CDB CRD as defined here: [config/crd/bases/database.oracle.com_cdbs.yaml](../../config/crd/bases/database.oracle.com_cdbs.yaml) +The Oracle Database Operator Multitenant Controller creates the CDB kind as a custom resource that models a target CDB as a native Kubernetes object. This kind is used only to create Pods to connect to the target CDB to perform PDB-LM operations. Each CDB resource follows the CDB CRD as defined here: [config/crd/bases/database.oracle.com_cdbs.yaml](../../config/crd/bases/database.oracle.com_cdbs.yaml) -To create a CDB CRD, see this example `.yaml` file: [config/samples/multitenant/cdb.yaml](../../config/samples/multitenant/cdb.yaml) +To create a CDB CRD, see this example `.yaml` file: [cdb_create.yaml](../multitenant/provisioning/singlenamespace/cdb_create.yaml) **Note:** The password and username fields in this *cdb.yaml* Yaml are the Kubernetes Secrets created earlier in this procedure. For more information, see the section [Kubernetes Secrets](https://kubernetes.io/docs/concepts/configuration/secret/). To understand more about creating secrets for pulling images from a Docker private registry, see [Kubernetes Private Registry Documenation]( https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/). -1. [Use Case: Create a CDB CRD Resource](./provisioning/cdb_crd_resource.md) -2. [Use Case: Add another replica to an existing CDB CRD Resource](./provisioning/add_replica.md) +Create a CDB CRD Resource example +```bash +kubectl apply -f cdb_create.yaml +``` -+ ## Kubernetes CRD for PDB +see [usecase01][uc01] and usecase03[uc03] for more information about file configuration -The Oracle Database Operator Multitenant Controller creates the PDB kind as a custom resource that models a PDB as a native Kubernetes object. There is a one-to-one mapping between the actual PDB and the Kubernetes PDB Custom Resource. You cannot have more than one Kubernetes resource for a target PDB. This PDB resource can be used to perform PDB-LM operations by specifying the action attribute in the PDB Specs. Each PDB resource follows the PDB CRD as defined here: [config/crd/bases/database.oracle.com_pdbs.yaml](../../../config/crd/bases/database.oracle.com_pdbs.yaml) +## Kubernetes CRD for PDB -To create a PDB CRD Resource, a sample .yaml file is available here: [config/samples/multitenant/pdb_create.yaml](../../config/samples/multitenant/pdb_create.yaml) +The Oracle Database Operator Multitenant Controller creates the PDB kind as a custom resource that models a PDB as a native Kubernetes object. There is a one-to-one mapping between the actual PDB and the Kubernetes PDB Custom Resource. You cannot have more than one Kubernetes resource for a target PDB. This PDB resource can be used to perform PDB-LM operations by specifying the action attribute in the PDB Specs. Each PDB resource follows the PDB CRD as defined here: [config/crd/bases/database.oracle.com_pdbs.yaml](../../../config/crd/bases/database.oracle.com_pdbs.yaml) -# Use Cases for PDB Lifecycle Management Operations using Oracle DB Operator Multitenant Controller +To create a PDB CRD Resource, a sample .yaml file is available here: [pdb_create.yaml](../multitenant/provisioning/singlenamespace/pdb_create.yaml) -Using the Oracle DB Operator Multitenant Controller, you can perform the following PDB-LM operations: CREATE, CLONE, MODIFY, DELETE, UNPLUG, PLUG. +```bash +kubectl apply -f cdb_create.yaml +``` -1. [Create PDB](./provisioning/create_pdb.md) -2. [Clone PDB](./provisioning/clone_pdb.md) -3. [Modify PDB](./provisioning/modify_pdb.md) -4. [Delete PDB](./provisioning/delete_pdb.md) -5. [Unplug PDB](./provisioning/unplug_pdb.md) -6. [Plug PDB](./provisioning/plug_pdb.md) +## Usecases files list +### Single Namespace -## Validation and Errors +1. [Create CDB](./provisioning/singlenamespace/cdb_create.yaml) +2. [Create PDB](./provisioning/singlenamespace/pdb_create.yaml) +3. [Clone PDB](./provisioning/singlenamespace/pdb_clone.yaml) +4. [Open PDB](./provisioning/singlenamespace/pdb_open.yaml) +4. [Close PDB](./provisioning/singlenamespace/pdb_close.yaml) +5. [Delete PDB](./provisioning/singlenamespace/pdb_delete.yaml) +6. [Unplug PDB](./provisioning/singlenamespace/pdb_unplug.yaml) +7. [Plug PDB](./provisioning/singlenamespace/pdb_plug.yaml) -To see how to look for any validation errors, see [validation_error](./provisioning/validation_error.md). +### Multiple namespace (cdbnamespace,dbnamespace) +1. [Create CDB](./provisioning/multinamespace/cdb_create.yaml) +2. [Create PDB](./provisioning/multinamespace/pdb_create.yaml) +3. [Clone PDB](./provisioning/multinamespace/pdb_clone.yaml) +4. [Open PDB](./provisioning/multinamespace/pdb_open.yaml) +4. [Close PDB](./provisioning/multinamespace/pdb_close.yaml) +5. [Delete PDB](./provisioning/multinamespace/pdb_delete.yaml) +6. [Unplug PDB](./provisioning/multinamespace/pdb_unplug.yaml) ## Known issues -To find out about known issue related to Oracle DB Operator Multitenant Controller, see [known_issues](./provisioning/known_issues.md). + - Ords installatian failure if pluaggable databases in the container db are not opened + + - Version 1.1.0: encoded password for https authentication may include carriege return as consequence the https request fails with http 404 error. W/A generate encoded password using **printf** instead of **echo**. + + - pdb controller authentication suddenly failes without any system change. Check the certificate expiration date **openssl .... -days 365** + + - Nothing happens after cdb yaml file applying: Make sure to have properly configure the WHATCH_NAMESPACE list in the operator yaml file + + [okelink]:https://docs.oracle.com/en-us/iaas/Content/ContEng/Concepts/contengoverview.htm + [ordsdoc]:https://docs.oracle.com/en/database/oracle/oracle-rest-data-services/23.1/index.html + [uc01]:../multitenant/usecase01/README.md + [uc02]:../multitenant/usecase02/README.md + [uc03]:../multitenant/usecase03/README.md + [oradocpdb]:https://docs.oracle.com/en/database/oracle/oracle-database/21/multi/introduction-to-the-multitenant-architecture.html#GUID-AB84D6C9-4BBE-4D36-992F-2BB85739329F + + \ No newline at end of file diff --git a/docs/multitenant/images/K8S_NAMESPACE_SEG.png b/docs/multitenant/images/K8S_NAMESPACE_SEG.png new file mode 100644 index 00000000..594471ed Binary files /dev/null and b/docs/multitenant/images/K8S_NAMESPACE_SEG.png differ diff --git a/docs/multitenant/provisioning/add_replica.log b/docs/multitenant/provisioning/add_replica.log deleted file mode 100644 index 53971443..00000000 --- a/docs/multitenant/provisioning/add_replica.log +++ /dev/null @@ -1,192 +0,0 @@ --- Check the status of CDB CRD Pod(s): - -% kubectl get all -n oracle-database-operator-system -NAME READY STATUS RESTARTS AGE -pod/cdb-dev-ords-rs-q2b68 1/1 Running 0 29s -pod/oracle-database-operator-controller-manager-76cb674c5c-4nrh8 1/1 Running 0 4d10h -pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd 1/1 Running 1 4d10h -pod/oracle-database-operator-controller-manager-76cb674c5c-xsv9g 1/1 Running 2 4d10h - -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -service/oracle-database-operator-controller-manager-metrics-service ClusterIP 10.96.98.47 8443/TCP 5d1h -service/oracle-database-operator-webhook-service ClusterIP 10.96.166.163 443/TCP 5d1h - -NAME READY UP-TO-DATE AVAILABLE AGE -deployment.apps/oracle-database-operator-controller-manager 3/3 3 3 5d1h - -NAME DESIRED CURRENT READY AGE -replicaset.apps/cdb-dev-ords-rs 1 1 1 31s -replicaset.apps/oracle-database-operator-controller-manager-76cb674c5c 3 3 3 5d1h - - --- .yaml file for the add replica use case: - -% cat add_replica.yaml -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: CDB -metadata: - name: cdb-dev - namespace: oracle-database-operator-system -spec: - cdbName: "goldcdb" - scanName: "goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com" - dbServer: "goldhost1.lbsub52b3b1cae.okecluster.oraclevcn.com" - ordsImage: phx.ocir.io//oracle/ords:21.4.3 - dbPort: 1521 - replicas: 2 - serviceName: "goldcdb_phx1pw.lbsub52b3b1cae.okecluster.oraclevcn.com" - sysAdminPwd: - secret: - secretName: "cdb1-secret" - key: "sysadmin_pwd" - ordsPwd: - secret: - secretName: "cdb1-secret" - key: "ords_pwd" - cdbAdminUser: - secret: - secretName: "cdb1-secret" - key: "cdbadmin_user" - cdbAdminPwd: - secret: - secretName: "cdb1-secret" - key: "cdbadmin_pwd" - webServerUser: - secret: - secretName: "cdb1-secret" - key: "webserver_user" - webServerPwd: - secret: - secretName: "cdb1-secret" - key: "webserver_pwd" - - - - --- Apply the .yaml file: - -% kubectl apply -f add_replica.yaml -cdb.database.oracle.com/cdb-dev configured - - - --- Check the status of the CDB CRD Pod(s): - -% kubectl get all -n oracle-database-operator-system -NAME READY STATUS RESTARTS AGE -pod/cdb-dev-ords-rs-5bztb 1/1 Running 0 21s << New Pod Added -pod/cdb-dev-ords-rs-q2b68 1/1 Running 0 7m40s -pod/oracle-database-operator-controller-manager-76cb674c5c-4nrh8 1/1 Running 0 4d10h -pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd 1/1 Running 1 4d10h -pod/oracle-database-operator-controller-manager-76cb674c5c-xsv9g 1/1 Running 2 4d10h - -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -service/cdb-dev-ords ClusterIP None 6m25s -service/oracle-database-operator-controller-manager-metrics-service ClusterIP 10.96.98.47 8443/TCP 5d2h -service/oracle-database-operator-webhook-service ClusterIP 10.96.166.163 443/TCP 5d2h - -NAME READY UP-TO-DATE AVAILABLE AGE -deployment.apps/oracle-database-operator-controller-manager 3/3 3 3 5d2h - -NAME DESIRED CURRENT READY AGE -replicaset.apps/cdb-dev-ords-rs 2 2 2 7m42s -replicaset.apps/oracle-database-operator-controller-manager-76cb674c5c 3 3 3 5d2h - - - - - --- Logs from Oracle DB Operator Pod: - -% kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -. -. -2022-06-27T03:24:34Z DEBUG controller-runtime.webhook.webhooks received request {"webhook": "/validate-database-oracle-com-v1alpha1-cdb", "UID": "19a3fbb6-57e4-4ad2-92c9-a90bb66cefae", "kind": "database.oracle.com/v1alpha1, Kind=CDB", "resource": {"group":"database.oracle.com","version":"v1alpha1","resource":"cdbs"}} -2022-06-27T03:24:34Z INFO cdb-webhook validate update {"name": "cdb-dev"} -2022-06-27T03:24:34Z DEBUG controller-runtime.webhook.webhooks wrote response {"webhook": "/validate-database-oracle-com-v1alpha1-cdb", "code": 200, "reason": "", "UID": "19a3fbb6-57e4-4ad2-92c9-a90bb66cefae", "allowed": true} -2022-06-27T03:24:34Z INFO controllers.CDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:24:34Z INFO controllers.CDB Res Status: {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "Ready", "Status": "true"} -2022-06-27T03:24:34Z INFO controllers.CDB Existing Replicas: 1, New Replicas: 2 {"evaluateSpecChange": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:24:34Z INFO controllers.CDB Current Phase:ValidatingPods {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev"} -2022-06-27T03:24:34Z INFO controllers.CDB Validating Pod creation for :cdb-dev {"validateORDSPod": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:24:34Z INFO controller.cdb Executing Command : {"reconciler group": "database.oracle.com", "reconciler kind": "CDB", "name": "cdb-dev", "namespace": "oracle-database-operator-system", "ExecCommand": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:24:34Z INFO controller.cdb bash -c curl -sSkv -k -X GET https://localhost:8888/ords/_/db-api/stable/metadata-catalog/ || curl -sSkv -X GET http://localhost:8888/ords/_/db-api/stable/metadata-catalog/ {"reconciler group": "database.oracle.com", "reconciler kind": "CDB", "name": "cdb-dev", "namespace": "oracle-database-operator-system", "ExecCommand": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:24:35Z INFO controllers.CDB Replicas: 2 {"validateORDSPod": "oracle-database-operator-system/cdb-dev", "Ready Pods: ": 1} -2022-06-27T03:24:35Z INFO controllers.CDB Reconcile queued {"onpremdboperator": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:24:35Z INFO controllers.CDB DEFER {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "ValidatingPods", "Status": "false"} -2022-06-27T03:24:50Z INFO controllers.CDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:24:50Z INFO controllers.CDB Res Status: {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "ValidatingPods", "Status": "false"} -2022-06-27T03:24:50Z INFO controllers.CDB Current Phase:ValidatingPods {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev"} -2022-06-27T03:24:50Z INFO controllers.CDB Validating Pod creation for :cdb-dev {"validateORDSPod": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:24:50Z INFO controller.cdb Executing Command : {"reconciler group": "database.oracle.com", "reconciler kind": "CDB", "name": "cdb-dev", "namespace": "oracle-database-operator-system", "ExecCommand": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:24:50Z INFO controller.cdb bash -c curl -sSkv -k -X GET https://localhost:8888/ords/_/db-api/stable/metadata-catalog/ || curl -sSkv -X GET http://localhost:8888/ords/_/db-api/stable/metadata-catalog/ {"reconciler group": "database.oracle.com", "reconciler kind": "CDB", "name": "cdb-dev", "namespace": "oracle-database-operator-system", "ExecCommand": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:24:50Z INFO controller.cdb Executing Command : {"reconciler group": "database.oracle.com", "reconciler kind": "CDB", "name": "cdb-dev", "namespace": "oracle-database-operator-system", "ExecCommand": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:24:50Z INFO controller.cdb bash -c curl -sSkv -k -X GET https://localhost:8888/ords/_/db-api/stable/metadata-catalog/ || curl -sSkv -X GET http://localhost:8888/ords/_/db-api/stable/metadata-catalog/ {"reconciler group": "database.oracle.com", "reconciler kind": "CDB", "name": "cdb-dev", "namespace": "oracle-database-operator-system", "ExecCommand": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:24:50Z INFO controllers.CDB Replicas: 2 {"validateORDSPod": "oracle-database-operator-system/cdb-dev", "Ready Pods: ": 1} -2022-06-27T03:24:50Z INFO controllers.CDB Reconcile queued {"onpremdboperator": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:24:50Z INFO controllers.CDB DEFER {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "ValidatingPods", "Status": "false"} -2022-06-27T03:25:05Z INFO controllers.CDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:25:05Z INFO controllers.CDB Res Status: {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "ValidatingPods", "Status": "false"} -2022-06-27T03:25:05Z INFO controllers.CDB Current Phase:ValidatingPods {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev"} -2022-06-27T03:25:05Z INFO controllers.CDB Validating Pod creation for :cdb-dev {"validateORDSPod": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:25:05Z INFO controller.cdb Executing Command : {"reconciler group": "database.oracle.com", "reconciler kind": "CDB", "name": "cdb-dev", "namespace": "oracle-database-operator-system", "ExecCommand": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:25:05Z INFO controller.cdb bash -c curl -sSkv -k -X GET https://localhost:8888/ords/_/db-api/stable/metadata-catalog/ || curl -sSkv -X GET http://localhost:8888/ords/_/db-api/stable/metadata-catalog/ {"reconciler group": "database.oracle.com", "reconciler kind": "CDB", "name": "cdb-dev", "namespace": "oracle-database-operator-system", "ExecCommand": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:25:05Z INFO controller.cdb Executing Command : {"reconciler group": "database.oracle.com", "reconciler kind": "CDB", "name": "cdb-dev", "namespace": "oracle-database-operator-system", "ExecCommand": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:25:05Z INFO controller.cdb bash -c curl -sSkv -k -X GET https://localhost:8888/ords/_/db-api/stable/metadata-catalog/ || curl -sSkv -X GET http://localhost:8888/ords/_/db-api/stable/metadata-catalog/ {"reconciler group": "database.oracle.com", "reconciler kind": "CDB", "name": "cdb-dev", "namespace": "oracle-database-operator-system", "ExecCommand": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:25:06Z INFO controllers.CDB DEFER {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "CreatingService", "Status": "false"} -2022-06-27T03:25:21Z INFO controllers.CDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:25:21Z INFO controllers.CDB Res Status: {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "CreatingService", "Status": "false"} -2022-06-27T03:25:21Z INFO controllers.CDB Current Phase:CreatingService {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev"} -2022-06-27T03:25:21Z INFO controllers.CDB ORDS Cluster Service already exists {"createORDSSVC": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:25:21Z INFO controllers.CDB DEFER {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "Ready", "Status": "false"} -2022-06-27T03:25:36Z INFO controllers.CDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:25:36Z INFO controllers.CDB Res Status: {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "Ready", "Status": "false"} -2022-06-27T03:25:36Z INFO controllers.CDB Current Phase:Ready {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev"} -2022-06-27T03:25:36Z INFO controllers.CDB DEFER {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "Ready", "Status": "true"} - - - --- Logs of the newly added CDB CRD Pod: - -% kubectl logs -f pod/cdb-dev-ords-rs-5bztb -n oracle-database-operator-system - -Retrieving information. -Requires to login with administrator privileges to verify Oracle REST Data Services schema. - -Connecting to database user: SYS AS SYSDBA url: jdbc:oracle:thin:@//goldhost1.lbsub52b3b1cae.okecluster.oraclevcn.com:1521/goldcdb_phx1pw.lbsub52b3b1cae.okecluster.oraclevcn.com - -Retrieving information.. -Completed verifying Oracle REST Data Services schema version 21.4.3.r1170405. -2022-06-27T03:24:40.351Z INFO reloaded pools: [] -2022-06-27T03:24:40.353Z INFO Oracle REST Data Services schema version 21.4.3.r1170405 is installed. -spawn java -jar /opt/oracle/ords/ords.war user sql_admin SQL Administrator -Enter a password for user sql_admin: -Confirm password for user sql_admin: -2022-06-27T03:24:42.034Z INFO Created user: sql_admin in file: /opt/oracle/ords/config/ords/credentials -2022-06-27T03:24:43.666Z INFO Modified: /opt/oracle/ords/config/ords/conf/apex_pu.xml, updated properties: database.api.admin.enabled, db.cdb.adminUser, db.cdb.adminUser.password -2022-06-27T03:24:45.455Z INFO HTTP and HTTP/2 cleartext listening on host: localhost port: 8888 -2022-06-27T03:24:45.520Z INFO The document root is serving static resources located in: /opt/oracle/ords/doc_root -2022-06-27T03:24:47.515Z INFO Configuration properties for: |apex|pu| -db.servicename=goldcdb_phx1pw.lbsub52b3b1cae.okecluster.oraclevcn.com -db.hostname=goldhost1.lbsub52b3b1cae.okecluster.oraclevcn.com -database.api.admin.enabled=true -db.password=****** -db.cdb.adminUser.password=****** -database.api.enabled=true -db.cdb.adminUser=C##DBAPI_CDB_ADMIN as SYSDBA -db.username=ORDS_PUBLIC_USER -restEnabledSql.active=true -resource.templates.enabled=true -db.port=1521 -feature.sdw=true -db.connectionType=basic - -2022-06-27T03:24:47.517Z WARNING *** jdbc.MaxLimit in configuration |apex|pu| is using a value of 10, this setting may not be sized adequately for a production environment *** -2022-06-27T03:24:47.517Z WARNING *** jdbc.InitialLimit in configuration |apex|pu| is using a value of 3, this setting may not be sized adequately for a production environment *** -2022-06-27T03:24:51.761Z INFO Oracle REST Data Services initialized -Oracle REST Data Services version : 21.4.3.r1170405 -Oracle REST Data Services server info: jetty/9.4.44.v20210927 diff --git a/docs/multitenant/provisioning/add_replica.md b/docs/multitenant/provisioning/add_replica.md deleted file mode 100644 index 1315dc9f..00000000 --- a/docs/multitenant/provisioning/add_replica.md +++ /dev/null @@ -1,36 +0,0 @@ -# Add a new replicate to an existing CDB CRD Resource using Oracle DB Operator On-Prem Controller - -In this use case, using the Oracle Database Operator On-Prem Controller, you will add a new replica to an existing CDB CRD resource. - -**NOTE:** It is assumed that before this step, you have followed the [prerequisite](./../README.md#prerequsites-to-manage-pdb-life-cycle-using-oracle-db-operator-on-prem-database-controller) steps. - -This example uses `add_replica.yaml` with: - -- CDB CRD resource Name as `cdb-dev` -- Container Database (CDB) Name as `goldcdb` -- Scan Name as `goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com` -- Database Server Name as `goldhost1.lbsub52b3b1cae.okecluster.oraclevcn.com` -- ORDS Docker Image as `phx.ocir.io//oracle/ords:21.4.3` -- Database Listener Port as `1521` -- Number of replicas for CDB CRD Resource as 2. - -**NOTE:** For the details of the parameters to be used in the .yaml file, please refer [config/crd/bases/database.oracle.com_cdbs.yaml](../../../config/crd/bases/database.oracle.com_cdbs.yaml) - -Use the file: [add_replica.yaml](./add_replica.yaml) for this use case as below: - -1. Deploy the .yaml file: -```sh -[root@test-server oracle-database-operator]# kubectl apply -f add_replica.yaml -``` - -2. Monitor the Oracle DB Operator Pod for the progress of the CDB CRD Resource creation. - -NOTE: Check the DB Operator Pod name in your environment. - -``` -[root@test-server oracle-database-operator]# kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -``` - -## Sample Output - -[Here](./add_replica.log) is the sample output for a PDB created using Oracle DB Operator On-Prem Controller using file [add_replica.yaml](./add_replica.yaml) diff --git a/docs/multitenant/provisioning/add_replica.yaml b/docs/multitenant/provisioning/add_replica.yaml deleted file mode 100644 index fac2d7ba..00000000 --- a/docs/multitenant/provisioning/add_replica.yaml +++ /dev/null @@ -1,40 +0,0 @@ -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: CDB -metadata: - name: cdb-dev - namespace: oracle-database-operator-system -spec: - cdbName: "goldcdb" - dbServer: "goldhost1.lbsub52b3b1cae.okecluster.oraclevcn.com" - ordsImage: phx.ocir.io//oracle/ords:21.4.3 - dbPort: 1521 - replicas: 2 - serviceName: "goldcdb_phx1pw.lbsub52b3b1cae.okecluster.oraclevcn.com" - sysAdminPwd: - secret: - secretName: "cdb1-secret" - key: "sysadmin_pwd" - ordsPwd: - secret: - secretName: "cdb1-secret" - key: "ords_pwd" - cdbAdminUser: - secret: - secretName: "cdb1-secret" - key: "cdbadmin_user" - cdbAdminPwd: - secret: - secretName: "cdb1-secret" - key: "cdbadmin_pwd" - webServerUser: - secret: - secretName: "cdb1-secret" - key: "webserver_user" - webServerPwd: - secret: - secretName: "cdb1-secret" - key: "webserver_pwd" diff --git a/docs/multitenant/provisioning/cdb.log b/docs/multitenant/provisioning/cdb.log deleted file mode 100644 index 8c3cbdc5..00000000 --- a/docs/multitenant/provisioning/cdb.log +++ /dev/null @@ -1,279 +0,0 @@ --- Check the status of the Oracle DB Operator Pods: - -% kubectl get all -n oracle-database-operator-system -NAME READY STATUS RESTARTS AGE -pod/oracle-database-operator-controller-manager-76cb674c5c-4nrh8 1/1 Running 0 29h -pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd 1/1 Running 1 29h -pod/oracle-database-operator-controller-manager-76cb674c5c-xsv9g 1/1 Running 2 29h - -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -service/oracle-database-operator-controller-manager-metrics-service ClusterIP 10.96.98.47 8443/TCP 45h -service/oracle-database-operator-webhook-service ClusterIP 10.96.166.163 443/TCP 45h - -NAME READY UP-TO-DATE AVAILABLE AGE -deployment.apps/oracle-database-operator-controller-manager 3/3 3 3 45h - -NAME DESIRED CURRENT READY AGE -replicaset.apps/oracle-database-operator-controller-manager-76cb674c5c 3 3 3 45h - - - --- Get the base64 values for the required passwords as below: - -% echo -n "WElcome_21##" | base64 -V0VsY29tZV8yMSMj - -% echo -n "C##DBAPI_CDB_ADMIN" | base64 -QyMjREJBUElfQ0RCX0FETUlO - -% echo -n "sql_admin" | base64 -c3FsX2FkbWlu - -% echo -n "welcome1" | base64 -d2VsY29tZTE= - - --- Add the base64 encoded values against the required variables in cdb_secret.yaml file for this use case: - -% cat cdb_secret.yaml -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: v1 -kind: Secret -metadata: - name: cdb1-secret - namespace: oracle-database-operator-system -type: Opaque -data: - ords_pwd: "V0VsY29tZV8yMSMj" - sysadmin_pwd: "V0VsY29tZV8yMSMj" - cdbadmin_user: "QyMjREJBUElfQ0RCX0FETUlO" - cdbadmin_pwd: "V0VsY29tZV8yMSMj" - webserver_user: "c3FsX2FkbWlu" - webserver_pwd: "d2VsY29tZTE=" - - --- Check the contents of the cdb.yaml file: -% cat cdb.yaml -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: CDB -metadata: - name: cdb-dev - namespace: oracle-database-operator-system -spec: - cdbName: "goldcdb" - scanName: "goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com" - dbServer: "goldhost1.lbsub52b3b1cae.okecluster.oraclevcn.com" - ordsImage: phx.ocir.io//oracle/ords:21.4.3 - ordsImagePullSecret: "container-registry-secret" - dbPort: 1521 - replicas: 1 - serviceName: "goldcdb_phx1pw.lbsub52b3b1cae.okecluster.oraclevcn.com" - sysAdminPwd: - secret: - secretName: "cdb1-secret" - key: "sysadmin_pwd" - ordsPwd: - secret: - secretName: "cdb1-secret" - key: "ords_pwd" - cdbAdminUser: - secret: - secretName: "cdb1-secret" - key: "cdbadmin_user" - cdbAdminPwd: - secret: - secretName: "cdb1-secret" - key: "cdbadmin_pwd" - webServerUser: - secret: - secretName: "cdb1-secret" - key: "webserver_user" - webServerPwd: - secret: - secretName: "cdb1-secret" - key: "webserver_pwd" - - - --- Apply the .yaml files: - -% kubectl apply -f cdb_secret.yaml -secret/cdb1-secret created - -% kubectl apply -f cdb.yaml -cdb.database.oracle.com/cdb-dev created - - - --- Monitor the Oracle DB Operator Pod during the period when the CDB CRD is getting deployed: - -% kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -. -. -2022-06-27T03:16:44Z INFO controllers.CDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:16:44Z INFO controllers.CDB Res Status: {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "", "Status": "false"} -2022-06-27T03:16:44Z INFO controllers.CDB Adding finalizer {"manageCDBDeletion": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:16:44Z INFO controllers.CDB Current Phase: {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev"} -2022-06-27T03:16:44Z INFO controllers.CDB DEFAULT: {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "", "Status": "false"} -2022-06-27T03:16:44Z INFO controllers.CDB DEFER {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "Initializing", "Status": "false"} -2022-06-27T03:17:00Z INFO controllers.CDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:17:00Z INFO controllers.CDB Res Status: {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "Initializing", "Status": "false"} -2022-06-27T03:17:00Z INFO controllers.CDB Current Phase:Initializing {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev"} -2022-06-27T03:17:00Z INFO controllers.CDB Verified secrets successfully {"verifySecrets": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:17:00Z INFO controllers.CDB DEFER {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "CreatingPod", "Status": "false"} -2022-06-27T03:17:15Z INFO controllers.CDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:17:15Z INFO controllers.CDB Res Status: {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "CreatingPod", "Status": "false"} -2022-06-27T03:17:15Z INFO controllers.CDB Current Phase:CreatingPod {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev"} -2022-06-27T03:17:15Z INFO controllers.CDB Creating ORDS Replicaset: cdb-dev-ords-rs {"createORDSInstances": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:17:15Z INFO controllers.CDB Created ORDS ReplicaSet successfully {"createORDSInstances": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:17:15Z DEBUG events Normal {"object": {"kind":"CDB","namespace":"oracle-database-operator-system","name":"cdb-dev","uid":"c36e8d5f-6103-4a70-a840-16c6683755ec","apiVersion":"database.oracle.com/v1alpha1","resourceVersion":"101443216"}, "reason": "CreatedORDSReplicaSet", "message": "Created ORDS Replicaset (Replicas - 1) for cdb-dev"} -2022-06-27T03:17:15Z INFO controllers.CDB DEFER {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "ValidatingPods", "Status": "false"} -2022-06-27T03:17:30Z INFO controllers.CDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:17:30Z INFO controllers.CDB Res Status: {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "ValidatingPods", "Status": "false"} -2022-06-27T03:17:30Z INFO controllers.CDB Current Phase:ValidatingPods {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev"} -2022-06-27T03:17:30Z INFO controllers.CDB Validating Pod creation for :cdb-dev {"validateORDSPod": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:17:30Z INFO controller.cdb Executing Command : {"reconciler group": "database.oracle.com", "reconciler kind": "CDB", "name": "cdb-dev", "namespace": "oracle-database-operator-system", "ExecCommand": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:17:30Z INFO controller.cdb bash -c curl -sSkv -k -X GET https://localhost:8888/ords/_/db-api/stable/metadata-catalog/ || curl -sSkv -X GET http://localhost:8888/ords/_/db-api/stable/metadata-catalog/ {"reconciler group": "database.oracle.com", "reconciler kind": "CDB", "name": "cdb-dev", "namespace": "oracle-database-operator-system", "ExecCommand": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:17:30Z INFO controllers.CDB Replicas: 1 {"validateORDSPod": "oracle-database-operator-system/cdb-dev", "Ready Pods: ": 0} -2022-06-27T03:17:30Z INFO controllers.CDB Reconcile queued {"onpremdboperator": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:17:30Z INFO controllers.CDB DEFER {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "ValidatingPods", "Status": "false"} -2022-06-27T03:17:45Z INFO controllers.CDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:17:45Z INFO controllers.CDB Res Status: {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "ValidatingPods", "Status": "false"} -2022-06-27T03:17:45Z INFO controllers.CDB Current Phase:ValidatingPods {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev"} -2022-06-27T03:17:45Z INFO controllers.CDB Validating Pod creation for :cdb-dev {"validateORDSPod": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:17:45Z INFO controller.cdb Executing Command : {"reconciler group": "database.oracle.com", "reconciler kind": "CDB", "name": "cdb-dev", "namespace": "oracle-database-operator-system", "ExecCommand": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:17:45Z INFO controller.cdb bash -c curl -sSkv -k -X GET https://localhost:8888/ords/_/db-api/stable/metadata-catalog/ || curl -sSkv -X GET http://localhost:8888/ords/_/db-api/stable/metadata-catalog/ {"reconciler group": "database.oracle.com", "reconciler kind": "CDB", "name": "cdb-dev", "namespace": "oracle-database-operator-system", "ExecCommand": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:17:45Z INFO controllers.CDB Replicas: 1 {"validateORDSPod": "oracle-database-operator-system/cdb-dev", "Ready Pods: ": 0} -2022-06-27T03:17:45Z INFO controllers.CDB Reconcile queued {"onpremdboperator": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:17:45Z INFO controllers.CDB DEFER {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "ValidatingPods", "Status": "false"} -2022-06-27T03:18:00Z INFO controllers.CDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:18:00Z INFO controllers.CDB Res Status: {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "ValidatingPods", "Status": "false"} -2022-06-27T03:18:00Z INFO controllers.CDB Current Phase:ValidatingPods {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev"} -2022-06-27T03:18:00Z INFO controllers.CDB Validating Pod creation for :cdb-dev {"validateORDSPod": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:18:00Z INFO controller.cdb Executing Command : {"reconciler group": "database.oracle.com", "reconciler kind": "CDB", "name": "cdb-dev", "namespace": "oracle-database-operator-system", "ExecCommand": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:18:00Z INFO controller.cdb bash -c curl -sSkv -k -X GET https://localhost:8888/ords/_/db-api/stable/metadata-catalog/ || curl -sSkv -X GET http://localhost:8888/ords/_/db-api/stable/metadata-catalog/ {"reconciler group": "database.oracle.com", "reconciler kind": "CDB", "name": "cdb-dev", "namespace": "oracle-database-operator-system", "ExecCommand": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:18:01Z INFO controllers.CDB Replicas: 1 {"validateORDSPod": "oracle-database-operator-system/cdb-dev", "Ready Pods: ": 0} -2022-06-27T03:18:01Z INFO controllers.CDB Reconcile queued {"onpremdboperator": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:18:01Z INFO controllers.CDB DEFER {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "ValidatingPods", "Status": "false"} -2022-06-27T03:18:16Z INFO controllers.CDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:18:16Z INFO controllers.CDB Res Status: {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "ValidatingPods", "Status": "false"} -2022-06-27T03:18:16Z INFO controllers.CDB Current Phase:ValidatingPods {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev"} -2022-06-27T03:18:16Z INFO controllers.CDB Validating Pod creation for :cdb-dev {"validateORDSPod": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:18:16Z INFO controller.cdb Executing Command : {"reconciler group": "database.oracle.com", "reconciler kind": "CDB", "name": "cdb-dev", "namespace": "oracle-database-operator-system", "ExecCommand": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:18:16Z INFO controller.cdb bash -c curl -sSkv -k -X GET https://localhost:8888/ords/_/db-api/stable/metadata-catalog/ || curl -sSkv -X GET http://localhost:8888/ords/_/db-api/stable/metadata-catalog/ {"reconciler group": "database.oracle.com", "reconciler kind": "CDB", "name": "cdb-dev", "namespace": "oracle-database-operator-system", "ExecCommand": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:18:16Z INFO controllers.CDB DEFER {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "CreatingService", "Status": "false"} -2022-06-27T03:18:31Z INFO controllers.CDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:18:31Z INFO controllers.CDB Res Status: {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "CreatingService", "Status": "false"} -2022-06-27T03:18:31Z INFO controllers.CDB Current Phase:CreatingService {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev"} -2022-06-27T03:18:31Z INFO controllers.CDB Creating a new Cluster Service for: cdb-dev {"createORDSSVC": "oracle-database-operator-system/cdb-dev", "Svc.Namespace": "oracle-database-operator-system", "Service.Name": "cdb-dev-ords"} -2022-06-27T03:18:31Z INFO controllers.CDB Created ORDS Cluster Service successfully {"createORDSSVC": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:18:31Z DEBUG events Normal {"object": {"kind":"CDB","namespace":"oracle-database-operator-system","name":"cdb-dev","uid":"c36e8d5f-6103-4a70-a840-16c6683755ec","apiVersion":"database.oracle.com/v1alpha1","resourceVersion":"101443627"}, "reason": "CreatedORDSService", "message": "Created ORDS Service for cdb-dev"} -2022-06-27T03:18:31Z INFO controllers.CDB DEFER {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "Ready", "Status": "false"} -2022-06-27T03:18:46Z INFO controllers.CDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/cdb-dev"} -2022-06-27T03:18:46Z INFO controllers.CDB Res Status: {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "Ready", "Status": "false"} -2022-06-27T03:18:46Z INFO controllers.CDB Current Phase:Ready {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev"} -2022-06-27T03:18:46Z INFO controllers.CDB DEFER {"onpremdboperator": "oracle-database-operator-system/cdb-dev", "Name": "cdb-dev", "Phase": "Ready", "Status": "true"} - - - - --- Check the status of the CDB CRD Pod after few minutes of running above commands: - -% kubectl get all -n oracle-database-operator-system -NAME READY STATUS RESTARTS AGE -pod/cdb-dev-ords-rs-q2b68 1/1 Running 0 29s <<< CDB CRD Resource Pod -pod/oracle-database-operator-controller-manager-76cb674c5c-4nrh8 1/1 Running 0 4d10h -pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd 1/1 Running 1 4d10h -pod/oracle-database-operator-controller-manager-76cb674c5c-xsv9g 1/1 Running 2 4d10h - -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -service/oracle-database-operator-controller-manager-metrics-service ClusterIP 10.96.98.47 8443/TCP 5d1h -service/oracle-database-operator-webhook-service ClusterIP 10.96.166.163 443/TCP 5d1h - -NAME READY UP-TO-DATE AVAILABLE AGE -deployment.apps/oracle-database-operator-controller-manager 3/3 3 3 5d1h - -NAME DESIRED CURRENT READY AGE -replicaset.apps/cdb-dev-ords-rs 1 1 1 31s -replicaset.apps/oracle-database-operator-controller-manager-76cb674c5c 3 3 3 5d1h - - - - --- Check the logs of the CDB CRD Pod created above: - -% kubectl logs -f pod/cdb-dev-ords-rs-q2b68 -n oracle-database-operator-system -Requires to login with administrator privileges to verify Oracle REST Data Services schema. - -Connecting to database user: SYS AS SYSDBA url: jdbc:oracle:thin:@//goldhost1.lbsub52b3b1cae.okecluster.oraclevcn.com:1521/goldcdb_phx1pw.lbsub52b3b1cae.okecluster.oraclevcn.com - -Retrieving information.. -Your database connection is to a CDB. ORDS common user ORDS_PUBLIC_USER will be created in the CDB. ORDS schema will be installed in the PDBs. -Root CDB$ROOT - create ORDS common user -PDB PDB$SEED - install ORDS 21.4.3.r1170405 - -2022-06-27T03:17:22.015Z INFO reloaded pools: [] -2022-06-27T03:17:22.024Z INFO - -2022-06-27T03:17:23.200Z INFO Installing Oracle REST Data Services version 21.4.3.r1170405 in CDB$ROOT -2022-06-27T03:17:23.234Z INFO ... Log file written to /home/oracle/ords_cdb_install_core_CDB_ROOT_2022-06-27_031723_00234.log -2022-06-27T03:17:24.352Z INFO ... Verified database prerequisites -2022-06-27T03:17:24.662Z INFO ... Created Oracle REST Data Services proxy user -2022-06-27T03:17:24.708Z INFO Completed installation for Oracle REST Data Services version 21.4.3.r1170405. Elapsed time: 00:00:01.504 - -2022-06-27T03:17:24.722Z INFO Installing Oracle REST Data Services version 21.4.3.r1170405 in PDB$SEED -2022-06-27T03:17:24.731Z INFO ... Log file written to /home/oracle/ords_cdb_install_core_PDB_SEED_2022-06-27_031724_00731.log -2022-06-27T03:17:24.863Z INFO ... Verified database prerequisites -2022-06-27T03:17:25.123Z INFO ... Created Oracle REST Data Services proxy user -2022-06-27T03:17:25.568Z INFO ... Created Oracle REST Data Services schema -2022-06-27T03:17:26.252Z INFO ... Granted privileges to Oracle REST Data Services -2022-06-27T03:17:34.493Z INFO ... Created Oracle REST Data Services database objects -2022-06-27T03:17:43.730Z INFO ... Log file written to /home/oracle/ords_cdb_install_datamodel_PDB_SEED_2022-06-27_031743_00730.log -2022-06-27T03:17:45.883Z INFO ... Log file written to /home/oracle/ords_cdb_install_scheduler_PDB_SEED_2022-06-27_031745_00883.log -2022-06-27T03:17:49.296Z INFO ... Log file written to /home/oracle/ords_cdb_install_apex_PDB_SEED_2022-06-27_031749_00296.log -2022-06-27T03:17:51.492Z INFO Completed installation for Oracle REST Data Services version 21.4.3.r1170405. Elapsed time: 00:00:26.768 - -2022-06-27T03:17:51.492Z INFO Completed CDB installation for Oracle REST Data Services version 21.4.3.r1170405. Total elapsed time: 00:00:28.297 - -spawn java -jar /opt/oracle/ords/ords.war user sql_admin SQL Administrator -Enter a password for user sql_admin: -Confirm password for user sql_admin: -2022-06-27T03:17:53.192Z INFO Created user: sql_admin in file: /opt/oracle/ords/config/ords/credentials -2022-06-27T03:17:54.816Z INFO Modified: /opt/oracle/ords/config/ords/conf/apex_pu.xml, updated properties: database.api.admin.enabled, db.cdb.adminUser, db.cdb.adminUser.password -2022-06-27T03:17:56.583Z INFO HTTP and HTTP/2 cleartext listening on host: localhost port: 8888 -2022-06-27T03:17:56.647Z INFO The document root is serving static resources located in: /opt/oracle/ords/doc_root -2022-06-27T03:17:58.593Z INFO Configuration properties for: |apex|pu| -db.servicename=goldcdb_phx1pw.lbsub52b3b1cae.okecluster.oraclevcn.com -db.hostname=goldhost1.lbsub52b3b1cae.okecluster.oraclevcn.com -database.api.admin.enabled=true -db.password=****** -db.cdb.adminUser.password=****** -database.api.enabled=true -db.cdb.adminUser=C##DBAPI_CDB_ADMIN as SYSDBA -db.username=ORDS_PUBLIC_USER -restEnabledSql.active=true -resource.templates.enabled=true -db.port=1521 -feature.sdw=true -db.connectionType=basic - -2022-06-27T03:17:58.595Z WARNING *** jdbc.MaxLimit in configuration |apex|pu| is using a value of 10, this setting may not be sized adequately for a production environment *** -2022-06-27T03:17:58.595Z WARNING *** jdbc.InitialLimit in configuration |apex|pu| is using a value of 3, this setting may not be sized adequately for a production environment *** -2022-06-27T03:18:02.803Z INFO Oracle REST Data Services initialized -Oracle REST Data Services version : 21.4.3.r1170405 -Oracle REST Data Services server info: jetty/9.4.44.v20210927 - - - --- Check the CDB CRD Resource and it should be in "Ready" status for a successful deployment: - -% kubectl get cdbs -A -NAMESPACE NAME CDB NAME DB SERVER DB PORT SCAN NAME REPLICAS STATUS MESSAGE -oracle-database-operator-system cdb-dev goldcdb goldhost1.lbsub52b3b1cae.okecluster.oraclevcn.com 1521 goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com 1 Ready diff --git a/docs/multitenant/provisioning/cdb.yaml b/docs/multitenant/provisioning/cdb.yaml deleted file mode 100644 index 8e25a763..00000000 --- a/docs/multitenant/provisioning/cdb.yaml +++ /dev/null @@ -1,41 +0,0 @@ -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: CDB -metadata: - name: cdb-dev - namespace: oracle-database-operator-system -spec: - cdbName: "goldcdb" - dbServer: "goldhost1.lbsub52b3b1cae.okecluster.oraclevcn.com" - ordsImage: phx.ocir.io//oracle/ords:21.4.3 - ordsImagePullSecret: "container-registry-secret" - dbPort: 1521 - replicas: 1 - serviceName: "goldcdb_phx1pw.lbsub52b3b1cae.okecluster.oraclevcn.com" - sysAdminPwd: - secret: - secretName: "cdb1-secret" - key: "sysadmin_pwd" - ordsPwd: - secret: - secretName: "cdb1-secret" - key: "ords_pwd" - cdbAdminUser: - secret: - secretName: "cdb1-secret" - key: "cdbadmin_user" - cdbAdminPwd: - secret: - secretName: "cdb1-secret" - key: "cdbadmin_pwd" - webServerUser: - secret: - secretName: "cdb1-secret" - key: "webserver_user" - webServerPwd: - secret: - secretName: "cdb1-secret" - key: "webserver_pwd" diff --git a/docs/multitenant/provisioning/cdb_crd_resource.md b/docs/multitenant/provisioning/cdb_crd_resource.md deleted file mode 100644 index f1f36404..00000000 --- a/docs/multitenant/provisioning/cdb_crd_resource.md +++ /dev/null @@ -1,38 +0,0 @@ -# Create a CDB CRD Resource using Oracle DB Operator On-Prem Controller - -In this use case, using the Oracle Database Operator On-Prem Controller, you will create the CDB kind as a custom resource that will model a CDB as a native Kubernetes object. - -**NOTE:** It is assumed that before this step, you have followed the [prerequisite](./../README.md#prerequsites-to-manage-pdb-life-cycle-using-oracle-db-operator-on-prem-database-controller) steps. - -This example uses `create_cdb.yaml` with: - -- CDB CRD resource Name as `cdb-dev` -- Container Database (CDB) Name as `goldcdb` -- Scan Name as `goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com` -- Database Server Name as `goldhost1.lbsub52b3b1cae.okecluster.oraclevcn.com` -- ORDS Docker Image as `phx.ocir.io//oracle/ords:21.4.3` -- Image Pull Secret as `container-registry-secret` -- Database Listener Port as `1521` -- Database Service Name as `goldcdb_phx1pw.lbsub52b3b1cae.okecluster.oraclevcn.com` -- Number of replicas for CDB CRD Resource as 1 - -**NOTE:** For the details of the parameters to be used in the .yaml file, please refer [config/crd/bases/database.oracle.com_cdbs.yaml](../../../config/crd/bases/database.oracle.com_cdbs.yaml) - -Use the file: [cdb.yaml](./cdb.yaml) for this use case as below: - -1. Deploy the .yaml file: -```sh -[root@test-server oracle-database-operator]# kubectl apply -f cdb.yaml -``` - -2. Monitor the Oracle DB Operator Pod for the progress of the CDB CRD Resource creation. - -NOTE: Check the DB Operator Pod name in your environment. - -``` -[root@test-server oracle-database-operator]# kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -``` - -## Sample Output - -[Here](./cdb.log) is the sample output for a PDB created using Oracle DB Operator On-Prem Controller using file [cdb.yaml](./cdb.yaml) diff --git a/docs/multitenant/provisioning/cdb_secret.yaml b/docs/multitenant/provisioning/cdb_secret.yaml deleted file mode 100644 index 4d03499e..00000000 --- a/docs/multitenant/provisioning/cdb_secret.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: v1 -kind: Secret -metadata: - name: cdb1-secret - namespace: oracle-database-operator-system -type: Opaque -data: - ords_pwd: "[ base64 encode values ]" - sysadmin_pwd: "[ base64 encode values ]" - cdbadmin_user: "[ base64 encode values ]" - cdbadmin_pwd: "[ base64 encode values ]" - webserver_user: "[ base64 encode values ]" - webserver_pwd: "[base64 encode values ]" diff --git a/docs/multitenant/provisioning/clone_pdb.log b/docs/multitenant/provisioning/clone_pdb.log deleted file mode 100644 index 54b54ef6..00000000 --- a/docs/multitenant/provisioning/clone_pdb.log +++ /dev/null @@ -1,137 +0,0 @@ --- Check the Oracle DB Operator Pod and CDB CRD Pod status: - -% kubectl get all -n oracle-database-operator-system -NAME READY STATUS RESTARTS AGE -pod/cdb-dev-ords-rs-5bztb 1/1 Running 0 5m23s -pod/cdb-dev-ords-rs-q2b68 1/1 Running 0 12m -pod/oracle-database-operator-controller-manager-76cb674c5c-4nrh8 1/1 Running 0 4d10h -pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd 1/1 Running 1 4d10h -pod/oracle-database-operator-controller-manager-76cb674c5c-xsv9g 1/1 Running 2 4d10h - -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -service/cdb-dev-ords ClusterIP None 11m -service/oracle-database-operator-controller-manager-metrics-service ClusterIP 10.96.98.47 8443/TCP 5d2h -service/oracle-database-operator-webhook-service ClusterIP 10.96.166.163 443/TCP 5d2h - -NAME READY UP-TO-DATE AVAILABLE AGE -deployment.apps/oracle-database-operator-controller-manager 3/3 3 3 5d2h - -NAME DESIRED CURRENT READY AGE -replicaset.apps/cdb-dev-ords-rs 2 2 2 12m -replicaset.apps/oracle-database-operator-controller-manager-76cb674c5c 3 3 3 5d2h - - --- Check the current PDB CRD resource: - -% kubectl get pdbs -A -NAMESPACE NAME CONNECT STRING CDB NAME PDB NAME PDB STATE PDB SIZE STATUS MESSAGE -oracle-database-operator-system pdb1 goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com:1521/pdbnew goldcdb pdbnew READ WRITE 1G Ready Success - - --- Check the current PDBs in the target CDB: - -SQL> show pdbs - - CON_ID CON_NAME OPEN MODE RESTRICTED ----------- ------------------------------ ---------- ---------- - 2 PDB$SEED READ WRITE NO - 3 PDBNEW READ WRITE NO - - - --- .yaml file used in this use case to clone a PDB: - -% cat clone_pdb.yaml -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: PDB -metadata: - name: pdb1-clone - namespace: oracle-database-operator-system - labels: - cdb: cdb-dev -spec: - cdbResName: "cdb-dev" - cdbName: "goldcdb" - pdbName: "pdbnewclone" - srcPdbName: "pdbnew" - fileNameConversions: "NONE" - totalSize: "UNLIMITED" - tempSize: "UNLIMITED" - action: "Clone" - - --- Apply the .yaml file: - -% kubectl apply -f clone_pdb.yaml -pdb.database.oracle.com/pdb1-clone created - - - -- Monitor the logs from the Oracle DB Operator Pod: - -% kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -. -. -2022-06-27T03:37:21Z DEBUG controller-runtime.webhook.webhooks received request {"webhook": "/mutate-database-oracle-com-v1alpha1-pdb", "UID": "7fbbd983-0309-4603-9c3e-77f7ffded000", "kind": "database.oracle.com/v1alpha1, Kind=PDB", "resource": {"group":"database.oracle.com","version":"v1alpha1","resource":"pdbs"}} -2022-06-27T03:37:21Z INFO pdb-webhook Setting default values in PDB spec for : pdb1-clone -2022-06-27T03:37:21Z INFO pdb-webhook - reuseTempFile : true -2022-06-27T03:37:21Z INFO pdb-webhook - unlimitedStorage : true -2022-06-27T03:37:21Z INFO pdb-webhook - tdeImport : false -2022-06-27T03:37:21Z INFO pdb-webhook - tdeExport : false -2022-06-27T03:37:21Z INFO pdb-webhook - asClone : false -2022-06-27T03:37:21Z INFO pdb-webhook - getScript : false -2022-06-27T03:37:21Z DEBUG controller-runtime.webhook.webhooks wrote response {"webhook": "/mutate-database-oracle-com-v1alpha1-pdb", "code": 200, "reason": "", "UID": "7fbbd983-0309-4603-9c3e-77f7ffded000", "allowed": true} -2022-06-27T03:37:21Z DEBUG controller-runtime.webhook.webhooks received request {"webhook": "/validate-database-oracle-com-v1alpha1-pdb", "UID": "12aa43ea-df81-4931-b29b-d665c121590f", "kind": "database.oracle.com/v1alpha1, Kind=PDB", "resource": {"group":"database.oracle.com","version":"v1alpha1","resource":"pdbs"}} -2022-06-27T03:37:21Z INFO pdb-webhook ValidateCreate-Validating PDB spec for : pdb1-clone -2022-06-27T03:37:21Z INFO pdb-webhook validateCommon {"name": "pdb1-clone"} -2022-06-27T03:37:21Z INFO pdb-webhook Valdiating PDB Resource Action : CLONE -2022-06-27T03:37:21Z INFO pdb-webhook PDB Resource : pdb1-clone successfully validated for Action : CLONE -2022-06-27T03:37:21Z DEBUG controller-runtime.webhook.webhooks wrote response {"webhook": "/validate-database-oracle-com-v1alpha1-pdb", "code": 200, "reason": "", "UID": "12aa43ea-df81-4931-b29b-d665c121590f", "allowed": true} -2022-06-27T03:37:21Z INFO controllers.PDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/pdb1-clone"} -2022-06-27T03:37:21Z INFO controllers.PDB Adding finalizer {"managePDBDeletion": "oracle-database-operator-system/pdb1-clone"} -2022-06-27T03:37:21Z DEBUG controller-runtime.webhook.webhooks received request {"webhook": "/mutate-database-oracle-com-v1alpha1-pdb", "UID": "b3bbaa0d-6865-4dd1-9ca9-d54f916a8d66", "kind": "database.oracle.com/v1alpha1, Kind=PDB", "resource": {"group":"database.oracle.com","version":"v1alpha1","resource":"pdbs"}} -2022-06-27T03:37:21Z INFO pdb-webhook Setting default values in PDB spec for : pdb1-clone -2022-06-27T03:37:21Z DEBUG controller-runtime.webhook.webhooks wrote response {"webhook": "/mutate-database-oracle-com-v1alpha1-pdb", "code": 200, "reason": "", "UID": "b3bbaa0d-6865-4dd1-9ca9-d54f916a8d66", "allowed": true} -2022-06-27T03:37:21Z DEBUG controller-runtime.webhook.webhooks received request {"webhook": "/validate-database-oracle-com-v1alpha1-pdb", "UID": "5924d376-7a5c-4d4a-8ca9-040c585fb4b6", "kind": "database.oracle.com/v1alpha1, Kind=PDB", "resource": {"group":"database.oracle.com","version":"v1alpha1","resource":"pdbs"}} -2022-06-27T03:37:21Z INFO pdb-webhook ValidateUpdate-Validating PDB spec for : pdb1-clone -2022-06-27T03:37:21Z INFO pdb-webhook validateCommon {"name": "pdb1-clone"} -2022-06-27T03:37:21Z INFO pdb-webhook Valdiating PDB Resource Action : CLONE -2022-06-27T03:37:21Z DEBUG controller-runtime.webhook.webhooks wrote response {"webhook": "/validate-database-oracle-com-v1alpha1-pdb", "code": 200, "reason": "", "UID": "5924d376-7a5c-4d4a-8ca9-040c585fb4b6", "allowed": true} -2022-06-27T03:37:21Z INFO controllers.PDB Found PDB: pdb1-clone {"checkDuplicatePDB": "oracle-database-operator-system/pdb1-clone"} -2022-06-27T03:37:21Z INFO controllers.PDB Validating PDB phase for: pdb1-clone {"validatePhase": "oracle-database-operator-system/pdb1-clone", "Action": "CLONE"} -2022-06-27T03:37:21Z INFO controllers.PDB Validation complete {"validatePhase": "oracle-database-operator-system/pdb1-clone"} -2022-06-27T03:37:21Z INFO controllers.PDB PDB: {"onpremdboperator": "oracle-database-operator-system/pdb1-clone", "Name": "pdb1-clone", "Phase": "Cloning", "Status": "false"} -2022-06-27T03:37:21Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1-clone", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:37:21Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1-clone", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/pdbnew/", "Action": "POST"} -2022-06-27T03:37:21Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1-clone", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:38:01Z INFO controllers.PDB Cloned PDB successfully {"clonePDB": "oracle-database-operator-system/pdb1-clone", "Source PDB Name": "pdbnew", "Clone PDB Name": "pdbnewclone"} -2022-06-27T03:38:01Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1-clone", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:38:01Z DEBUG events Normal {"object": {"kind":"PDB","namespace":"oracle-database-operator-system","name":"pdb1-clone","uid":"16276c26-60a3-463b-bdd5-10bd328f9d43","apiVersion":"database.oracle.com/v1alpha1","resourceVersion":"101449482"}, "reason": "Created", "message": "PDB 'pdbnewclone' cloned successfully"} -2022-06-27T03:38:01Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1-clone", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/pdbnewclone/status", "Action": "GET"} -2022-06-27T03:38:01Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1-clone", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:38:01Z INFO controllers.PDB Successfully obtained PDB state {"getPDBState": "oracle-database-operator-system/pdb1-clone", "PDB Name": "pdbnewclone", "State": "READ WRITE"} -2022-06-27T03:38:01Z INFO controllers.PDB Reconcile completed {"onpremdboperator": "oracle-database-operator-system/pdb1-clone"} - - - --- Check the status of the new PDB CRD resource created by cloning: - -% kubectl get pdbs -A -NAMESPACE NAME CONNECT STRING CDB NAME PDB NAME PDB STATE PDB SIZE STATUS MESSAGE -oracle-database-operator-system pdb1 goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com:1521/pdbnew goldcdb pdbnew READ WRITE 1G Ready Success -oracle-database-operator-system pdb1-clone goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com:1521/pdbnewclone goldcdb pdbnewclone READ WRITE Ready Success - - --- Verify the new PDB created from the target CDB: - -SQL> show pdbs - - CON_ID CON_NAME OPEN MODE RESTRICTED ----------- ------------------------------ ---------- ---------- - 2 PDB$SEED READ WRITE NO - 3 PDBNEW READ WRITE NO - 4 PDBNEWCLONE READ WRITE NO diff --git a/docs/multitenant/provisioning/clone_pdb.md b/docs/multitenant/provisioning/clone_pdb.md deleted file mode 100644 index b731d301..00000000 --- a/docs/multitenant/provisioning/clone_pdb.md +++ /dev/null @@ -1,38 +0,0 @@ -# Clone a PDB using Oracle DB Operator On-Prem Controller in a target CDB - -In this use case, a PDB is cloned using Oracle DB Operator On-Prem controller. - -To clone a PDB CRD Resource, a sample .yaml file is available here: [config/samples/onpremdb/pdb_clone.yaml](../../../config/samples/onpremdb/pdb_clone.yaml) - -**NOTE:** It is assumed that before this step, you have followed the [prerequisite](./../README.md#prerequsites-to-manage-pdb-life-cycle-using-oracle-db-operator-on-prem-database-controller) steps. - -This example uses `clone_pdb.yaml` to clone a PDB using Oracle DB Operator On-Prem Controller with: - -- PDB CRD resource Name as `pdb1-clone` -- Pluggable Database (PDB) Name as `pdbnewclone` -- Total Size of the PDB as `UNLIMITED` -- Total size for temporary tablespace as `UNLIMITED` -- Target CDB CRD Resource Name as `cdb-dev` -- Target CDB name as `goldcdb` -- Source PDB Name as `pdbnew` - -**NOTE:** For the details of the parameters to be used in the .yaml file, please refer [config/crd/bases/database.oracle.com_pdbs.yaml](../../../config/crd/bases/database.oracle.com_pdbs.yaml) - -Use the file: [clone_pdb.yaml](./clone_pdb.yaml) for this use case as below: - -1. Deploy the .yaml file: -```sh -[root@test-server oracle-database-operator]# kubectl apply -f clone_pdb.yaml -``` - -2. Monitor the Oracle DB Operator Pod for the progress of the PDB creation. - -NOTE: Check the DB Operator Pod name in your environment. - -``` -[root@test-server oracle-database-operator]# kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -``` - -## Sample Output - -[Here](./clone_pdb.log) is the sample output for a PDB created using Oracle DB Operator On-Prem Controller using file [clone_pdb.yaml](./clone_pdb.yaml) diff --git a/docs/multitenant/provisioning/clone_pdb.yaml b/docs/multitenant/provisioning/clone_pdb.yaml deleted file mode 100644 index 7d3cfff9..00000000 --- a/docs/multitenant/provisioning/clone_pdb.yaml +++ /dev/null @@ -1,20 +0,0 @@ -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: PDB -metadata: - name: pdb1-clone - namespace: oracle-database-operator-system - labels: - cdb: cdb-dev -spec: - cdbResName: "cdb-dev" - cdbName: "goldcdb" - pdbName: "pdbnewclone" - srcPdbName: "pdbnew" - fileNameConversions: "NONE" - totalSize: "UNLIMITED" - tempSize: "UNLIMITED" - action: "Clone" diff --git a/docs/multitenant/provisioning/create_pdb.log b/docs/multitenant/provisioning/create_pdb.log deleted file mode 100644 index ebba9e66..00000000 --- a/docs/multitenant/provisioning/create_pdb.log +++ /dev/null @@ -1,139 +0,0 @@ --- Check the Oracle DB Operator Pod and CDB CRD Pod status: - -% kubectl get all -n oracle-database-operator-system -NAME READY STATUS RESTARTS AGE -pod/cdb-dev-ords-rs-5bztb 1/1 Running 0 5m23s -pod/cdb-dev-ords-rs-q2b68 1/1 Running 0 12m -pod/oracle-database-operator-controller-manager-76cb674c5c-4nrh8 1/1 Running 0 4d10h -pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd 1/1 Running 1 4d10h -pod/oracle-database-operator-controller-manager-76cb674c5c-xsv9g 1/1 Running 2 4d10h - -NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE -service/cdb-dev-ords ClusterIP None 11m -service/oracle-database-operator-controller-manager-metrics-service ClusterIP 10.96.98.47 8443/TCP 5d2h -service/oracle-database-operator-webhook-service ClusterIP 10.96.166.163 443/TCP 5d2h - -NAME READY UP-TO-DATE AVAILABLE AGE -deployment.apps/oracle-database-operator-controller-manager 3/3 3 3 5d2h - -NAME DESIRED CURRENT READY AGE -replicaset.apps/cdb-dev-ords-rs 2 2 2 12m -replicaset.apps/oracle-database-operator-controller-manager-76cb674c5c 3 3 3 5d2h - - - --- PDB secrets in this use case were created using the below file: - -% cat pdb_secret.yaml -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: v1 -kind: Secret -metadata: - name: pdb1-secret - namespace: oracle-database-operator-system -type: Opaque -data: - sysadmin_user: "cGRiYWRtaW4=" - sysadmin_pwd: "V0VsY29tZV8yMSMj" - - --- This is the .yaml file used to create a PDB CRD resource in this use case: - -% cat pdb_create.yaml -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: PDB -metadata: - name: pdb1 - namespace: oracle-database-operator-system - labels: - cdb: cdb-dev -spec: - cdbResName: "cdb-dev" - cdbName: "goldcdb" - pdbName: "pdbnew" - adminName: - secret: - secretName: "pdb1-secret" - key: "sysadmin_user" - adminPwd: - secret: - secretName: "pdb1-secret" - key: "sysadmin_pwd" - fileNameConversions: "NONE" - totalSize: "1G" - tempSize: "100M" - action: "Create" - - - - --- Apply the .yaml files: - -% kubectl apply -f pdb_secret.yaml -secret/pdb1-secret created - -% kubectl apply -f pdb_create.yaml -pdb.database.oracle.com/pdb1 created - - --- Monitor the logs from the Oracle DB Operator Pod: - -% kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -. -. -2022-06-27T03:28:30Z DEBUG controller-runtime.webhook.webhooks received request {"webhook": "/mutate-database-oracle-com-v1alpha1-pdb", "UID": "6fca0e37-8fd9-4ccd-86ad-2edec604a28b", "kind": "database.oracle.com/v1alpha1, Kind=PDB", "resource": {"group":"database.oracle.com","version":"v1alpha1","resource":"pdbs"}} -2022-06-27T03:28:30Z INFO pdb-webhook Setting default values in PDB spec for : pdb1 -2022-06-27T03:28:30Z INFO pdb-webhook - reuseTempFile : true -2022-06-27T03:28:30Z INFO pdb-webhook - unlimitedStorage : true -2022-06-27T03:28:30Z INFO pdb-webhook - tdeImport : false -2022-06-27T03:28:30Z INFO pdb-webhook - tdeExport : false -2022-06-27T03:28:30Z INFO pdb-webhook - asClone : false -2022-06-27T03:28:30Z DEBUG controller-runtime.webhook.webhooks wrote response {"webhook": "/mutate-database-oracle-com-v1alpha1-pdb", "code": 200, "reason": "", "UID": "6fca0e37-8fd9-4ccd-86ad-2edec604a28b", "allowed": true} -2022-06-27T03:28:30Z DEBUG controller-runtime.webhook.webhooks received request {"webhook": "/validate-database-oracle-com-v1alpha1-pdb", "UID": "6ae20043-fa1a-4eba-b943-a2266183da48", "kind": "database.oracle.com/v1alpha1, Kind=PDB", "resource": {"group":"database.oracle.com","version":"v1alpha1","resource":"pdbs"}} -2022-06-27T03:28:30Z INFO pdb-webhook ValidateUpdate-Validating PDB spec for : pdb1 -2022-06-27T03:28:30Z INFO pdb-webhook validateCommon {"name": "pdb1"} -2022-06-27T03:28:30Z INFO pdb-webhook Valdiating PDB Resource Action : CREATE -2022-06-27T03:28:30Z DEBUG controller-runtime.webhook.webhooks wrote response {"webhook": "/validate-database-oracle-com-v1alpha1-pdb", "code": 200, "reason": "", "UID": "6ae20043-fa1a-4eba-b943-a2266183da48", "allowed": true} -2022-06-27T03:28:30Z INFO controllers.PDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/pdb1"} -2022-06-27T03:28:30Z INFO controllers.PDB Validating PDB phase for: pdb1 {"validatePhase": "oracle-database-operator-system/pdb1", "Action": "CREATE"} -2022-06-27T03:28:30Z INFO controllers.PDB Validation complete {"validatePhase": "oracle-database-operator-system/pdb1"} -2022-06-27T03:28:30Z INFO controllers.PDB PDB: {"onpremdboperator": "oracle-database-operator-system/pdb1", "Name": "pdb1", "Phase": "Creating", "Status": "false"} -2022-06-27T03:28:30Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:28:30Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/", "Action": "POST"} -2022-06-27T03:28:30Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:29:04Z INFO controllers.PDB Created PDB Resource {"createPDB": "oracle-database-operator-system/pdb1", "PDB Name": "pdbnew"} -2022-06-27T03:29:04Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:29:04Z DEBUG events Normal {"object": {"kind":"PDB","namespace":"oracle-database-operator-system","name":"pdb1","uid":"81f2e686-6e1b-4e2c-8a2f-e20c2f99d6b9","apiVersion":"database.oracle.com/v1alpha1","resourceVersion":"101446779"}, "reason": "Created", "message": "PDB 'pdbnew' created successfully"} -2022-06-27T03:29:04Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/pdbnew/status", "Action": "GET"} -2022-06-27T03:29:04Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:29:04Z INFO controllers.PDB Successfully obtained PDB state {"getPDBState": "oracle-database-operator-system/pdb1", "PDB Name": "pdbnew", "State": "READ WRITE"} -2022-06-27T03:29:04Z INFO controllers.PDB Reconcile completed {"onpremdboperator": "oracle-database-operator-system/pdb1"} - - - - --- Check the status of the PDB CRD Resource created: - -% kubectl get pdbs -A -NAMESPACE NAME CONNECT STRING CDB NAME PDB NAME PDB STATE PDB SIZE STATUS MESSAGE -oracle-database-operator-system pdb1 goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com:1521/pdbnew goldcdb pdbnew READ WRITE 1G Ready Success - - --- The status as "Ready" and message as "Success" confirms that the resource has been created successfully. - - --- Verify that the PDB is created from CDB: - -SQL> show pdbs - - CON_ID CON_NAME OPEN MODE RESTRICTED ----------- ------------------------------ ---------- ---------- - 2 PDB$SEED READ WRITE NO - 3 PDBNEW READ WRITE NO diff --git a/docs/multitenant/provisioning/create_pdb.md b/docs/multitenant/provisioning/create_pdb.md deleted file mode 100644 index 4f6e57aa..00000000 --- a/docs/multitenant/provisioning/create_pdb.md +++ /dev/null @@ -1,37 +0,0 @@ -# Create a PDB using Oracle DB Operator On-Prem Controller in a target CDB - -The Oracle Database Operator On-Prem Controller creates the PDB kind as a custom resource that models a PDB as a native Kubernetes object. There is a one-to-one mapping between the actual PDB and the Kubernetes PDB Custom Resource. Each PDB resource follows the PDB CRD as defined here: [config/crd/bases/database.oracle.com_pdbs.yaml](../../../config/crd/bases/database.oracle.com_pdbs.yaml) - -To create a PDB CRD Resource, a sample .yaml file is available here: [config/samples/onpremdb/pdb_create.yaml](../../../config/samples/onpremdb/pdb_create.yaml) - -**NOTE:** It is assumed that before this step, you have followed the [prerequisite](./../README.md#prerequsites-to-manage-pdb-life-cycle-using-oracle-db-operator-on-prem-database-controller) steps. - -This example uses `create_pdb.yaml` to create a PDB using Oracle DB Operator On-Prem Controller with: - -- PDB CRD resource Name as `pdb1` -- Pluggable Database (PDB) Name as `pdbnew` -- Total Size of the PDB as `1GB` -- Total size for temporary tablespace as `100M` -- Target CDB CRD Resource Name as `cdb-dev` -- Target CDB name as `goldcdb` - -**NOTE:** For the details of the parameters to be used in the .yaml file, please refer [config/crd/bases/database.oracle.com_pdbs.yaml](../../../config/crd/bases/database.oracle.com_pdbs.yaml) - -Use the file: [create_pdb.yaml](./create_pdb.yaml) for this use case as below: - -1. Deploy the .yaml file: -```sh -[root@test-server oracle-database-operator]# kubectl apply -f create_pdb.yaml -``` - -2. Monitor the Oracle DB Operator Pod for the progress of the PDB creation. - -NOTE: Check the DB Operator Pod name in your environment. - -``` -[root@test-server oracle-database-operator]# kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -``` - -## Sample Output - -[Here](./create_pdb.log) is the sample output for a PDB created using Oracle DB Operator On-Prem Controller using file [create_pdb.yaml](./create_pdb.yaml) diff --git a/docs/multitenant/provisioning/create_pdb.yaml b/docs/multitenant/provisioning/create_pdb.yaml deleted file mode 100644 index 82941185..00000000 --- a/docs/multitenant/provisioning/create_pdb.yaml +++ /dev/null @@ -1,27 +0,0 @@ -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: PDB -metadata: - name: pdb1 - namespace: oracle-database-operator-system - labels: - cdb: cdb-dev -spec: - cdbResName: "cdb-dev" - cdbName: "goldcdb" - pdbName: "pdbnew" - adminName: - secret: - secretName: "pdb1-secret" - key: "sysadmin_user" - adminPwd: - secret: - secretName: "pdb1-secret" - key: "sysadmin_pwd" - fileNameConversions: "NONE" - totalSize: "1G" - tempSize: "100M" - action: "Create" diff --git a/docs/multitenant/provisioning/delete_pdb.log b/docs/multitenant/provisioning/delete_pdb.log deleted file mode 100644 index 7f361871..00000000 --- a/docs/multitenant/provisioning/delete_pdb.log +++ /dev/null @@ -1,157 +0,0 @@ --- Check the existing PDB CRD resources: - -% kubectl get pdbs -A -NAMESPACE NAME CONNECT STRING CDB NAME PDB NAME PDB STATE PDB SIZE STATUS MESSAGE -oracle-database-operator-system pdb1 goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com:1521/pdbnew goldcdb pdbnew READ WRITE 1G Ready Success -oracle-database-operator-system pdb1-clone goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com:1521/pdbnewclone goldcdb pdbnewclone READ WRITE Ready Success - - --- Also check from the database as well: - -SQL> show pdbs - - CON_ID CON_NAME OPEN MODE RESTRICTED ----------- ------------------------------ ---------- ---------- - 2 PDB$SEED READ WRITE NO - 3 PDBNEW READ WRITE NO - 4 PDBNEWCLONE READ WRITE NO - - - -% cat modify_pdb_close.yaml -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: PDB -metadata: - name: pdb1-clone - namespace: oracle-database-operator-system - labels: - cdb: cdb-dev -spec: - cdbResName: "cdb-dev" - cdbName: "goldcdb" - pdbName: "pdbnewclone" - pdbState: "CLOSE" - modifyOption: "IMMEDIATE" - action: "Modify" - - -% kubectl apply -f modify_pdb_close.yaml -pdb.database.oracle.com/pdb1-clone configured - - - -% kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -. -. -2022-06-27T04:19:36Z DEBUG controller-runtime.webhook.webhooks received request {"webhook": "/mutate-database-oracle-com-v1alpha1-pdb", "UID": "24842cc8-0047-46cc-86a5-2782a95e3e36", "kind": "database.oracle.com/v1alpha1, Kind=PDB", "resource": {"group":"database.oracle.com","version":"v1alpha1","resource":"pdbs"}} -2022-06-27T04:19:36Z INFO pdb-webhook Setting default values in PDB spec for : pdb1-clone -2022-06-27T04:19:36Z DEBUG controller-runtime.webhook.webhooks wrote response {"webhook": "/mutate-database-oracle-com-v1alpha1-pdb", "code": 200, "reason": "", "UID": "24842cc8-0047-46cc-86a5-2782a95e3e36", "allowed": true} -2022-06-27T04:19:36Z INFO controllers.PDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/pdb1-clone"} -2022-06-27T04:19:36Z INFO controllers.PDB Validating PDB phase for: pdb1-clone {"validatePhase": "oracle-database-operator-system/pdb1-clone", "Action": "MODIFY"} -2022-06-27T04:19:36Z INFO controllers.PDB Validation complete {"validatePhase": "oracle-database-operator-system/pdb1-clone"} -2022-06-27T04:19:36Z INFO controllers.PDB PDB: {"onpremdboperator": "oracle-database-operator-system/pdb1-clone", "Name": "pdb1-clone", "Phase": "Modifying", "Status": "false"} -2022-06-27T04:19:36Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1-clone", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:19:36Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1-clone", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/pdbnewclone/status", "Action": "GET"} -2022-06-27T04:19:36Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1-clone", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:19:38Z INFO controllers.PDB Successfully obtained PDB state {"getPDBState": "oracle-database-operator-system/pdb1-clone", "PDB Name": "pdbnewclone", "State": "READ WRITE"} -2022-06-27T04:19:38Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1-clone", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:19:38Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1-clone", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/pdbnewclone/status", "Action": "POST"} -2022-06-27T04:19:38Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1-clone", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:19:39Z INFO controllers.PDB Successfully modified PDB state {"modifyPDB": "oracle-database-operator-system/pdb1-clone", "PDB Name": "pdbnewclone"} -2022-06-27T04:19:39Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1-clone", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:19:39Z DEBUG events Normal {"object": {"kind":"PDB","namespace":"oracle-database-operator-system","name":"pdb1-clone","uid":"309dd711-198b-45b6-a34b-da5069af70fb","apiVersion":"database.oracle.com/v1alpha1","resourceVersion":"101462484"}, "reason": "Modified", "message": "PDB 'pdbnewclone' modified successfully"} -2022-06-27T04:19:39Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1-clone", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/pdbnewclone/status", "Action": "GET"} -2022-06-27T04:19:39Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1-clone", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:19:39Z INFO controllers.PDB Successfully obtained PDB state {"getPDBState": "oracle-database-operator-system/pdb1-clone", "PDB Name": "pdbnewclone", "State": "MOUNTED"} -2022-06-27T04:19:39Z INFO controllers.PDB Reconcile completed {"onpremdboperator": "oracle-database-operator-system/pdb1-clone"} - - - -SQL> show pdbs - - CON_ID CON_NAME OPEN MODE RESTRICTED ----------- ------------------------------ ---------- ---------- - 2 PDB$SEED READ WRITE NO - 3 PDBNEW READ WRITE NO - 4 PDBNEWCLONE MOUNTED - - --- Check the .yaml file to be used to delete a PDB: - -% cat delete_pdb.yaml -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: PDB -metadata: - name: pdb1-clone - namespace: oracle-database-operator-system - labels: - cdb: cdb-dev -spec: - cdbResName: "cdb-dev" - pdbName: "pdbnewclone" - action: "Delete" - dropAction: "INCLUDING" - - - --- Apply the .yaml file: - -% kubectl apply -f delete_pdb.yaml -pdb.database.oracle.com/pdb1-clone configured - - --- Monitor the Oracle DB Operator Pod logs: - -% kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -. -. -2022-06-27T04:21:37Z DEBUG controller-runtime.webhook.webhooks received request {"webhook": "/validate-database-oracle-com-v1alpha1-pdb", "UID": "64148dda-d0df-4e03-88e3-98b1ce7b7aaf", "kind": "database.oracle.com/v1alpha1, Kind=PDB", "resource": {"group":"database.oracle.com","version":"v1alpha1","resource":"pdbs"}} -2022-06-27T04:21:37Z INFO pdb-webhook ValidateUpdate-Validating PDB spec for : pdb1-clone -2022-06-27T04:21:37Z INFO pdb-webhook validateCommon {"name": "pdb1-clone"} -2022-06-27T04:21:37Z INFO pdb-webhook Valdiating PDB Resource Action : DELETE -2022-06-27T04:21:37Z DEBUG controller-runtime.webhook.webhooks wrote response {"webhook": "/validate-database-oracle-com-v1alpha1-pdb", "code": 200, "reason": "", "UID": "64148dda-d0df-4e03-88e3-98b1ce7b7aaf", "allowed": true} -2022-06-27T04:21:37Z INFO controllers.PDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/pdb1-clone"} -2022-06-27T04:21:37Z INFO controllers.PDB Validating PDB phase for: pdb1-clone {"validatePhase": "oracle-database-operator-system/pdb1-clone", "Action": "DELETE"} -2022-06-27T04:21:37Z INFO controllers.PDB Validation complete {"validatePhase": "oracle-database-operator-system/pdb1-clone"} -2022-06-27T04:21:37Z INFO controllers.PDB PDB: {"onpremdboperator": "oracle-database-operator-system/pdb1-clone", "Name": "pdb1-clone", "Phase": "Deleting", "Status": "false"} -2022-06-27T04:21:37Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1-clone", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:21:37Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1-clone", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/pdbnewclone/", "Action": "DELETE"} -2022-06-27T04:21:37Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1-clone", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:21:39Z INFO controllers.PDB Successfully dropped PDB {"deletePDBInstance": "oracle-database-operator-system/pdb1-clone", "PDB Name": "pdbnewclone"} -2022-06-27T04:21:39Z INFO controllers.PDB Removing finalizer {"deletePDB": "oracle-database-operator-system/pdb1-clone"} -2022-06-27T04:21:39Z DEBUG controller-runtime.webhook.webhooks received request {"webhook": "/validate-database-oracle-com-v1alpha1-pdb", "UID": "15bd320b-3f9f-46a7-8493-c586310b7d84", "kind": "database.oracle.com/v1alpha1, Kind=PDB", "resource": {"group":"database.oracle.com","version":"v1alpha1","resource":"pdbs"}} -2022-06-27T04:21:39Z INFO pdb-webhook ValidateUpdate-Validating PDB spec for : pdb1-clone -2022-06-27T04:21:39Z INFO pdb-webhook validateCommon {"name": "pdb1-clone"} -2022-06-27T04:21:39Z INFO pdb-webhook Valdiating PDB Resource Action : DELETE -2022-06-27T04:21:39Z DEBUG controller-runtime.webhook.webhooks wrote response {"webhook": "/validate-database-oracle-com-v1alpha1-pdb", "code": 200, "reason": "", "UID": "15bd320b-3f9f-46a7-8493-c586310b7d84", "allowed": true} -2022-06-27T04:21:39Z INFO controllers.PDB Successfully deleted PDB resource {"deletePDB": "oracle-database-operator-system/pdb1-clone"} -2022-06-27T04:21:39Z INFO controllers.PDB Reconcile completed {"onpremdboperator": "oracle-database-operator-system/pdb1-clone"} -2022-06-27T04:21:39Z DEBUG events Normal {"object": {"kind":"PDB","namespace":"oracle-database-operator-system","name":"pdb1-clone","uid":"309dd711-198b-45b6-a34b-da5069af70fb","apiVersion":"database.oracle.com/v1alpha1","resourceVersion":"101463106"}, "reason": "Deleted", "message": "PDB 'pdbnewclone' dropped successfully"} - - - - - --- Check the PDB CRD resources: - -% kubectl get pdbs -A -NAMESPACE NAME CONNECT STRING CDB NAME PDB NAME PDB STATE PDB SIZE STATUS MESSAGE -oracle-database-operator-system pdb1 goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com:1521/pdbnew goldcdb pdbnew READ WRITE 1G Ready Success - - --- Verify from the CDB: - -SQL> show pdbs - - CON_ID CON_NAME OPEN MODE RESTRICTED ----------- ------------------------------ ---------- ---------- - 2 PDB$SEED READ WRITE NO - 3 PDBNEW READ WRITE NO diff --git a/docs/multitenant/provisioning/delete_pdb.md b/docs/multitenant/provisioning/delete_pdb.md deleted file mode 100644 index e36bb473..00000000 --- a/docs/multitenant/provisioning/delete_pdb.md +++ /dev/null @@ -1,37 +0,0 @@ -# Delete a PDB using Oracle DB Operator On-Prem Controller in a target CDB - -In this use case, a PDB is deleted using Oracle DB Operator On-Prem controller. - -To delete a PDB CRD Resource, a sample .yaml file is available here: [config/samples/onpremdb/pdb_delete.yaml](../../../config/samples/onpremdb/pdb_delete.yaml) - -**NOTE:** It is assumed that before this step, you have followed the [prerequisite](./../README.md#prerequsites-to-manage-pdb-life-cycle-using-oracle-db-operator-on-prem-database-controller) steps. - -This example uses `delete_pdb.yaml` to delete a PDB using Oracle DB Operator On-Prem Controller with: - -- Pluggable Database (PDB) Name as `pdbnewclone` -- Target CDB CRD Resource Name as `cdb-dev` -- Action to be taken on the PDB as `Delete` -- Option to specify if datafiles should be removed as `INCLUDING` - -**NOTE:** You need to *modify* the PDB status to MOUNTED, as described earlier, on the target CDB before you want to delete that PDB. - -**NOTE:** For the details of the parameters to be used in the .yaml file, please refer [config/crd/bases/database.oracle.com_pdbs.yaml](../../../config/crd/bases/database.oracle.com_pdbs.yaml) - -Use the file: [delete_pdb.yaml](./delete_pdb.yaml) for this use case as below: - -1. Deploy the .yaml file: -```sh -% kubectl apply -f delete_pdb.yaml -``` - -2. Monitor the Oracle DB Operator Pod `pod/oracle-database-operator-controller-manager-665874bd57-g2cgw` for the progress of the PDB deletion. - -NOTE: Check the DB Operator Pod name in your environment. - -```sh -% kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -``` - -## Sample Output - -[Here](./delete_pdb.log) is the sample output for a PDB created using Oracle DB Operator On-Prem Controller using file [delete_pdb.yaml](./delete_pdb.yaml) diff --git a/docs/multitenant/provisioning/delete_pdb.yaml b/docs/multitenant/provisioning/delete_pdb.yaml deleted file mode 100644 index d16084bb..00000000 --- a/docs/multitenant/provisioning/delete_pdb.yaml +++ /dev/null @@ -1,16 +0,0 @@ -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: PDB -metadata: - name: pdb1-clone - namespace: oracle-database-operator-system - labels: - cdb: cdb-dev -spec: - cdbResName: "cdb-dev" - pdbName: "pdbnewclone" - action: "Delete" - dropAction: "INCLUDING" diff --git a/docs/multitenant/provisioning/example_setup_using_oci_oke_cluster.md b/docs/multitenant/provisioning/example_setup_using_oci_oke_cluster.md index f3ed2489..d56efacb 100644 --- a/docs/multitenant/provisioning/example_setup_using_oci_oke_cluster.md +++ b/docs/multitenant/provisioning/example_setup_using_oci_oke_cluster.md @@ -18,7 +18,7 @@ Below are the main steps that will be involved in this setup: Check the [Oracle Documentation](https://docs.oracle.com/en-us/iaas/Content/ContEng/Concepts/contengnetworkconfigexample.htm#example-privatek8sapi-privateworkers-publiclb) for the OKE rules settings. -Create OKE cluster with CUSTOM option to use same VCN where ExaCS is provisioned. +Create OKE cluster with CUSTOM option to use same VCN where ExaCS is provisioned. **NOTE:** Make sure you choose same VCN exaphxvcn where ExaCS is provisioned. @@ -35,3 +35,4 @@ NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL- ``` Once this setup is ready, you can proceed with the installation of [Oracle Database Operator for Kubernetes](https://github.com/oracle/oracle-database-operator/blob/main/README.md) to use the Oracle On-prem controller to manage PDBs in this CDB. + diff --git a/docs/multitenant/provisioning/known_issues.md b/docs/multitenant/provisioning/known_issues.md deleted file mode 100644 index 3ab19897..00000000 --- a/docs/multitenant/provisioning/known_issues.md +++ /dev/null @@ -1,49 +0,0 @@ -# Known Issues - -Please refer to the below list of known issues related to Oracle DB Operator On-Prem Controller: - -1. **ORA-20002: ERROR: The user ORDS_PUBLIC_USER already exists in the logs of CDB CRD Pods.** - -This error is expected when you are deploying `2` replicas of CDB CRD during the deployment of the CDB CRD. Below is the snippet of a possible error: -``` -2022-06-22T20:06:32.616Z INFO Installing Oracle REST Data Services version 21.4.2.r0621806 in CDB$ROOT -2022-06-22T20:06:32.663Z INFO ... Log file written to /home/oracle/ords_cdb_install_core_CDB_ROOT_2022-06-22_200632_00662.log -2022-06-22T20:06:33.835Z INFO CDB restart file created in /home/oracle/ords_restart_2022-06-22_200633_00835.properties -2022-06-22T20:06:33.837Z SEVERE Error executing script: ords_prereq_env.sql Error: ORA-20002: ERROR: The user ORDS_PUBLIC_USER already exists. You must first uninstall ORDS using ords_uninstall.sql prior to running the install scripts. -ORA-06512: at line 8 -ORA-06512: at line 8 - - Refer to log file /home/oracle/ords_cdb_install_core_CDB_ROOT_2022-06-22_200632_00662.log for details - -java.io.IOException: Error executing script: ords_prereq_env.sql Error: ORA-20002: ERROR: The user ORDS_PUBLIC_USER already exists. You must first uninstall ORDS using ords_uninstall.sql prior to running the install scripts. -ORA-06512: at line 8 -ORA-06512: at line 8 -``` -This error is seen in the logs of one of the two CDB CRD pods. The other Pod `does not` show this error and the ORDS installation is done successfully. - -To avoid this error, you need to initially deploy the CDB CRD with a single replica and later add another replica as per need. - -2. **PDB create failure with error "Failed: Unauthorized"** - -It was observed that PDB creation fails with the below error when special characters like "_" or "#" were used in the password for user SQL_ADMIN: -``` -2022-06-22T20:10:09Z INFO controllers.PDB ORDS Error - HTTP Status Code :401 {"callAPI": "oracle-database-operator-system/pdb1", "Err": "\n{\n \"code\": \"Unauthorized\",\n \"message\": \"Unauthorized\",\n \"type\": \"tag:oracle.com,2020:error/Unauthorized\",\n \"instance\": \"tag:oracle.com,2020:ecid/OoqA0Zw3oBWdabzP8wUMcQ\"\n}"} -2022-06-22T20:10:09Z INFO controllers.PDB Reconcile completed {"onpremdboperator": "oracle-database-operator-system/pdb1"} -2022-06-22T20:10:09Z DEBUG events Warning {"object": {"kind":"PDB","namespace":"oracle-database-operator-system","name":"pdb1","uid":"19fc98b1-ca7f-4e63-a6c7-fdeb14b8c275","apiVersion":"database.oracle.com/v1alpha1","resourceVersion":"99558229"}, "reason": "ORDSError", "message": "Failed: Unauthorized"} -``` - -In testing, we have used the password `welcome1` for the user SQL_ADMIN. - -To avoid this error, please avoid password `welcome1` for SQL_ADMIN user. - - -3. **After cloning a PDB from another PDB, PDB SIZE field is show as empty even if the .yaml file used during the PDB cloning specifies the PDB size:** - -```sh -% kubectl get pdbs -A -NAMESPACE NAME CONNECT STRING CDB NAME PDB NAME PDB STATE PDB SIZE STATUS MESSAGE -oracle-database-operator-system pdb1 goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com:1521/pdbnew goldcdb pdbnew READ WRITE 1G Ready Success -oracle-database-operator-system pdb1-clone goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com:1521/pdbnewclone goldcdb pdbnewclone READ WRITE Ready Success -``` - -In the above example the PDB `pdbnewclone` is cloned from PDB `pdbnew` and is showing the size column as EMPTY. This will be fixed in future version. diff --git a/docs/multitenant/provisioning/modify_pdb.log b/docs/multitenant/provisioning/modify_pdb.log deleted file mode 100644 index 151393a7..00000000 --- a/docs/multitenant/provisioning/modify_pdb.log +++ /dev/null @@ -1,181 +0,0 @@ ------ Closing a PDB ------ - --- Check the existing PDB CRD resources - -jyotiprakashverma@jyotiprakashverma-mac onprem_test % kubectl get pdbs -A -NAMESPACE NAME CONNECT STRING CDB NAME PDB NAME PDB STATE PDB SIZE STATUS MESSAGE -oracle-database-operator-system pdb1 goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com:1521/pdbnew goldcdb pdbnew READ WRITE 1G Ready Success -oracle-database-operator-system pdb1-clone goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com:1521/pdbnewclone goldcdb pdbnewclone READ WRITE Ready Success - - - - --- Check the status of the PDBs in the CDB: - -SQL> show pdbs - - CON_ID CON_NAME OPEN MODE RESTRICTED ----------- ------------------------------ ---------- ---------- - 2 PDB$SEED READ WRITE NO - 3 PDBNEW READ WRITE NO - 5 PDBNEWCLONE READ WRITE NO - - - --- Check the file to modify the PDB state to CLOSE: - -% cat modify_pdb_close.yaml -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: PDB -metadata: - name: pdb1 - namespace: oracle-database-operator-system - labels: - cdb: cdb-dev -spec: - cdbResName: "cdb-dev" - cdbName: "goldcdb" - pdbName: "pdbnew" - pdbState: "CLOSE" - modifyOption: "IMMEDIATE" - action: "Modify" - - --- Apply the file: - -% kubectl apply -f modify_pdb_close.yaml -pdb.database.oracle.com/pdb1 configured - - --- Monitor the logs from the Oracle DB Operator Pod: - -% kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -. -. -2022-06-27T03:44:36Z DEBUG controller-runtime.webhook.webhooks received request {"webhook": "/mutate-database-oracle-com-v1alpha1-pdb", "UID": "08f95926-6bf1-4c70-b319-1b17015ce22a", "kind": "database.oracle.com/v1alpha1, Kind=PDB", "resource": {"group":"database.oracle.com","version":"v1alpha1","resource":"pdbs"}} -2022-06-27T03:44:36Z INFO pdb-webhook Setting default values in PDB spec for : pdb1 -2022-06-27T03:44:36Z DEBUG controller-runtime.webhook.webhooks wrote response {"webhook": "/mutate-database-oracle-com-v1alpha1-pdb", "code": 200, "reason": "", "UID": "08f95926-6bf1-4c70-b319-1b17015ce22a", "allowed": true} -2022-06-27T03:44:36Z DEBUG controller-runtime.webhook.webhooks received request {"webhook": "/validate-database-oracle-com-v1alpha1-pdb", "UID": "64ebebe2-87f2-4237-8928-532365f3cca9", "kind": "database.oracle.com/v1alpha1, Kind=PDB", "resource": {"group":"database.oracle.com","version":"v1alpha1","resource":"pdbs"}} -2022-06-27T03:44:36Z INFO pdb-webhook ValidateUpdate-Validating PDB spec for : pdb1 -2022-06-27T03:44:36Z INFO pdb-webhook validateCommon {"name": "pdb1"} -2022-06-27T03:44:36Z INFO pdb-webhook Valdiating PDB Resource Action : MODIFY -2022-06-27T03:44:36Z DEBUG controller-runtime.webhook.webhooks wrote response {"webhook": "/validate-database-oracle-com-v1alpha1-pdb", "code": 200, "reason": "", "UID": "64ebebe2-87f2-4237-8928-532365f3cca9", "allowed": true} -2022-06-27T03:44:36Z INFO controllers.PDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/pdb1"} -2022-06-27T03:44:36Z INFO controllers.PDB Validating PDB phase for: pdb1 {"validatePhase": "oracle-database-operator-system/pdb1", "Action": "MODIFY"} -2022-06-27T03:44:36Z INFO controllers.PDB Validation complete {"validatePhase": "oracle-database-operator-system/pdb1"} -2022-06-27T03:44:36Z INFO controllers.PDB PDB: {"onpremdboperator": "oracle-database-operator-system/pdb1", "Name": "pdb1", "Phase": "Modifying", "Status": "false"} -2022-06-27T03:44:36Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:44:36Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/pdbnew/status", "Action": "GET"} -2022-06-27T03:44:36Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:44:36Z INFO controllers.PDB Successfully obtained PDB state {"getPDBState": "oracle-database-operator-system/pdb1", "PDB Name": "pdbnew", "State": "READ WRITE"} -2022-06-27T03:44:36Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:44:36Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/pdbnew/status", "Action": "POST"} -2022-06-27T03:44:36Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:44:38Z INFO controllers.PDB Successfully modified PDB state {"modifyPDB": "oracle-database-operator-system/pdb1", "PDB Name": "pdbnew"} -2022-06-27T03:44:38Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:44:38Z DEBUG events Normal {"object": {"kind":"PDB","namespace":"oracle-database-operator-system","name":"pdb1","uid":"81f2e686-6e1b-4e2c-8a2f-e20c2f99d6b9","apiVersion":"database.oracle.com/v1alpha1","resourceVersion":"101451707"}, "reason": "Modified", "message": "PDB 'pdbnew' modified successfully"} -2022-06-27T03:44:38Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/pdbnew/status", "Action": "GET"} -2022-06-27T03:44:38Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:44:38Z INFO controllers.PDB Successfully obtained PDB state {"getPDBState": "oracle-database-operator-system/pdb1", "PDB Name": "pdbnew", "State": "MOUNTED"} -2022-06-27T03:44:38Z INFO controllers.PDB Reconcile completed {"onpremdboperator": "oracle-database-operator-system/pdb1"} - - - - --- Check the status of PDB CRD resources - -jyotiprakashverma@jyotiprakashverma-mac onprem_test % kubectl get pdbs -A -NAMESPACE NAME CONNECT STRING CDB NAME PDB NAME PDB STATE PDB SIZE STATUS MESSAGE -oracle-database-operator-system pdb1 goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com:1521/pdbnew goldcdb pdbnew MOUNTED 1G Ready Success -oracle-database-operator-system pdb1-clone goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com:1521/pdbnewclone goldcdb pdbnewclone READ WRITE Ready Success - - - --- Confirm the status of the PDB in the CDB: - -SQL> show pdbs - - CON_ID CON_NAME OPEN MODE RESTRICTED ----------- ------------------------------ ---------- ---------- - 2 PDB$SEED READ WRITE NO - 3 PDBNEW MOUNTED - 4 PDBNEWCLONE READ WRITE NO - - - - - - - - ------ Opening a PDB ------ - --- Check the .yaml file to open the PDB: - -% cat modify_pdb_open.yaml -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: PDB -metadata: - name: pdb1 - namespace: oracle-database-operator-system - labels: - cdb: cdb-dev -spec: - cdbResName: "cdb-dev" - cdbName: "goldcdb" - pdbName: "pdbnew" - pdbState: "OPEN" - modifyOption: "READ WRITE" - action: "Modify" - - - --- Apply the file: - -% kubectl apply -f modify_pdb_open.yaml -pdb.database.oracle.com/pdb1 configured - - --- Monitor the logs from the Oracle DB Operator Pod: - -% kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -. -. -2022-06-27T03:48:38Z INFO controllers.PDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/pdb1"} -2022-06-27T03:48:38Z INFO controllers.PDB Validating PDB phase for: pdb1 {"validatePhase": "oracle-database-operator-system/pdb1", "Action": "MODIFY"} -2022-06-27T03:48:38Z INFO controllers.PDB Validation complete {"validatePhase": "oracle-database-operator-system/pdb1"} -2022-06-27T03:48:38Z INFO controllers.PDB PDB: {"onpremdboperator": "oracle-database-operator-system/pdb1", "Name": "pdb1", "Phase": "Modifying", "Status": "false"} -2022-06-27T03:48:38Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:48:38Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/pdbnew/status", "Action": "GET"} -2022-06-27T03:48:38Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:48:38Z INFO controllers.PDB Successfully obtained PDB state {"getPDBState": "oracle-database-operator-system/pdb1", "PDB Name": "pdbnew", "State": "MOUNTED"} -2022-06-27T03:48:38Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:48:38Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/pdbnew/status", "Action": "POST"} -2022-06-27T03:48:38Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:48:41Z INFO controllers.PDB Successfully modified PDB state {"modifyPDB": "oracle-database-operator-system/pdb1", "PDB Name": "pdbnew"} -2022-06-27T03:48:41Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:48:41Z DEBUG events Normal {"object": {"kind":"PDB","namespace":"oracle-database-operator-system","name":"pdb1","uid":"81f2e686-6e1b-4e2c-8a2f-e20c2f99d6b9","apiVersion":"database.oracle.com/v1alpha1","resourceVersion":"101452939"}, "reason": "Modified", "message": "PDB 'pdbnew' modified successfully"} -2022-06-27T03:48:41Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/pdbnew/status", "Action": "GET"} -2022-06-27T03:48:41Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T03:48:41Z INFO controllers.PDB Successfully obtained PDB state {"getPDBState": "oracle-database-operator-system/pdb1", "PDB Name": "pdbnew", "State": "READ WRITE"} -2022-06-27T03:48:41Z INFO controllers.PDB Reconcile completed {"onpremdboperator": "oracle-database-operator-system/pdb1"} - - - --- Verify the status of the PDB: - -SQL> show pdbs - - CON_ID CON_NAME OPEN MODE RESTRICTED ----------- ------------------------------ ---------- ---------- - 2 PDB$SEED READ WRITE NO - 3 PDBNEW READ WRITE NO - 4 PDBNEWCLONE READ WRITE NO diff --git a/docs/multitenant/provisioning/modify_pdb.md b/docs/multitenant/provisioning/modify_pdb.md deleted file mode 100644 index a0432efb..00000000 --- a/docs/multitenant/provisioning/modify_pdb.md +++ /dev/null @@ -1,69 +0,0 @@ -# Modify a PDB using Oracle DB Operator On-Prem Controller in a target CDB - -In this use case, the state of an existing PDB is modified using Oracle DB Operator On-Prem controller. - -To modify a PDB CRD Resource, a sample .yaml file is available here: [config/samples/onpremdb/pdb_modify.yaml](../../../config/samples/onpremdb/pdb_modify.yaml) - -**NOTE:** It is assumed that before this step, you have followed the [prerequisite](./../README.md#prerequsites-to-manage-pdb-life-cycle-using-oracle-db-operator-on-prem-database-controller) steps. - -Subcase 1: This example uses `modify_pdb_close.yaml` to close a PDB using Oracle DB Operator On-Prem Controller with: - -- PDB CRD resource Name as `pdb1` -- Pluggable Database (PDB) Name as `pdbnew` -- Target CDB CRD Resource Name as `cdb-dev` -- Target CDB name as `goldcdb` -- Action to be taken on the PDB as `MODIFY` -- Target state of the PDB as `CLOSE` -- Option to close the state (i.e. modify) as `IMMEDIATE` - - -**NOTE:** For the details of the parameters to be used in the .yaml file, please refer [config/crd/bases/database.oracle.com_pdbs.yaml](../../../config/crd/bases/database.oracle.com_pdbs.yaml) - -Use the file: [modify_pdb_close.yaml](./modify_pdb_close.yaml) for this use case as below: - -1. Deploy the .yaml file: -```sh -% kubectl apply -f modify_pdb_close.yaml -pdb.database.oracle.com/pdb1 configured -``` - -2. Monitor the Oracle DB Operator Pod for the progress of the PDB creation. - -NOTE: Check the DB Operator Pod name in your environment. - -``` -[root@test-server oracle-database-operator]# kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -``` - -Subcase 2: This example uses `modify_pdb_open.yaml` to open a PDB using Oracle DB Operator On-Prem Controller with: - -- PDB CRD resource Name as `pdb1` -- Pluggable Database (PDB) Name as `pdbnew` -- Target CDB CRD Resource Name as `cdb-dev` -- Target CDB name as `goldcdb` -- Action to be taken on the PDB as `MODIFY` -- Target state of the PDB as `OPEN` -- Option to close the state (i.e. modify) as `READ WRITE` - - -**NOTE:** For the details of the parameters to be used in the .yaml file, please refer [config/crd/bases/database.oracle.com_pdbs.yaml](../../../config/crd/bases/database.oracle.com_pdbs.yaml) - -Use the file: [modify_pdb_open.yaml](./modify_pdb_open.yaml) for this use case as below: - -1. Deploy the .yaml file: -```sh -% kubectl apply -f modify_pdb_open.yaml -pdb.database.oracle.com/pdb1 configured -``` - -2. Monitor the Oracle DB Operator Pod for the progress of the PDB creation. - -NOTE: Check the DB Operator Pod name in your environment. - -``` -[root@test-server oracle-database-operator]# kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -``` - -## Sample Output - -[Here](./modify_pdb.log) is the sample output for a PDB created using Oracle DB Operator On-Prem Controller using file [modify_pdb_close.yaml](./modify_pdb_close.yaml) and [modify_pdb_open.yaml](./modify_pdb_open.yaml) diff --git a/docs/multitenant/provisioning/modify_pdb_close.yaml b/docs/multitenant/provisioning/modify_pdb_close.yaml deleted file mode 100644 index 8897b482..00000000 --- a/docs/multitenant/provisioning/modify_pdb_close.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: PDB -metadata: - name: pdb1 - namespace: oracle-database-operator-system - labels: - cdb: cdb-dev -spec: - cdbResName: "cdb-dev" - cdbName: "goldcdb" - pdbName: "pdbnew" - pdbState: "CLOSE" - modifyOption: "IMMEDIATE" - action: "Modify" diff --git a/docs/multitenant/provisioning/modify_pdb_open.yaml b/docs/multitenant/provisioning/modify_pdb_open.yaml deleted file mode 100644 index 0ec640d4..00000000 --- a/docs/multitenant/provisioning/modify_pdb_open.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: PDB -metadata: - name: pdb1 - namespace: oracle-database-operator-system - labels: - cdb: cdb-dev -spec: - cdbResName: "cdb-dev" - cdbName: "goldcdb" - pdbName: "pdbnew" - pdbState: "OPEN" - modifyOption: "READ WRITE" - action: "Modify" diff --git a/docs/multitenant/provisioning/multinamespace/cdb_create.yaml b/docs/multitenant/provisioning/multinamespace/cdb_create.yaml new file mode 100644 index 00000000..d3b5e04f --- /dev/null +++ b/docs/multitenant/provisioning/multinamespace/cdb_create.yaml @@ -0,0 +1,44 @@ +apiVersion: database.oracle.com/v1alpha1 +kind: CDB +metadata: + name: cdb-dev + namespace: cdbnamespace +spec: + cdbName: "DB12" + ordsImage: ".............your registry............./ords-dboper:latest" + ordsImagePullPolicy: "Always" + dbTnsurl : "...Container tns alias....." + replicas: 1 + sysAdminPwd: + secret: + secretName: "cdb1-secret" + key: "sysadmin_pwd" + ordsPwd: + secret: + secretName: "cdb1-secret" + key: "ords_pwd" + cdbAdminUser: + secret: + secretName: "cdb1-secret" + key: "cdbadmin_user" + cdbAdminPwd: + secret: + secretName: "cdb1-secret" + key: "cdbadmin_pwd" + webServerUser: + secret: + secretName: "cdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "cdb1-secret" + key: "webserver_pwd" + cdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + cdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + diff --git a/docs/multitenant/provisioning/multinamespace/pdb_clone.yaml b/docs/multitenant/provisioning/multinamespace/pdb_clone.yaml new file mode 100644 index 00000000..b88fb71b --- /dev/null +++ b/docs/multitenant/provisioning/multinamespace/pdb_clone.yaml @@ -0,0 +1,50 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +apiVersion: database.oracle.com/v1alpha1 +kind: PDB +metadata: + name: pdb2 + namespace: pdbnamespace + labels: + cdb: cdb-dev +spec: + cdbResName: "cdb-dev" + cdbNamespace: "cdbnamespace" + cdbName: "DB12" + pdbName: "pdb2_clone" + srcPdbName: "pdbdev" + fileNameConversions: "NONE" + totalSize: "UNLIMITED" + tempSize: "UNLIMITED" + assertivePdbDeletion: true + adminName: + secret: + secretName: "pdb1-secret" + key: "sysadmin_user" + adminPwd: + secret: + secretName: "pdb1-secret" + key: "sysadmin_pwd" + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + action: "Clone" diff --git a/docs/multitenant/provisioning/multinamespace/pdb_close.yaml b/docs/multitenant/provisioning/multinamespace/pdb_close.yaml new file mode 100644 index 00000000..a823f5d9 --- /dev/null +++ b/docs/multitenant/provisioning/multinamespace/pdb_close.yaml @@ -0,0 +1,44 @@ +apiVersion: database.oracle.com/v1alpha1 +kind: PDB +metadata: + name: pdb1 + namespace: pdbnamespace + labels: + cdb: cdb-dev +spec: + cdbResName: "cdb-dev" + cdbNamespace: "cdbnamespace" + cdbName: "DB12" + pdbName: "pdbdev" + adminName: + secret: + secretName: "pdb1-secret" + key: "sysadmin_user" + adminPwd: + secret: + secretName: "pdb1-secret" + key: "sysadmin_pwd" + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + pdbState: "CLOSE" + modifyOption: "IMMEDIATE" + action: "Modify" + diff --git a/docs/multitenant/provisioning/multinamespace/pdb_create.yaml b/docs/multitenant/provisioning/multinamespace/pdb_create.yaml new file mode 100644 index 00000000..200f3712 --- /dev/null +++ b/docs/multitenant/provisioning/multinamespace/pdb_create.yaml @@ -0,0 +1,46 @@ +apiVersion: database.oracle.com/v1alpha1 +kind: PDB +metadata: + name: pdb1 + namespace: pdbnamespace + labels: + cdb: cdb-dev +spec: + cdbResName: "cdb-dev" + cdbNamespace: "cdbnamespace" + cdbName: "DB12" + pdbName: "pdbdev" + adminName: + secret: + secretName: "pdb1-secret" + key: "sysadmin_user" + adminPwd: + secret: + secretName: "pdb1-secret" + key: "sysadmin_pwd" + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + fileNameConversions: "NONE" + tdeImport: false + totalSize: "1G" + tempSize: "100M" + action: "Create" + diff --git a/docs/multitenant/provisioning/multinamespace/pdb_delete.yaml b/docs/multitenant/provisioning/multinamespace/pdb_delete.yaml new file mode 100644 index 00000000..282885b0 --- /dev/null +++ b/docs/multitenant/provisioning/multinamespace/pdb_delete.yaml @@ -0,0 +1,34 @@ +apiVersion: database.oracle.com/v1alpha1 +kind: PDB +metadata: + name: pdb1 + namespace: pdbnamespace + labels: + cdb: cdb-dev +spec: + cdbResName: "cdb-dev" + cdbNamespace: "cdbnamespace" + pdbName: "pdbdev" + action: "Delete" + dropAction: "INCLUDING" + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + diff --git a/docs/multitenant/provisioning/multinamespace/pdb_open.yaml b/docs/multitenant/provisioning/multinamespace/pdb_open.yaml new file mode 100644 index 00000000..85fb2ce4 --- /dev/null +++ b/docs/multitenant/provisioning/multinamespace/pdb_open.yaml @@ -0,0 +1,43 @@ +apiVersion: database.oracle.com/v1alpha1 +kind: PDB +metadata: + name: pdb1 + namespace: pdbnamespace + labels: + cdb: cdb-dev +spec: + cdbResName: "cdb-dev" + cdbNamespace: "cdbnamespace" + cdbName: "DB12" + pdbName: "pdbdev" + adminName: + secret: + secretName: "pdb1-secret" + key: "sysadmin_user" + adminPwd: + secret: + secretName: "pdb1-secret" + key: "sysadmin_pwd" + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + action: "Modify" + pdbState: "OPEN" + modifyOption: "READ WRITE" diff --git a/docs/multitenant/provisioning/multinamespace/pdb_plug.yaml b/docs/multitenant/provisioning/multinamespace/pdb_plug.yaml new file mode 100644 index 00000000..d9135f13 --- /dev/null +++ b/docs/multitenant/provisioning/multinamespace/pdb_plug.yaml @@ -0,0 +1,46 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +apiVersion: database.oracle.com/v1alpha1 +kind: PDB +metadata: + name: pdb1 + namespace: pdbnamespace + labels: + cdb: cdb-dev +spec: + cdbResName: "cdb-dev" + cdbNamespace: "cdbnamespace" + cdbName: "DB12" + pdbName: "pdbdev" + xmlFileName: "/tmp/pdb.xml" + fileNameConversions: "NONE" + sourceFileNameConversions: "NONE" + copyAction: "MOVE" + totalSize: "1G" + tempSize: "100M" + action: "Plug" + assertivePdbDeletion: true + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + + diff --git a/docs/multitenant/provisioning/multinamespace/pdb_unplug.yaml b/docs/multitenant/provisioning/multinamespace/pdb_unplug.yaml new file mode 100644 index 00000000..f3667dad --- /dev/null +++ b/docs/multitenant/provisioning/multinamespace/pdb_unplug.yaml @@ -0,0 +1,39 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +apiVersion: database.oracle.com/v1alpha1 +kind: PDB +metadata: + name: pdb1 + namespace: pdbnamespace + labels: + cdb: cdb-dev +spec: + cdbResName: "cdb-dev" + cdbNamespace: "cdbnamespace" + cdbName: "DB12" + pdbName: "pdbdev" + xmlFileName: "/tmp/pdb.xml" + action: "Unplug" + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + diff --git a/docs/multitenant/provisioning/ords_image.log b/docs/multitenant/provisioning/ords_image.log deleted file mode 100644 index 771a22ca..00000000 --- a/docs/multitenant/provisioning/ords_image.log +++ /dev/null @@ -1,503 +0,0 @@ -/usr/bin/docker build -t oracle/ords-dboper:22.2.1 . -Sending build context to Docker daemon 280.6kB -Step 1/10 : FROM container-registry.oracle.com/java/jdk:latest - ---> 44b86e8925c4 -Step 2/10 : ENV ORDS_HOME=/opt/oracle/ords RUN_FILE="runOrdsSSL.sh" - ---> Running in e22c5a03b869 -Removing intermediate container e22c5a03b869 - ---> 1421497abef8 -Step 3/10 : COPY $RUN_FILE $ORDS_HOME/ - ---> d96ac1477d2d -Step 4/10 : RUN yum -y install yum-utils bind-utils tree hostname openssl net-tools zip unzip tar wget vim-minimal which sudo expect procps && yum-config-manager --add-repo=http://yum.oracle.com/repo/OracleLinux/OL8/oracle/software/x86_64 && yum -y install java-11-openjdk-devel && yum -y install ords && yum -y install iproute && yum clean all - ---> Running in c08b8dac80a5 -Oracle Linux 8 BaseOS Latest (x86_64) 72 MB/s | 49 MB 00:00 -Oracle Linux 8 Application Stream (x86_64) 88 MB/s | 37 MB 00:00 -Last metadata expiration check: 0:00:07 ago on Mon 12 Sep 2022 03:23:32 PM UTC. -Package yum-utils-4.0.21-11.0.1.el8.noarch is already installed. -Package vim-minimal-2:8.0.1763-19.0.1.el8_6.2.x86_64 is already installed. -Package procps-ng-3.3.15-6.0.1.el8.x86_64 is already installed. -Dependencies resolved. -================================================================================ - Package Arch Version Repository Size -================================================================================ -Installing: - bind-utils x86_64 32:9.11.36-3.el8 ol8_appstream 452 k - expect x86_64 5.45.4-5.el8 ol8_baseos_latest 266 k - hostname x86_64 3.20-6.el8 ol8_baseos_latest 32 k - net-tools x86_64 2.0-0.52.20160912git.el8 ol8_baseos_latest 322 k - openssl x86_64 1:1.1.1k-7.el8_6 ol8_baseos_latest 709 k - sudo x86_64 1.8.29-8.el8 ol8_baseos_latest 925 k - tar x86_64 2:1.30-5.el8 ol8_baseos_latest 838 k - tree x86_64 1.7.0-15.el8 ol8_baseos_latest 59 k - unzip x86_64 6.0-46.0.1.el8 ol8_baseos_latest 196 k - wget x86_64 1.19.5-10.0.1.el8 ol8_appstream 734 k - which x86_64 2.21-17.el8 ol8_baseos_latest 49 k - zip x86_64 3.0-23.el8 ol8_baseos_latest 270 k -Upgrading: - openssl-libs x86_64 1:1.1.1k-7.el8_6 ol8_baseos_latest 1.5 M - vim-minimal x86_64 2:8.0.1763-19.0.1.el8_6.4 ol8_baseos_latest 575 k -Installing dependencies: - bind-libs x86_64 32:9.11.36-3.el8 ol8_appstream 175 k - bind-libs-lite x86_64 32:9.11.36-3.el8 ol8_appstream 1.2 M - bind-license noarch 32:9.11.36-3.el8 ol8_appstream 103 k - fstrm x86_64 0.6.1-2.el8 ol8_appstream 29 k - libmaxminddb x86_64 1.2.0-10.el8 ol8_appstream 33 k - libmetalink x86_64 0.1.3-7.el8 ol8_baseos_latest 32 k - protobuf-c x86_64 1.3.0-6.el8 ol8_appstream 37 k - python3-bind noarch 32:9.11.36-3.el8 ol8_appstream 150 k - python3-ply noarch 3.9-9.el8 ol8_baseos_latest 111 k - tcl x86_64 1:8.6.8-2.el8 ol8_baseos_latest 1.1 M - -Transaction Summary -================================================================================ -Install 22 Packages -Upgrade 2 Packages - -Total download size: 9.7 M -Downloading Packages: -(1/24): expect-5.45.4-5.el8.x86_64.rpm 158 kB/s | 266 kB 00:01 -(2/24): hostname-3.20-6.el8.x86_64.rpm 18 kB/s | 32 kB 00:01 -(3/24): libmetalink-0.1.3-7.el8.x86_64.rpm 18 kB/s | 32 kB 00:01 -(4/24): net-tools-2.0-0.52.20160912git.el8.x86_ 2.3 MB/s | 322 kB 00:00 -(5/24): openssl-1.1.1k-7.el8_6.x86_64.rpm 4.0 MB/s | 709 kB 00:00 -(6/24): python3-ply-3.9-9.el8.noarch.rpm 538 kB/s | 111 kB 00:00 -(7/24): sudo-1.8.29-8.el8.x86_64.rpm 5.0 MB/s | 925 kB 00:00 -(8/24): tar-1.30-5.el8.x86_64.rpm 4.2 MB/s | 838 kB 00:00 -(9/24): unzip-6.0-46.0.1.el8.x86_64.rpm 3.6 MB/s | 196 kB 00:00 -(10/24): tcl-8.6.8-2.el8.x86_64.rpm 4.1 MB/s | 1.1 MB 00:00 -(11/24): which-2.21-17.el8.x86_64.rpm 613 kB/s | 49 kB 00:00 -(12/24): tree-1.7.0-15.el8.x86_64.rpm 208 kB/s | 59 kB 00:00 -(13/24): bind-libs-9.11.36-3.el8.x86_64.rpm 1.3 MB/s | 175 kB 00:00 -(14/24): bind-license-9.11.36-3.el8.noarch.rpm 2.6 MB/s | 103 kB 00:00 -(15/24): bind-libs-lite-9.11.36-3.el8.x86_64.rp 6.8 MB/s | 1.2 MB 00:00 -(16/24): bind-utils-9.11.36-3.el8.x86_64.rpm 3.6 MB/s | 452 kB 00:00 -(17/24): zip-3.0-23.el8.x86_64.rpm 804 kB/s | 270 kB 00:00 -(18/24): libmaxminddb-1.2.0-10.el8.x86_64.rpm 529 kB/s | 33 kB 00:00 -(19/24): fstrm-0.6.1-2.el8.x86_64.rpm 161 kB/s | 29 kB 00:00 -(20/24): python3-bind-9.11.36-3.el8.noarch.rpm 2.0 MB/s | 150 kB 00:00 -(21/24): protobuf-c-1.3.0-6.el8.x86_64.rpm 351 kB/s | 37 kB 00:00 -(22/24): vim-minimal-8.0.1763-19.0.1.el8_6.4.x8 6.4 MB/s | 575 kB 00:00 -(23/24): wget-1.19.5-10.0.1.el8.x86_64.rpm 3.3 MB/s | 734 kB 00:00 -(24/24): openssl-libs-1.1.1k-7.el8_6.x86_64.rpm 6.8 MB/s | 1.5 MB 00:00 --------------------------------------------------------------------------------- -Total 3.3 MB/s | 9.7 MB 00:02 -Running transaction check -Transaction check succeeded. -Running transaction test -Transaction test succeeded. -Running transaction - Preparing : 1/1 - Upgrading : openssl-libs-1:1.1.1k-7.el8_6.x86_64 1/26 - Running scriptlet: openssl-libs-1:1.1.1k-7.el8_6.x86_64 1/26 - Installing : protobuf-c-1.3.0-6.el8.x86_64 2/26 - Installing : libmaxminddb-1.2.0-10.el8.x86_64 3/26 - Running scriptlet: libmaxminddb-1.2.0-10.el8.x86_64 3/26 - Installing : fstrm-0.6.1-2.el8.x86_64 4/26 - Installing : bind-license-32:9.11.36-3.el8.noarch 5/26 - Installing : bind-libs-lite-32:9.11.36-3.el8.x86_64 6/26 - Installing : bind-libs-32:9.11.36-3.el8.x86_64 7/26 - Upgrading : vim-minimal-2:8.0.1763-19.0.1.el8_6.4.x86_64 8/26 - Installing : unzip-6.0-46.0.1.el8.x86_64 9/26 - Installing : tcl-1:8.6.8-2.el8.x86_64 10/26 - Running scriptlet: tcl-1:8.6.8-2.el8.x86_64 10/26 - Installing : python3-ply-3.9-9.el8.noarch 11/26 - Installing : python3-bind-32:9.11.36-3.el8.noarch 12/26 - Installing : libmetalink-0.1.3-7.el8.x86_64 13/26 - Installing : wget-1.19.5-10.0.1.el8.x86_64 14/26 - Running scriptlet: wget-1.19.5-10.0.1.el8.x86_64 14/26 - Installing : bind-utils-32:9.11.36-3.el8.x86_64 15/26 - Installing : expect-5.45.4-5.el8.x86_64 16/26 - Installing : zip-3.0-23.el8.x86_64 17/26 - Installing : sudo-1.8.29-8.el8.x86_64 18/26 - Running scriptlet: sudo-1.8.29-8.el8.x86_64 18/26 - Installing : openssl-1:1.1.1k-7.el8_6.x86_64 19/26 - Installing : which-2.21-17.el8.x86_64 20/26 - Installing : tree-1.7.0-15.el8.x86_64 21/26 - Installing : tar-2:1.30-5.el8.x86_64 22/26 - Running scriptlet: tar-2:1.30-5.el8.x86_64 22/26 - Installing : net-tools-2.0-0.52.20160912git.el8.x86_64 23/26 - Running scriptlet: net-tools-2.0-0.52.20160912git.el8.x86_64 23/26 - Installing : hostname-3.20-6.el8.x86_64 24/26 - Running scriptlet: hostname-3.20-6.el8.x86_64 24/26 - Cleanup : vim-minimal-2:8.0.1763-19.0.1.el8_6.2.x86_64 25/26 - Cleanup : openssl-libs-1:1.1.1k-6.el8_5.x86_64 26/26 - Running scriptlet: openssl-libs-1:1.1.1k-6.el8_5.x86_64 26/26 - Verifying : expect-5.45.4-5.el8.x86_64 1/26 - Verifying : hostname-3.20-6.el8.x86_64 2/26 - Verifying : libmetalink-0.1.3-7.el8.x86_64 3/26 - Verifying : net-tools-2.0-0.52.20160912git.el8.x86_64 4/26 - Verifying : openssl-1:1.1.1k-7.el8_6.x86_64 5/26 - Verifying : python3-ply-3.9-9.el8.noarch 6/26 - Verifying : sudo-1.8.29-8.el8.x86_64 7/26 - Verifying : tar-2:1.30-5.el8.x86_64 8/26 - Verifying : tcl-1:8.6.8-2.el8.x86_64 9/26 - Verifying : tree-1.7.0-15.el8.x86_64 10/26 - Verifying : unzip-6.0-46.0.1.el8.x86_64 11/26 - Verifying : which-2.21-17.el8.x86_64 12/26 - Verifying : zip-3.0-23.el8.x86_64 13/26 - Verifying : bind-libs-32:9.11.36-3.el8.x86_64 14/26 - Verifying : bind-libs-lite-32:9.11.36-3.el8.x86_64 15/26 - Verifying : bind-license-32:9.11.36-3.el8.noarch 16/26 - Verifying : bind-utils-32:9.11.36-3.el8.x86_64 17/26 - Verifying : fstrm-0.6.1-2.el8.x86_64 18/26 - Verifying : libmaxminddb-1.2.0-10.el8.x86_64 19/26 - Verifying : protobuf-c-1.3.0-6.el8.x86_64 20/26 - Verifying : python3-bind-32:9.11.36-3.el8.noarch 21/26 - Verifying : wget-1.19.5-10.0.1.el8.x86_64 22/26 - Verifying : openssl-libs-1:1.1.1k-7.el8_6.x86_64 23/26 - Verifying : openssl-libs-1:1.1.1k-6.el8_5.x86_64 24/26 - Verifying : vim-minimal-2:8.0.1763-19.0.1.el8_6.4.x86_64 25/26 - Verifying : vim-minimal-2:8.0.1763-19.0.1.el8_6.2.x86_64 26/26 - -Upgraded: - openssl-libs-1:1.1.1k-7.el8_6.x86_64 - vim-minimal-2:8.0.1763-19.0.1.el8_6.4.x86_64 -Installed: - bind-libs-32:9.11.36-3.el8.x86_64 - bind-libs-lite-32:9.11.36-3.el8.x86_64 - bind-license-32:9.11.36-3.el8.noarch - bind-utils-32:9.11.36-3.el8.x86_64 - expect-5.45.4-5.el8.x86_64 - fstrm-0.6.1-2.el8.x86_64 - hostname-3.20-6.el8.x86_64 - libmaxminddb-1.2.0-10.el8.x86_64 - libmetalink-0.1.3-7.el8.x86_64 - net-tools-2.0-0.52.20160912git.el8.x86_64 - openssl-1:1.1.1k-7.el8_6.x86_64 - protobuf-c-1.3.0-6.el8.x86_64 - python3-bind-32:9.11.36-3.el8.noarch - python3-ply-3.9-9.el8.noarch - sudo-1.8.29-8.el8.x86_64 - tar-2:1.30-5.el8.x86_64 - tcl-1:8.6.8-2.el8.x86_64 - tree-1.7.0-15.el8.x86_64 - unzip-6.0-46.0.1.el8.x86_64 - wget-1.19.5-10.0.1.el8.x86_64 - which-2.21-17.el8.x86_64 - zip-3.0-23.el8.x86_64 - -Complete! -Adding repo from: http://yum.oracle.com/repo/OracleLinux/OL8/oracle/software/x86_64 -created by dnf config-manager from http://yum.o 221 kB/s | 45 kB 00:00 -Dependencies resolved. -============================================================================================= - Package Arch Version Repository Size -============================================================================================= -Installing: - java-11-openjdk-devel x86_64 1:11.0.16.1.1-1.el8_6 ol8_appstream 3.4 M -Installing dependencies: - alsa-lib x86_64 1.2.6.1-3.el8 ol8_appstream 491 k - avahi-libs x86_64 0.7-20.el8 ol8_baseos_latest 62 k - copy-jdk-configs noarch 4.0-2.el8 ol8_appstream 30 k - crypto-policies-scripts noarch 20211116-1.gitae470d6.el8 ol8_baseos_latest 83 k - cups-libs x86_64 1:2.2.6-45.el8_6.2 ol8_baseos_latest 434 k - giflib x86_64 5.1.4-3.el8 ol8_appstream 51 k - graphite2 x86_64 1.3.10-10.el8 ol8_appstream 122 k - harfbuzz x86_64 1.7.5-3.el8 ol8_appstream 295 k - java-11-openjdk x86_64 1:11.0.16.1.1-1.el8_6 ol8_appstream 272 k - java-11-openjdk-headless x86_64 1:11.0.16.1.1-1.el8_6 ol8_appstream 40 M - javapackages-filesystem noarch 5.3.0-1.module+el8+5136+7ff78f74 ol8_appstream 30 k - lcms2 x86_64 2.9-2.el8 ol8_appstream 164 k - libX11 x86_64 1.6.8-5.el8 ol8_appstream 611 k - libX11-common noarch 1.6.8-5.el8 ol8_appstream 158 k - libXau x86_64 1.0.9-3.el8 ol8_appstream 37 k - libXcomposite x86_64 0.4.4-14.el8 ol8_appstream 28 k - libXext x86_64 1.3.4-1.el8 ol8_appstream 45 k - libXi x86_64 1.7.10-1.el8 ol8_appstream 49 k - libXrender x86_64 0.9.10-7.el8 ol8_appstream 33 k - libXtst x86_64 1.2.3-7.el8 ol8_appstream 22 k - libfontenc x86_64 1.1.3-8.el8 ol8_appstream 37 k - libjpeg-turbo x86_64 1.5.3-12.el8 ol8_appstream 157 k - libpkgconf x86_64 1.4.2-1.el8 ol8_baseos_latest 35 k - libxcb x86_64 1.13.1-1.el8 ol8_appstream 231 k - lksctp-tools x86_64 1.0.18-3.el8 ol8_baseos_latest 100 k - lua x86_64 5.3.4-12.el8 ol8_appstream 192 k - nspr x86_64 4.32.0-1.el8_4 ol8_appstream 142 k - nss x86_64 3.67.0-7.el8_5 ol8_appstream 741 k - nss-softokn x86_64 3.67.0-7.el8_5 ol8_appstream 487 k - nss-softokn-freebl x86_64 3.67.0-7.el8_5 ol8_appstream 395 k - nss-sysinit x86_64 3.67.0-7.el8_5 ol8_appstream 73 k - nss-util x86_64 3.67.0-7.el8_5 ol8_appstream 137 k - pkgconf x86_64 1.4.2-1.el8 ol8_baseos_latest 38 k - pkgconf-m4 noarch 1.4.2-1.el8 ol8_baseos_latest 17 k - pkgconf-pkg-config x86_64 1.4.2-1.el8 ol8_baseos_latest 15 k - ttmkfdir x86_64 3.0.9-54.el8 ol8_appstream 62 k - tzdata-java noarch 2022c-1.el8 ol8_appstream 186 k - xorg-x11-font-utils x86_64 1:7.5-41.el8 ol8_appstream 104 k - xorg-x11-fonts-Type1 noarch 7.5-19.el8 ol8_appstream 522 k -Enabling module streams: - javapackages-runtime 201801 - -Transaction Summary -============================================================================================= -Install 40 Packages - -Total download size: 50 M -Installed size: 194 M -Downloading Packages: -(1/40): crypto-policies-scripts-20211116-1.gita 1.3 MB/s | 83 kB 00:00 -(2/40): avahi-libs-0.7-20.el8.x86_64.rpm 952 kB/s | 62 kB 00:00 -(3/40): libpkgconf-1.4.2-1.el8.x86_64.rpm 2.2 MB/s | 35 kB 00:00 -(4/40): cups-libs-2.2.6-45.el8_6.2.x86_64.rpm 4.9 MB/s | 434 kB 00:00 -(5/40): lksctp-tools-1.0.18-3.el8.x86_64.rpm 3.9 MB/s | 100 kB 00:00 -(6/40): pkgconf-1.4.2-1.el8.x86_64.rpm 2.3 MB/s | 38 kB 00:00 -(7/40): pkgconf-m4-1.4.2-1.el8.noarch.rpm 1.1 MB/s | 17 kB 00:00 -(8/40): pkgconf-pkg-config-1.4.2-1.el8.x86_64.r 1.1 MB/s | 15 kB 00:00 -(9/40): copy-jdk-configs-4.0-2.el8.noarch.rpm 1.8 MB/s | 30 kB 00:00 -(10/40): giflib-5.1.4-3.el8.x86_64.rpm 3.0 MB/s | 51 kB 00:00 -(11/40): alsa-lib-1.2.6.1-3.el8.x86_64.rpm 12 MB/s | 491 kB 00:00 -(12/40): graphite2-1.3.10-10.el8.x86_64.rpm 5.9 MB/s | 122 kB 00:00 -(13/40): harfbuzz-1.7.5-3.el8.x86_64.rpm 13 MB/s | 295 kB 00:00 -(14/40): java-11-openjdk-11.0.16.1.1-1.el8_6.x8 15 MB/s | 272 kB 00:00 -(15/40): javapackages-filesystem-5.3.0-1.module 2.1 MB/s | 30 kB 00:00 -(16/40): lcms2-2.9-2.el8.x86_64.rpm 9.5 MB/s | 164 kB 00:00 -(17/40): libX11-1.6.8-5.el8.x86_64.rpm 24 MB/s | 611 kB 00:00 -(18/40): java-11-openjdk-devel-11.0.16.1.1-1.el 40 MB/s | 3.4 MB 00:00 -(19/40): libX11-common-1.6.8-5.el8.noarch.rpm 8.6 MB/s | 158 kB 00:00 -(20/40): libXau-1.0.9-3.el8.x86_64.rpm 2.6 MB/s | 37 kB 00:00 -(21/40): libXcomposite-0.4.4-14.el8.x86_64.rpm 2.2 MB/s | 28 kB 00:00 -(22/40): libXext-1.3.4-1.el8.x86_64.rpm 2.7 MB/s | 45 kB 00:00 -(23/40): libXi-1.7.10-1.el8.x86_64.rpm 2.8 MB/s | 49 kB 00:00 -(24/40): libXrender-0.9.10-7.el8.x86_64.rpm 2.4 MB/s | 33 kB 00:00 -(25/40): libXtst-1.2.3-7.el8.x86_64.rpm 1.6 MB/s | 22 kB 00:00 -(26/40): libfontenc-1.1.3-8.el8.x86_64.rpm 2.7 MB/s | 37 kB 00:00 -(27/40): libjpeg-turbo-1.5.3-12.el8.x86_64.rpm 9.6 MB/s | 157 kB 00:00 -(28/40): libxcb-1.13.1-1.el8.x86_64.rpm 13 MB/s | 231 kB 00:00 -(29/40): lua-5.3.4-12.el8.x86_64.rpm 11 MB/s | 192 kB 00:00 -(30/40): nspr-4.32.0-1.el8_4.x86_64.rpm 9.2 MB/s | 142 kB 00:00 -(31/40): nss-3.67.0-7.el8_5.x86_64.rpm 31 MB/s | 741 kB 00:00 -(32/40): nss-softokn-3.67.0-7.el8_5.x86_64.rpm 24 MB/s | 487 kB 00:00 -(33/40): nss-softokn-freebl-3.67.0-7.el8_5.x86_ 18 MB/s | 395 kB 00:00 -(34/40): nss-sysinit-3.67.0-7.el8_5.x86_64.rpm 4.3 MB/s | 73 kB 00:00 -(35/40): nss-util-3.67.0-7.el8_5.x86_64.rpm 8.7 MB/s | 137 kB 00:00 -(36/40): ttmkfdir-3.0.9-54.el8.x86_64.rpm 4.0 MB/s | 62 kB 00:00 -(37/40): tzdata-java-2022c-1.el8.noarch.rpm 12 MB/s | 186 kB 00:00 -(38/40): xorg-x11-font-utils-7.5-41.el8.x86_64. 6.0 MB/s | 104 kB 00:00 -(39/40): xorg-x11-fonts-Type1-7.5-19.el8.noarch 23 MB/s | 522 kB 00:00 -(40/40): java-11-openjdk-headless-11.0.16.1.1-1 73 MB/s | 40 MB 00:00 --------------------------------------------------------------------------------- -Total 71 MB/s | 50 MB 00:00 -Running transaction check -Transaction check succeeded. -Running transaction test -Transaction test succeeded. -Running transaction - Running scriptlet: copy-jdk-configs-4.0-2.el8.noarch 1/1 - Running scriptlet: java-11-openjdk-headless-1:11.0.16.1.1-1.el8_6.x86_6 1/1 - Preparing : 1/1 - Installing : nspr-4.32.0-1.el8_4.x86_64 1/40 - Running scriptlet: nspr-4.32.0-1.el8_4.x86_64 1/40 - Installing : nss-util-3.67.0-7.el8_5.x86_64 2/40 - Installing : libjpeg-turbo-1.5.3-12.el8.x86_64 3/40 - Installing : nss-softokn-freebl-3.67.0-7.el8_5.x86_64 4/40 - Installing : nss-softokn-3.67.0-7.el8_5.x86_64 5/40 - Installing : tzdata-java-2022c-1.el8.noarch 6/40 - Installing : ttmkfdir-3.0.9-54.el8.x86_64 7/40 - Installing : lua-5.3.4-12.el8.x86_64 8/40 - Installing : copy-jdk-configs-4.0-2.el8.noarch 9/40 - Installing : libfontenc-1.1.3-8.el8.x86_64 10/40 - Installing : libXau-1.0.9-3.el8.x86_64 11/40 - Installing : libxcb-1.13.1-1.el8.x86_64 12/40 - Installing : libX11-common-1.6.8-5.el8.noarch 13/40 - Installing : libX11-1.6.8-5.el8.x86_64 14/40 - Installing : libXext-1.3.4-1.el8.x86_64 15/40 - Installing : libXi-1.7.10-1.el8.x86_64 16/40 - Installing : libXtst-1.2.3-7.el8.x86_64 17/40 - Installing : libXcomposite-0.4.4-14.el8.x86_64 18/40 - Installing : libXrender-0.9.10-7.el8.x86_64 19/40 - Installing : lcms2-2.9-2.el8.x86_64 20/40 - Running scriptlet: lcms2-2.9-2.el8.x86_64 20/40 - Installing : javapackages-filesystem-5.3.0-1.module+el8+5136+7f 21/40 - Installing : graphite2-1.3.10-10.el8.x86_64 22/40 - Installing : harfbuzz-1.7.5-3.el8.x86_64 23/40 - Running scriptlet: harfbuzz-1.7.5-3.el8.x86_64 23/40 - Installing : giflib-5.1.4-3.el8.x86_64 24/40 - Installing : alsa-lib-1.2.6.1-3.el8.x86_64 25/40 - Running scriptlet: alsa-lib-1.2.6.1-3.el8.x86_64 25/40 - Installing : pkgconf-m4-1.4.2-1.el8.noarch 26/40 - Installing : lksctp-tools-1.0.18-3.el8.x86_64 27/40 - Running scriptlet: lksctp-tools-1.0.18-3.el8.x86_64 27/40 - Installing : libpkgconf-1.4.2-1.el8.x86_64 28/40 - Installing : pkgconf-1.4.2-1.el8.x86_64 29/40 - Installing : pkgconf-pkg-config-1.4.2-1.el8.x86_64 30/40 - Installing : xorg-x11-font-utils-1:7.5-41.el8.x86_64 31/40 - Installing : xorg-x11-fonts-Type1-7.5-19.el8.noarch 32/40 - Running scriptlet: xorg-x11-fonts-Type1-7.5-19.el8.noarch 32/40 - Installing : crypto-policies-scripts-20211116-1.gitae470d6.el8. 33/40 - Installing : nss-sysinit-3.67.0-7.el8_5.x86_64 34/40 - Installing : nss-3.67.0-7.el8_5.x86_64 35/40 - Installing : avahi-libs-0.7-20.el8.x86_64 36/40 - Installing : cups-libs-1:2.2.6-45.el8_6.2.x86_64 37/40 - Installing : java-11-openjdk-headless-1:11.0.16.1.1-1.el8_6.x86 38/40 - Running scriptlet: java-11-openjdk-headless-1:11.0.16.1.1-1.el8_6.x86 38/40 - Installing : java-11-openjdk-1:11.0.16.1.1-1.el8_6.x86_64 39/40 - Running scriptlet: java-11-openjdk-1:11.0.16.1.1-1.el8_6.x86_64 39/40 - Installing : java-11-openjdk-devel-1:11.0.16.1.1-1.el8_6.x86_64 40/40 - Running scriptlet: java-11-openjdk-devel-1:11.0.16.1.1-1.el8_6.x86_64 40/40 - Running scriptlet: copy-jdk-configs-4.0-2.el8.noarch 40/40 - Running scriptlet: crypto-policies-scripts-20211116-1.gitae470d6.el8. 40/40 - Running scriptlet: nss-3.67.0-7.el8_5.x86_64 40/40 - Running scriptlet: java-11-openjdk-headless-1:11.0.16.1.1-1.el8_6.x86 40/40 - Running scriptlet: java-11-openjdk-1:11.0.16.1.1-1.el8_6.x86_64 40/40 - Running scriptlet: java-11-openjdk-devel-1:11.0.16.1.1-1.el8_6.x86_64 40/40 - Verifying : avahi-libs-0.7-20.el8.x86_64 1/40 - Verifying : crypto-policies-scripts-20211116-1.gitae470d6.el8. 2/40 - Verifying : cups-libs-1:2.2.6-45.el8_6.2.x86_64 3/40 - Verifying : libpkgconf-1.4.2-1.el8.x86_64 4/40 - Verifying : lksctp-tools-1.0.18-3.el8.x86_64 5/40 - Verifying : pkgconf-1.4.2-1.el8.x86_64 6/40 - Verifying : pkgconf-m4-1.4.2-1.el8.noarch 7/40 - Verifying : pkgconf-pkg-config-1.4.2-1.el8.x86_64 8/40 - Verifying : alsa-lib-1.2.6.1-3.el8.x86_64 9/40 - Verifying : copy-jdk-configs-4.0-2.el8.noarch 10/40 - Verifying : giflib-5.1.4-3.el8.x86_64 11/40 - Verifying : graphite2-1.3.10-10.el8.x86_64 12/40 - Verifying : harfbuzz-1.7.5-3.el8.x86_64 13/40 - Verifying : java-11-openjdk-1:11.0.16.1.1-1.el8_6.x86_64 14/40 - Verifying : java-11-openjdk-devel-1:11.0.16.1.1-1.el8_6.x86_64 15/40 - Verifying : java-11-openjdk-headless-1:11.0.16.1.1-1.el8_6.x86 16/40 - Verifying : javapackages-filesystem-5.3.0-1.module+el8+5136+7f 17/40 - Verifying : lcms2-2.9-2.el8.x86_64 18/40 - Verifying : libX11-1.6.8-5.el8.x86_64 19/40 - Verifying : libX11-common-1.6.8-5.el8.noarch 20/40 - Verifying : libXau-1.0.9-3.el8.x86_64 21/40 - Verifying : libXcomposite-0.4.4-14.el8.x86_64 22/40 - Verifying : libXext-1.3.4-1.el8.x86_64 23/40 - Verifying : libXi-1.7.10-1.el8.x86_64 24/40 - Verifying : libXrender-0.9.10-7.el8.x86_64 25/40 - Verifying : libXtst-1.2.3-7.el8.x86_64 26/40 - Verifying : libfontenc-1.1.3-8.el8.x86_64 27/40 - Verifying : libjpeg-turbo-1.5.3-12.el8.x86_64 28/40 - Verifying : libxcb-1.13.1-1.el8.x86_64 29/40 - Verifying : lua-5.3.4-12.el8.x86_64 30/40 - Verifying : nspr-4.32.0-1.el8_4.x86_64 31/40 - Verifying : nss-3.67.0-7.el8_5.x86_64 32/40 - Verifying : nss-softokn-3.67.0-7.el8_5.x86_64 33/40 - Verifying : nss-softokn-freebl-3.67.0-7.el8_5.x86_64 34/40 - Verifying : nss-sysinit-3.67.0-7.el8_5.x86_64 35/40 - Verifying : nss-util-3.67.0-7.el8_5.x86_64 36/40 - Verifying : ttmkfdir-3.0.9-54.el8.x86_64 37/40 - Verifying : tzdata-java-2022c-1.el8.noarch 38/40 - Verifying : xorg-x11-font-utils-1:7.5-41.el8.x86_64 39/40 - Verifying : xorg-x11-fonts-Type1-7.5-19.el8.noarch 40/40 - -Installed: - alsa-lib-1.2.6.1-3.el8.x86_64 - avahi-libs-0.7-20.el8.x86_64 - copy-jdk-configs-4.0-2.el8.noarch - crypto-policies-scripts-20211116-1.gitae470d6.el8.noarch - cups-libs-1:2.2.6-45.el8_6.2.x86_64 - giflib-5.1.4-3.el8.x86_64 - graphite2-1.3.10-10.el8.x86_64 - harfbuzz-1.7.5-3.el8.x86_64 - java-11-openjdk-1:11.0.16.1.1-1.el8_6.x86_64 - java-11-openjdk-devel-1:11.0.16.1.1-1.el8_6.x86_64 - java-11-openjdk-headless-1:11.0.16.1.1-1.el8_6.x86_64 - javapackages-filesystem-5.3.0-1.module+el8+5136+7ff78f74.noarch - lcms2-2.9-2.el8.x86_64 - libX11-1.6.8-5.el8.x86_64 - libX11-common-1.6.8-5.el8.noarch - libXau-1.0.9-3.el8.x86_64 - libXcomposite-0.4.4-14.el8.x86_64 - libXext-1.3.4-1.el8.x86_64 - libXi-1.7.10-1.el8.x86_64 - libXrender-0.9.10-7.el8.x86_64 - libXtst-1.2.3-7.el8.x86_64 - libfontenc-1.1.3-8.el8.x86_64 - libjpeg-turbo-1.5.3-12.el8.x86_64 - libpkgconf-1.4.2-1.el8.x86_64 - libxcb-1.13.1-1.el8.x86_64 - lksctp-tools-1.0.18-3.el8.x86_64 - lua-5.3.4-12.el8.x86_64 - nspr-4.32.0-1.el8_4.x86_64 - nss-3.67.0-7.el8_5.x86_64 - nss-softokn-3.67.0-7.el8_5.x86_64 - nss-softokn-freebl-3.67.0-7.el8_5.x86_64 - nss-sysinit-3.67.0-7.el8_5.x86_64 - nss-util-3.67.0-7.el8_5.x86_64 - pkgconf-1.4.2-1.el8.x86_64 - pkgconf-m4-1.4.2-1.el8.noarch - pkgconf-pkg-config-1.4.2-1.el8.x86_64 - ttmkfdir-3.0.9-54.el8.x86_64 - tzdata-java-2022c-1.el8.noarch - xorg-x11-font-utils-1:7.5-41.el8.x86_64 - xorg-x11-fonts-Type1-7.5-19.el8.noarch - -Complete! -Last metadata expiration check: 0:00:10 ago on Mon 12 Sep 2022 03:23:49 PM UTC. -Dependencies resolved. -============================================================================================== - Package - Arch Version Repository Size -============================================================================================== -Installing: - ords noarch 22.2.1-2.el8 yum.oracle.com_repo_OracleLinux_OL8_oracle_software_x86_64 83 M -Installing dependencies: - lsof x86_64 4.93.2-1.el8 ol8_baseos_latest 253 k - -Transaction Summary -============================================================================================== -Install 2 Packages - -Total download size: 83 M -Installed size: 87 M -Downloading Packages: -(1/2): lsof-4.93.2-1.el8.x86_64.rpm 3.0 MB/s | 253 kB 00:00 -(2/2): ords-22.2.1-2.el8.noarch.rpm 56 MB/s | 83 MB 00:01 --------------------------------------------------------------------------------- -Total 56 MB/s | 83 MB 00:01 -Running transaction check -Transaction check succeeded. -Running transaction test -Transaction test succeeded. -Running transaction - Preparing : 1/1 - Installing : lsof-4.93.2-1.el8.x86_64 1/2 - Running scriptlet: ords-22.2.1-2.el8.noarch 2/2 - Installing : ords-22.2.1-2.el8.noarch 2/2 - Running scriptlet: ords-22.2.1-2.el8.noarch 2/2 -INFO: Before starting ORDS service, run the below command as user oracle: - ords --config /etc/ords/config install - - Verifying : lsof-4.93.2-1.el8.x86_64 1/2 - Verifying : ords-22.2.1-2.el8.noarch 2/2 - -Installed: - lsof-4.93.2-1.el8.x86_64 ords-22.2.1-2.el8.noarch - -Complete! -Last metadata expiration check: 0:00:15 ago on Mon 12 Sep 2022 03:23:49 PM UTC. -Package iproute-5.15.0-4.el8.x86_64 is already installed. -Dependencies resolved. -Nothing to do. -Complete! -24 files removed -Removing intermediate container c08b8dac80a5 - ---> bb1a717f3e6e -Step 5/10 : RUN mkdir -p $ORDS_HOME/doc_root && mkdir -p $ORDS_HOME/error && mkdir -p $ORDS_HOME/secrets && chmod ug+x $ORDS_HOME/*.sh && groupadd -g 54322 dba && usermod -u 54321 -d /home/oracle -g dba -m -s /bin/bash oracle && chown -R oracle:dba $ORDS_HOME && echo "oracle ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers - ---> Running in 0103c070f4b6 -Removing intermediate container 0103c070f4b6 - ---> 089d06d9b198 -Step 6/10 : USER oracle - ---> Running in 51b1846c8c6f -Removing intermediate container 51b1846c8c6f - ---> 6c7b115954a4 -Step 7/10 : WORKDIR /home/oracle - ---> Running in 5862e2bc8df9 -Removing intermediate container 5862e2bc8df9 - ---> 28543543a88c -Step 8/10 : VOLUME ["$ORDS_HOME/config/ords"] - ---> Running in 465398d6f2bb -Removing intermediate container 465398d6f2bb - ---> 4037eb7f2f12 -Step 9/10 : EXPOSE 8888 - ---> Running in 2813ab5473f6 -Removing intermediate container 2813ab5473f6 - ---> 3410f1be2fff -Step 10/10 : CMD $ORDS_HOME/$RUN_FILE - ---> Running in 0a9a72408177 -Removing intermediate container 0a9a72408177 - ---> 2ef5dc95701b -Successfully built 2ef5dc95701b -Successfully tagged oracle/ords-dboper:22.2.1 - diff --git a/docs/multitenant/provisioning/ords_image.md b/docs/multitenant/provisioning/ords_image.md index 21abcbab..e2d1dcef 100644 --- a/docs/multitenant/provisioning/ords_image.md +++ b/docs/multitenant/provisioning/ords_image.md @@ -2,43 +2,60 @@ # Build ORDS Docker Image -In the below steps, we are building an ORDS Docker Image for ORDS Software. The image built can be later pushed to a local repository to be used later for a deployment. +This file contains the steps to create an ORDS based image to be used solely by the PDB life cycle multitentant controllers. **NOTE:** It is assumed that before this step, you have followed the [prerequisite](./../README.md#prerequsites-to-manage-pdb-life-cycle-using-oracle-db-operator-on-prem-database-controller) steps. -1. Clone the software using git: +#### Clone the software using git: + +> Under directory ./oracle-database-operator/ords you will find the [Dockerfile](../../../ords/Dockerfile) and [runOrdsSSL.sh](../../../ords/runOrdsSSL.sh) required to build the image. + ```sh git clone git@orahub.oci.oraclecorp.com:rac-docker-dev/oracle-database-operator.git cd oracle-database-operator/ords/ ``` -2. Login to the registry: container-registry.oracle.com +#### Login to the registry: container-registry.oracle.com **NOTE:** To login to this registry, you will need to the URL https://container-registry.oracle.com , Sign in, then click on "Java" and then accept the agreement. ```bash docker login container-registry.oracle.com -``` +``` -3. Login to a repo where you want to push your docker image (if needed) to pull during deployment in your environment. +#### Login to the your container registry + +Login to a repo where you want to push your docker image (if needed) to pull during deployment in your environment. ```bash docker login ``` -4. Build the docker image by using below command: +#### Build the image + +Build the docker image by using below command: ```bash -docker build -t oracle/ords-dboper:ords-latest . +docker build -t oracle/ords-dboper:latest . ``` +> If your are working behind a proxy mind to specify https_proxy and http_proxy during image creation -5. Check the docker image details using: +Check the docker image details using: ```bash docker images ``` -6. Tag and push the image to your docker repository. +> OUTPUT EXAMPLE +```bash +REPOSITORY TAG IMAGE ID CREATED SIZE +oracle/ords-dboper latest fdb17aa242f8 4 hours ago 1.46GB + +``` + +#### Tag and push the image + +Tag and push the image to your image repository. NOTE: We have the repo as `phx.ocir.io//oracle/ords:latest`. Please change as per your environment. @@ -47,18 +64,18 @@ docker tag oracle/ords-dboper:ords-latest phx.ocir.io//oracle/ords:la docker push phx.ocir.io//oracle/ords:latest ``` -7. Verify the image pushed to your docker repository. - -You can refer to below sample output for above steps as well. +#### In case of private image -8. Create a Kubernetes Secret for your docker repository to pull the image during deployment using the below command: +If you the image not be public then yuo need to create a secret containing the password of your image repository. +Create a Kubernetes Secret for your docker repository to pull the image during deployment using the below command: ```bash kubectl create secret generic container-registry-secret --from-file=.dockerconfigjson=./.docker/config.json --type=kubernetes.io/dockerconfigjson -n oracle-database-operator-system ``` -This Kubernetes secret will be provided in the .yaml file against the parameter `ordsImagePullSecret` to pull the ORDS Docker Image from your docker repository (if its a private repository). +Use the parameter `ordsImagePullSecret` to specify the container secrets in pod creation yaml file + +#### [Image createion example](../usecase01/logfiles/BuildImage.log) -## Sample Output -[Here](./ords_image.log) is the sample output for docker image created for ORDS latest version + diff --git a/docs/multitenant/provisioning/pdb_crd_resource.md b/docs/multitenant/provisioning/pdb_crd_resource.md deleted file mode 100644 index e69de29b..00000000 diff --git a/docs/multitenant/provisioning/plug_pdb.log b/docs/multitenant/provisioning/plug_pdb.log deleted file mode 100644 index 3a0be247..00000000 --- a/docs/multitenant/provisioning/plug_pdb.log +++ /dev/null @@ -1,100 +0,0 @@ --- Check the status of the PDB CRD Resources: - -% kubectl get pdbs -A -No resources found - - - --- Verify from the CDB: - -SQL> show pdbs - - CON_ID CON_NAME OPEN MODE RESTRICTED ----------- ------------------------------ ---------- ---------- - 2 PDB$SEED READ WRITE NO - - - --- Confirm the availability of the required .xml file: - -[oracle@goldhost1 ~]$ ls -lrt /tmp/pdbnewclone.xml --rw-r--r-- 1 oracle asmadmin 9920 Jun 27 06:26 /tmp/pdbnewclone.xml - - --- Use the below .yaml file for the plug in operation: - -% cat plug_pdb.yaml -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: PDB -metadata: - name: pdb1 - namespace: oracle-database-operator-system - labels: - cdb: cdb-dev -spec: - cdbResName: "cdb-dev" - cdbName: "goldcdb" - pdbName: "pdbnew" - xmlFileName: "/tmp/pdbnewclone.xml" - fileNameConversions: "NONE" - sourceFileNameConversions: "NONE" - copyAction: "MOVE" - totalSize: "1G" - tempSize: "100M" - action: "Plug" - - - --- Apply the .yaml file: - -% kubectl apply -f plug_pdb.yaml -pdb.database.oracle.com/pdb1 created - - --- Monitor the logs from the Oracle DB Operator Pod: - -% kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -. -. -2022-06-27T04:28:36Z DEBUG controller-runtime.webhook.webhooks received request {"webhook": "/validate-database-oracle-com-v1alpha1-pdb", "UID": "bfad69af-36be-4792-87e3-639323300167", "kind": "database.oracle.com/v1alpha1, Kind=PDB", "resource": {"group":"database.oracle.com","version":"v1alpha1","resource":"pdbs"}} -2022-06-27T04:28:36Z INFO pdb-webhook ValidateCreate-Validating PDB spec for : pdb1 -2022-06-27T04:28:36Z INFO pdb-webhook validateCommon {"name": "pdb1"} -2022-06-27T04:28:36Z INFO pdb-webhook Valdiating PDB Resource Action : PLUG -2022-06-27T04:28:36Z INFO pdb-webhook PDB Resource : pdb1 successfully validated for Action : PLUG -2022-06-27T04:28:36Z DEBUG controller-runtime.webhook.webhooks wrote response {"webhook": "/validate-database-oracle-com-v1alpha1-pdb", "code": 200, "reason": "", "UID": "bfad69af-36be-4792-87e3-639323300167", "allowed": true} -2022-06-27T04:28:36Z INFO controllers.PDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/pdb1"} -2022-06-27T04:28:36Z INFO controllers.PDB Adding finalizer {"managePDBDeletion": "oracle-database-operator-system/pdb1"} -2022-06-27T04:28:36Z INFO controllers.PDB Found PDB: pdb1 {"checkDuplicatePDB": "oracle-database-operator-system/pdb1"} -2022-06-27T04:28:36Z INFO controllers.PDB Validating PDB phase for: pdb1 {"validatePhase": "oracle-database-operator-system/pdb1", "Action": "PLUG"} -2022-06-27T04:28:36Z INFO controllers.PDB Validation complete {"validatePhase": "oracle-database-operator-system/pdb1"} -2022-06-27T04:28:36Z INFO controllers.PDB PDB: {"onpremdboperator": "oracle-database-operator-system/pdb1", "Name": "pdb1", "Phase": "Plugging", "Status": "false"} -2022-06-27T04:28:36Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:28:36Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/", "Action": "POST"} -2022-06-27T04:28:36Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:29:07Z INFO controllers.PDB Successfully plugged PDB {"plugPDB": "oracle-database-operator-system/pdb1", "PDB Name": "pdbnew"} -2022-06-27T04:29:07Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:29:07Z DEBUG events Normal {"object": {"kind":"PDB","namespace":"oracle-database-operator-system","name":"pdb1","uid":"dd9bef3c-e493-4d5a-ae82-b24cbf5d0be3","apiVersion":"database.oracle.com/v1alpha1","resourceVersion":"101465242"}, "reason": "Created", "message": "PDB 'pdbnew' plugged successfully"} -2022-06-27T04:29:07Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/pdbnew/status", "Action": "GET"} -2022-06-27T04:29:07Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:29:07Z INFO controllers.PDB Successfully obtained PDB state {"getPDBState": "oracle-database-operator-system/pdb1", "PDB Name": "pdbnew", "State": "READ WRITE"} -2022-06-27T04:29:07Z INFO controllers.PDB Reconcile completed {"onpremdboperator": "oracle-database-operator-system/pdb1"} - - - --- Confirm the PDB CRD resource has been created and the PDB has been plugged in to the target CDB: - -% kubectl get pdbs -A -NAMESPACE NAME CONNECT STRING CDB NAME PDB NAME PDB STATE PDB SIZE STATUS MESSAGE -oracle-database-operator-system pdb1 goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com:1521/pdbnew goldcdb pdbnew READ WRITE 1G Ready Success - - -SQL> show pdbs - - CON_ID CON_NAME OPEN MODE RESTRICTED ----------- ------------------------------ ---------- ---------- - 2 PDB$SEED READ WRITE NO - 4 PDBNEW READ WRITE NO diff --git a/docs/multitenant/provisioning/plug_pdb.md b/docs/multitenant/provisioning/plug_pdb.md deleted file mode 100644 index 02645f52..00000000 --- a/docs/multitenant/provisioning/plug_pdb.md +++ /dev/null @@ -1,44 +0,0 @@ -# Plug in a PDB using Oracle DB Operator On-Prem Controller in a target CDB - -In this use case, a PDB is plugged in using Oracle DB Operator On-Prem controller using an existing .xml file which was generated when the PDB was unplugged from this target CDB or another CDB. - -To plug in a PDB CRD Resource, a sample .yaml file is available here: [config/samples/onpremdb/pdb_plug.yaml](../../../config/samples/onpremdb/pdb_plug.yaml) - -**NOTE:** It is assumed that before this step, you have followed the [prerequisite](./../README.md#prerequsites-to-manage-pdb-life-cycle-using-oracle-db-operator-on-prem-database-controller) steps. - -This example uses `plug_pdb.yaml` to plug in a PDB to a target CDB using Oracle DB Operator On-Prem Controller with: - -- Pluggable Database CRD Resource Name as `pdb1` -- Pluggable Database (PDB) Name as `pdbnew` -- Target CDB CRD Resource Name as `cdb-dev` -- CDB Name as `goldcdb` -- Action to be taken on the PDB as `Plug` -- XML metadata filename as `/tmp/pdbnewclone.xml` -- Source File Name Conversion as `NONE` -- File Name Conversion as `NONE` -- Copy Action as `MOVE` -- PDB Size as `1G` -- Temporary tablespace Size as `100M` - -**NOTE:** For the details of the parameters to be used in the .yaml file, please refer [config/crd/bases/database.oracle.com_pdbs.yaml](../../../config/crd/bases/database.oracle.com_pdbs.yaml) - -**NOTE:** Before performing the plug inoperation, you will first need to confirm the availability of the .xml file and the PDB datafiles. - -Use the file: [plug_pdb.yaml](./plug_pdb.yaml) for this use case as below: - -1. Deploy the .yaml file: -```sh -% kubectl apply -f plug_pdb.yaml -``` - -2. Monitor the Oracle DB Operator Pod for the progress of the PDB Unplug operation: - -NOTE: Check the DB Operator Pod name in your environment. - -```sh -% kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -``` - -## Sample Output - -[Here](./plug_pdb.log) is the sample output for a PDB created using Oracle DB Operator On-Prem Controller using file [plug_pdb.yaml](./plug_pdb.yaml) diff --git a/docs/multitenant/provisioning/plug_pdb.yaml b/docs/multitenant/provisioning/plug_pdb.yaml deleted file mode 100644 index a27d3255..00000000 --- a/docs/multitenant/provisioning/plug_pdb.yaml +++ /dev/null @@ -1,22 +0,0 @@ -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: PDB -metadata: - name: pdb1 - namespace: oracle-database-operator-system - labels: - cdb: cdb-dev -spec: - cdbResName: "cdb-dev" - cdbName: "goldcdb" - pdbName: "pdbnew" - xmlFileName: "/tmp/pdbnewclone.xml" - fileNameConversions: "NONE" - sourceFileNameConversions: "NONE" - copyAction: "MOVE" - totalSize: "1G" - tempSize: "100M" - action: "Plug" diff --git a/docs/multitenant/provisioning/quickOKEcreation.md b/docs/multitenant/provisioning/quickOKEcreation.md new file mode 100644 index 00000000..19d9323e --- /dev/null +++ b/docs/multitenant/provisioning/quickOKEcreation.md @@ -0,0 +1,136 @@ + + +### Quick Oke creation script + +Use this script to create quickly an OKE cluster in your OCI. + +#### Prerequisties: +- ocicli is properly configured on your client +- make is installed on your client +- vnc is already configured +- ssh key is configured (public key available under directory ~/.ssh) +- edit make providing all the information about your compartment, vnc,subnet,lb subnet and nd subnet (exported variables in the header section) + + +#### Execution: + +```bash +make all +``` + +Monitor the OKE from OCI console + +#### Makefile +```makefile +.EXPORT_ALL_VARIABLES: + +export CMPID=[.... COMPARTMENT ID.............] +export VNCID=[.... VNC ID ....................] +export ENDID=[.... SUBNET END POINT ID .......] +export LBSID=[.....LB SUBNET ID...............] +export NDSID=[.....NODE SUBNET ID.............] + + +#ssh public key +export KEYFL=~/.ssh/id_rsa.pub + +#cluster version +export KSVER=v1.27.2 + +#cluster name +export CLUNM=myoke + +#pool name +export PLNAM=Pool1 + +#logfile +export LOGFILE=./clustoke.log + +#shape +export SHAPE=VM.Standard.E4.Flex + +OCI=/home/oracle/bin/oci +CUT=/usr/bin/cut +KUBECTL=/usr/bin/kubectl +CAT=/usr/bin/cat + +all: cluster waitcluster pool waitpool config desccluster + +cluster: + @echo " - CREATING CLUSTER " + @$(OCI) ce cluster create \ + --compartment-id $(CMPID) \ + --kubernetes-version $(KSVER) \ + --name $(CLUNM) \ + --vcn-id $(VNCID) \ + --endpoint-subnet-id $(ENDID) \ + --service-lb-subnet-ids '["'$(LBSID)'"]' \ + --endpoint-public-ip-enabled true \ + --persistent-volume-freeform-tags '{"$(CLUNM)" : "OKE"}' 1>$(LOGFILE) 2>&1 + +waitcluster: + @while [ `$(OCI) ce cluster list --compartment-id $(CMPID) \ + --name $(CLUNM) --lifecycle-state ACTIVE --query data[0].id \ + --raw-output |wc -l ` -eq 0 ] ; do sleep 5 ; done + @echo " - CLUSTER CREATED" + + +pool: + @echo " - CREATING POOL" + @$(eval PBKEY :=$(shell $(CAT) $(KEYFL)|grep -v " PUBLIC KEY")) + @$(OCI) ce node-pool create \ + --cluster-id `$(OCI) ce cluster list --compartment-id $(CMPID) \ + --name $(CLUNM) --lifecycle-state ACTIVE --query data[0].id --raw-output` \ + --compartment-id $(CMPID) \ + --kubernetes-version $(KSVER) \ + --name $(PLNAM) \ + --node-shape $(SHAPE) \ + --node-shape-config '{"memoryInGBs": 8.0, "ocpus": 1.0}' \ + --node-image-id `$(OCI) compute image list \ + --operating-system 'Oracle Linux' --operating-system-version 7.9 \ + --sort-by TIMECREATED --compartment-id $(CMPID) --shape $(SHAPE) \ + --query data[1].id --raw-output` \ + --node-boot-volume-size-in-gbs 50 \ + --ssh-public-key "$(PBKEY)" \ + --size 3 \ + --placement-configs '[{"availabilityDomain": "'`oci iam availability-domain list \ + --compartment-id $(CMPID) \ + --query data[0].name --raw-output`'", "subnetId": "'$(NDSID)'"}]' 1>>$(LOGFILE) 2>&1 + +waitpool: + $(eval CLSID :=$(shell $(OCI) ce cluster list --compartment-id $(CMPID) \ + --name $(CLUNM) --lifecycle-state ACTIVE --query data[0].id --raw-output)) + @while [ `$(OCI) ce node-pool list --compartment-id $(CMPID) \ + --lifecycle-state ACTIVE --cluster-id $(CLSID) \ + --query data[0].id --raw-output |wc -l ` -eq 0 ] ; do sleep 5 ; done + @sleep 10 + $(eval PLLID :=$(shell $(OCI) ce node-pool list --compartment-id $(CMPID) \ + --lifecycle-state ACTIVE --cluster-id $(CLSID) --query data[0].id --raw-output)) + @echo " - POOL CREATED" + +config: + @$(OCI) ce cluster create-kubeconfig --cluster-id \ + `$(OCI) ce cluster list \ + --compartment-id $(CMPID) --name $(CLUNM) --lifecycle-state ACTIVE \ + --query data[0].id --raw-output` \ + --file $(HOME)/.kube/config --region \ + `$(OCI) ce cluster list \ + --compartment-id $(CMPID) --name $(CLUNM) --lifecycle-state ACTIVE \ + --query data[0].id --raw-output|$(CUT) -f4 -d. ` \ + --token-version 2.0.0 --kube-endpoint PUBLIC_ENDPOINT + @echo " - KUBECTL PUBLIC ENDPOINT CONFIGURED" + + +desccluster: + @$(eval TMPSP := $(shell date "+%y/%m/%d:%H:%M" )) + $(KUBECTL) get nodes -o wide + $(KUBECTL) get storageclass + +checkvol: + $(OCI) bv volume list \ + --compartment-id $(CMPID) \ + --lifecycle-state AVAILABLE \ + --query 'data[?"freeform-tags".stackgres == '\''OKE'\''].id' +``` + + diff --git a/docs/multitenant/provisioning/singlenamespace/cdb_create.yaml b/docs/multitenant/provisioning/singlenamespace/cdb_create.yaml new file mode 100644 index 00000000..01fc0a18 --- /dev/null +++ b/docs/multitenant/provisioning/singlenamespace/cdb_create.yaml @@ -0,0 +1,44 @@ +apiVersion: database.oracle.com/v1alpha1 +kind: CDB +metadata: + name: cdb-dev + namespace: oracle-database-operator-system +spec: + cdbName: "DB12" + ordsImage: ".............your registry............./ords-dboper:latest" + ordsImagePullPolicy: "Always" + dbTnsurl : "...Container tns alias....." + replicas: 1 + sysAdminPwd: + secret: + secretName: "cdb1-secret" + key: "sysadmin_pwd" + ordsPwd: + secret: + secretName: "cdb1-secret" + key: "ords_pwd" + cdbAdminUser: + secret: + secretName: "cdb1-secret" + key: "cdbadmin_user" + cdbAdminPwd: + secret: + secretName: "cdb1-secret" + key: "cdbadmin_pwd" + webServerUser: + secret: + secretName: "cdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "cdb1-secret" + key: "webserver_pwd" + cdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + cdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + diff --git a/docs/multitenant/provisioning/singlenamespace/cdb_secret.yaml b/docs/multitenant/provisioning/singlenamespace/cdb_secret.yaml new file mode 100644 index 00000000..567b90a4 --- /dev/null +++ b/docs/multitenant/provisioning/singlenamespace/cdb_secret.yaml @@ -0,0 +1,17 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +apiVersion: v1 +kind: Secret +metadata: + name: cdb1-secret + namespace: oracle-database-operator-system +type: Opaque +data: + ords_pwd: ".....base64 encoded password...." + sysadmin_pwd: ".....base64 encoded password...." + cdbadmin_user: ".....base64 encoded password...." + cdbadmin_pwd: ".....base64 encoded password...." + webserver_user: ".....base64 encoded password...." + webserver_pwd: ".....base64 encoded password...." diff --git a/docs/multitenant/provisioning/singlenamespace/pdb_clone.yaml b/docs/multitenant/provisioning/singlenamespace/pdb_clone.yaml new file mode 100644 index 00000000..0ecc3c70 --- /dev/null +++ b/docs/multitenant/provisioning/singlenamespace/pdb_clone.yaml @@ -0,0 +1,50 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +apiVersion: database.oracle.com/v1alpha1 +kind: PDB +metadata: + name: pdb2 + namespace: oracle-database-operator-system + labels: + cdb: cdb-dev +spec: + cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" + cdbName: "DB12" + pdbName: "pdb2_clone" + srcPdbName: "pdbdev" + fileNameConversions: "NONE" + totalSize: "UNLIMITED" + tempSize: "UNLIMITED" + assertivePdbDeletion: true + adminName: + secret: + secretName: "pdb1-secret" + key: "sysadmin_user" + adminPwd: + secret: + secretName: "pdb1-secret" + key: "sysadmin_pwd" + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + action: "Clone" diff --git a/docs/multitenant/provisioning/singlenamespace/pdb_close.yaml b/docs/multitenant/provisioning/singlenamespace/pdb_close.yaml new file mode 100644 index 00000000..5917d33a --- /dev/null +++ b/docs/multitenant/provisioning/singlenamespace/pdb_close.yaml @@ -0,0 +1,44 @@ +apiVersion: database.oracle.com/v1alpha1 +kind: PDB +metadata: + name: pdb1 + namespace: oracle-database-operator-system + labels: + cdb: cdb-dev +spec: + cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" + cdbName: "DB12" + pdbName: "pdbdev" + adminName: + secret: + secretName: "pdb1-secret" + key: "sysadmin_user" + adminPwd: + secret: + secretName: "pdb1-secret" + key: "sysadmin_pwd" + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + pdbState: "CLOSE" + modifyOption: "IMMEDIATE" + action: "Modify" + diff --git a/docs/multitenant/provisioning/singlenamespace/pdb_create.yaml b/docs/multitenant/provisioning/singlenamespace/pdb_create.yaml new file mode 100644 index 00000000..be3581ad --- /dev/null +++ b/docs/multitenant/provisioning/singlenamespace/pdb_create.yaml @@ -0,0 +1,47 @@ +apiVersion: database.oracle.com/v1alpha1 +kind: PDB +metadata: + name: pdb1 + namespace: oracle-database-operator-system + labels: + cdb: cdb-dev +spec: + cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" + cdbName: "DB12" + pdbName: "pdbdev" + adminName: + secret: + secretName: "pdb1-secret" + key: "sysadmin_user" + adminPwd: + secret: + secretName: "pdb1-secret" + key: "sysadmin_pwd" + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + fileNameConversions: "NONE" + tdeImport: false + totalSize: "1G" + tempSize: "100M" + action: "Create" + assertivePdbDeletion: true + diff --git a/docs/multitenant/provisioning/singlenamespace/pdb_delete.yaml b/docs/multitenant/provisioning/singlenamespace/pdb_delete.yaml new file mode 100644 index 00000000..c22b546a --- /dev/null +++ b/docs/multitenant/provisioning/singlenamespace/pdb_delete.yaml @@ -0,0 +1,34 @@ +apiVersion: database.oracle.com/v1alpha1 +kind: PDB +metadata: + name: pdb1 + namespace: oracle-database-operator-system + labels: + cdb: cdb-dev +spec: + cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" + pdbName: "pdbdev" + action: "Delete" + dropAction: "INCLUDING" + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + diff --git a/docs/multitenant/provisioning/singlenamespace/pdb_open.yaml b/docs/multitenant/provisioning/singlenamespace/pdb_open.yaml new file mode 100644 index 00000000..25fdccc4 --- /dev/null +++ b/docs/multitenant/provisioning/singlenamespace/pdb_open.yaml @@ -0,0 +1,43 @@ +apiVersion: database.oracle.com/v1alpha1 +kind: PDB +metadata: + name: pdb1 + namespace: oracle-database-operator-system + labels: + cdb: cdb-dev +spec: + cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" + cdbName: "DB12" + pdbName: "pdbdev" + adminName: + secret: + secretName: "pdb1-secret" + key: "sysadmin_user" + adminPwd: + secret: + secretName: "pdb1-secret" + key: "sysadmin_pwd" + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + action: "Modify" + pdbState: "OPEN" + modifyOption: "READ WRITE" diff --git a/docs/multitenant/provisioning/singlenamespace/pdb_plug.yaml b/docs/multitenant/provisioning/singlenamespace/pdb_plug.yaml new file mode 100644 index 00000000..77c00b9c --- /dev/null +++ b/docs/multitenant/provisioning/singlenamespace/pdb_plug.yaml @@ -0,0 +1,46 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +apiVersion: database.oracle.com/v1alpha1 +kind: PDB +metadata: + name: pdb1 + namespace: oracle-database-operator-system + labels: + cdb: cdb-dev +spec: + cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" + cdbName: "DB12" + pdbName: "pdbdev" + xmlFileName: "/tmp/pdb.xml" + fileNameConversions: "NONE" + sourceFileNameConversions: "NONE" + copyAction: "MOVE" + totalSize: "1G" + tempSize: "100M" + action: "Plug" + assertivePdbDeletion: true + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + + diff --git a/docs/multitenant/provisioning/singlenamespace/pdb_secret.yaml b/docs/multitenant/provisioning/singlenamespace/pdb_secret.yaml new file mode 100644 index 00000000..60d95d76 --- /dev/null +++ b/docs/multitenant/provisioning/singlenamespace/pdb_secret.yaml @@ -0,0 +1,16 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +apiVersion: v1 +kind: Secret +metadata: + name: pdb1-secret + namespace: oracle-database-operator-system +type: Opaque +data: + sysadmin_user: ".....base64 encoded password...." + sysadmin_pwd: ".....base64 encoded password...." + webserver_user: ".....base64 encoded password...." + webserver_pwd: ".....base64 encoded password...." + diff --git a/docs/multitenant/provisioning/pdb.yaml b/docs/multitenant/provisioning/singlenamespace/pdb_unplug.yaml similarity index 50% rename from docs/multitenant/provisioning/pdb.yaml rename to docs/multitenant/provisioning/singlenamespace/pdb_unplug.yaml index 82941185..085d337e 100644 --- a/docs/multitenant/provisioning/pdb.yaml +++ b/docs/multitenant/provisioning/singlenamespace/pdb_unplug.yaml @@ -11,17 +11,29 @@ metadata: cdb: cdb-dev spec: cdbResName: "cdb-dev" - cdbName: "goldcdb" - pdbName: "pdbnew" - adminName: + cdbNamespace: "oracle-database-operator-system" + cdbName: "DB12" + pdbName: "pdbdev" + xmlFileName: "/tmp/pdb.xml" + action: "Unplug" + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: secret: secretName: "pdb1-secret" - key: "sysadmin_user" - adminPwd: + key: "webserver_user" + webServerPwd: secret: secretName: "pdb1-secret" - key: "sysadmin_pwd" - fileNameConversions: "NONE" - totalSize: "1G" - tempSize: "100M" - action: "Create" + key: "webserver_pwd" + diff --git a/docs/multitenant/provisioning/unplug_pdb.log b/docs/multitenant/provisioning/unplug_pdb.log deleted file mode 100644 index c0995f83..00000000 --- a/docs/multitenant/provisioning/unplug_pdb.log +++ /dev/null @@ -1,165 +0,0 @@ --- Check the status of the PDB CRD resource: - -% kubectl get pdbs -A -NAMESPACE NAME CONNECT STRING CDB NAME PDB NAME PDB STATE PDB SIZE STATUS MESSAGE -oracle-database-operator-system pdb1 goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com:1521/pdbnew goldcdb pdbnew READ WRITE 1G Ready Success - - --- Verify the status from the CDB: - -SQL> show pdbs - - CON_ID CON_NAME OPEN MODE RESTRICTED ----------- ------------------------------ ---------- ---------- - 2 PDB$SEED READ WRITE NO - 3 PDBNEW READ WRITE NO - - --- Use the below .yaml file to close the PDB: - -% cat modify_pdb_close.yaml -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: PDB -metadata: - name: pdb1 - namespace: oracle-database-operator-system - labels: - cdb: cdb-dev -spec: - cdbResName: "cdb-dev" - cdbName: "goldcdb" - pdbName: "pdbnew" - pdbState: "CLOSE" - modifyOption: "IMMEDIATE" - action: "Modify" - - --- Apply the .yaml file: - -% kubectl apply -f modify_pdb_close.yaml -pdb.database.oracle.com/pdb1 configured - - --- Monitor the Oracle DB Operator Pod logs: - -% kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -. -. -2022-06-27T04:25:00Z DEBUG controller-runtime.webhook.webhooks received request {"webhook": "/mutate-database-oracle-com-v1alpha1-pdb", "UID": "1623a6e2-d7dc-4b0f-8aa8-efada76cac13", "kind": "database.oracle.com/v1alpha1, Kind=PDB", "resource": {"group":"database.oracle.com","version":"v1alpha1","resource":"pdbs"}} -2022-06-27T04:25:00Z INFO pdb-webhook Setting default values in PDB spec for : pdb1 -2022-06-27T04:25:00Z DEBUG controller-runtime.webhook.webhooks wrote response {"webhook": "/mutate-database-oracle-com-v1alpha1-pdb", "code": 200, "reason": "", "UID": "1623a6e2-d7dc-4b0f-8aa8-efada76cac13", "allowed": true} -2022-06-27T04:25:00Z INFO controllers.PDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/pdb1"} -2022-06-27T04:25:00Z INFO controllers.PDB Validating PDB phase for: pdb1 {"validatePhase": "oracle-database-operator-system/pdb1", "Action": "MODIFY"} -2022-06-27T04:25:00Z INFO controllers.PDB Validation complete {"validatePhase": "oracle-database-operator-system/pdb1"} -2022-06-27T04:25:00Z INFO controllers.PDB PDB: {"onpremdboperator": "oracle-database-operator-system/pdb1", "Name": "pdb1", "Phase": "Modifying", "Status": "false"} -2022-06-27T04:25:00Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:25:00Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/pdbnew/status", "Action": "GET"} -2022-06-27T04:25:00Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:25:00Z INFO controllers.PDB Successfully obtained PDB state {"getPDBState": "oracle-database-operator-system/pdb1", "PDB Name": "pdbnew", "State": "READ WRITE"} -2022-06-27T04:25:00Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:25:01Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/pdbnew/status", "Action": "POST"} -2022-06-27T04:25:01Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:25:02Z INFO controllers.PDB Successfully modified PDB state {"modifyPDB": "oracle-database-operator-system/pdb1", "PDB Name": "pdbnew"} -2022-06-27T04:25:02Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:25:02Z DEBUG events Normal {"object": {"kind":"PDB","namespace":"oracle-database-operator-system","name":"pdb1","uid":"447346c7-cfb0-43ed-abb2-a0fac844a3e4","apiVersion":"database.oracle.com/v1alpha1","resourceVersion":"101464133"}, "reason": "Modified", "message": "PDB 'pdbnew' modified successfully"} -2022-06-27T04:25:02Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/pdbnew/status", "Action": "GET"} -2022-06-27T04:25:02Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:25:02Z INFO controllers.PDB Successfully obtained PDB state {"getPDBState": "oracle-database-operator-system/pdb1", "PDB Name": "pdbnew", "State": "MOUNTED"} -2022-06-27T04:25:02Z INFO controllers.PDB Reconcile completed {"onpremdboperator": "oracle-database-operator-system/pdb1"} - - - --- Confirm the PDB is now in MOUNT status: - -% kubectl get pdbs -A -NAMESPACE NAME CONNECT STRING CDB NAME PDB NAME PDB STATE PDB SIZE STATUS MESSAGE -oracle-database-operator-system pdb1 goldhost-scan.lbsub52b3b1cae.okecluster.oraclevcn.com:1521/pdbnew goldcdb pdbnew MOUNTED 1G Ready Success - - -SQL> show pdbs - - CON_ID CON_NAME OPEN MODE RESTRICTED ----------- ------------------------------ ---------- ---------- - 2 PDB$SEED READ WRITE NO - 3 PDBNEW MOUNTED - - - - --- Use the below .yaml file to unplug the PDB: - -% cat unplug_pdb.yaml -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: PDB -metadata: - name: pdb1 - namespace: oracle-database-operator-system - labels: - cdb: cdb-dev -spec: - cdbResName: "cdb-dev" - cdbName: "goldcdb" - pdbName: "pdbnew" - xmlFileName: "/tmp/pdbnewclone.xml" - action: "Unplug" - - --- Apply the .yaml file: - -% kubectl apply -f unplug_pdb.yaml -pdb.database.oracle.com/pdb1 configured - - --- Monitor the Oracle DB Operator Pod logs: - -% kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -. -. -2022-06-27T04:26:10Z DEBUG controller-runtime.webhook.webhooks received request {"webhook": "/mutate-database-oracle-com-v1alpha1-pdb", "UID": "0f292426-8839-46b6-ba30-b3ffeee7e644", "kind": "database.oracle.com/v1alpha1, Kind=PDB", "resource": {"group":"database.oracle.com","version":"v1alpha1","resource":"pdbs"}} -2022-06-27T04:26:10Z INFO pdb-webhook Setting default values in PDB spec for : pdb1 -2022-06-27T04:26:10Z DEBUG controller-runtime.webhook.webhooks wrote response {"webhook": "/mutate-database-oracle-com-v1alpha1-pdb", "code": 200, "reason": "", "UID": "0f292426-8839-46b6-ba30-b3ffeee7e644", "allowed": true} -2022-06-27T04:26:10Z INFO controllers.PDB Reconcile requested {"onpremdboperator": "oracle-database-operator-system/pdb1"} -2022-06-27T04:26:10Z INFO controllers.PDB Validating PDB phase for: pdb1 {"validatePhase": "oracle-database-operator-system/pdb1", "Action": "UNPLUG"} -2022-06-27T04:26:10Z INFO controllers.PDB Validation complete {"validatePhase": "oracle-database-operator-system/pdb1"} -2022-06-27T04:26:10Z INFO controllers.PDB PDB: {"onpremdboperator": "oracle-database-operator-system/pdb1", "Name": "pdb1", "Phase": "Unplugging", "Status": "false"} -2022-06-27T04:26:10Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:26:10Z INFO controllers.PDB Issuing REST call {"callAPI": "oracle-database-operator-system/pdb1", "URL": "http://cdb-dev-ords:8888/ords/_/db-api/latest/database/pdbs/pdbnew/", "Action": "POST"} -2022-06-27T04:26:10Z INFO controllers.PDB Found CR for CDB {"getCDBResource": "oracle-database-operator-system/pdb1", "Name": "cdb-dev", "CR Name": "cdb-dev"} -2022-06-27T04:26:18Z INFO controllers.PDB Removing finalizer {"unplugPDB": "oracle-database-operator-system/pdb1"} -2022-06-27T04:26:19Z DEBUG controller-runtime.webhook.webhooks received request {"webhook": "/validate-database-oracle-com-v1alpha1-pdb", "UID": "ce9e1a52-a372-4e3b-b148-c1e31bcb26f8", "kind": "database.oracle.com/v1alpha1, Kind=PDB", "resource": {"group":"database.oracle.com","version":"v1alpha1","resource":"pdbs"}} -2022-06-27T04:26:19Z INFO pdb-webhook ValidateUpdate-Validating PDB spec for : pdb1 -2022-06-27T04:26:19Z INFO pdb-webhook validateCommon {"name": "pdb1"} -2022-06-27T04:26:19Z INFO pdb-webhook Valdiating PDB Resource Action : UNPLUG -2022-06-27T04:26:19Z DEBUG controller-runtime.webhook.webhooks wrote response {"webhook": "/validate-database-oracle-com-v1alpha1-pdb", "code": 200, "reason": "", "UID": "ce9e1a52-a372-4e3b-b148-c1e31bcb26f8", "allowed": true} -2022-06-27T04:26:19Z INFO controllers.PDB Successfully unplugged PDB resource {"unplugPDB": "oracle-database-operator-system/pdb1"} -2022-06-27T04:26:19Z INFO controllers.PDB Reconcile completed {"onpremdboperator": "oracle-database-operator-system/pdb1"} -2022-06-27T04:26:19Z DEBUG events Normal {"object": {"kind":"PDB","namespace":"oracle-database-operator-system","name":"pdb1","uid":"447346c7-cfb0-43ed-abb2-a0fac844a3e4","apiVersion":"database.oracle.com/v1alpha1","resourceVersion":"101464533"}, "reason": "Unplugged", "message": "PDB 'pdbnew' unplugged successfully"} - - - --- Confirm the PDB has been unplugged: - -% kubectl get pdbs -A -No resources found - - -SQL> show pdbs - - CON_ID CON_NAME OPEN MODE RESTRICTED ----------- ------------------------------ ---------- ---------- - 2 PDB$SEED READ WRITE NO - - - --- Confirm the .xml file generated in the CDB host: - -[oracle@goldhost1 ~]$ ls -lrt /tmp/pdbnewclone.xml --rw-r--r-- 1 oracle asmadmin 9920 Jun 27 06:26 /tmp/pdbnewclone.xml diff --git a/docs/multitenant/provisioning/unplug_pdb.md b/docs/multitenant/provisioning/unplug_pdb.md deleted file mode 100644 index fb98fc8b..00000000 --- a/docs/multitenant/provisioning/unplug_pdb.md +++ /dev/null @@ -1,39 +0,0 @@ -# Unplug a PDB using Oracle DB Operator On-Prem Controller in a target CDB - -In this use case, a PDB is unplugged using Oracle DB Operator On-Prem controller. - -To unplug a PDB CRD Resource, a sample .yaml file is available here: [config/samples/onpremdb/pdb_unplug.yaml](../../../config/samples/onpremdb/pdb_unplug.yaml) - -**NOTE:** It is assumed that before this step, you have followed the [prerequisite](./../README.md#prerequsites-to-manage-pdb-life-cycle-using-oracle-db-operator-on-prem-database-controller) steps. - -This example uses `unplug_pdb.yaml` to unplug a PDB from a target CDB using Oracle DB Operator On-Prem Controller with: - -- Pluggable Database CRD Resource Name as `pdb1` -- Pluggable Database (PDB) Name as `pdbnew` -- Target CDB CRD Resource Name as `cdb-dev` -- CDB Name as `goldcdb` -- Action to be taken on the PDB as `Unplug` -- XML metadata filename as `/tmp/pdbnewclone.xml` - -**NOTE:** For the details of the parameters to be used in the .yaml file, please refer [config/crd/bases/database.oracle.com_pdbs.yaml](../../../config/crd/bases/database.oracle.com_pdbs.yaml) - -**NOTE:** Before performing the unplug operation on the PDB CRD Resource, you will first need to perform the Modify Operation on that PDB CRD resource to Close the the PDB. After that you will be able to perform the Unplug operation. Please refer to the use case to modify the PDB state to Close. - -Use the file: [unplug_pdb.yaml](./unplug_pdb.yaml) for this use case as below: - -1. Deploy the .yaml file: -```sh -% kubectl apply -f unplug_pdb.yaml -``` - -2. Monitor the Oracle DB Operator Pod for the progress of the PDB Unplug operation: - -NOTE: Check the DB Operator Pod name in your environment. - -```sh -% kubectl logs -f pod/oracle-database-operator-controller-manager-76cb674c5c-f9wsd -n oracle-database-operator-system -``` - -## Sample Output - -[Here](./unplug_pdb.log) is the sample output for a PDB created using Oracle DB Operator On-Prem Controller using file [unplug_pdb.yaml](./unplug_pdb.yaml) diff --git a/docs/multitenant/provisioning/unplug_pdb.yaml b/docs/multitenant/provisioning/unplug_pdb.yaml deleted file mode 100644 index c9915b28..00000000 --- a/docs/multitenant/provisioning/unplug_pdb.yaml +++ /dev/null @@ -1,17 +0,0 @@ -# -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: PDB -metadata: - name: pdb1 - namespace: oracle-database-operator-system - labels: - cdb: cdb-dev -spec: - cdbResName: "cdb-dev" - cdbName: "goldcdb" - pdbName: "pdbnew" - xmlFileName: "/tmp/pdbnewclone.xml" - action: "Unplug" diff --git a/docs/multitenant/provisioning/validation_error.md b/docs/multitenant/provisioning/validation_error.md deleted file mode 100644 index ec527cdb..00000000 --- a/docs/multitenant/provisioning/validation_error.md +++ /dev/null @@ -1,73 +0,0 @@ -#Validation and Errors - -## Kubernetes Events -You can check Kubernetes events for any errors or status updates as shown below: -```sh -$ kubectl get events -A -NAMESPACE LAST SEEN TYPE REASON OBJECT MESSAGE -oracle-database-operator-system 58m Warning Failed pod/cdb-dev-ords-qiigr Error: secret "cdb1-secret" not found -oracle-database-operator-system 56m Normal DeletedORDSPod cdb/cdb-dev Deleted ORDS Pod(s) for cdb-dev -oracle-database-operator-system 56m Normal DeletedORDSService cdb/cdb-dev Deleted ORDS Service for cdb-dev -... -oracle-database-operator-system 26m Warning OraError pdb/pdb1 ORA-65016: FILE_NAME_CONVERT must be specified... -oracle-database-operator-system 24m Warning OraError pdb/pdb2 ORA-65011: Pluggable database DEMOTEST does not exist. -... -oracle-database-operator-system 20m Normal Created pdb/pdb1 PDB 'demotest' created successfully -... -oracle-database-operator-system 17m Warning OraError pdb/pdb3 ORA-65012: Pluggable database DEMOTEST already exists... -``` - -In case of successfull operation, you can see messages like below: - -```sh -% kubectl get events -A -NAMESPACE LAST SEEN TYPE REASON OBJECT MESSAGE -kube-system 33s Warning BackOff pod/kube-apiserver Back-off restarting failed container -oracle-database-operator-system 59m Normal CreatedORDSService cdb/cdb-dev Created ORDS Service for cdb-dev -oracle-database-operator-system 51m Normal Created pdb/pdb1-clone PDB 'pdbnewclone' cloned successfully -oracle-database-operator-system 49m Normal Modified pdb/pdb1-clone PDB 'pdbnewclone' modified successfully -oracle-database-operator-system 47m Normal Deleted pdb/pdb1-clone PDB 'pdbnewclone' dropped successfully -oracle-database-operator-system 53m Normal Created pdb/pdb1 PDB 'pdbnew' created successfully -oracle-database-operator-system 44m Normal Modified pdb/pdb1 PDB 'pdbnew' modified successfully -oracle-database-operator-system 42m Normal Unplugged pdb/pdb1 PDB 'pdbnew' unplugged successfully -oracle-database-operator-system 39m Normal Created pdb/pdb1 PDB 'pdbnew' plugged successfully -``` - -## CDB Validation and Errors - -Validation is done at the time of CDB resource creation as shown below: -```sh -$ kubectl apply -f cdb1.yaml -The PDB "cdb-dev" is invalid: -* spec.dbServer: Required value: Please specify Database Server Name or IP Address -* spec.dbPort: Required value: Please specify DB Server Port -* spec.ordsImage: Required value: Please specify name of ORDS Image to be used -``` - -Apart from events, listing of CDBs will also show the possible reasons why a particular CDB CR could not be created as shown below: -```sh - $ kubectl get cdbs -A - - NAMESPACE NAME CDB NAME DB SERVER DB PORT SCAN NAME STATUS MESSAGE - oracle-database-operator-system cdb-dev devdb 172.17.0.4 1521 devdb Failed Secret not found:cdb1-secret -``` - -## PDB Validation and Errors - -Validation is done at the time of PDB resource creation as shown below: -```sh -$ kubectl apply -f pdb1.yaml -The PDB "pdb1" is invalid: -* spec.cdbResName: Required value: Please specify the name of the CDB Kubernetes resource to use for PDB operations -* spec.pdbName: Required value: Please specify name of the PDB to be created -* spec.adminPwd: Required value: Please specify PDB System Administrator Password -* spec.fileNameConversions: Required value: Please specify a value for fileNameConversions. Values can be a filename convert pattern or NONE -``` - -Similarly, for PDBs, listing of PDBs will also show the possible reasons why a particular PDB CR could not be created as shown below: -```sh -$ kubectl get pdbs -A -NAMESPACE NAME CONNECT STRING CDB NAME PDB NAME PDB SIZE STATUS MESSAGE -oracle-database-operator-system pdb1 democdb demotest1 Failed Secret not found:pdb12-secret -oracle-database-operator-system pdb2 democdb demotest2 Failed ORA-65016: FILE_NAME_CONVERT must be specified... -``` diff --git a/docs/multitenant/usecase01/README.md b/docs/multitenant/usecase01/README.md index 490c4607..7352257e 100644 --- a/docs/multitenant/usecase01/README.md +++ b/docs/multitenant/usecase01/README.md @@ -3,20 +3,23 @@ # STEP BY STEP USE CASE -- [INTRODUCTION](#introduction) -- [OPERATION STEPS ](#operation-steps) -- [Download latest version from github ](#download-latest-version-from-orahub-a-namedownloada) -- [Upload webhook certificates](#upload-webhook-certificates-a-namewebhooka) -- [Create the dboperator](#create-the-dboperator-a-namedboperatora) -- [Create Secret for container registry](#create-secret-for-container-registry) -- [Build ords immage ](#build-ords-immage-a-nameordsimagea) -- [Database Configuration](#database-configuration) -- [Create CDB secret ](#create-cdb-secret) -- [Create Certificates](#create-certificates) -- [Apply cdb.yaml](#apply-cdbyaml) -- [Logs and throuble shutting](#cdb---logs-and-throuble-shutting) -- [Create PDB secret](#create-pdb-secret) -- [Other action ](#other-actions) +- [STEP BY STEP USE CASE](#step-by-step-use-case) + - [INTRODUCTION](#introduction) + - [OPERATIONAL STEPS](#operational-steps) + - [Download latest version from github ](#download-latest-version-from-github-) + - [Upload webhook certificates ](#upload-webhook-certificates-) + - [Create the dboperator ](#create-the-dboperator-) + - [Create secret for container registry](#create-secret-for-container-registry) + - [Build ords immage ](#build-ords-immage-) + - [Database Configuration](#database-configuration) + - [Create CDB secret](#create-cdb-secret) + - [Create Certificates](#create-certificates) + - [Apply cdb.yaml](#apply-cdbyaml) + - [CDB - Logs and throuble shutting](#cdb---logs-and-throuble-shutting) + - [Create PDB secret](#create-pdb-secret) + - [Apply pdb yaml file to create pdb](#apply-pdb-yaml-file-to-create-pdb) + - [Other actions](#other-actions) + - [Imperative approach on pdb deletion - will be avilable in 1.2.0 ](#imperative-approach-on-pdb-deletion) @@ -47,6 +50,7 @@ The following table reports the parameters required to configure and use oracle | pdbTlsKey | | [standalone.https.cert.key][key] | | pdbTlsCrt | | [standalone.https.cert][cr] | | pdbTlsCat | | certificate authority | +| assertivePdbDeletion | boolean | [turn on imperative approach on crd deleteion][imperative] | > A [makfile](./makefile) is available to sped up the command execution for the multitenant setup and test. See the comments in the header of file @@ -78,6 +82,7 @@ make operator-yaml IMG=operator:latest > **NOTE:** If you are using oracle-container-registry make sure to accept the license agreement otherwise the operator image pull fails. ---- + #### Upload webhook certificates ```bash @@ -101,6 +106,7 @@ oracle-database-operator-controller-manager-557ff6c659-xpswv 1/1 Running ``` ---- + #### Create secret for container registry + Make sure to login to your container registry and then create the secret for you container registry. @@ -119,6 +125,7 @@ container-registry-secret kubernetes.io/dockerconfigjson 1 19s webhook-server-cert kubernetes.io/tls ``` ---- + #### Build ords immage + Build the ords image, downloading ords software is no longer needed; just build the image and push it to your repository @@ -128,16 +135,17 @@ cd oracle-database-operator/ords docker build -t oracle/ords-dboper:latest . ``` -[example of execution](./BuildImage.log) +[Example of execution](./logfiles/BuildImage.log) + Login to your container registry and push the ords image. ```bash docker tag /ords-dboper:latest docker push /ords-dboper:latest ``` -[example of execution](./ImagePush.log) +[Example of execution](./logfiles/tagandpush.log) ---- + #### Database Configuration + Configure Database @@ -153,6 +161,7 @@ GRANT SYSDBA TO CONTAINER = ALL; GRANT CREATE SESSION TO CONTAINER = ALL; ``` ---- + #### Create CDB secret + Create secret for CDB connection @@ -208,6 +217,7 @@ webhook-server-cert kubernetes.io/tls 3 4m55s >**TIPS:** Use the following commands to analyze contents of an existing secret ```bash kubectl get secret -o yaml -n ``` ---- + #### Create Certificates + Create certificates: At this stage we need to create certificates on our local machine and upload into kubernetes cluster by creating new secrets. @@ -258,65 +268,69 @@ kubectl create secret generic db-ca --from-file= -n oracle-database-op ``` -[example of execution:](./openssl_execution.log) +[Example of execution:](./logfiles/openssl_execution.log) ---- + #### Apply cdb.yaml + +**note:** + Before creating the CDB pod make sure that all the pluggable databases in the container DB are open. + + + Create ords container ```bash -/usr/bin/kubectl apply -f cdb.yaml -n oracle-database-operator-system +/usr/bin/kubectl apply -f cdb_create.yaml -n oracle-database-operator-system ``` -Example: **cdb.yaml** +Example: **cdb_create.yaml** ```yaml apiVersion: database.oracle.com/v1alpha1 -kind: CDB -metadata: - name: +kind: CDB +metadata: + name: cdb-dev namespace: oracle-database-operator-system spec: - cdbName: "" - dbServer: "" or - dbPort: - ordsImage: "/ords-dboper:.latest" + cdbName: "DB12" + ordsImage: ".............your registry............./ords-dboper:latest" ordsImagePullPolicy: "Always" - serviceName: + dbTnsurl : "...Container tns alias....." replicas: 1 - sysAdminPwd: - secret: + sysAdminPwd: + secret: secretName: "cdb1-secret" key: "sysadmin_pwd" ordsPwd: - secret: + secret: secretName: "cdb1-secret" - key: "ords_pwd" - cdbAdminUser: - secret: + key: "ords_pwd" + cdbAdminUser: + secret: secretName: "cdb1-secret" key: "cdbadmin_user" - cdbAdminPwd: - secret: + cdbAdminPwd: + secret: secretName: "cdb1-secret" key: "cdbadmin_pwd" - webServerUser: - secret: + webServerUser: + secret: secretName: "cdb1-secret" key: "webserver_user" - webServerPwd: - secret: + webServerPwd: + secret: secretName: "cdb1-secret" - key: "webserver_pwd" + key: "webserver_pwd" cdbTlsKey: secret: secretName: "db-tls" - key: "" + key: "tls.key" cdbTlsCrt: secret: secretName: "db-tls" - key: ":" + key: "tls.crt" ``` > **Note** if you are working in dataguard environment with multiple sites (AC/DR) specifying the host name (dbServer/dbPort/serviceName) may not be the suitable solution for this kind of configuration, use **dbTnsurl** instead. Specify the whole tns string which includes the hosts/scan list. @@ -337,9 +351,11 @@ spec: dbtnsurl:((DESCRIPTION=(CONNECT_TIMEOUT=90)(RETRY_COUNT=30)(RETRY_DELAY=10)(TRANSPORT_CONNECT_TIMEOUT=70)(TRANS...... ``` -[example of cdb.yaml](./cdb.yaml) +[Example of cdb.yaml](./cdb_create.yaml) + ---- + #### CDB - Logs and throuble shutting + Check the status of ords container @@ -374,14 +390,14 @@ NAME CDB NAME DB SERVER DB PORT REPLICAS STATUS MESSAG ```bash /usr/bin/kubectl logs `/usr/bin/kubectl get pods -n oracle-database-operator-system|grep ords|cut -d ' ' -f 1` -n oracle-database-operator-system ``` -[example of execution](./cdb.log) +[Example of cdb creation log](./logfiles/cdb_creation.log) + Test REST API from the pod. By querying the metadata catalog you can verify the status of https setting ```bash /usr/bin/kubectl exec -it `/usr/bin/kubectl get pods -n oracle-database-operator-system|grep ords|cut -d ' ' -f 1` -n oracle-database-operator-system -i -t -- /usr/bin/curl -sSkv -k -X GET https://localhost:8888/ords/_/db-api/stable/metadata-catalog/ ``` -[example of execution](./testapi.log) +[Example of execution](./logfiles/testapi.log) + Verify the pod environment varaibles ```bash @@ -398,9 +414,10 @@ NAME CDB NAME DB SERVER DB PORT REPLICAS STATUS MESSAG ```bash /usr/bin/kubectl exec -it `/usr/bin/kubectl get pods -n oracle-database-operator-system|grep ords|cut -d ' ' -f 1` -n oracle-database-operator-system -i -t -- /usr/local/bin/ords --config /etc/ords/config config list ``` -[Example of executions](./ordsconfig.log) +[Example of executions](./logfiles/ordsconfig.log) ----- + #### Create PDB secret @@ -434,30 +451,32 @@ pdb1-secret Opaque 2 79m <--- webhook-server-cert kubernetes.io/tls 3 79m ``` --- + #### Apply pdb yaml file to create pdb ```bash /usr/bin/kubectl apply -f pdb.yaml -n oracle-database-operator-system ``` -Example: **pdb.yaml** +Example: **pdb_create.yaml** ```yaml apiVersion: database.oracle.com/v1alpha1 kind: PDB metadata: - name: + name: pdb1 namespace: oracle-database-operator-system labels: - cdb: + cdb: cdb-dev spec: - cdbResName: "" - cdbName: "" - pdbName: + cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" + cdbName: "DB12" + pdbName: "pdbdev" adminName: secret: secretName: "pdb1-secret" - key: "sysadmin_user" + key: "sysadmin_user" adminPwd: secret: secretName: "pdb1-secret" @@ -465,19 +484,29 @@ spec: pdbTlsKey: secret: secretName: "db-tls" - key: "" + key: "tls.key" pdbTlsCrt: secret: secretName: "db-tls" - key: "" + key: "tls.crt" pdbTlsCat: secret: secretName: "db-ca" - key: "" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" fileNameConversions: "NONE" + tdeImport: false totalSize: "1G" tempSize: "100M" action: "Create" + assertivePdbDeletion: true ``` + Monitor the pdb creation status until message is success @@ -524,13 +553,17 @@ kubectl logs -f $(kubectl get pods -n oracle-database-operator-system|grep oracl ``` --- + #### Other actions -Configure and use other yaml files to perform pluggable database life cycle managment action **modify_pdb_open.yaml** **modify_pdb_close.yaml** +Configure and use other yaml files to perform pluggable database life cycle managment action **pdb_open.yaml** **pdb_close.yaml** -> **Note** sql command *"alter pluggable database open instances=all;"* acts only on closed databases, so you want get any oracle error in case of execution against an pluggable database already opened +> **Note** sql command *"alter pluggable database open instances=all;"* acts only on closed databases, so you don't get any oracle error in case of execution against an pluggable database already opened +#### Imperative approach on pdb deletion +If **assertivePdbDeletion** is true then the command execution **kubectl delete pdbs crd_pdb_name** automatically deletes the pluggable database on the container database. By default this option is disabled. You can use this option during **create**,**map**,**plug** and **clone** operation. If the option is disabled then **kubectl delete** only deletes the crd but not the pluggable on the container db. Database deletion uses the option **including datafiles**. +If you drop the CRD without dropping the pluggable database and you need to recreate the CRD then you can use the [pdb_map.yaml](./pdb_map.yaml) [1]:https://docs.oracle.com/en/database/oracle/oracle-rest-data-services/22.2/ordig/installing-and-configuring-oracle-rest-data-services.html#GUID-E9625FAB-9BC8-468B-9FF9-443C88D76FA1:~:text=Table%202%2D2%20Command%20Options%20for%20Command%2DLine%20Interface%20Installation @@ -553,4 +586,8 @@ Configure and use other yaml files to perform pluggable database life cycle mana [http]:https://docs.oracle.com/en/database/oracle/oracle-rest-data-services/22.2/ordig/installing-and-configuring-oracle-rest-data-services.html#GUID-BEECC057-A8F5-4EAB-B88E-9828C2809CD8:~:text=Example%3A%20delete%20%5B%2D%2Dglobal%5D-,user%20add,-Add%20a%20user -[dbtnsurl]:https://docs.oracle.com/en/database/oracle/oracle-rest-data-services/22.2/ordig/installing-and-configuring-oracle-rest-data-services.html#GUID-A9AED253-4EEC-4E13-A0C4-B7CE82EC1C22 \ No newline at end of file +[dbtnsurl]:https://docs.oracle.com/en/database/oracle/oracle-rest-data-services/22.2/ordig/installing-and-configuring-oracle-rest-data-services.html#GUID-A9AED253-4EEC-4E13-A0C4-B7CE82EC1C22 + +[imperative]:https://kubernetes.io/docs/concepts/overview/working-with-objects/object-management/ + + diff --git a/docs/multitenant/usecase01/ca.crt b/docs/multitenant/usecase01/ca.crt new file mode 100644 index 00000000..cc9aa8bb --- /dev/null +++ b/docs/multitenant/usecase01/ca.crt @@ -0,0 +1,25 @@ +-----BEGIN CERTIFICATE----- +MIIEJTCCAw2gAwIBAgIUNXPtpnNEFBCMcnxRP5kJsBDpafcwDQYJKoZIhvcNAQEL +BQAwgaExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQH +DAxTYW5GcmFuY2lzY28xEDAOBgNVBAoMB29yYWNsZSAxNjA0BgNVBAMMLWNkYi1k +ZXYtb3Jkcy5vcmFjbGUtZGF0YWJhc2Utb3BlcmF0b3Itc3lzdGVtIDEcMBoGA1UE +AwwTbG9jYWxob3N0ICBSb290IENBIDAeFw0yNDA4MTIxNTMyMzVaFw0yNTA4MTIx +NTMyMzVaMIGhMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMG +A1UEBwwMU2FuRnJhbmNpc2NvMRAwDgYDVQQKDAdvcmFjbGUgMTYwNAYDVQQDDC1j +ZGItZGV2LW9yZHMub3JhY2xlLWRhdGFiYXNlLW9wZXJhdG9yLXN5c3RlbSAxHDAa +BgNVBAMME2xvY2FsaG9zdCAgUm9vdCBDQSAwggEiMA0GCSqGSIb3DQEBAQUAA4IB +DwAwggEKAoIBAQCmnGVApwUBF1kpqcyr2nYeED0VKvefpoHLtxHSP+vP0lWhW7NU +NJlb1YuUagjJ4/rpGRQmPxcVU51n3aAW3a5qHazIpNxNa3fvgB1rMOPFxGmdel2d +8lIt+u19q19DknX/GNgH9Mog8RcyZyPeA7d2icT8TBo74ognr+8p68O3CjBHQ8EM +SnRQR7/bh1c10Uia317ilKvs+I7oErTq5JFLeIuPDdAJ6UncaeblTf1XJ/1FrpHG +fSS7xmR8x0/MblBQlku4eImYmN35g+eRgf8bLDDwC+GPzDnAqqMLjx6h2N+btDxr +tnn05qyqmN9G08uUlP4d4BXi9ISb/toYypklAgMBAAGjUzBRMB0GA1UdDgQWBBS+ +a4X2XTmdPivdQtqDWNpfOtHypDAfBgNVHSMEGDAWgBS+a4X2XTmdPivdQtqDWNpf +OtHypDAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUAA4IBAQAZIrGBNdSw +pe+1agefHfaR8hjZQiXBxdwHM1gR2LWOaFzMS8Q/eRETHTO6+VwQ0/FNaXbAqgqk +G317gZMXS5ZmXuOi28fTpAQtuzokkEKpoK0puTnbXOKGA2QSbBlpSFPqb3aJXvVt +afXFQb5P/0mhr4kuVt7Ech82WM/o5ryFgObygDayDmLatTp+VaRmBZPksnSMhslq +3zPyS7bx2YhbPTLkDxq8Mfr/Msxme8LvSXUpFf4PpQ5zwp1RE32gekct6eRQLmqU +5LXY2aPtqpMF0fBpcwPWbqA9gOYCRKcvXXIr+u1x8hf6Er6grZegHkM9TQ8s0hJd +sxi5tK0lPMHJ +-----END CERTIFICATE----- diff --git a/docs/multitenant/usecase01/ca.key b/docs/multitenant/usecase01/ca.key new file mode 100644 index 00000000..1a0ef89d --- /dev/null +++ b/docs/multitenant/usecase01/ca.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAppxlQKcFARdZKanMq9p2HhA9FSr3n6aBy7cR0j/rz9JVoVuz +VDSZW9WLlGoIyeP66RkUJj8XFVOdZ92gFt2uah2syKTcTWt374AdazDjxcRpnXpd +nfJSLfrtfatfQ5J1/xjYB/TKIPEXMmcj3gO3donE/EwaO+KIJ6/vKevDtwowR0PB +DEp0UEe/24dXNdFImt9e4pSr7PiO6BK06uSRS3iLjw3QCelJ3Gnm5U39Vyf9Ra6R +xn0ku8ZkfMdPzG5QUJZLuHiJmJjd+YPnkYH/Gyww8Avhj8w5wKqjC48eodjfm7Q8 +a7Z59OasqpjfRtPLlJT+HeAV4vSEm/7aGMqZJQIDAQABAoIBAGXRGYdjCgnarOBr +Jeq3vIsuvUVcVqs35AYMQFXOPltoXHAZTAPfiQC4BW6TRf+q1MDyVH/y+jZMPNsm +cxjGLDopHFgZd4/QZyDzmAbTf75yA2D7UI6fcV0sBUpRGgx/SqC0HADwtT1gWB6z +LRYWC13jX4AXOcjy7OXj/DIQJDCMivedt3dv0rDWJUcBCnVot5tr6zjycefxGKa8 +mG9LZQb3x71FxwpFUau3WLDSwOjtXCeMytaGXnGmIiofJmXnFi0KA4ApzKL7QV6I +cCBS1WBLLXeVM9vOfrtzKVLWGe0qADyLm35p5Fnl3j+vimkk8h/2DEvCZ75c987m +O3PEgdkCgYEA0Scg+KINTA78sdZL5v2+8fT4b+EfoCgUqfr10ReUPKrz3HfrVHcj +7Vf00RT52TkfmkL3mIdLyBUzQ9vzPgweo1o4yKCKNCpR9G3ydNW+KI5jSYnq2efz +Gpe3wTt+8YoyCgm9eUxNWjfO9fipS91sSotY0PovkBohj9aezfcWp1sCgYEAy+3n +MIvW/9PoYxCvQ9fDGLvx3B4/uy0ZYPh7j5edDuaRzwFd2YXUysXhJVuqTp0KT2tv +dRPFRE9Oq5N8e5ITIUiKLQ5PIRNBZm8CiAof+XS1fIuU+MTDaTfXwyGQo0xSg8MB +ITnJulmUlkcTWEtGyBi9sIjor5ve8kqvyrdAKX8CgYA9ZUUSd0978jJPad6iEf6J +PCXpgaYs91cJhre+BzPmkzA+mZ0lEEwlkdo1vfiRwWj7eYkA50Zhl4eS9e/zWM9t +mEBu9GFdasbf/55amZvWf+W5YpjkGmiMd9jjCjn7YVvLAozyHGngf91q6vGXaYou +X7VUsvxfSqxrcs7vGwc1XQKBgB0qaD80MMqj5v+MGlTsndWCw8OEe/7sI04QG7Pc +rjS8Wyws+NwsXNOnW1z5cDEQGrJjHiyzaCot4YV+cXZG3P+MnV52RnDnjRn2VHla +YVpPC8nFOMgfdAcvWmdo/IOuXbrEf/vdhPFm8G5Ruf2NvpDNoQuHeSfsdgVXEy89 +6CpHAoGBAMZInYD0XjcnZNqiQnQdcIJN3CqDIU76Z45OOpcUrYrvTos2xhGLrRI5 +qrk5Od/sovJfse+oUIIbgsABieqtyfxM03iu8fvbahIY6Un1iw2KN9t+mcPrSZJK +jTXKf7XxZ1+yN9kvohdLc65ySyXFSm++glDq8WGrmnOtLUlr0oMm +-----END RSA PRIVATE KEY----- diff --git a/docs/multitenant/usecase01/ca.srl b/docs/multitenant/usecase01/ca.srl new file mode 100644 index 00000000..7c9868bb --- /dev/null +++ b/docs/multitenant/usecase01/ca.srl @@ -0,0 +1 @@ +77D97AB4C4B6D5A9377B84B455D3E16348C6DE04 diff --git a/docs/multitenant/usecase01/cdb_create.yaml b/docs/multitenant/usecase01/cdb_create.yaml new file mode 100644 index 00000000..01fc0a18 --- /dev/null +++ b/docs/multitenant/usecase01/cdb_create.yaml @@ -0,0 +1,44 @@ +apiVersion: database.oracle.com/v1alpha1 +kind: CDB +metadata: + name: cdb-dev + namespace: oracle-database-operator-system +spec: + cdbName: "DB12" + ordsImage: ".............your registry............./ords-dboper:latest" + ordsImagePullPolicy: "Always" + dbTnsurl : "...Container tns alias....." + replicas: 1 + sysAdminPwd: + secret: + secretName: "cdb1-secret" + key: "sysadmin_pwd" + ordsPwd: + secret: + secretName: "cdb1-secret" + key: "ords_pwd" + cdbAdminUser: + secret: + secretName: "cdb1-secret" + key: "cdbadmin_user" + cdbAdminPwd: + secret: + secretName: "cdb1-secret" + key: "cdbadmin_pwd" + webServerUser: + secret: + secretName: "cdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "cdb1-secret" + key: "webserver_pwd" + cdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + cdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + diff --git a/docs/multitenant/usecase01/cdb_secret.yaml b/docs/multitenant/usecase01/cdb_secret.yaml new file mode 100644 index 00000000..567b90a4 --- /dev/null +++ b/docs/multitenant/usecase01/cdb_secret.yaml @@ -0,0 +1,17 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +apiVersion: v1 +kind: Secret +metadata: + name: cdb1-secret + namespace: oracle-database-operator-system +type: Opaque +data: + ords_pwd: ".....base64 encoded password...." + sysadmin_pwd: ".....base64 encoded password...." + cdbadmin_user: ".....base64 encoded password...." + cdbadmin_pwd: ".....base64 encoded password...." + webserver_user: ".....base64 encoded password...." + webserver_pwd: ".....base64 encoded password...." diff --git a/docs/multitenant/usecase01/extfile.txt b/docs/multitenant/usecase01/extfile.txt new file mode 100644 index 00000000..c51d22a3 --- /dev/null +++ b/docs/multitenant/usecase01/extfile.txt @@ -0,0 +1 @@ +subjectAltName=DNS:cdb-dev-ords.oracle-database-operator-system,DNS:www.example.com diff --git a/docs/multitenant/usecase01/logfiles/BuildImage.log b/docs/multitenant/usecase01/logfiles/BuildImage.log index 4ee2fa05..f35c66d8 100644 --- a/docs/multitenant/usecase01/logfiles/BuildImage.log +++ b/docs/multitenant/usecase01/logfiles/BuildImage.log @@ -1,487 +1,896 @@ -/usr/bin/docker build -t oracle/ords-dboper:latest . -Sending build context to Docker daemon 92.38MB -Step 1/10 : FROM container-registry.oracle.com/java/jdk:latest -Trying to pull repository container-registry.oracle.com/java/jdk ... -latest: Pulling from container-registry.oracle.com/java/jdk -7cb069903b8a: Pull complete -a98ca67f4239: Pull complete -1b4060d1d804: Pull complete -Digest: sha256:8e7161bbd6a3a3beb77ee6f2d80c17ae4c80d88e0f5af667a19a0271c33f1b5e -Status: Downloaded newer image for container-registry.oracle.com/java/jdk:latest - ---> ad9ff1bbe92a -Step 2/10 : ENV ORDS_HOME=/opt/oracle/ords/ RUN_FILE="runOrdsSSL.sh" - ---> Running in e6f76deab66e -Removing intermediate container e6f76deab66e - ---> 0b26c489e4fd -Step 3/10 : COPY $RUN_FILE $ORDS_HOME - ---> ee472155adab -Step 4/10 : RUN yum -y install yum-utils bind-utils tree hostname openssl net-tools zip unzip tar wget vim-minimal which sudo expect procps && yum-config-manager --add-repo=http://yum.oracle.com/repo/OracleLinux/OL8/oracle/software/x86_64 && yum -y install java-11-openjdk-devel && yum -y install ords && yum -y install iproute && yum clean all - ---> Running in d38a69d2cc70 -Oracle Linux 8 BaseOS Latest (x86_64) 105 MB/s | 50 MB 00:00 -Oracle Linux 8 Application Stream (x86_64) 90 MB/s | 38 MB 00:00 -Last metadata expiration check: 0:00:07 ago on Mon 10 Oct 2022 04:06:15 PM UTC. -Package yum-utils-4.0.21-11.0.1.el8.noarch is already installed. -Package tar-2:1.30-5.el8.x86_64 is already installed. +/usr/bin/docker build -t oracle/ords-dboper:latest ../../../ords +Sending build context to Docker daemon 13.82kB +Step 1/12 : FROM container-registry.oracle.com/java/jdk:latest + ---> b8457e2f0b73 +Step 2/12 : ENV ORDS_HOME=/opt/oracle/ords/ RUN_FILE="runOrdsSSL.sh" ORDSVERSION=23.4.0-8 + ---> Using cache + ---> 3317a16cd6f8 +Step 3/12 : COPY $RUN_FILE $ORDS_HOME + ---> 7995edec33cc +Step 4/12 : RUN yum -y install yum-utils bind-utils tree hostname openssl net-tools zip unzip tar wget vim-minimal which sudo expect procps curl lsof && yum-config-manager --add-repo=http://yum.oracle.com/repo/OracleLinux/OL8/oracle/software/x86_64 && yum -y install java-11-openjdk-devel && yum -y install iproute && yum clean all + ---> Running in fe168b01f3ad +Oracle Linux 8 BaseOS Latest (x86_64) 91 MB/s | 79 MB 00:00 +Oracle Linux 8 Application Stream (x86_64) 69 MB/s | 62 MB 00:00 +Last metadata expiration check: 0:00:12 ago on Tue 20 Aug 2024 08:54:50 AM UTC. +Package yum-utils-4.0.21-23.0.1.el8.noarch is already installed. +Package tar-2:1.30-9.el8.x86_64 is already installed. Package vim-minimal-2:8.0.1763-19.0.1.el8_6.4.x86_64 is already installed. -Package procps-ng-3.3.15-6.0.1.el8.x86_64 is already installed. +Package procps-ng-3.3.15-14.0.1.el8.x86_64 is already installed. +Package curl-7.61.1-33.el8_9.5.x86_64 is already installed. Dependencies resolved. ================================================================================ - Package Arch Version Repository Size + Package Arch Version Repository Size ================================================================================ Installing: - bind-utils x86_64 32:9.11.36-3.el8_6.1 ol8_appstream 452 k - expect x86_64 5.45.4-5.el8 ol8_baseos_latest 266 k - hostname x86_64 3.20-6.el8 ol8_baseos_latest 32 k - net-tools x86_64 2.0-0.52.20160912git.el8 ol8_baseos_latest 322 k - openssl x86_64 1:1.1.1k-7.el8_6 ol8_baseos_latest 709 k - sudo x86_64 1.8.29-8.el8 ol8_baseos_latest 925 k - tree x86_64 1.7.0-15.el8 ol8_baseos_latest 59 k - unzip x86_64 6.0-46.0.1.el8 ol8_baseos_latest 196 k - wget x86_64 1.19.5-10.0.1.el8 ol8_appstream 734 k - which x86_64 2.21-17.el8 ol8_baseos_latest 49 k - zip x86_64 3.0-23.el8 ol8_baseos_latest 270 k + bind-utils x86_64 32:9.11.36-16.el8_10.2 ol8_appstream 453 k + expect x86_64 5.45.4-5.el8 ol8_baseos_latest 266 k + hostname x86_64 3.20-6.el8 ol8_baseos_latest 32 k + lsof x86_64 4.93.2-1.el8 ol8_baseos_latest 253 k + net-tools x86_64 2.0-0.52.20160912git.el8 ol8_baseos_latest 322 k + openssl x86_64 1:1.1.1k-12.el8_9 ol8_baseos_latest 710 k + sudo x86_64 1.9.5p2-1.el8_9 ol8_baseos_latest 1.0 M + tree x86_64 1.7.0-15.el8 ol8_baseos_latest 59 k + unzip x86_64 6.0-46.0.1.el8 ol8_baseos_latest 196 k + wget x86_64 1.19.5-12.0.1.el8_10 ol8_appstream 733 k + which x86_64 2.21-20.el8 ol8_baseos_latest 50 k + zip x86_64 3.0-23.el8 ol8_baseos_latest 270 k +Upgrading: + curl x86_64 7.61.1-34.el8 ol8_baseos_latest 352 k + dnf-plugins-core noarch 4.0.21-25.0.1.el8 ol8_baseos_latest 76 k + libcurl x86_64 7.61.1-34.el8 ol8_baseos_latest 303 k + python3-dnf-plugins-core + noarch 4.0.21-25.0.1.el8 ol8_baseos_latest 263 k + yum-utils noarch 4.0.21-25.0.1.el8 ol8_baseos_latest 75 k Installing dependencies: - bind-libs x86_64 32:9.11.36-3.el8_6.1 ol8_appstream 175 k - bind-libs-lite x86_64 32:9.11.36-3.el8_6.1 ol8_appstream 1.2 M - bind-license noarch 32:9.11.36-3.el8_6.1 ol8_appstream 103 k - fstrm x86_64 0.6.1-2.el8 ol8_appstream 29 k - libmaxminddb x86_64 1.2.0-10.el8 ol8_appstream 33 k - libmetalink x86_64 0.1.3-7.el8 ol8_baseos_latest 32 k - protobuf-c x86_64 1.3.0-6.el8 ol8_appstream 37 k - python3-bind noarch 32:9.11.36-3.el8_6.1 ol8_appstream 150 k - python3-ply noarch 3.9-9.el8 ol8_baseos_latest 111 k - tcl x86_64 1:8.6.8-2.el8 ol8_baseos_latest 1.1 M + bind-libs x86_64 32:9.11.36-16.el8_10.2 ol8_appstream 176 k + bind-libs-lite x86_64 32:9.11.36-16.el8_10.2 ol8_appstream 1.2 M + bind-license noarch 32:9.11.36-16.el8_10.2 ol8_appstream 104 k + fstrm x86_64 0.6.1-3.el8 ol8_appstream 29 k + libmaxminddb x86_64 1.2.0-10.el8_9.1 ol8_appstream 32 k + libmetalink x86_64 0.1.3-7.el8 ol8_baseos_latest 32 k + protobuf-c x86_64 1.3.0-8.el8 ol8_appstream 37 k + python3-bind noarch 32:9.11.36-16.el8_10.2 ol8_appstream 151 k + python3-ply noarch 3.9-9.el8 ol8_baseos_latest 111 k + tcl x86_64 1:8.6.8-2.el8 ol8_baseos_latest 1.1 M +Installing weak dependencies: + geolite2-city noarch 20180605-1.el8 ol8_appstream 19 M + geolite2-country noarch 20180605-1.el8 ol8_appstream 1.0 M Transaction Summary ================================================================================ -Install 21 Packages +Install 24 Packages +Upgrade 5 Packages -Total download size: 6.9 M -Installed size: 20 M +Total download size: 28 M Downloading Packages: -(1/21): hostname-3.20-6.el8.x86_64.rpm 555 kB/s | 32 kB 00:00 -(2/21): libmetalink-0.1.3-7.el8.x86_64.rpm 492 kB/s | 32 kB 00:00 -(3/21): expect-5.45.4-5.el8.x86_64.rpm 3.2 MB/s | 266 kB 00:00 -(4/21): python3-ply-3.9-9.el8.noarch.rpm 5.5 MB/s | 111 kB 00:00 -(5/21): net-tools-2.0-0.52.20160912git.el8.x86_ 6.7 MB/s | 322 kB 00:00 -(6/21): openssl-1.1.1k-7.el8_6.x86_64.rpm 12 MB/s | 709 kB 00:00 -(7/21): tree-1.7.0-15.el8.x86_64.rpm 4.1 MB/s | 59 kB 00:00 -(8/21): sudo-1.8.29-8.el8.x86_64.rpm 19 MB/s | 925 kB 00:00 -(9/21): which-2.21-17.el8.x86_64.rpm 2.5 MB/s | 49 kB 00:00 -(10/21): unzip-6.0-46.0.1.el8.x86_64.rpm 5.9 MB/s | 196 kB 00:00 -(11/21): tcl-8.6.8-2.el8.x86_64.rpm 15 MB/s | 1.1 MB 00:00 -(12/21): zip-3.0-23.el8.x86_64.rpm 15 MB/s | 270 kB 00:00 -(13/21): bind-libs-9.11.36-3.el8_6.1.x86_64.rpm 7.9 MB/s | 175 kB 00:00 -(14/21): bind-license-9.11.36-3.el8_6.1.noarch. 4.9 MB/s | 103 kB 00:00 -(15/21): bind-utils-9.11.36-3.el8_6.1.x86_64.rp 21 MB/s | 452 kB 00:00 -(16/21): bind-libs-lite-9.11.36-3.el8_6.1.x86_6 28 MB/s | 1.2 MB 00:00 -(17/21): libmaxminddb-1.2.0-10.el8.x86_64.rpm 1.8 MB/s | 33 kB 00:00 -(18/21): fstrm-0.6.1-2.el8.x86_64.rpm 1.0 MB/s | 29 kB 00:00 -(19/21): protobuf-c-1.3.0-6.el8.x86_64.rpm 1.4 MB/s | 37 kB 00:00 -(20/21): python3-bind-9.11.36-3.el8_6.1.noarch. 9.2 MB/s | 150 kB 00:00 -(21/21): wget-1.19.5-10.0.1.el8.x86_64.rpm 7.5 MB/s | 734 kB 00:00 +(1/29): hostname-3.20-6.el8.x86_64.rpm 268 kB/s | 32 kB 00:00 +(2/29): libmetalink-0.1.3-7.el8.x86_64.rpm 257 kB/s | 32 kB 00:00 +(3/29): expect-5.45.4-5.el8.x86_64.rpm 1.4 MB/s | 266 kB 00:00 +(4/29): lsof-4.93.2-1.el8.x86_64.rpm 3.2 MB/s | 253 kB 00:00 +(5/29): net-tools-2.0-0.52.20160912git.el8.x86_ 3.6 MB/s | 322 kB 00:00 +(6/29): python3-ply-3.9-9.el8.noarch.rpm 2.7 MB/s | 111 kB 00:00 +(7/29): openssl-1.1.1k-12.el8_9.x86_64.rpm 10 MB/s | 710 kB 00:00 +(8/29): tree-1.7.0-15.el8.x86_64.rpm 2.2 MB/s | 59 kB 00:00 +(9/29): sudo-1.9.5p2-1.el8_9.x86_64.rpm 14 MB/s | 1.0 MB 00:00 +(10/29): unzip-6.0-46.0.1.el8.x86_64.rpm 6.8 MB/s | 196 kB 00:00 +(11/29): which-2.21-20.el8.x86_64.rpm 2.0 MB/s | 50 kB 00:00 +(12/29): tcl-8.6.8-2.el8.x86_64.rpm 13 MB/s | 1.1 MB 00:00 +(13/29): bind-libs-9.11.36-16.el8_10.2.x86_64.r 6.7 MB/s | 176 kB 00:00 +(14/29): zip-3.0-23.el8.x86_64.rpm 8.4 MB/s | 270 kB 00:00 +(15/29): bind-libs-lite-9.11.36-16.el8_10.2.x86 29 MB/s | 1.2 MB 00:00 +(16/29): bind-license-9.11.36-16.el8_10.2.noarc 3.3 MB/s | 104 kB 00:00 +(17/29): bind-utils-9.11.36-16.el8_10.2.x86_64. 13 MB/s | 453 kB 00:00 +(18/29): fstrm-0.6.1-3.el8.x86_64.rpm 1.2 MB/s | 29 kB 00:00 +(19/29): libmaxminddb-1.2.0-10.el8_9.1.x86_64.r 1.3 MB/s | 32 kB 00:00 +(20/29): geolite2-country-20180605-1.el8.noarch 17 MB/s | 1.0 MB 00:00 +(21/29): protobuf-c-1.3.0-8.el8.x86_64.rpm 1.5 MB/s | 37 kB 00:00 +(22/29): python3-bind-9.11.36-16.el8_10.2.noarc 5.8 MB/s | 151 kB 00:00 +(23/29): wget-1.19.5-12.0.1.el8_10.x86_64.rpm 17 MB/s | 733 kB 00:00 +(24/29): curl-7.61.1-34.el8.x86_64.rpm 12 MB/s | 352 kB 00:00 +(25/29): dnf-plugins-core-4.0.21-25.0.1.el8.noa 2.4 MB/s | 76 kB 00:00 +(26/29): libcurl-7.61.1-34.el8.x86_64.rpm 8.6 MB/s | 303 kB 00:00 +(27/29): python3-dnf-plugins-core-4.0.21-25.0.1 9.8 MB/s | 263 kB 00:00 +(28/29): yum-utils-4.0.21-25.0.1.el8.noarch.rpm 3.0 MB/s | 75 kB 00:00 +(29/29): geolite2-city-20180605-1.el8.noarch.rp 66 MB/s | 19 MB 00:00 -------------------------------------------------------------------------------- -Total 20 MB/s | 6.9 MB 00:00 +Total 43 MB/s | 28 MB 00:00 Running transaction check Transaction check succeeded. Running transaction test Transaction test succeeded. Running transaction Preparing : 1/1 - Installing : protobuf-c-1.3.0-6.el8.x86_64 1/21 - Installing : libmaxminddb-1.2.0-10.el8.x86_64 2/21 - Running scriptlet: libmaxminddb-1.2.0-10.el8.x86_64 2/21 - Installing : fstrm-0.6.1-2.el8.x86_64 3/21 - Installing : bind-license-32:9.11.36-3.el8_6.1.noarch 4/21 - Installing : bind-libs-lite-32:9.11.36-3.el8_6.1.x86_64 5/21 - Installing : bind-libs-32:9.11.36-3.el8_6.1.x86_64 6/21 - Installing : unzip-6.0-46.0.1.el8.x86_64 7/21 - Installing : tcl-1:8.6.8-2.el8.x86_64 8/21 - Running scriptlet: tcl-1:8.6.8-2.el8.x86_64 8/21 - Installing : python3-ply-3.9-9.el8.noarch 9/21 - Installing : python3-bind-32:9.11.36-3.el8_6.1.noarch 10/21 - Installing : libmetalink-0.1.3-7.el8.x86_64 11/21 - Installing : wget-1.19.5-10.0.1.el8.x86_64 12/21 - Running scriptlet: wget-1.19.5-10.0.1.el8.x86_64 12/21 - Installing : bind-utils-32:9.11.36-3.el8_6.1.x86_64 13/21 - Installing : expect-5.45.4-5.el8.x86_64 14/21 - Installing : zip-3.0-23.el8.x86_64 15/21 - Installing : which-2.21-17.el8.x86_64 16/21 - Installing : tree-1.7.0-15.el8.x86_64 17/21 - Installing : sudo-1.8.29-8.el8.x86_64 18/21 - Running scriptlet: sudo-1.8.29-8.el8.x86_64 18/21 - Installing : openssl-1:1.1.1k-7.el8_6.x86_64 19/21 - Installing : net-tools-2.0-0.52.20160912git.el8.x86_64 20/21 - Running scriptlet: net-tools-2.0-0.52.20160912git.el8.x86_64 20/21 - Installing : hostname-3.20-6.el8.x86_64 21/21 - Running scriptlet: hostname-3.20-6.el8.x86_64 21/21 - Verifying : expect-5.45.4-5.el8.x86_64 1/21 - Verifying : hostname-3.20-6.el8.x86_64 2/21 - Verifying : libmetalink-0.1.3-7.el8.x86_64 3/21 - Verifying : net-tools-2.0-0.52.20160912git.el8.x86_64 4/21 - Verifying : openssl-1:1.1.1k-7.el8_6.x86_64 5/21 - Verifying : python3-ply-3.9-9.el8.noarch 6/21 - Verifying : sudo-1.8.29-8.el8.x86_64 7/21 - Verifying : tcl-1:8.6.8-2.el8.x86_64 8/21 - Verifying : tree-1.7.0-15.el8.x86_64 9/21 - Verifying : unzip-6.0-46.0.1.el8.x86_64 10/21 - Verifying : which-2.21-17.el8.x86_64 11/21 - Verifying : zip-3.0-23.el8.x86_64 12/21 - Verifying : bind-libs-32:9.11.36-3.el8_6.1.x86_64 13/21 - Verifying : bind-libs-lite-32:9.11.36-3.el8_6.1.x86_64 14/21 - Verifying : bind-license-32:9.11.36-3.el8_6.1.noarch 15/21 - Verifying : bind-utils-32:9.11.36-3.el8_6.1.x86_64 16/21 - Verifying : fstrm-0.6.1-2.el8.x86_64 17/21 - Verifying : libmaxminddb-1.2.0-10.el8.x86_64 18/21 - Verifying : protobuf-c-1.3.0-6.el8.x86_64 19/21 - Verifying : python3-bind-32:9.11.36-3.el8_6.1.noarch 20/21 - Verifying : wget-1.19.5-10.0.1.el8.x86_64 21/21 + Running scriptlet: protobuf-c-1.3.0-8.el8.x86_64 1/1 + Installing : protobuf-c-1.3.0-8.el8.x86_64 1/34 + Installing : fstrm-0.6.1-3.el8.x86_64 2/34 + Installing : bind-license-32:9.11.36-16.el8_10.2.noarch 3/34 + Upgrading : python3-dnf-plugins-core-4.0.21-25.0.1.el8.noarch 4/34 + Upgrading : dnf-plugins-core-4.0.21-25.0.1.el8.noarch 5/34 + Upgrading : libcurl-7.61.1-34.el8.x86_64 6/34 + Installing : geolite2-country-20180605-1.el8.noarch 7/34 + Installing : geolite2-city-20180605-1.el8.noarch 8/34 + Installing : libmaxminddb-1.2.0-10.el8_9.1.x86_64 9/34 + Running scriptlet: libmaxminddb-1.2.0-10.el8_9.1.x86_64 9/34 + Installing : bind-libs-lite-32:9.11.36-16.el8_10.2.x86_64 10/34 + Installing : bind-libs-32:9.11.36-16.el8_10.2.x86_64 11/34 + Installing : unzip-6.0-46.0.1.el8.x86_64 12/34 + Installing : tcl-1:8.6.8-2.el8.x86_64 13/34 + Running scriptlet: tcl-1:8.6.8-2.el8.x86_64 13/34 + Installing : python3-ply-3.9-9.el8.noarch 14/34 + Installing : python3-bind-32:9.11.36-16.el8_10.2.noarch 15/34 + Installing : libmetalink-0.1.3-7.el8.x86_64 16/34 + Installing : wget-1.19.5-12.0.1.el8_10.x86_64 17/34 + Running scriptlet: wget-1.19.5-12.0.1.el8_10.x86_64 17/34 + Installing : bind-utils-32:9.11.36-16.el8_10.2.x86_64 18/34 + Installing : expect-5.45.4-5.el8.x86_64 19/34 + Installing : zip-3.0-23.el8.x86_64 20/34 + Upgrading : curl-7.61.1-34.el8.x86_64 21/34 + Upgrading : yum-utils-4.0.21-25.0.1.el8.noarch 22/34 + Installing : which-2.21-20.el8.x86_64 23/34 + Installing : tree-1.7.0-15.el8.x86_64 24/34 + Installing : sudo-1.9.5p2-1.el8_9.x86_64 25/34 + Running scriptlet: sudo-1.9.5p2-1.el8_9.x86_64 25/34 + Installing : openssl-1:1.1.1k-12.el8_9.x86_64 26/34 + Installing : net-tools-2.0-0.52.20160912git.el8.x86_64 27/34 + Running scriptlet: net-tools-2.0-0.52.20160912git.el8.x86_64 27/34 + Installing : lsof-4.93.2-1.el8.x86_64 28/34 + Installing : hostname-3.20-6.el8.x86_64 29/34 + Running scriptlet: hostname-3.20-6.el8.x86_64 29/34 + Cleanup : curl-7.61.1-33.el8_9.5.x86_64 30/34 + Cleanup : yum-utils-4.0.21-23.0.1.el8.noarch 31/34 + Cleanup : dnf-plugins-core-4.0.21-23.0.1.el8.noarch 32/34 + Cleanup : python3-dnf-plugins-core-4.0.21-23.0.1.el8.noarch 33/34 + Cleanup : libcurl-7.61.1-33.el8_9.5.x86_64 34/34 + Running scriptlet: libcurl-7.61.1-33.el8_9.5.x86_64 34/34 + Verifying : expect-5.45.4-5.el8.x86_64 1/34 + Verifying : hostname-3.20-6.el8.x86_64 2/34 + Verifying : libmetalink-0.1.3-7.el8.x86_64 3/34 + Verifying : lsof-4.93.2-1.el8.x86_64 4/34 + Verifying : net-tools-2.0-0.52.20160912git.el8.x86_64 5/34 + Verifying : openssl-1:1.1.1k-12.el8_9.x86_64 6/34 + Verifying : python3-ply-3.9-9.el8.noarch 7/34 + Verifying : sudo-1.9.5p2-1.el8_9.x86_64 8/34 + Verifying : tcl-1:8.6.8-2.el8.x86_64 9/34 + Verifying : tree-1.7.0-15.el8.x86_64 10/34 + Verifying : unzip-6.0-46.0.1.el8.x86_64 11/34 + Verifying : which-2.21-20.el8.x86_64 12/34 + Verifying : zip-3.0-23.el8.x86_64 13/34 + Verifying : bind-libs-32:9.11.36-16.el8_10.2.x86_64 14/34 + Verifying : bind-libs-lite-32:9.11.36-16.el8_10.2.x86_64 15/34 + Verifying : bind-license-32:9.11.36-16.el8_10.2.noarch 16/34 + Verifying : bind-utils-32:9.11.36-16.el8_10.2.x86_64 17/34 + Verifying : fstrm-0.6.1-3.el8.x86_64 18/34 + Verifying : geolite2-city-20180605-1.el8.noarch 19/34 + Verifying : geolite2-country-20180605-1.el8.noarch 20/34 + Verifying : libmaxminddb-1.2.0-10.el8_9.1.x86_64 21/34 + Verifying : protobuf-c-1.3.0-8.el8.x86_64 22/34 + Verifying : python3-bind-32:9.11.36-16.el8_10.2.noarch 23/34 + Verifying : wget-1.19.5-12.0.1.el8_10.x86_64 24/34 + Verifying : curl-7.61.1-34.el8.x86_64 25/34 + Verifying : curl-7.61.1-33.el8_9.5.x86_64 26/34 + Verifying : dnf-plugins-core-4.0.21-25.0.1.el8.noarch 27/34 + Verifying : dnf-plugins-core-4.0.21-23.0.1.el8.noarch 28/34 + Verifying : libcurl-7.61.1-34.el8.x86_64 29/34 + Verifying : libcurl-7.61.1-33.el8_9.5.x86_64 30/34 + Verifying : python3-dnf-plugins-core-4.0.21-25.0.1.el8.noarch 31/34 + Verifying : python3-dnf-plugins-core-4.0.21-23.0.1.el8.noarch 32/34 + Verifying : yum-utils-4.0.21-25.0.1.el8.noarch 33/34 + Verifying : yum-utils-4.0.21-23.0.1.el8.noarch 34/34 +Upgraded: + curl-7.61.1-34.el8.x86_64 + dnf-plugins-core-4.0.21-25.0.1.el8.noarch + libcurl-7.61.1-34.el8.x86_64 + python3-dnf-plugins-core-4.0.21-25.0.1.el8.noarch + yum-utils-4.0.21-25.0.1.el8.noarch Installed: - bind-libs-32:9.11.36-3.el8_6.1.x86_64 - bind-libs-lite-32:9.11.36-3.el8_6.1.x86_64 - bind-license-32:9.11.36-3.el8_6.1.noarch - bind-utils-32:9.11.36-3.el8_6.1.x86_64 + bind-libs-32:9.11.36-16.el8_10.2.x86_64 + bind-libs-lite-32:9.11.36-16.el8_10.2.x86_64 + bind-license-32:9.11.36-16.el8_10.2.noarch + bind-utils-32:9.11.36-16.el8_10.2.x86_64 expect-5.45.4-5.el8.x86_64 - fstrm-0.6.1-2.el8.x86_64 + fstrm-0.6.1-3.el8.x86_64 + geolite2-city-20180605-1.el8.noarch + geolite2-country-20180605-1.el8.noarch hostname-3.20-6.el8.x86_64 - libmaxminddb-1.2.0-10.el8.x86_64 + libmaxminddb-1.2.0-10.el8_9.1.x86_64 libmetalink-0.1.3-7.el8.x86_64 + lsof-4.93.2-1.el8.x86_64 net-tools-2.0-0.52.20160912git.el8.x86_64 - openssl-1:1.1.1k-7.el8_6.x86_64 - protobuf-c-1.3.0-6.el8.x86_64 - python3-bind-32:9.11.36-3.el8_6.1.noarch + openssl-1:1.1.1k-12.el8_9.x86_64 + protobuf-c-1.3.0-8.el8.x86_64 + python3-bind-32:9.11.36-16.el8_10.2.noarch python3-ply-3.9-9.el8.noarch - sudo-1.8.29-8.el8.x86_64 + sudo-1.9.5p2-1.el8_9.x86_64 tcl-1:8.6.8-2.el8.x86_64 tree-1.7.0-15.el8.x86_64 unzip-6.0-46.0.1.el8.x86_64 - wget-1.19.5-10.0.1.el8.x86_64 - which-2.21-17.el8.x86_64 + wget-1.19.5-12.0.1.el8_10.x86_64 + which-2.21-20.el8.x86_64 zip-3.0-23.el8.x86_64 Complete! Adding repo from: http://yum.oracle.com/repo/OracleLinux/OL8/oracle/software/x86_64 -created by dnf config-manager from http://yum.o 194 kB/s | 49 kB 00:00 +created by dnf config-manager from http://yum.o 496 kB/s | 139 kB 00:00 +Last metadata expiration check: 0:00:01 ago on Tue 20 Aug 2024 08:55:14 AM UTC. Dependencies resolved. -============================================================================================= - Package Arch Version Repository Size -============================================================================================= +============================================================================================== + Package Arch Version Repository Size +============================================================================================== Installing: - java-11-openjdk-devel x86_64 1:11.0.16.1.1-1.el8_6 ol8_appstream 3.4 M + java-11-openjdk-devel x86_64 1:11.0.24.0.8-3.0.1.el8 ol8_appstream 3.4 M Installing dependencies: - alsa-lib x86_64 1.2.6.1-3.el8 ol8_appstream 491 k - avahi-libs x86_64 0.7-20.el8 ol8_baseos_latest 62 k - copy-jdk-configs noarch 4.0-2.el8 ol8_appstream 30 k - crypto-policies-scripts noarch 20211116-1.gitae470d6.el8 ol8_baseos_latest 83 k - cups-libs x86_64 1:2.2.6-45.el8_6.2 ol8_baseos_latest 434 k - giflib x86_64 5.1.4-3.el8 ol8_appstream 51 k - graphite2 x86_64 1.3.10-10.el8 ol8_appstream 122 k - harfbuzz x86_64 1.7.5-3.el8 ol8_appstream 295 k - java-11-openjdk x86_64 1:11.0.16.1.1-1.el8_6 ol8_appstream 272 k - java-11-openjdk-headless x86_64 1:11.0.16.1.1-1.el8_6 ol8_appstream 40 M - javapackages-filesystem noarch 5.3.0-1.module+el8+5136+7ff78f74 ol8_appstream 30 k - lcms2 x86_64 2.9-2.el8 ol8_appstream 164 k - libX11 x86_64 1.6.8-5.el8 ol8_appstream 611 k - libX11-common noarch 1.6.8-5.el8 ol8_appstream 158 k - libXau x86_64 1.0.9-3.el8 ol8_appstream 37 k - libXcomposite x86_64 0.4.4-14.el8 ol8_appstream 28 k - libXext x86_64 1.3.4-1.el8 ol8_appstream 45 k - libXi x86_64 1.7.10-1.el8 ol8_appstream 49 k - libXrender x86_64 0.9.10-7.el8 ol8_appstream 33 k - libXtst x86_64 1.2.3-7.el8 ol8_appstream 22 k - libfontenc x86_64 1.1.3-8.el8 ol8_appstream 37 k - libjpeg-turbo x86_64 1.5.3-12.el8 ol8_appstream 157 k - libpkgconf x86_64 1.4.2-1.el8 ol8_baseos_latest 35 k - libxcb x86_64 1.13.1-1.el8 ol8_appstream 231 k - lksctp-tools x86_64 1.0.18-3.el8 ol8_baseos_latest 100 k - lua x86_64 5.3.4-12.el8 ol8_appstream 192 k - nspr x86_64 4.34.0-3.el8_6 ol8_appstream 143 k - nss x86_64 3.79.0-10.el8_6 ol8_appstream 747 k - nss-softokn x86_64 3.79.0-10.el8_6 ol8_appstream 1.2 M - nss-softokn-freebl x86_64 3.79.0-10.el8_6 ol8_appstream 398 k - nss-sysinit x86_64 3.79.0-10.el8_6 ol8_appstream 74 k - nss-util x86_64 3.79.0-10.el8_6 ol8_appstream 138 k - pkgconf x86_64 1.4.2-1.el8 ol8_baseos_latest 38 k - pkgconf-m4 noarch 1.4.2-1.el8 ol8_baseos_latest 17 k - pkgconf-pkg-config x86_64 1.4.2-1.el8 ol8_baseos_latest 15 k - ttmkfdir x86_64 3.0.9-54.el8 ol8_appstream 62 k - tzdata-java noarch 2022d-1.el8 ol8_appstream 186 k - xorg-x11-font-utils x86_64 1:7.5-41.el8 ol8_appstream 104 k - xorg-x11-fonts-Type1 noarch 7.5-19.el8 ol8_appstream 522 k + adwaita-cursor-theme noarch 3.28.0-3.el8 ol8_appstream 647 k + adwaita-icon-theme noarch 3.28.0-3.el8 ol8_appstream 11 M + alsa-lib x86_64 1.2.10-2.el8 ol8_appstream 500 k + at-spi2-atk x86_64 2.26.2-1.el8 ol8_appstream 89 k + at-spi2-core x86_64 2.28.0-1.el8 ol8_appstream 169 k + atk x86_64 2.28.1-1.el8 ol8_appstream 272 k + avahi-libs x86_64 0.7-27.el8 ol8_baseos_latest 61 k + cairo x86_64 1.15.12-6.el8 ol8_appstream 719 k + cairo-gobject x86_64 1.15.12-6.el8 ol8_appstream 33 k + colord-libs x86_64 1.4.2-1.el8 ol8_appstream 236 k + copy-jdk-configs noarch 4.0-2.el8 ol8_appstream 30 k + cpio x86_64 2.12-11.el8 ol8_baseos_latest 266 k + crypto-policies-scripts noarch 20230731-1.git3177e06.el8 ol8_baseos_latest 84 k + cups-libs x86_64 1:2.2.6-60.el8_10 ol8_baseos_latest 435 k + dracut x86_64 049-233.git20240115.0.1.el8 ol8_baseos_latest 382 k + file x86_64 5.33-25.el8 ol8_baseos_latest 77 k + fribidi x86_64 1.0.4-9.el8 ol8_appstream 89 k + gdk-pixbuf2 x86_64 2.36.12-6.el8_10 ol8_baseos_latest 465 k + gdk-pixbuf2-modules x86_64 2.36.12-6.el8_10 ol8_appstream 108 k + gettext x86_64 0.19.8.1-17.el8 ol8_baseos_latest 1.1 M + gettext-libs x86_64 0.19.8.1-17.el8 ol8_baseos_latest 312 k + glib-networking x86_64 2.56.1-1.1.el8 ol8_baseos_latest 155 k + graphite2 x86_64 1.3.10-10.el8 ol8_appstream 122 k + grub2-common noarch 1:2.02-156.0.2.el8 ol8_baseos_latest 897 k + grub2-tools x86_64 1:2.02-156.0.2.el8 ol8_baseos_latest 2.0 M + grub2-tools-minimal x86_64 1:2.02-156.0.2.el8 ol8_baseos_latest 215 k + gsettings-desktop-schemas x86_64 3.32.0-6.el8 ol8_baseos_latest 633 k + gtk-update-icon-cache x86_64 3.22.30-11.el8 ol8_appstream 32 k + harfbuzz x86_64 1.7.5-4.el8 ol8_appstream 295 k + hicolor-icon-theme noarch 0.17-2.el8 ol8_appstream 48 k + jasper-libs x86_64 2.0.14-5.el8 ol8_appstream 167 k + java-11-openjdk x86_64 1:11.0.24.0.8-3.0.1.el8 ol8_appstream 475 k + java-11-openjdk-headless x86_64 1:11.0.24.0.8-3.0.1.el8 ol8_appstream 42 M + javapackages-filesystem noarch 5.3.0-1.module+el8+5136+7ff78f74 ol8_appstream 30 k + jbigkit-libs x86_64 2.1-14.el8 ol8_appstream 55 k + json-glib x86_64 1.4.4-1.el8 ol8_baseos_latest 144 k + kbd-legacy noarch 2.0.4-11.el8 ol8_baseos_latest 481 k + kbd-misc noarch 2.0.4-11.el8 ol8_baseos_latest 1.5 M + lcms2 x86_64 2.9-2.el8 ol8_appstream 164 k + libX11 x86_64 1.6.8-8.el8 ol8_appstream 611 k + libX11-common noarch 1.6.8-8.el8 ol8_appstream 157 k + libXau x86_64 1.0.9-3.el8 ol8_appstream 37 k + libXcomposite x86_64 0.4.4-14.el8 ol8_appstream 28 k + libXcursor x86_64 1.1.15-3.el8 ol8_appstream 36 k + libXdamage x86_64 1.1.4-14.el8 ol8_appstream 27 k + libXext x86_64 1.3.4-1.el8 ol8_appstream 45 k + libXfixes x86_64 5.0.3-7.el8 ol8_appstream 25 k + libXft x86_64 2.3.3-1.el8 ol8_appstream 67 k + libXi x86_64 1.7.10-1.el8 ol8_appstream 49 k + libXinerama x86_64 1.1.4-1.el8 ol8_appstream 15 k + libXrandr x86_64 1.5.2-1.el8 ol8_appstream 34 k + libXrender x86_64 0.9.10-7.el8 ol8_appstream 33 k + libXtst x86_64 1.2.3-7.el8 ol8_appstream 22 k + libcroco x86_64 0.6.12-4.el8_2.1 ol8_baseos_latest 113 k + libdatrie x86_64 0.2.9-7.el8 ol8_appstream 33 k + libepoxy x86_64 1.5.8-1.el8 ol8_appstream 225 k + libfontenc x86_64 1.1.3-8.el8 ol8_appstream 37 k + libgomp x86_64 8.5.0-22.0.1.el8_10 ol8_baseos_latest 218 k + libgusb x86_64 0.3.0-1.el8 ol8_baseos_latest 49 k + libjpeg-turbo x86_64 1.5.3-12.el8 ol8_appstream 157 k + libkcapi x86_64 1.4.0-2.0.1.el8 ol8_baseos_latest 52 k + libkcapi-hmaccalc x86_64 1.4.0-2.0.1.el8 ol8_baseos_latest 31 k + libmodman x86_64 2.0.1-17.el8 ol8_baseos_latest 36 k + libpkgconf x86_64 1.4.2-1.el8 ol8_baseos_latest 35 k + libproxy x86_64 0.4.15-5.2.el8 ol8_baseos_latest 75 k + libsoup x86_64 2.62.3-5.el8 ol8_baseos_latest 424 k + libthai x86_64 0.1.27-2.el8 ol8_appstream 203 k + libtiff x86_64 4.0.9-32.el8_10 ol8_appstream 189 k + libwayland-client x86_64 1.21.0-1.el8 ol8_appstream 41 k + libwayland-cursor x86_64 1.21.0-1.el8 ol8_appstream 26 k + libwayland-egl x86_64 1.21.0-1.el8 ol8_appstream 19 k + libxcb x86_64 1.13.1-1.el8 ol8_appstream 231 k + libxkbcommon x86_64 0.9.1-1.el8 ol8_appstream 116 k + lksctp-tools x86_64 1.0.18-3.el8 ol8_baseos_latest 100 k + lua x86_64 5.3.4-12.el8 ol8_appstream 192 k + nspr x86_64 4.35.0-1.el8_8 ol8_appstream 143 k + nss x86_64 3.90.0-7.el8_10 ol8_appstream 750 k + nss-softokn x86_64 3.90.0-7.el8_10 ol8_appstream 1.2 M + nss-softokn-freebl x86_64 3.90.0-7.el8_10 ol8_appstream 375 k + nss-sysinit x86_64 3.90.0-7.el8_10 ol8_appstream 74 k + nss-util x86_64 3.90.0-7.el8_10 ol8_appstream 139 k + os-prober x86_64 1.74-9.0.1.el8 ol8_baseos_latest 51 k + pango x86_64 1.42.4-8.el8 ol8_appstream 297 k + pixman x86_64 0.38.4-4.el8 ol8_appstream 256 k + pkgconf x86_64 1.4.2-1.el8 ol8_baseos_latest 38 k + pkgconf-m4 noarch 1.4.2-1.el8 ol8_baseos_latest 17 k + pkgconf-pkg-config x86_64 1.4.2-1.el8 ol8_baseos_latest 15 k + rest x86_64 0.8.1-2.el8 ol8_appstream 70 k + shared-mime-info x86_64 1.9-4.el8 ol8_baseos_latest 328 k + systemd-udev x86_64 239-78.0.4.el8 ol8_baseos_latest 1.6 M + ttmkfdir x86_64 3.0.9-54.el8 ol8_appstream 62 k + tzdata-java noarch 2024a-1.0.1.el8 ol8_appstream 186 k + xkeyboard-config noarch 2.28-1.el8 ol8_appstream 782 k + xorg-x11-font-utils x86_64 1:7.5-41.el8 ol8_appstream 104 k + xorg-x11-fonts-Type1 noarch 7.5-19.el8 ol8_appstream 522 k + xz x86_64 5.2.4-4.el8_6 ol8_baseos_latest 153 k +Installing weak dependencies: + abattis-cantarell-fonts noarch 0.0.25-6.el8 ol8_appstream 155 k + dconf x86_64 0.28.0-4.0.1.el8 ol8_appstream 108 k + dejavu-sans-mono-fonts noarch 2.35-7.el8 ol8_baseos_latest 447 k + grubby x86_64 8.40-49.0.2.el8 ol8_baseos_latest 50 k + gtk3 x86_64 3.22.30-11.el8 ol8_appstream 4.5 M + hardlink x86_64 1:1.3-6.el8 ol8_baseos_latest 29 k + kbd x86_64 2.0.4-11.el8 ol8_baseos_latest 390 k + memstrack x86_64 0.2.5-2.el8 ol8_baseos_latest 51 k + pigz x86_64 2.4-4.el8 ol8_baseos_latest 80 k Enabling module streams: - javapackages-runtime 201801 + javapackages-runtime 201801 Transaction Summary -============================================================================================= -Install 40 Packages +============================================================================================== +Install 106 Packages -Total download size: 50 M -Installed size: 196 M +Total download size: 86 M +Installed size: 312 M Downloading Packages: -(1/40): crypto-policies-scripts-20211116-1.gita 1.3 MB/s | 83 kB 00:00 -(2/40): avahi-libs-0.7-20.el8.x86_64.rpm 879 kB/s | 62 kB 00:00 -(3/40): libpkgconf-1.4.2-1.el8.x86_64.rpm 2.0 MB/s | 35 kB 00:00 -(4/40): cups-libs-2.2.6-45.el8_6.2.x86_64.rpm 4.5 MB/s | 434 kB 00:00 -(5/40): lksctp-tools-1.0.18-3.el8.x86_64.rpm 3.7 MB/s | 100 kB 00:00 -(6/40): pkgconf-1.4.2-1.el8.x86_64.rpm 2.2 MB/s | 38 kB 00:00 -(7/40): pkgconf-m4-1.4.2-1.el8.noarch.rpm 1.2 MB/s | 17 kB 00:00 -(8/40): pkgconf-pkg-config-1.4.2-1.el8.x86_64.r 929 kB/s | 15 kB 00:00 -(9/40): copy-jdk-configs-4.0-2.el8.noarch.rpm 2.2 MB/s | 30 kB 00:00 -(10/40): giflib-5.1.4-3.el8.x86_64.rpm 3.3 MB/s | 51 kB 00:00 -(11/40): graphite2-1.3.10-10.el8.x86_64.rpm 7.7 MB/s | 122 kB 00:00 -(12/40): alsa-lib-1.2.6.1-3.el8.x86_64.rpm 12 MB/s | 491 kB 00:00 -(13/40): java-11-openjdk-11.0.16.1.1-1.el8_6.x8 14 MB/s | 272 kB 00:00 -(14/40): harfbuzz-1.7.5-3.el8.x86_64.rpm 8.7 MB/s | 295 kB 00:00 -(15/40): javapackages-filesystem-5.3.0-1.module 2.0 MB/s | 30 kB 00:00 -(16/40): lcms2-2.9-2.el8.x86_64.rpm 6.7 MB/s | 164 kB 00:00 -(17/40): java-11-openjdk-devel-11.0.16.1.1-1.el 46 MB/s | 3.4 MB 00:00 -(18/40): libX11-common-1.6.8-5.el8.noarch.rpm 8.4 MB/s | 158 kB 00:00 -(19/40): libX11-1.6.8-5.el8.x86_64.rpm 17 MB/s | 611 kB 00:00 -(20/40): libXau-1.0.9-3.el8.x86_64.rpm 2.6 MB/s | 37 kB 00:00 -(21/40): libXcomposite-0.4.4-14.el8.x86_64.rpm 2.0 MB/s | 28 kB 00:00 -(22/40): libXi-1.7.10-1.el8.x86_64.rpm 2.2 MB/s | 49 kB 00:00 -(23/40): libXext-1.3.4-1.el8.x86_64.rpm 1.6 MB/s | 45 kB 00:00 -(24/40): libXtst-1.2.3-7.el8.x86_64.rpm 1.1 MB/s | 22 kB 00:00 -(25/40): libXrender-0.9.10-7.el8.x86_64.rpm 1.3 MB/s | 33 kB 00:00 -(26/40): libfontenc-1.1.3-8.el8.x86_64.rpm 2.2 MB/s | 37 kB 00:00 -(27/40): libjpeg-turbo-1.5.3-12.el8.x86_64.rpm 8.6 MB/s | 157 kB 00:00 -(28/40): libxcb-1.13.1-1.el8.x86_64.rpm 13 MB/s | 231 kB 00:00 -(29/40): lua-5.3.4-12.el8.x86_64.rpm 11 MB/s | 192 kB 00:00 -(30/40): nspr-4.34.0-3.el8_6.x86_64.rpm 7.8 MB/s | 143 kB 00:00 -(31/40): nss-3.79.0-10.el8_6.x86_64.rpm 23 MB/s | 747 kB 00:00 -(32/40): nss-softokn-3.79.0-10.el8_6.x86_64.rpm 42 MB/s | 1.2 MB 00:00 -(33/40): nss-softokn-freebl-3.79.0-10.el8_6.x86 19 MB/s | 398 kB 00:00 -(34/40): nss-sysinit-3.79.0-10.el8_6.x86_64.rpm 5.3 MB/s | 74 kB 00:00 -(35/40): nss-util-3.79.0-10.el8_6.x86_64.rpm 8.7 MB/s | 138 kB 00:00 -(36/40): ttmkfdir-3.0.9-54.el8.x86_64.rpm 4.2 MB/s | 62 kB 00:00 -(37/40): tzdata-java-2022d-1.el8.noarch.rpm 11 MB/s | 186 kB 00:00 -(38/40): xorg-x11-font-utils-7.5-41.el8.x86_64. 6.7 MB/s | 104 kB 00:00 -(39/40): xorg-x11-fonts-Type1-7.5-19.el8.noarch 24 MB/s | 522 kB 00:00 -(40/40): java-11-openjdk-headless-11.0.16.1.1-1 77 MB/s | 40 MB 00:00 +(1/106): crypto-policies-scripts-20230731-1.git 862 kB/s | 84 kB 00:00 +(2/106): avahi-libs-0.7-27.el8.x86_64.rpm 602 kB/s | 61 kB 00:00 +(3/106): cpio-2.12-11.el8.x86_64.rpm 1.8 MB/s | 266 kB 00:00 +(4/106): cups-libs-2.2.6-60.el8_10.x86_64.rpm 5.7 MB/s | 435 kB 00:00 +(5/106): dejavu-sans-mono-fonts-2.35-7.el8.noar 5.1 MB/s | 447 kB 00:00 +(6/106): dracut-049-233.git20240115.0.1.el8.x86 7.0 MB/s | 382 kB 00:00 +(7/106): gdk-pixbuf2-2.36.12-6.el8_10.x86_64.rp 12 MB/s | 465 kB 00:00 +(8/106): gettext-libs-0.19.8.1-17.el8.x86_64.rp 9.3 MB/s | 312 kB 00:00 +(9/106): gettext-0.19.8.1-17.el8.x86_64.rpm 16 MB/s | 1.1 MB 00:00 +(10/106): glib-networking-2.56.1-1.1.el8.x86_64 6.0 MB/s | 155 kB 00:00 +(11/106): grub2-common-2.02-156.0.2.el8.noarch. 26 MB/s | 897 kB 00:00 +(12/106): grub2-tools-minimal-2.02-156.0.2.el8. 8.2 MB/s | 215 kB 00:00 +(13/106): grubby-8.40-49.0.2.el8.x86_64.rpm 2.1 MB/s | 50 kB 00:00 +(14/106): grub2-tools-2.02-156.0.2.el8.x86_64.r 26 MB/s | 2.0 MB 00:00 +(15/106): gsettings-desktop-schemas-3.32.0-6.el 19 MB/s | 633 kB 00:00 +(16/106): hardlink-1.3-6.el8.x86_64.rpm 1.1 MB/s | 29 kB 00:00 +(17/106): json-glib-1.4.4-1.el8.x86_64.rpm 5.9 MB/s | 144 kB 00:00 +(18/106): kbd-2.0.4-11.el8.x86_64.rpm 14 MB/s | 390 kB 00:00 +(19/106): kbd-legacy-2.0.4-11.el8.noarch.rpm 17 MB/s | 481 kB 00:00 +(20/106): kbd-misc-2.0.4-11.el8.noarch.rpm 41 MB/s | 1.5 MB 00:00 +(21/106): libcroco-0.6.12-4.el8_2.1.x86_64.rpm 4.7 MB/s | 113 kB 00:00 +(22/106): libgomp-8.5.0-22.0.1.el8_10.x86_64.rp 9.1 MB/s | 218 kB 00:00 +(23/106): libgusb-0.3.0-1.el8.x86_64.rpm 2.1 MB/s | 49 kB 00:00 +(24/106): libkcapi-1.4.0-2.0.1.el8.x86_64.rpm 1.6 MB/s | 52 kB 00:00 +(25/106): libkcapi-hmaccalc-1.4.0-2.0.1.el8.x86 822 kB/s | 31 kB 00:00 +(26/106): libmodman-2.0.1-17.el8.x86_64.rpm 1.6 MB/s | 36 kB 00:00 +(27/106): libpkgconf-1.4.2-1.el8.x86_64.rpm 1.2 MB/s | 35 kB 00:00 +(28/106): libproxy-0.4.15-5.2.el8.x86_64.rpm 3.0 MB/s | 75 kB 00:00 +(29/106): libsoup-2.62.3-5.el8.x86_64.rpm 15 MB/s | 424 kB 00:00 +(30/106): lksctp-tools-1.0.18-3.el8.x86_64.rpm 3.5 MB/s | 100 kB 00:00 +(31/106): memstrack-0.2.5-2.el8.x86_64.rpm 2.2 MB/s | 51 kB 00:00 +(32/106): os-prober-1.74-9.0.1.el8.x86_64.rpm 2.2 MB/s | 51 kB 00:00 +(33/106): pigz-2.4-4.el8.x86_64.rpm 3.5 MB/s | 80 kB 00:00 +(34/106): pkgconf-1.4.2-1.el8.x86_64.rpm 1.7 MB/s | 38 kB 00:00 +(35/106): pkgconf-m4-1.4.2-1.el8.noarch.rpm 761 kB/s | 17 kB 00:00 +(36/106): pkgconf-pkg-config-1.4.2-1.el8.x86_64 691 kB/s | 15 kB 00:00 +(37/106): shared-mime-info-1.9-4.el8.x86_64.rpm 13 MB/s | 328 kB 00:00 +(38/106): systemd-udev-239-78.0.4.el8.x86_64.rp 32 MB/s | 1.6 MB 00:00 +(39/106): xz-5.2.4-4.el8_6.x86_64.rpm 5.2 MB/s | 153 kB 00:00 +(40/106): abattis-cantarell-fonts-0.0.25-6.el8. 6.4 MB/s | 155 kB 00:00 +(41/106): adwaita-cursor-theme-3.28.0-3.el8.noa 22 MB/s | 647 kB 00:00 +(42/106): alsa-lib-1.2.10-2.el8.x86_64.rpm 18 MB/s | 500 kB 00:00 +(43/106): at-spi2-atk-2.26.2-1.el8.x86_64.rpm 3.8 MB/s | 89 kB 00:00 +(44/106): at-spi2-core-2.28.0-1.el8.x86_64.rpm 6.9 MB/s | 169 kB 00:00 +(45/106): atk-2.28.1-1.el8.x86_64.rpm 9.2 MB/s | 272 kB 00:00 +(46/106): cairo-1.15.12-6.el8.x86_64.rpm 24 MB/s | 719 kB 00:00 +(47/106): adwaita-icon-theme-3.28.0-3.el8.noarc 65 MB/s | 11 MB 00:00 +(48/106): cairo-gobject-1.15.12-6.el8.x86_64.rp 914 kB/s | 33 kB 00:00 +(49/106): colord-libs-1.4.2-1.el8.x86_64.rpm 9.5 MB/s | 236 kB 00:00 +(50/106): copy-jdk-configs-4.0-2.el8.noarch.rpm 1.1 MB/s | 30 kB 00:00 +(51/106): dconf-0.28.0-4.0.1.el8.x86_64.rpm 4.4 MB/s | 108 kB 00:00 +(52/106): fribidi-1.0.4-9.el8.x86_64.rpm 3.9 MB/s | 89 kB 00:00 +(53/106): graphite2-1.3.10-10.el8.x86_64.rpm 5.1 MB/s | 122 kB 00:00 +(54/106): gdk-pixbuf2-modules-2.36.12-6.el8_10. 3.6 MB/s | 108 kB 00:00 +(55/106): gtk-update-icon-cache-3.22.30-11.el8. 1.4 MB/s | 32 kB 00:00 +(56/106): harfbuzz-1.7.5-4.el8.x86_64.rpm 11 MB/s | 295 kB 00:00 +(57/106): gtk3-3.22.30-11.el8.x86_64.rpm 68 MB/s | 4.5 MB 00:00 +(58/106): hicolor-icon-theme-0.17-2.el8.noarch. 2.1 MB/s | 48 kB 00:00 +(59/106): java-11-openjdk-11.0.24.0.8-3.0.1.el8 17 MB/s | 475 kB 00:00 +(60/106): jasper-libs-2.0.14-5.el8.x86_64.rpm 5.0 MB/s | 167 kB 00:00 +(61/106): java-11-openjdk-devel-11.0.24.0.8-3.0 61 MB/s | 3.4 MB 00:00 +(62/106): javapackages-filesystem-5.3.0-1.modul 1.2 MB/s | 30 kB 00:00 +(63/106): jbigkit-libs-2.1-14.el8.x86_64.rpm 2.1 MB/s | 55 kB 00:00 +(64/106): lcms2-2.9-2.el8.x86_64.rpm 3.8 MB/s | 164 kB 00:00 +(65/106): libX11-1.6.8-8.el8.x86_64.rpm 20 MB/s | 611 kB 00:00 +(66/106): libX11-common-1.6.8-8.el8.noarch.rpm 6.8 MB/s | 157 kB 00:00 +(67/106): libXau-1.0.9-3.el8.x86_64.rpm 1.6 MB/s | 37 kB 00:00 +(68/106): libXcomposite-0.4.4-14.el8.x86_64.rpm 1.3 MB/s | 28 kB 00:00 +(69/106): libXcursor-1.1.15-3.el8.x86_64.rpm 1.6 MB/s | 36 kB 00:00 +(70/106): libXdamage-1.1.4-14.el8.x86_64.rpm 1.2 MB/s | 27 kB 00:00 +(71/106): libXext-1.3.4-1.el8.x86_64.rpm 2.0 MB/s | 45 kB 00:00 +(72/106): libXfixes-5.0.3-7.el8.x86_64.rpm 1.1 MB/s | 25 kB 00:00 +(73/106): libXft-2.3.3-1.el8.x86_64.rpm 2.9 MB/s | 67 kB 00:00 +(74/106): libXi-1.7.10-1.el8.x86_64.rpm 2.2 MB/s | 49 kB 00:00 +(75/106): libXinerama-1.1.4-1.el8.x86_64.rpm 717 kB/s | 15 kB 00:00 +(76/106): libXrandr-1.5.2-1.el8.x86_64.rpm 1.5 MB/s | 34 kB 00:00 +(77/106): libXrender-0.9.10-7.el8.x86_64.rpm 1.4 MB/s | 33 kB 00:00 +(78/106): libXtst-1.2.3-7.el8.x86_64.rpm 957 kB/s | 22 kB 00:00 +(79/106): java-11-openjdk-headless-11.0.24.0.8- 71 MB/s | 42 MB 00:00 +(80/106): libdatrie-0.2.9-7.el8.x86_64.rpm 274 kB/s | 33 kB 00:00 +(81/106): libepoxy-1.5.8-1.el8.x86_64.rpm 9.1 MB/s | 225 kB 00:00 +(82/106): libfontenc-1.1.3-8.el8.x86_64.rpm 1.5 MB/s | 37 kB 00:00 +(83/106): libthai-0.1.27-2.el8.x86_64.rpm 8.2 MB/s | 203 kB 00:00 +(84/106): libjpeg-turbo-1.5.3-12.el8.x86_64.rpm 5.1 MB/s | 157 kB 00:00 +(85/106): libtiff-4.0.9-32.el8_10.x86_64.rpm 7.8 MB/s | 189 kB 00:00 +(86/106): libwayland-client-1.21.0-1.el8.x86_64 1.7 MB/s | 41 kB 00:00 +(87/106): libwayland-cursor-1.21.0-1.el8.x86_64 1.2 MB/s | 26 kB 00:00 +(88/106): libwayland-egl-1.21.0-1.el8.x86_64.rp 801 kB/s | 19 kB 00:00 +(89/106): libxcb-1.13.1-1.el8.x86_64.rpm 9.7 MB/s | 231 kB 00:00 +(90/106): libxkbcommon-0.9.1-1.el8.x86_64.rpm 5.0 MB/s | 116 kB 00:00 +(91/106): nspr-4.35.0-1.el8_8.x86_64.rpm 6.0 MB/s | 143 kB 00:00 +(92/106): lua-5.3.4-12.el8.x86_64.rpm 5.9 MB/s | 192 kB 00:00 +(93/106): nss-softokn-3.90.0-7.el8_10.x86_64.rp 38 MB/s | 1.2 MB 00:00 +(94/106): nss-3.90.0-7.el8_10.x86_64.rpm 17 MB/s | 750 kB 00:00 +(95/106): nss-softokn-freebl-3.90.0-7.el8_10.x8 14 MB/s | 375 kB 00:00 +(96/106): nss-sysinit-3.90.0-7.el8_10.x86_64.rp 3.2 MB/s | 74 kB 00:00 +(97/106): nss-util-3.90.0-7.el8_10.x86_64.rpm 5.8 MB/s | 139 kB 00:00 +(98/106): pango-1.42.4-8.el8.x86_64.rpm 11 MB/s | 297 kB 00:00 +(99/106): pixman-0.38.4-4.el8.x86_64.rpm 10 MB/s | 256 kB 00:00 +(100/106): rest-0.8.1-2.el8.x86_64.rpm 3.1 MB/s | 70 kB 00:00 +(101/106): ttmkfdir-3.0.9-54.el8.x86_64.rpm 2.5 MB/s | 62 kB 00:00 +(102/106): tzdata-java-2024a-1.0.1.el8.noarch.r 7.4 MB/s | 186 kB 00:00 +(103/106): xkeyboard-config-2.28-1.el8.noarch.r 27 MB/s | 782 kB 00:00 +(104/106): xorg-x11-font-utils-7.5-41.el8.x86_6 3.9 MB/s | 104 kB 00:00 +(105/106): xorg-x11-fonts-Type1-7.5-19.el8.noar 1.3 MB/s | 522 kB 00:00 +(106/106): file-5.33-25.el8.x86_64.rpm 26 kB/s | 77 kB 00:02 -------------------------------------------------------------------------------- -Total 74 MB/s | 50 MB 00:00 +Total 27 MB/s | 86 MB 00:03 Running transaction check Transaction check succeeded. Running transaction test Transaction test succeeded. Running transaction Running scriptlet: copy-jdk-configs-4.0-2.el8.noarch 1/1 - Running scriptlet: java-11-openjdk-headless-1:11.0.16.1.1-1.el8_6.x86_6 1/1 + Running scriptlet: java-11-openjdk-headless-1:11.0.24.0.8-3.0.1.el8.x86 1/1 Preparing : 1/1 - Installing : nspr-4.34.0-3.el8_6.x86_64 1/40 - Running scriptlet: nspr-4.34.0-3.el8_6.x86_64 1/40 - Installing : nss-util-3.79.0-10.el8_6.x86_64 2/40 - Installing : libjpeg-turbo-1.5.3-12.el8.x86_64 3/40 - Installing : nss-softokn-freebl-3.79.0-10.el8_6.x86_64 4/40 - Installing : nss-softokn-3.79.0-10.el8_6.x86_64 5/40 - Installing : tzdata-java-2022d-1.el8.noarch 6/40 - Installing : ttmkfdir-3.0.9-54.el8.x86_64 7/40 - Installing : lua-5.3.4-12.el8.x86_64 8/40 - Installing : copy-jdk-configs-4.0-2.el8.noarch 9/40 - Installing : libfontenc-1.1.3-8.el8.x86_64 10/40 - Installing : libXau-1.0.9-3.el8.x86_64 11/40 - Installing : libxcb-1.13.1-1.el8.x86_64 12/40 - Installing : libX11-common-1.6.8-5.el8.noarch 13/40 - Installing : libX11-1.6.8-5.el8.x86_64 14/40 - Installing : libXext-1.3.4-1.el8.x86_64 15/40 - Installing : libXi-1.7.10-1.el8.x86_64 16/40 - Installing : libXtst-1.2.3-7.el8.x86_64 17/40 - Installing : libXcomposite-0.4.4-14.el8.x86_64 18/40 - Installing : libXrender-0.9.10-7.el8.x86_64 19/40 - Installing : lcms2-2.9-2.el8.x86_64 20/40 - Running scriptlet: lcms2-2.9-2.el8.x86_64 20/40 - Installing : javapackages-filesystem-5.3.0-1.module+el8+5136+7f 21/40 - Installing : graphite2-1.3.10-10.el8.x86_64 22/40 - Installing : harfbuzz-1.7.5-3.el8.x86_64 23/40 - Running scriptlet: harfbuzz-1.7.5-3.el8.x86_64 23/40 - Installing : giflib-5.1.4-3.el8.x86_64 24/40 - Installing : alsa-lib-1.2.6.1-3.el8.x86_64 25/40 - Running scriptlet: alsa-lib-1.2.6.1-3.el8.x86_64 25/40 - Installing : pkgconf-m4-1.4.2-1.el8.noarch 26/40 - Installing : lksctp-tools-1.0.18-3.el8.x86_64 27/40 - Running scriptlet: lksctp-tools-1.0.18-3.el8.x86_64 27/40 - Installing : libpkgconf-1.4.2-1.el8.x86_64 28/40 - Installing : pkgconf-1.4.2-1.el8.x86_64 29/40 - Installing : pkgconf-pkg-config-1.4.2-1.el8.x86_64 30/40 - Installing : xorg-x11-font-utils-1:7.5-41.el8.x86_64 31/40 - Installing : xorg-x11-fonts-Type1-7.5-19.el8.noarch 32/40 - Running scriptlet: xorg-x11-fonts-Type1-7.5-19.el8.noarch 32/40 - Installing : crypto-policies-scripts-20211116-1.gitae470d6.el8. 33/40 - Installing : nss-sysinit-3.79.0-10.el8_6.x86_64 34/40 - Installing : nss-3.79.0-10.el8_6.x86_64 35/40 - Installing : avahi-libs-0.7-20.el8.x86_64 36/40 - Installing : cups-libs-1:2.2.6-45.el8_6.2.x86_64 37/40 - Installing : java-11-openjdk-headless-1:11.0.16.1.1-1.el8_6.x86 38/40 - Running scriptlet: java-11-openjdk-headless-1:11.0.16.1.1-1.el8_6.x86 38/40 - Installing : java-11-openjdk-1:11.0.16.1.1-1.el8_6.x86_64 39/40 - Running scriptlet: java-11-openjdk-1:11.0.16.1.1-1.el8_6.x86_64 39/40 - Installing : java-11-openjdk-devel-1:11.0.16.1.1-1.el8_6.x86_64 40/40 - Running scriptlet: java-11-openjdk-devel-1:11.0.16.1.1-1.el8_6.x86_64 40/40 - Running scriptlet: copy-jdk-configs-4.0-2.el8.noarch 40/40 - Running scriptlet: crypto-policies-scripts-20211116-1.gitae470d6.el8. 40/40 - Running scriptlet: nss-3.79.0-10.el8_6.x86_64 40/40 - Running scriptlet: java-11-openjdk-headless-1:11.0.16.1.1-1.el8_6.x86 40/40 - Running scriptlet: java-11-openjdk-1:11.0.16.1.1-1.el8_6.x86_64 40/40 - Running scriptlet: java-11-openjdk-devel-1:11.0.16.1.1-1.el8_6.x86_64 40/40 - Verifying : avahi-libs-0.7-20.el8.x86_64 1/40 - Verifying : crypto-policies-scripts-20211116-1.gitae470d6.el8. 2/40 - Verifying : cups-libs-1:2.2.6-45.el8_6.2.x86_64 3/40 - Verifying : libpkgconf-1.4.2-1.el8.x86_64 4/40 - Verifying : lksctp-tools-1.0.18-3.el8.x86_64 5/40 - Verifying : pkgconf-1.4.2-1.el8.x86_64 6/40 - Verifying : pkgconf-m4-1.4.2-1.el8.noarch 7/40 - Verifying : pkgconf-pkg-config-1.4.2-1.el8.x86_64 8/40 - Verifying : alsa-lib-1.2.6.1-3.el8.x86_64 9/40 - Verifying : copy-jdk-configs-4.0-2.el8.noarch 10/40 - Verifying : giflib-5.1.4-3.el8.x86_64 11/40 - Verifying : graphite2-1.3.10-10.el8.x86_64 12/40 - Verifying : harfbuzz-1.7.5-3.el8.x86_64 13/40 - Verifying : java-11-openjdk-1:11.0.16.1.1-1.el8_6.x86_64 14/40 - Verifying : java-11-openjdk-devel-1:11.0.16.1.1-1.el8_6.x86_64 15/40 - Verifying : java-11-openjdk-headless-1:11.0.16.1.1-1.el8_6.x86 16/40 - Verifying : javapackages-filesystem-5.3.0-1.module+el8+5136+7f 17/40 - Verifying : lcms2-2.9-2.el8.x86_64 18/40 - Verifying : libX11-1.6.8-5.el8.x86_64 19/40 - Verifying : libX11-common-1.6.8-5.el8.noarch 20/40 - Verifying : libXau-1.0.9-3.el8.x86_64 21/40 - Verifying : libXcomposite-0.4.4-14.el8.x86_64 22/40 - Verifying : libXext-1.3.4-1.el8.x86_64 23/40 - Verifying : libXi-1.7.10-1.el8.x86_64 24/40 - Verifying : libXrender-0.9.10-7.el8.x86_64 25/40 - Verifying : libXtst-1.2.3-7.el8.x86_64 26/40 - Verifying : libfontenc-1.1.3-8.el8.x86_64 27/40 - Verifying : libjpeg-turbo-1.5.3-12.el8.x86_64 28/40 - Verifying : libxcb-1.13.1-1.el8.x86_64 29/40 - Verifying : lua-5.3.4-12.el8.x86_64 30/40 - Verifying : nspr-4.34.0-3.el8_6.x86_64 31/40 - Verifying : nss-3.79.0-10.el8_6.x86_64 32/40 - Verifying : nss-softokn-3.79.0-10.el8_6.x86_64 33/40 - Verifying : nss-softokn-freebl-3.79.0-10.el8_6.x86_64 34/40 - Verifying : nss-sysinit-3.79.0-10.el8_6.x86_64 35/40 - Verifying : nss-util-3.79.0-10.el8_6.x86_64 36/40 - Verifying : ttmkfdir-3.0.9-54.el8.x86_64 37/40 - Verifying : tzdata-java-2022d-1.el8.noarch 38/40 - Verifying : xorg-x11-font-utils-1:7.5-41.el8.x86_64 39/40 - Verifying : xorg-x11-fonts-Type1-7.5-19.el8.noarch 40/40 + Installing : nspr-4.35.0-1.el8_8.x86_64 1/106 + Running scriptlet: nspr-4.35.0-1.el8_8.x86_64 1/106 + Installing : nss-util-3.90.0-7.el8_10.x86_64 2/106 + Installing : libjpeg-turbo-1.5.3-12.el8.x86_64 3/106 + Installing : pixman-0.38.4-4.el8.x86_64 4/106 + Installing : libwayland-client-1.21.0-1.el8.x86_64 5/106 + Installing : atk-2.28.1-1.el8.x86_64 6/106 + Installing : libgomp-8.5.0-22.0.1.el8_10.x86_64 7/106 + Running scriptlet: libgomp-8.5.0-22.0.1.el8_10.x86_64 7/106 + Installing : libcroco-0.6.12-4.el8_2.1.x86_64 8/106 + Running scriptlet: libcroco-0.6.12-4.el8_2.1.x86_64 8/106 + Installing : grub2-common-1:2.02-156.0.2.el8.noarch 9/106 + Installing : gettext-libs-0.19.8.1-17.el8.x86_64 10/106 + Installing : gettext-0.19.8.1-17.el8.x86_64 11/106 + Running scriptlet: gettext-0.19.8.1-17.el8.x86_64 11/106 + Installing : grub2-tools-minimal-1:2.02-156.0.2.el8.x86_64 12/106 + Installing : libwayland-cursor-1.21.0-1.el8.x86_64 13/106 + Installing : jasper-libs-2.0.14-5.el8.x86_64 14/106 + Installing : nss-softokn-freebl-3.90.0-7.el8_10.x86_64 15/106 + Installing : nss-softokn-3.90.0-7.el8_10.x86_64 16/106 + Installing : xkeyboard-config-2.28-1.el8.noarch 17/106 + Installing : libxkbcommon-0.9.1-1.el8.x86_64 18/106 + Installing : tzdata-java-2024a-1.0.1.el8.noarch 19/106 + Installing : ttmkfdir-3.0.9-54.el8.x86_64 20/106 + Installing : lua-5.3.4-12.el8.x86_64 21/106 + Installing : copy-jdk-configs-4.0-2.el8.noarch 22/106 + Installing : libwayland-egl-1.21.0-1.el8.x86_64 23/106 + Installing : libfontenc-1.1.3-8.el8.x86_64 24/106 + Installing : libepoxy-1.5.8-1.el8.x86_64 25/106 + Installing : libdatrie-0.2.9-7.el8.x86_64 26/106 + Running scriptlet: libdatrie-0.2.9-7.el8.x86_64 26/106 + Installing : libthai-0.1.27-2.el8.x86_64 27/106 + Running scriptlet: libthai-0.1.27-2.el8.x86_64 27/106 + Installing : libXau-1.0.9-3.el8.x86_64 28/106 + Installing : libxcb-1.13.1-1.el8.x86_64 29/106 + Installing : libX11-common-1.6.8-8.el8.noarch 30/106 + Installing : libX11-1.6.8-8.el8.x86_64 31/106 + Installing : libXext-1.3.4-1.el8.x86_64 32/106 + Installing : libXrender-0.9.10-7.el8.x86_64 33/106 + Installing : cairo-1.15.12-6.el8.x86_64 34/106 + Installing : libXi-1.7.10-1.el8.x86_64 35/106 + Installing : libXfixes-5.0.3-7.el8.x86_64 36/106 + Installing : libXtst-1.2.3-7.el8.x86_64 37/106 + Installing : libXcomposite-0.4.4-14.el8.x86_64 38/106 + Installing : at-spi2-core-2.28.0-1.el8.x86_64 39/106 + Running scriptlet: at-spi2-core-2.28.0-1.el8.x86_64 39/106 + Installing : at-spi2-atk-2.26.2-1.el8.x86_64 40/106 + Running scriptlet: at-spi2-atk-2.26.2-1.el8.x86_64 40/106 + Installing : libXcursor-1.1.15-3.el8.x86_64 41/106 + Installing : libXdamage-1.1.4-14.el8.x86_64 42/106 + Installing : cairo-gobject-1.15.12-6.el8.x86_64 43/106 + Installing : libXft-2.3.3-1.el8.x86_64 44/106 + Installing : libXrandr-1.5.2-1.el8.x86_64 45/106 + Installing : libXinerama-1.1.4-1.el8.x86_64 46/106 + Installing : lcms2-2.9-2.el8.x86_64 47/106 + Running scriptlet: lcms2-2.9-2.el8.x86_64 47/106 + Installing : jbigkit-libs-2.1-14.el8.x86_64 48/106 + Running scriptlet: jbigkit-libs-2.1-14.el8.x86_64 48/106 + Installing : libtiff-4.0.9-32.el8_10.x86_64 49/106 + Installing : javapackages-filesystem-5.3.0-1.module+el8+5136+ 50/106 + Installing : hicolor-icon-theme-0.17-2.el8.noarch 51/106 + Installing : graphite2-1.3.10-10.el8.x86_64 52/106 + Installing : harfbuzz-1.7.5-4.el8.x86_64 53/106 + Running scriptlet: harfbuzz-1.7.5-4.el8.x86_64 53/106 + Installing : fribidi-1.0.4-9.el8.x86_64 54/106 + Installing : pango-1.42.4-8.el8.x86_64 55/106 + Running scriptlet: pango-1.42.4-8.el8.x86_64 55/106 + Installing : dconf-0.28.0-4.0.1.el8.x86_64 56/106 + Installing : alsa-lib-1.2.10-2.el8.x86_64 57/106 + Running scriptlet: alsa-lib-1.2.10-2.el8.x86_64 57/106 + Installing : adwaita-cursor-theme-3.28.0-3.el8.noarch 58/106 + Installing : adwaita-icon-theme-3.28.0-3.el8.noarch 59/106 + Installing : abattis-cantarell-fonts-0.0.25-6.el8.noarch 60/106 + Installing : xz-5.2.4-4.el8_6.x86_64 61/106 + Installing : shared-mime-info-1.9-4.el8.x86_64 62/106 + Running scriptlet: shared-mime-info-1.9-4.el8.x86_64 62/106 + Installing : gdk-pixbuf2-2.36.12-6.el8_10.x86_64 63/106 + Running scriptlet: gdk-pixbuf2-2.36.12-6.el8_10.x86_64 63/106 + Installing : gdk-pixbuf2-modules-2.36.12-6.el8_10.x86_64 64/106 + Installing : gtk-update-icon-cache-3.22.30-11.el8.x86_64 65/106 + Installing : pkgconf-m4-1.4.2-1.el8.noarch 66/106 + Installing : pigz-2.4-4.el8.x86_64 67/106 + Installing : memstrack-0.2.5-2.el8.x86_64 68/106 + Installing : lksctp-tools-1.0.18-3.el8.x86_64 69/106 + Running scriptlet: lksctp-tools-1.0.18-3.el8.x86_64 69/106 + Installing : libpkgconf-1.4.2-1.el8.x86_64 70/106 + Installing : pkgconf-1.4.2-1.el8.x86_64 71/106 + Installing : pkgconf-pkg-config-1.4.2-1.el8.x86_64 72/106 + Installing : xorg-x11-font-utils-1:7.5-41.el8.x86_64 73/106 + Installing : xorg-x11-fonts-Type1-7.5-19.el8.noarch 74/106 + Running scriptlet: xorg-x11-fonts-Type1-7.5-19.el8.noarch 74/106 + Installing : libmodman-2.0.1-17.el8.x86_64 75/106 + Running scriptlet: libmodman-2.0.1-17.el8.x86_64 75/106 + Installing : libproxy-0.4.15-5.2.el8.x86_64 76/106 + Running scriptlet: libproxy-0.4.15-5.2.el8.x86_64 76/106 + Installing : libkcapi-1.4.0-2.0.1.el8.x86_64 77/106 + Installing : libkcapi-hmaccalc-1.4.0-2.0.1.el8.x86_64 78/106 + Installing : libgusb-0.3.0-1.el8.x86_64 79/106 + Installing : colord-libs-1.4.2-1.el8.x86_64 80/106 + Installing : kbd-misc-2.0.4-11.el8.noarch 81/106 + Installing : kbd-legacy-2.0.4-11.el8.noarch 82/106 + Installing : kbd-2.0.4-11.el8.x86_64 83/106 + Installing : systemd-udev-239-78.0.4.el8.x86_64 84/106 + Running scriptlet: systemd-udev-239-78.0.4.el8.x86_64 84/106 + Installing : os-prober-1.74-9.0.1.el8.x86_64 85/106 + Installing : json-glib-1.4.4-1.el8.x86_64 86/106 + Installing : hardlink-1:1.3-6.el8.x86_64 87/106 + Installing : file-5.33-25.el8.x86_64 88/106 + Installing : dejavu-sans-mono-fonts-2.35-7.el8.noarch 89/106 + Installing : gsettings-desktop-schemas-3.32.0-6.el8.x86_64 90/106 + Installing : glib-networking-2.56.1-1.1.el8.x86_64 91/106 + Installing : libsoup-2.62.3-5.el8.x86_64 92/106 + Installing : rest-0.8.1-2.el8.x86_64 93/106 + Running scriptlet: rest-0.8.1-2.el8.x86_64 93/106 + Installing : cpio-2.12-11.el8.x86_64 94/106 + Installing : dracut-049-233.git20240115.0.1.el8.x86_64 95/106 + Running scriptlet: grub2-tools-1:2.02-156.0.2.el8.x86_64 96/106 + Installing : grub2-tools-1:2.02-156.0.2.el8.x86_64 96/106 + Running scriptlet: grub2-tools-1:2.02-156.0.2.el8.x86_64 96/106 + Installing : grubby-8.40-49.0.2.el8.x86_64 97/106 + Installing : crypto-policies-scripts-20230731-1.git3177e06.el 98/106 + Installing : nss-sysinit-3.90.0-7.el8_10.x86_64 99/106 + Installing : nss-3.90.0-7.el8_10.x86_64 100/106 + Installing : avahi-libs-0.7-27.el8.x86_64 101/106 + Installing : cups-libs-1:2.2.6-60.el8_10.x86_64 102/106 + Installing : java-11-openjdk-headless-1:11.0.24.0.8-3.0.1.el8 103/106 + Running scriptlet: java-11-openjdk-headless-1:11.0.24.0.8-3.0.1.el8 103/106 + Installing : gtk3-3.22.30-11.el8.x86_64 104/106 + Installing : java-11-openjdk-1:11.0.24.0.8-3.0.1.el8.x86_64 105/106 + Running scriptlet: java-11-openjdk-1:11.0.24.0.8-3.0.1.el8.x86_64 105/106 + Installing : java-11-openjdk-devel-1:11.0.24.0.8-3.0.1.el8.x8 106/106 + Running scriptlet: java-11-openjdk-devel-1:11.0.24.0.8-3.0.1.el8.x8 106/106 + Running scriptlet: copy-jdk-configs-4.0-2.el8.noarch 106/106 + Running scriptlet: dconf-0.28.0-4.0.1.el8.x86_64 106/106 + Running scriptlet: crypto-policies-scripts-20230731-1.git3177e06.el 106/106 + Running scriptlet: nss-3.90.0-7.el8_10.x86_64 106/106 + Running scriptlet: java-11-openjdk-headless-1:11.0.24.0.8-3.0.1.el8 106/106 + Running scriptlet: java-11-openjdk-1:11.0.24.0.8-3.0.1.el8.x86_64 106/106 + Running scriptlet: java-11-openjdk-devel-1:11.0.24.0.8-3.0.1.el8.x8 106/106 + Running scriptlet: hicolor-icon-theme-0.17-2.el8.noarch 106/106 + Running scriptlet: adwaita-icon-theme-3.28.0-3.el8.noarch 106/106 + Running scriptlet: shared-mime-info-1.9-4.el8.x86_64 106/106 + Running scriptlet: gdk-pixbuf2-2.36.12-6.el8_10.x86_64 106/106 + Running scriptlet: systemd-udev-239-78.0.4.el8.x86_64 106/106 + Verifying : avahi-libs-0.7-27.el8.x86_64 1/106 + Verifying : cpio-2.12-11.el8.x86_64 2/106 + Verifying : crypto-policies-scripts-20230731-1.git3177e06.el 3/106 + Verifying : cups-libs-1:2.2.6-60.el8_10.x86_64 4/106 + Verifying : dejavu-sans-mono-fonts-2.35-7.el8.noarch 5/106 + Verifying : dracut-049-233.git20240115.0.1.el8.x86_64 6/106 + Verifying : file-5.33-25.el8.x86_64 7/106 + Verifying : gdk-pixbuf2-2.36.12-6.el8_10.x86_64 8/106 + Verifying : gettext-0.19.8.1-17.el8.x86_64 9/106 + Verifying : gettext-libs-0.19.8.1-17.el8.x86_64 10/106 + Verifying : glib-networking-2.56.1-1.1.el8.x86_64 11/106 + Verifying : grub2-common-1:2.02-156.0.2.el8.noarch 12/106 + Verifying : grub2-tools-1:2.02-156.0.2.el8.x86_64 13/106 + Verifying : grub2-tools-minimal-1:2.02-156.0.2.el8.x86_64 14/106 + Verifying : grubby-8.40-49.0.2.el8.x86_64 15/106 + Verifying : gsettings-desktop-schemas-3.32.0-6.el8.x86_64 16/106 + Verifying : hardlink-1:1.3-6.el8.x86_64 17/106 + Verifying : json-glib-1.4.4-1.el8.x86_64 18/106 + Verifying : kbd-2.0.4-11.el8.x86_64 19/106 + Verifying : kbd-legacy-2.0.4-11.el8.noarch 20/106 + Verifying : kbd-misc-2.0.4-11.el8.noarch 21/106 + Verifying : libcroco-0.6.12-4.el8_2.1.x86_64 22/106 + Verifying : libgomp-8.5.0-22.0.1.el8_10.x86_64 23/106 + Verifying : libgusb-0.3.0-1.el8.x86_64 24/106 + Verifying : libkcapi-1.4.0-2.0.1.el8.x86_64 25/106 + Verifying : libkcapi-hmaccalc-1.4.0-2.0.1.el8.x86_64 26/106 + Verifying : libmodman-2.0.1-17.el8.x86_64 27/106 + Verifying : libpkgconf-1.4.2-1.el8.x86_64 28/106 + Verifying : libproxy-0.4.15-5.2.el8.x86_64 29/106 + Verifying : libsoup-2.62.3-5.el8.x86_64 30/106 + Verifying : lksctp-tools-1.0.18-3.el8.x86_64 31/106 + Verifying : memstrack-0.2.5-2.el8.x86_64 32/106 + Verifying : os-prober-1.74-9.0.1.el8.x86_64 33/106 + Verifying : pigz-2.4-4.el8.x86_64 34/106 + Verifying : pkgconf-1.4.2-1.el8.x86_64 35/106 + Verifying : pkgconf-m4-1.4.2-1.el8.noarch 36/106 + Verifying : pkgconf-pkg-config-1.4.2-1.el8.x86_64 37/106 + Verifying : shared-mime-info-1.9-4.el8.x86_64 38/106 + Verifying : systemd-udev-239-78.0.4.el8.x86_64 39/106 + Verifying : xz-5.2.4-4.el8_6.x86_64 40/106 + Verifying : abattis-cantarell-fonts-0.0.25-6.el8.noarch 41/106 + Verifying : adwaita-cursor-theme-3.28.0-3.el8.noarch 42/106 + Verifying : adwaita-icon-theme-3.28.0-3.el8.noarch 43/106 + Verifying : alsa-lib-1.2.10-2.el8.x86_64 44/106 + Verifying : at-spi2-atk-2.26.2-1.el8.x86_64 45/106 + Verifying : at-spi2-core-2.28.0-1.el8.x86_64 46/106 + Verifying : atk-2.28.1-1.el8.x86_64 47/106 + Verifying : cairo-1.15.12-6.el8.x86_64 48/106 + Verifying : cairo-gobject-1.15.12-6.el8.x86_64 49/106 + Verifying : colord-libs-1.4.2-1.el8.x86_64 50/106 + Verifying : copy-jdk-configs-4.0-2.el8.noarch 51/106 + Verifying : dconf-0.28.0-4.0.1.el8.x86_64 52/106 + Verifying : fribidi-1.0.4-9.el8.x86_64 53/106 + Verifying : gdk-pixbuf2-modules-2.36.12-6.el8_10.x86_64 54/106 + Verifying : graphite2-1.3.10-10.el8.x86_64 55/106 + Verifying : gtk-update-icon-cache-3.22.30-11.el8.x86_64 56/106 + Verifying : gtk3-3.22.30-11.el8.x86_64 57/106 + Verifying : harfbuzz-1.7.5-4.el8.x86_64 58/106 + Verifying : hicolor-icon-theme-0.17-2.el8.noarch 59/106 + Verifying : jasper-libs-2.0.14-5.el8.x86_64 60/106 + Verifying : java-11-openjdk-1:11.0.24.0.8-3.0.1.el8.x86_64 61/106 + Verifying : java-11-openjdk-devel-1:11.0.24.0.8-3.0.1.el8.x8 62/106 + Verifying : java-11-openjdk-headless-1:11.0.24.0.8-3.0.1.el8 63/106 + Verifying : javapackages-filesystem-5.3.0-1.module+el8+5136+ 64/106 + Verifying : jbigkit-libs-2.1-14.el8.x86_64 65/106 + Verifying : lcms2-2.9-2.el8.x86_64 66/106 + Verifying : libX11-1.6.8-8.el8.x86_64 67/106 + Verifying : libX11-common-1.6.8-8.el8.noarch 68/106 + Verifying : libXau-1.0.9-3.el8.x86_64 69/106 + Verifying : libXcomposite-0.4.4-14.el8.x86_64 70/106 + Verifying : libXcursor-1.1.15-3.el8.x86_64 71/106 + Verifying : libXdamage-1.1.4-14.el8.x86_64 72/106 + Verifying : libXext-1.3.4-1.el8.x86_64 73/106 + Verifying : libXfixes-5.0.3-7.el8.x86_64 74/106 + Verifying : libXft-2.3.3-1.el8.x86_64 75/106 + Verifying : libXi-1.7.10-1.el8.x86_64 76/106 + Verifying : libXinerama-1.1.4-1.el8.x86_64 77/106 + Verifying : libXrandr-1.5.2-1.el8.x86_64 78/106 + Verifying : libXrender-0.9.10-7.el8.x86_64 79/106 + Verifying : libXtst-1.2.3-7.el8.x86_64 80/106 + Verifying : libdatrie-0.2.9-7.el8.x86_64 81/106 + Verifying : libepoxy-1.5.8-1.el8.x86_64 82/106 + Verifying : libfontenc-1.1.3-8.el8.x86_64 83/106 + Verifying : libjpeg-turbo-1.5.3-12.el8.x86_64 84/106 + Verifying : libthai-0.1.27-2.el8.x86_64 85/106 + Verifying : libtiff-4.0.9-32.el8_10.x86_64 86/106 + Verifying : libwayland-client-1.21.0-1.el8.x86_64 87/106 + Verifying : libwayland-cursor-1.21.0-1.el8.x86_64 88/106 + Verifying : libwayland-egl-1.21.0-1.el8.x86_64 89/106 + Verifying : libxcb-1.13.1-1.el8.x86_64 90/106 + Verifying : libxkbcommon-0.9.1-1.el8.x86_64 91/106 + Verifying : lua-5.3.4-12.el8.x86_64 92/106 + Verifying : nspr-4.35.0-1.el8_8.x86_64 93/106 + Verifying : nss-3.90.0-7.el8_10.x86_64 94/106 + Verifying : nss-softokn-3.90.0-7.el8_10.x86_64 95/106 + Verifying : nss-softokn-freebl-3.90.0-7.el8_10.x86_64 96/106 + Verifying : nss-sysinit-3.90.0-7.el8_10.x86_64 97/106 + Verifying : nss-util-3.90.0-7.el8_10.x86_64 98/106 + Verifying : pango-1.42.4-8.el8.x86_64 99/106 + Verifying : pixman-0.38.4-4.el8.x86_64 100/106 + Verifying : rest-0.8.1-2.el8.x86_64 101/106 + Verifying : ttmkfdir-3.0.9-54.el8.x86_64 102/106 + Verifying : tzdata-java-2024a-1.0.1.el8.noarch 103/106 + Verifying : xkeyboard-config-2.28-1.el8.noarch 104/106 + Verifying : xorg-x11-font-utils-1:7.5-41.el8.x86_64 105/106 + Verifying : xorg-x11-fonts-Type1-7.5-19.el8.noarch 106/106 Installed: - alsa-lib-1.2.6.1-3.el8.x86_64 - avahi-libs-0.7-20.el8.x86_64 + abattis-cantarell-fonts-0.0.25-6.el8.noarch + adwaita-cursor-theme-3.28.0-3.el8.noarch + adwaita-icon-theme-3.28.0-3.el8.noarch + alsa-lib-1.2.10-2.el8.x86_64 + at-spi2-atk-2.26.2-1.el8.x86_64 + at-spi2-core-2.28.0-1.el8.x86_64 + atk-2.28.1-1.el8.x86_64 + avahi-libs-0.7-27.el8.x86_64 + cairo-1.15.12-6.el8.x86_64 + cairo-gobject-1.15.12-6.el8.x86_64 + colord-libs-1.4.2-1.el8.x86_64 copy-jdk-configs-4.0-2.el8.noarch - crypto-policies-scripts-20211116-1.gitae470d6.el8.noarch - cups-libs-1:2.2.6-45.el8_6.2.x86_64 - giflib-5.1.4-3.el8.x86_64 + cpio-2.12-11.el8.x86_64 + crypto-policies-scripts-20230731-1.git3177e06.el8.noarch + cups-libs-1:2.2.6-60.el8_10.x86_64 + dconf-0.28.0-4.0.1.el8.x86_64 + dejavu-sans-mono-fonts-2.35-7.el8.noarch + dracut-049-233.git20240115.0.1.el8.x86_64 + file-5.33-25.el8.x86_64 + fribidi-1.0.4-9.el8.x86_64 + gdk-pixbuf2-2.36.12-6.el8_10.x86_64 + gdk-pixbuf2-modules-2.36.12-6.el8_10.x86_64 + gettext-0.19.8.1-17.el8.x86_64 + gettext-libs-0.19.8.1-17.el8.x86_64 + glib-networking-2.56.1-1.1.el8.x86_64 graphite2-1.3.10-10.el8.x86_64 - harfbuzz-1.7.5-3.el8.x86_64 - java-11-openjdk-1:11.0.16.1.1-1.el8_6.x86_64 - java-11-openjdk-devel-1:11.0.16.1.1-1.el8_6.x86_64 - java-11-openjdk-headless-1:11.0.16.1.1-1.el8_6.x86_64 + grub2-common-1:2.02-156.0.2.el8.noarch + grub2-tools-1:2.02-156.0.2.el8.x86_64 + grub2-tools-minimal-1:2.02-156.0.2.el8.x86_64 + grubby-8.40-49.0.2.el8.x86_64 + gsettings-desktop-schemas-3.32.0-6.el8.x86_64 + gtk-update-icon-cache-3.22.30-11.el8.x86_64 + gtk3-3.22.30-11.el8.x86_64 + hardlink-1:1.3-6.el8.x86_64 + harfbuzz-1.7.5-4.el8.x86_64 + hicolor-icon-theme-0.17-2.el8.noarch + jasper-libs-2.0.14-5.el8.x86_64 + java-11-openjdk-1:11.0.24.0.8-3.0.1.el8.x86_64 + java-11-openjdk-devel-1:11.0.24.0.8-3.0.1.el8.x86_64 + java-11-openjdk-headless-1:11.0.24.0.8-3.0.1.el8.x86_64 javapackages-filesystem-5.3.0-1.module+el8+5136+7ff78f74.noarch + jbigkit-libs-2.1-14.el8.x86_64 + json-glib-1.4.4-1.el8.x86_64 + kbd-2.0.4-11.el8.x86_64 + kbd-legacy-2.0.4-11.el8.noarch + kbd-misc-2.0.4-11.el8.noarch lcms2-2.9-2.el8.x86_64 - libX11-1.6.8-5.el8.x86_64 - libX11-common-1.6.8-5.el8.noarch + libX11-1.6.8-8.el8.x86_64 + libX11-common-1.6.8-8.el8.noarch libXau-1.0.9-3.el8.x86_64 libXcomposite-0.4.4-14.el8.x86_64 + libXcursor-1.1.15-3.el8.x86_64 + libXdamage-1.1.4-14.el8.x86_64 libXext-1.3.4-1.el8.x86_64 + libXfixes-5.0.3-7.el8.x86_64 + libXft-2.3.3-1.el8.x86_64 libXi-1.7.10-1.el8.x86_64 + libXinerama-1.1.4-1.el8.x86_64 + libXrandr-1.5.2-1.el8.x86_64 libXrender-0.9.10-7.el8.x86_64 libXtst-1.2.3-7.el8.x86_64 + libcroco-0.6.12-4.el8_2.1.x86_64 + libdatrie-0.2.9-7.el8.x86_64 + libepoxy-1.5.8-1.el8.x86_64 libfontenc-1.1.3-8.el8.x86_64 + libgomp-8.5.0-22.0.1.el8_10.x86_64 + libgusb-0.3.0-1.el8.x86_64 libjpeg-turbo-1.5.3-12.el8.x86_64 + libkcapi-1.4.0-2.0.1.el8.x86_64 + libkcapi-hmaccalc-1.4.0-2.0.1.el8.x86_64 + libmodman-2.0.1-17.el8.x86_64 libpkgconf-1.4.2-1.el8.x86_64 + libproxy-0.4.15-5.2.el8.x86_64 + libsoup-2.62.3-5.el8.x86_64 + libthai-0.1.27-2.el8.x86_64 + libtiff-4.0.9-32.el8_10.x86_64 + libwayland-client-1.21.0-1.el8.x86_64 + libwayland-cursor-1.21.0-1.el8.x86_64 + libwayland-egl-1.21.0-1.el8.x86_64 libxcb-1.13.1-1.el8.x86_64 + libxkbcommon-0.9.1-1.el8.x86_64 lksctp-tools-1.0.18-3.el8.x86_64 lua-5.3.4-12.el8.x86_64 - nspr-4.34.0-3.el8_6.x86_64 - nss-3.79.0-10.el8_6.x86_64 - nss-softokn-3.79.0-10.el8_6.x86_64 - nss-softokn-freebl-3.79.0-10.el8_6.x86_64 - nss-sysinit-3.79.0-10.el8_6.x86_64 - nss-util-3.79.0-10.el8_6.x86_64 + memstrack-0.2.5-2.el8.x86_64 + nspr-4.35.0-1.el8_8.x86_64 + nss-3.90.0-7.el8_10.x86_64 + nss-softokn-3.90.0-7.el8_10.x86_64 + nss-softokn-freebl-3.90.0-7.el8_10.x86_64 + nss-sysinit-3.90.0-7.el8_10.x86_64 + nss-util-3.90.0-7.el8_10.x86_64 + os-prober-1.74-9.0.1.el8.x86_64 + pango-1.42.4-8.el8.x86_64 + pigz-2.4-4.el8.x86_64 + pixman-0.38.4-4.el8.x86_64 pkgconf-1.4.2-1.el8.x86_64 pkgconf-m4-1.4.2-1.el8.noarch pkgconf-pkg-config-1.4.2-1.el8.x86_64 + rest-0.8.1-2.el8.x86_64 + shared-mime-info-1.9-4.el8.x86_64 + systemd-udev-239-78.0.4.el8.x86_64 ttmkfdir-3.0.9-54.el8.x86_64 - tzdata-java-2022d-1.el8.noarch + tzdata-java-2024a-1.0.1.el8.noarch + xkeyboard-config-2.28-1.el8.noarch xorg-x11-font-utils-1:7.5-41.el8.x86_64 xorg-x11-fonts-Type1-7.5-19.el8.noarch + xz-5.2.4-4.el8_6.x86_64 Complete! -Last metadata expiration check: 0:00:10 ago on Mon 10 Oct 2022 04:06:28 PM UTC. +Last metadata expiration check: 0:00:23 ago on Tue 20 Aug 2024 08:55:14 AM UTC. +Package iproute-6.2.0-5.el8_9.x86_64 is already installed. Dependencies resolved. -============================================================================================== - Package - Arch Version Repository Size -============================================================================================== -Installing: - ords noarch 22.3.0-7.el8 yum.oracle.com_repo_OracleLinux_OL8_oracle_software_x86_64 87 M -Installing dependencies: - lsof x86_64 4.93.2-1.el8 ol8_baseos_latest 253 k +================================================================================ + Package Architecture Version Repository Size +================================================================================ +Upgrading: + iproute x86_64 6.2.0-6.el8_10 ol8_baseos_latest 853 k Transaction Summary -============================================================================================== -Install 2 Packages +================================================================================ +Upgrade 1 Package -Total download size: 87 M -Installed size: 92 M +Total download size: 853 k Downloading Packages: -(1/2): lsof-4.93.2-1.el8.x86_64.rpm 3.0 MB/s | 253 kB 00:00 -(2/2): ords-22.3.0-7.el8.noarch.rpm 66 MB/s | 87 MB 00:01 +iproute-6.2.0-6.el8_10.x86_64.rpm 4.2 MB/s | 853 kB 00:00 -------------------------------------------------------------------------------- -Total 66 MB/s | 87 MB 00:01 +Total 4.2 MB/s | 853 kB 00:00 Running transaction check Transaction check succeeded. Running transaction test Transaction test succeeded. Running transaction Preparing : 1/1 - Installing : lsof-4.93.2-1.el8.x86_64 1/2 - Running scriptlet: ords-22.3.0-7.el8.noarch 2/2 - Installing : ords-22.3.0-7.el8.noarch 2/2 - Running scriptlet: ords-22.3.0-7.el8.noarch 2/2 -INFO: Before starting ORDS service, run the below command as user oracle: - ords --config /etc/ords/config install + Upgrading : iproute-6.2.0-6.el8_10.x86_64 1/2 + Cleanup : iproute-6.2.0-5.el8_9.x86_64 2/2 + Running scriptlet: iproute-6.2.0-5.el8_9.x86_64 2/2 + Verifying : iproute-6.2.0-6.el8_10.x86_64 1/2 + Verifying : iproute-6.2.0-5.el8_9.x86_64 2/2 - Verifying : lsof-4.93.2-1.el8.x86_64 1/2 - Verifying : ords-22.3.0-7.el8.noarch 2/2 - -Installed: - lsof-4.93.2-1.el8.x86_64 ords-22.3.0-7.el8.noarch +Upgraded: + iproute-6.2.0-6.el8_10.x86_64 -Complete! -Last metadata expiration check: 0:00:15 ago on Mon 10 Oct 2022 04:06:28 PM UTC. -Package iproute-5.15.0-4.el8_6.1.x86_64 is already installed. -Dependencies resolved. -Nothing to do. Complete! 24 files removed -Removing intermediate container d38a69d2cc70 - ---> 3a7b8edb327e -Step 5/10 : RUN mkdir -p $ORDS_HOME/doc_root && mkdir -p $ORDS_HOME/error && mkdir -p $ORDS_HOME/secrets && chmod ug+x $ORDS_HOME/*.sh && groupadd -g 54322 dba && usermod -u 54321 -d /home/oracle -g dba -m -s /bin/bash oracle && chown -R oracle:dba $ORDS_HOME && echo "oracle ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers - ---> Running in 1d05951f8252 -Removing intermediate container 1d05951f8252 - ---> 265cb7ab4f2c -Step 6/10 : USER oracle - ---> Running in 180d432ae42d -Removing intermediate container 180d432ae42d - ---> a9caee3d9426 -Step 7/10 : WORKDIR /home/oracle - ---> Running in bf8ac95c724a -Removing intermediate container bf8ac95c724a - ---> 4623d696e603 -Step 8/10 : VOLUME ["$ORDS_HOME/config/ords"] - ---> Running in 3afce627e4c0 -Removing intermediate container 3afce627e4c0 - ---> 914d4ee42ede -Step 9/10 : EXPOSE 8888 - ---> Running in 13460b132c52 -Removing intermediate container 13460b132c52 - ---> 4c9edba5aade -Step 10/10 : CMD $ORDS_HOME/$RUN_FILE - ---> Running in f97b17d8cea4 -Removing intermediate container f97b17d8cea4 - ---> c8e95aadf5e3 -Successfully built c8e95aadf5e3 +Removing intermediate container fe168b01f3ad + ---> 791878694a50 +Step 5/12 : RUN curl -o /tmp/ords-$ORDSVERSION.el8.noarch.rpm https://yum.oracle.com/repo/OracleLinux/OL8/oracle/software/x86_64/getPackage/ords-$ORDSVERSION.el8.noarch.rpm + ---> Running in 59d7143da358 + % Total % Received % Xferd Average Speed Time Time Time Current + Dload Upload Total Spent Left Speed +100 108M 100 108M 0 0 1440k 0 0:01:16 0:01:16 --:--:-- 1578k +Removing intermediate container 59d7143da358 + ---> 17c4534293e5 +Step 6/12 : RUN rpm -ivh /tmp/ords-$ORDSVERSION.el8.noarch.rpm + ---> Running in 84b1cbffdc51 +Verifying... ######################################## +Preparing... ######################################## +Updating / installing... +ords-23.4.0-8.el8 ######################################## +INFO: Before starting ORDS service, run the below command as user oracle: + ords --config /etc/ords/config install +Removing intermediate container 84b1cbffdc51 + ---> 6e7151b79588 +Step 7/12 : RUN mkdir -p $ORDS_HOME/doc_root && mkdir -p $ORDS_HOME/error && mkdir -p $ORDS_HOME/secrets && chmod ug+x $ORDS_HOME/*.sh && groupadd -g 54322 dba && usermod -u 54321 -d /home/oracle -g dba -m -s /bin/bash oracle && chown -R oracle:dba $ORDS_HOME && echo "oracle ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers + ---> Running in 66e5db5f343f +Removing intermediate container 66e5db5f343f + ---> 0523dc897bf4 +Step 8/12 : USER oracle + ---> Running in ffda8495ac77 +Removing intermediate container ffda8495ac77 + ---> 162acd4d0b93 +Step 9/12 : WORKDIR /home/oracle + ---> Running in 8c14310ffbc7 +Removing intermediate container 8c14310ffbc7 + ---> c8dae809e772 +Step 10/12 : VOLUME ["$ORDS_HOME/config/ords"] + ---> Running in ed64548fd997 +Removing intermediate container ed64548fd997 + ---> 22e2c99247b0 +Step 11/12 : EXPOSE 8888 + ---> Running in 921f7c85d61d +Removing intermediate container 921f7c85d61d + ---> e5d503c92224 +Step 12/12 : CMD $ORDS_HOME/$RUN_FILE + ---> Running in cad487298d63 +Removing intermediate container cad487298d63 + ---> fdb17aa242f8 +Successfully built fdb17aa242f8 Successfully tagged oracle/ords-dboper:latest +08:57:18 oracle@mitk01:# diff --git a/docs/multitenant/usecase01/logfiles/cdb_creation.log b/docs/multitenant/usecase01/logfiles/cdb_creation.log new file mode 100644 index 00000000..b4602f54 --- /dev/null +++ b/docs/multitenant/usecase01/logfiles/cdb_creation.log @@ -0,0 +1,357 @@ +/usr/local/go/bin/kubectl logs -f `/usr/local/go/bin/kubectl get pods -n oracle-database-operator-system|grep ords|cut -d ' ' -f 1` -n oracle-database-operator-system +** Copyright (c) 2022 Oracle and/or its affiliates. +** +** The Universal Permissive License (UPL), Version 1.0 +** +** Subject to the condition set forth below, permission is hereby granted to any +** person obtaining a copy of this software, associated documentation and/or data +** (collectively the "Software"), free of charge and under any and all copyright +** rights in the Software, and any and all patent rights owned or freely +** licensable by each licensor hereunder covering either (i) the unmodified +** Software as contributed to or provided by such licensor, or (ii) the Larger +** Works (as defined below), to deal in both +** +** (a) the Software, and +** (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +** one is included with the Software (each a "Larger Work" to which the Software +** is contributed by such licensors), +** +** without restriction, including without limitation the rights to copy, create +** derivative works of, display, perform, and distribute the Software and make, +** use, sell, offer for sale, import, export, have made, and have sold the +** Software and the Larger Work(s), and to sublicense the foregoing rights on +** either these or other terms. +** +** This license is subject to the following condition: +** The above copyright notice and either this complete permission notice or at +** a minimum a reference to the UPL must be included in all copies or +** substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +** SOFTWARE. +ORDSVERSIN:23.4.0-8 +NOT_INSTALLED=2 + SETUP +==================================================== +CONFIG=/etc/ords/config +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:16 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: db.connectionType was set to: customurl in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:18 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: db.customURL was set to: jdbc:oracle:thin:@(DESCRIPTION=(CONNECT_TIMEOUT=90)(RETRY_COUNT=30)(RETRY_DELAY=10)(TRANSPORT_CONNECT_TIMEOUT=70)(LOAD_BALLANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=scan12.testrac.com)(PORT=1521)(IP=V4_ONLY))(LOAD_BALLANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=scan34.testrac.com)(PORT=1521)(IP=V4_ONLY))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=TESTORDS))) in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:20 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: security.requestValidationFunction was set to: false in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:22 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: jdbc.MaxLimit was set to: 100 in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:24 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: jdbc.InitialLimit was set to: 50 in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:25 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The global setting named: error.externalPath was set to: /opt/oracle/ords/error +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:27 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The global setting named: standalone.access.log was set to: /home/oracle +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:29 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The global setting named: standalone.https.port was set to: 8888 +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:31 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The global setting named: standalone.https.cert was set to: /opt/oracle/ords//secrets/tls.crt +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:33 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The global setting named: standalone.https.cert.key was set to: /opt/oracle/ords//secrets/tls.key +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:35 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: restEnabledSql.active was set to: true in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:37 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The global setting named: security.verifySSL was set to: true +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:39 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The global setting named: database.api.enabled was set to: true +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:41 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: plsql.gateway.mode was set to: disabled in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:43 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The global setting named: database.api.management.services.disabled was set to: false +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:45 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: misc.pagination.maxRows was set to: 1000 in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:47 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: db.cdb.adminUser was set to: C##DBAPI_CDB_ADMIN AS SYSDBA in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:49 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: db.cdb.adminUser.password was set to: ****** in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:51 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +Created user welcome in file /etc/ords/config/global/credentials +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:53 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +Oracle REST Data Services - Non-Interactive Install + +Retrieving information... +Completed verifying Oracle REST Data Services schema version 23.4.0.r3461619. +Connecting to database user: ORDS_PUBLIC_USER url: jdbc:oracle:thin:@(DESCRIPTION=(CONNECT_TIMEOUT=90)(RETRY_COUNT=30)(RETRY_DELAY=10)(TRANSPORT_CONNECT_TIMEOUT=70)(LOAD_BALLANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=scan12.testrac.com)(PORT=1521)(IP=V4_ONLY))(LOAD_BALLANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=scan34.testrac.com)(PORT=1521)(IP=V4_ONLY))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=TESTORDS))) +The setting named: db.serviceNameSuffix was set to: in configuration: default +The setting named: db.username was set to: ORDS_PUBLIC_USER in configuration: default +The setting named: db.password was set to: ****** in configuration: default +The setting named: security.requestValidationFunction was set to: ords_util.authorize_plsql_gateway in configuration: default +2024-08-20T07:21:57.563Z INFO Oracle REST Data Services schema version 23.4.0.r3461619 is installed. +2024-08-20T07:21:57.565Z INFO To run in standalone mode, use the ords serve command: +2024-08-20T07:21:57.565Z INFO ords --config /etc/ords/config serve +2024-08-20T07:21:57.565Z INFO Visit the ORDS Documentation to access tutorials, developer guides and more to help you get started with the new ORDS Command Line Interface (http://oracle.com/rest). +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.4 Production on Tue Aug 20 07:21:59 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +2024-08-20T07:21:59.739Z INFO HTTP and HTTP/2 cleartext listening on host: 0.0.0.0 port: 8080 +2024-08-20T07:21:59.741Z INFO HTTPS and HTTPS/2 listening on host: 0.0.0.0 port: 8888 +2024-08-20T07:21:59.765Z INFO Disabling document root because the specified folder does not exist: /etc/ords/config/global/doc_root +2024-08-20T07:21:59.765Z INFO Default forwarding from / to contextRoot configured. +2024-08-20T07:22:05.313Z INFO Configuration properties for: |default|lo| +db.serviceNameSuffix= +java.specification.version=22 +conf.use.wallet=true +database.api.management.services.disabled=false +sun.jnu.encoding=UTF-8 +user.region=US +java.class.path=/opt/oracle/ords/ords.war +java.vm.vendor=Oracle Corporation +standalone.https.cert.key=/opt/oracle/ords//secrets/tls.key +sun.arch.data.model=64 +nashorn.args=--no-deprecation-warning +java.vendor.url=https://java.oracle.com/ +resource.templates.enabled=false +user.timezone=UTC +java.vm.specification.version=22 +os.name=Linux +sun.java.launcher=SUN_STANDARD +user.country=US +sun.boot.library.path=/usr/java/jdk-22/lib +sun.java.command=/opt/oracle/ords/ords.war --config /etc/ords/config serve --port 8888 --secure +jdk.debug=release +sun.cpu.endian=little +user.home=/home/oracle +oracle.dbtools.launcher.executable.jar.path=/opt/oracle/ords/ords.war +user.language=en +db.cdb.adminUser.password=****** +java.specification.vendor=Oracle Corporation +java.version.date=2024-07-16 +database.api.enabled=true +java.home=/usr/java/jdk-22 +db.username=ORDS_PUBLIC_USER +file.separator=/ +java.vm.compressedOopsMode=32-bit +line.separator= + +restEnabledSql.active=true +java.specification.name=Java Platform API Specification +java.vm.specification.vendor=Oracle Corporation +java.awt.headless=true +standalone.https.cert=/opt/oracle/ords//secrets/tls.crt +db.password=****** +sun.management.compiler=HotSpot 64-Bit Tiered Compilers +security.requestValidationFunction=ords_util.authorize_plsql_gateway +misc.pagination.maxRows=1000 +java.runtime.version=22.0.2+9-70 +user.name=oracle +error.externalPath=/opt/oracle/ords/error +stdout.encoding=UTF-8 +path.separator=: +db.cdb.adminUser=C##DBAPI_CDB_ADMIN AS SYSDBA +os.version=5.4.17-2136.329.3.1.el7uek.x86_64 +java.runtime.name=Java(TM) SE Runtime Environment +file.encoding=UTF-8 +plsql.gateway.mode=disabled +security.verifySSL=true +standalone.https.port=8888 +java.vm.name=Java HotSpot(TM) 64-Bit Server VM +java.vendor.url.bug=https://bugreport.java.com/bugreport/ +java.io.tmpdir=/tmp +oracle.dbtools.cmdline.ShellCommand=ords +java.version=22.0.2 +user.dir=/home/oracle +os.arch=amd64 +java.vm.specification.name=Java Virtual Machine Specification +jdbc.MaxLimit=100 +oracle.dbtools.cmdline.home=/opt/oracle/ords +native.encoding=UTF-8 +java.library.path=/usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib +java.vendor=Oracle Corporation +java.vm.info=mixed mode, sharing +stderr.encoding=UTF-8 +java.vm.version=22.0.2+9-70 +sun.io.unicode.encoding=UnicodeLittle +jdbc.InitialLimit=50 +db.connectionType=customurl +java.class.version=66.0 +db.customURL=jdbc:oracle:thin:@(DESCRIPTION=(CONNECT_TIMEOUT=90)(RETRY_COUNT=30)(RETRY_DELAY=10)(TRANSPORT_CONNECT_TIMEOUT=70)(LOAD_BALLANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=scan12.testrac.com)(PORT=1521)(IP=V4_ONLY))(LOAD_BALLANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=scan34.testrac.com)(PORT=1521)(IP=V4_ONLY))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=TESTORDS))) +standalone.access.log=/home/oracle + +2024-08-20T07:22:09.268Z INFO + +Mapped local pools from /etc/ords/config/databases: + /ords/ => default => VALID + + +2024-08-20T07:22:09.414Z INFO Oracle REST Data Services initialized +Oracle REST Data Services version : 23.4.0.r3461619 +Oracle REST Data Services server info: jetty/10.0.18 +Oracle REST Data Services java info: Java HotSpot(TM) 64-Bit Server VM 22.0.2+9-70 + diff --git a/docs/multitenant/usecase01/logfiles/openssl_execution.log b/docs/multitenant/usecase01/logfiles/openssl_execution.log index 30a1c5d4..e3915a21 100644 --- a/docs/multitenant/usecase01/logfiles/openssl_execution.log +++ b/docs/multitenant/usecase01/logfiles/openssl_execution.log @@ -1,22 +1,19 @@ +CREATING TLS CERTIFICATES /usr/bin/openssl genrsa -out ca.key 2048 -Generating RSA private key, 2048 bit long modulus -......................................................................................................................................................................................+++ -...................................+++ -e is 65537 (0x10001) -/usr/bin/openssl req -new -x509 -days 365 -key ca.key -subj "/C=CN/ST=GD/L=SZ/O=oracle, Inc./CN=oracle Root CA" -out ca.crt -/usr/bin/openssl req -newkey rsa:2048 -nodes -keyout tls.key -subj "/C=CN/ST=GD/L=SZ/O=oracle, Inc./CN=cdb-dev-ords" -out server.csr -Generating a 2048 bit RSA private key -...................................+++ -........................................+++ +Generating RSA private key, 2048 bit long modulus (2 primes) +......................+++++ +..................................................+++++ +e is 65537 (0x010001) +/usr/bin/openssl req -new -x509 -days 365 -key ca.key -subj "/C=US/ST=California/L=SanFrancisco/O=oracle /CN=cdb-dev-ords.oracle-database-operator-system /CN=localhost Root CA " -out ca.crt +/usr/bin/openssl req -newkey rsa:2048 -nodes -keyout tls.key -subj "/C=US/ST=California/L=SanFrancisco/O=oracle /CN=cdb-dev-ords.oracle-database-operator-system /CN=localhost" -out server.csr +Generating a RSA private key +...........+++++ +...........................................+++++ writing new private key to 'tls.key' ----- -/usr/bin/echo "subjectAltName=DNS:cdb-dev-ords,DNS:www.example.com" > extfile.txt +/usr/bin/echo "subjectAltName=DNS:cdb-dev-ords.oracle-database-operator-system,DNS:www.example.com" > extfile.txt /usr/bin/openssl x509 -req -extfile extfile.txt -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out tls.crt Signature ok -subject=/C=CN/ST=GD/L=SZ/O=oracle, Inc./CN=cdb-dev-ords +subject=C = US, ST = California, L = SanFrancisco, O = "oracle ", CN = "cdb-dev-ords.oracle-database-operator-system ", CN = localhost Getting CA Private Key -/usr/bin/kubectl create secret tls db-tls --key="tls.key" --cert="tls.crt" -n oracle-database-operator-system -secret/db-tls created -/usr/bin/kubectl create secret generic db-ca --from-file="ca.crt" -n oracle-database-operator-system -secret/db-ca created diff --git a/docs/multitenant/usecase01/logfiles/ordsconfig.log b/docs/multitenant/usecase01/logfiles/ordsconfig.log index ad5e7bab..b787b752 100644 --- a/docs/multitenant/usecase01/logfiles/ordsconfig.log +++ b/docs/multitenant/usecase01/logfiles/ordsconfig.log @@ -1,35 +1,39 @@ -: Release 22.3 Production on Tue Oct 11 12:51:50 2022 +ORDS: Release 23.4 Production on Tue Aug 20 07:48:44 2024 -Copyright (c) 2010, 2022, Oracle. +Copyright (c) 2010, 2024, Oracle. Configuration: /etc/ords/config/ Database pool: default -Setting Value Source ------------------------------------------ -------------------------------------- ----------- -database.api.enabled true Global -database.api.management.services.disabled false Global -db.cdb.adminUser C##DBAPI_CDB_ADMIN AS SYSDBA Pool -db.cdb.adminUser.password ****** Pool Wallet -db.connectionType basic Pool -db.hostname racnode1.testrac.com Pool -db.password ****** Pool Wallet -db.port 1521 Pool -db.serviceNameSuffix Pool -db.servicename TESTORDS Pool -db.username ORDS_PUBLIC_USER Pool -error.externalPath /opt/oracle/ords/error Global -jdbc.InitialLimit 50 Pool -jdbc.MaxLimit 100 Pool -misc.pagination.maxRows 1000 Pool -plsql.gateway.mode proxied Pool -restEnabledSql.active true Pool -security.requestValidationFunction wwv_flow_epg_include_modules.authorize Pool -security.verifySSL true Global -standalone.access.log /home/oracle Global -standalone.https.cert /opt/oracle/ords//secrets/tls.crt Global -standalone.https.cert.key /opt/oracle/ords//secrets/tls.key Global -standalone.https.port 8888 Global +Setting Value Source +----------------------------------------- -------------------------------------------------- ----------- +database.api.enabled true Global +database.api.management.services.disabled false Global +db.cdb.adminUser C##DBAPI_CDB_ADMIN AS SYSDBA Pool +db.cdb.adminUser.password ****** Pool Wallet +db.connectionType customurl Pool +db.customURL jdbc:oracle:thin:@(DESCRIPTION=(CONNECT_TIMEOUT=90 Pool + )(RETRY_COUNT=30)(RETRY_DELAY=10)(TRANSPORT_CONNEC + T_TIMEOUT=70)(LOAD_BALLANCE=ON)(ADDRESS=(PROTOCOL= + TCP)(HOST=scan12.testrac.com)(PORT=1521)(IP=V4_ONL + Y))(LOAD_BALLANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST= + scan34.testrac.com)(PORT=1521)(IP=V4_ONLY))(CONNEC + T_DATA=(SERVER=DEDICATED)(SERVICE_NAME=TESTORDS))) +db.password ****** Pool Wallet +db.serviceNameSuffix Pool +db.username ORDS_PUBLIC_USER Pool +error.externalPath /opt/oracle/ords/error Global +jdbc.InitialLimit 50 Pool +jdbc.MaxLimit 100 Pool +misc.pagination.maxRows 1000 Pool +plsql.gateway.mode disabled Pool +restEnabledSql.active true Pool +security.requestValidationFunction ords_util.authorize_plsql_gateway Pool +security.verifySSL true Global +standalone.access.log /home/oracle Global +standalone.https.cert /opt/oracle/ords//secrets/tls.crt Global +standalone.https.cert.key /opt/oracle/ords//secrets/tls.key Global +standalone.https.port 8888 Global diff --git a/docs/multitenant/usecase01/logfiles/tagandpush.log b/docs/multitenant/usecase01/logfiles/tagandpush.log new file mode 100644 index 00000000..232d5bb2 --- /dev/null +++ b/docs/multitenant/usecase01/logfiles/tagandpush.log @@ -0,0 +1,14 @@ +/usr/bin/docker tag oracle/ords-dboper:latest [.......]/ords-dboper:latest + +/usr/bin/docker push [your container registry]/ords-dboper:latest +The push refers to repository [your container registry] +0405aac3af1c: Pushed +6be46e8e1e21: Pushed +c9884830a66d: Pushed +a46244557bb9: Pushing [===========================> ] 261.8MB/469.9MB +f988845e261e: Pushed +fe07ec0b1f5a: Layer already exists +2ac63de5f950: Layer already exists +386cd7a64c01: Layer already exists +826c69252b8b: Layer already exists + diff --git a/docs/multitenant/usecase01/logfiles/testapi.log b/docs/multitenant/usecase01/logfiles/testapi.log index 4c95b457..cb42ecc3 100644 --- a/docs/multitenant/usecase01/logfiles/testapi.log +++ b/docs/multitenant/usecase01/logfiles/testapi.log @@ -1,6 +1,7 @@ -* Trying 127.0.0.1... +kubectl exec -it `kubectl get pods -n oracle-database-operator-system|grep ords|cut -d ' ' -f 1` -n oracle-database-operator-system -i -t -- /usr/bin/curl -sSkv -k -X GET https://localhost:8888/ords/_/db-api/stable/metadata-catalog/ +* Trying ::1... * TCP_NODELAY set -* Connected to localhost (127.0.0.1) port 8888 (#0) +* Connected to localhost (::1) port 8888 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: @@ -19,10 +20,10 @@ * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384 * ALPN, server accepted to use h2 * Server certificate: -* subject: C=CN; ST=GD; L=SZ; O=oracle, Inc.; CN=cdb-dev-ords -* start date: Oct 11 07:44:38 2022 GMT -* expire date: Oct 11 07:44:38 2023 GMT -* issuer: C=CN; ST=GD; L=SZ; O=oracle, Inc.; CN=oracle Root CA +* subject: C=US; ST=California; L=SanFrancisco; O=oracle ; CN=cdb-dev-ords.oracle-database-operator-system ; CN=localhost +* start date: Aug 20 07:14:04 2024 GMT +* expire date: Aug 20 07:14:04 2025 GMT +* issuer: C=US; ST=California; L=SanFrancisco; O=oracle ; CN=cdb-dev-ords.oracle-database-operator-system ; CN=localhost Root CA * SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway. * Using HTTP2, server supports multi-use * Connection state changed (HTTP/2 confirmed) @@ -30,7 +31,7 @@ * TLSv1.3 (OUT), TLS app data, [no content] (0): * TLSv1.3 (OUT), TLS app data, [no content] (0): * TLSv1.3 (OUT), TLS app data, [no content] (0): -* Using Stream ID: 1 (easy handle 0x564be7b0b970) +* Using Stream ID: 1 (easy handle 0x55d14a7dea90) * TLSv1.3 (OUT), TLS app data, [no content] (0): > GET /ords/_/db-api/stable/metadata-catalog/ HTTP/2 > Host: localhost:8888 @@ -46,4 +47,16 @@ * TLSv1.3 (OUT), TLS app data, [no content] (0): * TLSv1.3 (IN), TLS app data, [no content] (0): * TLSv1.3 (IN), TLS app data, [no content] (0): - +< HTTP/2 200 +< content-type: application/json +< +* TLSv1.3 (IN), TLS handshake, [no content] (0): +* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4): +* TLSv1.3 (IN), TLS app data, [no content] (0): +* TLSv1.3 (IN), TLS app data, [no content] (0): +* TLSv1.3 (IN), TLS app data, [no content] (0): +* TLSv1.3 (IN), TLS app data, [no content] (0): +* TLSv1.3 (IN), TLS app data, [no content] (0): +* TLSv1.3 (IN), TLS app data, [no content] (0): +* Connection #0 to host localhost left intact +{"items":[{"name":"default","links":[{"rel":"canonical","href":"https://localhost:8888/ords/_/db-api/stable/metadata-catalog/openapi.json","mediaType":"application/vnd.oai.openapi+json;version=3.0"}]}],"links":[{"rel":"self","href":"https://localhost:8888/ords/_/db-api/stable/metadata-catalog/"},{"rel":"describes","href":"https://localhost:8888/ords/_/db-api/stable/"}]} diff --git a/docs/multitenant/usecase01/makefile b/docs/multitenant/usecase01/makefile index 0a96d1e7..d4176c75 100644 --- a/docs/multitenant/usecase01/makefile +++ b/docs/multitenant/usecase01/makefile @@ -42,10 +42,16 @@ # +-----------------------------+---------------------------------------------+ # |tde_secret.yaml | Secret file for the tablepsace enc. | # +-----------------------------+---------------------------------------------+ -# |cdb.yaml | Rest server pod creation | +# |cdb_create.yaml | Rest server pod creation | # +-----------------------------+---------------------------------------------+ -# |pdb.yaml | Pluggable database creation | +# |pdb_create.yaml | Pluggable database creation | # +-----------------------------+---------------------------------------------+ +# |pdb_close.yaml | Close pluggable database | +# +-----------------------------+---------------------------------------------+ +# |pdb_open.yaml | Open pluggable database | +# +-----------------------------+---------------------------------------------+ +# |pdb_map.yaml | Map an existing pdb | +# +-----------------------------+---------------------------------------------+ # |oracle-database-operator.yaml| Database operator | # +-----------------------------+---------------------------------------------+ # |Dockerfiles | Dockerfile for CBD | @@ -94,6 +100,17 @@ # | | +---------------------------------------------+ # | +---> checkpdb | Monitor PDB status | # +-----------------------------+---------------------------------------------+ +# |step11 | Close pluggable database | +# +-----------------------------+---------------------------------------------+ +# |step12 | Open pluggable database | +# +-----------------------------+---------------------------------------------+ +# |step13 | Map pluggable database | +# +-----------------------------+---------------------------------------------+ +# | Before testing step13 delete the crd: | +# | kubectl delete pdb pdb1 -n oracle-database-operator-system | +# +---------------------------------------------------------------------------+ +# |step14 | delete pdb | +# +-----------------------------+---------------------------------------------+ # | DIAGNOSTIC TARGETS | # +-----------------------------+---------------------------------------------+ # | dump | Dump pods info into a file | @@ -120,20 +137,28 @@ URLPATH=/_/db-api/stable/database/pdbs/ OPENSSL=/usr/bin/openssl ORDSPORT=8888 MAKE=/usr/bin/make -DOCKERFILE=Dockerfile +DOCKERFILE=../../../ords/Dockerfile +RUNSCRIPT=../../../ords/runOrdsSSL.sh +ORDSIMGDIR=../../../ords RM=/usr/bin/rm +CP=/usr/bin/cp ECHO=/usr/bin/echo NAMESPACE=oracle-database-operator-system CERTMANAGER=https://github.com/jetstack/cert-manager/releases/latest/download/cert-manager.yaml CDB_SECRET=cdb_secret.yaml PDB_SECRET=pdb_secret.yaml TDE_SECRET=tde_secret.yaml -CDB=cdb.yaml -PDB=pdb.yaml +CDB=cdb_create.yaml +PDB=pdb_create.yaml +PDB_CLOSE=pdb_close.yaml +PDB_OPEN=pdb_open.yaml +PDB_MAP=pdb_map.yaml SKEY=tls.key SCRT=tls.crt CART=ca.crt COMPANY=oracle +LOCALHOST=localhost +RESTPREFIX=cdb-dev step1: createimage step2: tagimage @@ -145,23 +170,16 @@ step7: tlssecret step8: dbsecret step9: cdb step10: pdb +step11: close +step12: open +step13: map +step14: delete checkstep9: checkcdb createimage: - @echo "BUILDING CDB IMAGES" - @if [[ ! -f ./Dockerfile ]]; \ - then\ - echo "DOCKERFILE DOES NOT EXISTS";\ - exit 1; \ - fi; - @if [[ ! -f ../runOrdsSSL.sh ]]; \ - then\ - echo "DOCKERFILE DOES NOT EXISTS";\ - exit 1; \ - fi; - $(DOCKER) build -t $(IMAGE) . + $(DOCKER) build -t $(IMAGE) $(ORDSIMGDIR) tagimage: @echo "TAG IMAGE" @@ -179,12 +197,19 @@ dboperator: @echo "ORACLE DATABASE OPERATOR" $(KUBECTL) apply -f $(DBOPERATOR) + +#C: Country +#ST: State +#L: locality (city) +#O: Organization Name Organization Unit +#CN: Common Name + tlscert: - @echo "CREATING TLS CERTIFICATES" + @echo "CREATING TLS CERTIFICATES" $(OPENSSL) genrsa -out ca.key 2048 - $(OPENSSL) req -new -x509 -days 365 -key ca.key -subj "/C=CN/ST=GD/L=SZ/O=$(COMPANY), Inc./CN=$(COMPANY) Root CA" -out ca.crt - $(OPENSSL) req -newkey rsa:2048 -nodes -keyout $(SKEY) -subj "/C=CN/ST=GD/L=SZ/O=$(COMPANY), Inc./CN=cdb-dev-$(REST_SERVER)" -out server.csr - $(ECHO) "subjectAltName=DNS:cdb-dev-$(REST_SERVER),DNS:www.example.com" > extfile.txt + $(OPENSSL) req -new -x509 -days 365 -key ca.key -subj "/C=US/ST=California/L=SanFrancisco/O=$(COMPANY) /CN=$(RESTPREFIX)-$(REST_SERVER).$(NAMESPACE) /CN=$(LOCALHOST) Root CA " -out ca.crt + $(OPENSSL) req -newkey rsa:2048 -nodes -keyout $(SKEY) -subj "/C=US/ST=California/L=SanFrancisco/O=$(COMPANY) /CN=$(RESTPREFIX)-$(REST_SERVER).$(NAMESPACE) /CN=$(LOCALHOST)" -out server.csr + $(ECHO) "subjectAltName=DNS:$(RESTPREFIX)-$(REST_SERVER).$(NAMESPACE),DNS:www.example.com" > extfile.txt $(OPENSSL) x509 -req -extfile extfile.txt -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out $(SCRT) tlssecret: @@ -208,9 +233,21 @@ checkcdb: pdb: $(KUBECTL) apply -f $(PDB) +close: + $(KUBECTL) apply -f $(PDB_CLOSE) + +open: + $(KUBECTL) apply -f $(PDB_OPEN) + +map: + $(KUBECTL) apply -f $(PDB_MAP) + checkpdb: $(KUBECTL) get pdbs -n $(NAMESPACE) +delete: + $(KUBECTL) apply -f pdb_delete.yaml + dump: @$(eval TMPSP := $(shell date "+%y%m%d%H%M%S" )) @$(eval DIAGFILE := ./opdmp.$(TMPSP)) diff --git a/docs/multitenant/usecase01/oracle-database-operator.yaml b/docs/multitenant/usecase01/oracle-database-operator.yaml new file mode 120000 index 00000000..d5bae7bc --- /dev/null +++ b/docs/multitenant/usecase01/oracle-database-operator.yaml @@ -0,0 +1 @@ +../../../oracle-database-operator.yaml \ No newline at end of file diff --git a/docs/multitenant/usecase01/pdb_close.yaml b/docs/multitenant/usecase01/pdb_close.yaml new file mode 100644 index 00000000..5917d33a --- /dev/null +++ b/docs/multitenant/usecase01/pdb_close.yaml @@ -0,0 +1,44 @@ +apiVersion: database.oracle.com/v1alpha1 +kind: PDB +metadata: + name: pdb1 + namespace: oracle-database-operator-system + labels: + cdb: cdb-dev +spec: + cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" + cdbName: "DB12" + pdbName: "pdbdev" + adminName: + secret: + secretName: "pdb1-secret" + key: "sysadmin_user" + adminPwd: + secret: + secretName: "pdb1-secret" + key: "sysadmin_pwd" + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + pdbState: "CLOSE" + modifyOption: "IMMEDIATE" + action: "Modify" + diff --git a/docs/multitenant/usecase01/pdb_create.yaml b/docs/multitenant/usecase01/pdb_create.yaml new file mode 100644 index 00000000..be3581ad --- /dev/null +++ b/docs/multitenant/usecase01/pdb_create.yaml @@ -0,0 +1,47 @@ +apiVersion: database.oracle.com/v1alpha1 +kind: PDB +metadata: + name: pdb1 + namespace: oracle-database-operator-system + labels: + cdb: cdb-dev +spec: + cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" + cdbName: "DB12" + pdbName: "pdbdev" + adminName: + secret: + secretName: "pdb1-secret" + key: "sysadmin_user" + adminPwd: + secret: + secretName: "pdb1-secret" + key: "sysadmin_pwd" + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + fileNameConversions: "NONE" + tdeImport: false + totalSize: "1G" + tempSize: "100M" + action: "Create" + assertivePdbDeletion: true + diff --git a/docs/multitenant/usecase01/pdb_delete.yaml b/docs/multitenant/usecase01/pdb_delete.yaml new file mode 100644 index 00000000..c22b546a --- /dev/null +++ b/docs/multitenant/usecase01/pdb_delete.yaml @@ -0,0 +1,34 @@ +apiVersion: database.oracle.com/v1alpha1 +kind: PDB +metadata: + name: pdb1 + namespace: oracle-database-operator-system + labels: + cdb: cdb-dev +spec: + cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" + pdbName: "pdbdev" + action: "Delete" + dropAction: "INCLUDING" + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + diff --git a/docs/multitenant/usecase01/pdb_map.yaml b/docs/multitenant/usecase01/pdb_map.yaml new file mode 100644 index 00000000..3300a7fa --- /dev/null +++ b/docs/multitenant/usecase01/pdb_map.yaml @@ -0,0 +1,45 @@ +apiVersion: database.oracle.com/v1alpha1 +kind: PDB +metadata: + name: pdb1 + namespace: oracle-database-operator-system + labels: + cdb: cdb-dev +spec: + cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" + cdbName: "DB12" + pdbName: "pdbdev" + adminName: + secret: + secretName: "pdb1-secret" + key: "sysadmin_user" + adminPwd: + secret: + secretName: "pdb1-secret" + key: "sysadmin_pwd" + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + fileNameConversions: "NONE" + totalSize: "1G" + tempSize: "100M" + action: "Map" + assertivePdbDeletion: true diff --git a/docs/multitenant/usecase01/pdb_open.yaml b/docs/multitenant/usecase01/pdb_open.yaml new file mode 100644 index 00000000..25fdccc4 --- /dev/null +++ b/docs/multitenant/usecase01/pdb_open.yaml @@ -0,0 +1,43 @@ +apiVersion: database.oracle.com/v1alpha1 +kind: PDB +metadata: + name: pdb1 + namespace: oracle-database-operator-system + labels: + cdb: cdb-dev +spec: + cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" + cdbName: "DB12" + pdbName: "pdbdev" + adminName: + secret: + secretName: "pdb1-secret" + key: "sysadmin_user" + adminPwd: + secret: + secretName: "pdb1-secret" + key: "sysadmin_pwd" + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + action: "Modify" + pdbState: "OPEN" + modifyOption: "READ WRITE" diff --git a/docs/multitenant/usecase01/pdb_secret.yaml b/docs/multitenant/usecase01/pdb_secret.yaml new file mode 100644 index 00000000..60d95d76 --- /dev/null +++ b/docs/multitenant/usecase01/pdb_secret.yaml @@ -0,0 +1,16 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +apiVersion: v1 +kind: Secret +metadata: + name: pdb1-secret + namespace: oracle-database-operator-system +type: Opaque +data: + sysadmin_user: ".....base64 encoded password...." + sysadmin_pwd: ".....base64 encoded password...." + webserver_user: ".....base64 encoded password...." + webserver_pwd: ".....base64 encoded password...." + diff --git a/docs/multitenant/usecase01/server.csr b/docs/multitenant/usecase01/server.csr new file mode 100644 index 00000000..e308d301 --- /dev/null +++ b/docs/multitenant/usecase01/server.csr @@ -0,0 +1,18 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIC3TCCAcUCAQAwgZcxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh +MRUwEwYDVQQHDAxTYW5GcmFuY2lzY28xEDAOBgNVBAoMB29yYWNsZSAxNjA0BgNV +BAMMLWNkYi1kZXYtb3Jkcy5vcmFjbGUtZGF0YWJhc2Utb3BlcmF0b3Itc3lzdGVt +IDESMBAGA1UEAwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAm9nlNSQNsPTVqH57MkWKZEyaVtzVKQ8Z3oDK6hWXfB24p0jVj6sTOJkf +NVAxnqmU8DpW3odpbU6qWe/n+B5vJpqdXUGdsq9NKyus2fGb/xf1UnskpA2FUuWZ +o3upyCFxDAOvE4eZUzlxIn+54XXaNAdQiU9E8VXPr5YxrvZ15T/xCXLtJPs/RCOF +cJ8+gvZGcjMbdP16auJDVWZzBaur3eKbiHN7LXNCCRzGO++dv0kGY8vH7MyFfgp3 +qYBiSHS3WDiFUJjYIvfa8lLfP1hnlCyHn8TnU9gjGjmd1YcccSKqWIAT24wPUKVU +Lme4n91jxDPp7g8nRtDw0Smj9gYCtQIDAQABoAAwDQYJKoZIhvcNAQELBQADggEB +AGOG/9IJJRvT2JLcuzE5Arai1XHc6Jh65iuDRqXQav47Bz38FFF2gZNO69gzDmhq +6k7tie+5bPcAHuuJZ0dAa71a9SLjKl+XNkkI0vS6te6OK3DCVUoMqNCk5VdwrJw0 +RORbKUwgLEG6mu80Gc/6wCdeR/36hoYTMeNPjm6M9e+X5ppsXqxCNsgDxasJFT82 +FejuJE2sZ6RCradlDToUHNS1dMLoW0WAIISqOmrDvEI6snm9ZZr3Sxo1auEtpI6v +NllBM4AgEghy/2mAtke+By4WHCfXBpxEGv9S7ATqJHYrR5Qa3nwx0eojWW1vmn0/ +aEzslX1tAH6oz2jA6QZ0sNo= +-----END CERTIFICATE REQUEST----- diff --git a/docs/multitenant/provisioning/pdb_secret.yaml b/docs/multitenant/usecase01/tde_secret.yaml similarity index 67% rename from docs/multitenant/provisioning/pdb_secret.yaml rename to docs/multitenant/usecase01/tde_secret.yaml index cf385dda..7cf66c03 100644 --- a/docs/multitenant/provisioning/pdb_secret.yaml +++ b/docs/multitenant/usecase01/tde_secret.yaml @@ -5,9 +5,13 @@ apiVersion: v1 kind: Secret metadata: - name: pdb1-secret + name: tde1-secret namespace: oracle-database-operator-system -type: Opaque -data: - sysadmin_user: "[ base64 encode values ]" - sysadmin_pwd: "[base64 encode values ]" +type: Opaque +data: + tdepassword: "bW1hbHZlenoK" + tdesecret: "bW1hbHZlenoK" + + + + diff --git a/docs/multitenant/usecase01/tls.crt b/docs/multitenant/usecase01/tls.crt new file mode 100644 index 00000000..6bf8aef4 --- /dev/null +++ b/docs/multitenant/usecase01/tls.crt @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEFDCCAvygAwIBAgIUd9l6tMS21ak3e4S0VdPhY0jG3gQwDQYJKoZIhvcNAQEL +BQAwgaExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQH +DAxTYW5GcmFuY2lzY28xEDAOBgNVBAoMB29yYWNsZSAxNjA0BgNVBAMMLWNkYi1k +ZXYtb3Jkcy5vcmFjbGUtZGF0YWJhc2Utb3BlcmF0b3Itc3lzdGVtIDEcMBoGA1UE +AwwTbG9jYWxob3N0ICBSb290IENBIDAeFw0yNDA4MTIxNTMyMzVaFw0yNTA4MTIx +NTMyMzVaMIGXMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMG +A1UEBwwMU2FuRnJhbmNpc2NvMRAwDgYDVQQKDAdvcmFjbGUgMTYwNAYDVQQDDC1j +ZGItZGV2LW9yZHMub3JhY2xlLWRhdGFiYXNlLW9wZXJhdG9yLXN5c3RlbSAxEjAQ +BgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AJvZ5TUkDbD01ah+ezJFimRMmlbc1SkPGd6AyuoVl3wduKdI1Y+rEziZHzVQMZ6p +lPA6Vt6HaW1Oqlnv5/gebyaanV1BnbKvTSsrrNnxm/8X9VJ7JKQNhVLlmaN7qcgh +cQwDrxOHmVM5cSJ/ueF12jQHUIlPRPFVz6+WMa72deU/8Qly7ST7P0QjhXCfPoL2 +RnIzG3T9emriQ1VmcwWrq93im4hzey1zQgkcxjvvnb9JBmPLx+zMhX4Kd6mAYkh0 +t1g4hVCY2CL32vJS3z9YZ5Qsh5/E51PYIxo5ndWHHHEiqliAE9uMD1ClVC5nuJ/d +Y8Qz6e4PJ0bQ8NEpo/YGArUCAwEAAaNMMEowSAYDVR0RBEEwP4IsY2RiLWRldi1v +cmRzLm9yYWNsZS1kYXRhYmFzZS1vcGVyYXRvci1zeXN0ZW2CD3d3dy5leGFtcGxl +LmNvbTANBgkqhkiG9w0BAQsFAAOCAQEAh7Lsu2ITS6Bc2q/Ef4No5Us0Vo9BWKoL +AlrfQPjsv1erMGsyEEyZ0Cg8l3QrXlscQ1ESvx0BnRGjoqZGE4+PoVZTEYSkokXP +aAr69epPzXQRyyAGCg5GeL6IFAj1AzqJGNnKOrPaLpcTri4MboiWmW+MHmgLdyPK +iwl8bNa8841nK/L/m6QET15BI+MIAvn7pgcpztum5jmkB+eceXzXnKUGg77TaFiX +bXqVBR4EvexC4DgUfQJI4zJLFdcH/GHxCpaaXNjbXeVz1ZK/qo2TCrXp2UXVrznU +9VTUuCaQA2VYZCitvAbupt+1OvMFYhWiIAroJSmzrvH4oK+IXgY6GA== +-----END CERTIFICATE----- diff --git a/docs/multitenant/usecase01/tls.key b/docs/multitenant/usecase01/tls.key new file mode 100644 index 00000000..666c5639 --- /dev/null +++ b/docs/multitenant/usecase01/tls.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCb2eU1JA2w9NWo +fnsyRYpkTJpW3NUpDxnegMrqFZd8HbinSNWPqxM4mR81UDGeqZTwOlbeh2ltTqpZ +7+f4Hm8mmp1dQZ2yr00rK6zZ8Zv/F/VSeySkDYVS5Zmje6nIIXEMA68Th5lTOXEi +f7nhddo0B1CJT0TxVc+vljGu9nXlP/EJcu0k+z9EI4Vwnz6C9kZyMxt0/Xpq4kNV +ZnMFq6vd4puIc3stc0IJHMY7752/SQZjy8fszIV+CnepgGJIdLdYOIVQmNgi99ry +Ut8/WGeULIefxOdT2CMaOZ3VhxxxIqpYgBPbjA9QpVQuZ7if3WPEM+nuDydG0PDR +KaP2BgK1AgMBAAECggEAKUwl1l0FW7yk2Q8a6glPUKCTzSybN1QPEMyj+D9ccsEV +aw57uKQmZbr9cA0d+OMK2lU7K6BKKXLM5SQTHcZCwcH6rPl0JiMZmbTrCp1hLslU +clS7MtV6XKsGeTGNncBuyjY3sD8gO9NezTt3L+0gsuS1TI06wZBxhh+QbsJUHzjW +bC3mNjD4SqXree4Snp05nlFaT2s2isIjj25mKDwBu8IX0BN2VjsaSiQcjb8Dmzmu +42Xh7bcWBebns8Ehuq9TIl6ZjQht+pmVOMlB862baVpW/9CxkknzM+UQhIkXTSJk +Jt/mGeO89V4/Zh2N4ixIOE1hw87EvRFBoYh2VF58QQKBgQDMujXYblh+eEdsB1LG +kY0LerFHuQgdzifYmjPl0jtBsWDmh5i6q9PRUs2JZ/Fsq4QMQ8SLinGzaIBq5FKr +CL067X5blrFA9H0D6exJI3iHBTQpeMFwtqvu3j+zpCmgzonaUDQrczUpc0hxU7YI +/jhDe9LSWknPrzzMoWWKuy0sTQKBgQDC4g8F2krqm9Q5ug8bRKTAvMrY0skFIwrP +5LXBq9C8YCnLnT4S4tYQfbnWaBeG7YpkkmkZe30c9MUjsr1OHZbo+jlxHBU+oRYZ +e1j0UorVGt7FfNe/zjW0fLd72CBO741EDvV6pVeItkAwH6P5/cbRu085dwvyFbxv +JmOaYddECQKBgQCuid6YG1NE10SE3CV89uAZtktny18ZEgY0ixrNx5MPaaskPtw9 +4Xofjol+qOhR7lQQpMHu+WQAQYqiFvBHspapo4pDiVCrAQWIDamNnTkHW69h3/qD +HqmsZzxF6iI3X351akVf+cOMCCXtwCGEvz+2gN12ytT8w/iAuOS6BuP3TQKBgBlf +v57+diSn13EQtajSPjVOH4ctorjFgEHjQHsP+OSeDLMTLSLeYArTo9+zu+R4hz1j +BsYnmvmrMQPd4OIL3jtFYTdF9coqxSraMZHWMXdfwUOrZpf1rG5skqNQV5yPejAz +Vmj6oDQPrrnVVM9W6I0kO0N7KZYCmH9MW0mdlZ6pAoGAB60f2sk35VUBpvh7qzTY +70WDbNnCCU3I3KZ7LCUwUPWzGLQwMXRlAb5ZMheT/SGPChX4QXCNUCjXkR3Am3NO +yURHqZIRy0bwZRVjYnlCtc9YQ8pB0isZ1z2a9FXRD75o2WboFZ+VsG0FU81IE2ZO +gW802gT76NRnz851B7/nFNs= +-----END PRIVATE KEY----- diff --git a/docs/multitenant/usecase02/README.md b/docs/multitenant/usecase02/README.md index f43d1f26..c434271f 100644 --- a/docs/multitenant/usecase02/README.md +++ b/docs/multitenant/usecase02/README.md @@ -8,11 +8,12 @@ - [UNPLUG DATABASE](#unplug-database) - [PLUG DATABASE](#plug-database) - [CLONE PDB](#clone-pdb) - - [UNPLUG AND PLUG WITH TDE](#unplug-and-plug-with-tde) ### INTRODUCTION -This page explains how to plug and unplug database a pdb; it assumes that you have already configured a pluggable database (see usecase01) +> ☞ The examples of this folder are based on single namespace **oracle-database-operator-system** + +This page explains how to plug and unplug database a pdb; it assumes that you have already configured a pluggable database (see [usecase01](../usecase01/README.md)) The following table reports the parameters required to configure and use oracle multi tenant controller for pluggable database lifecycle management. | yaml file parameters | value | description /ords parameter | @@ -77,7 +78,7 @@ The following table reports the parameters required to configure and use oracle ### UNPLUG DATABASE -Use the following command to check kubernets pdb resources. Note that the output of the commands can be tailored to fit to your needs. Just check the structure of pdb resource **kubectl get pdbs -n oracle-database-operator-system -o=json** and modify the script accordingly. For the sake of simplicity put this command in a single script **checkpdbs.sh**. +Use the following command to check kubernets pdb resources. Note that the output of the commands can be tailored to meet your needs. Just check the structure of pdb resource **kubectl get pdbs -n oracle-database-operator-system -o=json** and modify the script accordingly. For the sake of simplicity put this command in a single script **checkpdbs.sh**. ```bash kubectl get pdbs -n oracle-database-operator-system -o=jsonpath='{range .items[*]} @@ -91,7 +92,7 @@ kubectl get pdbs -n oracle-database-operator-system -o=jsonpath='{range .items[* {"\n"}{end}' ``` -We assume that the pluggable database pdbdev is already configured on opened in read write mode +We assume that the pluggable database pdbdev is already configured and opened in read write mode ```bash ./checkpdbs.sh @@ -105,9 +106,12 @@ MSG=Success ``` -Prepare a new yaml file **pdb_unplug.yaml** to unplug the pdbdev database. Make sure that the path of the xml file is correct and check the existence of all the required secrets. +Prepare a new yaml file **pdb_unplug.yaml** to unplug the pdbdev database. Make sure that the path of the xml file is correct and check the existence of all the required secrets. Do not reuse an existing xml files. ```yaml +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# #pdb_unplug.yaml apiVersion: database.oracle.com/v1alpha1 kind: PDB @@ -118,6 +122,7 @@ metadata: cdb: cdb-dev spec: cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" cdbName: "DB12" pdbName: "pdbdev" xmlFileName: "/tmp/pdbunplug.xml" @@ -134,11 +139,23 @@ spec: secret: secretName: "db-ca" key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + ``` Close the pluggable database by applying the following yaml file **pdb_close.yaml** ```yaml +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# #pdb_close.yaml apiVersion: database.oracle.com/v1alpha1 kind: PDB @@ -149,6 +166,7 @@ metadata: cdb: cdb-dev spec: cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" cdbName: "DB12" pdbName: "pdbdev" adminName: @@ -230,7 +248,7 @@ Completed: DROP PLUGGABLE DATABASE "pdbdev" KEEP DATAFILES ``` -login to the server and check xml file existence. Get the datafile path on the ASM filesystem. +login to the server and check xml file existence. Verify the datafile path on the ASM filesystem. ```bash ls -ltr /tmp/pdbunplug.xml @@ -253,7 +271,9 @@ DATAFILE UNPROT COARSE JAN 03 14:00:00 Y system.353.1125061021 Prepare a new yaml file **pdb_plug.yaml** to plug the database back into the container. ```yaml - +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# # pdb_plug.yaml apiVersion: database.oracle.com/v1alpha1 kind: PDB @@ -264,6 +284,7 @@ metadata: cdb: cdb-dev spec: cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" cdbName: "DB12" pdbName: "pdbdev" xmlFileName: "/tmp/pdbunplug.xml" @@ -362,6 +383,7 @@ metadata: cdb: cdb-dev spec: cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" cdbName: "DB12" pdbName: "pdb2-clone" srcPdbName: "pdbdev" @@ -458,6 +480,13 @@ PDBDEV(3):Buffer Cache flush finished: 3 ``` ### UNPLUG AND PLUG WITH TDE + + + +> ⚠ __WARNING FOR THE TDE USERS__ ⚠ According to the [ords documentation](https://docs.oracle.com/en/database/oracle/oracle-database/21/dbrst/op-database-pdbs-pdb_name-post.html) the plug and unplug operation with tde is supported only if ords runs on the same host of the database which is not the case of operator where ords runs on an isolated pods. Do not use pdb controller for unplug and plug operation with tde in production environments. + + + You can use unplug and plug database with TDE; in order to do that you have to specify a key store path and create new kubernets secret for TDE using the following yaml file. **tde_secrete.yaml**. The procedure to unplug and plug database does not change apply the same file. ```yaml @@ -491,6 +520,7 @@ metadata: cdb: cdb-dev spec: cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" cdbName: "DB12" pdbName: "pdbdev" adminName: @@ -541,6 +571,7 @@ metadata: cdb: cdb-dev spec: cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" cdbName: "DB12" pdbName: "pdbdev" adminName: diff --git a/docs/multitenant/usecase02/pdb_clone.yaml b/docs/multitenant/usecase02/pdb_clone.yaml index befae41e..0ecc3c70 100644 --- a/docs/multitenant/usecase02/pdb_clone.yaml +++ b/docs/multitenant/usecase02/pdb_clone.yaml @@ -2,7 +2,6 @@ # Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. # Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. # - apiVersion: database.oracle.com/v1alpha1 kind: PDB metadata: @@ -12,12 +11,14 @@ metadata: cdb: cdb-dev spec: cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" cdbName: "DB12" - pdbName: "pdb2-clone" + pdbName: "pdb2_clone" srcPdbName: "pdbdev" fileNameConversions: "NONE" totalSize: "UNLIMITED" tempSize: "UNLIMITED" + assertivePdbDeletion: true adminName: secret: secretName: "pdb1-secret" @@ -38,5 +39,12 @@ spec: secret: secretName: "db-ca" key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" action: "Clone" - diff --git a/docs/multitenant/usecase02/pdb_plug.yaml b/docs/multitenant/usecase02/pdb_plug.yaml index ac035623..77c00b9c 100644 --- a/docs/multitenant/usecase02/pdb_plug.yaml +++ b/docs/multitenant/usecase02/pdb_plug.yaml @@ -2,7 +2,6 @@ # Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. # Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. # - apiVersion: database.oracle.com/v1alpha1 kind: PDB metadata: @@ -12,15 +11,17 @@ metadata: cdb: cdb-dev spec: cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" cdbName: "DB12" pdbName: "pdbdev" - xmlFileName: "/tmp/pdbunplug.xml" + xmlFileName: "/tmp/pdb.xml" fileNameConversions: "NONE" sourceFileNameConversions: "NONE" copyAction: "MOVE" totalSize: "1G" tempSize: "100M" action: "Plug" + assertivePdbDeletion: true pdbTlsKey: secret: secretName: "db-tls" @@ -33,5 +34,13 @@ spec: secret: secretName: "db-ca" key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" diff --git a/docs/multitenant/usecase02/pdb_unplug.yaml b/docs/multitenant/usecase02/pdb_unplug.yaml index 6d995ac8..085d337e 100644 --- a/docs/multitenant/usecase02/pdb_unplug.yaml +++ b/docs/multitenant/usecase02/pdb_unplug.yaml @@ -2,7 +2,6 @@ # Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. # Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. # - apiVersion: database.oracle.com/v1alpha1 kind: PDB metadata: @@ -12,9 +11,10 @@ metadata: cdb: cdb-dev spec: cdbResName: "cdb-dev" + cdbNamespace: "oracle-database-operator-system" cdbName: "DB12" pdbName: "pdbdev" - xmlFileName: "/tmp/pdbunplug.xml" + xmlFileName: "/tmp/pdb.xml" action: "Unplug" pdbTlsKey: secret: @@ -28,4 +28,12 @@ spec: secret: secretName: "db-ca" key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" diff --git a/docs/multitenant/usecase03/Dockerfile b/docs/multitenant/usecase03/Dockerfile new file mode 100644 index 00000000..772a7e6d --- /dev/null +++ b/docs/multitenant/usecase03/Dockerfile @@ -0,0 +1,80 @@ +## Copyright (c) 2022 Oracle and/or its affiliates. +## +## The Universal Permissive License (UPL), Version 1.0 +## +## Subject to the condition set forth below, permission is hereby granted to any +## person obtaining a copy of this software, associated documentation and/or data +## (collectively the "Software"), free of charge and under any and all copyright +## rights in the Software, and any and all patent rights owned or freely +## licensable by each licensor hereunder covering either (i) the unmodified +## Software as contributed to or provided by such licensor, or (ii) the Larger +## Works (as defined below), to deal in both +## +## (a) the Software, and +## (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +## one is included with the Software (each a "Larger Work" to which the Software +## is contributed by such licensors), +## +## without restriction, including without limitation the rights to copy, create +## derivative works of, display, perform, and distribute the Software and make, +## use, sell, offer for sale, import, export, have made, and have sold the +## Software and the Larger Work(s), and to sublicense the foregoing rights on +## either these or other terms. +## +## This license is subject to the following condition: +## The above copyright notice and either this complete permission notice or at +## a minimum a reference to the UPL must be included in all copies or +## substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +## SOFTWARE. + +FROM container-registry.oracle.com/java/jdk:latest + +# Environment variables required for this build (do NOT change) +# ------------------------------------------------------------- +ENV ORDS_HOME=/opt/oracle/ords/ \ + RUN_FILE="runOrdsSSL.sh" \ + ORDSVERSION=23.4.0-8 + +# Copy binaries +# ------------- +COPY $RUN_FILE $ORDS_HOME + +RUN yum -y install yum-utils bind-utils tree hostname openssl net-tools zip unzip tar wget vim-minimal which sudo expect procps curl lsof && \ + yum-config-manager --add-repo=http://yum.oracle.com/repo/OracleLinux/OL8/oracle/software/x86_64 && \ + yum -y install java-11-openjdk-devel && \ + yum -y install iproute && \ + yum clean all + +RUN curl -o /tmp/ords-$ORDSVERSION.el8.noarch.rpm https://yum.oracle.com/repo/OracleLinux/OL8/oracle/software/x86_64/getPackage/ords-$ORDSVERSION.el8.noarch.rpm + +RUN rpm -ivh /tmp/ords-$ORDSVERSION.el8.noarch.rpm + +# Setup filesystem and oracle user +# -------------------------------- +RUN mkdir -p $ORDS_HOME/doc_root && \ + mkdir -p $ORDS_HOME/error && \ + mkdir -p $ORDS_HOME/secrets && \ + chmod ug+x $ORDS_HOME/*.sh && \ + groupadd -g 54322 dba && \ + usermod -u 54321 -d /home/oracle -g dba -m -s /bin/bash oracle && \ + chown -R oracle:dba $ORDS_HOME && \ + echo "oracle ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers + +# Finalize setup +# ------------------- +USER oracle +WORKDIR /home/oracle + +VOLUME ["$ORDS_HOME/config/ords"] +EXPOSE 8888 + +# Define default command to start Ords Services +CMD $ORDS_HOME/$RUN_FILE + diff --git a/docs/multitenant/usecase03/NamespaceSegregation.png b/docs/multitenant/usecase03/NamespaceSegregation.png new file mode 100644 index 00000000..bcb0ae77 Binary files /dev/null and b/docs/multitenant/usecase03/NamespaceSegregation.png differ diff --git a/docs/multitenant/usecase03/README.md b/docs/multitenant/usecase03/README.md new file mode 100644 index 00000000..c06368cd --- /dev/null +++ b/docs/multitenant/usecase03/README.md @@ -0,0 +1,268 @@ + + + +# STEP BY STEP (NAMESPACE SEGREGATION) + +- [STEP BY STEP (NAMESPACE SEGREGATION)](#step-by-step-namespace-segregation) + - [INTRODUCTION](#introduction) + - [GIT CLONE ORACLE DATABASE OPERATOR PROJECT](#git-clone-oracle-database-operator-project) + - [NAMESPACE CREATION](#namespace-creation) + - [WEBHOOK CERTIFICATES](#webhook-certificates) + - [ORACLE DATABASE OPERATOR](#oracle-database-operator) + - [CREATE PDB AND CDB SECRETS](#create-pdb-and-cdb-secrets) + - [CREATE TLS CERTIFICATE](#create-tls-certificate) + - [REST SERVER IMAGE CREATION](#rest-server-image-creation) + - [CDB POD CREATION](#cdb-pod-creation) + - [PDB CREATION](#pdb-creation) + - [MAKEFILE](#makefile) + + +### INTRODUCTION + +> ☞ This folder contains the yaml files required to configure and manage cdb and pdb in different namespaces. The main change here is the possibility to specify the namespace where CDB will be created, this implies the introduction of new parameter at PDB level in order to specify the CDB namespace. + +Tasks performed in the usecase03 are the same ones of the other usecase01 with the exception that controller pods cdb pods and pdb crd are running in different namespaces. You must be aware of the fact that secrets must be created in the proper namespaces; cdb secrets go into cdb namespace , pdb secrets go into pdbnamespace while certificate secrets need to be created in every namespace. + + +| yaml file parameters | value | description /ords parameter | +|-------------- |--------------------------- |-------------------------------------------------| +| ☞ cdbNamespace | | Cdb namespace | +| dbserver | or | [--db-hostname][1] | +| dbTnsurl | | [--db-custom-url/db.customURL][dbtnsurl] | +| port | | [--db-port][2] | +| cdbName | | Container Name | +| name | | Ords podname prefix in cdb.yaml | +| name | | pdb resource in pdb.yaml | +| ordsImage | /ords-dboper:latest|My public container registry | +| pdbName | | Pluggable database name | +| servicename | | [--db-servicename][3] | +| sysadmin_user | | [--admin-user][adminuser] | +| sysadmin_pwd | | [--password-stdin][pwdstdin] | +| cdbadmin_user | | [db.cdb.adminUser][1] | +| cdbadmin_pwd | | [db.cdb.adminUser.password][cdbadminpwd] | +| webserver_user| | [https user][http] NOT A DB USER | +| webserver_pwd | | [http user password][http] | +| ords_pwd | | [ORDS_PUBLIC_USER password][public_user] | +| pdbTlsKey | | [standalone.https.cert.key][key] | +| pdbTlsCrt | | [standalone.https.cert][cr] | +| pdbTlsCat | | certificate authority | +| xmlFileName | | path for the unplug and plug operation | +| srcPdbName | | name of the database to be cloned | +| fileNameConversions | | used for database cloning | +| tdeKeystorePath | | [tdeKeystorePath][tdeKeystorePath] | +| tdeExport | | [tdeExport] | +| tdeSecret | | [tdeSecret][tdeSecret] | +| tdePassword | | [tdeSecret][tdeSecret] | +| assertivePdbDeletion | boolean | [turn on imperative approach on crd deleteion][imperative] | + +![generla schema](./NamespaceSegregation.png) + +### GIT CLONE ORACLE DATABASE OPERATOR PROJECT + +```bash +git clone https://github.com/oracle/oracle-database-operator.git +cd oracle-database-operator/docs/multitenant/usecase03 +``` +### NAMESPACE CREATION + +We need first to create two different namespaces (**cdbnamespace**,**pdbnamespace**) using ns_pdb_namespace.yaml and ns_cdb_namespace.yaml + +```bash +kubectl apply -f ns_pdb_namespace.yaml +kubectl apply -f ns_cdb_namespace.yaml +``` + +### WEBHOOK CERTIFICATES +Create cert manager and verify the status + +```bash +kubectl apply -f https://github.com/jetstack/cert-manager/releases/latest/download/cert-manager.yaml +``` + +```bash +kubectl get pods --namespace cert-manager +NAME READY STATUS RESTARTS AGE +cert-manager-75997f4b44-4nf5c 1/1 Running 1 9d +cert-manager-cainjector-769785cd7b-mzfq5 1/1 Running 1 9d +cert-manager-webhook-6bc9944d78-tslrp 1/1 Running 1 9d +``` + +### ORACLE DATABASE OPERATOR + +Create the oracle database operator using oracle-database-operator.yaml +```bash +cd oracle-database-operator +kubectl apply -f oracle-database-operator.yaml +cd - +``` + +[operator creation log](operator_creation_log.txt) +### CREATE PDB AND CDB SECRETS + +Update secrets files with your base64 encodede password. + +```bash +echo ImAdemoPassword | base64 +SW1BZGVtb1Bhc3N3b3JkCg== +``` +Apply the cdb_secret and pdb_secret yaml file to generate credential information in each namespace. + +``` +kubectl apply -f cdb_secret.yaml +kubectl apply -f pdb_secret.yaml +``` +> ☞ Note that https credential needs to be replicated in any secret file. It is possible to improve configuration by creating a dedicated namespace for https credential in order to specify this information only once. + +Namespace segregation enables the capability of deploying and manages pluggable database without the cdb administrative passwords. + +### CREATE TLS CERTIFICATE + +Here follow an example of script shell that can be used to create secret certificates in each namespace involved in the kubernets multi tenant architecture + +```bash +#!/bin/bash +export CDB_NAMESPACE=cdbnamespace +export PDB_NAMESPACE=pdbnamespace +export OPR_NAMESPACE=oracle-database-operator-system +export SKEY=tls.key +export SCRT=tls.crt +export CART=ca.crt +export COMPANY=oracle +export REST_SERVER=ords + +openssl genrsa -out ca.key 2048 +openssl req -new -x509 -days 365 -key ca.key -subj "/C=CN/ST=GD/L=SZ/O=${COMPANY}, Inc./CN=${COMPANY} Root CA" -out ca.crt +openssl req -newkey rsa:2048 -nodes -keyout ${SKEY} -subj "/C=CN/ST=GD/L=SZ/O=${COMPANY}, Inc./CN=cdb-dev-${REST_SERVER}.${CDB_NAMESPACE}" -out server.csr +echo "subjectAltName=DNS:cdb-dev-${REST_SERVER}.${CDB_NAMESPACE},DNS:www.example.com" > extfile.txt +openssl x509 -req -extfile extfile.txt -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out ${SCRT} + +kubectl create secret tls db-tls --key="${SKEY}" --cert="${SCRT}" -n ${CDB_NAMESPACE} +kubectl create secret generic db-ca --from-file="${CART}" -n ${CDB_NAMESPACE} +kubectl create secret tls db-tls --key="${SKEY}" --cert="${SCRT}" -n ${PDB_NAMESPACE} +kubectl create secret generic db-ca --from-file="${CART}" -n ${PDB_NAMESPACE} +kubectl create secret tls db-tls --key="${SKEY}" --cert="${SCRT}" -n ${OPR_NAMESPACE} +kubectl create secret generic db-ca --from-file="${CART}" -n ${OPR_NAMESPACE} +``` +after all secrets creation you shoud have the following pattern + +```bash +kubectl get secrets -n oracle-database-operator-system +NAME TYPE DATA AGE +db-ca Opaque 1 6d5h +db-tls kubernetes.io/tls 2 6d5h +webhook-server-cert kubernetes.io/tls 3 6d15h + + +kubectl get secrets -n cdbnamespace +NAME TYPE DATA AGE +cdb1-secret Opaque 6 6d15h +db-ca Opaque 1 6d6h +db-tls kubernetes.io/tls 2 6d6h + + +kubectl get secrets -n pdbnamespace +NAME TYPE DATA AGE +db-ca Opaque 1 6d6h +db-tls kubernetes.io/tls 2 6d6h +pdb1-secret Opaque 4 2d16h +tde1-secret Opaque 2 22h +``` +### REST SERVER IMAGE CREATION + +```bash +cd oracle-database-operator/ords +docker build -t oracle/ords-dboper:latest . +docker tag oracle/ords-dboper:latest [path_of_your_registry]/ords-dboper:latest +docker push [path_of_your_registry]/ords-dboper.latest +cd - +``` + +### CDB POD CREATION + +**note:** + Before creating the CDB pod make sure that all the pluggable databases in the container DB are open. + + + +Update the cdb_create.yaml with the path of the image generated before to create CDB pod + +```bash +kubectl apply -f cdb_create.yaml +``` + +Verify the status of the operation and cdb pod existence using the following commands + +```bash +## check the pod creation +kubectl get pods -n cdbnamespace + +## check the rest server log after pod creation +kubectl logs -f `/usr/bin/kubectl get pods -n cdbnamespace|grep ords|cut -d ' ' -f 1` -n cdbnamespace + +##login to the pod for further debug and information gathering +kubectl exec -it `kubectl get pods -n cdbnamespace |grep ords|cut -d ' ' -f 1` -n cdbnamespace bash +``` + +[log cdb creation](./cdb_creation_log.txt) + +### PDB CREATION + +Apply the the pdb_create.yaml file to create a new pdb , after pdb creation you should be able to get pdb details using **kubectl get** command + +```bash +kubectl apply -f pdb_create.yaml +``` + +```bash +#!/bin/bash +#checkpdbs.sh +kubectl get pdbs -n pdbnamespace -o=jsonpath='{range .items[*]} +{"\n==================================================================\n"} +{"CDB="}{.metadata.labels.cdb} +{"K8SNAME="}{.metadata.name} +{"PDBNAME="}{.spec.pdbName} +{"OPENMODE="}{.status.openMode} +{"ACTION="}{.status.action} +{"MSG="}{.status.msg} +{"\n"}{end}' +``` + +```bash +./checkpdbs.sh +================================================================== +CDB=cdb-dev +K8SNAME=pdb1 +PDBNAME=pdbdev +OPENMODE=READ WRITE +ACTION=CREATE +MSG=Success + +``` +[pdb creation log](./pdb_creation_log.txt) + +### MAKEFILE + +In order to facilitate the command execution use the [makefile](./makefile) available target details are exposed in the following tables. + +|target |Action | +|-----------------------------|-------------------------------------| +|step1 | Build rest server images | +|step2 | Tag the immages | +|step3 | Push the image into the repository | +|step4 | Load webhook certmanager | +|step5 | Create the db operator | +|step6 | Create tls certificates | +|step7 | Create tls secret | +|step8 | Create database secrets | +|step9 | Create restserver pod | +|checkstep9 | Monitor the executions | +|step10 | Create pluggable database | +|checkpdb | Monitor PDB status | +|dump | Dump pods info into a file | +|reloadop | Reload the db operator | +|login | Login into cdb pod | + +[imperative]:https://kubernetes.io/docs/concepts/overview/working-with-objects/object-management/ + + + diff --git a/docs/multitenant/usecase03/cdb_create.yaml b/docs/multitenant/usecase03/cdb_create.yaml new file mode 100644 index 00000000..d3b5e04f --- /dev/null +++ b/docs/multitenant/usecase03/cdb_create.yaml @@ -0,0 +1,44 @@ +apiVersion: database.oracle.com/v1alpha1 +kind: CDB +metadata: + name: cdb-dev + namespace: cdbnamespace +spec: + cdbName: "DB12" + ordsImage: ".............your registry............./ords-dboper:latest" + ordsImagePullPolicy: "Always" + dbTnsurl : "...Container tns alias....." + replicas: 1 + sysAdminPwd: + secret: + secretName: "cdb1-secret" + key: "sysadmin_pwd" + ordsPwd: + secret: + secretName: "cdb1-secret" + key: "ords_pwd" + cdbAdminUser: + secret: + secretName: "cdb1-secret" + key: "cdbadmin_user" + cdbAdminPwd: + secret: + secretName: "cdb1-secret" + key: "cdbadmin_pwd" + webServerUser: + secret: + secretName: "cdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "cdb1-secret" + key: "webserver_pwd" + cdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + cdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + diff --git a/docs/multitenant/usecase03/cdb_creation_log.txt b/docs/multitenant/usecase03/cdb_creation_log.txt new file mode 100644 index 00000000..8c7dc161 --- /dev/null +++ b/docs/multitenant/usecase03/cdb_creation_log.txt @@ -0,0 +1,336 @@ +kubectl get pods -n cdbnamespace +NAME READY STATUS RESTARTS AGE +cdb-dev-ords-rs-pgqqh 0/1 ContainerCreating 0 1s + +kubectl get pods -n cdbnamespace +NAME READY STATUS RESTARTS AGE +cdb-dev-ords-rs-pgqqh 1/1 Running 0 6s + +kubectl logs -f `/usr/bin/kubectl get pods -n cdbnamespace|grep ords|cut -d ' ' -f 1` -n cdbnamespace +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M +NOT_INSTALLED=2 + SETUP +==================================================== +CONFIG=/etc/ords/config +total 0 +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:20 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: db.connectionType was set to: customurl in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:21 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: db.customURL was set to: jdbc:oracle:thin:@(DESCRIPTION=(CONNECT_TIMEOUT=90)(RETRY_COUNT=30)(RETRY_DELAY=10)(TRANSPORT_CONNECT_TIMEOUT=70)(LOAD_BALLANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=scan12.testrac.com)(PORT=1521)(IP=V4_ONLY))(LOAD_BALLANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=scan34.testrac.com)(PORT=1521)(IP=V4_ONLY))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=TESTORDS))) in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:23 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: security.requestValidationFunction was set to: false in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:25 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: jdbc.MaxLimit was set to: 100 in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:27 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: jdbc.InitialLimit was set to: 50 in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:29 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The global setting named: error.externalPath was set to: /opt/oracle/ords/error +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:31 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The global setting named: standalone.access.log was set to: /home/oracle +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:32 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The global setting named: standalone.https.port was set to: 8888 +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:34 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The global setting named: standalone.https.cert was set to: /opt/oracle/ords//secrets/tls.crt +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:36 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The global setting named: standalone.https.cert.key was set to: /opt/oracle/ords//secrets/tls.key +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:38 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: restEnabledSql.active was set to: true in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:40 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The global setting named: security.verifySSL was set to: true +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:42 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The global setting named: database.api.enabled was set to: true +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:43 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: plsql.gateway.mode was set to: disabled in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:45 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The global setting named: database.api.management.services.disabled was set to: false +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:47 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: misc.pagination.maxRows was set to: 1000 in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:49 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: db.cdb.adminUser was set to: C##DBAPI_CDB_ADMIN AS SYSDBA in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:51 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +The setting named: db.cdb.adminUser.password was set to: ****** in configuration: default +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:53 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +Created user welcome in file /etc/ords/config/global/credentials +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:17:55 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +Oracle REST Data Services - Non-Interactive Install + +Retrieving information.. +Completed verifying Oracle REST Data Services schema version 23.3.0.r2891830. +Connecting to database user: ORDS_PUBLIC_USER url: jdbc:oracle:thin:@(DESCRIPTION=(CONNECT_TIMEOUT=90)(RETRY_COUNT=30)(RETRY_DELAY=10)(TRANSPORT_CONNECT_TIMEOUT=70)(LOAD_BALLANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=scan12.testrac.com)(PORT=1521)(IP=V4_ONLY))(LOAD_BALLANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=scan34.testrac.com)(PORT=1521)(IP=V4_ONLY))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=TESTORDS))) +The setting named: db.serviceNameSuffix was set to: in configuration: default +The setting named: db.username was set to: ORDS_PUBLIC_USER in configuration: default +The setting named: db.password was set to: ****** in configuration: default +The setting named: security.requestValidationFunction was set to: ords_util.authorize_plsql_gateway in configuration: default +2024-01-25T17:17:58.898Z INFO Oracle REST Data Services schema version 23.3.0.r2891830 is installed. +2024-01-25T17:17:58.900Z INFO To run in standalone mode, use the ords serve command: +2024-01-25T17:17:58.900Z INFO ords --config /etc/ords/config serve +2024-01-25T17:17:58.900Z INFO Visit the ORDS Documentation to access tutorials, developer guides and more to help you get started with the new ORDS Command Line Interface (http://oracle.com/rest). +Picked up _JAVA_OPTIONS: -Xms1126M -Xmx1126M + +ORDS: Release 23.3 Production on Thu Jan 25 17:18:00 2024 + +Copyright (c) 2010, 2024, Oracle. + +Configuration: + /etc/ords/config/ + +2024-01-25T17:18:00.960Z INFO HTTP and HTTP/2 cleartext listening on host: 0.0.0.0 port: 8080 +2024-01-25T17:18:00.963Z INFO HTTPS and HTTPS/2 listening on host: 0.0.0.0 port: 8888 +2024-01-25T17:18:00.980Z INFO Disabling document root because the specified folder does not exist: /etc/ords/config/global/doc_root +2024-01-25T17:18:00.981Z INFO Default forwarding from / to contextRoot configured. +2024-01-25T17:18:06.634Z INFO Configuration properties for: |default|lo| +db.serviceNameSuffix= +java.specification.version=21 +conf.use.wallet=true +database.api.management.services.disabled=false +sun.jnu.encoding=UTF-8 +user.region=US +java.class.path=/opt/oracle/ords/ords.war +java.vm.vendor=Oracle Corporation +standalone.https.cert.key=/opt/oracle/ords//secrets/tls.key +sun.arch.data.model=64 +nashorn.args=--no-deprecation-warning +java.vendor.url=https://java.oracle.com/ +resource.templates.enabled=false +user.timezone=UTC +java.vm.specification.version=21 +os.name=Linux +sun.java.launcher=SUN_STANDARD +user.country=US +sun.boot.library.path=/usr/java/jdk-21/lib +sun.java.command=/opt/oracle/ords/ords.war --config /etc/ords/config serve --port 8888 --secure +jdk.debug=release +sun.cpu.endian=little +user.home=/home/oracle +oracle.dbtools.launcher.executable.jar.path=/opt/oracle/ords/ords.war +user.language=en +db.cdb.adminUser.password=****** +java.specification.vendor=Oracle Corporation +java.version.date=2023-10-17 +database.api.enabled=true +java.home=/usr/java/jdk-21 +db.username=ORDS_PUBLIC_USER +file.separator=/ +java.vm.compressedOopsMode=32-bit +line.separator= + +restEnabledSql.active=true +java.specification.name=Java Platform API Specification +java.vm.specification.vendor=Oracle Corporation +java.awt.headless=true +standalone.https.cert=/opt/oracle/ords//secrets/tls.crt +db.password=****** +sun.management.compiler=HotSpot 64-Bit Tiered Compilers +security.requestValidationFunction=ords_util.authorize_plsql_gateway +misc.pagination.maxRows=1000 +java.runtime.version=21.0.1+12-LTS-29 +user.name=oracle +error.externalPath=/opt/oracle/ords/error +stdout.encoding=UTF-8 +path.separator=: +db.cdb.adminUser=C##DBAPI_CDB_ADMIN AS SYSDBA +os.version=5.4.17-2136.323.8.1.el7uek.x86_64 +java.runtime.name=Java(TM) SE Runtime Environment +file.encoding=UTF-8 +plsql.gateway.mode=disabled +security.verifySSL=true +standalone.https.port=8888 +java.vm.name=Java HotSpot(TM) 64-Bit Server VM +java.vendor.url.bug=https://bugreport.java.com/bugreport/ +java.io.tmpdir=/tmp +oracle.dbtools.cmdline.ShellCommand=ords +java.version=21.0.1 +user.dir=/home/oracle/keystore +os.arch=amd64 +java.vm.specification.name=Java Virtual Machine Specification +jdbc.MaxLimit=100 +oracle.dbtools.cmdline.home=/opt/oracle/ords +native.encoding=UTF-8 +java.library.path=/usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib +java.vendor=Oracle Corporation +java.vm.info=mixed mode, sharing +stderr.encoding=UTF-8 +java.vm.version=21.0.1+12-LTS-29 +sun.io.unicode.encoding=UnicodeLittle +jdbc.InitialLimit=50 +db.connectionType=customurl +java.class.version=65.0 +db.customURL=jdbc:oracle:thin:@(DESCRIPTION=(CONNECT_TIMEOUT=90)(RETRY_COUNT=30)(RETRY_DELAY=10)(TRANSPORT_CONNECT_TIMEOUT=70)(LOAD_BALLANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=scan12.testrac.com)(PORT=1521)(IP=V4_ONLY))(LOAD_BALLANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=scan34.testrac.com)(PORT=1521)(IP=V4_ONLY))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=TESTORDS))) +standalone.access.log=/home/oracle + +2024-01-25T17:18:10.381Z INFO + +Mapped local pools from /etc/ords/config/databases: + /ords/ => default => VALID + + +2024-01-25T17:18:10.532Z INFO Oracle REST Data Services initialized +Oracle REST Data Services version : 23.3.0.r2891830 +Oracle REST Data Services server info: jetty/10.0.17 +Oracle REST Data Services java info: Java HotSpot(TM) 64-Bit Server VM 21.0.1+12-LTS-29 + + +exec -it `kubectl get pods -n cdbnamespace |grep ords|cut -d ' ' -f 1` -n cdbnamespace bash +[oracle@cdb-dev-ords-rs-pgqqh ~]$ ps -ef|grep java +oracle 1147 1116 10 17:17 ? 00:00:21 /usr/java/jdk-21/bin/java -Doracle.dbtools.cmdline.home=/opt/oracle/ords -Duser.language=en -Duser.region=US -Dfile.encoding=UTF-8 -Djava.awt.headless=true -Dnashorn.args=--no-deprecation-warning -Doracle.dbtools.cmdline.ShellCommand=ords -Duser.timezone=UTC -jar /opt/oracle/ords/ords.war --config /etc/ords/config serve --port 8888 --secure +oracle 1227 1200 0 17:21 pts/0 00:00:00 grep --color=auto java diff --git a/docs/multitenant/usecase03/cdb_secret.yaml b/docs/multitenant/usecase03/cdb_secret.yaml new file mode 100644 index 00000000..8f1b6fc9 --- /dev/null +++ b/docs/multitenant/usecase03/cdb_secret.yaml @@ -0,0 +1,17 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +apiVersion: v1 +kind: Secret +metadata: + name: cdb1-secret + namespace: cdbnamespace +type: Opaque +data: + ords_pwd: "[...base64 encoded password...]" + sysadmin_pwd: "[...base64 encoded password...]" + cdbadmin_user: "[...base64 encoded password...]" + cdbadmin_pwd: "[...base64 encoded password...]" + webserver_user: "[...base64 encoded password...]" + webserver_pwd: "[...base64 encoded password...]" diff --git a/docs/multitenant/usecase03/gentlscert.sh b/docs/multitenant/usecase03/gentlscert.sh new file mode 100644 index 00000000..49e29147 --- /dev/null +++ b/docs/multitenant/usecase03/gentlscert.sh @@ -0,0 +1,23 @@ +#!/bin/bash +export CDB_NAMESPACE=cdbnamespace +export PDB_NAMESPACE=pdbnamespace +export OPR_NAMESPACE=oracle-database-operator-system +export SKEY=tls.key +export SCRT=tls.crt +export CART=ca.crt +export COMPANY=oracle +export REST_SERVER=ords + +openssl genrsa -out ca.key 2048 +openssl req -new -x509 -days 365 -key ca.key -subj "/C=CN/ST=GD/L=SZ/O=${COMPANY}, Inc./CN=${COMPANY} Root CA" -out ca.crt +openssl req -newkey rsa:2048 -nodes -keyout ${SKEY} -subj "/C=CN/ST=GD/L=SZ/O=${COMPANY}, Inc./CN=cdb-dev-${REST_SERVER}.${CDB_NAMESPACE}" -out server.csr +echo "subjectAltName=DNS:cdb-dev-${REST_SERVER}.${CDB_NAMESPACE},DNS:www.example.com" > extfile.txt +openssl x509 -req -extfile extfile.txt -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out ${SCRT} + +kubectl create secret tls db-tls --key="${SKEY}" --cert="${SCRT}" -n ${CDB_NAMESPACE} +kubectl create secret generic db-ca --from-file="${CART}" -n ${CDB_NAMESPACE} +kubectl create secret tls db-tls --key="${SKEY}" --cert="${SCRT}" -n ${PDB_NAMESPACE} +kubectl create secret generic db-ca --from-file="${CART}" -n ${PDB_NAMESPACE} +kubectl create secret tls db-tls --key="${SKEY}" --cert="${SCRT}" -n ${OPR_NAMESPACE} +kubectl create secret generic db-ca --from-file="${CART}" -n ${OPR_NAMESPACE} + diff --git a/docs/multitenant/usecase03/makefile b/docs/multitenant/usecase03/makefile new file mode 100644 index 00000000..7270a5e0 --- /dev/null +++ b/docs/multitenant/usecase03/makefile @@ -0,0 +1,285 @@ +# __ __ _ __ _ _ +# | \/ | __ _| | _____ / _(_) | ___ +# | |\/| |/ _` | |/ / _ \ |_| | |/ _ \ +# | | | | (_| | < __/ _| | | __/ +# |_| |_|\__,_|_|\_\___|_| |_|_|\___| +# +# ___ +# / _ \ _ __ _ __ _ __ ___ _ __ ___ +# | | | | '_ \| '_ \| '__/ _ \ '_ ` _ \ +# | |_| | | | | |_) | | | __/ | | | | | +# \___/|_| |_| .__/|_| \___|_| |_| |_| +# |_| +# ____ _ _ _ +# / ___|___ _ __ | |_ _ __ ___ | | | ___ _ __ +# | | / _ \| '_ \| __| '__/ _ \| | |/ _ \ '__| +# | |__| (_) | | | | |_| | | (_) | | | __/ | +# \____\___/|_| |_|\__|_| \___/|_|_|\___|_| +# +# +# This makefile helps to speed up the kubectl commands executions to deploy and test +# the mutlitenant operator. Although it has few functionality you can adapt to your needs +# by adding much more targets. +# +# Quick start: +# ~~~~~~~~~~~ +# +# - Copy files of tab.1 in the makefile directory. +# - Edit the secret files and other yaml files with the correct credential as +# specified in the documentation. +# - Edit makefile updating variables of tab.2 +# - Execute commands of tab.3 "make step1" "make step2" "make step3".... +# +# Tab.1 - List of required files +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# +-----------------------------+---------------------------------------------+ +# |oracle-database-operator.yaml| Opertaor yaml file | +# +-----------------------------+---------------------------------------------+ +# |cdb_secret.yaml | Secret file for the rest server pod | +# +-----------------------------+---------------------------------------------+ +# |pdb_secret.yaml | Secret file for the pdb creation | +# +-----------------------------+---------------------------------------------+ +# |cdb_create.yaml | Rest server pod creation | +# +-----------------------------+---------------------------------------------+ +# |pdb_create.yaml | Pluggable database creation | +# +-----------------------------+---------------------------------------------+ +# |oracle-database-operator.yaml| Database operator | +# +-----------------------------+---------------------------------------------+ +# |Dockerfiles | Dockerfile for CBD | +# +-----------------------------+---------------------------------------------+ +# |runOrdsSSL.sh | Init script executed by Dockerfile | +# +-----------------------------+---------------------------------------------+ +# +# Tab.2 - List of variables +# ~~~~~~~~~~~~~~~~~~~~~~~~~ +# +# +-----------------------------+---------------------------------------------+ +# |OCIR | Your image registry | +# +-----------------------------+---------------------------------------------+ +# |OCIRPATH | Path of the image in your registry | +# +-----------------------------+---------------------------------------------+ +# +# Tab.3 - Execution steps +# ~~~~~~~~~~~~~~~~~~~~~~~ +# +# +-----------------------------+---------------------------------------------+ +# | MAKEFILE TARGETS LIST | +# | ----- ooo ----- | +# | - TARGET - - DESCRIPTION - | +# +-----------------------------+-------------------------------------+-------+ +# |step1 | Build rest server images | | +# +-----------------------------+-------------------------------------+ REST | +# |step2 | Tag the immages | SRV | +# +-----------------------------+-------------------------------------+ IMG | +# |step3 | Push the image into the repository | | +# +-----------------------------+-------------------------------------+-------+ +# |step4 | Load webhook certmanager | DB | +# +-----------------------------+-------------------------------------+ OPER | +# |step5 | Create the db operator | | +# +-----------------------------+-------------------------------------+-------+ +# |step6 | Create tls certificates | T | +# +-----------------------------+-------------------------------------+ L | +# |step7 | Create tls secret | S | +# +-----------------------------+---------------------------------------------+ +# |step8 | Create database secrets | +# +-----------------------------+---------------------------------------------+ +# |step9 | Create restserver pod | +# | | +---------------------------------------------+ +# | +---> checkstep9 | Monitor the executions | +# +-----------------------------+---------------------------------------------+ +# |step10 | Create pluggable database | +# | | +---------------------------------------------+ +# | +---> checkpdb | Monitor PDB status | +# +-----------------------------+---------------------------------------------+ +# | DIAGNOSTIC TARGETS | +# +-----------------------------+---------------------------------------------+ +# | dump | Dump pods info into a file | +# +-----------------------------+---------------------------------------------+ +# | reloadop | Reload the db operator | +# +-----------------------------+---------------------------------------------+ +# | login | Login into cdb pod | +# +-----------------------------+---------------------------------------------+ + + +################ TAB 2 VARIABLES ############ +REST_SERVER=ords +ORDSVERSION=latest + +OCIR=[container registry] +OCIRPATH=$(REST_SERVER)-dboper:$(ORDSVERSION) + +#examples: +#OCIR=lin.ocir.io +#OCIRPATH=/sampletenancy/samplepath/sampledir/$(REST_SERVER)-dboper:$(ORDSVERSION) +############################################# +DOCKER=/usr/bin/docker +KUBECTL=/usr/bin/kubectl +ORDS=/usr/local/bin/ords +CONFIG=/etc/ords/config +IMAGE=oracle/$(REST_SERVER)-dboper:$(ORDSVERSION) +DBOPERATOR=oracle-database-operator.yaml +URLPATH=/_/db-api/stable/database/pdbs/ +OPENSSL=/usr/bin/openssl +ORDSPORT=8888 +MAKE=/usr/bin/make +DOCKERFILE=../../../ords/Dockerfile +RUNSCRIPT=../../../ords/runOrdsSSL.sh +RM=/usr/bin/rm +CP=/bin/cp +ECHO=/usr/bin/echo +CERTMANAGER=https://github.com/jetstack/cert-manager/releases/latest/download/cert-manager.yaml +CDB_SECRET_YAML=cdb_secret.yaml +PDB_SECRET_YAML=pdb_secret.yaml +TDE_SECRET_YAML=tde_secret.yaml +CDB_NAMESPACE_YAML=ns_namespace_cdb.yaml +PDB_NAMESPACE_YAML=ns_namespace_pdb.yaml +OPR_NAMESPACE=oracle-database-operator-system +PDB_NAMESPACE=$(shell grep namespace $(PDB_NAMESPACE_YAML) |cut -d: -f 2| tr -d ' ') +CDB_NAMESPACE=$(shell grep namespace $(CDB_NAMESPACE_YAML) |cut -d: -f 2| tr -d ' ') +CDB=cdb_create.yaml +PDB=pdb_create.yaml +SKEY=tls.key +SCRT=tls.crt +CART=ca.crt +COMPANY=oracle +LOCALHOST=localhost +RESTPREFIX=cdb-dev + + +step1: createimage +step2: tagimage +step3: push +step4: certmanager +step5: dboperator +step6: tlscert +step7: tlssecret +step8: dbsecret +step9: cdb +step10: pdb + +checkstep9: checkcdb + + +createimage: + @echo "BUILDING CDB IMAGES" + $(CP) $(DOCKERFILE) . + $(CP) $(RUNSCRIPT) . + $(DOCKER) build -t $(IMAGE) . + +tagimage: + @echo "TAG IMAGE" + $(DOCKER) tag $(IMAGE) $(OCIR)$(OCIRPATH) + +push: + @echo "PUSH IMAGE INTO THE REGISTRY" + $(DOCKER) push $(OCIR)$(OCIRPATH) + +certmanager: + @echo "WEBHOOK CERT MANAGER" + $(KUBECTL) apply -f $(CERTMANAGER) + +dboperator: + @echo "ORACLE DATABASE OPERATOR" + $(KUBECTL) apply -f $(DBOPERATOR) + +namespace: + $(KUBECTL) get namespaces + $(KUBECTL) apply -f $(CDB_NAMESPACE_YAML) + $(KUBECTL) apply -f $(PDB_NAMESPACE_YAML) + $(KUBECTL) get namespaces + + +tlscert: + @echo "CREATING TLS CERTIFICATES" + $(OPENSSL) genrsa -out ca.key 2048 + $(OPENSSL) req -new -x509 -days 365 -key ca.key -subj "/C=US/ST=California/L=SanFrancisco/O=$(COMPANY) /CN=$(RESTPREFIX)-$(REST_SERVER).$(CDB_NAMESPACE) /CN=$(LOCALHOST) Root CA " -out ca.crt + $(OPENSSL) req -newkey rsa:2048 -nodes -keyout $(SKEY) -subj "/C=US/ST=California/L=SanFrancisco/O=$(COMPANY) /CN=$(RESTPREFIX)-$(REST_SERVER).$(CDB_NAMESPACE) /CN=$(LOCALHOST)" -out server.csr + $(ECHO) "subjectAltName=DNS:$(RESTPREFIX)-$(REST_SERVER).$(CDB_NAMESPACE),DNS:www.example.com" > extfile.txt + $(OPENSSL) x509 -req -extfile extfile.txt -days 365 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out $(SCRT) + + +tlssecret: + $(KUBECTL) create secret tls db-tls --key="$(SKEY)" --cert="$(SCRT)" -n $(CDB_NAMESPACE) + $(KUBECTL) create secret generic db-ca --from-file="$(CART)" -n $(CDB_NAMESPACE) + $(KUBECTL) create secret tls db-tls --key="$(SKEY)" --cert="$(SCRT)" -n $(PDB_NAMESPACE) + $(KUBECTL) create secret generic db-ca --from-file="$(CART)" -n $(PDB_NAMESPACE) + $(KUBECTL) create secret tls db-tls --key="$(SKEY)" --cert="$(SCRT)" -n $(OPR_NAMESPACE) + $(KUBECTL) create secret generic db-ca --from-file="$(CART)" -n $(OPR_NAMESPACE) + + +dbsecret: + @echo "CREATING DB SECRETS" + $(KUBECTL) apply -f $(CDB_SECRET_YAML) + $(KUBECTL) apply -f $(PDB_SECRET_YAML) + $(KUBECTL) apply -f $(TDE_SECRET_YAML) + + +cdb: + @echo "CREATING REST SRV POD" + $(KUBECTL) apply -f $(CDB) + +checkcdb: + $(KUBECTL) logs -f `$(KUBECTL) get pods -n $(CDB_NAMESPACE)|grep $(REST_SERVER)|cut -d ' ' -f 1` -n $(CDB_NAMESPACE) + +pdb: + $(KUBECTL) apply -f $(PDB) + +checkpdb: + $(KUBECTL) get pdbs -n $(OPR_NAMESPACE) + +dump: + @$(eval TMPSP := $(shell date "+%y%m%d%H%M%S" )) + @$(eval DIAGFILE := ./opdmp.$(TMPSP)) + @>$(DIAGFILE) + @echo "OPERATOR DUMP" >> $(DIAGFILE) + @echo "~~~~~~~~~~~~~" >> $(DIAGFILE) + $(KUBECTL) logs pod/`$(KUBECTL) get pods -n $(OPR_NAMESPACE)|grep oracle-database-operator-controller|head -1|cut -d ' ' -f 1` -n $(OPR_NAMESPACE) >>$(DIAGFILE) + $(KUBECTL) logs pod/`$(KUBECTL) get pods -n $(OPR_NAMESPACE)|grep oracle-database-operator-controller|head -2|tail -1 | cut -d ' ' -f 1` -n $(OPR_NAMESPACE) >>$(DIAGFILE) + $(KUBECTL) logs pod/`$(KUBECTL) get pods -n $(OPR_NAMESPACE)|grep oracle-database-operator-controller|tail -1|cut -d ' ' -f 1` -n $(OPR_NAMESPACE) >>$(DIAGFILE) + @echo "CDB LOG DUMP" >> $(DIAGFILE) + @echo "~~~~~~~~" >> $(DIAGFILE) + $(KUBECTL) logs `$(KUBECTL) get pods -n $(OPR_NAMESPACE)|grep $(REST_SERVER)| cut -d ' ' -f 1` -n $(OPR_NAMESPACE) >>$(DIAGFILE) + @echo "SECRET DMP" >>$(DIAGFILE) + @echo "~~~~~~~~" >> $(DIAGFILE) + $(KUBECTL) get secrets -o yaml -n $(OPR_NAMESPACE) >> $(DIAGFILE) + @echo "CDB/PDB DMP" >> $(DIAGFILE) + $(KUBECTL) get pdbs -o yaml -n $(OPR_NAMESPACE) >> $(DIAGFILE) + $(KUBECTL) get cdb -o yaml -n $(OPR_NAMESPACE) >> $(DIAGFILE) + @echo "CLUSTER INFO" >> $(DIAGFILE) + $(KUBECTL) get nodes -o wide + $(KUBECTL) get svc --namespace=kube-system + +reloadop: + echo "RESTARTING OPERATOR" + $(eval OP1 := $(shell $(KUBECTL) get pods -n $(OPR_NAMESPACE)|grep oracle-database-operator-controller|head -1|cut -d ' ' -f 1 )) + $(eval OP2 := $(shell $(KUBECTL) get pods -n $(OPR_NAMESPACE)|grep oracle-database-operator-controller|head -2|tail -1|cut -d ' ' -f 1 )) + $(eval OP3 := $(shell $(KUBECTL) get pods -n $(OPR_NAMESPACE)|grep oracle-database-operator-controller|tail -1|cut -d ' ' -f 1 )) + $(KUBECTL) get pod $(OP1) -n $(OPR_NAMESPACE) -o yaml | kubectl replace --force -f - + $(KUBECTL) get pod $(OP2) -n $(OPR_NAMESPACE) -o yaml | kubectl replace --force -f - + $(KUBECTL) get pod $(OP3) -n $(OPR_NAMESPACE) -o yaml | kubectl replace --force -f - + +login: + $(KUBECTL) exec -it `$(KUBECTL) get pods -n $(CDB_NAMESPACE) |grep $(REST_SERVER)|cut -d ' ' -f 1` -n $(CDB_NAMESPACE) bash + +cdblog: + $(KUBECTL) logs -f `$(KUBECTL) get pods -n $(CDB_NAMESPACE)|grep $(REST_SERVER)|cut -d ' ' -f 1` -n $(CDB_NAMESPACE) + + + +xlog1: + $(KUBECTL) logs -f pod/`$(KUBECTL) get pods -n $(OPR_NAMESPACE)|grep oracle-database-operator-controller|head -1|cut -d ' ' -f 1` -n $(OPR_NAMESPACE) + +xlog2: + $(KUBECTL) logs -f pod/`$(KUBECTL) get pods -n $(OPR_NAMESPACE)|grep oracle-database-operator-controller|head -2|tail -1|cut -d ' ' -f 1` -n $(OPR_NAMESPACE) + +xlog3: + $(KUBECTL) logs -f pod/`$(KUBECTL) get pods -n $(OPR_NAMESPACE)|grep oracle-database-operator-controller|tail -1|cut -d ' ' -f 1` -n $(OPR_NAMESPACE) + +checkdep: + $(KUBECTL) api-resources --verbs=list --namespaced -o name | xargs -n 1 $(KUBECTL) get -n $(OPR_NAMESPACE) + $(KUBECTL) api-resources --verbs=list --namespaced -o name | xargs -n 1 $(KUBECTL) get -n $(CBD_NAMESPACE) + $(KUBECTL) api-resources --verbs=list --namespaced -o name | xargs -n 1 $(KUBECTL) get -n $(PDB_NAMESPACE) + + + diff --git a/docs/multitenant/usecase03/ns_namespace_cdb.yaml b/docs/multitenant/usecase03/ns_namespace_cdb.yaml new file mode 100644 index 00000000..f4c6d77b --- /dev/null +++ b/docs/multitenant/usecase03/ns_namespace_cdb.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + control-plane: controller-manager + name: cdbnamespace + diff --git a/docs/multitenant/usecase03/ns_namespace_pdb.yaml b/docs/multitenant/usecase03/ns_namespace_pdb.yaml new file mode 100644 index 00000000..b22245f9 --- /dev/null +++ b/docs/multitenant/usecase03/ns_namespace_pdb.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + control-plane: controller-manager + name: pdbnamespace + diff --git a/docs/multitenant/usecase03/operator_creation_log.txt b/docs/multitenant/usecase03/operator_creation_log.txt new file mode 100644 index 00000000..36ed02ac --- /dev/null +++ b/docs/multitenant/usecase03/operator_creation_log.txt @@ -0,0 +1,27 @@ +kubectl apply -f oracle-database-operator.yaml +namespace/oracle-database-operator-system created +customresourcedefinition.apiextensions.k8s.io/autonomouscontainerdatabases.database.oracle.com configured +customresourcedefinition.apiextensions.k8s.io/autonomousdatabasebackups.database.oracle.com configured +customresourcedefinition.apiextensions.k8s.io/autonomousdatabaserestores.database.oracle.com configured +customresourcedefinition.apiextensions.k8s.io/autonomousdatabases.database.oracle.com configured +customresourcedefinition.apiextensions.k8s.io/cdbs.database.oracle.com configured +customresourcedefinition.apiextensions.k8s.io/dataguardbrokers.database.oracle.com configured +customresourcedefinition.apiextensions.k8s.io/dbcssystems.database.oracle.com configured +customresourcedefinition.apiextensions.k8s.io/oraclerestdataservices.database.oracle.com configured +customresourcedefinition.apiextensions.k8s.io/pdbs.database.oracle.com configured +customresourcedefinition.apiextensions.k8s.io/shardingdatabases.database.oracle.com configured +customresourcedefinition.apiextensions.k8s.io/singleinstancedatabases.database.oracle.com configured +role.rbac.authorization.k8s.io/oracle-database-operator-leader-election-role created +clusterrole.rbac.authorization.k8s.io/oracle-database-operator-manager-role created +clusterrole.rbac.authorization.k8s.io/oracle-database-operator-metrics-reader created +clusterrole.rbac.authorization.k8s.io/oracle-database-operator-oracle-database-operator-proxy-role created +rolebinding.rbac.authorization.k8s.io/oracle-database-operator-oracle-database-operator-leader-election-rolebinding created +clusterrolebinding.rbac.authorization.k8s.io/oracle-database-operator-oracle-database-operator-manager-rolebinding created +clusterrolebinding.rbac.authorization.k8s.io/oracle-database-operator-oracle-database-operator-proxy-rolebinding created +service/oracle-database-operator-controller-manager-metrics-service created +service/oracle-database-operator-webhook-service created +certificate.cert-manager.io/oracle-database-operator-serving-cert created +issuer.cert-manager.io/oracle-database-operator-selfsigned-issuer created +mutatingwebhookconfiguration.admissionregistration.k8s.io/oracle-database-operator-mutating-webhook-configuration created +validatingwebhookconfiguration.admissionregistration.k8s.io/oracle-database-operator-validating-webhook-configuration created +deployment.apps/oracle-database-operator-controller-manager created diff --git a/docs/multitenant/usecase03/pdb_create.yaml b/docs/multitenant/usecase03/pdb_create.yaml new file mode 100644 index 00000000..200f3712 --- /dev/null +++ b/docs/multitenant/usecase03/pdb_create.yaml @@ -0,0 +1,46 @@ +apiVersion: database.oracle.com/v1alpha1 +kind: PDB +metadata: + name: pdb1 + namespace: pdbnamespace + labels: + cdb: cdb-dev +spec: + cdbResName: "cdb-dev" + cdbNamespace: "cdbnamespace" + cdbName: "DB12" + pdbName: "pdbdev" + adminName: + secret: + secretName: "pdb1-secret" + key: "sysadmin_user" + adminPwd: + secret: + secretName: "pdb1-secret" + key: "sysadmin_pwd" + pdbTlsKey: + secret: + secretName: "db-tls" + key: "tls.key" + pdbTlsCrt: + secret: + secretName: "db-tls" + key: "tls.crt" + pdbTlsCat: + secret: + secretName: "db-ca" + key: "ca.crt" + webServerUser: + secret: + secretName: "pdb1-secret" + key: "webserver_user" + webServerPwd: + secret: + secretName: "pdb1-secret" + key: "webserver_pwd" + fileNameConversions: "NONE" + tdeImport: false + totalSize: "1G" + tempSize: "100M" + action: "Create" + diff --git a/docs/multitenant/usecase03/pdb_creation_log.txt b/docs/multitenant/usecase03/pdb_creation_log.txt new file mode 100644 index 00000000..71d0eb4f --- /dev/null +++ b/docs/multitenant/usecase03/pdb_creation_log.txt @@ -0,0 +1,6 @@ +kubectl apply -f pdb_create.yaml +pdb.database.oracle.com/pdb1 created + +kubectl get pdbs -n pdbnamespace +NAME CONNECT_STRING CDB NAME PDB NAME PDB STATE PDB SIZE STATUS MESSAGE +pdb1 (DESCRIPTION=(CONNECT_TIMEOUT=90)(RETRY_COUNT=30)(RETRY_DELAY=10)(TRANSPORT_CONNECT_TIMEOUT=70)(LOAD_BALLANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=scan12.testrac.com)(PORT=1521)(IP=V4_ONLY))(LOAD_BALLANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=scan34.testrac.com)(PORT=1521)(IP=V4_ONLY))(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=pdbdev))) DB12 pdbdev READ WRITE 0.78G Ready Success diff --git a/docs/multitenant/usecase03/pdb_secret.yaml b/docs/multitenant/usecase03/pdb_secret.yaml new file mode 100644 index 00000000..f1dfdac6 --- /dev/null +++ b/docs/multitenant/usecase03/pdb_secret.yaml @@ -0,0 +1,16 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +apiVersion: v1 +kind: Secret +metadata: + name: pdb1-secret + namespace: pdbnamespace +type: Opaque +data: + sysadmin_user: "[...base64 encoded password...]" + sysadmin_pwd: "[...base64 encoded password...]" + webserver_user: "[...base64 encoded password...]" + webserver_pwd: "[...base64 encoded password...]" + diff --git a/docs/multitenant/usecase03/runOrdsSSL.sh b/docs/multitenant/usecase03/runOrdsSSL.sh new file mode 100644 index 00000000..35f1b77b --- /dev/null +++ b/docs/multitenant/usecase03/runOrdsSSL.sh @@ -0,0 +1,190 @@ +#!/bin/bash + +cat <$TNSNAME + + +function SetParameter() { + ##ords config info <--- Use this command to get the list + +[[ ! -z "${ORACLE_HOST}" && -z "${DBTNSURL}" ]] && { + $ORDS --config ${CONFIG} config set db.hostname ${ORACLE_HOST:-racnode1} + $ORDS --config ${CONFIG} config set db.port ${ORACLE_PORT:-1521} + $ORDS --config ${CONFIG} config set db.servicename ${ORACLE_SERVICE:-TESTORDS} +} + +[[ -z "${ORACLE_HOST}" && ! -z "${DBTNSURL}" ]] && { + #$ORDS --config ${CONFIG} config set db.tnsAliasName ${TNSALIAS} + #$ORDS --config ${CONFIG} config set db.tnsDirectory ${TNS_ADMIN} + #$ORDS --config ${CONFIG} config set db.connectionType tns + + $ORDS --config ${CONFIG} config set db.connectionType customurl + $ORDS --config ${CONFIG} config set db.customURL jdbc:oracle:thin:@${DBTNSURL} +} + + $ORDS --config ${CONFIG} config set security.requestValidationFunction false + $ORDS --config ${CONFIG} config set jdbc.MaxLimit 100 + $ORDS --config ${CONFIG} config set jdbc.InitialLimit 50 + $ORDS --config ${CONFIG} config set error.externalPath ${ERRORFOLDER} + $ORDS --config ${CONFIG} config set standalone.access.log /home/oracle + $ORDS --config ${CONFIG} config set standalone.https.port 8888 + $ORDS --config ${CONFIG} config set standalone.https.cert ${CERTIFICATE} + $ORDS --config ${CONFIG} config set standalone.https.cert.key ${KEY} + $ORDS --config ${CONFIG} config set restEnabledSql.active true + $ORDS --config ${CONFIG} config set security.verifySSL true + $ORDS --config ${CONFIG} config set database.api.enabled true + $ORDS --config ${CONFIG} config set plsql.gateway.mode disabled + $ORDS --config ${CONFIG} config set database.api.management.services.disabled false + $ORDS --config ${CONFIG} config set misc.pagination.maxRows 1000 + $ORDS --config ${CONFIG} config set db.cdb.adminUser "${CDBADMIN_USER:-C##DBAPI_CDB_ADMIN} AS SYSDBA" + $ORDS --config ${CONFIG} config secret --password-stdin db.cdb.adminUser.password << EOF +${CDBADMIN_PWD:-PROVIDE_A_PASSWORD} +EOF + +$ORDS --config ${CONFIG} config user add --password-stdin ${WEBSERVER_USER:-ordspdbadmin} "SQL Administrator, System Administrator" <${CKF} 2>&1 +echo "checkfile" >> ${CKF} +NOT_INSTALLED=`cat ${CKF} | grep "INFO: The" |wc -l ` +echo NOT_INSTALLED=$NOT_INSTALLED + + +function StartUp () { + $ORDS --config $CONFIG serve --port 8888 --secure +} + +# Check whether ords is already setup +if [ $NOT_INSTALLED -ne 0 ] +then + echo " SETUP " + setupOrds; + StartUp; +fi + +if [ $NOT_INSTALLED -eq 0 ] +then + echo " STARTUP " + StartUp; +fi + + diff --git a/docs/observability/README.md b/docs/observability/README.md new file mode 100644 index 00000000..986b1885 --- /dev/null +++ b/docs/observability/README.md @@ -0,0 +1,256 @@ +# Managing Observability on Kubernetes for Oracle Databases + +Oracle Database Operator for Kubernetes (`OraOperator`) includes the +Observability controller for Oracle Databases and adds the `DatabaseObserver` CRD, which enables users to observe +Oracle Databases by scraping database metrics using SQL queries. The controller +automates the deployment and maintenance of the metrics exporter container image, +metrics exporter service and a Prometheus servicemonitor. + +The following sections explains the configuration and functionality +of the controller. + +* [Prerequisites](#prerequisites) +* [The DatabaseObserver Custom Resource Definition](#the-databaseobserver-custom-resource) +* [Configuration of DatabaseObservers](#configuration) + * [Create](#create-resource) + * [List](#list-resource) + * [Get Status](#get-detailed-status) + * [Update](#patch-resource) + * [Delete](#delete-resource) +* [Mandatory Roles and Privileges](#mandatory-roles-and-privileges-requirements-for-observability-controller) +* [Debugging and troubleshooting](#debugging-and-troubleshooting) + +## Prerequisites +The `DatabaseObserver` custom resource has the following pre-requisites: + +1. Prometheus and its `servicemonitor` custom resource definition must be installed on the cluster. + +- The Observability controller creates multiple Kubernetes resources that include + a Prometheus `servicemonitor`. In order for the controller + to create ServiceMonitors, the ServiceMonitor custom resource must exist. + +2. A pre-existing Oracle Database and the proper database grants and privileges. + +- The controller exports metrics through SQL queries that the user can control + and specify through a _toml_ file. The necessary access privileges to the tables used in the queries + are not provided and applied automatically. + +### The DatabaseObserver Custom Resource +The Oracle Database Operator (__v1.1.0__) includes the Oracle Database Observability controller which automates +the deployment and setting up of the Oracle Database metrics exporter and the related resources to make Oracle databases observable. + +In the sample YAML file found in +[./config/samples/observability/databaseobserver.yaml](../../config/samples/observability/databaseobserver.yaml), +the databaseObserver custom resource offers the following properties to be configured: + +| Attribute | Type | Default | Required? | Example | +|-------------------------------------------------------|---------|-----------------|--------------|-----------------------------------------------------------------------| +| `spec.database.dbUser.key` | string | user | Optional | _username_ | +| `spec.database.dbUser.secret` | string | - | Yes | _db-secret_ | +| `spec.database.dbPassword.key` | string | password | Optional | _admin-password_ | +| `spec.database.dbPassword.secret` | string | - | Conditional | _db-secret_ | +| `spec.database.dbPassword.vaultOCID` | string | - | Conditional | _ocid1.vault.oc1..._ | +| `spec.database.dbPassword.vaultSecretName` | string | - | Conditional | _db-vault_ | +| `spec.database.dbWallet.secret` | string | - | Conditional | _devsec-oradevdb-wallet_ | +| `spec.database.dbConnectionString.key` | string | connection | Optional | _connection_ | +| `spec.database.dbConnectionString.secret` | string | - | Yes | _db-secretg_ | +| `spec.exporter.image` | string | - | Optional | _container-registry.oracle.com/database/observability-exporter:1.0.2_ | +| `spec.exporter.configuration.configmap.key` | string | config.toml | Optional | _config.toml_ | +| `spec.exporter.configuration.configmap.configmapName` | string | - | Optional | _devcm-oradevdb-config_ | +| `spec.exporter.service.port` | number | 9161 | Optional | _9161_ | +| `spec.prometheus.port` | string | metrics | Optional | _metrics_ | +| `spec.prometheus.labels` | map | app: obs-{name} | Optional | _app: oradevdb-apps_ | +| `spec.replicas` | number | 1 | Optional | _1_ | +| `spec.ociConfig.configMapName` | string | - | Conditional | _oci-cred_ | +| `spec.ociConfig.secretName` | string | - | Conditional | _oci-privatekey_ | + + + + + +### Configuration +The `databaseObserver` custom resource has the following fields for all configurations that are required: +* `spec.database.dbUser.secret` - secret containing the database username. The corresponding key can be any value but must match the key in the secret provided. +* `spec.database.dbPassword.secret` - secret containing the database password (if vault is NOT used). The corresponding key field can be any value but must match the key in the secret provided +* `spec.database.dbConnectionString.secret` - secret containing the database connection string. The corresponding key field can be any value but must match the key in the secret provided i + +If a database wallet is required to connect, the following field containing the secret is required: +* `spec.database.dbWallet.secret` - secret containing the database wallet. The filenames must be used as the keys + +If vault is used to store the database password instead, the following fields are required: +* `spec.database.dbPassword.vaultOCID` - OCID of the vault used +* `spec.database.dbPassword.vaultSecretName` - Name of the secret inside the desired vault +* `spec.ociConfig.configMapName` - holds the rest of the information of the OCI API signing key. The following keys must be used: `fingerprint`, `region`, `tenancy` and `user` +* `spec.ociConfig.secretName` - holds the private key of the OCI API signing key. The key to the file containing the user private key must be: `privatekey` + +The `databaseObserver` provides the remaining multiple fields that are optional: +* `spec.prometheus.labels` - labels to use for Service, ServiceMonitor and Deployment +* `spec.prometheus.port` - port to use for ServiceMonitor +* `spec.replicas` - number of replicas to deploy +* `spec.exporter.service.port` - port of service +* `spec.exporter.image` - image version of observability exporter to use + + +### Create Resource +Follow the steps below to create a new databaseObserver resource object. + +1. To begin, creating a databaseObserver requires you to create and provide kubernetes Secrets to provide connection details: +```bash +kubectl create secret generic db-secret \ + --from-literal=username='username' \ + --from-literal=password='password_here' \ + --from-literal=connection='dbsample_tp' +``` + +2. (Conditional) Create a Kubernetes secret for the wallet (if a wallet is required to connect to the database). + +You can create this secret by using a command similar to the following example below. +If you are connecting to an Autunomous Database and the operator is used to manage the Oracle Autonomous Database, +a client wallet can also be downloaded as a secret through kubectl commands. You can find out how, [here](../../docs/adb/README.md#download-wallets). + +Otherwise, you can create the wallet secret from a local directory containing the wallet files. +```bash +kubectl create secret generic db-wallet --from-file=wallet_dir +``` + +3. Finally, update the databaseObserver manifest with the resources you have created. You can use the example manifest +inside config/samples/observability to specify and create your databaseObserver object with a +YAML file. + +```YAML +# example +apiVersion: observability.oracle.com/v1alpha1 +kind: DatabaseObserver +metadata: + name: obs-sample +spec: + database: + dbUser: + key: "username" + secret: db-secret + + dbPassword: + key: "password" + secret: db-secret + + dbConnectionString: + key: "connection" + secret: db-secret + + dbWallet: + secret: db-wallet +``` + +```bash + kubectl apply -f databaseobserver.yaml +``` + +### List Resource +To list the Observability custom resources, use the following command as an example: +```bash +kubectl get databaseobserver -A +``` + +### Get Detailed Status +To obtain a quick status, use the following command as an example: + +> Note: The databaseobserver custom resource is named `obs-sample` in the next following sections. +> We will use this name as an example. + +```sh +$ kubectl get databaseobserver obs-sample +NAME EXPORTERCONFIG STATUS +obs-sample default READY +``` + + +To obtain a more detailed status, use the following command as an example: + +```bash +kubectl describe databaseobserver obs-sample +``` + +This provides details of the current state of your databaseObserver resource object. A successful +deployment of the databaseObserver resource object should display `READY` as the status and all conditions with a `True` +value for every ConditionType. + + +### Patch Resource +The Observability controller currently supports updates for most of the fields in the manifest. An example of patching the databaseObserver resource is as follows: +```bash +kubectl --type=merge -p '{"spec":{"exporter":{"image":"container-registry.oracle.com/database/observability-exporter:latest"}}}' patch databaseobserver obs-sample +``` + +The fields listed below can be updated with the given example command: + +* spec.exporter.image +* spec.exporter.configuration.configmap.configmapName +* spec.exporter.configuration.configmap.key +* spec.database.dbUser.secret +* spec.database.dbPassword.secret +* spec.database.dbConnectionString.secret +* spec.database.dbWallet.secret +* spec.ociConfig.configMapName +* spec.ociConfig.secretName +* spec.replicas +* spec.database.dbPassword.vaultOCID +* spec.database.dbPassword.vaultSecretName + + +### Delete Resource + +To delete the DatabaseObserver custom resource and all related resources: + +```bash +kubectl delete databaseobserver obs-sample +``` + +## Mandatory roles and privileges requirements for Observability Controller + +The Observability controller issues the following policy rules for the following resources. Besides +databaseobserver resources, the controller manages its own service, deployment, pods and servicemonitor +and gets and lists configmaps and secrets. + +| Resources | Verbs | +|-------------------------------------------------------|-------------------------------------------| +| services | create delete get list patch update watch | +| deployments | create delete get list patch update watch | +| pods | create delete get list patch update watch | +| events | create delete get list patch update watch | +| services.apps | create delete get list patch update watch | +| deployments.apps | create delete get list patch update watch | +| pods.apps | create delete get list patch update watch | +| servicemonitors.monitoring.coreos.com | create delete get list patch update watch | +| databaseobservers.observability.oracle.com | create delete get list patch update watch | +| databaseobservers.observability.oracle.com/status | get patch update | +| configmaps | get list | +| secrets | get list | +| configmaps.apps | get list | +| databaseobservers.observability.oracle.com/finalizers | update | + +## Debugging and troubleshooting + +### Show the details of the resource +To get the verbose output of the current spec, use the command below: + +```sh +kubectl describe databaseobserver/database-observer-sample +``` + +If any error occurs during the reconciliation loop, the Operator either reports +the error using the resource's event stream, or will show the error under conditions. + +### Check the logs of the pod where the operator deploys +Follow the steps to check the logs. + +1. List the pod replicas + + ```sh + kubectl get pods -n oracle-database-operator-system + ``` + +2. Use the below command to check the logs of the deployment + + ```sh + kubectl logs deployment.apps/oracle-database-operator-controller-manager -n oracle-database-operator-system + ``` diff --git a/docs/sharding/README.md b/docs/sharding/README.md index beb155d6..0c817467 100644 --- a/docs/sharding/README.md +++ b/docs/sharding/README.md @@ -22,20 +22,23 @@ The Sharding Database controller in Oracle Database Operator deploys Oracle Shar The Oracle Sharding database controller provides end-to-end automation of Oracle Database sharding topology deployment in Kubernetes clusters. -## Using Oracle Sharding Database Operator +## Using Oracle Database Operator Sharding Controller -To create a Sharding Topology, complete the steps in the following sections below: +Following sections provide the details for deploying Oracle Globally Distributed Database (Oracle Sharded Database) using Oracle Database Operator Sharding Controller with different use cases: -1. [Prerequsites for running Oracle Sharding Database Controller](#prerequsites-for-running-oracle-sharding-database-controller) -2. [Provisioning Sharding Topology in a Cloud based Kubernetes Cluster (OKE in this case)](#provisioning-sharding-topology-in-a-cloud-based-kubernetes-cluster-oke-in-this-case) -3. [Connecting to Shard Databases](#connecting-to-shard-databases) -4. [Debugging and Troubleshooting](#debugging-and-troubleshooting) +* [Prerequisites for running Oracle Sharding Database Controller](#prerequisites-for-running-oracle-sharding-database-controller) +* [Oracle Database 23ai Free](#oracle-database-23ai-free) +* [Provisioning Sharding Topology with System-Managed Sharding in a Cloud-Based Kubernetes Cluster](#provisioning-sharding-topology-with-system-managed-sharding-in-a-cloud-based-kubernetes-cluster) +* [Provisioning Sharding Topology with User Defined Sharding in a Cloud-Based Kubernetes Cluster](#provisioning-sharding-topology-with-user-defined-sharding-in-a-cloud-based-kubernetes-cluster) +* [Provisioning System-Managed Sharding Topology with Raft replication enabled in a Cloud-Based Kubernetes Cluster](#provisioning-system-managed-sharding-topology-with-raft-replication-enabled-in-a-cloud-based-kubernetes-cluster) +* [Connecting to Shard Databases](#connecting-to-shard-databases) +* [Debugging and Troubleshooting](#debugging-and-troubleshooting) **Note** Before proceeding to the next section, you must complete the instructions given in each section, based on your enviornment, before proceeding to next section. -## Prerequsites for Running Oracle Sharding Database Controller +## Prerequisites for running Oracle Sharding Database Controller -**IMPORTANT :** You must make the changes specified in this section before you proceed to the next section. +**IMPORTANT:** You must make the changes specified in this section before you proceed to the next section. ### 1. Kubernetes Cluster: To deploy Oracle Sharding database controller with Oracle Database Operator, you need a Kubernetes Cluster which can be one of the following: @@ -44,9 +47,24 @@ To create a Sharding Topology, complete the steps in the following sections belo To use Oracle Sharding Database Controller, ensure that your system is provisioned with a supported Kubernetes release. Refer to the [Release Status Section](../../README.md#release-status). +#### Mandatory roles and privileges requirements for Oracle Sharding Database Controller + + Oracle Sharding Database Controller uses Kubernetes objects such as :- + + | Resources | Verbs | + | --- | --- | + | Pods | create delete get list patch update watch | + | Containers | create delete get list patch update watch | + | PersistentVolumeClaims | create delete get list patch update watch | + | Services | create delete get list patch update watch | + | Secrets | create delete get list patch update watch | + | Events | create patch | + ### 2. Deploy Oracle Database Operator -To deploy Oracle Database Operator in a Kubernetes cluster, go to the section [Quick Install of the Operator](../../README.md#oracle-database-kubernetes-operator-deployment) in the README, and complete the operator deployment before you proceed further. If you have already deployed the operator, then proceed to the next section. +To deploy Oracle Database Operator in a Kubernetes cluster, go to the section [Install Oracle DB Operator](../../README.md#install-oracle-db-operator) in the README, and complete the operator deployment before you proceed further. If you have already deployed the operator, then proceed to the next section. + +**IMPORTANT:** Make sure you have completed the steps for [Role Binding for access management](../../README.md#role-binding-for-access-management) as well before installing the Oracle DB Operator. ### 3. Oracle Database and Global Data Services Docker Images Choose one of the following deployment options: @@ -70,6 +88,8 @@ You can either download the images and push them to your Docker Images Repositor **Note**: In the sharding example yaml files, we are using GDS and database images available on [Oracle Container Registry](https://container-registry.oracle.com/ords/f?p=113:10::::::). +**Note:** In case you want to use the `Oracle Database 23ai Free` Image for Database and GSM, refer to section [Oracle Database 23ai Free](#oracle-database-23ai-free) for more details. + ### 4. Create a namespace for the Oracle DB Sharding Setup Create a Kubernetes namespace named `shns`. All the resources belonging to the Oracle Database Sharding Setup will be provisioned in this namespace named `shns`. For example: @@ -84,22 +104,80 @@ You can either download the images and push them to your Docker Images Repositor ### 5. Create a Kubernetes secret for the database installation owner for the database Sharding Deployment -Create a Kubernetes secret named `db-user-pass` using these steps: [Create Kubernetes Secret](./provisioning/create_kubernetes_secret_for_db_user.md) +Create a Kubernetes secret named `db-user-pass-rsa` using these steps: [Create Kubernetes Secret](./provisioning/create_kubernetes_secret_for_db_user.md) + +After you have the above prerequisites completed, you can proceed to the next section for your environment to provision the Oracle Database Sharding Topology. + +### 6. Provisioning a Persistent Volume having an Oracle Database Gold Image + +This step is needed when you want to provision a Persistent Volume having an Oracle Database Gold Image for Database Cloning. + +In case of an `OCI OKE` cluster, you can use this Persistent Volume during provisioning Shard Databases by cloning in the same Availability Domain or you can use a Full Backup of this Persistent Volume during provisioning Shard Databases by cloning in different Availability Domains. + +You can refer [here](./provisioning/provisioning_persistent_volume_having_db_gold_image.md) for the steps involved. + +**NOTE:** Provisioning the Sharded Database using Cloning from Database Gold Image is `NOT` supported with Oracle Database 23ai Free. So, this step will not be needed if you are deploying Oracle Sharded Database using Oracle 23ai Free Database and GSM Images. + +## Oracle Database 23ai Free + +Please refer to [Oracle Database 23ai Free](https://www.oracle.com/database/free/get-started/) documentation for more details. + +If you want to use Oracle Database 23ai Free Image for Database and GSM for deployment of the Sharded Database using Sharding Controller in Oracle Database Kubernetes Operator, you need to consider the below points: + +* To deploy using the FREE Database and GSM Image, you will need to add the additional parameter `dbEdition: "free"` to the .yaml file. +* Refer to [Sample Sharded Database Deployment using Oracle 23ai FREE Database and GSM Images](./provisioning/free/sharding_provisioning_with_free_images.md) for an example. +* For Oracle Database 23ai Free, you can control the `CPU` and `Memory` allocation of the PODs using tags `cpu` and `memory` respectively but tags `INIT_SGA_SIZE` and `INIT_PGA_SIZE` to control the SGA and PGA allocation at the database level are `not` supported. +* Provisioning the Sharded Database using Cloning from Database Gold Image is `NOT` supported with Oracle Database 23ai Free. +* Total number of chunks for FREE Database defaults to `12` if `CATALOG_CHUNKS` parameter is not specified. This default value is determined considering limitation of 12 GB of user data on disk for oracle free database. + + +## Provisioning Sharding Topology with System-Managed Sharding in a Cloud-Based Kubernetes Cluster + +Deploy Oracle Database Sharding Topology with `System-Managed Sharding` on your Cloud based Kubernetes cluster. + +In this example, the deployment uses the YAML file based on `OCI OKE` cluster. There are multiple use case possible for deploying the Oracle Database Sharding Topology covered by below examples: + +[1. Provisioning Oracle Sharded Database with System-Managed Sharding without Database Gold Image](./provisioning/system_sharding/ssharding_provisioning_without_db_gold_image.md) +[2. Provisioning Oracle Sharded Database with System-Managed Sharding with number of chunks specified](./provisioning/system_sharding/ssharding_provisioning_with_chunks_specified.md) +[3. Provisioning Oracle Sharded Database with System-Managed Sharding with additional control on resources like Memory and CPU allocated to Pods](./provisioning/system_sharding/ssharding_provisioning_with_control_on_resources.md) +[4. Provisioning Oracle Sharded Database with System-Managed Sharding by cloning database from your own Database Gold Image in the same Availability Domain(AD)](./provisioning/system_sharding/ssharding_provisioning_by_cloning_db_gold_image_in_same_ad.md) +[5. Provisioning Oracle Sharded Database with System-Managed Sharding by cloning database from your own Database Gold Image across Availability Domains(ADs)](./provisioning/system_sharding/ssharding_provisioning_by_cloning_db_from_gold_image_across_ads.md) +[6. Provisioning Oracle Sharded Database with System-Managed Sharding and send Notification using OCI Notification Service](./provisioning/system_sharding/ssharding_provisioning_with_notification_using_oci_notification.md) +[7. Scale Out - Add Shards to an existing Oracle Sharded Database provisioned earlier with System-Managed Sharding](./provisioning/system_sharding/ssharding_scale_out_add_shards.md) +[8. Scale In - Delete an existing Shard from a working Oracle Sharded Database provisioned earlier with System-Managed Sharding](./provisioning/system_sharding/ssharding_scale_in_delete_an_existing_shard.md) + + +## Provisioning Sharding Topology with User Defined Sharding in a Cloud-Based Kubernetes Cluster + +Deploy Oracle Database Sharding Topology with `User Defined Sharding` on your Cloud based Kubernetes cluster. + +In this example, the deployment uses the YAML file based on `OCI OKE` cluster. There are multiple use case possible for deploying the Oracle Database Sharding Topology covered by below examples: + +[1. Provisioning Oracle Sharded Database with User Defined Sharding without Database Gold Image](./provisioning/user-defined-sharding/udsharding_provisioning_without_db_gold_image.md) +[2. Provisioning Oracle Sharded Database with User Defined Sharding with additional control on resources like Memory and CPU allocated to Pods](./provisioning/user-defined-sharding/udsharding_provisioning_with_control_on_resources.md) +[3. Provisioning Oracle Sharded Database with User Defined Sharding by cloning database from your own Database Gold Image in the same Availability Domain(AD)](./provisioning/user-defined-sharding/udsharding_provisioning_by_cloning_db_gold_image_in_same_ad.md) +[4. Provisioning Oracle Sharded Database with User Defined Sharding by cloning database from your own Database Gold Image across Availability Domains(ADs)](./provisioning/user-defined-sharding/udsharding_provisioning_by_cloning_db_from_gold_image_across_ads.md) +[5. Provisioning Oracle Sharded Database with User Defined Sharding and send Notification using OCI Notification Service](./provisioning/user-defined-sharding/udsharding_provisioning_with_notification_using_oci_notification.md) +[6. Scale Out - Add Shards to an existing Oracle Sharded Database provisioned earlier with User Defined Sharding](./provisioning/user-defined-sharding/udsharding_scale_out_add_shards.md) +[7. Scale In - Delete an existing Shard from a working Oracle Sharded Database provisioned earlier with User Defined Sharding](./provisioning/user-defined-sharding/udsharding_scale_in_delete_an_existing_shard.md) + + +## Provisioning System-Managed Sharding Topology with Raft replication enabled in a Cloud-Based Kubernetes Cluster -After you have the above prerequsites completed, you can proceed to the next section for your environment to provision the Oracle Database Sharding Topology. +Deploy Oracle Database Sharding Topology with `System-Managed Sharding with SNR RAFT enabled` on your Cloud based Kubernetes cluster. -## Provisioning Sharding Topology in a Cloud-Based Kubernetes Cluster (OKE in this case) +**NOTE: SNR RAFT Feature is available only for Oracle 23ai RDBMS and Oracle 23ai GSM version.** -Deploy Oracle Database sharding topology on your Cloud based Kubernetes cluster. In this example, the deployment uses the YAML file based on `OCI OKE` cluster. There are multiple use case possible for deploying the Oracle Database sharding topology. +In this example, the deployment uses the YAML file based on `OCI OKE` cluster. There are multiple use case possible for deploying the Oracle Database Sharding Topology covered by below examples: -[1. Provisioning Oracle Database sharding topology without Database Gold Image](./provisioning/provisioning_without_db_gold_image.md) -[2. Provisioning Oracle Database sharding topology with additional control on resources like Memory and CPU allocated to Pods](./provisioning/provisioning_with_control_on_resources.md) -[3. Provisioning a Persistent Volume having an Oracle Database Gold Image](./provisioning/provisioning_persistent_volume_having_db_gold_image.md) -[4. Provisioning Oracle Database sharding topology by cloning database from your own Database Gold Image in the same Availability Domain(AD)](./provisioning/provisioning_by_cloning_db_gold_image_in_same_ad.md) -[5. Provisioning Oracle Database sharding topology by cloning database from your own Database Gold Image across Availability Domains(ADs)](./provisioning/provisioning_by_cloning_db_from_gold_image_across_ads.md) -[6. Provisioning Oracle Database sharding topology and send Notification using OCI Notification Service](./provisioning/provisioning_with_notification_using_oci_notification.md) -[7. Scale Out - Add Shards to an existing Oracle Database Sharding Topology](./provisioning/scale_out_add_shards.md) -[8. Scale In - Delete an existing Shard from a working Oracle Database sharding topology](./provisioning/scale_in_delete_an_existing_shard.md) +[1. Provisioning System-Managed Sharding Topology with Raft replication enabled without Database Gold Image](./provisioning/snr_system_sharding/snr_ssharding_provisioning_without_db_gold_image.md) +[2. Provisioning System-Managed Sharding Topology with Raft replication enabled with number of chunks specified](./provisioning/snr_system_sharding/snr_ssharding_provisioning_with_chunks_specified.md) +[3. Provisioning System-Managed Sharding Topology with Raft replication enabled with additional control on resources like Memory and CPU allocated to Pods](./provisioning/snr_system_sharding/snr_ssharding_provisioning_with_control_on_resources.md) +[4. Provisioning System-Managed Sharding Topology with Raft replication enabled by cloning database from your own Database Gold Image in the same Availability Domain(AD)](./provisioning/snr_system_sharding/snr_ssharding_provisioning_by_cloning_db_gold_image_in_same_ad.md) +[5. Provisioning System-Managed Sharding Topology with Raft replication enabled by cloning database from your own Database Gold Image across Availability Domains(ADs)](./provisioning/snr_system_sharding/snr_ssharding_provisioning_by_cloning_db_from_gold_image_across_ads.md) +[6. Provisioning System-Managed Sharding Topology with Raft replication enabled and send Notification using OCI Notification Service](./provisioning/snr_system_sharding/snr_ssharding_provisioning_with_notification_using_oci_notification.md) +[7. Scale Out - Add Shards to an existing Oracle Sharded Database provisioned earlier with System-Managed Sharding with RAFT replication enabled](./provisioning/snr_system_sharding/snr_ssharding_scale_out_add_shards.md) +[8. Scale In - Delete an existing Shard from a working Oracle Sharded Database provisioned earlier with System-Managed Sharding with RAFT reolication enabled](./provisioning/snr_system_sharding/snr_ssharding_scale_in_delete_an_existing_shard.md) ## Connecting to Shard Databases diff --git a/docs/sharding/provisioning/create_kubernetes_secret_for_db_user.md b/docs/sharding/provisioning/create_kubernetes_secret_for_db_user.md index 0d66f49b..99620f04 100644 --- a/docs/sharding/provisioning/create_kubernetes_secret_for_db_user.md +++ b/docs/sharding/provisioning/create_kubernetes_secret_for_db_user.md @@ -1,25 +1,46 @@ # Create kubernetes secret for db user -Create a Kubernetes secret named "db-user-pass" using a password in a text file and then encrypt it using an `openssl` key. The text file will be removed after secret is created. +Below are the steps to create an encrypted file with a password for the DB User: + +- Create a text file which is having the password which you want to use for the DB user. +- Create an RSA key pair using `openssl`. +- Encrypt the text file with password using `openssl` with the RSA key pair generated earlier. +- Remove the initial text file. +- Create the Kubernetes secret named `db-user-pass-rsa` using the encrypted file. + +Please refer the below example for the above steps: ```sh +# Create a directory for files for the secret: +rm -rf /tmp/.secrets/ mkdir /tmp/.secrets/ -# Generate a random openssl key -openssl rand -hex 64 -out /tmp/.secrets/pwd.key +# Create directories and initialize the variables +RSADIR="/tmp/.secrets" +PRIVKEY="${RSADIR}"/"key.pem" +PUBKEY="${RSADIR}"/"key.pub" +NAMESPACE="shns" +PWDFILE="${RSADIR}"/"pwdfile.txt" +PWDFILE_ENC="${RSADIR}"/"pwdfile.enc" +SECRET_NAME="db-user-pass-rsa" + +# Generate the RSA Key +openssl genrsa -out "${RSADIR}"/key.pem +openssl rsa -in "${RSADIR}"/key.pem -out "${RSADIR}"/key.pub -pubout -# Use a password you want and add it to a text file -echo ORacle_21c > /tmp/.secrets/common_os_pwdfile +# Create a text file with the password +rm -f $PWDFILE_ENC +echo ORacle_23c > ${RSADIR}/pwdfile.txt -# Encrypt the file with the password with the random openssl key generated above -openssl enc -aes-256-cbc -md md5 -salt -in /tmp/.secrets/common_os_pwdfile -out /tmp/.secrets/common_os_pwdfile.enc -pass file:/tmp/.secrets/pwd.key +# Create encrypted file from the text file using the RSA key +openssl pkeyutl -in $PWDFILE -out $PWDFILE_ENC -pubin -inkey $PUBKEY -encrypt -# Remove the password text file -rm -f /tmp/.secrets/common_os_pwdfile +# Remove the initial text file: +rm -f $PWDFILE -# Create the Kubernetes secret in namespace "shns" -kubectl create secret generic db-user-pass --from-file=/tmp/.secrets/common_os_pwdfile.enc --from-file=/tmp/.secrets/pwd.key -n shns +# Deleting the existing secret if existing +kubectl delete secret $SECRET_NAME -n $NAMESPACE -# Check the secret details -kubectl get secret -n shns -``` +# Create the Kubernetes secret in namespace "NAMESPACE" +kubectl create secret generic $SECRET_NAME --from-file=$PWDFILE_ENC --from-file=${PRIVKEY} -n $NAMESPACE +``` \ No newline at end of file diff --git a/docs/sharding/provisioning/debugging.md b/docs/sharding/provisioning/debugging.md index 545bf034..63e02b6a 100644 --- a/docs/sharding/provisioning/debugging.md +++ b/docs/sharding/provisioning/debugging.md @@ -41,3 +41,10 @@ kubectl exec -it catalog-0 -n shns /bin/bash ``` Now, you can troubleshooting the corresponding component using the alert log or the trace files etc just like a normal Sharding Database Deployment. Please refer to [Oracle Database Sharding Documentation](https://docs.oracle.com/en/database/oracle/oracle-database/19/shard/sharding-troubleshooting.html#GUID-629262E5-7910-4690-A726-A565C59BA73E) for this purpose. + + +## Debugging using Database Events + +* You can enable database events as part of the Sharded Database Deployment +* This can be enabled using the `envVars` +* One example of enabling Database Events is [sharding_provisioning_with_db_events.md](./debugging/sharding_provisioning_with_db_events.md) \ No newline at end of file diff --git a/docs/sharding/provisioning/debugging/sharding_provisioning_with_db_events.md b/docs/sharding/provisioning/debugging/sharding_provisioning_with_db_events.md new file mode 100644 index 00000000..fa73920f --- /dev/null +++ b/docs/sharding/provisioning/debugging/sharding_provisioning_with_db_events.md @@ -0,0 +1,40 @@ +# Example of provisioning Oracle Sharded Database along with DB Events set at Database Level + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +This example sets a Database Event at the Database Level for Catalog and Shard Databases. + +The sharded database in this example is deployed with System-Managed Sharding type. In this use case, the database is created automatically using DBCA during the provisioning of the shard databases and the catalog database when the Oracle Sharding topology with System-Managed Sharding is deployed using Oracle Sharding controller. + +**NOTE:** In this use case, because DBCA creates the database automatically during the deployment, the time required to create the database is greater than the time it takes when the database is created by cloning from a Database Gold Image. + +This example uses `sharding_provisioning_with_db_events.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` +* One Catalog Pod: `catalog` +* Namespace: `shns` +* Database Event: `10798 trace name context forever, level 7` set along with `GWM_TRACE level 263` + + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `sharding_provisioning_with_db_events.yaml`. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + + +Use the file: [sharding_provisioning_with_db_events.yaml](./sharding_provisioning_with_db_events.yaml) for this use case as below: + +1. Deploy the `sharding_provisioning_with_db_events.yaml` file: + ```sh + kubectl apply -f sharding_provisioning_with_db_events.yaml + ``` +2. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + + # Check the logs of a particular pod. For example, to check status of pod "shard1-0": + kubectl logs -f pod/shard1-0 -n shns + ``` +3. You can confirm the Database event and the tracing enabled in the RDBMS alert log file of the Database. \ No newline at end of file diff --git a/docs/sharding/provisioning/debugging/sharding_provisioning_with_db_events.yaml b/docs/sharding/provisioning/debugging/sharding_provisioning_with_db_events.yaml new file mode 100644 index 00000000..7d136d58 --- /dev/null +++ b/docs/sharding/provisioning/debugging/sharding_provisioning_with_db_events.yaml @@ -0,0 +1,69 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + envVars: + - name: "DB_EVENTS" + value: "10798 trace name context forever, level 7:scope=spfile;immediate trace name GWM_TRACE level 263" + - name: shard2 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + envVars: + - name: "DB_EVENTS" + value: "10798 trace name context forever, level 7:scope=spfile;immediate trace name GWM_TRACE level 263" + - name: shard3 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + envVars: + - name: "DB_EVENTS" + value: "10798 trace name context forever, level 7:scope=spfile;immediate trace name GWM_TRACE level 263" + catalog: + - name: catalog + storageSizeInGb: 50 + imagePullPolicy: "Always" + envVars: + - name: "DB_EVENTS" + value: "10798 trace name context forever, level 7:scope=spfile;immediate trace name GWM_TRACE level 263" + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + isExternalSvc: False + isDeleteOraPvc: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns diff --git a/docs/sharding/provisioning/free/sharding_provisioning_with_free_images.md b/docs/sharding/provisioning/free/sharding_provisioning_with_free_images.md new file mode 100644 index 00000000..61641312 --- /dev/null +++ b/docs/sharding/provisioning/free/sharding_provisioning_with_free_images.md @@ -0,0 +1,40 @@ +# Example of provisioning Oracle Sharded Database with Oracle 23ai FREE Database and GSM Images + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +This example uses the Oracle 23ai FREE Database and GSM Images. + +The sharded database in this example is deployed with System-Managed Sharding type. In this use case, the database is created automatically using DBCA during the provisioning of the shard databases and the catalog database when the Oracle Sharding topology with System-Managed Sharding is deployed using Oracle Sharding controller. + +**NOTE:** In this use case, because DBCA creates the database automatically during the deployment, the time required to create the database is greater than the time it takes when the database is created by cloning from a Database Gold Image. + +This example uses `sharding_provisioning_with_free_images.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` +* One Catalog Pod: `catalog` +* Namespace: `shns` + + +To get the Oracle 23ai FREE Database and GSM Images: + * The Oracle 23ai FREE RDBMS Image used is `container-registry.oracle.com/database/free:latest`. Check [Oracle Database Free Get Started](https://www.oracle.com/database/free/get-started/?source=v0-DBFree-ChatCTA-j2032-20240709) for details. + * To pull the above image from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * Use the Oracle 23ai FREE GSM Binaries `LINUX.X64_234000_gsm.zip` as listed on page [Oracle Database Free Get Started](https://www.oracle.com/database/free/get-started/?source=v0-DBFree-ChatCTA-j2032-20240709) and prepare the GSM Container Image following [Oracle Global Data Services Image](https://github.com/oracle/db-sharding/tree/master/docker-based-sharding-deployment/dockerfiles) + * You need to change `dbImage` and `gsmImage` tag with the images you want to use in your enviornment in file `sharding_provisioning_with_free_images.yaml`. + + + +Use the file: [sharding_provisioning_with_free_images.yaml](./sharding_provisioning_with_free_images.yaml) for this use case as below: + +1. Deploy the `sharding_provisioning_with_free_images.yaml` file: + ```sh + kubectl apply -f sharding_provisioning_with_free_images.yaml + ``` +2. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + + # Check the logs of a particular pod. For example, to check status of pod "shard1-0": + kubectl logs -f pod/shard1-0 -n shns + ``` \ No newline at end of file diff --git a/docs/sharding/provisioning/free/sharding_provisioning_with_free_images.yaml b/docs/sharding/provisioning/free/sharding_provisioning_with_free_images.yaml new file mode 100644 index 00000000..7e39b3b2 --- /dev/null +++ b/docs/sharding/provisioning/free/sharding_provisioning_with_free_images.yaml @@ -0,0 +1,58 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + imagePullPolicy: "Always" + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + storageClass: oci + dbImage: container-registry.oracle.com/database/free:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: + gsmImagePullSecret: + dbEdition: "free" + isExternalSvc: False + isDeleteOraPvc: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns diff --git a/docs/sharding/provisioning/oraclesi.yaml b/docs/sharding/provisioning/oraclesi.yaml index 2e0607b7..cac70ffa 100644 --- a/docs/sharding/provisioning/oraclesi.yaml +++ b/docs/sharding/provisioning/oraclesi.yaml @@ -1,14 +1,14 @@ # -# Copyright (c) 2022, Oracle and/or its affiliates. +# Copyright (c) 2022, Oracle and/or its affiliates. # Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. # apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: oshard-gold-image-pvc19c + name: oshard-gold-image-pvc21c namespace: shns labels: - app: oshard19cdb-dep + app: oshard21cdb-dep spec: accessModes: - ReadWriteOnce @@ -18,28 +18,28 @@ spec: storageClassName: oci selector: matchLabels: - failure-domain.beta.kubernetes.io/zone: "EU-FRANKFURT-1-AD-1" + topology.kubernetes.io/zone: "PHX-AD-1" --- apiVersion: apps/v1 kind: StatefulSet metadata: - name: oshard19cdb + name: oshard21cdb namespace: shns labels: - app: oshard19cdb-dep + app: oshard21cdb-dep spec: selector: matchLabels: - app: oshard19cdb-dep + app: oshard21cdb-dep serviceName: gold-shard template: metadata: labels: - app: oshard19cdb-dep + app: oshard21cdb-dep spec: containers: - image: container-registry.oracle.com/database/enterprise:latest - name: oshard19cdb + name: oshard21cdb ports: - containerPort: 1521 name: db1-dbport @@ -68,17 +68,17 @@ spec: volumes: - name: data persistentVolumeClaim: - claimName: oshard-gold-image-pvc19c + claimName: oshard-gold-image-pvc21c - name: dshm emptyDir: medium: Memory nodeSelector: - failure-domain.beta.kubernetes.io/zone: "EU-FRANKFURT-1-AD-1" + topology.kubernetes.io/zone: "PHX-AD-1" --- apiVersion: v1 kind: Service metadata: - name: oshard19cdb + name: oshard21cdb namespace: shns spec: ports: @@ -95,5 +95,4 @@ spec: port: 6234 targetPort: db1-onsrport selector: - app: oshard19cdb-dep - + app: oshard21cdb-dep \ No newline at end of file diff --git a/docs/sharding/provisioning/oraclesi_pvc_commented.yaml b/docs/sharding/provisioning/oraclesi_pvc_commented.yaml index 89707a08..43b50a5e 100644 --- a/docs/sharding/provisioning/oraclesi_pvc_commented.yaml +++ b/docs/sharding/provisioning/oraclesi_pvc_commented.yaml @@ -1,46 +1,45 @@ # -# Copyright (c) 2022, Oracle and/or its affiliates. +# Copyright (c) 2022, Oracle and/or its affiliates. # Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. # - -# apiVersion: v1 -# kind: PersistentVolumeClaim -# metadata: -# name: oshard-gold-image-pvc19c -# namespace: shns -# labels: -# app: oshard19cdb-dep -# spec: -# accessModes: -# - ReadWriteOnce -# resources: -# requests: -# storage: 50Gi -# storageClassName: oci -# selector: -# matchLabels: -# failure-domain.beta.kubernetes.io/zone: "EU-FRANKFURT-1-AD-1" -# --- +#apiVersion: v1 +#kind: PersistentVolumeClaim +#metadata: +# name: oshard-gold-image-pvc21c +# namespace: shns +# labels: +# app: oshard21cdb-dep +#spec: +# accessModes: +# - ReadWriteOnce +# resources: +# requests: +# storage: 50Gi +# storageClassName: oci +# selector: +# matchLabels: +# topology.kubernetes.io/zone: "PHX-AD-1" +#--- apiVersion: apps/v1 kind: StatefulSet metadata: - name: oshard19cdb + name: oshard21cdb namespace: shns labels: - app: oshard19cdb-dep + app: oshard21cdb-dep spec: selector: matchLabels: - app: oshard19cdb-dep + app: oshard21cdb-dep serviceName: gold-shard template: metadata: labels: - app: oshard19cdb-dep + app: oshard21cdb-dep spec: containers: - image: container-registry.oracle.com/database/enterprise:latest - name: oshard19cdb + name: oshard21cdb ports: - containerPort: 1521 name: db1-dbport @@ -69,17 +68,17 @@ spec: volumes: - name: data persistentVolumeClaim: - claimName: oshard-gold-image-pvc19c + claimName: oshard-gold-image-pvc21c - name: dshm emptyDir: medium: Memory nodeSelector: - failure-domain.beta.kubernetes.io/zone: "EU-FRANKFURT-1-AD-1" + topology.kubernetes.io/zone: "PHX-AD-1" --- apiVersion: v1 kind: Service metadata: - name: oshard19cdb + name: oshard21cdb namespace: shns spec: ports: @@ -96,5 +95,4 @@ spec: port: 6234 targetPort: db1-onsrport selector: - app: oshard19cdb-dep - + app: oshard21cdb-dep \ No newline at end of file diff --git a/docs/sharding/provisioning/provisioning_persistent_volume_having_db_gold_image.md b/docs/sharding/provisioning/provisioning_persistent_volume_having_db_gold_image.md index 581fc62c..7d3312a6 100644 --- a/docs/sharding/provisioning/provisioning_persistent_volume_having_db_gold_image.md +++ b/docs/sharding/provisioning/provisioning_persistent_volume_having_db_gold_image.md @@ -9,7 +9,7 @@ This example uses file `oraclesi.yaml` to provision a single instance Oracle Dat * A Persistent Volume Claim * Repository location for Database Docker Image: `image: container-registry.oracle.com/database/enterprise:latest` * Namespace: `shns` -* Tag `nodeSelector` to deploy the Single Oracle Database in AD `EU-FRANKFURT-1-AD-1` +* Tag `nodeSelector` to deploy the Single Oracle Database in AD `PHX-AD-1` In this example, we are using pre-built Oracle Database image available on [Oracle Container Registry](https://container-registry.oracle.com/) * To pull the above image from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. diff --git a/docs/sharding/provisioning/provisioning_with_control_on_resources.md b/docs/sharding/provisioning/provisioning_with_control_on_resources.md deleted file mode 100644 index 734cad89..00000000 --- a/docs/sharding/provisioning/provisioning_with_control_on_resources.md +++ /dev/null @@ -1,39 +0,0 @@ -# Provisioning Oracle Database Sharding Topology with Additional Control on Resources Allocated to Pods - -In this use case, there are additional tags used to control resources such as CPU and Memory used by the different Pods when the Oracle Sharding topology is deployed using Oracle Sharding controller. - -This example uses `shard_prov_memory_cpu.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: - -* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` -* Two sharding Pods: `shard1` and `shard2` -* One Catalog Pod: `catalog` -* Namespace: `shns` -* Tags `memory` and `cpu` to control the Memory and CPU of the PODs -* Additional tags `INIT_SGA_SIZE` and `INIT_PGA_SIZE` to control the SGA and PGA allocation at the database level - -In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) - * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. - * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `shard_prov_memory_cpu.yaml`. - * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../README.md#3-oracle-database-and-global-data-services-docker-images) - -Use the YAML file [shard_prov_memory_cpu.yaml](./shard_prov_memory_cpu.yaml). - -1. Deploy the `shard_prov_memory_cpu.yaml` file: - - ```sh - kubectl apply -f shard_prov_memory_cpu.yaml - ``` - -1. Check the details of a POD. For example: To check the details of Pod `shard1-0`: - - ```sh - kubectl describe pod/shard1-0 -n shns - ``` -3. Check the status of the deployment: - ```sh - # Check the status of the Kubernetes Pods: - kubectl get all -n shns - - # Check the logs of a particular pod. For example, to check status of pod "shard1-0": - kubectl logs -f pod/shard1-0 -n shns - ``` diff --git a/docs/sharding/provisioning/scale_in_delete_an_existing_shard.md b/docs/sharding/provisioning/scale_in_delete_an_existing_shard.md deleted file mode 100644 index 9334741b..00000000 --- a/docs/sharding/provisioning/scale_in_delete_an_existing_shard.md +++ /dev/null @@ -1,44 +0,0 @@ -# Scale In - Delete an existing Shard From a Working Oracle Database Sharding Topology - -This use case demonstrates how to delete an existing Shard from an existing Oracle Database sharding topology provisioned using Oracle Database Sharding controller. - -**NOTE** The deletion of a shard is done after verifying the Chunks have been moved out of that shard. - -In this use case, the existing database Sharding is having: - -* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` -* Five sharding Pods: `shard1`,`shard2`,`shard3`,`shard4` and `shard5` -* One Catalog Pod: `catalog` -* Namespace: `shns` - -In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) - * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. - * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `shard_prov.yaml`. - * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../README.md#3-oracle-database-and-global-data-services-docker-images) - -NOTE: Use tag `isDelete: true` to delete the shard you want. - -This use case deletes the shard `shard2` from the above Sharding Topology. - -Use the file: [shard_prov_delshard.yaml](./shard_prov_delshard.yaml) for this use case as below: - -1. Deploy the `shard_prov_delshard.yaml` file: - ```sh - kubectl apply -f shard_prov_delshard.yaml - ``` -2. Check the status of the deployment: - ```sh - # Check the status of the Kubernetes Pods: - kubectl get all -n shns - -**NOTE:** After you apply `shard_prov_delshard.yaml`, the change may not be visible immediately. When the shard is removed, first the chunks will be moved out of that shard that is going to be deleted. - -To monitor the chunk movement, use the following command: - -```sh -# Switch to the primary GSM Container: -kubectl exec -i -t gsm1-0 -n shns /bin/bash - -# Check the status of the chunks and repeat to observe the chunk movement: -gdsctl config chunks -``` diff --git a/docs/sharding/provisioning/scale_out_add_shards.md b/docs/sharding/provisioning/scale_out_add_shards.md deleted file mode 100644 index 174d8c6c..00000000 --- a/docs/sharding/provisioning/scale_out_add_shards.md +++ /dev/null @@ -1,31 +0,0 @@ -# Scale Out - Add Shards to an existing Oracle Database Sharding Topology - -This use case demonstrates adding a new shard to an existing Oracle Database sharding topology provisioned earlier using Oracle Database Sharding controller. - -In this use case, the existing Oracle Database sharding topology is having: - -* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` -* Two sharding Pods: `shard1` and `shard2` -* One Catalog Pod: `catalog` -* Namespace: `shns` - -In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) - * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. - * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `shard_prov.yaml`. - * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../README.md#3-oracle-database-and-global-data-services-docker-images) - -This use case adds three new shards `shard3`,`shard4`,`shard4` to above Sharding Topology. - -Use the file: [shard_prov_extshard.yaml](./shard_prov_extshard.yaml) for this use case as below: - -1. Deploy the `shard_prov_extshard.yaml` file: - ```sh - kubectl apply -f shard_prov_extshard.yaml - ``` -2. Check the status of the deployment: - ```sh - # Check the status of the Kubernetes Pods: - kubectl get all -n shns - - # Check the logs of a particular pod. For example, to check status of pod "shard3-0": - kubectl logs -f pod/shard3-0 -n shns diff --git a/docs/sharding/provisioning/shard_prov_clone.yaml b/docs/sharding/provisioning/shard_prov_clone.yaml deleted file mode 100644 index f9d3f826..00000000 --- a/docs/sharding/provisioning/shard_prov_clone.yaml +++ /dev/null @@ -1,64 +0,0 @@ -# -# Copyright (c) 2022, Oracle and/or its affiliates. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: ShardingDatabase -metadata: - name: shardingdatabase-sample - namespace: shns -spec: - shard: - - name: shard1 - storageSizeInGb: 50 - nodeSelector: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-1" - pvMatchLabels: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-1" - pvAnnotations: - volume.beta.kubernetes.io/oci-volume-source: ocid1.volume.oc1.eu-frankfurt-1.abtheljtmwcwf7liuhaibzgdcoxqcwwfpsqiqlsumrjlzkin7y4zx3x2idua - - name: shard2 - storageSizeInGb: 50 - nodeSelector: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-1" - pvMatchLabels: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-1" - pvAnnotations: - volume.beta.kubernetes.io/oci-volume-source: ocid1.volume.oc1.eu-frankfurt-1.abtheljtmwcwf7liuhaibzgdcoxqcwwfpsqiqlsumrjlzkin7y4zx3x2idua - catalog: - - name: catalog - storageSizeInGb: 50 - nodeSelector: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-1" - pvMatchLabels: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-1" - pvAnnotations: - volume.beta.kubernetes.io/oci-volume-source: ocid1.volume.oc1.eu-frankfurt-1.abtheljtmwcwf7liuhaibzgdcoxqcwwfpsqiqlsumrjlzkin7y4zx3x2idua - gsm: - - name: gsm1 - storageSizeInGb: 50 - replicas: 1 - envVars: - - name: "SERVICE1_PARAMS" - value: "service_name=oltp_rw_svc;service_role=primary" - - name: "SERVICE2_PARAMS" - value: "service_name=oltp_ro_svc;service_role=primary" - - name: gsm2 - storageSizeInGb: 50 - replicas: 1 - envVars: - - name: "SERVICE1_PARAMS" - value: "service_name=oltp_rw_svc;service_role=primary" - - name: "SERVICE2_PARAMS" - value: "service_name=oltp_ro_svc;service_role=primary" - storageClass: oci - dbImage: container-registry.oracle.com/database/enterprise:latest - dbImagePullSecret: ocr-reg-cred - gsmImage: container-registry.oracle.com/database/gsm:latest - gsmImagePullSecret: ocr-reg-cred - scriptsLocation: "set -ex;curl https://codeload.github.com/oracle/db-sharding/tar.gz/master | tar -xz --strip=4 db-sharding-master/docker-based-sharding-deployment/dockerfiles/21.3.0/scripts; cp -i -r scripts/* /opt/oracle/scripts/sharding/scripts/;cp -i -r scripts/*py /opt/oracle/scripts/sharding" - secret: db-user-pass - isExternalSvc: false - isClone: True - isDeleteOraPvc: True - namespace: shns diff --git a/docs/sharding/provisioning/shard_prov_clone_across_ads.yaml b/docs/sharding/provisioning/shard_prov_clone_across_ads.yaml deleted file mode 100644 index 6b815541..00000000 --- a/docs/sharding/provisioning/shard_prov_clone_across_ads.yaml +++ /dev/null @@ -1,72 +0,0 @@ -# -# Copyright (c) 2022, Oracle and/or its affiliates. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: ShardingDatabase -metadata: - name: shardingdatabase-sample - namespace: shns -spec: - shard: - - name: shard1 - storageSizeInGb: 50 - nodeSelector: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-2" - pvMatchLabels: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-2" - pvAnnotations: - volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.eu-frankfurt-1.abtheljtjlc7oce3sgq55vnskb4sjdip5sdaighm54hpmlcg7avgc76pjbea - - name: shard2 - storageSizeInGb: 50 - nodeSelector: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-1" - pvMatchLabels: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-1" - pvAnnotations: - volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.eu-frankfurt-1.abtheljtjlc7oce3sgq55vnskb4sjdip5sdaighm54hpmlcg7avgc76pjbea - catalog: - - name: catalog - storageSizeInGb: 50 - nodeSelector: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-2" - pvMatchLabels: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-2" - pvAnnotations: - volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.eu-frankfurt-1.abtheljtjlc7oce3sgq55vnskb4sjdip5sdaighm54hpmlcg7avgc76pjbea - gsm: - - name: gsm1 - storageSizeInGb: 50 - replicas: 1 - envVars: - - name: "SERVICE1_PARAMS" - value: "service_name=oltp_rw_svc;service_role=primary" - - name: "SERVICE2_PARAMS" - value: "service_name=oltp_ro_svc;service_role=primary" - nodeSelector: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-2" - pvMatchLabels: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-2" - - name: gsm2 - storageSizeInGb: 50 - replicas: 1 - envVars: - - name: "SERVICE1_PARAMS" - value: "service_name=oltp_rw_svc;service_role=primary" - - name: "SERVICE2_PARAMS" - value: "service_name=oltp_ro_svc;service_role=primary" - nodeSelector: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-3" - pvMatchLabels: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-3" - storageClass: oci - dbImage: container-registry.oracle.com/database/enterprise:latest - dbImagePullSecret: ocr-reg-cred - gsmImage: container-registry.oracle.com/database/gsm:latest - gsmImagePullSecret: ocr-reg-cred - scriptsLocation: "set -ex;curl https://codeload.github.com/oracle/db-sharding/tar.gz/master | tar -xz --strip=4 db-sharding-master/docker-based-sharding-deployment/dockerfiles/21.3.0/scripts; cp -i -r scripts/* /opt/oracle/scripts/sharding/scripts/;cp -i -r scripts/*py /opt/oracle/scripts/sharding" - secret: db-user-pass - isExternalSvc: false - isClone: True - isDeleteOraPvc: True - namespace: shns diff --git a/docs/sharding/provisioning/shard_prov_delshard.yaml b/docs/sharding/provisioning/shard_prov_delshard.yaml deleted file mode 100644 index 09cbd549..00000000 --- a/docs/sharding/provisioning/shard_prov_delshard.yaml +++ /dev/null @@ -1,52 +0,0 @@ -# -# Copyright (c) 2022, Oracle and/or its affiliates. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: ShardingDatabase -metadata: - name: shardingdatabase-sample - namespace: shns -spec: - shard: - - name: shard1 - storageSizeInGb: 50 - - name: shard2 - storageSizeInGb: 50 - isDelete: true - - name: shard3 - storageSizeInGb: 50 - - name: shard4 - storageSizeInGb: 50 - - name: shard5 - storageSizeInGb: 50 - catalog: - - name: catalog - storageSizeInGb: 50 - gsm: - - name: gsm1 - storageSizeInGb: 50 - replicas: 1 - envVars: - - name: "SERVICE1_PARAMS" - value: "service_name=oltp_rw_svc;service_role=primary" - - name: "SERVICE2_PARAMS" - value: "service_name=oltp_ro_svc;service_role=primary" - - name: gsm2 - storageSizeInGb: 50 - replicas: 1 - envVars: - - name: "SERVICE1_PARAMS" - value: "service_name=oltp_rw_svc;service_role=primary" - - name: "SERVICE2_PARAMS" - value: "service_name=oltp_ro_svc;service_role=primary" - storageClass: oci - dbImage: container-registry.oracle.com/database/enterprise:latest - dbImagePullSecret: ocr-reg-cred - gsmImage: container-registry.oracle.com/database/gsm:latest - gsmImagePullSecret: ocr-reg-cred - scriptsLocation: "set -ex;curl https://codeload.github.com/oracle/db-sharding/tar.gz/master | tar -xz --strip=4 db-sharding-master/docker-based-sharding-deployment/dockerfiles/21.3.0/scripts; cp -i -r scripts/* /opt/oracle/scripts/sharding/scripts/;cp -i -r scripts/*py /opt/oracle/scripts/sharding" - secret: db-user-pass - isExternalSvc: false - isDeleteOraPvc: True - namespace: shns diff --git a/docs/sharding/provisioning/shard_prov_send_notification.yaml b/docs/sharding/provisioning/shard_prov_send_notification.yaml deleted file mode 100644 index 19f3c02c..00000000 --- a/docs/sharding/provisioning/shard_prov_send_notification.yaml +++ /dev/null @@ -1,75 +0,0 @@ -# -# Copyright (c) 2022, Oracle and/or its affiliates. -# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. -# -apiVersion: database.oracle.com/v1alpha1 -kind: ShardingDatabase -metadata: - name: shardingdatabase-sample - namespace: shns -spec: - shard: - - name: shard1 - storageSizeInGb: 50 - nodeSelector: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-2" - pvMatchLabels: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-2" - pvAnnotations: - volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.eu-frankfurt-1.abtheljtjlc7oce3sgq55vnskb4sjdip5sdaighm54hpmlcg7avgc76pjbea - - name: shard2 - storageSizeInGb: 50 - nodeSelector: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-1" - pvMatchLabels: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-1" - pvAnnotations: - volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.eu-frankfurt-1.abtheljtjlc7oce3sgq55vnskb4sjdip5sdaighm54hpmlcg7avgc76pjbea - catalog: - - name: catalog - storageSizeInGb: 50 - nodeSelector: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-2" - pvMatchLabels: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-2" - pvAnnotations: - volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.eu-frankfurt-1.abtheljtjlc7oce3sgq55vnskb4sjdip5sdaighm54hpmlcg7avgc76pjbea - gsm: - - name: gsm1 - storageSizeInGb: 50 - replicas: 1 - envVars: - - name: "SERVICE1_PARAMS" - value: "service_name=oltp_rw_svc;service_role=primary" - - name: "SERVICE2_PARAMS" - value: "service_name=oltp_ro_svc;service_role=primary" - nodeSelector: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-2" - pvMatchLabels: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-2" - - name: gsm2 - storageSizeInGb: 50 - replicas: 1 - envVars: - - name: "SERVICE1_PARAMS" - value: "service_name=oltp_rw_svc;service_role=primary" - - name: "SERVICE2_PARAMS" - value: "service_name=oltp_ro_svc;service_role=primary" - nodeSelector: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-3" - pvMatchLabels: - "failure-domain.beta.kubernetes.io/zone": "EU-FRANKFURT-1-AD-3" - storageClass: oci - dbImage: container-registry.oracle.com/database/enterprise:latest - dbImagePullSecret: ocr-reg-cred - gsmImage: container-registry.oracle.com/database/gsm:latest - gsmImagePullSecret: ocr-reg-cred - scriptsLocation: "set -ex;curl https://codeload.github.com/oracle/db-sharding/tar.gz/master | tar -xz --strip=4 db-sharding-master/docker-based-sharding-deployment/dockerfiles/21.3.0/scripts; cp -i -r scripts/* /opt/oracle/scripts/sharding/scripts/;cp -i -r scripts/*py /opt/oracle/scripts/sharding" - secret: db-user-pass - isExternalSvc: false - isClone: True - isDeleteOraPvc: True - namespace: shns - nsConfigMap: onsconfigmap - nsSecret: my-secret - diff --git a/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_provisioning_by_cloning_db_from_gold_image_across_ads.md b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_provisioning_by_cloning_db_from_gold_image_across_ads.md new file mode 100644 index 00000000..ba72be25 --- /dev/null +++ b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_provisioning_by_cloning_db_from_gold_image_across_ads.md @@ -0,0 +1,57 @@ +# Provisioning System managed Sharding Topology with Raft replication enabled by cloning database from your own Database Gold Image across Availability Domains(ADs) + +**NOTE: RAFT Replication Feature is available only for Oracle 23c RDBMS and Oracle 23c GSM version.** + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +In this test case, you provision the System managed Sharding Topology with Raft replication enabled while provisioning the Catalog and Shard Databases by cloning from an existing Oracle Database Gold Image created earlier. + +This use case applies when you want to provision the database Pods on a Kubernetes Node in any availability domain (AD), which can also be different from the availability domain (AD) of the Block Volume that has the Oracle Database Gold Image provisioned earlier. + +Choosing this option takes substantially less time during the Oracle Database Sharding Topology setup across ADs. + +NOTE: + +* Cloning from Block Volume Backup in OCI enables the new Persistent Volumes to be created in other ADs. +* To specify the AD where you want to provision the database Pod, use the tag `nodeSelector` and the POD will be provisioned in a node running in that AD. +* To specify GSM containers, you can also use the tag `nodeSelector` to specify the AD. +* Before you can provision with the Gold Image, you need the OCID of the Persistent Volume that has the Oracle Database Gold Image. + +1. Check the OCID of the Persistent Volume provisioned for the Oracle Database Gold Image: + ```sh + kubectl get pv -n shns + ``` +2. Create a Block Volume Backup for this Block Volume, and use the OCID of the Block Volume Backup in the next step. This example uses `snr_ssharding_shard_prov_clone_across_ads.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` +* One Catalog Pod: `catalog` +* Namespace: `shns` +* Database Cloning from the `BLOCK VOLUME FULL BACKUP` of the Persistent Volume which had the Gold Image. +* OCID of the Block Volume Backup: `ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq` +* `RAFT Replication` enabled + +NOTE: In this case, the Persistent Volume with DB Gold Image was provisioned in the Availability Domain `PHX-AD-1`. The Shards and Catalog will be provisioned across multiple Availability Domains by cloning the database. + +**NOTE:** Provisioning the Sharded Database using Cloning from Database Gold Image is `NOT` supported with Oracle Database 23ai Free. + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `snr_ssharding_shard_prov_clone_across_ads.yaml`. + * The `dbImage` used during provisioning the Persistent Volume with Database Gold Image and the `dbImage` used for deploying the Shard or Catalog Database by cloning should be same. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + +Use the file: [snr_ssharding_shard_prov_clone_across_ads.yaml](./snr_ssharding_shard_prov_clone_across_ads.yaml) for this use case as below: + +1. Deploy the `snr_ssharding_shard_prov_clone_across_ads.yaml` file: + ```sh + kubectl apply -f snr_ssharding_shard_prov_clone_across_ads.yaml + ``` +2. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + + # Check the logs of a particular pod. For example, to check status of pod "shard1-0": + kubectl logs -f pod/shard1-0 -n shns + diff --git a/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_provisioning_by_cloning_db_gold_image_in_same_ad.md b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_provisioning_by_cloning_db_gold_image_in_same_ad.md new file mode 100644 index 00000000..cf4240f7 --- /dev/null +++ b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_provisioning_by_cloning_db_gold_image_in_same_ad.md @@ -0,0 +1,53 @@ +# Provisioning System managed Sharding Topology with Raft replication enabled by cloning database from your own Database Gold Image in the same Availability Domain(AD) + +**NOTE: RAFT Replication Feature is available only for Oracle 23c RDBMS and Oracle 23c GSM version.** + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +In this test case, you provision the System managed Sharding Topology with Raft replication enabled while provisioning the Catalog and Shard Databases by cloning from an existing Oracle Database Gold Image created earlier. + +This use case applies when you are cloning from a Block Volume, and you can clone _only_ in the same availability domain (AD). The result is that the cloned shard database PODs can be created _only_ in the same AD where the Gold Image Block Volume is present. + +Choosing this option takes substantially less time during the Oracle Database Sharding Topology setup. + +**NOTE** For this step, the Persistent Volume that has the Oracle Database Gold Image is identified using its OCID. + +1. Check the OCID of the Persistent Volume provisioned earlier using below command: + + ```sh + kubectl get pv -n shns + ``` + +2. This example uses `snr_ssharding_shard_prov_clone.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` +* One Catalog Pod: `catalog` +* Namespace: `shns` +* Database Cloning from the Database Gold Image present in Persistent Volume having OCID: `ocid1.volume.oc1.phx.abyhqljr3z3w72t6ay5eud7d5w3kdfhktfp6gwb6euy5tzwfaxgmbvwqlvsq` +* `RAFT Replication` enabled + +NOTE: In this case, the Persistent Volume with DB Gold Image was provisioned in the Availability Domain `PHX-AD-1`. The Shards and Catalog will be provisioned in the same Availability Domain `PHX-AD-1` by cloning the database. + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `snr_ssharding_shard_prov_clone.yaml`. + * The `dbImage` used during provisioning the Persistent Volume with Database Gold Image and the `dbImage` used for deploying the Shard or Catalog Database by cloning should be same. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + +**NOTE:** Provisioning the Sharded Database using Cloning from Database Gold Image is `NOT` supported with Oracle Database 23ai Free. + +Use the file: [snr_ssharding_shard_prov_clone.yaml](./snr_ssharding_shard_prov_clone.yaml) for this use case as below: + +1. Deploy the `snr_ssharding_shard_prov_clone.yaml` file: + ```sh + kubectl apply -f snr_ssharding_shard_prov_clone.yaml + ``` +2. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + + # Check the logs of a particular pod. For example, to check status of pod "shard1-0": + kubectl logs -f pod/shard1-0 -n shns + ``` diff --git a/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_provisioning_with_chunks_specified.md b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_provisioning_with_chunks_specified.md new file mode 100644 index 00000000..44972090 --- /dev/null +++ b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_provisioning_with_chunks_specified.md @@ -0,0 +1,43 @@ +# Provisioning System-Managed Sharding Topology with Raft replication enabled with number of chunks specified + +**NOTE: RAFT Replication Feature is available only for Oracle 23c RDBMS and Oracle 23c GSM version.** + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +In this use case, the database is created automatically using DBCA during the provisioning of the shard databases and the catalog database when the Oracle Sharding topology with System-Managed with RAFT Replication enabled is deployed using Oracle Sharding controller. + +**NOTE** In this use case, because DBCA creates the database automatically during the deployment, the time required to create the database is greater than the time it takes when the database is created by cloning from a Database Gold Image. + +By default, the System-Managed with RAFT Replication deploys the Sharded Database with 360 chunks per Shard Database (because there are 3 chunks created for each replication unit). In this example, the Sharded Database will be deployed with non-default number of chunks specified using parameter `CATALOG_CHUNKS`. + +This example uses `snr_ssharding_shard_prov_chunks.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` +* One Catalog Pod: `catalog` +* Total number of chunks as `120` specified by variable `CATALOG_CHUNKS` (it will be 120 chunks per shard) +* Namespace: `shns` +* `RAFT Replication` enabled + + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `snr_ssharding_shard_prov.yaml`. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + * In case you want to use the [Oracle Database 23ai Free](https://www.oracle.com/database/free/get-started/) Image for Database and GSM, then you will need to add the additional parameter `dbEdition: "free"` to the below .yaml file. + + +Use the file: [snr_ssharding_shard_prov_chunks.yaml](./snr_ssharding_shard_prov_chunks.yaml) for this use case as below: + +1. Deploy the `snr_ssharding_shard_prov_chunks.yaml` file: + ```sh + kubectl apply -f snr_ssharding_shard_prov_chunks.yaml + ``` +1. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + + # Check the logs of a particular pod. For example, to check status of pod "shard1-0": + kubectl logs -f pod/shard1-0 -n shns + ``` diff --git a/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_provisioning_with_control_on_resources.md b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_provisioning_with_control_on_resources.md new file mode 100644 index 00000000..9cfd6afb --- /dev/null +++ b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_provisioning_with_control_on_resources.md @@ -0,0 +1,47 @@ +# Provisioning System-Managed Sharding Topology with Raft replication enabled with additional control on resources like Memory and CPU allocated to Pods + +**NOTE: RAFT Replication Feature is available only for Oracle 23c RDBMS and Oracle 23c GSM version.** + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +In this use case, there are additional tags used to control resources such as CPU and Memory used by the different Pods when the Oracle Sharding topology with System-Managed with RAFT Replication is deployed using Oracle Sharding controller. + +This example uses `snr_ssharding_shard_prov_memory_cpu.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` +* One Catalog Pod: `catalog` +* Namespace: `shns` +* Tags `memory` and `cpu` to control the Memory and CPU of the PODs +* Additional tags `INIT_SGA_SIZE` and `INIT_PGA_SIZE` to control the SGA and PGA allocation at the database level +* `RAFT Replication` enabled + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `snr_ssharding_shard_prov_memory_cpu.yaml`. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + * In case you want to use the [Oracle Database 23ai Free](https://www.oracle.com/database/free/get-started/) Image for Database and GSM, then you will need to add the additional parameter `dbEdition: "free"` to the below .yaml file. + +**NOTE:** For Oracle Database 23ai Free, you can control the `CPU` and `Memory` allocation of the PODs using tags `cpu` and `memory` respectively but tags `INIT_SGA_SIZE` and `INIT_PGA_SIZE` to control the SGA and PGA allocation at the database level are `not` supported. + +Use the YAML file [snr_ssharding_shard_prov_memory_cpu.yaml](./snr_ssharding_shard_prov_memory_cpu.yaml). + +1. Deploy the `snr_ssharding_shard_prov_memory_cpu.yaml` file: + + ```sh + kubectl apply -f snr_ssharding_shard_prov_memory_cpu.yaml + ``` + +1. Check the details of a POD. For example: To check the details of Pod `shard1-0`: + + ```sh + kubectl describe pod/shard1-0 -n shns + ``` +3. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + + # Check the logs of a particular pod. For example, to check status of pod "shard1-0": + kubectl logs -f pod/shard1-0 -n shns + ``` diff --git a/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_provisioning_with_notification_using_oci_notification.md b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_provisioning_with_notification_using_oci_notification.md new file mode 100644 index 00000000..d4cb11de --- /dev/null +++ b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_provisioning_with_notification_using_oci_notification.md @@ -0,0 +1,87 @@ +# Provisioning System managed Sharding Topology with Raft replication enabled and send Notification using OCI Notification Service + +**NOTE: RAFT Replication Feature is available only for Oracle 23c RDBMS and Oracle 23c GSM version.** + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +This use case demonstrates how to use a notification service like OCI Notification service to send an email notification when a particular operation is completed on an Oracle Database sharding topology provisioned using the Oracle Database sharding controller. + +This example uses `snr_ssharding_shard_prov_send_notification.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` +* One Catalog Pod: `catalog` +* Namespace: `shns` +* Database Cloning from the `BLOCK VOLUME FULL BACKUP` of the Persistent Volume that has the Database Gold Image created earlier. +* OCID of the Block Volume Backup: `ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq` +* Configmap to send notification email when a particular operation is completed. For example: When a shard is added. +* `RAFT Replication` enabled + +**NOTE:** + +* The notification will be sent using a configmap created with the credentials of the OCI user account in this use case. + +We will create a topic in Notification Service of the OCI Console and use its OCID. + +To do this: + +1. Create a `configmap_data.txt` file, such as the following, which has the OCI User details that will be used to send notfication: + + ```sh + user=ocid1.user.oc1........fx7omxfq + fingerprint=fa:18:98:...............:8a + tenancy=ocid1.tenancy.oc1..aaaa.......orpn7inq + region=us-phoenix-1 + topicid=ocid1.onstopic.oc1.phx.aaa............6xrq + ``` +2. Create a configmap using the below command using the file created above: + ```sh + kubectl create configmap onsconfigmap --from-file=./configmap_data.txt -n shns + ``` + +3. Create a key file `priavatekey` having the PEM key of the OCI user being used to send notification: + ```sh + -----BEGIN PRIVATE KEY-G---- + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXYxA0DJvEwtVR + +o4OxrunL3L2NZJRADTFR+TDHqrNF1JwbaFBizSdL+EXbxQW1faZs5lXZ/sVmQF9 + . + . + . + zn/xWC0FzXGRzfvYHhq8XT3omf6L47KqIzqo3jDKdgvVq4u+lb+fXJlhj6Rwi99y + QEp36HnZiUxAQnR331DacN+YSTE+vpzSwZ38OP49khAB1xQsbiv1adG7CbNpkxpI + nS7CkDLg4Hcs4b9bGLHYJVY= + -----END PRIVATE KEY----- + ``` +4. Use the key file `privatekey` to create a Kubernetes secret in namespace `shns`: + + ```sh + kubectl create secret generic my-secret --from-file=./privatekey -n shns + ``` + +5. Use this command to check details of the secret that you created: + + ```sh + kubectl describe secret my-secret -n shns + ``` + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `snr_ssharding_shard_prov_send_notification.yaml`. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + * In case you want to use the [Oracle Database 23ai Free](https://www.oracle.com/database/free/get-started/) Image for Database and GSM, then you will need to add the additional parameter `dbEdition: "free"` to the below .yaml file. + +**NOTE:** Provisioning the Sharded Database using Cloning from Database Gold Image is `NOT` supported with Oracle Database 23ai Free. + +Use the file: [snr_ssharding_shard_prov_send_notification.yaml](./snr_ssharding_shard_prov_send_notification.yaml) for this use case as below: + +1. Deploy the `snr_ssharding_shard_prov_send_notification.yaml` file: + ```sh + kubectl apply -f snr_ssharding_shard_prov_send_notification.yaml + ``` +2. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + + # Check the logs of a particular pod. For example, to check status of pod "shard1-0": + kubectl logs -f pod/shard1-0 -n shns diff --git a/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_provisioning_without_db_gold_image.md b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_provisioning_without_db_gold_image.md new file mode 100644 index 00000000..892741a5 --- /dev/null +++ b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_provisioning_without_db_gold_image.md @@ -0,0 +1,40 @@ +# Provisioning System-Managed Sharding Topology with Raft replication enabled without Database Gold Image + +**NOTE: RAFT Replication Feature is available only for Oracle 23c RDBMS and Oracle 23c GSM version.** + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +In this use case, the database is created automatically using DBCA during the provisioning of the shard databases and the catalog database when the Oracle Sharding topology with System-Managed with RAFT Replication enabled is deployed using Oracle Sharding controller. + +**NOTE** In this use case, because DBCA creates the database automatically during the deployment, the time required to create the database is greater than the time it takes when the database is created by cloning from a Database Gold Image. + +This example uses `snr_ssharding_shard_prov.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` +* One Catalog Pod: `catalog` +* Namespace: `shns` +* `RAFT Replication` enabled + + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `snr_ssharding_shard_prov.yaml`. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + * In case you want to use the [Oracle Database 23ai Free](https://www.oracle.com/database/free/get-started/) Image for Database and GSM, then you will need to add the additional parameter `dbEdition: "free"` to the below .yaml file. + + +Use the file: [snr_ssharding_shard_prov.yaml](./snr_ssharding_shard_prov.yaml) for this use case as below: + +1. Deploy the `snr_ssharding_shard_prov.yaml` file: + ```sh + kubectl apply -f snr_ssharding_shard_prov.yaml + ``` +1. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + + # Check the logs of a particular pod. For example, to check status of pod "shard1-0": + kubectl logs -f pod/shard1-0 -n shns + ``` diff --git a/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_scale_in_delete_an_existing_shard.md b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_scale_in_delete_an_existing_shard.md new file mode 100644 index 00000000..fe3157ec --- /dev/null +++ b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_scale_in_delete_an_existing_shard.md @@ -0,0 +1,50 @@ +# Scale In - Delete an existing Shard from a working Oracle Sharded Database provisioned earlier with System-Managed Sharding with RAFT reolication enabled + +**NOTE: RAFT Replication Feature is available only for Oracle 23c RDBMS and Oracle 23c GSM version.** + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +This use case demonstrates how to delete an existing Shard from an existing Oracle Database sharding topology with System-Managed with RAFT Replication enabled provisioned using Oracle Database Sharding controller. + +**NOTE** The deletion of a shard is done after verifying the Chunks have been moved out of that shard. + +In this use case, the existing database Sharding is having: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Five sharding Pods: `shard1`,`shard2`,`shard3`,`shard4` and `shard5` +* One Catalog Pod: `catalog` +* Namespace: `shns` +* `RAFT Replication` enabled + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `snr_ssharding_shard_prov_delshard.yaml`. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + * In case you want to use the [Oracle Database 23ai Free](https://www.oracle.com/database/free/get-started/) Image for Database and GSM, then you will need to add the additional parameter `dbEdition: "free"` to the below .yaml file. + +NOTE: Use tag `isDelete: enable` to delete the shard you want. + +This use case deletes the shard `shard4` from the above Sharding Topology. + +Use the file: [snr_ssharding_shard_prov_delshard.yaml](./snr_ssharding_shard_prov_delshard.yaml) for this use case as below: + +1. Deploy the `snr_ssharding_shard_prov_delshard.yaml` file: + ```sh + kubectl apply -f snr_ssharding_shard_prov_delshard.yaml + ``` +2. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + +**NOTE:** After you apply `snr_ssharding_shard_prov_delshard.yaml`, the change may not be visible immediately. When the shard is removed, first the chunks will be moved out of that shard that is going to be deleted. + +To monitor the chunk movement, use the following command: + +```sh +# Switch to the primary GSM Container: +kubectl exec -i -t gsm1-0 -n shns /bin/bash + +# Check the status of the chunks and repeat to observe the chunk movement: +gdsctl config chunks +``` diff --git a/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_scale_out_add_shards.md b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_scale_out_add_shards.md new file mode 100644 index 00000000..03423e72 --- /dev/null +++ b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_scale_out_add_shards.md @@ -0,0 +1,37 @@ +# Scale Out - Add Shards to an existing Oracle Sharded Database provisioned earlier with System-Managed Sharding with RAFT replication enabled + +**NOTE: RAFT Replication Feature is available only for Oracle 23c RDBMS and Oracle 23c GSM version.** + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +This use case demonstrates adding a new shard to an existing Oracle Database sharding topology with System-Managed with RAFT Replication enabled provisioned earlier using Oracle Database Sharding controller. + +In this use case, the existing Oracle Database sharding topology is having: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` +* One Catalog Pod: `catalog` +* Namespace: `shns` +* `RAFT Replication` enabled + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `snr_ssharding_shard_prov_extshard.yaml`. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + * If the existing Sharding Topology was deployed using [Oracle Database 23ai Free](https://www.oracle.com/database/free/get-started/) Image for Database and GSM, then the additional parameter `dbEdition: "free"` will be needed for the below .yaml file as well. + +This use case adds two new shards `shard4`,`shard5` to above Sharding Topology. + +Use the file: [snr_ssharding_shard_prov_extshard.yaml](./snr_ssharding_shard_prov_extshard.yaml) for this use case as below: + +1. Deploy the `snr_ssharding_shard_prov_extshard.yaml` file: + ```sh + kubectl apply -f snr_ssharding_shard_prov_extshard.yaml + ``` +2. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + + # Check the logs of a particular pod. For example, to check status of pod "shard4-0": + kubectl logs -f pod/shard4-0 -n shns diff --git a/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov.yaml b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov.yaml new file mode 100644 index 00000000..efe3abec --- /dev/null +++ b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov.yaml @@ -0,0 +1,58 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + imagePullPolicy: "Always" + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + replicationType: "native" + isExternalSvc: False + isDeleteOraPvc: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns \ No newline at end of file diff --git a/docs/sharding/provisioning/shard_prov.yaml b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_chunks.yaml similarity index 50% rename from docs/sharding/provisioning/shard_prov.yaml rename to docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_chunks.yaml index 032abd68..a79eafdc 100644 --- a/docs/sharding/provisioning/shard_prov.yaml +++ b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_chunks.yaml @@ -2,6 +2,7 @@ # Copyright (c) 2022, Oracle and/or its affiliates. # Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. # +--- apiVersion: database.oracle.com/v1alpha1 kind: ShardingDatabase metadata: @@ -11,36 +12,50 @@ spec: shard: - name: shard1 storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary - name: shard2 storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary catalog: - name: catalog storageSizeInGb: 50 + imagePullPolicy: "Always" + envVars: + - name: "CATALOG_CHUNKS" + value: "120" gsm: - name: gsm1 + imagePullPolicy: "Always" storageSizeInGb: 50 - replicas: 1 - envVars: - - name: "SERVICE1_PARAMS" - value: "service_name=oltp_rw_svc;service_role=primary" - - name: "SERVICE2_PARAMS" - value: "service_name=oltp_ro_svc;service_role=primary" + region: primary - name: gsm2 + imagePullPolicy: "Always" storageSizeInGb: 50 - replicas: 1 - envVars: - - name: "SERVICE1_PARAMS" - value: "service_name=oltp_rw_svc;service_role=primary" - - name: "SERVICE2_PARAMS" - value: "service_name=oltp_ro_svc;service_role=primary" + region: standby storageClass: oci dbImage: container-registry.oracle.com/database/enterprise:latest dbImagePullSecret: ocr-reg-cred gsmImage: container-registry.oracle.com/database/gsm:latest gsmImagePullSecret: ocr-reg-cred - scriptsLocation: "set -ex;curl https://codeload.github.com/oracle/db-sharding/tar.gz/master | tar -xz --strip=4 db-sharding-master/docker-based-sharding-deployment/dockerfiles/21.3.0/scripts; cp -i -r scripts/* /opt/oracle/scripts/sharding/scripts/;cp -i -r scripts/*py /opt/oracle/scripts/sharding" - secret: db-user-pass - isExternalSvc: false + replicationType: "native" + isExternalSvc: False isDeleteOraPvc: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary namespace: shns - diff --git a/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_clone.yaml b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_clone.yaml new file mode 100644 index 00000000..218fda0a --- /dev/null +++ b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_clone.yaml @@ -0,0 +1,83 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volume.oc1.phx.abyhqljr3z3w72t6ay5eud7d5w3kdfhktfp6gwb6euy5tzwfaxgmbvwqlvsq + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volume.oc1.phx.abyhqljr3z3w72t6ay5eud7d5w3kdfhktfp6gwb6euy5tzwfaxgmbvwqlvsq + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volume.oc1.phx.abyhqljr3z3w72t6ay5eud7d5w3kdfhktfp6gwb6euy5tzwfaxgmbvwqlvsq + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volume.oc1.phx.abyhqljr3z3w72t6ay5eud7d5w3kdfhktfp6gwb6euy5tzwfaxgmbvwqlvsq + imagePullPolicy: "Always" + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + replicationType: "native" + isExternalSvc: False + isDeleteOraPvc: True + isClone: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns \ No newline at end of file diff --git a/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_clone_across_ads.yaml b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_clone_across_ads.yaml new file mode 100644 index 00000000..4eb3954a --- /dev/null +++ b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_clone_across_ads.yaml @@ -0,0 +1,91 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-2" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-2" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + imagePullPolicy: "Always" + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + replicationType: "native" + isExternalSvc: False + isDeleteOraPvc: True + isClone: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns \ No newline at end of file diff --git a/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_delshard.yaml b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_delshard.yaml new file mode 100644 index 00000000..145ef616 --- /dev/null +++ b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_delshard.yaml @@ -0,0 +1,69 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard4 + isDelete: enable + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard5 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + imagePullPolicy: "Always" + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + replicationType: "native" + isExternalSvc: False + isDeleteOraPvc: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns \ No newline at end of file diff --git a/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_extshard.yaml b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_extshard.yaml new file mode 100644 index 00000000..ea0c05a5 --- /dev/null +++ b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_extshard.yaml @@ -0,0 +1,68 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard4 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard5 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + imagePullPolicy: "Always" + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + replicationType: "native" + isExternalSvc: False + isDeleteOraPvc: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns \ No newline at end of file diff --git a/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_memory_cpu.yaml b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_memory_cpu.yaml new file mode 100644 index 00000000..5c15c724 --- /dev/null +++ b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_memory_cpu.yaml @@ -0,0 +1,89 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + resources: + requests: + memory: "1000Mi" + cpu: "1000m" + envVars: + - name: "INIT_SGA_SIZE" + value: "600" + - name: "INIT_PGA_SIZE" + value: "400" + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + resources: + requests: + memory: "1000Mi" + cpu: "1000m" + envVars: + - name: "INIT_SGA_SIZE" + value: "600" + - name: "INIT_PGA_SIZE" + value: "400" + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + resources: + requests: + memory: "1000Mi" + cpu: "1000m" + envVars: + - name: "INIT_SGA_SIZE" + value: "600" + - name: "INIT_PGA_SIZE" + value: "400" + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + resources: + requests: + memory: "1000Mi" + cpu: "1000m" + imagePullPolicy: "Always" + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + replicationType: "native" + isExternalSvc: False + isDeleteOraPvc: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns \ No newline at end of file diff --git a/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_send_notification.yaml b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_send_notification.yaml new file mode 100644 index 00000000..50c85443 --- /dev/null +++ b/docs/sharding/provisioning/snr_system_sharding/snr_ssharding_shard_prov_send_notification.yaml @@ -0,0 +1,85 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-2" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-2" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + imagePullPolicy: "Always" + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + replicationType: "native" + isExternalSvc: False + isDeleteOraPvc: True + isClone: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + nsConfigMap: onsconfigmap + nsSecret: my-secret + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns \ No newline at end of file diff --git a/docs/sharding/provisioning/provisioning_by_cloning_db_from_gold_image_across_ads.md b/docs/sharding/provisioning/system_sharding/ssharding_provisioning_by_cloning_db_from_gold_image_across_ads.md similarity index 55% rename from docs/sharding/provisioning/provisioning_by_cloning_db_from_gold_image_across_ads.md rename to docs/sharding/provisioning/system_sharding/ssharding_provisioning_by_cloning_db_from_gold_image_across_ads.md index 75a6f743..64e2f4eb 100644 --- a/docs/sharding/provisioning/provisioning_by_cloning_db_from_gold_image_across_ads.md +++ b/docs/sharding/provisioning/system_sharding/ssharding_provisioning_by_cloning_db_from_gold_image_across_ads.md @@ -1,6 +1,8 @@ -# Provisioning Oracle Database Sharding Topology by Cloning the Database from Your Own Database Gold Image Across Availability Domains (ADs) +# Provisioning Oracle Sharded Database with System-Managed Sharding by cloning database from your own Database Gold Image across Availability Domains(ADs) -In this test case, you provision the Oracle Database sharding topology while provisioning the Catalog and Shard Databases by cloning from an existing Oracle Database Gold Image created earlier. +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +In this test case, you provision the Oracle Database sharding topology with System-Managed Sharding while provisioning the Catalog and Shard Databases by cloning from an existing Oracle Database Gold Image created earlier. This use case applies when you want to provision the database Pods on a Kubernetes Node in any availability domain (AD), which can also be different from the availability domain (AD) of the Block Volume that has the Oracle Database Gold Image provisioned earlier. @@ -17,25 +19,31 @@ NOTE: ```sh kubectl get pv -n shns ``` -2. Create a Block Volume Backup for this Block Volume, and use the OCID of the Block Volume Backup in the next step. This example uses `shard_prov_clone_across_ads.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: +2. Create a Block Volume Backup for this Block Volume, and use the OCID of the Block Volume Backup in the next step. This example uses `ssharding_shard_prov_clone_across_ads.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: * Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` -* Two sharding Pods: `shard1` and `shard2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` * One Catalog Pod: `catalog` * Namespace: `shns` * Database Cloning from the `BLOCK VOLUME FULL BACKUP` of the Persistent Volume which had the Gold Image. -* OCID of the Block Volume Backup: `ocid1.volumebackup.oc1.eu-frankfurt-1.abtheljtjlc7oce3sgq55vnskb4sjdip5sdaighm54hpmlcg7avgc76pjbea` +* OCID of the Block Volume Backup: `ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq` + +NOTE: In this case, the Persistent Volume with DB Gold Image was provisioned in the Availability Domain `PHX-AD-1`. The Shards and Catalog will be provisioned across multiple Availability Domains by cloning the database. + + +**NOTE:** Provisioning the Sharded Database using Cloning from Database Gold Image is `NOT` supported with Oracle Database 23ai Free. In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. - * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `shard_prov_clone_across_ads.yaml`. - * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../README.md#3-oracle-database-and-global-data-services-docker-images) + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `ssharding_shard_prov_clone_across_ads.yaml`. + * The `dbImage` used during provisioning the Persistent Volume with Database Gold Image and the `dbImage` used for deploying the Shard or Catalog Database by cloning should be same. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) -Use the file: [shard_prov_clone_across_ads.yaml](./shard_prov_clone_across_ads.yaml) for this use case as below: +Use the file: [ssharding_shard_prov_clone_across_ads.yaml](./ssharding_shard_prov_clone_across_ads.yaml) for this use case as below: -1. Deploy the `shard_prov_clone_across_ads.yaml` file: +1. Deploy the `ssharding_shard_prov_clone_across_ads.yaml` file: ```sh - kubectl apply -f shard_prov_clone_across_ads.yaml + kubectl apply -f ssharding_shard_prov_clone_across_ads.yaml ``` 2. Check the status of the deployment: ```sh diff --git a/docs/sharding/provisioning/provisioning_by_cloning_db_gold_image_in_same_ad.md b/docs/sharding/provisioning/system_sharding/ssharding_provisioning_by_cloning_db_gold_image_in_same_ad.md similarity index 52% rename from docs/sharding/provisioning/provisioning_by_cloning_db_gold_image_in_same_ad.md rename to docs/sharding/provisioning/system_sharding/ssharding_provisioning_by_cloning_db_gold_image_in_same_ad.md index 531c3839..f7aef949 100644 --- a/docs/sharding/provisioning/provisioning_by_cloning_db_gold_image_in_same_ad.md +++ b/docs/sharding/provisioning/system_sharding/ssharding_provisioning_by_cloning_db_gold_image_in_same_ad.md @@ -1,4 +1,6 @@ -# Provisioning Oracle Database Sharding Topology by Cloning the Database from Your Own Database Gold Image in the same Availability Domain (AD) +# Provisioning Oracle Sharded Database with System-Managed Sharding by cloning database from your own Database Gold Image in the same Availability Domain(AD) + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. In this case, the database is created automatically by cloning from an existing Oracle Database Gold Image during the provisioning of the shard databases and the catalog database when the Oracle Sharding topology is deployed using Oracle Sharding controller. @@ -8,30 +10,35 @@ Choosing this option takes substantially less time during the Oracle Database Sh **NOTE** For this step, the Persistent Volume that has the Oracle Database Gold Image is identified using its OCID. -1. Check the OCID of the Persistent Volume provisioned by above step using below command: +1. Check the OCID of the Persistent Volume provisioned earlier using below command: ```sh kubectl get pv -n shns ``` -2. This example uses `shard_prov_clone.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: +2. This example uses `ssharding_shard_prov_clone.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: * Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` -* Two sharding Pods: `shard1` and `shard2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` * One Catalog Pod: `catalog` * Namespace: `shns` -* Database Cloning from the Database Gold Image present in Persistent Volume having OCID: `ocid1.volume.oc1.eu-frankfurt-1.abtheljtmwcwf7liuhaibzgdcoxqcwwfpsqiqlsumrjlzkin7y4zx3x2idua` +* Database Cloning from the Database Gold Image present in Persistent Volume having OCID: `ocid1.volume.oc1.phx.abyhqljr3z3w72t6ay5eud7d5w3kdfhktfp6gwb6euy5tzwfaxgmbvwqlvsq` + +**NOTE:** Provisioning the Sharded Database using Cloning from Database Gold Image is `NOT` supported with Oracle Database 23ai Free. + +NOTE: In this case, the Persistent Volume with DB Gold Image was provisioned in the Availability Domain `PHX-AD-1`. The Shards and Catalog will be provisioned in the same Availability Domain `PHX-AD-1` by cloning the database. In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. - * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `shard_prov.yaml`. - * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../README.md#3-oracle-database-and-global-data-services-docker-images) + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `ssharding_shard_prov_clone.yaml`. + * The `dbImage` used during provisioning the Persistent Volume with Database Gold Image and the `dbImage` used for deploying the Shard or Catalog Database by cloning should be same. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) -Use the file: [shard_prov_clone.yaml](./shard_prov_clone.yaml) for this use case as below: +Use the file: [ssharding_shard_prov_clone.yaml](./ssharding_shard_prov_clone.yaml) for this use case as below: -1. Deploy the `shard_prov_clone.yaml` file: +1. Deploy the `ssharding_shard_prov_clone.yaml` file: ```sh - kubectl apply -f shard_prov_clone.yaml + kubectl apply -f ssharding_shard_prov_clone.yaml ``` 2. Check the status of the deployment: ```sh diff --git a/docs/sharding/provisioning/system_sharding/ssharding_provisioning_with_chunks_specified.md b/docs/sharding/provisioning/system_sharding/ssharding_provisioning_with_chunks_specified.md new file mode 100644 index 00000000..0c6ea8fe --- /dev/null +++ b/docs/sharding/provisioning/system_sharding/ssharding_provisioning_with_chunks_specified.md @@ -0,0 +1,40 @@ +# Provisioning Oracle Sharded Database with System-Managed Sharding with number of chunks specified + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +In this use case, the database is created automatically using DBCA during the provisioning of the shard databases and the catalog database when the Oracle Sharding topology with System-Managed Sharding is deployed using Oracle Sharding controller. + +**NOTE:** In this use case, because DBCA creates the database automatically during the deployment, the time required to create the database is greater than the time it takes when the database is created by cloning from a Database Gold Image. + +By default, the System-Managed Sharding deploys the Sharded Database with 120 chunks per Shard Database. If, for example, we have three shards in the Sharded Database, it will be total of 360 chunks. In this example, the Sharded Database will be deployed with non-default number of chunks specified using parameter `CATALOG_CHUNKS`. + +This example uses `ssharding_shard_prov_chunks.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` +* One Catalog Pod: `catalog` +* Total number of chunks as `120` specified by variable `CATALOG_CHUNKS` (it will be 40 chunks per shard) +* Namespace: `shns` + + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `ssharding_shard_prov.yaml`. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + * In case you want to use the [Oracle Database 23ai Free](https://www.oracle.com/database/free/get-started/) Image for Database and GSM, then you will need to add the additional parameter `dbEdition: "free"` to the below .yaml file. + + +Use the file: [ssharding_shard_prov_chunks.yaml](./ssharding_shard_prov_chunks.yaml) for this use case as below: + +1. Deploy the `ssharding_shard_prov_chunks.yaml` file: + ```sh + kubectl apply -f ssharding_shard_prov_chunks.yaml + ``` +1. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + + # Check the logs of a particular pod. For example, to check status of pod "shard1-0": + kubectl logs -f pod/shard1-0 -n shns + ``` diff --git a/docs/sharding/provisioning/system_sharding/ssharding_provisioning_with_control_on_resources.md b/docs/sharding/provisioning/system_sharding/ssharding_provisioning_with_control_on_resources.md new file mode 100644 index 00000000..c4f45a48 --- /dev/null +++ b/docs/sharding/provisioning/system_sharding/ssharding_provisioning_with_control_on_resources.md @@ -0,0 +1,44 @@ +# Provisioning Oracle Sharded Database with System-Managed Sharding with additional control on resources like Memory and CPU allocated to Pods + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +In this use case, there are additional tags used to control resources such as CPU and Memory used by the different Pods when the Oracle Sharding topology with System-Managed Sharding is deployed using Oracle Sharding controller. + +This example uses `ssharding_shard_prov_memory_cpu.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` +* One Catalog Pod: `catalog` +* Namespace: `shns` +* Tags `memory` and `cpu` to control the Memory and CPU of the PODs +* Additional tags `INIT_SGA_SIZE` and `INIT_PGA_SIZE` to control the SGA and PGA allocation at the database level + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `ssharding_shard_prov_memory_cpu.yaml`. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + * In case you want to use the [Oracle Database 23ai Free](https://www.oracle.com/database/free/get-started/) Image for Database and GSM, then you will need to add the additional parameter `dbEdition: "free"` to the below .yaml file. + + **NOTE:** For Oracle Database 23ai Free, you can control the `CPU` and `Memory` allocation of the PODs using tags `cpu` and `memory` respectively but tags `INIT_SGA_SIZE` and `INIT_PGA_SIZE` to control the SGA and PGA allocation at the database level are `not` supported. + +Use the YAML file [ssharding_shard_prov_memory_cpu.yaml](./ssharding_shard_prov_memory_cpu.yaml). + +1. Deploy the `ssharding_shard_prov_memory_cpu.yaml` file: + + ```sh + kubectl apply -f ssharding_shard_prov_memory_cpu.yaml + ``` + +1. Check the details of a POD. For example: To check the details of Pod `shard1-0`: + + ```sh + kubectl describe pod/shard1-0 -n shns + ``` +3. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + + # Check the logs of a particular pod. For example, to check status of pod "shard1-0": + kubectl logs -f pod/shard1-0 -n shns + ``` diff --git a/docs/sharding/provisioning/provisioning_with_notification_using_oci_notification.md b/docs/sharding/provisioning/system_sharding/ssharding_provisioning_with_notification_using_oci_notification.md similarity index 65% rename from docs/sharding/provisioning/provisioning_with_notification_using_oci_notification.md rename to docs/sharding/provisioning/system_sharding/ssharding_provisioning_with_notification_using_oci_notification.md index 7df7bc05..1a6a1ee3 100644 --- a/docs/sharding/provisioning/provisioning_with_notification_using_oci_notification.md +++ b/docs/sharding/provisioning/system_sharding/ssharding_provisioning_with_notification_using_oci_notification.md @@ -1,15 +1,17 @@ -# Provisioning Oracle Database Sharding Topology and Send Notification Using OCI Notification Service +# Provisioning Oracle Sharded Database with System-Managed Sharding and send Notification using OCI Notification Service -This use case demonstrates how to use a notification service like OCI Notification service to send an email notification when a particular operation is completed on an Oracle Database sharding topology provisioned using the Oracle Database sharding controller. +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. -This example uses `shard_prov_send_notification.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: +This use case demonstrates how to use a notification service like OCI Notification service to send an email notification when a particular operation is completed on an Oracle Database sharding topology provisioned using the Oracle Database sharding controller. + +This example uses `ssharding_shard_prov_send_notification.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: * Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` -* Two sharding Pods: `shard1` and `shard2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` * One Catalog Pod: `catalog` * Namespace: `shns` * Database Cloning from the `BLOCK VOLUME FULL BACKUP` of the Persistent Volume that has the Database Gold Image created earlier. -* OCID of the Block Volume Backup: `ocid1.volumebackup.oc1.eu-frankfurt-1.abtheljtjlc7oce3sgq55vnskb4sjdip5sdaighm54hpmlcg7avgc76pjbea` +* OCID of the Block Volume Backup: `ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq` * Configmap to send notification email when a particular operation is completed. For example: When a shard is added. **NOTE:** @@ -26,8 +28,8 @@ To do this: user=ocid1.user.oc1........fx7omxfq fingerprint=fa:18:98:...............:8a tenancy=ocid1.tenancy.oc1..aaaa.......orpn7inq - region=eu-frankfurt-1 - topicid=ocid1.onstopic.oc1.eu-frankfurt-1.aaa............6xrq + region=us-phoenix-1 + topicid=ocid1.onstopic.oc1.phx.aaa............6xrq ``` 2. Create a configmap using the below command using the file created above: ```sh @@ -61,14 +63,17 @@ To do this: In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. - * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `shard_prov.yaml`. - * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../README.md#3-oracle-database-and-global-data-services-docker-images) + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `ssharding_shard_prov_send_notification.yaml`. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + * In case you want to use the [Oracle Database 23ai Free](https://www.oracle.com/database/free/get-started/) Image for Database and GSM, then you will need to add the additional parameter `dbEdition: "free"` to the below .yaml file. + +**NOTE:** Provisioning the Sharded Database using Cloning from Database Gold Image is `NOT` supported with Oracle Database 23ai Free. -Use the file: [shard_prov_send_notification.yaml](./shard_prov_send_notification.yaml) for this use case as below: +Use the file: [ssharding_shard_prov_send_notification.yaml](./ssharding_shard_prov_send_notification.yaml) for this use case as below: -1. Deploy the `shard_prov_send_notification.yaml` file: +1. Deploy the `ssharding_shard_prov_send_notification.yaml` file: ```sh - kubectl apply -f shard_prov_send_notification.yaml + kubectl apply -f ssharding_shard_prov_send_notification.yaml ``` 2. Check the status of the deployment: ```sh diff --git a/docs/sharding/provisioning/system_sharding/ssharding_provisioning_without_db_gold_image.md b/docs/sharding/provisioning/system_sharding/ssharding_provisioning_without_db_gold_image.md new file mode 100644 index 00000000..b223d1af --- /dev/null +++ b/docs/sharding/provisioning/system_sharding/ssharding_provisioning_without_db_gold_image.md @@ -0,0 +1,37 @@ +# Provisioning Oracle Sharded Database with System-Managed Sharding without Database Gold Image + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +In this use case, the database is created automatically using DBCA during the provisioning of the shard databases and the catalog database when the Oracle Sharding topology with System-Managed Sharding is deployed using Oracle Sharding controller. + +**NOTE:** In this use case, because DBCA creates the database automatically during the deployment, the time required to create the database is greater than the time it takes when the database is created by cloning from a Database Gold Image. + +This example uses `ssharding_shard_prov.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` +* One Catalog Pod: `catalog` +* Namespace: `shns` + + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `ssharding_shard_prov.yaml`. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + * In case you want to use the [Oracle Database 23ai Free](https://www.oracle.com/database/free/get-started/) Image for Database and GSM, then you will need to add the additional parameter `dbEdition: "free"` to the below .yaml file. + + +Use the file: [ssharding_shard_prov.yaml](./ssharding_shard_prov.yaml) for this use case as below: + +1. Deploy the `ssharding_shard_prov.yaml` file: + ```sh + kubectl apply -f ssharding_shard_prov.yaml + ``` +1. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + + # Check the logs of a particular pod. For example, to check status of pod "shard1-0": + kubectl logs -f pod/shard1-0 -n shns + ``` \ No newline at end of file diff --git a/docs/sharding/provisioning/system_sharding/ssharding_scale_in_delete_an_existing_shard.md b/docs/sharding/provisioning/system_sharding/ssharding_scale_in_delete_an_existing_shard.md new file mode 100644 index 00000000..bca34253 --- /dev/null +++ b/docs/sharding/provisioning/system_sharding/ssharding_scale_in_delete_an_existing_shard.md @@ -0,0 +1,47 @@ +# Scale In - Delete an existing Shard from a working Oracle Sharded Database provisioned earlier with System-Managed Sharding + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +This use case demonstrates how to delete an existing Shard from an existing Oracle Database sharding topology with System-Managed Sharding provisioned using Oracle Database Sharding controller. + +**NOTE** The deletion of a shard is done after verifying the Chunks have been moved out of that shard. + +In this use case, the existing database Sharding is having: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Five sharding Pods: `shard1`,`shard2`,`shard3`,`shard4` and `shard5` +* One Catalog Pod: `catalog` +* Namespace: `shns` + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `ssharding_shard_prov_delshard.yaml`. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + * In case you want to use the [Oracle Database 23ai Free](https://www.oracle.com/database/free/get-started/) Image for Database and GSM, then you will need to add the additional parameter `dbEdition: "free"` to the below .yaml file. + +NOTE: Use tag `isDelete: enable` to delete the shard you want. + +This use case deletes the shard `shard4` from the above Sharding Topology. + +Use the file: [ssharding_shard_prov_delshard.yaml](./ssharding_shard_prov_delshard.yaml) for this use case as below: + +1. Deploy the `ssharding_shard_prov_delshard.yaml` file: + ```sh + kubectl apply -f ssharding_shard_prov_delshard.yaml + ``` +2. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + +**NOTE:** After you apply `ssharding_shard_prov_delshard.yaml`, the change may not be visible immediately. When the shard is removed, first the chunks will be moved out of that shard that is going to be deleted. + +To monitor the chunk movement, use the following command: + +```sh +# Switch to the primary GSM Container: +kubectl exec -i -t gsm1-0 -n shns /bin/bash + +# Check the status of the chunks and repeat to observe the chunk movement: +gdsctl config chunks +``` diff --git a/docs/sharding/provisioning/system_sharding/ssharding_scale_out_add_shards.md b/docs/sharding/provisioning/system_sharding/ssharding_scale_out_add_shards.md new file mode 100644 index 00000000..1db8e6c3 --- /dev/null +++ b/docs/sharding/provisioning/system_sharding/ssharding_scale_out_add_shards.md @@ -0,0 +1,34 @@ +# Scale Out - Add Shards to an existing Oracle Sharded Database provisioned earlier with System-Managed Sharding + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +This use case demonstrates adding a new shard to an existing Oracle Database sharding topology with System-Managed Sharding provisioned earlier using Oracle Database Sharding controller. + +In this use case, the existing Oracle Database sharding topology is having: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` +* One Catalog Pod: `catalog` +* Namespace: `shns` + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `ssharding_shard_prov_extshard.yaml`. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + * If the existing Sharding Topology was deployed using [Oracle Database 23ai Free](https://www.oracle.com/database/free/get-started/) Image for Database and GSM, then the additional parameter `dbEdition: "free"` will be needed for the below .yaml file as well. + +This use case adds two new shards `shard4`,`shard5` to above Sharding Topology. + +Use the file: [ssharding_shard_prov_extshard.yaml](./ssharding_shard_prov_extshard.yaml) for this use case as below: + +1. Deploy the `ssharding_shard_prov_extshard.yaml` file: + ```sh + kubectl apply -f ssharding_shard_prov_extshard.yaml + ``` +2. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + + # Check the logs of a particular pod. For example, to check status of pod "shard4-0": + kubectl logs -f pod/shard4-0 -n shns diff --git a/docs/sharding/provisioning/system_sharding/ssharding_shard_prov.yaml b/docs/sharding/provisioning/system_sharding/ssharding_shard_prov.yaml new file mode 100644 index 00000000..7d4e16ec --- /dev/null +++ b/docs/sharding/provisioning/system_sharding/ssharding_shard_prov.yaml @@ -0,0 +1,57 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + imagePullPolicy: "Always" + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + isExternalSvc: False + isDeleteOraPvc: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns diff --git a/docs/sharding/provisioning/system_sharding/ssharding_shard_prov_clone.yaml b/docs/sharding/provisioning/system_sharding/ssharding_shard_prov_clone.yaml new file mode 100644 index 00000000..9a690626 --- /dev/null +++ b/docs/sharding/provisioning/system_sharding/ssharding_shard_prov_clone.yaml @@ -0,0 +1,82 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volume.oc1.phx.abyhqljr3z3w72t6ay5eud7d5w3kdfhktfp6gwb6euy5tzwfaxgmbvwqlvsq + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volume.oc1.phx.abyhqljr3z3w72t6ay5eud7d5w3kdfhktfp6gwb6euy5tzwfaxgmbvwqlvsq + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volume.oc1.phx.abyhqljr3z3w72t6ay5eud7d5w3kdfhktfp6gwb6euy5tzwfaxgmbvwqlvsq + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volume.oc1.phx.abyhqljr3z3w72t6ay5eud7d5w3kdfhktfp6gwb6euy5tzwfaxgmbvwqlvsq + imagePullPolicy: "Always" + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + isExternalSvc: False + isDeleteOraPvc: True + isClone: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns diff --git a/docs/sharding/provisioning/system_sharding/ssharding_shard_prov_clone_across_ads.yaml b/docs/sharding/provisioning/system_sharding/ssharding_shard_prov_clone_across_ads.yaml new file mode 100644 index 00000000..b7dd1397 --- /dev/null +++ b/docs/sharding/provisioning/system_sharding/ssharding_shard_prov_clone_across_ads.yaml @@ -0,0 +1,90 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-2" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-2" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + imagePullPolicy: "Always" + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + isExternalSvc: False + isDeleteOraPvc: True + isClone: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns diff --git a/docs/sharding/provisioning/system_sharding/ssharding_shard_prov_delshard.yaml b/docs/sharding/provisioning/system_sharding/ssharding_shard_prov_delshard.yaml new file mode 100644 index 00000000..75caca31 --- /dev/null +++ b/docs/sharding/provisioning/system_sharding/ssharding_shard_prov_delshard.yaml @@ -0,0 +1,68 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard4 + isDelete: enable + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard5 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + imagePullPolicy: "Always" + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + isExternalSvc: False + isDeleteOraPvc: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns \ No newline at end of file diff --git a/docs/sharding/provisioning/system_sharding/ssharding_shard_prov_extshard.yaml b/docs/sharding/provisioning/system_sharding/ssharding_shard_prov_extshard.yaml new file mode 100644 index 00000000..d25dc901 --- /dev/null +++ b/docs/sharding/provisioning/system_sharding/ssharding_shard_prov_extshard.yaml @@ -0,0 +1,67 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard4 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard5 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + imagePullPolicy: "Always" + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + isExternalSvc: False + isDeleteOraPvc: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns \ No newline at end of file diff --git a/docs/sharding/provisioning/shard_prov_memory_cpu.yaml b/docs/sharding/provisioning/system_sharding/ssharding_shard_prov_memory_cpu.yaml similarity index 60% rename from docs/sharding/provisioning/shard_prov_memory_cpu.yaml rename to docs/sharding/provisioning/system_sharding/ssharding_shard_prov_memory_cpu.yaml index 0e66c563..793a3e4d 100644 --- a/docs/sharding/provisioning/shard_prov_memory_cpu.yaml +++ b/docs/sharding/provisioning/system_sharding/ssharding_shard_prov_memory_cpu.yaml @@ -2,6 +2,7 @@ # Copyright (c) 2022, Oracle and/or its affiliates. # Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. # +--- apiVersion: database.oracle.com/v1alpha1 kind: ShardingDatabase metadata: @@ -20,6 +21,9 @@ spec: value: "600" - name: "INIT_PGA_SIZE" value: "400" + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary - name: shard2 storageSizeInGb: 50 resources: @@ -31,6 +35,23 @@ spec: value: "600" - name: "INIT_PGA_SIZE" value: "400" + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + resources: + requests: + memory: "1000Mi" + cpu: "1000m" + envVars: + - name: "INIT_SGA_SIZE" + value: "600" + - name: "INIT_PGA_SIZE" + value: "400" + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary catalog: - name: catalog storageSizeInGb: 50 @@ -38,30 +59,30 @@ spec: requests: memory: "1000Mi" cpu: "1000m" + imagePullPolicy: "Always" gsm: - name: gsm1 + imagePullPolicy: "Always" storageSizeInGb: 50 - replicas: 1 - envVars: - - name: "SERVICE1_PARAMS" - value: "service_name=oltp_rw_svc;service_role=primary" - - name: "SERVICE2_PARAMS" - value: "service_name=oltp_ro_svc;service_role=primary" + region: primary - name: gsm2 + imagePullPolicy: "Always" storageSizeInGb: 50 - replicas: 1 - envVars: - - name: "SERVICE1_PARAMS" - value: "service_name=oltp_rw_svc;service_role=primary" - - name: "SERVICE2_PARAMS" - value: "service_name=oltp_ro_svc;service_role=primary" + region: standby storageClass: oci dbImage: container-registry.oracle.com/database/enterprise:latest dbImagePullSecret: ocr-reg-cred gsmImage: container-registry.oracle.com/database/gsm:latest gsmImagePullSecret: ocr-reg-cred - scriptsLocation: "set -ex;curl https://codeload.github.com/oracle/db-sharding/tar.gz/master | tar -xz --strip=4 db-sharding-master/docker-based-sharding-deployment/dockerfiles/21.3.0/scripts; cp -i -r scripts/* /opt/oracle/scripts/sharding/scripts/;cp -i -r scripts/*py /opt/oracle/scripts/sharding" - secret: db-user-pass - isExternalSvc: false + isExternalSvc: False isDeleteOraPvc: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary namespace: shns diff --git a/docs/sharding/provisioning/system_sharding/ssharding_shard_prov_send_notification.yaml b/docs/sharding/provisioning/system_sharding/ssharding_shard_prov_send_notification.yaml new file mode 100644 index 00000000..96217b74 --- /dev/null +++ b/docs/sharding/provisioning/system_sharding/ssharding_shard_prov_send_notification.yaml @@ -0,0 +1,85 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-2" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-2" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + imagePullPolicy: "Always" + shardGroup: shardgroup1 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + imagePullPolicy: "Always" + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + isExternalSvc: False + isDeleteOraPvc: True + isClone: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + nsConfigMap: onsconfigmap + nsSecret: my-secret + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns + diff --git a/docs/sharding/provisioning/user-defined-sharding/udsharding_provisioning_by_cloning_db_from_gold_image_across_ads.md b/docs/sharding/provisioning/user-defined-sharding/udsharding_provisioning_by_cloning_db_from_gold_image_across_ads.md new file mode 100644 index 00000000..9b2905e8 --- /dev/null +++ b/docs/sharding/provisioning/user-defined-sharding/udsharding_provisioning_by_cloning_db_from_gold_image_across_ads.md @@ -0,0 +1,55 @@ +# Provisioning Oracle Sharded Database with User Defined Sharding by cloning database from your own Database Gold Image across Availability Domains(ADs) + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +In this test case, you provision the Oracle Database sharding topology with User Defined Sharding while provisioning the Catalog and Shard Databases by cloning from an existing Oracle Database Gold Image created earlier. + +This use case applies when you want to provision the database Pods on a Kubernetes Node in any availability domain (AD), which can also be different from the availability domain (AD) of the Block Volume that has the Oracle Database Gold Image provisioned earlier. + +Choosing this option takes substantially less time during the Oracle Database Sharding Topology setup across ADs. + +NOTE: + +* Cloning from Block Volume Backup in OCI enables the new Persistent Volumes to be created in other ADs. +* To specify the AD where you want to provision the database Pod, use the tag `nodeSelector` and the POD will be provisioned in a node running in that AD. +* To specify GSM containers, you can also use the tag `nodeSelector` to specify the AD. +* Before you can provision with the Gold Image, you need the OCID of the Persistent Volume that has the Oracle Database Gold Image. + +1. Check the OCID of the Persistent Volume provisioned for the Oracle Database Gold Image: + ```sh + kubectl get pv -n shns + ``` +2. Create a Block Volume Backup for this Block Volume, and use the OCID of the Block Volume Backup in the next step. This example uses `udsharding_shard_prov_clone_across_ads.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` +* One Catalog Pod: `catalog` +* Namespace: `shns` +* Database Cloning from the `BLOCK VOLUME FULL BACKUP` of the Persistent Volume which had the Gold Image. +* OCID of the Block Volume Backup: `ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq` +* User Defined Sharding is specified using `shardingType: USER` + +NOTE: In this case, the Persistent Volume with DB Gold Image was provisioned in the Availability Domain `PHX-AD-1`. The Shards and Catalog will be provisioned across multiple Availability Domains by cloning the database. + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `udsharding_shard_prov_clone_across_ads.yaml`. + * The `dbImage` used during provisioning the Persistent Volume with Database Gold Image and the `dbImage` used for deploying the Shard or Catalog Database by cloning should be same. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + +**NOTE:** Provisioning the Sharded Database using Cloning from Database Gold Image is `NOT` supported with Oracle Database 23ai Free. + +Use the file: [udsharding_shard_prov_clone_across_ads.yaml](./udsharding_shard_prov_clone_across_ads.yaml) for this use case as below: + +1. Deploy the `udsharding_shard_prov_clone_across_ads.yaml` file: + ```sh + kubectl apply -f udsharding_shard_prov_clone_across_ads.yaml + ``` +2. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + + # Check the logs of a particular pod. For example, to check status of pod "shard1-0": + kubectl logs -f pod/shard1-0 -n shns + diff --git a/docs/sharding/provisioning/user-defined-sharding/udsharding_provisioning_by_cloning_db_gold_image_in_same_ad.md b/docs/sharding/provisioning/user-defined-sharding/udsharding_provisioning_by_cloning_db_gold_image_in_same_ad.md new file mode 100644 index 00000000..a4669667 --- /dev/null +++ b/docs/sharding/provisioning/user-defined-sharding/udsharding_provisioning_by_cloning_db_gold_image_in_same_ad.md @@ -0,0 +1,51 @@ +# Provisioning Oracle Sharded Database with User Defined Sharding by cloning database from your own Database Gold Image in the same Availability Domain(AD) + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +In this case, the database is created automatically by cloning from an existing Oracle Database Gold Image during the provisioning of the shard databases and the catalog database when the Oracle Sharding topology is deployed using Oracle Sharding controller. + +This use case applies when you are cloning from a Block Volume, and you can clone _only_ in the same availability domain (AD). The result is that the cloned shard database PODs can be created _only_ in the same AD where the Gold Image Block Volume is present. + +Choosing this option takes substantially less time during the Oracle Database Sharding Topology setup. + +**NOTE** For this step, the Persistent Volume that has the Oracle Database Gold Image is identified using its OCID. + +1. Check the OCID of the Persistent Volume provisioned earlier using below command: + + ```sh + kubectl get pv -n shns + ``` + +2. This example uses `udsharding_shard_prov_clone.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` +* One Catalog Pod: `catalog` +* Namespace: `shns` +* Database Cloning from the Database Gold Image present in Persistent Volume having OCID: `ocid1.volume.oc1.phx.abyhqljr3z3w72t6ay5eud7d5w3kdfhktfp6gwb6euy5tzwfaxgmbvwqlvsq` +* User Defined Sharding is specified using `shardingType: USER` + +NOTE: In this case, the Persistent Volume with DB Gold Image was provisioned in the Availability Domain `PHX-AD-1`. The Shards and Catalog will be provisioned in the same Availability Domain `PHX-AD-1` by cloning the database. + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `ssharding_shard_prov_clone.yaml`. + * The `dbImage` used during provisioning the Persistent Volume with Database Gold Image and the `dbImage` used for deploying the Shard or Catalog Database by cloning should be same. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + +**NOTE:** Provisioning the Sharded Database using Cloning from Database Gold Image is `NOT` supported with Oracle Database 23ai Free. + +Use the file: [udsharding_shard_prov_clone.yaml](./udsharding_shard_prov_clone.yaml) for this use case as below: + +1. Deploy the `udsharding_shard_prov_clone.yaml` file: + ```sh + kubectl apply -f udsharding_shard_prov_clone.yaml + ``` +2. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + + # Check the logs of a particular pod. For example, to check status of pod "shard1-0": + kubectl logs -f pod/shard1-0 -n shns + ``` diff --git a/docs/sharding/provisioning/user-defined-sharding/udsharding_provisioning_with_control_on_resources.md b/docs/sharding/provisioning/user-defined-sharding/udsharding_provisioning_with_control_on_resources.md new file mode 100644 index 00000000..b52b8745 --- /dev/null +++ b/docs/sharding/provisioning/user-defined-sharding/udsharding_provisioning_with_control_on_resources.md @@ -0,0 +1,45 @@ +# Provisioning Oracle Sharded Database with User Defined Sharding with additional control on resources like Memory and CPU allocated to Pods + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +In this use case, there are additional tags used to control resources such as CPU and Memory used by the different Pods when the Oracle Sharding topology with User Defined Sharding is deployed using Oracle Sharding controller. + +This example uses `udsharding_shard_prov_memory_cpu.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` +* One Catalog Pod: `catalog` +* Namespace: `shns` +* Tags `memory` and `cpu` to control the Memory and CPU of the PODs +* Additional tags `INIT_SGA_SIZE` and `INIT_PGA_SIZE` to control the SGA and PGA allocation at the database level +* User Defined Sharding is specified using `shardingType: USER` + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `udsharding_shard_prov_memory_cpu.yaml`. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + * In case you want to use the [Oracle Database 23ai Free](https://www.oracle.com/database/free/get-started/) Image for Database and GSM, then you will need to add the additional parameter `dbEdition: "free"` to the below .yaml file. + +**NOTE:** For Oracle Database 23ai Free, you can control the `CPU` and `Memory` allocation of the PODs using tags `cpu` and `memory` respectively but tags `INIT_SGA_SIZE` and `INIT_PGA_SIZE` to control the SGA and PGA allocation at the database level are `not` supported. + +Use the YAML file [udsharding_shard_prov_memory_cpu.yaml](./udsharding_shard_prov_memory_cpu.yaml). + +1. Deploy the `udsharding_shard_prov_memory_cpu.yaml` file: + + ```sh + kubectl apply -f udsharding_shard_prov_memory_cpu.yaml + ``` + +1. Check the details of a POD. For example: To check the details of Pod `shard1-0`: + + ```sh + kubectl describe pod/shard1-0 -n shns + ``` +3. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + + # Check the logs of a particular pod. For example, to check status of pod "shard1-0": + kubectl logs -f pod/shard1-0 -n shns + ``` diff --git a/docs/sharding/provisioning/user-defined-sharding/udsharding_provisioning_with_notification_using_oci_notification.md b/docs/sharding/provisioning/user-defined-sharding/udsharding_provisioning_with_notification_using_oci_notification.md new file mode 100644 index 00000000..640301a2 --- /dev/null +++ b/docs/sharding/provisioning/user-defined-sharding/udsharding_provisioning_with_notification_using_oci_notification.md @@ -0,0 +1,85 @@ +# Provisioning Oracle Sharded Database with User Defined Sharding and send Notification using OCI Notification Service + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +This use case demonstrates how to use a notification service like OCI Notification service to send an email notification when a particular operation is completed on an Oracle Database sharding topology provisioned using the Oracle Database sharding controller. + +This example uses `udsharding_shard_prov_send_notification.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` +* One Catalog Pod: `catalog` +* Namespace: `shns` +* Database Cloning from the `BLOCK VOLUME FULL BACKUP` of the Persistent Volume that has the Database Gold Image created earlier. +* OCID of the Block Volume Backup: `ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq` +* Configmap to send notification email when a particular operation is completed. For example: When a shard is added. +* User Defined Sharding is specified using `shardingType: USER` + +**NOTE:** + +* The notification will be sent using a configmap created with the credentials of the OCI user account in this use case. + +We will create a topic in Notification Service of the OCI Console and use its OCID. + +To do this: + +1. Create a `configmap_data.txt` file, such as the following, which has the OCI User details that will be used to send notfication: + + ```sh + user=ocid1.user.oc1........fx7omxfq + fingerprint=fa:18:98:...............:8a + tenancy=ocid1.tenancy.oc1..aaaa.......orpn7inq + region=us-phoenix-1 + topicid=ocid1.onstopic.oc1.phx.aaa............6xrq + ``` +2. Create a configmap using the below command using the file created above: + ```sh + kubectl create configmap onsconfigmap --from-file=./configmap_data.txt -n shns + ``` + +3. Create a key file `priavatekey` having the PEM key of the OCI user being used to send notification: + ```sh + -----BEGIN PRIVATE KEY-G---- + MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXYxA0DJvEwtVR + +o4OxrunL3L2NZJRADTFR+TDHqrNF1JwbaFBizSdL+EXbxQW1faZs5lXZ/sVmQF9 + . + . + . + zn/xWC0FzXGRzfvYHhq8XT3omf6L47KqIzqo3jDKdgvVq4u+lb+fXJlhj6Rwi99y + QEp36HnZiUxAQnR331DacN+YSTE+vpzSwZ38OP49khAB1xQsbiv1adG7CbNpkxpI + nS7CkDLg4Hcs4b9bGLHYJVY= + -----END PRIVATE KEY----- + ``` +4. Use the key file `privatekey` to create a Kubernetes secret in namespace `shns`: + + ```sh + kubectl create secret generic my-secret --from-file=./privatekey -n shns + ``` + +5. Use this command to check details of the secret that you created: + + ```sh + kubectl describe secret my-secret -n shns + ``` + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `udsharding_shard_prov_send_notification.yaml`. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + * In case you want to use the [Oracle Database 23ai Free](https://www.oracle.com/database/free/get-started/) Image for Database and GSM, then you will need to add the additional parameter `dbEdition: "free"` to the below .yaml file. + +**NOTE:** Provisioning the Sharded Database using Cloning from Database Gold Image is `NOT` supported with Oracle Database 23ai Free. + +Use the file: [udsharding_shard_prov_send_notification.yaml](./udsharding_shard_prov_send_notification.yaml) for this use case as below: + +1. Deploy the `udsharding_shard_prov_send_notification.yaml` file: + ```sh + kubectl apply -f udsharding_shard_prov_send_notification.yaml + ``` +2. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + + # Check the logs of a particular pod. For example, to check status of pod "shard1-0": + kubectl logs -f pod/shard1-0 -n shns diff --git a/docs/sharding/provisioning/provisioning_without_db_gold_image.md b/docs/sharding/provisioning/user-defined-sharding/udsharding_provisioning_without_db_gold_image.md similarity index 52% rename from docs/sharding/provisioning/provisioning_without_db_gold_image.md rename to docs/sharding/provisioning/user-defined-sharding/udsharding_provisioning_without_db_gold_image.md index 0a908b52..2be5ac9f 100644 --- a/docs/sharding/provisioning/provisioning_without_db_gold_image.md +++ b/docs/sharding/provisioning/user-defined-sharding/udsharding_provisioning_without_db_gold_image.md @@ -1,28 +1,31 @@ -# Provisioning Oracle Database Sharding Topology Without Database Gold Image +# Provisioning Oracle Sharded Database with User Defined Sharding without Database Gold Image -In this use case, the database is created automatically using DBCA during the provisioning of the shard databases and the catalog database when the Oracle Sharding topology is deployed using Oracle Sharding controller. +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +In this use case, the database is created automatically using DBCA during the provisioning of the shard databases and the catalog database when the Oracle Sharding topology with User Defined Sharding is deployed using Oracle Sharding controller. **NOTE** In this use case, because DBCA creates the database automatically during the deployment, the time required to create the database is greater than the time it takes when the database is created by cloning from a Database Gold Image. -This example uses `shard_prov.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: +This example uses `udsharding_shard_prov.yaml` to provision an Oracle Database sharding topology using Oracle Sharding controller with: * Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` -* Two sharding Pods: `shard1` and `shard2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` * One Catalog Pod: `catalog` * Namespace: `shns` +* User Defined Sharding is specified using `shardingType: USER` In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. - * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `shard_prov.yaml`. - * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../README.md#3-oracle-database-and-global-data-services-docker-images) - + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `udsharding_shard_prov.yaml`. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + * In case you want to use the [Oracle Database 23ai Free](https://www.oracle.com/database/free/get-started/) Image for Database and GSM, then you will need to add the additional parameter `dbEdition: "free"` to the below .yaml file. -Use the file: [shard_prov.yaml](./shard_prov.yaml) for this use case as below: +Use the file: [udsharding_shard_prov.yaml](./udsharding_shard_prov.yaml) for this use case as below: -1. Deploy the `shard_prov.yaml` file: +1. Deploy the `udsharding_shard_prov.yaml` file: ```sh - kubectl apply -f shard_prov.yaml + kubectl apply -f udsharding_shard_prov.yaml ``` 1. Check the status of the deployment: ```sh diff --git a/docs/sharding/provisioning/user-defined-sharding/udsharding_scale_in_delete_an_existing_shard.md b/docs/sharding/provisioning/user-defined-sharding/udsharding_scale_in_delete_an_existing_shard.md new file mode 100644 index 00000000..2c4cbfc2 --- /dev/null +++ b/docs/sharding/provisioning/user-defined-sharding/udsharding_scale_in_delete_an_existing_shard.md @@ -0,0 +1,65 @@ +# Scale In - Delete an existing Shard from a working Oracle Sharded Database provisioned earlier with User Defined Sharding + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +This use case demonstrates how to delete an existing Shard from an existing Oracle Database sharding topology with User Defined Sharding provisioned using Oracle Database Sharding controller. + +In this use case, the existing database Sharding is having: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Five sharding Pods: `shard1`,`shard2`,`shard3`,`shard4` and `shard5` +* One Catalog Pod: `catalog` +* Namespace: `shns` +* User Defined Sharding is specified using `shardingType: USER` + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `udsharding_shard_prov_delshard.yaml`. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + * In case you want to use the [Oracle Database 23ai Free](https://www.oracle.com/database/free/get-started/) Image for Database and GSM, then you will need to add the additional parameter `dbEdition: "free"` to the below .yaml file. + +**NOTE:** Use tag `isDelete: enable` to delete the shard you want. + +This use case deletes the shard `shard4` from the above Sharding Topology. + +Use the file: [udsharding_shard_prov_delshard.yaml](./udsharding_shard_prov_delshard.yaml) for this use case as below: + +1. Move out the chunks from the shard to be deleted to another shard. For example, in the current case, before deleting the `shard4`, if you want to move the chunks from `shard4` to `shard2`, then you can run the below `kubectl` command where `/u01/app/oracle/product/23ai/gsmhome_1` is the GSM HOME: + ```sh + kubectl exec -it pod/gsm1-0 -n shns -- /u01/app/oracle/product/23ai/gsmhome_1/bin/gdsctl "move chunk -chunk all -source shard4_shard4pdb -target shard4_shard4pdb" + ``` +2. Confirm the shard to be deleted (`shard4` in this case) is not having any chunk using below command: + ```sh + kubectl exec -it pod/gsm1-0 -n shns -- /u01/app/oracle/product/23ai/gsmhome_1/bin/gdsctl "config chunks" + ``` + If there is no chunk present in the shard to be deleted, you can move to the next step. + +3. Apply the `udsharding_shard_prov_delshard.yaml` file: + ```sh + kubectl apply -f udsharding_shard_prov_delshard.yaml + ``` +4. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + ``` + +**NOTE:** +- After you apply `udsharding_shard_prov_delshard.yaml`, the change may not be visible immediately and it may take some time for the delete operation to complete. +- If the shard, that you are trying to delete, is still having chunks, then the you will see message like below in the logs of the Oracle Database Operator Pod. + ```sh + INFO controllers.database.ShardingDatabase manual intervention required + ``` + In this case, you will need to first move out the chunks from the shard to be deleted using Step 2 above and then apply the file in Step 3 to delete that shard. + +To check the status, use the following command: + ```sh + # Switch to the primary GSM Container: + kubectl exec -i -t gsm1-0 -n shns /bin/bash + + # Check the status shards: + gdsctl config shard + + # Check the status of the chunks: + gdsctl config chunks + ``` diff --git a/docs/sharding/provisioning/user-defined-sharding/udsharding_scale_out_add_shards.md b/docs/sharding/provisioning/user-defined-sharding/udsharding_scale_out_add_shards.md new file mode 100644 index 00000000..20f50b29 --- /dev/null +++ b/docs/sharding/provisioning/user-defined-sharding/udsharding_scale_out_add_shards.md @@ -0,0 +1,35 @@ +# Scale Out - Add Shards to an existing Oracle Sharded Database provisioned earlier with User Defined Sharding + +**IMPORTANT:** Make sure you have completed the steps for [Prerequsites for Running Oracle Sharding Database Controller](../../README.md#prerequsites-for-running-oracle-sharding-database-controller) before using Oracle Sharding Controller. + +This use case demonstrates adding a new shard to an existing Oracle Database sharding topology with User Defined Sharding provisioned earlier using Oracle Database Sharding controller. + +In this use case, the existing Oracle Database sharding topology is having: + +* Primary GSM Pods `gsm1` and standby GSM Pod `gsm2` +* Three sharding Pods: `shard1`, `shard2` and `shard3` +* One Catalog Pod: `catalog` +* Namespace: `shns` +* User Defined Sharding is specified using `shardingType: USER` + +In this example, we are using pre-built Oracle Database and Global Data Services container images available on [Oracle Container Registry](https://container-registry.oracle.com/) + * To pull the above images from Oracle Container Registry, create a Kubernetes secret named `ocr-reg-cred` using your credentials with type set to `kubernetes.io/dockerconfigjson` in the namespace `shns`. + * If you plan to use images built by you, you need to change `dbImage` and `gsmImage` tag with the images you have built in your enviornment in file `udsharding_shard_prov_extshard.yaml`. + * To understand the Pre-requisite of Database and Global Data Services docker images, refer [Oracle Database and Global Data Services Docker Images](../../README.md#3-oracle-database-and-global-data-services-docker-images) + * If the existing Sharding Topology was deployed using [Oracle Database 23ai Free](https://www.oracle.com/database/free/get-started/) Image for Database and GSM, then the additional parameter `dbEdition: "free"` will be needed for the below .yaml file as well. + +This use case adds two new shards `shard4`,`shard5` to above Sharding Topology. + +Use the file: [udsharding_shard_prov_extshard.yaml](./udsharding_shard_prov_extshard.yaml) for this use case as below: + +1. Deploy the `udsharding_shard_prov_extshard.yaml` file: + ```sh + kubectl apply -f udsharding_shard_prov_extshard.yaml + ``` +2. Check the status of the deployment: + ```sh + # Check the status of the Kubernetes Pods: + kubectl get all -n shns + + # Check the logs of a particular pod. For example, to check status of pod "shard4-0": + kubectl logs -f pod/shard4-0 -n shns diff --git a/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov.yaml b/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov.yaml new file mode 100644 index 00000000..9b565b73 --- /dev/null +++ b/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov.yaml @@ -0,0 +1,58 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardSpace: sspace1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardSpace: sspace2 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardSpace: sspace3 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + imagePullPolicy: "Always" + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + shardingType: USER + isExternalSvc: False + isDeleteOraPvc: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns diff --git a/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov_clone.yaml b/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov_clone.yaml new file mode 100644 index 00000000..adc2271f --- /dev/null +++ b/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov_clone.yaml @@ -0,0 +1,83 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + imagePullPolicy: "Always" + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volume.oc1.phx.abyhqljr3z3w72t6ay5eud7d5w3kdfhktfp6gwb6euy5tzwfaxgmbvwqlvsq + shardSpace: sspace1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + imagePullPolicy: "Always" + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volume.oc1.phx.abyhqljr3z3w72t6ay5eud7d5w3kdfhktfp6gwb6euy5tzwfaxgmbvwqlvsq + shardSpace: sspace2 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + imagePullPolicy: "Always" + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volume.oc1.phx.abyhqljr3z3w72t6ay5eud7d5w3kdfhktfp6gwb6euy5tzwfaxgmbvwqlvsq + shardSpace: sspace3 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + imagePullPolicy: "Always" + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volume.oc1.phx.abyhqljr3z3w72t6ay5eud7d5w3kdfhktfp6gwb6euy5tzwfaxgmbvwqlvsq + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + shardingType: USER + isExternalSvc: False + isDeleteOraPvc: True + isClone: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns diff --git a/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov_clone_across_ads.yaml b/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov_clone_across_ads.yaml new file mode 100644 index 00000000..28f36608 --- /dev/null +++ b/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov_clone_across_ads.yaml @@ -0,0 +1,91 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + imagePullPolicy: "Always" + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + shardSpace: sspace1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + imagePullPolicy: "Always" + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-2" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-2" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + shardSpace: sspace2 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + imagePullPolicy: "Always" + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + shardSpace: sspace3 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + imagePullPolicy: "Always" + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + shardingType: USER + isExternalSvc: False + isDeleteOraPvc: True + isClone: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns diff --git a/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov_delshard.yaml b/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov_delshard.yaml new file mode 100644 index 00000000..2342dc55 --- /dev/null +++ b/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov_delshard.yaml @@ -0,0 +1,69 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardSpace: sspace1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardSpace: sspace2 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardSpace: sspace3 + shardRegion: primary + - name: shard4 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardSpace: sspace4 + shardRegion: primary + isDelete: enable + - name: shard5 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardSpace: sspace5 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + imagePullPolicy: "Always" + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + shardingType: USER + isExternalSvc: False + isDeleteOraPvc: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns \ No newline at end of file diff --git a/docs/sharding/provisioning/shard_prov_extshard.yaml b/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov_extshard.yaml similarity index 51% rename from docs/sharding/provisioning/shard_prov_extshard.yaml rename to docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov_extshard.yaml index 449ba90b..f45d421f 100644 --- a/docs/sharding/provisioning/shard_prov_extshard.yaml +++ b/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov_extshard.yaml @@ -11,41 +11,57 @@ spec: shard: - name: shard1 storageSizeInGb: 50 + imagePullPolicy: "Always" + shardSpace: sspace1 + shardRegion: primary - name: shard2 storageSizeInGb: 50 + imagePullPolicy: "Always" + shardSpace: sspace2 + shardRegion: primary - name: shard3 storageSizeInGb: 50 + imagePullPolicy: "Always" + shardSpace: sspace3 + shardRegion: primary - name: shard4 storageSizeInGb: 50 + imagePullPolicy: "Always" + shardSpace: sspace4 + shardRegion: primary - name: shard5 - storageSizeInGb: 50 + storageSizeInGb: 50 + imagePullPolicy: "Always" + shardSpace: sspace5 + shardRegion: primary catalog: - name: catalog storageSizeInGb: 50 + imagePullPolicy: "Always" gsm: - name: gsm1 + imagePullPolicy: "Always" storageSizeInGb: 50 - replicas: 1 - envVars: - - name: "SERVICE1_PARAMS" - value: "service_name=oltp_rw_svc;service_role=primary" - - name: "SERVICE2_PARAMS" - value: "service_name=oltp_ro_svc;service_role=primary" + region: primary - name: gsm2 + imagePullPolicy: "Always" storageSizeInGb: 50 - replicas: 1 - envVars: - - name: "SERVICE1_PARAMS" - value: "service_name=oltp_rw_svc;service_role=primary" - - name: "SERVICE2_PARAMS" - value: "service_name=oltp_ro_svc;service_role=primary" + region: standby storageClass: oci dbImage: container-registry.oracle.com/database/enterprise:latest dbImagePullSecret: ocr-reg-cred gsmImage: container-registry.oracle.com/database/gsm:latest gsmImagePullSecret: ocr-reg-cred - scriptsLocation: "set -ex;curl https://codeload.github.com/oracle/db-sharding/tar.gz/master | tar -xz --strip=4 db-sharding-master/docker-based-sharding-deployment/dockerfiles/21.3.0/scripts; cp -i -r scripts/* /opt/oracle/scripts/sharding/scripts/;cp -i -r scripts/*py /opt/oracle/scripts/sharding" - secret: db-user-pass - isExternalSvc: false + shardingType: USER + isExternalSvc: False isDeleteOraPvc: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary namespace: shns diff --git a/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov_memory_cpu.yaml b/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov_memory_cpu.yaml new file mode 100644 index 00000000..e663aa65 --- /dev/null +++ b/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov_memory_cpu.yaml @@ -0,0 +1,89 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + resources: + requests: + memory: "1000Mi" + cpu: "1000m" + envVars: + - name: "INIT_SGA_SIZE" + value: "600" + - name: "INIT_PGA_SIZE" + value: "400" + imagePullPolicy: "Always" + shardSpace: sspace1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + resources: + requests: + memory: "1000Mi" + cpu: "1000m" + envVars: + - name: "INIT_SGA_SIZE" + value: "600" + - name: "INIT_PGA_SIZE" + value: "400" + imagePullPolicy: "Always" + shardSpace: sspace2 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + resources: + requests: + memory: "1000Mi" + cpu: "1000m" + envVars: + - name: "INIT_SGA_SIZE" + value: "600" + - name: "INIT_PGA_SIZE" + value: "400" + imagePullPolicy: "Always" + shardSpace: sspace3 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + resources: + requests: + memory: "1000Mi" + cpu: "1000m" + imagePullPolicy: "Always" + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + shardingType: USER + isExternalSvc: False + isDeleteOraPvc: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns diff --git a/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov_send_notification.yaml b/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov_send_notification.yaml new file mode 100644 index 00000000..afd951fe --- /dev/null +++ b/docs/sharding/provisioning/user-defined-sharding/udsharding_shard_prov_send_notification.yaml @@ -0,0 +1,85 @@ +# +# Copyright (c) 2022, Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl. +# +--- +apiVersion: database.oracle.com/v1alpha1 +kind: ShardingDatabase +metadata: + name: shardingdatabase-sample + namespace: shns +spec: + shard: + - name: shard1 + storageSizeInGb: 50 + imagePullPolicy: "Always" + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + shardSpace: sspace1 + shardRegion: primary + - name: shard2 + storageSizeInGb: 50 + imagePullPolicy: "Always" + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-2" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-2" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + shardSpace: sspace2 + shardRegion: primary + - name: shard3 + storageSizeInGb: 50 + imagePullPolicy: "Always" + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-3" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + shardSpace: sspace3 + shardRegion: primary + catalog: + - name: catalog + storageSizeInGb: 50 + imagePullPolicy: "Always" + nodeSelector: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvMatchLabels: + "failure-domain.beta.kubernetes.io/zone": "PHX-AD-1" + pvAnnotations: + volume.beta.kubernetes.io/oci-volume-source: ocid1.volumebackup.oc1.phx.abyhqljrxtv7tu5swqb3lzc7vpzwbwzdktd2y4k2vjjy2srmgu2w7bqdftjq + gsm: + - name: gsm1 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: primary + - name: gsm2 + imagePullPolicy: "Always" + storageSizeInGb: 50 + region: standby + storageClass: oci + dbImage: container-registry.oracle.com/database/enterprise:latest + dbImagePullSecret: ocr-reg-cred + gsmImage: container-registry.oracle.com/database/gsm:latest + gsmImagePullSecret: ocr-reg-cred + shardingType: USER + isExternalSvc: False + isDeleteOraPvc: True + isClone: True + dbSecret: + name: db-user-pass-rsa + pwdFileName: pwdfile.enc + keyFileName: key.pem + nsConfigMap: onsconfigmap + nsSecret: my-secret + gsmService: + - name: oltp_rw_svc + role: primary + - name: oltp_ro_svc + role: primary + namespace: shns diff --git a/docs/sidb/PREREQUISITES.md b/docs/sidb/PREREQUISITES.md index 6315d308..b904f5da 100644 --- a/docs/sidb/PREREQUISITES.md +++ b/docs/sidb/PREREQUISITES.md @@ -1,17 +1,21 @@ -## Prerequisites for Oracle Docker Image Deployment -To deploy Oracle Database Operator for Kubernetes on Oracle Docker images, complete these steps. +## Deployment Prerequisites +To deploy Oracle Single Instance Database in Kubernetes using the OraOperator, complete these steps. -* ### Prepare Oracle Docker Images +* ### Prepare Oracle Container Images - Build Single Instance Database Docker Images from source, following the instructions at [https://github.com/oracle/docker-images/tree/main/OracleDatabase/SingleInstance](https://github.com/oracle/docker-images/tree/main/OracleDatabase/SingleInstance), or + Build Single Instance Database Container Images from source, following the instructions at [https://github.com/oracle/docker-images/tree/main/OracleDatabase/SingleInstance](https://github.com/oracle/docker-images/tree/main/OracleDatabase/SingleInstance), or use the pre-built images available at [https://container-registry.oracle.com](https://container-registry.oracle.com) by signing in and accepting the required license agreement. Oracle Database Releases Supported: Enterprise and Standard Edition for Oracle Database 19c, and later releases. Express Edition for Oracle Database 21.3.0 only. Oracle Database Free 23.2.0 and later Free releases - Build Oracle REST Data Service Docker Images from source following the instructions at [https://github.com/oracle/docker-images/tree/main/OracleRestDataServices](https://github.com/oracle/docker-images/tree/main/OracleRestDataServices). + Build Oracle REST Data Service Container Images from source following the instructions at [https://github.com/oracle/docker-images/tree/main/OracleRestDataServices](https://github.com/oracle/docker-images/tree/main/OracleRestDataServices). Supported Oracle REST Data Service version is 21.4.2 -* ### Set Up Kubernetes and Volumes +* ### Ensure Sufficient Disk Space in Kubernetes Worker Nodes + + Provision Kubernetes worker nodes with recommended 250 GiB or more of free disk space required for pulling the base and patched database container images. If deploying on cloud you may choose to increase the custom boot volume size of the worker nodes. + +* ### Set Up Kubernetes and Volumes for Database Persistence Set up an on-premises Kubernetes cluster, or subscribe to a managed Kubernetes service, such as Oracle Cloud Infrastructure Container Engine for Kubernetes. Use a dynamic volume provisioner or pre-provision static persistent volumes manually. These volumes are required for persistent storage of the database files. diff --git a/docs/sidb/README.md b/docs/sidb/README.md index eb5116a4..ff357195 100644 --- a/docs/sidb/README.md +++ b/docs/sidb/README.md @@ -3,6 +3,9 @@ Oracle Database Operator for Kubernetes (`OraOperator`) includes the Single Instance Database Controller, which enables provisioning, cloning, and patching of Oracle Single Instance Databases on Kubernetes. It also enables configuring the database for Oracle REST Data Services with Oracle APEX development platform. The following sections explain the setup and functionality of the operator * [Prerequisites](#prerequisites) + * [Mandatory Resource Privileges](#mandatory-resource-privileges) + * [Optional Resource Privileges](#optional-resource-privileges) + * [OpenShift Security Context Constraints](#openshift-security-context-constraints) * [SingleInstanceDatabase Resource](#singleinstancedatabase-resource) * [Create a Database](#create-a-database) * [New Database](#new-database) @@ -12,6 +15,7 @@ Oracle Database Operator for Kubernetes (`OraOperator`) includes the Single Inst * [Connecting to Database](#connecting-to-database) * [Database Persistence (Storage) Configuration Options](#database-persistence-storage-configuration-options) * [Dynamic Persistence](#dynamic-persistence) + * [Storage Expansion](#storage-expansion) * [Static Persistence](#static-persistence) * [Configuring a Database](#configuring-a-database) * [Switching Database Modes](#switching-database-modes) @@ -21,6 +25,7 @@ Oracle Database Operator for Kubernetes (`OraOperator`) includes the Single Inst * [Delete a Database](#delete-a-database) * [Advanced Database Configurations](#advanced-database-configurations) * [Run Database with Multiple Replicas](#run-database-with-multiple-replicas) + * [Database Pod Resource Management](#database-pod-resource-management) * [Setup Database with LoadBalancer](#setup-database-with-loadbalancer) * [Enabling TCPS Connections](#enabling-tcps-connections) * [Specifying Custom Ports](#specifying-custom-ports) @@ -30,6 +35,7 @@ Oracle Database Operator for Kubernetes (`OraOperator`) includes the Single Inst * [Perform a Switchover](#perform-a-switchover) * [Patch Primary and Standby databases in Data Guard configuration](#patch-primary-and-standby-databases-in-data-guard-configuration) * [Delete the Data Guard Configuration](#delete-the-data-guard-configuration) + * [Execute Custom Scripts](#execute-custom-scripts) * [OracleRestDataService Resource](#oraclerestdataservice-resource) * [REST Enable a Database](#rest-enable-a-database) * [Provision ORDS](#provision-ords) @@ -43,9 +49,73 @@ Oracle Database Operator for Kubernetes (`OraOperator`) includes the Single Inst * [Maintenance Operations](#maintenance-operations) * [Additional Information](#additional-information) + ## Prerequisites -Oracle strongly recommends that you follow the [prerequisites](./PREREQUISITES.md). +Oracle strongly recommends to comply with the [prerequisites](./PREREQUISITES.md) and the following requirements + + ### Mandatory Resource Privileges + + Single Instance Database(sidb) controller mandatorily requires the following Kubernetes resource privileges: + + | Resources | Privileges | + | --- | --- | + | Pods | create delete get list patch update watch | + | Containers | create delete get list patch update watch | + | PersistentVolumeClaims | create delete get list patch update watch | + | Services | create delete get list patch update watch | + | Secrets | create delete get list patch update watch | + | Events | create patch | + + For managing the required levels of access, configure [role binding](../../README.md#role-binding-for-access-management) + + ### Optional Resource Privileges + + Single Instance Database(sidb) controller optionally requires the following Kubernetes resource privileges depending on the functionality being used: + + | Functionality | Resources | Privileges | + | --- | --- | --- | + | NodePort Services | Nodes | list watch | + | Storage Expansion with block volumes | StorageClasses | get list watch | + | Custom Scripts Execution | PersistentVolumes | get list watch | + + + For exposing the database via Nodeport services, apply [RBAC](../../rbac/node-rbac.yaml) + ```sh + kubectl apply -f rbac/node-rbac.yaml + ``` + For automatic storage expansion of block volumes, apply [RBAC](../../rbac/storage-class-rbac.yaml) + ```sh + kubectl apply -f rbac/storage-class-rbac.yaml + ``` + For automatic execution of custom scripts post database setup or startup, apply [RBAC](../../rbac/persistent-volume-rbac.yaml) + ```sh + kubectl apply -f rbac/persistent-volume-rbac.yaml + ``` + + ### OpenShift Security Context Constraints + + OpenShift requires additional Security Context Constraints (SCC) for deploying and managing the SingleInstanceDatabase resource. Follow these steps to create the appropriate SCCs before deploying the SingleInstanceDatabase resource. + + 1. Create a new project/namespace for deploying the SingleInstanceDatabase resource + + ```sh + oc new-project sidb-ns + ``` + + **Note:** OpenShift recommends not to deploy in namespaces starting with `kube`, `openshift` and the `default` namespace. + + 2. Apply the file [openshift_rbac.yaml](../../config/samples/sidb/openshift_rbac.yaml) with cluster-admin user privileges. + + ```sh + oc apply -f openshift-rbac.yaml + ``` + + This would result in creation of SCC (Security Context Constraints) and serviceaccount `sidb-sa` in the namespace `sidb-ns` which has access to the SCC. + + **Note:** The above config yaml file will bind the SCC to the serviceaccount `sidb-sa` in namespace `sidb-ns`. For any other project/namespace update the file appropriately with the namespace before applying. + + 3. Set the `serviceAccountName` attribute to `sidb-sa` and the namespace to `sidb-ns` in **[config/samples/sidb/singleinstancedatabase.yaml](../../config/samples/sidb/singleinstancedatabase.yaml)** before deploying the SingleInstanceDatabase resource. ## SingleInstanceDatabase Resource @@ -159,10 +229,12 @@ To provision a new database instance on the Kubernetes cluster, use the example 2. If you have not already done so, create an image pull secret for the Oracle Container Registry: ```sh - $ kubectl create secret docker-registry oracle-container-registry-secret --docker-server=container-registry.oracle.com --docker-username='' --docker-password='' --docker-email='' + $ kubectl create secret docker-registry oracle-container-registry-secret --docker-server=container-registry.oracle.com --docker-username='' --docker-password='' --docker-email='' - secret/oracle-container-registry-secret created + secret/oracle-container-registry-secret created ``` + Note: Generate the auth token from user profile section on top right of the page after logging into container-registry.oracle.com + This secret can also be created from the docker config.json or from podman auth.json after a successful login ```sh docker login container-registry.oracle.com @@ -171,7 +243,7 @@ To provision a new database instance on the Kubernetes cluster, use the example or ```sh podman login container-registry.oracle.com - podman create secret generic oracle-container-registry-secret --from-file=.dockerconfigjson=${XDG_RUNTIME_DIR}/containers/auth.json --type=kubernetes.io/dockerconfigjson + kubectl create secret generic oracle-container-registry-secret --from-file=.dockerconfigjson=${XDG_RUNTIME_DIR}/containers/auth.json --type=kubernetes.io/dockerconfigjson ``` 3. Provision a new database instance on the cluster by using the following command: @@ -221,10 +293,10 @@ To provision new Oracle Database Free database, use the sample **[config/samples This command pulls the Free image uploaded on the [Oracle Container Registry](https://container-registry.oracle.com/). **Note:** -- Provisioning Oracle Database Free is supported for release 23c (23.2.0) and later releases. +- Provisioning Oracle Database Free is supported for release 23.3.0 and later releases. - For Free database, only single replica mode (i.e. `replicas: 1`) is supported. - For Free database, you **cannot change** the init parameters i.e. `cpuCount, processes, sgaTarget or pgaAggregateTarget`. -- Oracle Enterprise Manager is not supported from release 23c and later release. +- Oracle Enterprise Manager Express (OEM Express) is not supported from release 23.3.0 and later releases. #### Additional Information You are required to specify the database admin password secret in the corresponding YAML file. The default values mentioned in the `adminPassword.secretName` fields of [singleinstancedatabase_create.yaml](../../config/samples/sidb/singleinstancedatabase_create.yaml), [singleinstancedatabase_prebuiltdb.yaml](../../config/samples/sidb/singleinstancedatabase_prebuiltdb.yaml), [singleinstancedatabase_express.yaml](../../config/samples/sidb/singleinstancedatabase_express.yaml) and [singleinstancedatabse_free.yaml](../../config/samples/sidb/singleinstancedatabase_free.yaml) files are `db-admin-secret`, `prebuiltdb-admin-secret`, `xedb-admin-secret` and `free-admin-secret` respectively. You can create these secrets manually by using the sample command mentioned in the [Template YAML](#template-yaml) section. Alternatively, you can create these secrets by filling the passwords in the **[singleinstancedatabase_secrets.yaml](../../config/samples/sidb/singleinstancedatabase_secrets.yaml)** file and applying it using the command below: @@ -281,7 +353,7 @@ $ kubectl get singleinstancedatabase sidb-sample -o "jsonpath={.status.oemExpres https://10.0.25.54:5500/em ``` -**Note:** OEM Express is not available for 23c and later releases +**Note:** OEM Express is not available for 23.3.0 and later releases ### Database Persistence (Storage) Configuration Options The database persistence can be achieved in the following two ways: @@ -295,8 +367,19 @@ In **Dynamic Persistence Provisioning**, a persistent volume is provisioned by m - Generally, the `Reclaim Policy` of such dynamically provisioned volumes is `Delete`. These volumes are deleted when their corresponding database deployment is deleted. To retain volumes, use static provisioning, as explained in the Block Volume Static Provisioning section. - In **Minikube**, the dynamic persistence provisioning class is **standard**. +#### Storage Expansion +When using dynamic persistence, you can at any time scale up your persistent volumes by simply patching the singleinstancedatabase resource using the following command : +```sh +$ kubectl patch singleinstancedatabase sidb-sample -p '{"spec":{"persistence":{"size":"100Gi"}}}' --type=merge +``` + +**Note:** +- Storage expansion requires the storage class to be configured with `allowVolumeExpansion:true` +- Storage expansion requires read and watch access for storage account as mentioned in [prerequisites](#prerequisites) +- User can only scale up a volume/storage and not scale down + #### Static Persistence -In **Static Persistence Provisioning**, you have to create a volume manually, and then use the name of this volume with the `<.spec.persistence.volumeName>` field which corresponds to the `volumeName` field of the persistence section in the **[singleinstancedatabase.yaml](../../config/samples/sidb/singleinstancedatabase.yaml)**. The `Reclaim Policy` of such volume can be set to `Retain`. So, this volume does not get deleted with the deletion of its corresponding deployment. +In **Static Persistence Provisioning**, you have to create a volume manually, and then use the name of this volume with the `<.spec.persistence.datafilesVolumeName>` field which corresponds to the `datafilesVolumeName` field of the persistence section in the **[singleinstancedatabase.yaml](../../config/samples/sidb/singleinstancedatabase.yaml)**. The `Reclaim Policy` of such volume can be set to `Retain`. So, this volume does not get deleted with the deletion of its corresponding deployment. For example in **Minikube**, a persistent volume can be provisioned using the sample yaml file below: ```yaml apiVersion: v1 @@ -312,7 +395,7 @@ spec: hostPath: path: /data/oradata ``` -The persistent volume name (i.e. db-vol) can be mentioned in the `volumeName` field of the **[singleinstancedatabase.yaml](../../config/samples/sidb/singleinstancedatabase.yaml)**. `storageClass` field is not required in this case, and can be left empty. +The persistent volume name (i.e. db-vol) can be mentioned in the `datafilesVolumeName` field of the **[singleinstancedatabase.yaml](../../config/samples/sidb/singleinstancedatabase.yaml)**. `storageClass` field is not required in this case, and can be left empty. Static Persistence Provisioning in Oracle Cloud Infrastructure (OCI) is explained in the following subsections: @@ -423,7 +506,7 @@ The following attributes cannot be modified after creating the Single Instance D - `edition` - `charset` - `pdbName` -- `cloneFrom` +- `primaryDatabaseRef` If you attempt to changing one of these attributes, then you receive an error similar to the following: @@ -439,8 +522,6 @@ To create copies of your existing database quickly, you can use the cloning func To quickly clone the existing database sidb-sample created above, use the sample **[config/samples/sidb/singleinstancedatabase_clone.yaml](../../config/samples/sidb/singleinstancedatabase_clone.yaml)** file. -**Note**: To clone a database, the source database must have archiveLog mode set to true. - For example: ```sh @@ -450,7 +531,10 @@ $ kubectl apply -f singleinstancedatabase_clone.yaml singleinstancedatabase.database.oracle.com/sidb-sample-clone created ``` -**Note:** The clone database can specify a database image that is different from the source database. In such cases, cloning is supported only between databases of the same major release. +**Note:** +- To clone a database, the source database must have archiveLog mode set to true. +- The clone database can specify a database image that is different from the source database. In such cases, cloning is supported only between databases of the same major release. +- Only enterprise and standard editions support cloning. ### Patch a Database @@ -469,7 +553,10 @@ singleinstancedatabase.database.oracle.com/sidb-sample patched ``` -After patching is complete, the database pods are restarted with the new release update image. For minimum downtime, ensure that you have multiple replicas of the database pods running before you start the patch operation. +After patching is complete, the database pods are restarted with the new release update image. + +**Note:** +- Only enterprise and standard editions support patching. #### Patch after Cloning @@ -518,16 +605,33 @@ The command above will delete the database pods and associated service. Some advanced database configuration scenarios are as follows: #### Run Database with Multiple Replicas -In multiple replicas mode, more than one pod is created for the database. The database is open and mounted by one of the replica pods. Other replica pods have instances started but not mounted, and serve to provide a quick cold fail-over in case the active pod goes down. Multiple replicas are also helpful in [patching](#patch-existing-database) operation. Ensure that you have multiple replicas of the database pods running before you start the patching operation for minimum downtime. +In multiple replicas mode, more than one pod is created for the database. Setting the replica count equal to or more than the number of worker nodes helps in distributing the replicas accross all the nodes that have access to the database persistent storage volume. +The database is open and mounted by one of the replica pods. Other replica pods have the database instance started but not mounted, and serve to provide a quick cold fail-over in case the active pod goes down. To enable multiple replicas, update the replica attribute in the `.yaml`, and apply by using the `kubectl apply` or `kubectl scale` commands. +The following table depicts the fail over matrix for any destructive operation to the primary replica pod + +| Pod Destructive Operation | Pod Restart/FailOver| + | --- | --- | + | Database instance crash | Yes | + | Force delete pod with zero grace period | Yes | + | Gracefully delete pod | Yes | + | Node running primary replica dies | Yes | + | Direct shutdown [All modes] | Yes | + | Maintenance shutdown [All modes] | No | + | PDB close | No | + **Note:** +- Maintence shutdown/startup can be executed using the scripts /home/oracle/shutDown.sh and /home/oracle/startUp.sh - This functionality requires the [k8s extension](https://github.com/oracle/docker-images/tree/main/OracleDatabase/SingleInstance/extensions/k8s) extended images. The database image from the container registry `container-registry.oracle.com` includes the K8s extension. - Because Oracle Database Express Edition (XE) does not support [k8s extension](https://github.com/oracle/docker-images/tree/main/OracleDatabase/SingleInstance/extensions/k8s), it does not support multiple replicas. - If the `ReadWriteOnce` access mode is used, all the replicas will be scheduled on the same node where the persistent volume would be mounted. - If the `ReadWriteMany` access mode is used, all the replicas will be distributed on different nodes. So, it is recommended to have replicas more than or equal to the number of the nodes as the database image is downloaded on all those nodes. This is beneficial in quick cold fail-over scenario (when the active pod dies) as the image would already be available on that node. +#### Database Pod Resource Management +When creating a Single Instance Database you can specify the cpu and memory resources needed by the database pod. These specified resources are passed to the `kube-scheduler` so that the pod gets scheduled on one of the pods that has the required resources available. To use database pod resource management specify values for the `resources` attributes in the [config/samples/sidb/singleinstancedatabase.yaml](../../config/samples/sidb/singleinstancedatabase.yaml) file, and apply it. + #### Setup Database with LoadBalancer For the Single Instance Database, the default service is the `NodePort` service. You can enable the `LoadBalancer` service by using `kubectl patch` command. @@ -540,39 +644,49 @@ $ kubectl --type=merge -p '{"spec":{"loadBalancer": true}}' patch singleinstance ``` ### Enabling TCPS Connections -You can enable TCPS connections in the database by setting the `enableTCPS` field to `true` in the [config/samples/sidb/singleinstancedatabase.yaml](../../config/samples/sidb/singleinstancedatabase.yaml) file, and applying it using `kubectl apply` command. +You can enable TCPS connections in the database by setting the `enableTCPS` field to `true` in the [config/samples/sidb/singleinstancedatabase.yaml](../../config/samples/sidb/singleinstancedatabase.yaml) file, and applying it. Alternatively, you can use the following command: ```bash kubectl patch --type=merge singleinstancedatabases.database.oracle.com sidb-sample -p '{"spec": {"enableTCPS": true}}' ``` -Once TCPS connections are enabled, the database connect string will change accordingly. The TCPS connections status can also be queried by the following command: +By default self signed certs are used for TCPS connections. The TCPS connections status can also be queried by the following command: ```bash kubectl get singleinstancedatabase sidb-sample -o "jsonpath={.status.isTcpsEnabled}" true ``` -The following steps are required to connect the Database using TCPS: -- You need to download the wallet from the Persistent Volume (PV) attached with the database pod. The location of the wallet inside the pod is as `/opt/oracle/oradata/clientWallet/$ORACLE_SID`. **Let us assume the `ORACLE_SID` is `ORCL1`, and singleinstance database resource name is `sidb-sample` for the upcoming example command**. You can copy the wallet to the destination directory by the following command: +**With Self Signed Certs** +- When TCPS is enabled, a self-signed certificate is generated and stored in wallets. For users' convenience, a client-side wallet is generated in location `/opt/oracle/oradata/clientWallet/$ORACLE_SID` in the pod. +- The self-signed certificate used with TCPS has validity for 1 year. After the certificate is expired, it will be renewed by the `OraOperator` automatically. Download the wallet again after auto-renewal. +- You can set the certificate renew interval with the help of `tcpsCertRenewInterval` field in the **[config/samples/sidb/singleinstancedatabase.yaml](../../config/samples/sidb/singleinstancedatabase.yaml)** file. The minimum accepted value is 24h, and the maximum value is 8760h (1 year). The certificates used with TCPS will automatically be renewed after this interval. If this field is omitted/commented in the yaml file, the certificates will not be renewed automatically. +- When the certificate gets created/renewed, the `.status.certCreationTimestamp` status variable gets updated accordingly. You can see this timestamp by using the following command: ```bash - kubectl cp $(kubectl get pods -l app=sidb-sample -o=jsonpath='{.items[0].metadata.name}'):/opt/oracle/oradata/clientWallet/ORCL1 + kubectl get singleinstancedatabase sidb-sample -o "jsonpath={.status.certCreationTimestamp}" ``` -- This wallet includes the sample `tnsnames.ora` and `sqlnet.ora` files. All the TNS entries for the database (corresponding to the CDB and PDB) resides in `tnsnames.ora` file. You need to go inside the downloaded wallet directory and set the `TNS_ADMIN` environment variable to point to the current directory as follows: + +**With User Provided Certs** +- Users can provide custom certs to be used for TCPS connections instead of self signed ones. +- Specify the certs by creating a Kubernetes tls secret resource using following command: ```bash - # After going inside the downloaded wallet directory - export TNS_ADMIN=$(pwd) + kubectl create secret tls my-tls-secret --cert=path/to/cert/tls.crt --key=path/to/key/tls.key ``` - After this, you can connect using SQL\*Plus using the following sample commands: +- `tls.crt` is a certificate chain in the order of client, followed by intermediate and then root certificate and `tls.key` is client key. +- Specify the secret created above (`my-tls-secret`) as the value for the attribute `tcpsTlsSecret` in the [config/samples/sidb/singleinstancedatabase_tcps.yaml](../../config/samples/sidb/singleinstancedatabase_tcps.yaml) file, and apply it. + +**Connecting to the Database using TCPS** +- Download the wallet from the Persistent Volume (PV) attached with the database pod. The location of the wallet inside the pod is as `/opt/oracle/oradata/clientWallet/$ORACLE_SID`. Let us assume the `ORACLE_SID` is `ORCL1`, and singleinstance database resource name is `sidb-sample` for the upcoming example command. You can copy the wallet to the destination directory by the following command: ```bash - sqlplus sys@ORCL1 as sysdba + kubectl cp $(kubectl get pods -l app=sidb-sample -o=jsonpath='{.items[0].metadata.name}'):/opt/oracle/oradata/clientWallet/ORCL1 ``` -**Note:** -- When TCPS is enabled, a self-signed certificate is generated and stored inside the wallets. For users' convenience, a client-side wallet is generated and stored at `/opt/oracle/oradata/clientWallet/$ORACLE_SID` location in the pod. -- The self-signed certificate used with TCPS has validity for 1 year. After the certificate is expired, it will be renewed by the `OraOperator` automatically. You need to download the wallet again after the auto-renewal. -- You can set the certificate renew interval with the help of `tcpsCertRenewInterval` field in the **[config/samples/sidb/singleinstancedatabase.yaml](../../config/samples/sidb/singleinstancedatabase.yaml)** file. The minimum accepted value is 24h, and the maximum value is 8760h (1 year). The certificates used with TCPS will automatically be renewed after this interval. If this field is omitted/commented in the yaml file, the certificates will not be renewed automatically. -- When the certificate gets created/renewed, the `.status.certCreationTimestamp` status variable gets updated accordingly. You can see this timestamp by using the following command: +- This wallet includes the sample `tnsnames.ora` and `sqlnet.ora` files. All the TNS entries for the database (corresponding to the CDB and PDB) reside in the `tnsnames.ora` file. Switch to the downloaded wallet directory and set the `TNS_ADMIN` environment variable to point to the current directory as follows: ```bash - kubectl get singleinstancedatabase sidb-sample -o "jsonpath={.status.certCreationTimestamp}" + cd + export TNS_ADMIN=$(pwd) + ``` + After this, connect using SQL\*Plus using the following sample commands: + ```bash + sqlplus sys@ORCL1 as sysdba ``` ### Specifying Custom Ports @@ -595,7 +709,8 @@ In case of `NodePort` service, `listenerPort`, and `tcpsListenerPort` will be th ### Create a Standby Database #### Prerequisites -Before creating a standby, ArchiveLog, FlashBack, and ForceLog on primary Single Instance Database(`.spec.primaryDatabaseRef`) should be turned on. +- Before creating a Standby, ensure that ArchiveLog, FlashBack, and ForceLog on primary Single Instance Database(`.spec.primaryDatabaseRef`) are turned on. +- Standby database is not supported for TCPS enabled Primary databases. #### Template YAML To create a standby database, edit and apply the sample yaml file [config/samples/sidb/singleinstancedatabase_standby.yaml](../../config/samples/sidb/singleinstancedatabase_standby.yaml). @@ -603,7 +718,7 @@ To create a standby database, edit and apply the sample yaml file [config/sample **Note:** - The `adminPassword` field of the above [config/samples/sidb/singleinstancedatabase_standby.yaml](../../config/samples/sidb/singleinstancedatabase_standby.yaml) contains an admin password secret of the primary database ref for Standby Database creation. This secret will get deleted after the database pod becomes ready if the `keepSecret` attribute of `adminPassword` field is set to `false`. By default `keepSecret` is set to `true`. - Mention referred primary database in `.spec.primaryDatabaseRef` in the yaml file. -- `.spec.createAsStandby` field of the yaml file should be true. +- `.spec.createAs` field of the yaml file should be set to "standby". - Database configuration like `Archivelog`, `FlashBack`, `ForceLog`, `TCPS connections` are not supported for standby database. #### List Standby Databases @@ -766,7 +881,7 @@ $ kubectl --type=merge -p '{"spec":{"setAsPrimaryDatabase":"ORCLS1"}}' patch dat ### Patch Primary and Standby databases in Data Guard configuration -Databases (both primary and standby) running in you cluster and managed by the Oracle Database operator can be patched or rolled back between release updates of the same major release. While patching databases configured with the dataguard broker you need to first patch the Primary database followed by seconday/standby databases in any order. +Databases (both primary and standby) running in you cluster and managed by the Oracle Database operator can be patched between release updates of the same major release. To patch an existing database, edit and apply the **[config/samples/sidb/singleinstancedatabase_patch.yaml](../../config/samples/sidb/singleinstancedatabase_patch.yaml)** file of the database resource/object either by specifying a new release update for image attributes, or by running the following command: @@ -774,6 +889,15 @@ To patch an existing database, edit and apply the **[config/samples/sidb/singlei kubectl --type=merge -p '{"spec":{"image":{"pullFrom":"patched-image:tag","pullSecrets":"pull-secret"}}}' patch singleinstancedatabase ``` +Follow these steps for patching databases configured with the dataguard broker: +1. First patch all the standby databases by replacing the image with the new release update image +2. Perform switch over of the primary to one of the standby databases +3. Now patch the original primary database (currently standby after #2) + After #3 the software for primary and standby databases is at the same release update +4. Now bounce the current primary database by updating the replica count to 0 and then 1 + #4 will trigger a datapatch execution resulting in patching of the datafiles +5. Finally perform switch over of the current primary back to the original primary (current standby) + ### Delete the Data Guard Configuration @@ -785,7 +909,8 @@ $ kubectl delete dataguardbroker dgbroker-sample dataguardbroker.database.oracle.com/dgbroker-sample deleted ``` -**Note:** Deleting of DataGuardBroker resource is allowed only when role of `.spec.primaryDatabaseRef` is PRIMARY + +**Note:** If a switch over to standby was performed, make sure to switch back to the original primary database before deleting the dataguard broker resource #### Delete Standby Database ```sh @@ -794,6 +919,14 @@ $ kubectl delete singleinstancedatabase stdby-1 singleinstancedatabase.database.oracle.com "stdby-1" deleted ``` +### Execute Custom Scripts + +Custom scripts (sql and/or shell scripts) can be executed after the initial database setup and/or after each startup of the database. SQL scripts will be executed as sysdba, shell scripts will be executed as the current user. To ensure proper order it is recommended to prefix your scripts with a number. For example `01_users.sql`, `02_permissions.sql`, etc. Place all such scripts in setup and startup folders created in a persistent volume to execute them post setup and post startup respectively. + +Create a persistent volume using [static provisioning](#static-persistence) and then specify the name of this volume with the `<.spec.persistence.scriptsVolumeName>` field which corresponds to the `scriptsVolumeName` field of the persistence section in the **[singleinstancedatabase.yaml](../../config/samples/sidb/singleinstancedatabase.yaml)**. + +**Note:** Executing custom scripts requires read and list access for persistent volumes as mentioned in [prerequisites](#prerequisites) + ## OracleRestDataService Resource The Oracle Database Operator creates the `OracleRestDataService` as a custom resource. We will refer `OracleRestDataService` as ORDS from now onwards. Creating ORDS as a custom resource enables the RESTful API access to the Oracle Database in K8s and enables it to be managed as a native Kubernetes object. @@ -857,12 +990,12 @@ $ kubectl describe oraclerestdataservice ords-sample ### Template YAML -The template `.yaml` file for Oracle Rest Data Services (`OracleRestDataService` kind), including all the configurable options, is available at **[config/samples/sidb/oraclerestdataservice.yaml](config/samples/sidb/oraclerestdataservice.yaml)**. +The template `.yaml` file for Oracle Rest Data Services (`OracleRestDataService` kind), including all the configurable options, is available at **[config/samples/sidb/oraclerestdataservice.yaml](../../config/samples/sidb/oraclerestdataservice.yaml)**. **Note:** - The `adminPassword` and `ordsPassword` fields in the `oraclerestdataservice.yaml` file contains secrets for authenticating the Single Instance Database and the ORDS user with the following roles: `SQL Administrator, System Administrator, SQL Developer, oracle.dbtools.autorest.any.schema`. - To build the ORDS image, use the following instructions: [Building Oracle REST Data Services Install Images](https://github.com/oracle/docker-images/tree/main/OracleRestDataServices#building-oracle-rest-data-services-install-images). -- By default, ORDS uses self-signed certificates. To use certificates from the Certificate Authority, the ORDS image needs to be rebuilt after specifying the values of `ssl.cert` and `ssl.cert.key` in the [standalone.properties](https://github.com/oracle/docker-images/blob/main/OracleRestDataServices/dockerfiles/standalone.properties.tmpl) file. After you rebuild the ORDS image, use the rebuilt image in the **[config/samples/sidb/oraclerestdataservice.yaml](config/samples/sidb/oraclerestdataservice.yaml)** file. +- By default, ORDS uses self-signed certificates. To use certificates from the Certificate Authority, the ORDS image needs to be rebuilt after specifying the values of `ssl.cert` and `ssl.cert.key` in the [standalone.properties](https://github.com/oracle/docker-images/blob/main/OracleRestDataServices/dockerfiles/standalone.properties.tmpl) file. After you rebuild the ORDS image, use the rebuilt image in the **[config/samples/sidb/oraclerestdataservice.yaml](../../config/samples/sidb/oraclerestdataservice.yaml)** file. - If you want to install ORDS in a [prebuilt database](#provision-a-pre-built-database), make sure to attach the **database persistence** by uncommenting the `persistence` section in the **[config/samples/sidb/singleinstancedatabase_prebuiltdb.yaml](../../config/samples/sidb/singleinstancedatabase_prebuiltdb.yaml)** file, while provisioning the prebuilt database. ### REST Enable a Database @@ -1010,7 +1143,7 @@ Fetch all entries from 'DEPT' table by calling the following API Database Actions is a web-based interface that uses Oracle REST Data Services to provide development, data tools, administration and monitoring features for Oracle Database. * To use Database Actions, you must sign in as a database user whose schema has been REST-enabled. -* To enable a schema for REST, you can specify appropriate values for the `.spec.restEnableSchemas` attributes details in the sample `yaml` **[config/samples/sidb/oraclerestdataservice.yaml](config/samples/sidb/oraclerestdataservice.yaml)**, which are needed for authorizing Database Actions. +* To enable a schema for REST, you can specify appropriate values for the `.spec.restEnableSchemas` attributes details in the sample `yaml` **[config/samples/sidb/oraclerestdataservice.yaml](../../config/samples/sidb/oraclerestdataservice.yaml)**, which are needed for authorizing Database Actions. * Schema are created (if they exist) with the username as `.spec.restEnableSchema[].schema` and password as `.spec.ordsPassword.`. * UrlMapping `.spec.restEnableSchema[].urlMapping` is optional and is defaulted to `.spec.restEnableSchema[].schema`. @@ -1044,7 +1177,7 @@ Using APEX, developers can quickly develop and deploy compelling apps that solve The `OraOperator` facilitates installation of APEX in the database and also configures ORDS for it. The following section will explain installing APEX with configured ORDS: -* For quick provisioning, use the sample **[config/samples/sidb/oraclerestdataservice_apex.yaml](../../confi/samples/sidb/oraclerestdataservice_apex.yaml)** file. For example: +* For quick provisioning, use the sample **[config/samples/sidb/oraclerestdataservice_apex.yaml](../../config/samples/sidb/oraclerestdataservice_apex.yaml)** file. For example: kubectl apply -f oraclerestdataservice_apex.yaml diff --git a/go.mod b/go.mod index 81c4d435..1f30279f 100644 --- a/go.mod +++ b/go.mod @@ -1,82 +1,106 @@ module github.com/oracle/oracle-database-operator -go 1.19 +go 1.21 require ( - github.com/go-logr/logr v1.2.3 - github.com/onsi/ginkgo/v2 v2.5.0 - github.com/onsi/gomega v1.24.1 - github.com/oracle/oci-go-sdk/v65 v65.26.1 - go.uber.org/zap v1.23.0 - gopkg.in/yaml.v2 v2.4.0 - k8s.io/api v0.25.4 - k8s.io/apimachinery v0.25.4 - k8s.io/client-go v0.25.4 - sigs.k8s.io/controller-runtime v0.13.1 + github.com/go-logr/logr v1.3.0 + github.com/onsi/ginkgo/v2 v2.13.0 + github.com/onsi/gomega v1.29.0 + github.com/oracle/oci-go-sdk/v65 v65.49.3 + github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.62.0 + go.uber.org/zap v1.26.0 + golang.org/x/text v0.14.0 + gopkg.in/yaml.v3 v3.0.1 + k8s.io/api v0.29.2 + k8s.io/apimachinery v0.29.2 + k8s.io/cli-runtime v0.29.2 + k8s.io/client-go v0.29.2 + k8s.io/kubectl v0.29.2 + sigs.k8s.io/controller-runtime v0.16.2 sigs.k8s.io/yaml v1.3.0 ) require ( - github.com/PuerkitoBio/purell v1.1.1 // indirect - github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect + github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect + github.com/MakeNowJust/heredoc v1.0.0 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/chai2010/gettext-go v1.0.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/emicklei/go-restful/v3 v3.8.0 // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/evanphx/json-patch v5.6.0+incompatible // indirect github.com/evanphx/json-patch/v5 v5.6.0 // indirect - github.com/fsnotify/fsnotify v1.5.4 // indirect - github.com/go-openapi/jsonpointer v0.19.5 // indirect - github.com/go-openapi/jsonreference v0.19.5 // indirect - github.com/go-openapi/swag v0.19.14 // indirect + github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect + github.com/fatih/camelcase v1.0.0 // indirect + github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/fvbommel/sortorder v1.1.0 // indirect + github.com/go-errors/errors v1.4.2 // indirect + github.com/go-logr/zapr v1.2.4 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.22.3 // indirect + github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gofrs/flock v0.8.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/golang/protobuf v1.5.2 // indirect - github.com/google/gnostic v0.5.7-v3refs // indirect - github.com/google/go-cmp v0.5.9 // indirect - github.com/imdario/mergo v0.3.12 // indirect + github.com/golang/protobuf v1.5.3 // indirect + github.com/google/btree v1.0.1 // indirect + github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect + github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect + github.com/imdario/mergo v0.3.6 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/mailru/easyjson v0.7.6 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect + github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/moby/spdystream v0.2.0 // indirect + github.com/moby/term v0.0.0-20221205130635-1aeaba878587 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f // indirect + github.com/peterbourgon/diskv v2.0.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.12.2 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.32.1 // indirect - github.com/prometheus/procfs v0.7.3 // indirect + github.com/prometheus/client_golang v1.16.0 // indirect + github.com/prometheus/client_model v0.4.0 // indirect + github.com/prometheus/common v0.44.0 // indirect + github.com/prometheus/procfs v0.10.1 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sony/gobreaker v0.5.0 // indirect + github.com/spf13/cobra v1.7.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/stretchr/objx v0.4.0 // indirect - go.uber.org/atomic v1.9.0 // indirect - go.uber.org/multierr v1.7.0 // indirect - golang.org/x/net v0.7.0 // indirect - golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect - golang.org/x/sys v0.5.0 // indirect - golang.org/x/term v0.5.0 // indirect - golang.org/x/text v0.7.0 // indirect - golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect - gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect + github.com/xlab/treeprint v1.2.0 // indirect + go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect + golang.org/x/net v0.19.0 // indirect + golang.org/x/oauth2 v0.10.0 // indirect + golang.org/x/sync v0.5.0 // indirect + golang.org/x/sys v0.15.0 // indirect + golang.org/x/term v0.15.0 // indirect + golang.org/x/time v0.3.0 // indirect + golang.org/x/tools v0.16.1 // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.28.0 // indirect + google.golang.org/protobuf v1.31.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.25.0 // indirect - k8s.io/component-base v0.25.0 // indirect - k8s.io/klog/v2 v2.70.1 // indirect - k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect - k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect - sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect -) - -require ( - cloud.google.com/go/compute v1.2.0 // indirect - github.com/evanphx/json-patch v5.6.0+incompatible // indirect - github.com/go-logr/zapr v1.2.3 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/google/uuid v1.3.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + k8s.io/apiextensions-apiserver v0.28.0 // indirect + k8s.io/component-base v0.29.2 // indirect + k8s.io/klog/v2 v2.110.1 // indirect + k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 // indirect + k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect + sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect ) diff --git a/go.sum b/go.sum index aacb116a..08185f3e 100644 --- a/go.sum +++ b/go.sum @@ -1,809 +1,362 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI= -cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk= -cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg= -cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8= -cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0= -cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY= -cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM= -cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY= -cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ= -cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI= -cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4= -cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= -cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= -cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow= -cloud.google.com/go/compute v1.2.0 h1:EKki8sSdvDU0OO9mAXGwPXOTOgPz2l08R0/IutDH11I= -cloud.google.com/go/compute v1.2.0/go.mod h1:xlogom/6gr8RJGBe7nT2eGsQYAFUbbv8dbC29qE3Xmw= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= -github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= -github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= -github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= -github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= +github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= +github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= +github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= -github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= +github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= -github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= -github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= -github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc= -github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw= -github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= -github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= -github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= -github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= -github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ= github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI= -github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= -github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= -github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/zapr v1.2.3 h1:a9vnzlIBPQBBkeaR9IuMUfmVOrQlkoC4YfPoFkX3T7A= -github.com/go-logr/zapr v1.2.3/go.mod h1:eIauM6P8qSvTw5o2ez6UEAfGjQKrxQTl5EoK+Qa2oG4= -github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= -github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= -github.com/go-openapi/jsonreference v0.19.5 h1:1WJP/wi4OjB4iV8KVbH73rQaoialJrqv8gitZLxGLtM= -github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg= -github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng= -github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= -github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM= +github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4= +github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8= +github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc= +github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/fvbommel/sortorder v1.1.0 h1:fUmoe+HLsBTctBDoaBwpQo5N+nrCp8g/BjKb/6ZQmYw= +github.com/fvbommel/sortorder v1.1.0/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= +github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= +github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= +github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= +github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= +github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= +github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= -github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= -github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= -github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= -github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= -github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54= -github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= +github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= +github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= -github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= -github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= +github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= +github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM= +github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= +github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= -github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= -github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA= -github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= +github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= +github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= +github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA= +github.com/moby/term v0.0.0-20221205130635-1aeaba878587/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= +github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo/v2 v2.5.0 h1:TRtrvv2vdQqzkwrQ1ke6vtXf7IK34RBUJafIy1wMwls= -github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw= -github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E= -github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM= -github.com/oracle/oci-go-sdk/v65 v65.26.1 h1:Ms20RSRj+CuvQmw5ET1TkmzxLBI+bmLjZ6NYANA3gkk= -github.com/oracle/oci-go-sdk/v65 v65.26.1/go.mod h1:oyMrMa1vOzzKTmPN+kqrTR9y9kPA2tU1igN3NUSNTIE= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= +github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= +github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= +github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= +github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= +github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= +github.com/oracle/oci-go-sdk/v65 v65.49.3 h1:HHv+XMZiBYHtoU8Ac/fURdp9v1vJPPCpIbJAWeadREw= +github.com/oracle/oci-go-sdk/v65 v65.49.3/go.mod h1:IBEV9l1qBzUpo7zgGaRUhbB05BVfcDGYRFBCPlTcPp0= +github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= +github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.62.0 h1:55138zTXw/yRYizPxZ672I/aDD7Yte3uYRAfUjWUu2M= +github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring v0.62.0/go.mod h1:j51242bf6LQwvJ1JPKWApzTnifmCwcQq0i1p29ylWiM= +github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= +github.com/prometheus/client_golang v1.16.0/go.mod h1:Zsulrv/L9oM40tJ7T815tM89lFEugiJ9HzIqaAx4LKc= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= -github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= +github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= +github.com/prometheus/client_model v0.4.0/go.mod h1:oMQmHW1/JoDwqLtg57MGgP/Fb1CJEYF2imWWhWtMkYU= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= +github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= +github.com/prometheus/procfs v0.10.1/go.mod h1:nwNm2aOCAYw8uTR/9bWRREkZFxAUcWzPHWJq+XBB/FM= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= +github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sony/gobreaker v0.5.0 h1:dRCvqm0P490vZPmy7ppEk2qCnCieBooFJ+YoXGYB+yg= github.com/sony/gobreaker v0.5.0/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= -github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= +github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= +github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= +github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= -go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= +go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= +go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= -go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= -go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= +go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= -go.uber.org/multierr v1.7.0 h1:zaiO/rmgFjbmCXdSYJWQcdvOCsthmdaHfr3Gm2Kx4Ec= -go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= -go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= -go.uber.org/zap v1.23.0 h1:OjGQ5KQDEUawVHxNwQgPpiypGHOxo2mNZsOqTak4fFY= -go.uber.org/zap v1.23.0/go.mod h1:D+nX8jyLsMHMYrln8A0rJjFt/T/9/bGgIhAqxv5URuY= -golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= +golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= -golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= -golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= -golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c= +golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= +golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= +golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= +golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858 h1:Dpdu/EMxGMFgq0CeYMh4fazTD2vtlZRYE7wyynxJb9U= -golang.org/x/time v0.0.0-20220609170525-579cf78fd858/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= -golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= -golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= +golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.2.0 h1:4pT439QV83L+G9FkcCriY6EkpcK6r6bK+A5FBUMI7qY= -gomodules.xyz/jsonpatch/v2 v2.2.0/go.mod h1:WXp+iVDkoLQqPudfQ9GBlwB2eZ5DKOnjQZCYdOS8GPY= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg= -google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE= -google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= -google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= -google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= -google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= -google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= -google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU= -google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k= -google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE= -google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI= -google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= -google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo= -google.golang.org/api v0.66.0/go.mod h1:I1dmXYpX7HGwz/ejRxwQp2qj5bFAz93HiCU1C1oYd9M= +gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= +gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= -google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= -google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= -google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= -google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24= -google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k= -google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48= -google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w= -google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220114231437-d2e6a121cae0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20220201184016-50beb8ab5c44/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= -google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= -google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8= -google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= -google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= -google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw= -google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= +google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= +google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -k8s.io/api v0.25.4 h1:3YO8J4RtmG7elEgaWMb4HgmpS2CfY1QlaOz9nwB+ZSs= -k8s.io/api v0.25.4/go.mod h1:IG2+RzyPQLllQxnhzD8KQNEu4c4YvyDTpSMztf4A0OQ= -k8s.io/apiextensions-apiserver v0.25.0 h1:CJ9zlyXAbq0FIW8CD7HHyozCMBpDSiH7EdrSTCZcZFY= -k8s.io/apiextensions-apiserver v0.25.0/go.mod h1:3pAjZiN4zw7R8aZC5gR0y3/vCkGlAjCazcg1me8iB/E= -k8s.io/apimachinery v0.25.4 h1:CtXsuaitMESSu339tfhVXhQrPET+EiWnIY1rcurKnAc= -k8s.io/apimachinery v0.25.4/go.mod h1:jaF9C/iPNM1FuLl7Zuy5b9v+n35HGSh6AQ4HYRkCqwo= -k8s.io/client-go v0.25.4 h1:3RNRDffAkNU56M/a7gUfXaEzdhZlYhoW8dgViGy5fn8= -k8s.io/client-go v0.25.4/go.mod h1:8trHCAC83XKY0wsBIpbirZU4NTUpbuhc2JnI7OruGZw= -k8s.io/component-base v0.25.0 h1:haVKlLkPCFZhkcqB6WCvpVxftrg6+FK5x1ZuaIDaQ5Y= -k8s.io/component-base v0.25.0/go.mod h1:F2Sumv9CnbBlqrpdf7rKZTmmd2meJq0HizeyY/yAFxk= -k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= -k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ= -k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA= -k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU= -k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4= -k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/controller-runtime v0.13.1 h1:tUsRCSJVM1QQOOeViGeX3GMT3dQF1eePPw6sEE3xSlg= -sigs.k8s.io/controller-runtime v0.13.1/go.mod h1:Zbz+el8Yg31jubvAEyglRZGdLAjplZl+PgtYNI6WNTI= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k= -sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= +k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A= +k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0= +k8s.io/apiextensions-apiserver v0.28.0 h1:CszgmBL8CizEnj4sj7/PtLGey6Na3YgWyGCPONv7E9E= +k8s.io/apiextensions-apiserver v0.28.0/go.mod h1:uRdYiwIuu0SyqJKriKmqEN2jThIJPhVmOWETm8ud1VE= +k8s.io/apimachinery v0.29.2 h1:EWGpfJ856oj11C52NRCHuU7rFDwxev48z+6DSlGNsV8= +k8s.io/apimachinery v0.29.2/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU= +k8s.io/cli-runtime v0.29.2 h1:smfsOcT4QujeghsNjECKN3lwyX9AwcFU0nvJ7sFN3ro= +k8s.io/cli-runtime v0.29.2/go.mod h1:KLisYYfoqeNfO+MkTWvpqIyb1wpJmmFJhioA0xd4MW8= +k8s.io/client-go v0.29.2 h1:FEg85el1TeZp+/vYJM7hkDlSTFZ+c5nnK44DJ4FyoRg= +k8s.io/client-go v0.29.2/go.mod h1:knlvFZE58VpqbQpJNbCbctTVXcd35mMyAAwBdpt4jrA= +k8s.io/component-base v0.29.2 h1:lpiLyuvPA9yV1aQwGLENYyK7n/8t6l3nn3zAtFTJYe8= +k8s.io/component-base v0.29.2/go.mod h1:BfB3SLrefbZXiBfbM+2H1dlat21Uewg/5qtKOl8degM= +k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= +k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= +k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= +k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= +k8s.io/kubectl v0.29.2 h1:uaDYaBhumvkwz0S2XHt36fK0v5IdNgL7HyUniwb2IUo= +k8s.io/kubectl v0.29.2/go.mod h1:BhizuYBGcKaHWyq+G7txGw2fXg576QbPrrnQdQDZgqI= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= +k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= +sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQVuIPU= +sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= +sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 h1:XX3Ajgzov2RKUdc5jW3t5jwY7Bo7dcRm+tFxT+NfgY0= +sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3/go.mod h1:9n16EZKMhXBNSiUC5kSdFQJkdH3zbxS/JoO619G1VAY= +sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 h1:W6cLQc5pnqM7vh3b7HvGNfXrJ/xL6BDMS0v1V/HHg5U= +sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3/go.mod h1:JWP1Fj0VWGHyw3YUPjXSQnRnrwezrZSrApfX5S0nIag= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/image.png b/image.png new file mode 100644 index 00000000..8bd1bbd5 Binary files /dev/null and b/image.png differ diff --git a/main.go b/main.go index 6dbf2305..4174e97d 100644 --- a/main.go +++ b/main.go @@ -41,21 +41,31 @@ package main import ( "context" "flag" + "fmt" "os" "strconv" + "strings" "time" + monitorv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" + "go.uber.org/zap/zapcore" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" clientgoscheme "k8s.io/client-go/kubernetes/scheme" _ "k8s.io/client-go/plugin/pkg/client/auth/gcp" + "k8s.io/client-go/rest" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/cache" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/log/zap" + metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" databasev1alpha1 "github.com/oracle/oracle-database-operator/apis/database/v1alpha1" databasecontroller "github.com/oracle/oracle-database-operator/controllers/database" + + observabilityv1alpha1 "github.com/oracle/oracle-database-operator/apis/observability/v1alpha1" + observabilitycontroller "github.com/oracle/oracle-database-operator/controllers/observability" // +kubebuilder:scaffold:imports ) @@ -66,7 +76,8 @@ var ( func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) - + utilruntime.Must(observabilityv1alpha1.AddToScheme(scheme)) + utilruntime.Must(monitorv1.AddToScheme(scheme)) utilruntime.Must(databasev1alpha1.AddToScheme(scheme)) // +kubebuilder:scaffold:scheme } @@ -88,13 +99,25 @@ func main() { ctrl.SetLogger(zap.New(func(o *zap.Options) { *o = *options })) - mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ - Scheme: scheme, - MetricsBindAddress: metricsAddr, - Port: 9443, - LeaderElection: enableLeaderElection, - LeaderElectionID: "a9d608ea.oracle.com", - }) + watchNamespaces, err := getWatchNamespace() + if err != nil { + setupLog.Error(err, "Failed to get watch namespaces") + os.Exit(1) + } + opt := ctrl.Options{ + Scheme: scheme, + Metrics: metricsserver.Options{ + BindAddress: metricsAddr, + }, + LeaderElection: enableLeaderElection, + LeaderElectionID: "a9d608ea.oracle.com", + NewCache: func(config *rest.Config, opts cache.Options) (cache.Cache, error) { + opts.DefaultNamespaces = watchNamespaces + return cache.New(config, opts) + }, + } + + mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), opt) if err != nil { setupLog.Error(err, "unable to start manager") os.Exit(1) @@ -226,6 +249,13 @@ func main() { setupLog.Error(err, "unable to create webhook", "webhook", "DataguardBroker") os.Exit(1) } + if err = (&databasev1alpha1.ShardingDatabase{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "ShardingDatabase") + } + if err = (&observabilityv1alpha1.DatabaseObserver{}).SetupWebhookWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create webhook", "webhook", "DatabaseObserver") + os.Exit(1) + } } // PDB Reconciler @@ -263,6 +293,17 @@ func main() { os.Exit(1) } + // Observability DatabaseObserver Reconciler + if err = (&observabilitycontroller.DatabaseObserverReconciler{ + Client: mgr.GetClient(), + Log: ctrl.Log.WithName("controllers").WithName("observability").WithName("DatabaseObserver"), + Scheme: mgr.GetScheme(), + Recorder: mgr.GetEventRecorderFor("DatabaseObserver"), + }).SetupWithManager(mgr); err != nil { + setupLog.Error(err, "unable to create controller", "controller", "DatabaseObserver") + os.Exit(1) + } + // +kubebuilder:scaffold:builder // Add index for PDB CR to enable mgr to cache PDBs @@ -280,3 +321,35 @@ func main() { os.Exit(1) } } + +func getWatchNamespace() (map[string]cache.Config, error) { + // WatchNamespaceEnvVar is the constant for env variable WATCH_NAMESPACE + // which specifies the Namespace to watch. + // An empty value means the operator is running with cluster scope. + + var watchNamespaceEnvVar = "WATCH_NAMESPACE" + var nsmap map[string]cache.Config + ns, found := os.LookupEnv(watchNamespaceEnvVar) + values := strings.Split(ns, ",") + if len(values) == 1 && values[0] == "" { + fmt.Printf(":CLUSTER SCOPED:\n") + return nil, nil + } + fmt.Printf(":NAMESPACE SCOPED:\n") + fmt.Printf("WATCH LIST=%s\n", values) + nsmap = make(map[string]cache.Config, len(values)) + if !found { + return nsmap, fmt.Errorf("%s must be set", watchNamespaceEnvVar) + } + + if ns == "" { + return nil, nil + } + + for _, ns := range values { + nsmap[ns] = cache.Config{} + } + + return nsmap, nil + +} diff --git a/oracle-database-operator.yaml b/oracle-database-operator.yaml index 70f026c1..504fc7cd 100644 --- a/oracle-database-operator.yaml +++ b/oracle-database-operator.yaml @@ -165,6 +165,8 @@ spec: type: string displayName: type: string + isLongTermBackup: + type: boolean ociConfig: description: "*********************** *\tOCI config ***********************" properties: @@ -173,6 +175,8 @@ spec: secretName: type: string type: object + retentionPeriodInDays: + type: integer target: description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster Important: Run "make" to regenerate code after modifying this file' properties: @@ -572,11 +576,59 @@ spec: - connectionStrings type: object type: array + conditions: + items: + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n \ttype FooStatus struct{ \t // Represents the observations of a foo's current state. \t // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" \t // +patchMergeKey=type \t // +patchStrategy=merge \t // +listType=map \t // +listMapKey=type \t Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n \t // other fields \t}" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map lifecycleState: description: 'INSERT ADDITIONAL STATUS FIELD - define observed state of cluster Important: Run "make" to regenerate code after modifying this file' type: string timeCreated: type: string + walletExpiringDate: + type: string type: object type: object served: true @@ -853,6 +905,195 @@ status: --- apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.1 + creationTimestamp: null + name: databaseobservers.observability.oracle.com +spec: + group: observability.oracle.com + names: + kind: DatabaseObserver + listKind: DatabaseObserverList + plural: databaseobservers + singular: databaseobserver + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.exporterConfig + name: ExporterConfig + type: string + - jsonPath: .status.status + name: Status + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: DatabaseObserver is the Schema for the databaseobservers 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: DatabaseObserverSpec defines the desired state of DatabaseObserver + properties: + database: + description: DatabaseObserverDatabase defines the database details used for DatabaseObserver + properties: + dbConnectionString: + properties: + key: + type: string + secret: + type: string + type: object + dbPassword: + properties: + key: + type: string + secret: + type: string + vaultOCID: + type: string + vaultSecretName: + type: string + type: object + dbUser: + properties: + key: + type: string + secret: + type: string + type: object + dbWallet: + properties: + key: + type: string + secret: + type: string + type: object + type: object + exporter: + description: DatabaseObserverExporterConfig defines the configuration details related to the exporters of DatabaseObserver + properties: + configuration: + properties: + configmap: + description: ConfigMapDetails defines the configmap name + properties: + configmapName: + type: string + key: + type: string + type: object + type: object + image: + type: string + service: + description: DatabaseObserverService defines the exporter service component of DatabaseObserver + properties: + port: + format: int32 + type: integer + type: object + type: object + ociConfig: + properties: + configMapName: + type: string + secretName: + type: string + type: object + prometheus: + description: PrometheusConfig defines the generated resources for Prometheus + properties: + labels: + additionalProperties: + type: string + type: object + port: + type: string + type: object + replicas: + format: int32 + type: integer + type: object + status: + description: DatabaseObserverStatus defines the observed state of DatabaseObserver + properties: + conditions: + description: 'INSERT ADDITIONAL STATUS FIELD - define observed state of cluster Important: Run "make" to regenerate code after modifying this file' + items: + description: "Condition contains details for one aspect of the current state of this API Resource. --- This struct is intended for direct use as an array at the field path .status.conditions. For example, \n \ttype FooStatus struct{ \t // Represents the observations of a foo's current state. \t // Known .status.conditions.type are: \"Available\", \"Progressing\", and \"Degraded\" \t // +patchMergeKey=type \t // +patchStrategy=merge \t // +listType=map \t // +listMapKey=type \t Conditions []metav1.Condition `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"` \n \t // other fields \t}" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition transitioned from one status to another. This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation that the condition was set based upon. For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating the reason for the condition's last transition. Producers of specific condition types may define expected values and meanings for this field, and whether the values are considered a guaranteed API. The value should be a CamelCase string. This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. --- Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be useful (see .node.status.conditions), the ability to deconflict is important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + exporterConfig: + type: string + replicas: + type: integer + status: + type: string + required: + - conditions + - exporterConfig + type: object + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.6.1 @@ -1533,9 +1774,15 @@ spec: asClone: description: Indicate if 'AS CLONE' option should be used in the command to plug in a PDB. This property is applicable when the Action property is PLUG but not required. type: boolean + assertivePdbDeletion: + description: turn on the assertive approach to delete pdb resource kubectl delete pdb ..... automatically triggers the pluggable database deletion + type: boolean cdbName: description: Name of the CDB type: string + cdbNamespace: + description: CDB Namespace + type: string cdbResName: description: Name of the CDB Custom Resource that runs the ORDS container type: string @@ -1688,6 +1935,40 @@ spec: unlimitedStorage: description: Relevant for Create and Plug operations. True for unlimited storage. Even when set to true, totalSize and tempSize MUST be specified in the request if Action is Create. type: boolean + webServerPwd: + description: Password for the Web ServerPDB User + properties: + secret: + description: PDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object + webServerUser: + description: Web Server User with SQL Administrator role to allow us to authenticate to the PDB Lifecycle Management REST endpoints + properties: + secret: + description: PDBSecret defines the secretName + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - secret + type: object xmlFileName: description: XML metadata filename to be used for Plug or Unplug operations type: string @@ -1753,7 +2034,18 @@ spec: singular: shardingdatabase scope: Namespaced versions: - - name: v1alpha1 + - additionalPrinterColumns: + - jsonPath: .status.gsm.state + name: Gsm State + type: string + - jsonPath: .status.gsm.services + name: Services + type: string + - jsonPath: .status.gsm.shards + name: shards + priority: 1 + type: string + name: v1alpha1 schema: openAPIV3Schema: description: ShardingDatabase is the Schema for the shardingdatabases API @@ -1769,6 +2061,8 @@ spec: spec: description: ShardingDatabaseSpec defines the desired state of ShardingDatabase properties: + InvitedNodeSubnet: + type: string catalog: items: description: CatalogSpec defines the desired state of CatalogSpec @@ -1790,7 +2084,7 @@ spec: description: PullPolicy describes a policy for if/when to pull a container image type: string isDelete: - type: boolean + type: string label: type: string name: @@ -1812,6 +2106,21 @@ spec: resources: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -1828,7 +2137,7 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object storageSizeInGb: @@ -1838,20 +2147,52 @@ spec: - name type: object type: array + dbEdition: + type: string dbImage: type: string dbImagePullSecret: type: string - gsm: - items: - description: GsmSpec defines the desired state of GsmSpec - properties: - envVars: - items: - description: EnvironmentVariable represents a named variable accessible for containers. - properties: - name: - type: string + dbSecret: + description: Secret Details + properties: + encryptionType: + type: string + keyFileMountLocation: + type: string + keyFileName: + type: string + keySecretName: + type: string + name: + type: string + nsConfigMap: + type: string + nsSecret: + type: string + pwdFileMountLocation: + type: string + pwdFileName: + type: string + required: + - name + - pwdFileName + type: object + fssStorageClass: + type: string + gsm: + items: + description: GsmSpec defines the desired state of GsmSpec + properties: + directorName: + type: string + envVars: + description: Replicas int32 `json:"replicas,omitempty"` // Gsm Replicas. If you set OraGsmPvcName then it is set default to 1. + items: + description: EnvironmentVariable represents a named variable accessible for containers. + properties: + name: + type: string value: type: string required: @@ -1863,7 +2204,7 @@ spec: description: PullPolicy describes a policy for if/when to pull a container image type: string isDelete: - type: boolean + type: string label: type: string name: @@ -1878,12 +2219,26 @@ spec: type: object pvcName: type: string - replicas: - format: int32 - type: integer + region: + type: string resources: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -1900,7 +2255,7 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object storageSizeInGb: @@ -1910,10 +2265,109 @@ spec: - name type: object type: array + gsmDevMode: + type: string gsmImage: type: string gsmImagePullSecret: type: string + gsmService: + items: + description: Service Definition + properties: + available: + type: string + clbGoal: + type: string + commitOutcome: + type: string + drainTimeout: + type: string + dtp: + type: string + edition: + type: string + failoverDelay: + type: string + failoverMethod: + type: string + failoverPrimary: + type: string + failoverRestore: + type: string + failoverRetry: + type: string + failoverType: + type: string + gdsPool: + type: string + lag: + type: integer + locality: + type: string + name: + type: string + notification: + type: string + pdbName: + type: string + policy: + type: string + preferred: + type: string + prferredAll: + type: string + regionFailover: + type: string + retention: + type: string + role: + type: string + sessionState: + type: string + sqlTransactionProfile: + type: string + stopOption: + type: string + tableFamily: + type: string + tfaPolicy: + type: string + required: + - name + type: object + type: array + gsmShardGroup: + items: + properties: + deployAs: + type: string + name: + type: string + region: + type: string + required: + - name + type: object + type: array + gsmShardSpace: + items: + description: ShardSpace Specs + properties: + chunks: + type: integer + name: + type: string + protectionMode: + type: string + shardGroup: + type: string + required: + - name + type: object + type: array + invitedNodeSubnetFlag: + type: string isClone: type: boolean isDataGuard: @@ -1922,13 +2376,15 @@ spec: type: boolean isDeleteOraPvc: type: boolean + isDownloadScripts: + type: boolean isExternalSvc: type: boolean - namespace: + isTdeWallet: type: string - nsConfigMap: - type: string - nsSecret: + liveinessCheckPeriod: + type: integer + namespace: type: string portMappings: items: @@ -1949,15 +2405,19 @@ spec: - targetPort type: object type: array - scriptsLocation: + readinessCheckPeriod: + type: integer + replicationType: type: string - secret: + scriptsLocation: type: string shard: description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster Important: Run "make" to regenerate code after modifying this file' items: description: ShardSpec is a specification of Shards for an application deployment. properties: + deployAs: + type: string envVars: items: description: EnvironmentVariable represents a named variable accessible for containers. @@ -1975,7 +2435,12 @@ spec: description: PullPolicy describes a policy for if/when to pull a container image type: string isDelete: - type: boolean + enum: + - enable + - disable + - failed + - force + type: string label: type: string name: @@ -1997,6 +2462,21 @@ spec: resources: description: ResourceRequirements describes the compute resource requirements. properties: + claims: + description: "Claims lists the names of resources, defined in spec.resourceClaims, that are used by this container. \n This is an alpha field and requires enabling the DynamicResourceAllocation feature gate. \n This field is immutable. It can only be set for containers." + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: Name must match the name of one entry in pod.spec.resourceClaims of the Pod where this field is used. It makes that resource available inside a container. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map limits: additionalProperties: anyOf: @@ -2013,9 +2493,15 @@ spec: - type: string pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ x-kubernetes-int-or-string: true - description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' + description: 'Requests describes the minimum amount of compute resources required. If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, otherwise to an implementation-defined value. Requests cannot exceed Limits. More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/' type: object type: object + shardGroup: + type: string + shardRegion: + type: string + shardSpace: + type: string storageSizeInGb: format: int32 type: integer @@ -2023,16 +2509,29 @@ spec: - name type: object type: array + shardBuddyRegion: + type: string + shardConfigName: + type: string + shardRegion: + items: + type: string + type: array + shardingType: + type: string stagePvcName: type: string storageClass: type: string + tdeWalletPvc: + type: string + tdeWalletPvcMountLocation: + type: string required: - catalog - dbImage - gsm - gsmImage - - secret - shard type: object status: @@ -2207,10 +2706,12 @@ spec: type: boolean charset: type: string - cloneFrom: + createAs: + enum: + - primary + - standby + - clone type: string - createAsStandby: - type: boolean dgBrokerConfigured: type: boolean edition: @@ -2270,14 +2771,18 @@ spec: - ReadWriteOnce - ReadWriteMany type: string + datafilesVolumeName: + type: string + scriptsVolumeName: + type: string + setWritePermissions: + type: boolean size: type: string storageClass: type: string volumeClaimAnnotation: type: string - volumeName: - type: string type: object primaryDatabaseRef: type: string @@ -2285,6 +2790,23 @@ spec: type: integer replicas: type: integer + resources: + properties: + limits: + properties: + cpu: + type: string + memory: + type: string + type: object + requests: + properties: + cpu: + type: string + memory: + type: string + type: object + type: object serviceAccountName: type: string serviceAnnotations: @@ -2300,6 +2822,8 @@ spec: type: string tcpsListenerPort: type: integer + tcpsTlsSecret: + type: string required: - image type: object @@ -2318,8 +2842,6 @@ spec: type: string clientWalletLoc: type: string - cloneFrom: - type: string clusterConnectString: type: string conditions: @@ -2370,6 +2892,8 @@ spec: x-kubernetes-list-type: map connectString: type: string + createdAs: + type: string datafilesCreated: default: "false" type: string @@ -2423,14 +2947,18 @@ spec: - ReadWriteOnce - ReadWriteMany type: string + datafilesVolumeName: + type: string + scriptsVolumeName: + type: string + setWritePermissions: + type: boolean size: type: string storageClass: type: string volumeClaimAnnotation: type: string - volumeName: - type: string type: object prebuiltDB: type: boolean @@ -2454,9 +2982,13 @@ spec: type: string tcpsPdbConnectString: type: string + tcpsTlsSecret: + default: "" + type: string required: - isTcpsEnabled - persistence + - tcpsTlsSecret type: object type: object served: true @@ -2525,6 +3057,23 @@ metadata: creationTimestamp: null name: oracle-database-operator-manager-role rules: +- apiGroups: + - "" + resources: + - configmaps + - deployments + - events + - pods + - secrets + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - "" resources: @@ -2570,11 +3119,31 @@ rules: - patch - update - watch +- apiGroups: + - "" + resources: + - deployments + - events + - pods + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - "" resources: - events - - nodes + verbs: + - create + - patch +- apiGroups: + - "" + resources: - persistentvolumeclaims - pods - pods/exec @@ -2588,6 +3157,14 @@ rules: - patch - update - watch +- apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - get + - list + - watch - apiGroups: - '''''' resources: @@ -2600,6 +3177,27 @@ rules: - patch - update - watch +- apiGroups: + - apps + resources: + - configmaps + verbs: + - get + - list +- apiGroups: + - apps + resources: + - deployments + - pods + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - apps resources: @@ -2637,9 +3235,9 @@ rules: - "" resources: - configmaps + - containers - events - namespaces - - nodes - persistentvolumeclaims - pods - pods/exec @@ -2654,6 +3252,26 @@ rules: - patch - update - watch +- apiGroups: + - "" + resources: + - configmaps + - containers + - events + - namespaces + - pods + - pods/exec + - pods/log + - secrets + - services + verbs: + - create + - delete + - get + - list + - patch + - update + - watch - apiGroups: - "" resources: @@ -2947,6 +3565,52 @@ rules: - get - patch - update +- apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - observability.oracle.com + resources: + - databaseobservers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - observability.oracle.com + resources: + - databaseobservers/finalizers + verbs: + - update +- apiGroups: + - observability.oracle.com + resources: + - databaseobservers/status + verbs: + - get + - patch + - update +- apiGroups: + - storage.k8s.io + resources: + - storageclasses + verbs: + - get + - list + - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -2991,9 +3655,10 @@ subjects: namespace: oracle-database-operator-system --- apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding +kind: RoleBinding metadata: name: oracle-database-operator-oracle-database-operator-manager-rolebinding + namespace: oracle-database-operator-system roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole @@ -3006,11 +3671,11 @@ subjects: apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: - name: oracle-database-operator-oracle-database-operator-proxy-rolebinding + name: oracle-database-operator-proxy-rolebinding roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole - name: proxy-role + name: oracle-database-operator-oracle-database-operator-proxy-role subjects: - kind: ServiceAccount name: default @@ -3197,6 +3862,26 @@ webhooks: resources: - pdbs sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: oracle-database-operator-webhook-service + namespace: oracle-database-operator-system + path: /mutate-database-oracle-com-v1alpha1-shardingdatabase + failurePolicy: Fail + name: mshardingdatabase.kb.io + rules: + - apiGroups: + - database.oracle.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - shardingdatabases + sideEffects: None - admissionReviewVersions: - v1 - v1beta1 @@ -3218,6 +3903,26 @@ webhooks: resources: - singleinstancedatabases sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: oracle-database-operator-webhook-service + namespace: oracle-database-operator-system + path: /mutate-observability-oracle-com-v1alpha1-databaseobserver + failurePolicy: Fail + name: mdatabaseobserver.kb.io + rules: + - apiGroups: + - observability.oracle.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - databaseobservers + sideEffects: None --- apiVersion: admissionregistration.k8s.io/v1 kind: ValidatingWebhookConfiguration @@ -3390,6 +4095,27 @@ webhooks: resources: - pdbs sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: oracle-database-operator-webhook-service + namespace: oracle-database-operator-system + path: /validate-database-oracle-com-v1alpha1-shardingdatabase + failurePolicy: Fail + name: vshardingdatabase.kb.io + rules: + - apiGroups: + - database.oracle.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + - DELETE + resources: + - shardingdatabases + sideEffects: None - admissionReviewVersions: - v1 - v1beta1 @@ -3412,6 +4138,26 @@ webhooks: resources: - singleinstancedatabases sideEffects: None +- admissionReviewVersions: + - v1 + clientConfig: + service: + name: oracle-database-operator-webhook-service + namespace: oracle-database-operator-system + path: /validate-observability-oracle-com-v1alpha1-databaseobserver + failurePolicy: Fail + name: vdatabaseobserver.kb.io + rules: + - apiGroups: + - observability.oracle.com + apiVersions: + - v1alpha1 + operations: + - CREATE + - UPDATE + resources: + - databaseobservers + sideEffects: None --- apiVersion: apps/v1 kind: Deployment @@ -3435,7 +4181,10 @@ spec: - --enable-leader-election command: - /manager - image: container-registry.oracle.com/database/operator:1.0.0 + env: + - name: WATCH_NAMESPACE + value: "" + image: container-registry.oracle.com/database/operator:latest imagePullPolicy: Always name: manager ports: diff --git a/ords/Dockerfile b/ords/Dockerfile index d4e16b6c..772a7e6d 100644 --- a/ords/Dockerfile +++ b/ords/Dockerfile @@ -1,34 +1,63 @@ -#LICENSE UPL 1.0 -# -# Copyright (c) 1982-2017 Oracle and/or its affiliates. All rights reserved. -# -# ORACLE DOCKERFILES PROJECT -# -------------------------- -# This is the Dockerfile for Oracle Rest Data Services 22.2 -# +## Copyright (c) 2022 Oracle and/or its affiliates. +## +## The Universal Permissive License (UPL), Version 1.0 +## +## Subject to the condition set forth below, permission is hereby granted to any +## person obtaining a copy of this software, associated documentation and/or data +## (collectively the "Software"), free of charge and under any and all copyright +## rights in the Software, and any and all patent rights owned or freely +## licensable by each licensor hereunder covering either (i) the unmodified +## Software as contributed to or provided by such licensor, or (ii) the Larger +## Works (as defined below), to deal in both +## +## (a) the Software, and +## (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if +## one is included with the Software (each a "Larger Work" to which the Software +## is contributed by such licensors), +## +## without restriction, including without limitation the rights to copy, create +## derivative works of, display, perform, and distribute the Software and make, +## use, sell, offer for sale, import, export, have made, and have sold the +## Software and the Larger Work(s), and to sublicense the foregoing rights on +## either these or other terms. +## +## This license is subject to the following condition: +## The above copyright notice and either this complete permission notice or at +## a minimum a reference to the UPL must be included in all copies or +## substantial portions of the Software. +## +## THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +## IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +## FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +## AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +## LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +## OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +## SOFTWARE. + FROM container-registry.oracle.com/java/jdk:latest # Environment variables required for this build (do NOT change) # ------------------------------------------------------------- ENV ORDS_HOME=/opt/oracle/ords/ \ - RUN_FILE="runOrdsSSL.sh" - -#RUN_FILE_NOSSL="runOrdsNOSSL.sh" + RUN_FILE="runOrdsSSL.sh" \ + ORDSVERSION=23.4.0-8 # Copy binaries # ------------- COPY $RUN_FILE $ORDS_HOME -#COPY $RUN_FILE_NOSSL $ORDS_HOME -RUN yum -y install yum-utils bind-utils tree hostname openssl net-tools zip unzip tar wget vim-minimal which sudo expect procps && \ +RUN yum -y install yum-utils bind-utils tree hostname openssl net-tools zip unzip tar wget vim-minimal which sudo expect procps curl lsof && \ yum-config-manager --add-repo=http://yum.oracle.com/repo/OracleLinux/OL8/oracle/software/x86_64 && \ yum -y install java-11-openjdk-devel && \ - yum -y install ords && \ yum -y install iproute && \ yum clean all +RUN curl -o /tmp/ords-$ORDSVERSION.el8.noarch.rpm https://yum.oracle.com/repo/OracleLinux/OL8/oracle/software/x86_64/getPackage/ords-$ORDSVERSION.el8.noarch.rpm + +RUN rpm -ivh /tmp/ords-$ORDSVERSION.el8.noarch.rpm + # Setup filesystem and oracle user -# ------------------------------------------------------------ +# -------------------------------- RUN mkdir -p $ORDS_HOME/doc_root && \ mkdir -p $ORDS_HOME/error && \ mkdir -p $ORDS_HOME/secrets && \ @@ -49,5 +78,3 @@ EXPOSE 8888 # Define default command to start Ords Services CMD $ORDS_HOME/$RUN_FILE -## ONLY FOR DEVELOPMENT STAGE -#CMD ["/usr/sbin/init"] diff --git a/ords/runOrdsSSL.sh b/ords/runOrdsSSL.sh index 23b99f1e..35f1b77b 100644 --- a/ords/runOrdsSSL.sh +++ b/ords/runOrdsSSL.sh @@ -1,16 +1,44 @@ #!/bin/bash -# -# Since: June, 2022 -# Author: matteo.malvezzi@oracle.com -# Description: Setup and runs Oracle Rest Data Services 22.2. -# -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. -# -# Copyright (c) 2014-2017 Oracle and/or its affiliates. All rights reserved. -# -# MODIFIED (DD-Mon-YY) -# mmalvezz 25-Jun-22 - Initial version -# mmalvezz 17-Oct-22 - db.customURL utilization + +cat <$TNSNAME - - function SetParameter() { ##ords config info <--- Use this command to get the list @@ -67,65 +91,16 @@ function SetParameter() { $ORDS --config ${CONFIG} config set misc.pagination.maxRows 1000 $ORDS --config ${CONFIG} config set db.cdb.adminUser "${CDBADMIN_USER:-C##DBAPI_CDB_ADMIN} AS SYSDBA" $ORDS --config ${CONFIG} config secret --password-stdin db.cdb.adminUser.password << EOF -${CDBADMIN_PWD:-WElcome_12##} +${CDBADMIN_PWD:-PROVIDE_A_PASSWORD} EOF -## $ORDS --config ${CONFIG} config set db.username "SYS AS SYSDBA" -## $ORDS --config ${CONFIG} config secret --password-stdin db.password <$PASSFILE -welcome1 -EOF - -## $JAVA_HOME/bin/keytool -genkey -keyalg RSA -alias selfsigned -keystore keystore.jks \ -## -dname "CN=${HN}, OU=Example Department, O=Example Company, L=Birmingham, ST=West Midlands, C=GB" \ -## -storepass welcome1 -validity 3600 -keysize 2048 -keypass welcome1 -## -## -## $JAVA_HOME/bin/keytool -importkeystore -srckeystore keystore.jks -srcalias selfsigned -srcstorepass welcome1 \ -## -destkeystore keystore.p12 -deststoretype PKCS12 -deststorepass welcome1 -destkeypass welcome1 -## -## -## ${OPENSSL} pkcs12 -in ${KEYSTORE}/keystore.p12 -nodes -nocerts -out ${KEYSTORE}/${HN}-key.pem -passin file:${PASSFILE} -## ${OPENSSL} pkcs12 -in ${KEYSTORE}/keystore.p12 -nokeys -out ${KEYSTORE}/${HN}.pem -passin file:${PASSFILE} -## ${OPENSSL} pkcs8 -topk8 -inform PEM -outform DER -in ${HN}-key.pem -out ${HN}-key.der -nocrypt -## ${OPENSSL} x509 -inform PEM -outform DER -in ${HN}.pem -out ${HN}.der - - - - - - - - -rm $PASSFILE -ls -ltr $KEYSTORE - - - -} - - function setupOrds() { echo "====================================================" @@ -163,7 +138,6 @@ export ORDS_LOGS=/tmp ORDS_PASSWORD=`cat $ORDS_HOME/secrets/$ORDS_PWD_KEY` } -setupHTTPS; SetParameter; $ORDS --config ${CONFIG} install \ @@ -173,8 +147,8 @@ $ORDS --config ${CONFIG} install \ --log-folder ${ORDS_LOGS} \ --proxy-user \ --password-stdin <${CKF} 2>&1 +echo "checkfile" >> ${CKF} +NOT_INSTALLED=`cat ${CKF} | grep "INFO: The" |wc -l ` echo NOT_INSTALLED=$NOT_INSTALLED + function StartUp () { $ORDS --config $CONFIG serve --port 8888 --secure } diff --git a/rbac/cluster-role-binding.yaml b/rbac/cluster-role-binding.yaml new file mode 100644 index 00000000..1c609012 --- /dev/null +++ b/rbac/cluster-role-binding.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: oracle-database-operator-oracle-database-operator-manager-rolebinding + namespace: oracle-database-operator-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: oracle-database-operator-manager-role +subjects: +- kind: ServiceAccount + name: default + namespace: oracle-database-operator-system +--- diff --git a/rbac/default-ns-role-binding.yaml b/rbac/default-ns-role-binding.yaml new file mode 100644 index 00000000..b737e1f1 --- /dev/null +++ b/rbac/default-ns-role-binding.yaml @@ -0,0 +1,15 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: oracle-database-operator-oracle-database-operator-manager-rolebinding + namespace: default +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: oracle-database-operator-manager-role +subjects: +- kind: ServiceAccount + name: default + namespace: oracle-database-operator-system +--- diff --git a/rbac/node-rbac.yaml b/rbac/node-rbac.yaml new file mode 100644 index 00000000..ac474873 --- /dev/null +++ b/rbac/node-rbac.yaml @@ -0,0 +1,27 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: oracle-database-operator-manager-role-node +rules: +- apiGroups: + - "" + resources: + - nodes + verbs: + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: oracle-database-operator-manager-role-node-cluster-role-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: oracle-database-operator-manager-role-node +subjects: +- kind: ServiceAccount + name: default + namespace: oracle-database-operator-system +--- diff --git a/rbac/persistent-volume-rbac.yaml b/rbac/persistent-volume-rbac.yaml new file mode 100644 index 00000000..bce9733d --- /dev/null +++ b/rbac/persistent-volume-rbac.yaml @@ -0,0 +1,28 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: oracle-database-operator-manager-role-persistent-volume +rules: +- apiGroups: + - "" + resources: + - persistentvolumes + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: oracle-database-operator-manager-role-persistent-volume-cluster-role-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: oracle-database-operator-manager-role-persistent-volume +subjects: +- kind: ServiceAccount + name: default + namespace: oracle-database-operator-system +--- diff --git a/rbac/storage-class-rbac.yaml b/rbac/storage-class-rbac.yaml new file mode 100644 index 00000000..a34f67d4 --- /dev/null +++ b/rbac/storage-class-rbac.yaml @@ -0,0 +1,28 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: oracle-database-operator-manager-role-storage-class +rules: +- apiGroups: + - storage.k8s.io + resources: + - storageclasses + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: oracle-database-operator-manager-role-storage-class-cluster-role-binding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: oracle-database-operator-manager-role-storage-class +subjects: +- kind: ServiceAccount + name: default + namespace: oracle-database-operator-system +--- diff --git a/test/e2e/resource/test_config.yaml b/test/e2e/resource/test_config.yaml index 1907af47..dc2768e2 100644 --- a/test/e2e/resource/test_config.yaml +++ b/test/e2e/resource/test_config.yaml @@ -18,7 +18,7 @@ instanceWalletPasswordOCID: ocid1.vaultsecret... subnetOCID: ocid1.subnet... # The OCID of the network security group used to test the network access settings nsgOCID: ocid1.networksecuritygroup... -# The URL of the bucket used for configure ADB manual backup +# The URL of the bucket used for configure ADB on-demand backup bucketURL: https://swiftobjectstorage.region.oraclecloud.com/v1/namespace-string/bucket_name # The auth token generated in OCI Console > Profile > User Settings > Auth Token authToken: token diff --git a/test/e2e/util/util.go b/test/e2e/util/util.go index 81b5259d..b9e76aa7 100644 --- a/test/e2e/util/util.go +++ b/test/e2e/util/util.go @@ -44,7 +44,7 @@ import ( "strings" "time" - goyaml "gopkg.in/yaml.v2" + goyaml "gopkg.in/yaml.v3" dbv1alpha1 "github.com/oracle/oracle-database-operator/apis/database/v1alpha1"