oracle/controllers/common.go (131 lines of code) (raw):
// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package controllers
import (
"context"
"fmt"
"strings"
"time"
"github.com/go-logr/logr"
"google.golang.org/grpc"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
commonv1alpha1 "github.com/GoogleCloudPlatform/elcarro-oracle-operator/common/api/v1alpha1"
v1alpha1 "github.com/GoogleCloudPlatform/elcarro-oracle-operator/oracle/api/v1alpha1"
"github.com/GoogleCloudPlatform/elcarro-oracle-operator/oracle/pkg/agents/common"
"github.com/GoogleCloudPlatform/elcarro-oracle-operator/oracle/pkg/agents/consts"
dbdpb "github.com/GoogleCloudPlatform/elcarro-oracle-operator/oracle/pkg/agents/oracle"
)
const (
FinalizerName = "oracle.db.anthosapis.com"
PhysBackupTimeLimitDefault = 60 * time.Minute
StatusReady = "Ready"
StatusInProgress = "InProgress"
RestoreInProgress = "Restore" + StatusInProgress
CreateInProgress = "Create" + StatusInProgress
PITRLabel = "pitr"
IncarnationLabel = "incarnation"
ParentIncarnationLabel = "parent-incarnation"
SCNAnnotation = "scn"
TimestampAnnotation = "timestamp"
DatabaseImageAnnotation = "database-image"
ParameterUpdateStateMachine = "ParameterUpdateStateMachine"
DatabaseContainerName = "oracledb"
)
var (
// SvcName is a string template for service names.
SvcName = "%s-svc"
// AgentSvcName is a string template for agent service names.
AgentSvcName = "%s-agent-svc"
// DbdaemonSvcName is a string template for dbdaemon service names.
DbdaemonSvcName = "%s-dbdaemon-svc"
// SvcEndpoint is a string template for service endpoints.
SvcEndpoint = "%s.%s" // SvcName.namespaceName
sourceCidrRange = []string{"0.0.0.0/0"}
// StsName is a string template for Database stateful set names.
StsName = "%s-sts"
// AgentDeploymentName is a string template for agent deployment names.
AgentDeploymentName = "%s-agent-deployment"
// PvcMountName is a string template for pvc names.
PvcMountName = "%s-pvc-%s" // inst.name-pvc-mount, e.g. mydb-pvc-u02
// CmName is a string template for config map names.
CmName = "%s-cm"
// DatabaseTaskType is the value of the 'task-type' label assigned to db pod.
DatabaseTaskType = "oracle-db"
// MonitorTaskType is the value of the 'task-type' label assigned to the monitoring deployment.
MonitorTaskType = "monitor"
// DefaultDiskSpecs is the default DiskSpec settings.
DefaultDiskSpecs = map[string]commonv1alpha1.DiskSpec{
"DataDisk": {
Name: "DataDisk",
Size: resource.MustParse("100Gi"),
},
"LogDisk": {
Name: "LogDisk",
Size: resource.MustParse("150Gi"),
},
"BackupDisk": {
Name: "BackupDisk",
Size: resource.MustParse("100Gi"),
},
}
defaultDiskMountLocations = map[string]string{
"DataDisk": "u02",
"LogDisk": "u03",
"BackupDisk": "u04",
}
)
// StsParams stores parameters for creating a database stateful set.
type StsParams struct {
Inst *v1alpha1.Instance
Scheme *runtime.Scheme
Namespace string
Images map[string]string
SvcName string
StsName string
PrivEscalation bool
ConfigMap *corev1.ConfigMap
Restore *v1alpha1.RestoreSpec
Disks []commonv1alpha1.DiskSpec
Config *v1alpha1.Config
Log logr.Logger
Services []commonv1alpha1.Service
}
type ConnCloseFunc func()
type GRPCDatabaseClientFactory struct {
dbclient *dbdpb.DatabaseDaemonClient
}
// DatabaseClientFactory is a GRPC implementation of DatabaseClientFactory. Exists for test mock.
type DatabaseClientFactory interface {
// New returns new Client.
// connection close function should be invoked by the caller if
// error is nil.
New(ctx context.Context, r client.Reader, namespace, instName string) (dbdpb.DatabaseDaemonClient, func() error, error)
}
// GetPVCNameAndMount returns PVC names and their corresponding mount.
func GetPVCNameAndMount(instName, diskName string) (string, string) {
spec := DefaultDiskSpecs[diskName]
mountLocation := defaultDiskMountLocations[spec.Name]
pvcName := fmt.Sprintf(PvcMountName, instName, mountLocation)
return pvcName, mountLocation
}
// GetCustomPVCNameAndMount returns PVC names and their corresponding mounts for extra disks.
func GetCustomPVCNameAndMount(inst *v1alpha1.Instance, diskName string) (string, string) {
pvcName := fmt.Sprintf(PvcMountName, inst.GetName(), strings.ToLower(diskName))
mountLocation := strings.ToLower(diskName)
return pvcName, mountLocation
}
// New returns a new database daemon client
func (d *GRPCDatabaseClientFactory) New(ctx context.Context, r client.Reader, namespace, instName string) (dbdpb.DatabaseDaemonClient, func() error, error) {
var dbservice = fmt.Sprintf(DbdaemonSvcName, instName)
svc := &corev1.Service{}
if err := r.Get(ctx, types.NamespacedName{Name: dbservice, Namespace: namespace}, svc); err != nil {
return nil, nil, err
}
conn, err := common.DatabaseDaemonDialService(ctx, fmt.Sprintf("%s:%d", svc.Spec.ClusterIP, consts.DefaultDBDaemonPort), grpc.WithBlock())
if err != nil {
return nil, func() error { return nil }, err
}
return dbdpb.NewDatabaseDaemonClient(conn), conn.Close, nil
}
// GetBackupGcsPath resolves the actual gcs path based on backup spec.
func GetBackupGcsPath(backup *v1alpha1.Backup) string {
gcsPath := backup.Spec.GcsPath
if backup.Spec.GcsDir != "" {
if !strings.HasSuffix(backup.Spec.GcsDir, "/") {
gcsPath = backup.Spec.GcsDir + "/"
}
gcsPath = gcsPath + backup.Name
}
return gcsPath
}
var reservedDiskNames = map[string]struct{}{
"datadisk": {},
"backupdisk": {},
"logdisk": {},
}
func IsReservedDiskName(diskName string) bool {
_, exists := reservedDiskNames[strings.ToLower(diskName)]
return exists
}