polardbxoperator/pkg/operator/v1/xstore/convention/convention.go

286 lines
7.5 KiB
Go

/*
Copyright 2021 Alibaba Group Holding Limited.
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 convention
import (
"errors"
"fmt"
"github.com/alibaba/polardbx-operator/pkg/util/name"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/util/rand"
"strconv"
"strings"
"sigs.k8s.io/controller-runtime/pkg/client"
polardbxv1 "github.com/alibaba/polardbx-operator/api/v1"
polardbxv1xstore "github.com/alibaba/polardbx-operator/api/v1/xstore"
k8shelper "github.com/alibaba/polardbx-operator/pkg/k8s/helper"
xstoremeta "github.com/alibaba/polardbx-operator/pkg/operator/v1/xstore/meta"
)
// Conventions for services.
type ServiceType string
const (
ServiceTypeReadWrite ServiceType = "readwrite"
ServiceTypeReadOnly ServiceType = "readonly"
ServiceTypeMetrics ServiceType = "metrics"
ServiceTypeClusterIp ServiceType = "clusterIp"
ServiceTypeStaticClusterIp ServiceType = "staticClusterIp"
)
func GetXStoreServiceName(xstore *polardbxv1.XStore) string {
if xstore.Spec.ServiceName == "" {
return xstore.Name
} else {
return xstore.Spec.ServiceName
}
}
func NewClusterIpServiceName(podName string) string {
return podName + "-service"
}
func NewServiceName(xstore *polardbxv1.XStore, serviceType ServiceType) string {
xstoreServiceName := GetXStoreServiceName(xstore)
switch serviceType {
case ServiceTypeReadWrite:
return xstoreServiceName
case ServiceTypeReadOnly:
return xstoreServiceName + "-ro"
case ServiceTypeMetrics:
return xstoreServiceName + "-metrics"
}
panic("invalid service type: " + serviceType)
}
func NewXstorePodServiceName(pod *corev1.Pod) string {
return pod.Name + "-service"
}
// Conventions for port names.
const (
PortAccess = "mysql"
PortMetrics = "metrics"
PortProbe = "probe"
)
// Conventions for secret.
const SuperAccount = "admin"
func NewSecretName(xstore *polardbxv1.XStore) string {
return xstore.Name
}
// Convention for labels.
func ConstLabels(xstore *polardbxv1.XStore) map[string]string {
labels := map[string]string{
xstoremeta.LabelName: xstore.Name,
}
if xstore.Status.Rand != "" {
labels[xstoremeta.LabelRand] = xstore.Status.Rand
}
return labels
}
func LabelGeneration(xstore *polardbxv1.XStore) map[string]string {
return map[string]string{
xstoremeta.LabelGeneration: strconv.FormatInt(xstore.Status.ObservedGeneration, 10),
}
}
func DefaultRoleOf(nodeRole polardbxv1xstore.NodeRole) string {
switch nodeRole {
case polardbxv1xstore.RoleCandidate:
return xstoremeta.RoleFollower
case polardbxv1xstore.RoleVoter:
return xstoremeta.RoleLogger
case polardbxv1xstore.RoleLearner:
return xstoremeta.RoleLearner
default:
panic("invalid node role: " + nodeRole)
}
}
func ConstPodLabels(xstore *polardbxv1.XStore, nodeSet *polardbxv1xstore.NodeSet) map[string]string {
return k8shelper.PatchLabels(
ConstLabels(xstore),
LabelGeneration(xstore),
map[string]string{
xstoremeta.LabelNodeRole: strings.ToLower(string(nodeSet.Role)),
xstoremeta.LabelNodeSet: nodeSet.Name,
},
)
}
func GetGenerationLabelValue(object client.Object) (int64, error) {
labels := object.GetLabels()
val, ok := labels[xstoremeta.LabelGeneration]
if !ok {
return 0, errors.New("generation label not found")
}
return strconv.ParseInt(val, 10, 64)
}
func GetHashLabelValue(object client.Object) string {
labels := object.GetLabels()
if val, ok := labels[xstoremeta.LabelHash]; ok {
return val
}
return ""
}
func IsGenerationOutdated(xstore *polardbxv1.XStore, object client.Object) (bool, error) {
observedGeneration, err := GetGenerationLabelValue(object)
if err != nil {
return false, err
}
generation := xstore.Generation
return observedGeneration < generation, nil
}
// Conventions for pods.
func NewPodName(xstore *polardbxv1.XStore, nodeSet *polardbxv1xstore.NodeSet, index int) string {
// Dash linked string for empty parts [xstore name, xstore rand, node set name, index]
podName := xstore.Name
if xstore.Status.Rand != "" {
podName += "-" + xstore.Status.Rand
}
if nodeSet.Name != "" {
podName += "-" + nodeSet.Name
}
podName += "-" + strconv.Itoa(index)
return podName
}
func PodIndexInNodeSet(podName string) (int, error) {
dashIndex := strings.LastIndex(podName, "-")
if dashIndex < 0 {
return 0, errors.New("invalid pod name, no dash found")
}
indexStr := podName[dashIndex+1:]
return strconv.Atoi(indexStr)
}
// Conventions for config.
const (
ConfigMyCnfTemplate = "my.cnf.template"
ConfigMyCnfOverride = "my.cnf.override"
)
type ConfigMapType string
const (
ConfigMapTypeConfig ConfigMapType = "config"
ConfigMapTypeShared ConfigMapType = "shared"
ConfigMapTypeTask ConfigMapType = "task"
ConfigMapTypeRestore ConfigMapType = "restore"
)
func NewConfigMapName(xstore *polardbxv1.XStore, cmType ConfigMapType) string {
if xstore.Status.Rand != "" {
return fmt.Sprintf("%s-%s-%s", xstore.Name, xstore.Status.Rand, cmType)
} else {
return fmt.Sprintf("%s-%s", xstore.Name, cmType)
}
}
func NewBackupConfigMapName(xstoreBackup *polardbxv1.XStoreBackup, cmType ConfigMapType) string {
return fmt.Sprintf("%s-%s", xstoreBackup.Name, cmType)
}
// Conventions for containers.
const (
ContainerEngine = "engine"
ContainerExporter = "exporter"
ContainerProber = "prober"
)
// Conventions for xStore follower
const (
FileStreamBackupFilename = "backup"
FileStreamRootDir = "/filestream"
XClusterBackupBinFilepath = "/u01/xcluster_xtrabackup/bin/innobackupex"
XClusterBackupSetPrepareArg = "--apply-log"
GalaxyEngineBackupExtraArgs = " --slave-info --lock-ddl "
XClusterBackupExtraArgs = " --rds-execute-backup-lock-timeout=120 "
GalaxyEngineBackupStreamArgs = "--stream=xbstream"
XClusterBackupStreamArgs = "--stream=tar"
GalaxyEngineTargetDirArgs = "--target-dir="
XClusterTargetDirArgs = ""
GalaxyEngineBackupBinFilepath = "/tools/xstore/current/xcluster_xtrabackup80/bin/xtrabackup"
GalaxyEngineBackupSetPrepareArg = "--prepare"
PodInfoVolumeName = "podinfo"
PodInfoNamePath = "name"
PodInfoNameFieldPath = "metadata.labels['xstorefollowerjob/target_pod_name']"
TempPodSuffix = "-tmp"
)
// Conventions for jobs.
func NewJobName(xstore *polardbxv1.XStore, name string) string {
if xstore.Status.Rand != "" {
return fmt.Sprintf("%s-%s-%s", xstore.Name, xstore.Status.Rand, name)
} else {
return fmt.Sprintf("%s-%s", xstore.Name, name)
}
}
const (
ParameterName = "parameter"
ParameterType = "dynamic"
)
func GetParameterLabel() map[string]string {
return map[string]string{
ParameterName: ParameterType,
}
}
const AutoRebuildConfigMapName = "auto-build"
// Conventions for backup
type BackupJobType string
const (
BackupJobTypeFullBackup = "backup"
BackupJobTypeBinlogBackup = "binlog"
BackupJobTypeCollect = "collect"
)
func NewBackupJobName(targetPod *corev1.Pod, jobType BackupJobType) string {
return name.NewSplicedName(
name.WithTokens(string(jobType), "job", targetPod.Name, rand.String(4)),
name.WithPrefix(fmt.Sprintf("%s-job", jobType)),
)
}