diff --git a/.github/workflows/reviewdog.yml b/.github/workflows/reviewdog.yml index a2014ea9d..4d1c4f644 100644 --- a/.github/workflows/reviewdog.yml +++ b/.github/workflows/reviewdog.yml @@ -52,7 +52,7 @@ jobs: with: github_token: ${{ secrets.github_token }} reporter: github-pr-check - shellcheck_flags: -e SC2155 + shellcheck_flags: -e SC2155 --external-sources exclude: "./vendor/*" misspell: diff --git a/Makefile b/Makefile index 4f8f1de0b..ef813f046 100644 --- a/Makefile +++ b/Makefile @@ -103,7 +103,19 @@ kuttl-shfmt: e2e-test: kuttl-shfmt ROOT_REPO=$(ROOT_REPO) kubectl kuttl test --config e2e-tests/kuttl.yaml -manifests: kustomize generate ## Generate Kubernetes manifests (CRDs, RBAC, operator deployment) +.PHONY: generate-cr-yaml +generate-cr-yaml: + ./cmd/example-gen/scripts/generate.sh ps + +.PHONY: generate-restore-yaml +generate-restore-yaml: + ./cmd/example-gen/scripts/generate.sh ps-restore + +.PHONY: generate-backup-yaml +generate-backup-yaml: + ./cmd/example-gen/scripts/generate.sh ps-backup + +manifests: kustomize generate generate-cr-yaml generate-restore-yaml generate-backup-yaml ## Generate Kubernetes manifests (CRDs, RBAC, operator deployment) $(KUSTOMIZE) build config/crd/ > $(DEPLOYDIR)/crd.yaml echo "---" >> $(DEPLOYDIR)/crd.yaml diff --git a/api/v1/perconaservermysql_types.go b/api/v1/perconaservermysql_types.go index b7c35e62c..cb9379558 100644 --- a/api/v1/perconaservermysql_types.go +++ b/api/v1/perconaservermysql_types.go @@ -147,6 +147,8 @@ type MySQLSpec struct { VaultSecretName string `json:"vaultSecretName,omitempty"` + VolumeSpec *VolumeSpec `json:"volumeSpec,omitempty"` + PodSpec `json:",inline"` } @@ -194,7 +196,6 @@ type PodSpec struct { Size int32 `json:"size,omitempty"` Annotations map[string]string `json:"annotations,omitempty"` Labels map[string]string `json:"labels,omitempty"` - VolumeSpec *VolumeSpec `json:"volumeSpec,omitempty"` // Deprecated: not supported since v0.12.0. Use initContainer instead InitImage string `json:"initImage,omitempty"` @@ -409,7 +410,6 @@ type BackupStorageS3Spec struct { CredentialsSecret string `json:"credentialsSecret"` Region string `json:"region,omitempty"` EndpointURL string `json:"endpointUrl,omitempty"` - StorageClass string `json:"storageClass,omitempty"` } // BucketAndPrefix returns bucket name and backup prefix from Bucket concatenated with Prefix. diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go index 149c9023d..e78e2e2ad 100644 --- a/api/v1/zz_generated.deepcopy.go +++ b/api/v1/zz_generated.deepcopy.go @@ -501,6 +501,11 @@ func (in *MySQLSpec) DeepCopyInto(out *MySQLSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } + if in.VolumeSpec != nil { + in, out := &in.VolumeSpec, &out.VolumeSpec + *out = new(VolumeSpec) + (*in).DeepCopyInto(*out) + } in.PodSpec.DeepCopyInto(&out.PodSpec) } @@ -996,11 +1001,6 @@ func (in *PodSpec) DeepCopyInto(out *PodSpec) { (*out)[key] = val } } - if in.VolumeSpec != nil { - in, out := &in.VolumeSpec, &out.VolumeSpec - *out = new(VolumeSpec) - (*in).DeepCopyInto(*out) - } if in.InitContainer != nil { in, out := &in.InitContainer, &out.InitContainer *out = new(InitContainerSpec) diff --git a/build/run-backup.sh b/build/run-backup.sh index aed360ebd..c070fd5bb 100755 --- a/build/run-backup.sh +++ b/build/run-backup.sh @@ -18,8 +18,7 @@ request_data() { "endpointUrl": "$(json_escape "${AWS_ENDPOINT}")", "accessKey": "$(json_escape "${AWS_ACCESS_KEY_ID}")", "secretKey": "$(json_escape "${AWS_SECRET_ACCESS_KEY}")", - "region": "$(json_escape "${AWS_DEFAULT_REGION}")", - "storageClass": "$(json_escape "${S3_STORAGE_CLASS}")" + "region": "$(json_escape "${AWS_DEFAULT_REGION}")" } } EOF diff --git a/cmd/example-gen/internal/fill/bytype.go b/cmd/example-gen/internal/fill/bytype.go new file mode 100644 index 000000000..3b41bd84b --- /dev/null +++ b/cmd/example-gen/internal/fill/bytype.go @@ -0,0 +1,147 @@ +package fill + +import ( + "fmt" + "reflect" +) + +// ByType recursively fills zero or nil fields in the given pointer value `v` +// using provided preset values matched by type. It modifies `v` in place. +func ByType(v any, presets ...any) error { + rv := reflect.ValueOf(v) + if !rv.IsValid() { + return fmt.Errorf("nil value") + } + if rv.Kind() != reflect.Pointer || rv.IsNil() { + return fmt.Errorf("value must be a non-nil pointer") + } + fillValue(rv, buildRules(presets...)) + return nil +} + +type rules map[reflect.Type]reflect.Value + +func buildRules(presets ...any) rules { + r := make(rules, len(presets)) + for _, p := range presets { + if p == nil { + continue + } + v := reflect.ValueOf(p) + r[v.Type()] = v + } + return r +} + +func fillValue(v reflect.Value, r rules) { + for v.Kind() == reflect.Pointer { + if v.IsNil() { + if ok, def := lookup(v.Type(), r); ok { + v.Set(def) + } else { + return + } + } + v = v.Elem() + } + + switch v.Kind() { + case reflect.Struct: + t := v.Type() + for i := 0; i < v.NumField(); i++ { + sf := t.Field(i) + if sf.PkgPath != "" { // not exported + continue + } + fv := v.Field(i) + + setIfZero(fv, r) + + switch fv.Kind() { + case reflect.Pointer, reflect.Struct, reflect.Slice, reflect.Map, reflect.Interface: + fillValue(fv, r) + } + } + + case reflect.Slice: + for i := 0; i < v.Len(); i++ { + fillValue(v.Index(i), r) + } + + case reflect.Map: + iter := v.MapRange() + for iter.Next() { + k, val := iter.Key(), iter.Value() + + elem := reflect.New(v.Type().Elem()).Elem() + elem.Set(val) + + setIfZero(elem, r) + + switch elem.Kind() { + case reflect.Pointer, reflect.Struct, reflect.Slice, reflect.Map, reflect.Interface: + fillValue(elem, r) + } + v.SetMapIndex(k, elem) + } + + case reflect.Interface: + if !v.IsNil() { + cur := v.Elem() + tmp := reflect.New(cur.Type()).Elem() + tmp.Set(cur) + fillValue(tmp, r) + v.Set(tmp) + } + } +} + +func setIfZero(fv reflect.Value, r rules) { + need := false + switch fv.Kind() { + case reflect.Pointer, reflect.Map, reflect.Slice, reflect.Interface: + need = fv.IsNil() + default: + need = fv.IsZero() + } + if !need { + return + } + if ok, def := lookup(fv.Type(), r); ok { + fv.Set(def) + return + } +} + +func lookup(t reflect.Type, r rules) (bool, reflect.Value) { + if dv, ok := r[t]; ok { + if dv.Type().AssignableTo(t) { + return true, dv + } + if dv.Type().ConvertibleTo(t) { + return true, dv.Convert(t) + } + } + + if t.Kind() == reflect.Pointer { + elem := t.Elem() + if dv, ok := r[elem]; ok { + ptr := reflect.New(elem) + if dv.Type().AssignableTo(elem) { + ptr.Elem().Set(dv) + return true, ptr + } + if dv.Type().ConvertibleTo(elem) { + ptr.Elem().Set(dv.Convert(elem)) + return true, ptr + } + } + } + + if t.Kind() != reflect.Interface { + if dv, ok := r[reflect.PointerTo(t)]; ok && dv.Kind() == reflect.Pointer && !dv.IsNil() && dv.Type().Elem().AssignableTo(t) { + return true, dv.Elem() + } + } + return false, reflect.Value{} +} diff --git a/cmd/example-gen/internal/marshal/marshal.go b/cmd/example-gen/internal/marshal/marshal.go new file mode 100644 index 000000000..7bb670c34 --- /dev/null +++ b/cmd/example-gen/internal/marshal/marshal.go @@ -0,0 +1,274 @@ +package marshal + +import ( + "encoding/json" + "errors" + "fmt" + "maps" + "reflect" + "slices" + "strconv" + "strings" +) + +// MarshalIgnoreOmitEmpty marshals v to JSON ignoring `omitempty` tags. +// Types in passthrough are encoded with standard json.Marshal. +func MarshalIgnoreOmitEmpty(v any, passthrough ...any) ([]byte, error) { + rules := buildPassRules(passthrough...) + seen := make(map[uintptr]struct{}) + tree, err := marshalValue(reflect.ValueOf(v), rules, seen) + if err != nil { + return nil, err + } + return json.Marshal(tree) +} + +func marshalValue(rv reflect.Value, rules passRules, seen map[uintptr]struct{}) (any, error) { + if !rv.IsValid() { + return nil, nil + } + + if rules.isPassthrough(rv) { + b, err := json.Marshal(rv.Interface()) + if err != nil { + return nil, err + } + return json.RawMessage(b), nil + } + + switch rv.Kind() { + case reflect.Pointer: + if rv.IsNil() { + return nil, nil + } + ptr := rv.Pointer() + if _, ok := seen[ptr]; ok { + return nil, errors.New("cycle detected while marshaling struct") + } + seen[ptr] = struct{}{} + defer delete(seen, ptr) + return marshalValue(rv.Elem(), rules, seen) + case reflect.Interface: + if rv.IsNil() { + return nil, nil + } + return marshalValue(rv.Elem(), rules, seen) + } + + switch rv.Kind() { + case reflect.Bool: + return rv.Bool(), nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return rv.Int(), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return rv.Uint(), nil + case reflect.Float32, reflect.Float64: + return rv.Float(), nil + case reflect.String: + return rv.String(), nil + + case reflect.Slice, reflect.Array: + n := rv.Len() + out := make([]any, n) + for i := range n { + x, err := marshalValue(rv.Index(i), rules, seen) + if err != nil { + return nil, err + } + out[i] = x + } + return out, nil + + case reflect.Map: + if rv.Type().Key().Kind() != reflect.String { + return nil, fmt.Errorf("map key type %s is not supported by JSON (must be string)", rv.Type().Key()) + } + if rv.IsNil() { + return nil, nil + } + out := make(map[string]any, rv.Len()) + iter := rv.MapRange() + for iter.Next() { + k := iter.Key().String() + val, err := marshalValue(iter.Value(), rules, seen) + if err != nil { + return nil, err + } + out[k] = val + } + return out, nil + + case reflect.Struct: + return marshalStruct(rv, rules, seen) + + default: + b, err := json.Marshal(rv.Interface()) + if err != nil { + return nil, err + } + return json.RawMessage(b), nil + } +} + +func marshalStruct(rv reflect.Value, rules passRules, seen map[uintptr]struct{}) (any, error) { + t := rv.Type() + out := make(map[string]any, t.NumField()) + + for i := 0; i < t.NumField(); i++ { + sf := t.Field(i) + if sf.PkgPath != "" { // unexported + continue + } + + name, opts := parseJSONTag(sf.Tag.Get("json")) + if name == "-" { + continue + } + if name == "" { + name = sf.Name + } + + fv := rv.Field(i) + + if opts["inline"] { + v := derefAll(fv) + if !v.IsValid() { + continue + } + switch v.Kind() { + case reflect.Struct: + objAny, err := marshalStruct(v, rules, seen) + if err != nil { + return nil, err + } + if obj, ok := objAny.(map[string]any); ok { + maps.Copy(out, obj) + } + case reflect.Map: + if v.Type().Key().Kind() != reflect.String { + continue + } + objAny, err := marshalValue(v, rules, seen) + if err != nil { + return nil, err + } + if obj, ok := objAny.(map[string]any); ok { + maps.Copy(out, obj) + } + } + continue + } + + val, err := marshalValue(fv, rules, seen) + if err != nil { + return nil, err + } + + if opts["string"] { + switch v := val.(type) { + case int64, uint64, float64, bool, string, nil: + val = toJSONStringScalar(v) + case json.RawMessage: + val = json.RawMessage(strconv.AppendQuote(nil, string(v))) + } + } + + out[name] = val + } + + return out, nil +} + +func derefAll(v reflect.Value) reflect.Value { + for v.IsValid() && (v.Kind() == reflect.Pointer || v.Kind() == reflect.Interface) { + if v.IsNil() { + return reflect.Value{} + } + v = v.Elem() + } + return v +} + +func parseJSONTag(tag string) (name string, opts map[string]bool) { + opts = make(map[string]bool) + if tag == "" { + return "", opts + } + if i := strings.IndexByte(tag, ','); i >= 0 { + name = tag[:i] + for p := range strings.SplitSeq(tag[i+1:], ",") { + if p != "" { + opts[p] = true + } + } + return name, opts + } + return tag, opts +} + +func toJSONStringScalar(v any) string { + switch x := v.(type) { + case int64: + return strconv.FormatInt(x, 10) + case uint64: + return strconv.FormatUint(x, 10) + case float64: + b, _ := json.Marshal(x) + return string(b) + case bool: + if x { + return "true" + } + return "false" + case string: + return x + case nil: + return "null" + default: + b, _ := json.Marshal(x) + return string(b) + } +} + +type passRules struct { + exact map[reflect.Type]struct{} + ifaces []reflect.Type +} + +func (p passRules) isPassthrough(v reflect.Value) bool { + vt := v.Type() + if _, ok := p.exact[vt]; ok { + return true + } + return slices.ContainsFunc(p.ifaces, vt.Implements) +} + +func buildPassRules(passthrough ...any) passRules { + r := passRules{exact: make(map[reflect.Type]struct{})} + addType := func(t reflect.Type) { + if t == nil { + return + } + if t.Kind() == reflect.Interface { + r.ifaces = append(r.ifaces, t) + return + } + r.exact[t] = struct{}{} + if t.Kind() == reflect.Pointer { + r.exact[t.Elem()] = struct{}{} + } else { + r.exact[reflect.PointerTo(t)] = struct{}{} + } + } + for _, p := range passthrough { + if p == nil { + continue + } + if rt, ok := p.(reflect.Type); ok { + addType(rt) + continue + } + addType(reflect.TypeOf(p)) + } + return r +} diff --git a/cmd/example-gen/main.go b/cmd/example-gen/main.go new file mode 100644 index 000000000..70dba8dd7 --- /dev/null +++ b/cmd/example-gen/main.go @@ -0,0 +1,215 @@ +package main + +import ( + "context" + "fmt" + "os" + "os/signal" + "syscall" + + "github.com/pkg/errors" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "sigs.k8s.io/yaml" + + apiv1 "github.com/percona/percona-server-mysql-operator/api/v1" + "github.com/percona/percona-server-mysql-operator/cmd/example-gen/internal/marshal" + "github.com/percona/percona-server-mysql-operator/cmd/example-gen/pkg/defaults" +) + +func main() { + ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) + defer cancel() + + if len(os.Args) != 2 { + fmt.Println("Expected arguments are: `ps`, `ps-backup` or `ps-restore`") + os.Exit(1) + } + switch os.Args[1] { + case "ps": + if err := printCluster(ctx); err != nil { + panic(err) + } + case "ps-backup": + if err := printBackup(); err != nil { + panic(err) + } + case "ps-restore": + if err := printRestore(); err != nil { + panic(err) + } + default: + fmt.Println("Unexpected argument. Expected arguments are: `ps`, `ps-backup` or `ps-restore`") + os.Exit(1) + } +} + +func printCluster(ctx context.Context) error { + cr := &apiv1.PerconaServerMySQL{ + TypeMeta: metav1.TypeMeta{ + Kind: "PerconaServerMySQL", + APIVersion: "ps.percona.com/v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: defaults.NameCluster, + Finalizers: []string{ + "percona.com/delete-mysql-pods-in-order", + "percona.com/delete-ssl", + "percona.com/delete-mysql-pvc", + }, + }, + Spec: apiv1.PerconaServerMySQLSpec{ + Backup: &apiv1.BackupSpec{ + Image: defaults.ImageBackup, + }, + MySQL: apiv1.MySQLSpec{ + VolumeSpec: &apiv1.VolumeSpec{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, + }, + }, + Status: apiv1.PerconaServerMySQLStatus{}, + } + + if err := cr.CheckNSetDefaults(ctx, nil); err != nil { + return errors.Wrap(err, "check and set defaults") + } + defaults.ManualCluster(cr) + if err := defaults.FromPresets(cr); err != nil { + return errors.Wrap(err, "preset defaults") + } + + jsonBytes, err := marshal.MarshalIgnoreOmitEmpty(cr, + metav1.ObjectMeta{}, + corev1.ResourceRequirements{}, + corev1.SecurityContext{}, + corev1.Probe{}, + corev1.Affinity{}, + corev1.ServicePort{}, + corev1.TopologySpreadConstraint{}, + corev1.Toleration{}, + corev1.EnvVar{}, + corev1.EnvFromSource{}, + corev1.PodSecurityContext{}, + intstr.IntOrString{}, + corev1.EmptyDirVolumeSource{}, + corev1.HostPathVolumeSource{}, + corev1.PersistentVolumeClaimSpec{}, + corev1.Volume{}, + corev1.Container{}, + ) + if err != nil { + return errors.Wrap(err, "marshal") + } + b, err := yaml.JSONToYAML(jsonBytes) + if err != nil { + return errors.Wrap(err, "json to yaml") + } + + _, err = os.Stdout.Write(b) + return errors.Wrap(err, "write") +} + +func printBackup() error { + cr := &apiv1.PerconaServerMySQLBackup{ + TypeMeta: metav1.TypeMeta{ + Kind: "PerconaServerMySQLBackup", + APIVersion: "ps.percona.com/v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: defaults.NameBackup, + Finalizers: []string{ + "percona.com/delete-backup", + }, + }, + Spec: apiv1.PerconaServerMySQLBackupSpec{ + ClusterName: defaults.NameCluster, + StorageName: "minio", + SourcePod: defaults.SourcePod, + }, + } + + if err := defaults.FromPresets(cr); err != nil { + return errors.Wrap(err, "preset defaults") + } + jsonBytes, err := marshal.MarshalIgnoreOmitEmpty(cr, + corev1.EnvVar{}, + corev1.EnvFromSource{}, + metav1.ObjectMeta{}) + if err != nil { + return errors.Wrap(err, "marshal") + } + b, err := yaml.JSONToYAML(jsonBytes) + if err != nil { + return errors.Wrap(err, "json to yaml") + } + + _, err = os.Stdout.Write(b) + return errors.Wrap(err, "write") +} + +func printRestore() error { + cr := &apiv1.PerconaServerMySQLRestore{ + TypeMeta: metav1.TypeMeta{ + Kind: "PerconaServerMySQLRestore", + APIVersion: "ps.percona.com/v1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: defaults.NameRestore, + }, + Spec: apiv1.PerconaServerMySQLRestoreSpec{ + ClusterName: defaults.NameCluster, + BackupName: defaults.NameBackup, + BackupSource: &apiv1.PerconaServerMySQLBackupStatus{ + Destination: "s3://S3-BACKUP-BUCKET-NAME-HERE/backup-path", + Storage: &apiv1.BackupStorageSpec{ + Type: apiv1.BackupStorageS3, + S3: &apiv1.BackupStorageS3Spec{ + Bucket: "S3-BACKUP-BUCKET-NAME-HERE", + Prefix: "PREFIX_NAME", + CredentialsSecret: fmt.Sprintf("%s-s3-credentials", defaults.NameCluster), + Region: "us-west-2", + EndpointURL: "https://s3.amazonaws.com", + }, + Labels: defaults.Labels, + Annotations: defaults.Annotations, + SchedulerName: defaults.SchedulerName, + PriorityClassName: defaults.PriorityClassName, + NodeSelector: defaults.NodeSelector, + VerifyTLS: defaults.VerifyTLS, + RuntimeClassName: defaults.RuntimeClassName, + }, + }, + }, + } + + if err := defaults.FromPresets(cr); err != nil { + return errors.Wrap(err, "preset defaults") + } + jsonBytes, err := marshal.MarshalIgnoreOmitEmpty(cr, + corev1.EnvVar{}, + corev1.EnvFromSource{}, + metav1.ObjectMeta{}, + corev1.Affinity{}, + corev1.PodSecurityContext{}, + corev1.SecurityContext{}, + corev1.TopologySpreadConstraint{}, + corev1.Volume{}, + corev1.PersistentVolumeClaimSpec{}, + corev1.EmptyDirVolumeSource{}, + corev1.HostPathVolumeSource{}, + corev1.ResourceRequirements{}, + corev1.Toleration{}, + ) + if err != nil { + return errors.Wrap(err, "marshal") + } + b, err := yaml.JSONToYAML(jsonBytes) + if err != nil { + return errors.Wrap(err, "json to yaml") + } + + _, err = os.Stdout.Write(b) + return errors.Wrap(err, "write") +} diff --git a/cmd/example-gen/pkg/defaults/configs.go b/cmd/example-gen/pkg/defaults/configs.go new file mode 100644 index 000000000..04d14cd90 --- /dev/null +++ b/cmd/example-gen/pkg/defaults/configs.go @@ -0,0 +1,46 @@ +package defaults + +const ( + configurationHAProxy = `# the actual default configuration file can be found here https://github.com/percona/percona-server-mysql-operator/blob/main/build/haproxy-global.cfg + +global + maxconn 2048 + external-check + insecure-fork-wanted + stats socket /etc/haproxy/mysql/haproxy.sock mode 600 expose-fd listeners level admin + +defaults + default-server init-addr last,libc,none + log global + mode tcp + retries 10 + timeout client 28800s + timeout connect 100500 + timeout server 28800s + +frontend mysql-primary-in + bind *:3309 accept-proxy + bind *:3306 + mode tcp + option clitcpka + default_backend mysql-primary + +frontend mysql-replicas-in + bind *:3307 + mode tcp + option clitcpka + default_backend mysql-replicas + +frontend stats + bind *:8404 + mode http + http-request use-service prometheus-exporter if { path /metrics }` + + configurationMySQL = `max_connections=250 +innodb_buffer_pool_size={{containerMemoryLimit * 3/4}}` + + configurationRouter = `[default] +logging_folder=/tmp/router/log +[logger] +level=DEBUG` +) diff --git a/cmd/example-gen/pkg/defaults/manual.go b/cmd/example-gen/pkg/defaults/manual.go new file mode 100644 index 000000000..6bde25532 --- /dev/null +++ b/cmd/example-gen/pkg/defaults/manual.go @@ -0,0 +1,203 @@ +package defaults + +import ( + "fmt" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/utils/ptr" + + apiv1 "github.com/percona/percona-server-mysql-operator/api/v1" + "github.com/percona/percona-server-mysql-operator/pkg/version" +) + +// ManualCluster sets default values for empty fields in example cr.yaml +// that are not set by CheckNSetDefaults and cannot be set via PresetDefaults. +func ManualCluster(cr *apiv1.PerconaServerMySQL) { + cr.Spec.CRVersion = version.Version() + cr.Spec.VolumeExpansionEnabled = true + cr.Spec.UpdateStrategy = "SmartUpdate" + cr.Spec.InitContainer.Image = ImageInitContainer + cr.Spec.IgnoreAnnotations = []string{"service.beta.kubernetes.io/aws-load-balancer-backend-protocol"} + cr.Spec.IgnoreLabels = []string{"rack"} + + mysqlDefaults(&cr.Spec.MySQL) + haproxyDefaults(cr.Spec.Proxy.HAProxy) + routerDefaults(cr.Spec.Proxy.Router) + orchestratorDefaults(&cr.Spec.Orchestrator) + pmmDefaults(cr.Spec.PMM) + toolkitDefaults(cr.Spec.Toolkit) + backupDefaults(cr.Spec.Backup) +} + +func mysqlDefaults(spec *apiv1.MySQLSpec) { + podSpecDefaults(&spec.PodSpec, ImageMySQL, resources("2Gi", "", "4Gi", ""), configurationMySQL, 600, envList("BOOTSTRAP_READ_TIMEOUT", "600"), envFromList("mysql-env-secret")) + + spec.AutoRecovery = true + spec.VolumeSpec = nil + spec.ExposePrimary.Enabled = true + + c := func(name string) corev1.Container { + return corev1.Container{ + Name: name, + Image: "busybox", + Command: []string{"sleep", "30d"}, + VolumeMounts: []corev1.VolumeMount{ + { + Name: "memory-vol", + MountPath: "/var/log/app/memory", + }, + }, + LivenessProbe: &corev1.Probe{}, + ReadinessProbe: &corev1.Probe{}, + StartupProbe: &corev1.Probe{}, + Lifecycle: &corev1.Lifecycle{}, + SecurityContext: &corev1.SecurityContext{}, + Resources: resources("16M", "", "", ""), + } + } + spec.Sidecars = []corev1.Container{ + c("noop-memory"), + c("noop-pvc"), + } + spec.SidecarVolumes = []corev1.Volume{ + { + Name: "memory-vol", + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{ + Medium: corev1.StorageMediumMemory, + }, + }, + }, + } +} + +func haproxyDefaults(spec *apiv1.HAProxySpec) { + podSpecDefaults(&spec.PodSpec, ImageHAProxy, resources("1Gi", "600m", "1Gi", "700m"), configurationHAProxy, 30, envList("HA_CONNECTION_TIMEOUT", "600"), envFromList("haproxy-env-secret")) + + spec.Enabled = true +} + +func routerDefaults(spec *apiv1.MySQLRouterSpec) { + podSpecDefaults(&spec.PodSpec, ImageRouter, resources("256M", "", "256M", ""), configurationRouter, 30, envList("ROUTER_ENV", "VALUE"), envFromList("router-env-secret")) + + spec.Enabled = false + p := func(name string, port int32, targetPort int) corev1.ServicePort { + servicePort := corev1.ServicePort{Name: name, Port: port} + if targetPort != 0 { + servicePort.TargetPort = intstr.FromInt(targetPort) + } + return servicePort + } + spec.Ports = []corev1.ServicePort{ + p("http", 8443, 0), + p("rw-default", 3306, 6446), + p("read-write", 6446, 0), + p("read-only", 6447, 0), + p("x-read-write", 6448, 0), + p("x-read-only", 6449, 0), + p("x-default", 33060, 0), + p("rw-admin", 33062, 0), + p("custom-port", 1111, 6446), + } +} + +func orchestratorDefaults(spec *apiv1.OrchestratorSpec) { + podSpecDefaults(&spec.PodSpec, ImageOrchestrator, resources("128M", "", "256M", ""), "", 30, envList("ORC_ENV", "VALUE"), envFromList("orc-env-secret")) + + spec.Enabled = false + spec.ServiceAccountName = "percona-server-mysql-operator-orchestrator" + spec.PodSecurityContext = &corev1.PodSecurityContext{ + SupplementalGroups: []int64{1001}, + } +} + +func pmmDefaults(spec *apiv1.PMMSpec) { + spec.Image = ImagePMM + spec.Resources = resources("150M", "300m", "256M", "400m") + spec.ServerHost = "monitoring-service" + spec.MySQLParams = "PMM_ADMIN_CUSTOM_PARAMS" +} + +func backupDefaults(spec *apiv1.BackupSpec) { + spec.Image = ImageBackup + spec.Enabled = true + spec.SourcePod = SourcePod + spec.ServiceAccountName = "some-service-account" + spec.BackoffLimit = ptr.To(int32(6)) + spec.Schedule = []apiv1.BackupSchedule{ + { + Name: "sat-night-backup", + Schedule: "0 0 * * 6", + Keep: 3, + StorageName: "s3-us-west", + }, + { + Name: "daily-backup", + Schedule: "0 0 * * *", + Keep: 5, + StorageName: "s3", + }, + } + spec.Storages = map[string]*apiv1.BackupStorageSpec{ + "azure-blob": { + Type: apiv1.BackupStorageAzure, + Azure: &apiv1.BackupStorageAzureSpec{ + ContainerName: "CONTAINER-NAME", + Prefix: "PREFIX-NAME", + CredentialsSecret: "SECRET-NAME", + EndpointURL: "https://accountName.blob.core.windows.net", + StorageClass: "Cool", + }, + }, + "s3-us-west": { + Type: apiv1.BackupStorageS3, + S3: &apiv1.BackupStorageS3Spec{ + Bucket: "S3-BACKUP-BUCKET-NAME-HERE", + Prefix: "PREFIX_NAME", + CredentialsSecret: fmt.Sprintf("%s-s3-credentials", NameCluster), + Region: "us-west-2", + EndpointURL: "https://s3.amazonaws.com", + }, + Annotations: map[string]string{ + "testName": "scheduled-backup", + }, + Labels: map[string]string{ + "backupWorker": "True", + }, + PriorityClassName: PriorityClassName, + RuntimeClassName: RuntimeClassName, + SchedulerName: SchedulerName, + VerifyTLS: VerifyTLS, + NodeSelector: NodeSelector, + }, + } +} + +func toolkitDefaults(spec *apiv1.ToolkitSpec) { + spec.Image = ImageToolkit + spec.Resources = resources("150M", "100m", "256M", "400m") + spec.Env = envList("TOOLKIT_ENV", "VALUE") + spec.EnvFrom = envFromList("toolkit-env-secret") +} + +func podSpecDefaults(spec *apiv1.PodSpec, image string, resources corev1.ResourceRequirements, configuration string, gracePeriod int64, env []corev1.EnvVar, envFrom []corev1.EnvFromSource) { + spec.Image = image + spec.Resources = resources + spec.Configuration = configuration + spec.TerminationGracePeriodSeconds = ptr.To(gracePeriod) + spec.Env = env + spec.EnvFrom = envFrom + + spec.Size = 3 + + spec.RuntimeClassName = RuntimeClassName + spec.Labels = Labels + spec.Annotations = Annotations + spec.PriorityClassName = PriorityClassName + spec.SchedulerName = SchedulerName + spec.NodeSelector = NodeSelector + + spec.ServiceAccountName = "some-service-account" + spec.PodSecurityContext = nil +} diff --git a/cmd/example-gen/pkg/defaults/preset.go b/cmd/example-gen/pkg/defaults/preset.go new file mode 100644 index 000000000..5c832e7b7 --- /dev/null +++ b/cmd/example-gen/pkg/defaults/preset.go @@ -0,0 +1,202 @@ +package defaults + +import ( + cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/utils/ptr" + + apiv1 "github.com/percona/percona-server-mysql-operator/api/v1" + "github.com/percona/percona-server-mysql-operator/cmd/example-gen/internal/fill" +) + +// FromPresets assigns default values to fields in provided custom resource based on their types. +// The internal presets slice defines the default value associated with each type. +func FromPresets(cr any) error { + presets := []any{ + apiv1.Metadata{ + Labels: Labels, + Annotations: Annotations, + }, + corev1.SecurityContext{ + Privileged: ptr.To(false), + RunAsUser: ptr.To(int64(1001)), + RunAsGroup: ptr.To(int64(1001)), + }, + corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("100m"), + corev1.ResourceMemory: resource.MustParse("100M"), + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: resource.MustParse("200m"), + corev1.ResourceMemory: resource.MustParse("200M"), + }, + }, + apiv1.TLSSpec{ + SANs: []string{ + "mysql-1.example.com", + "mysql-2.example.com", + "mysql-3.example.com", + }, + IssuerConf: &cmmeta.ObjectReference{ + Name: "special-selfsigned-issuer", + Kind: "ClusterIssuer", + Group: "cert-manager.io", + }, + }, + apiv1.PodAffinity{ + TopologyKey: ptr.To("kubernetes.io/hostname"), + Advanced: &corev1.Affinity{ + NodeAffinity: &corev1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ + NodeSelectorTerms: []corev1.NodeSelectorTerm{ + { + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Key: "kubernetes.io/e2e-az-name", + Operator: "In", + Values: []string{ + "e2e-az1", + "e2e-az2", + }, + }, + }, + }, + }, + }, + }, + }, + }, + []corev1.TopologySpreadConstraint{ + { + MaxSkew: 1, + TopologyKey: "kubernetes.io/hostname", + WhenUnsatisfiable: corev1.DoNotSchedule, + LabelSelector: &metav1.LabelSelector{ + MatchLabels: map[string]string{ + "app.kubernetes.io/name": "percona-server", + }, + }, + }, + }, + apiv1.ServiceExpose{ + Type: corev1.ServiceTypeClusterIP, + LoadBalancerSourceRanges: []string{ + "10.0.0.0/8", + }, + Annotations: Annotations, + Labels: Labels, + InternalTrafficPolicy: ptr.To(corev1.ServiceInternalTrafficPolicyCluster), + ExternalTrafficPolicy: corev1.ServiceExternalTrafficPolicyCluster, + }, + apiv1.VolumeSpec{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + HostPath: &corev1.HostPathVolumeSource{ + Path: "/data", + Type: ptr.To(corev1.HostPathDirectory), + }, + PersistentVolumeClaim: &corev1.PersistentVolumeClaimSpec{ + StorageClassName: ptr.To("standard"), + AccessModes: []corev1.PersistentVolumeAccessMode{ + corev1.ReadWriteOnce, + }, + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("2Gi"), + }, + }, + }, + }, + corev1.Probe{ + TimeoutSeconds: 3, + PeriodSeconds: 5, + SuccessThreshold: 1, + FailureThreshold: 3, + }, + apiv1.PodDisruptionBudgetSpec{ + MinAvailable: ptr.To(intstr.FromInt(0)), + MaxUnavailable: ptr.To(intstr.FromInt(1)), + }, + corev1.PodSecurityContext{ + FSGroup: ptr.To(int64(1001)), + SupplementalGroups: []int64{1001, 1002, 1003}, + }, + apiv1.UpgradeOptions{ + VersionServiceEndpoint: "https://check.percona.com", + Apply: "disabled", + }, + []corev1.Toleration{ + { + Key: "node.alpha.kubernetes.io/unreachable", + Operator: "Exists", + Effect: "NoExecute", + TolerationSeconds: ptr.To(int64(6000)), + }, + }, + []corev1.LocalObjectReference{ + {Name: "my-secret-1"}, + {Name: "my-secret-2"}, + }, + corev1.PullAlways, + apiv1.InitContainerSpec{ + Image: ImageInitContainer, + }, + []apiv1.SidecarPVC{ + { + Name: "pvc-vol", + Spec: corev1.PersistentVolumeClaimSpec{ + Resources: corev1.VolumeResourceRequirements{ + Requests: corev1.ResourceList{ + corev1.ResourceStorage: resource.MustParse("1Gi"), + }, + }, + }, + }, + }, + + corev1.Affinity{ + NodeAffinity: &corev1.NodeAffinity{ + RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{ + NodeSelectorTerms: []corev1.NodeSelectorTerm{ + { + MatchExpressions: []corev1.NodeSelectorRequirement{ + { + Key: "kubernetes.io/e2e-az-name", + Operator: "In", + Values: []string{ + "e2e-az1", + "e2e-az2", + }, + }, + }, + }, + }, + }, + }, + }, + apiv1.BackupContainerOptions{ + Env: []corev1.EnvVar{ + { + Name: "CUSTOM_VAR", + Value: "false", + }, + }, + Args: apiv1.BackupContainerArgs{ + Xtrabackup: []string{ + "--someflag=abc", + }, + Xbcloud: []string{ + "--someflag=abc", + }, + Xbstream: []string{ + "--someflag=abc", + }, + }, + }, + } + + return fill.ByType(cr, presets...) +} diff --git a/cmd/example-gen/pkg/defaults/util.go b/cmd/example-gen/pkg/defaults/util.go new file mode 100644 index 000000000..8fe6e073b --- /dev/null +++ b/cmd/example-gen/pkg/defaults/util.go @@ -0,0 +1,58 @@ +package defaults + +import ( + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" +) + +func resources(requestsMemory, requestsCPU, limitsMemory, limitsCPU string) corev1.ResourceRequirements { + r := corev1.ResourceRequirements{} + + if requestsMemory != "" { + if r.Requests == nil { + r.Requests = make(corev1.ResourceList) + } + r.Requests[corev1.ResourceMemory] = resource.MustParse(requestsMemory) + } + if requestsCPU != "" { + if r.Requests == nil { + r.Requests = make(corev1.ResourceList) + } + r.Requests[corev1.ResourceCPU] = resource.MustParse(requestsCPU) + } + if limitsMemory != "" { + if r.Limits == nil { + r.Limits = make(corev1.ResourceList) + } + r.Limits[corev1.ResourceMemory] = resource.MustParse(limitsMemory) + } + if limitsCPU != "" { + if r.Limits == nil { + r.Limits = make(corev1.ResourceList) + } + r.Limits[corev1.ResourceCPU] = resource.MustParse(limitsCPU) + } + + return r +} + +func envList(name, value string) []corev1.EnvVar { + return []corev1.EnvVar{ + { + Name: name, + Value: value, + }, + } +} + +func envFromList(name string) []corev1.EnvFromSource { + return []corev1.EnvFromSource{ + { + SecretRef: &corev1.SecretEnvSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: name, + }, + }, + }, + } +} diff --git a/cmd/example-gen/pkg/defaults/values.go b/cmd/example-gen/pkg/defaults/values.go new file mode 100644 index 000000000..1160c836e --- /dev/null +++ b/cmd/example-gen/pkg/defaults/values.go @@ -0,0 +1,44 @@ +package defaults + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/utils/ptr" + + apiv1 "github.com/percona/percona-server-mysql-operator/api/v1" + "github.com/percona/percona-server-mysql-operator/pkg/mysql" +) + +const ( + ImageInitContainer = "perconalab/percona-server-mysql-operator:main" + ImageMySQL = "perconalab/percona-server-mysql-operator:main-psmysql8.4" + ImageHAProxy = "perconalab/percona-server-mysql-operator:main-haproxy" + ImageRouter = "perconalab/percona-server-mysql-operator:main-router8.4" + ImageOrchestrator = "perconalab/percona-server-mysql-operator:main-orchestrator" + ImagePMM = "perconalab/pmm-client:3-dev-latest" + ImageBackup = "perconalab/percona-server-mysql-operator:main-backup8.4" + ImageToolkit = "perconalab/percona-server-mysql-operator:main-toolkit" +) + +const ( + NameCluster = "ps-cluster1" + NameBackup = "backup1" + NameRestore = "restore1" +) + +var ( + Labels = map[string]string{ + "rack": "rack-22", + } + Annotations = map[string]string{ + "service.beta.kubernetes.io/aws-load-balancer-backend-protocol": "tcp", + "service.beta.kubernetes.io/aws-load-balancer-type": "nlb", + } + NodeSelector = map[string]string{ + "topology.kubernetes.io/zone": "us-east-1a", + } + VerifyTLS = ptr.To(true) + RuntimeClassName = ptr.To("image-rc") + SchedulerName = "default-scheduler" + PriorityClassName = "high-priority" + SourcePod = mysql.PodName(&apiv1.PerconaServerMySQL{ObjectMeta: metav1.ObjectMeta{Name: NameCluster}}, 1) +) diff --git a/cmd/example-gen/scripts/generate.sh b/cmd/example-gen/scripts/generate.sh new file mode 100755 index 000000000..4850e60bb --- /dev/null +++ b/cmd/example-gen/scripts/generate.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash + +resource=${1:-} + +SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")" + +case "$resource" in + ps) + # shellcheck source=cmd/example-gen/scripts/lib/ps.sh + . "$SCRIPT_DIR/lib/ps.sh" + ;; + ps-backup) + # shellcheck source=cmd/example-gen/scripts/lib/ps-backup.sh + . "$SCRIPT_DIR/lib/ps-backup.sh" + ;; + ps-restore) + # shellcheck source=cmd/example-gen/scripts/lib/ps-restore.sh + . "$SCRIPT_DIR/lib/ps-restore.sh" + ;; + *) + echo "Usage: $0 {ps|ps-backup|ps-restore}" >&2 + exit 2 + ;; +esac + +go run cmd/example-gen/main.go "$resource" \ + | sort_yaml \ + | remove_fields \ + | comment_fields \ + >"$RESOURCE_PATH" diff --git a/cmd/example-gen/scripts/lib/ps-backup.sh b/cmd/example-gen/scripts/lib/ps-backup.sh new file mode 100644 index 000000000..129b7d1f2 --- /dev/null +++ b/cmd/example-gen/scripts/lib/ps-backup.sh @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +# shellcheck source=cmd/example-gen/scripts/lib/util.sh +. "$SCRIPT_DIR/lib/util.sh" + +export RESOURCE_PATH="deploy/backup/backup.yaml" + +sort_yaml() { + SPEC_ORDER='"clusterName", "storageName", "sourcePod", "containerOptions"' + CONTAINER_OPTS_ORDER='"env", "args"' + + yq - \ + | yq '.spec |= pick((['"$SPEC_ORDER"'] + keys) | unique)' \ + | yq '.spec.containerOptions |= pick((['"$CONTAINER_OPTS_ORDER"'] + keys) | unique)' +} + +remove_fields() { + yq - \ + | yq "del(.status)" +} + +del_fields_to_comment() { + yq - \ + | yq "del(.spec.containerOptions)" \ + | yq "del(.spec.sourcePod)" +} diff --git a/cmd/example-gen/scripts/lib/ps-restore.sh b/cmd/example-gen/scripts/lib/ps-restore.sh new file mode 100644 index 000000000..cf7ef2a54 --- /dev/null +++ b/cmd/example-gen/scripts/lib/ps-restore.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash + +# shellcheck source=cmd/example-gen/scripts/lib/util.sh +. "$SCRIPT_DIR/lib/util.sh" + +export RESOURCE_PATH="deploy/backup/restore.yaml" + +sort_yaml() { + SPEC_ORDER='"clusterName", "backupName", "containerOptions", "backupSource"' + CONTAINER_OPTS_ORDER='"env", "args"' + + yq - \ + | yq '.spec |= pick((['"$SPEC_ORDER"'] + keys) | unique)' \ + | yq '.spec.containerOptions |= pick((['"$CONTAINER_OPTS_ORDER"'] + keys) | unique)' +} + +remove_fields() { + yq - \ + | yq "del(.status)" \ + | yq "del(.spec.backupSource.backupSource)" \ + | yq "del(.spec.backupSource.completed)" \ + | yq "del(.spec.backupSource.image)" \ + | yq "del(.spec.backupSource.state)" \ + | yq "del(.spec.backupSource.stateDescription)" \ + | yq "del(.spec.backupSource.storage.azure)" \ + | yq "del(.spec.backupSource.storage.gcs)" +} + +del_fields_to_comment() { + yq - \ + | yq "del(.spec.containerOptions)" \ + | yq "del(.spec.backupSource)" +} diff --git a/cmd/example-gen/scripts/lib/ps.sh b/cmd/example-gen/scripts/lib/ps.sh new file mode 100644 index 000000000..1f0243ef9 --- /dev/null +++ b/cmd/example-gen/scripts/lib/ps.sh @@ -0,0 +1,213 @@ +#!/usr/bin/env bash + +# shellcheck source=cmd/example-gen/scripts/lib/util.sh +. "$SCRIPT_DIR/lib/util.sh" + +export RESOURCE_PATH="deploy/cr.yaml" + +sort_yaml() { + GENERAL_ORDER='"metadata", "unsafeFlags", "pause", "crVersion", "enableVolumeExpansion", "secretsName", "sslSecretName", "updateStrategy", "upgradeOptions", "initContainer", "ignoreAnnotations", "ignoreLabels", "tls", "mysql", "proxy", "orchestrator", "pmm", "backup", "toolkit"' + + POD_SPEC_ORDER='"size", "image", "imagePullPolicy","imagePullSecrets", "runtimeClassName", "tolerations", "annotations", "labels", "nodeSelector", "priorityClassName", "schedulerName", "serviceAccountName","gracePeriod", "initContainer", "env", "envFrom", "podDisruptionBudget", "resources","startupProbe", "readinessProbe", "livenessProbe", "affinity", "topologySpreadConstraints", "containerSecurityContext", "podSecurityContext"' + MYSQL_ORDER='"clusterType", "autoRecovery", "vaultSecretName", '"$POD_SPEC_ORDER"',"exposePrimary", "expose", "volumeSpec", "configuration", "sidecars", "sidecarVolumes", "sidecarPVCs"' + HAPROXY_ORDER='"enabled", "expose", '"$POD_SPEC_ORDER" + ROUTER_ORDER='"enabled", "expose", '"$POD_SPEC_ORDER"', "ports"' + ORCHESTRATOR_ORDER='"enabled", "expose", '"$POD_SPEC_ORDER" + + PMM_ORDER='"enabled","image","imagePullPolicy","serverHost","mysqlParams","containerSecurityContext", "resources", "readinessProbes", "livenessProbes"' + BACKUP_ORDER='"enabled","pitr","sourcePod","image","imagePullPolicy","imagePullSecrets","schedule","backoffLimit", "serviceAccountName", "initContainer", "containerSecurityContext", "resources","storages","pitr"' + TOOLKIT_ORDER='"image","imagePullPolicy","imagePullSecrets","env","envFrom","resources","containerSecurityContext", "startupProbe", "readinessProbe", "livenessProbe"' + + yq - \ + | yq '.spec |= pick((['"$GENERAL_ORDER"'] + keys) | unique)' \ + | yq '.spec.mysql |= pick((['"$MYSQL_ORDER"'] + keys) | unique)' \ + | yq '.spec.proxy.haproxy |= pick((['"$HAPROXY_ORDER"'] + keys) | unique)' \ + | yq '.spec.proxy.router |= pick((['"$ROUTER_ORDER"'] + keys) | unique)' \ + | yq '.spec.orchestrator |= pick((['"$ORCHESTRATOR_ORDER"'] + keys) | unique)' \ + | yq '.spec.pmm |= pick((['"$PMM_ORDER"'] + keys) | unique)' \ + | yq '.spec.backup |= pick((['"$BACKUP_ORDER"'] + keys) | unique)' \ + | yq '.spec.toolkit |= pick((['"$TOOLKIT_ORDER"'] + keys) | unique)' +} + +remove_fields() { + # - removing initImage as it is deprecated + # - removing binlogServer is not used + # - removing azure-blob fields to reduce size + # - removing non-s3 fields in s3-us-west + yq - \ + | yq 'del(.status)' \ + | yq 'del(.spec.backup.initImage)' \ + | yq 'del(.spec.initImage)' \ + | yq 'del(.spec.mysql.initImage)' \ + | yq 'del(.spec.orchestrator.initImage)' \ + | yq 'del(.spec.proxy.haproxy.initImage)' \ + | yq 'del(.spec.proxy.router.initImage)' \ + | yq 'del(.spec.backup.pitr.binlogServer)' \ + | yq 'del(.spec.backup.storages.azure-blob.affinity)' \ + | yq 'del(.spec.backup.storages.azure-blob.annotations)' \ + | yq 'del(.spec.backup.storages.azure-blob.gcs)' \ + | yq 'del(.spec.backup.storages.azure-blob.labels)' \ + | yq 'del(.spec.backup.storages.azure-blob.nodeSelector)' \ + | yq 'del(.spec.backup.storages.azure-blob.priorityClassName)' \ + | yq 'del(.spec.backup.storages.azure-blob.runtimeClassName)' \ + | yq 'del(.spec.backup.storages.azure-blob.s3)' \ + | yq 'del(.spec.backup.storages.azure-blob.schedulerName)' \ + | yq 'del(.spec.backup.storages.azure-blob.volumeSpec)' \ + | yq 'del(.spec.backup.storages.s3-us-west.azure)' \ + | yq 'del(.spec.backup.storages.s3-us-west.gcs)' +} + +del_fields_to_comment() { + yq - \ + | yq "del(.metadata.finalizers[1])" \ + | yq "del(.metadata.finalizers[1])" \ + | yq "del(.spec.metadata)" \ + | yq "del(.spec.unsafeFlags)" \ + | yq "del(.spec.pause)" \ + | yq "del(.spec.enableVolumeExpansion)" \ + | yq "del(.spec.initContainer)" \ + | yq "del(.spec.ignoreAnnotations)" \ + | yq "del(.spec.ignoreLabels)" \ + | yq "del(.spec.tls)" \ + | yq "del(.spec.mysql.runtimeClassName)" \ + | yq "del(.spec.mysql.tolerations)" \ + | yq "del(.spec.mysql.annotations)" \ + | yq "del(.spec.mysql.labels)" \ + | yq "del(.spec.mysql.nodeSelector)" \ + | yq "del(.spec.mysql.priorityClassName)" \ + | yq "del(.spec.mysql.schedulerName)" \ + | yq "del(.spec.mysql.serviceAccountName)" \ + | yq "del(.spec.mysql.imagePullSecrets)" \ + | yq "del(.spec.mysql.initContainer)" \ + | yq "del(.spec.mysql.vaultSecretName)" \ + | yq "del(.spec.mysql.env)" \ + | yq "del(.spec.mysql.envFrom)" \ + | yq "del(.spec.mysql.podDisruptionBudget.minAvailable)" \ + | yq "del(.spec.mysql.startupProbe)" \ + | yq "del(.spec.mysql.readinessProbe)" \ + | yq "del(.spec.mysql.livenessProbe)" \ + | yq "del(.spec.mysql.affinity.advanced)" \ + | yq "del(.spec.mysql.topologySpreadConstraints)" \ + | yq "del(.spec.mysql.expose)" \ + | yq "del(.spec.mysql.exposePrimary.annotations)" \ + | yq "del(.spec.mysql.exposePrimary.labels)" \ + | yq "del(.spec.mysql.exposePrimary.loadBalancerSourceRanges)" \ + | yq "del(.spec.mysql.exposePrimary.type)" \ + | yq "del(.spec.mysql.exposePrimary.internalTrafficPolicy)" \ + | yq "del(.spec.mysql.exposePrimary.externalTrafficPolicy)" \ + | yq "del(.spec.mysql.containerSecurityContext)" \ + | yq "del(.spec.mysql.podSecurityContext)" \ + | yq "del(.spec.mysql.configuration)" \ + | yq "del(.spec.mysql.sidecars)" \ + | yq "del(.spec.mysql.sidecarVolumes)" \ + | yq "del(.spec.mysql.sidecarPVCs)" \ + | yq "del(.spec.mysql.volumeSpec.emptyDir)" \ + | yq "del(.spec.mysql.volumeSpec.hostPath)" \ + | yq "del(.spec.mysql.volumeSpec.persistentVolumeClaim.storageClassName)" \ + | yq "del(.spec.mysql.volumeSpec.persistentVolumeClaim.accessModes)" \ + | yq "del(.spec.proxy.haproxy.runtimeClassName)" \ + | yq "del(.spec.proxy.haproxy.tolerations)" \ + | yq "del(.spec.proxy.haproxy.annotations)" \ + | yq "del(.spec.proxy.haproxy.labels)" \ + | yq "del(.spec.proxy.haproxy.nodeSelector)" \ + | yq "del(.spec.proxy.haproxy.priorityClassName)" \ + | yq "del(.spec.proxy.haproxy.schedulerName)" \ + | yq "del(.spec.proxy.haproxy.serviceAccountName)" \ + | yq "del(.spec.proxy.haproxy.imagePullSecrets)" \ + | yq "del(.spec.proxy.haproxy.podDisruptionBudget.minAvailable)" \ + | yq "del(.spec.proxy.haproxy.resources.limits)" \ + | yq "del(.spec.proxy.haproxy.env)" \ + | yq "del(.spec.proxy.haproxy.envFrom)" \ + | yq "del(.spec.proxy.haproxy.startupProbe)" \ + | yq "del(.spec.proxy.haproxy.readinessProbe)" \ + | yq "del(.spec.proxy.haproxy.livenessProbe)" \ + | yq "del(.spec.proxy.haproxy.affinity.advanced)" \ + | yq "del(.spec.proxy.haproxy.expose)" \ + | yq "del(.spec.proxy.haproxy.topologySpreadConstraints)" \ + | yq "del(.spec.proxy.haproxy.initContainer)" \ + | yq "del(.spec.proxy.haproxy.containerSecurityContext)" \ + | yq "del(.spec.proxy.haproxy.podSecurityContext)" \ + | yq "del(.spec.proxy.haproxy.configuration)" \ + | yq "del(.spec.proxy.router.runtimeClassName)" \ + | yq "del(.spec.proxy.router.tolerations)" \ + | yq "del(.spec.proxy.router.annotations)" \ + | yq "del(.spec.proxy.router.labels)" \ + | yq "del(.spec.proxy.router.nodeSelector)" \ + | yq "del(.spec.proxy.router.priorityClassName)" \ + | yq "del(.spec.proxy.router.schedulerName)" \ + | yq "del(.spec.proxy.router.serviceAccountName)" \ + | yq "del(.spec.proxy.router.imagePullSecrets)" \ + | yq "del(.spec.proxy.router.podDisruptionBudget.minAvailable)" \ + | yq "del(.spec.proxy.router.env)" \ + | yq "del(.spec.proxy.router.envFrom)" \ + | yq "del(.spec.proxy.router.startupProbe)" \ + | yq "del(.spec.proxy.router.readinessProbe)" \ + | yq "del(.spec.proxy.router.livenessProbe)" \ + | yq "del(.spec.proxy.router.affinity.advanced)" \ + | yq "del(.spec.proxy.router.expose)" \ + | yq "del(.spec.proxy.router.topologySpreadConstraints)" \ + | yq "del(.spec.proxy.router.initContainer)" \ + | yq "del(.spec.proxy.router.containerSecurityContext)" \ + | yq "del(.spec.proxy.router.podSecurityContext)" \ + | yq "del(.spec.proxy.router.configuration)" \ + | yq "del(.spec.proxy.router.ports)" \ + | yq "del(.spec.orchestrator.runtimeClassName)" \ + | yq "del(.spec.orchestrator.tolerations)" \ + | yq "del(.spec.orchestrator.annotations)" \ + | yq "del(.spec.orchestrator.labels)" \ + | yq "del(.spec.orchestrator.nodeSelector)" \ + | yq "del(.spec.orchestrator.priorityClassName)" \ + | yq "del(.spec.orchestrator.schedulerName)" \ + | yq "del(.spec.orchestrator.serviceAccountName)" \ + | yq "del(.spec.orchestrator.imagePullSecrets)" \ + | yq "del(.spec.orchestrator.podDisruptionBudget.minAvailable)" \ + | yq "del(.spec.orchestrator.env)" \ + | yq "del(.spec.orchestrator.envFrom)" \ + | yq "del(.spec.orchestrator.startupProbe)" \ + | yq "del(.spec.orchestrator.readinessProbe)" \ + | yq "del(.spec.orchestrator.livenessProbe)" \ + | yq "del(.spec.orchestrator.affinity.advanced)" \ + | yq "del(.spec.orchestrator.expose)" \ + | yq "del(.spec.orchestrator.topologySpreadConstraints)" \ + | yq "del(.spec.orchestrator.initContainer)" \ + | yq "del(.spec.orchestrator.containerSecurityContext)" \ + | yq "del(.spec.orchestrator.podSecurityContext)" \ + | yq "del(.spec.pmm.mysqlParams)" \ + | yq "del(.spec.pmm.readinessProbes)" \ + | yq "del(.spec.pmm.livenessProbes)" \ + | yq "del(.spec.pmm.containerSecurityContext)" \ + | yq "del(.spec.pmm.resources.limits)" \ + | yq "del(.spec.backup.sourcePod)" \ + | yq "del(.spec.backup.schedule)" \ + | yq "del(.spec.backup.backoffLimit)" \ + | yq "del(.spec.backup.imagePullSecrets)" \ + | yq "del(.spec.backup.initContainer)" \ + | yq "del(.spec.backup.containerSecurityContext)" \ + | yq "del(.spec.backup.resources)" \ + | yq "del(.spec.backup.serviceAccountName)" \ + | yq "del(.spec.backup.storages.azure-blob)" \ + | yq "del(.spec.backup.storages.s3-us-west.resources)" \ + | yq "del(.spec.backup.storages.s3-us-west.topologySpreadConstraints)" \ + | yq "del(.spec.backup.storages.s3-us-west.tolerations)" \ + | yq "del(.spec.backup.storages.s3-us-west.containerSecurityContext)" \ + | yq "del(.spec.backup.storages.s3-us-west.labels)" \ + | yq "del(.spec.backup.storages.s3-us-west.nodeSelector)" \ + | yq "del(.spec.backup.storages.s3-us-west.podSecurityContext)" \ + | yq "del(.spec.backup.storages.s3-us-west.priorityClassName)" \ + | yq "del(.spec.backup.storages.s3-us-west.annotations)" \ + | yq "del(.spec.backup.storages.s3-us-west.containerOptions)" \ + | yq "del(.spec.backup.storages.s3-us-west.volumeSpec)" \ + | yq "del(.spec.backup.storages.s3-us-west.affinity)" \ + | yq "del(.spec.backup.storages.s3-us-west.s3.prefix)" \ + | yq "del(.spec.backup.storages.s3-us-west.s3.endpointUrl)" \ + | yq "del(.spec.backup.storages.s3-us-west.schedulerName)" \ + | yq "del(.spec.backup.storages.s3-us-west.runtimeClassName)" \ + | yq "del(.spec.toolkit.imagePullSecrets)" \ + | yq "del(.spec.toolkit.env)" \ + | yq "del(.spec.toolkit.envFrom)" \ + | yq "del(.spec.toolkit.resources)" \ + | yq "del(.spec.toolkit.containerSecurityContext)" \ + | yq "del(.spec.toolkit.startupProbe)" \ + | yq "del(.spec.toolkit.readinessProbe)" \ + | yq "del(.spec.toolkit.livenessProbe)" +} diff --git a/cmd/example-gen/scripts/lib/util.sh b/cmd/example-gen/scripts/lib/util.sh new file mode 100644 index 000000000..3821eb702 --- /dev/null +++ b/cmd/example-gen/scripts/lib/util.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash + +comment_fields() { + local tmp_old tmp_new tmp_diff tmp_out + + tmp_old=$(mktemp) + tmp_new=$(mktemp) + tmp_diff=$(mktemp) + tmp_out=$(mktemp) + + yq - >"$tmp_old" + del_fields_to_comment <"$tmp_old" >"$tmp_new" + + diff "$tmp_old" "$tmp_new" >"$tmp_diff" + + # convert delete-only hunks into change hunks with identical new-range, + # and duplicate "< ..." lines as "> # ..." + awk ' +/^[0-9]+(,[0-9]+)?[acd][0-9]+(,[0-9]+)?$/ { + if (inblock) process() + hdr = $0; inblock = 1; n = 0 + next +} +inblock { block[++n] = $0; next } +{ print } + +END { if (inblock) process() } + +function process(i, ln, has_lt, has_gt, has_sep, pos, ch, left) { + has_lt = has_gt = has_sep = 0 + for (i = 1; i <= n; i++) { + ln = block[i] + if (ln ~ /^/) has_gt = 1 + else if (ln ~ /^---$/) has_sep = 1 + } + + if (has_lt && !has_gt) { + # if header was a delete, make it a change with identical new-range + pos = 0 + for (i = 1; i <= length(hdr); i++) { ch = substr(hdr, i, 1); if (ch=="a"||ch=="c"||ch=="d"){ pos = i; break } } + if (pos && substr(hdr, pos, 1) == "d") { + left = substr(hdr, 1, pos-1) + hdr = left "c" left + } else if (match(hdr, /[acd]/)) { + pos = RSTART + if (substr(hdr, pos, 1) != "c") hdr = substr(hdr,1,pos-1) "c" substr(hdr,pos+1) + } + + print hdr + for (i = 1; i <= n; i++) print block[i] + if (!has_sep) print "---" + for (i = 1; i <= n; i++) { + ln = block[i] + if (ln ~ /^ #" ln } + } + } else { + print hdr + for (i = 1; i <= n; i++) print block[i] + } + inblock = 0; n = 0 +}' "$tmp_diff" >"$tmp_out" + + mv "$tmp_out" "$tmp_diff" + + patch -s -i "$tmp_diff" "$tmp_old" + + cat "$tmp_old" +} diff --git a/config/crd/bases/ps.percona.com_perconaservermysqlbackups.yaml b/config/crd/bases/ps.percona.com_perconaservermysqlbackups.yaml index 6b7c3e3ad..d66dd5f6c 100644 --- a/config/crd/bases/ps.percona.com_perconaservermysqlbackups.yaml +++ b/config/crd/bases/ps.percona.com_perconaservermysqlbackups.yaml @@ -957,8 +957,6 @@ spec: type: string region: type: string - storageClass: - type: string required: - bucket - credentialsSecret diff --git a/config/crd/bases/ps.percona.com_perconaservermysqlrestores.yaml b/config/crd/bases/ps.percona.com_perconaservermysqlrestores.yaml index 42d5dd914..6ea227042 100644 --- a/config/crd/bases/ps.percona.com_perconaservermysqlrestores.yaml +++ b/config/crd/bases/ps.percona.com_perconaservermysqlrestores.yaml @@ -838,8 +838,6 @@ spec: type: string region: type: string - storageClass: - type: string required: - bucket - credentialsSecret diff --git a/config/crd/bases/ps.percona.com_perconaservermysqls.yaml b/config/crd/bases/ps.percona.com_perconaservermysqls.yaml index 78795acae..cb002f376 100644 --- a/config/crd/bases/ps.percona.com_perconaservermysqls.yaml +++ b/config/crd/bases/ps.percona.com_perconaservermysqls.yaml @@ -1432,8 +1432,6 @@ spec: type: string region: type: string - storageClass: - type: string required: - bucket - credentialsSecret @@ -1509,117 +1507,6 @@ spec: - whenUnsatisfiable type: object type: array - volumeSpec: - properties: - emptyDir: - properties: - medium: - type: string - sizeLimit: - 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 - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - persistentVolumeClaim: - properties: - accessModes: - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object - type: object writeTimeout: format: int32 type: integer @@ -2477,8 +2364,6 @@ spec: type: string region: type: string - storageClass: - type: string required: - bucket - credentialsSecret @@ -7056,117 +6941,6 @@ spec: - whenUnsatisfiable type: object type: array - volumeSpec: - properties: - emptyDir: - properties: - medium: - type: string - sizeLimit: - 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 - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - persistentVolumeClaim: - properties: - accessModes: - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object - type: object required: - image - size @@ -8697,117 +8471,6 @@ spec: - whenUnsatisfiable type: object type: array - volumeSpec: - properties: - emptyDir: - properties: - medium: - type: string - sizeLimit: - 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 - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - persistentVolumeClaim: - properties: - accessModes: - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object - type: object required: - image - size @@ -10077,117 +9740,6 @@ spec: - whenUnsatisfiable type: object type: array - volumeSpec: - properties: - emptyDir: - properties: - medium: - type: string - sizeLimit: - 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 - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - persistentVolumeClaim: - properties: - accessModes: - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object - type: object required: - image - size diff --git a/deploy/backup/backup.yaml b/deploy/backup/backup.yaml index 4fab3c5ac..3917f6b9f 100644 --- a/deploy/backup/backup.yaml +++ b/deploy/backup/backup.yaml @@ -1,21 +1,21 @@ apiVersion: ps.percona.com/v1 kind: PerconaServerMySQLBackup metadata: - name: backup1 finalizers: - percona.com/delete-backup + name: backup1 spec: clusterName: ps-cluster1 storageName: minio # sourcePod: ps-cluster1-mysql-1 # containerOptions: # env: -# - name: CUSTOM_VAR -# value: "false" +# - name: CUSTOM_VAR +# value: "false" # args: -# xtrabackup: -# - "--someflag=abc" # xbcloud: -# - "--someflag=abc" +# - --someflag=abc # xbstream: -# - "--someflag=abc" +# - --someflag=abc +# xtrabackup: +# - --someflag=abc diff --git a/deploy/backup/restore.yaml b/deploy/backup/restore.yaml index b8f7cd204..6790fa2ad 100644 --- a/deploy/backup/restore.yaml +++ b/deploy/backup/restore.yaml @@ -7,20 +7,95 @@ spec: backupName: backup1 # containerOptions: # env: -# - name: CUSTOM_VAR -# value: "false" +# - name: CUSTOM_VAR +# value: "false" # args: -# xtrabackup: -# - "--someflag=abc" # xbcloud: -# - "--someflag=abc" +# - --someflag=abc # xbstream: -# - "--someflag=abc" +# - --someflag=abc +# xtrabackup: +# - --someflag=abc # backupSource: # destination: s3://S3-BACKUP-BUCKET-NAME-HERE/backup-path # storage: +# affinity: +# nodeAffinity: +# requiredDuringSchedulingIgnoredDuringExecution: +# nodeSelectorTerms: +# - matchExpressions: +# - key: kubernetes.io/e2e-az-name +# operator: In +# values: +# - e2e-az1 +# - e2e-az2 +# annotations: +# service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp +# service.beta.kubernetes.io/aws-load-balancer-type: nlb +# containerOptions: +# args: +# xbcloud: +# - --someflag=abc +# xbstream: +# - --someflag=abc +# xtrabackup: +# - --someflag=abc +# env: +# - name: CUSTOM_VAR +# value: "false" +# containerSecurityContext: +# privileged: false +# runAsGroup: 1001 +# runAsUser: 1001 +# labels: +# rack: rack-22 +# nodeSelector: +# topology.kubernetes.io/zone: us-east-1a +# podSecurityContext: +# fsGroup: 1001 +# supplementalGroups: +# - 1001 +# - 1002 +# - 1003 +# priorityClassName: high-priority +# resources: +# limits: +# cpu: 100m +# memory: 100M +# requests: +# cpu: 200m +# memory: 200M +# runtimeClassName: image-rc # s3: # bucket: S3-BACKUP-BUCKET-NAME-HERE -# credentialsSecret: cluster1-s3-credentials +# credentialsSecret: ps-cluster1-s3-credentials +# endpointUrl: https://s3.amazonaws.com +# prefix: PREFIX_NAME # region: us-west-2 +# schedulerName: default-scheduler +# tolerations: +# - effect: NoExecute +# key: node.alpha.kubernetes.io/unreachable +# operator: Exists +# tolerationSeconds: 6000 +# topologySpreadConstraints: +# - labelSelector: +# matchLabels: +# app.kubernetes.io/name: percona-server +# maxSkew: 1 +# topologyKey: kubernetes.io/hostname +# whenUnsatisfiable: DoNotSchedule # type: s3 +# verifyTLS: true +# volumeSpec: +# emptyDir: {} +# hostPath: +# path: /data +# type: Directory +# persistentVolumeClaim: +# accessModes: +# - ReadWriteOnce +# resources: +# requests: +# storage: 2Gi +# storageClassName: standard diff --git a/deploy/bundle.yaml b/deploy/bundle.yaml index c1595a804..bde632fab 100644 --- a/deploy/bundle.yaml +++ b/deploy/bundle.yaml @@ -961,8 +961,6 @@ spec: type: string region: type: string - storageClass: - type: string required: - bucket - credentialsSecret @@ -2008,8 +2006,6 @@ spec: type: string region: type: string - storageClass: - type: string required: - bucket - credentialsSecret @@ -3765,8 +3761,6 @@ spec: type: string region: type: string - storageClass: - type: string required: - bucket - credentialsSecret @@ -3842,117 +3836,6 @@ spec: - whenUnsatisfiable type: object type: array - volumeSpec: - properties: - emptyDir: - properties: - medium: - type: string - sizeLimit: - 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 - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - persistentVolumeClaim: - properties: - accessModes: - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object - type: object writeTimeout: format: int32 type: integer @@ -4810,8 +4693,6 @@ spec: type: string region: type: string - storageClass: - type: string required: - bucket - credentialsSecret @@ -9389,117 +9270,6 @@ spec: - whenUnsatisfiable type: object type: array - volumeSpec: - properties: - emptyDir: - properties: - medium: - type: string - sizeLimit: - 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 - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - persistentVolumeClaim: - properties: - accessModes: - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object - type: object required: - image - size @@ -11030,117 +10800,6 @@ spec: - whenUnsatisfiable type: object type: array - volumeSpec: - properties: - emptyDir: - properties: - medium: - type: string - sizeLimit: - 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 - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - persistentVolumeClaim: - properties: - accessModes: - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object - type: object required: - image - size @@ -12410,117 +12069,6 @@ spec: - whenUnsatisfiable type: object type: array - volumeSpec: - properties: - emptyDir: - properties: - medium: - type: string - sizeLimit: - 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 - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - persistentVolumeClaim: - properties: - accessModes: - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object - type: object required: - image - size diff --git a/deploy/cr.yaml b/deploy/cr.yaml index ddf8ea990..5c0097cd8 100644 --- a/deploy/cr.yaml +++ b/deploy/cr.yaml @@ -1,11 +1,11 @@ apiVersion: ps.percona.com/v1 kind: PerconaServerMySQL metadata: - name: ps-cluster1 finalizers: - percona.com/delete-mysql-pods-in-order - # - percona.com/delete-ssl - # - percona.com/delete-mysql-pvc +# - percona.com/delete-ssl +# - percona.com/delete-mysql-pvc + name: ps-cluster1 spec: # metadata: # annotations: @@ -21,26 +21,26 @@ spec: # proxySize: false # pause: false crVersion: 1.0.0 -# enableVolumeExpansion: false +# enableVolumeExpansion: true secretsName: ps-cluster1-secrets sslSecretName: ps-cluster1-ssl updateStrategy: SmartUpdate upgradeOptions: - versionServiceEndpoint: https://check.percona.com apply: disabled + versionServiceEndpoint: https://check.percona.com # initContainer: -# image: perconalab/percona-server-mysql-operator:main # containerSecurityContext: # privileged: false -# runAsUser: 1001 # runAsGroup: 1001 +# runAsUser: 1001 +# image: perconalab/percona-server-mysql-operator:main # resources: -# requests: -# memory: 100M -# cpu: 100m # limits: -# memory: 200M +# cpu: 100m +# memory: 100M +# requests: # cpu: 200m +# memory: 200M # ignoreAnnotations: # - service.beta.kubernetes.io/aws-load-balancer-backend-protocol # ignoreLabels: @@ -51,238 +51,308 @@ spec: # - mysql-2.example.com # - mysql-3.example.com # issuerConf: -# name: special-selfsigned-issuer -# kind: ClusterIssuer # group: cert-manager.io - +# kind: ClusterIssuer +# name: special-selfsigned-issuer mysql: clusterType: group-replication autoRecovery: true +# vaultSecretName: ps-cluster1-vault + size: 3 image: perconalab/percona-server-mysql-operator:main-psmysql8.4 imagePullPolicy: Always +# imagePullSecrets: +# - name: my-secret-1 +# - name: my-secret-2 # runtimeClassName: image-rc -# schedulerName: mycustom-scheduler -# priorityClassName: high-priority -# nodeSelector: -# disktype: ssd -# serviceAccountName: percona-server-mysql-operator-orchestrator # tolerations: -# - key: "node.alpha.kubernetes.io/unreachable" -# operator: "Exists" -# effect: "NoExecute" -# tolerationSeconds: 6000 -# imagePullSecrets: -# - name: "my-secret-1" -# - name: "my-secret-2" +# - effect: NoExecute +# key: node.alpha.kubernetes.io/unreachable +# operator: Exists +# tolerationSeconds: 6000 +# annotations: +# service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp +# service.beta.kubernetes.io/aws-load-balancer-type: nlb +# labels: +# rack: rack-22 +# nodeSelector: +# topology.kubernetes.io/zone: us-east-1a +# priorityClassName: high-priority +# schedulerName: default-scheduler +# serviceAccountName: some-service-account + gracePeriod: 600 # initContainer: -# image: perconalab/percona-server-mysql-operator:main # containerSecurityContext: # privileged: false -# runAsUser: 1001 # runAsGroup: 1001 +# runAsUser: 1001 +# image: perconalab/percona-server-mysql-operator:main # resources: -# requests: -# memory: 100M -# cpu: 100m # limits: -# memory: 200M +# cpu: 100m +# memory: 100M +# requests: # cpu: 200m -# vaultSecretName: ps-cluster1-vault - size: 3 - +# memory: 200M # env: -# - name: BOOTSTRAP_READ_TIMEOUT -# value: "600" +# - name: BOOTSTRAP_READ_TIMEOUT +# value: "600" +# envFrom: +# - secretRef: +# name: mysql-env-secret podDisruptionBudget: maxUnavailable: 1 # minAvailable: 0 resources: - requests: - memory: 2Gi limits: memory: 4Gi - + requests: + memory: 2Gi # startupProbe: +# failureThreshold: 1 # initialDelaySeconds: 15 -# timeoutSeconds: 43200 # periodSeconds: 10 -# failureThreshold: 1 # successThreshold: 1 -# +# timeoutSeconds: 43200 # readinessProbe: -# initialDelaySeconds: 30 -# timeoutSeconds: 10 -# periodSeconds: 10 # failureThreshold: 3 +# initialDelaySeconds: 30 +# periodSeconds: 5 # successThreshold: 1 -# +# timeoutSeconds: 3 # livenessProbe: +# failureThreshold: 3 # initialDelaySeconds: 15 -# timeoutSeconds: 10 # periodSeconds: 10 -# failureThreshold: 3 # successThreshold: 1 - +# timeoutSeconds: 10 affinity: - antiAffinityTopologyKey: "kubernetes.io/hostname" # advanced: # nodeAffinity: # requiredDuringSchedulingIgnoredDuringExecution: # nodeSelectorTerms: -# - matchExpressions: -# - key: kubernetes.io/e2e-az-name -# operator: In -# values: -# - e2e-az1 -# - e2e-az2 +# - matchExpressions: +# - key: kubernetes.io/e2e-az-name +# operator: In +# values: +# - e2e-az1 +# - e2e-az2 + antiAffinityTopologyKey: kubernetes.io/hostname # topologySpreadConstraints: -# - labelSelector: -# matchLabels: -# app.kubernetes.io/name: percona-server -# maxSkew: 1 -# topologyKey: kubernetes.io/hostname -# whenUnsatisfiable: DoNotSchedule - +# - labelSelector: +# matchLabels: +# app.kubernetes.io/name: percona-server +# maxSkew: 1 +# topologyKey: kubernetes.io/hostname +# whenUnsatisfiable: DoNotSchedule +# containerSecurityContext: +# privileged: false +# runAsGroup: 1001 +# runAsUser: 1001 +# podSecurityContext: +# fsGroup: 1001 +# supplementalGroups: +# - 1001 +# - 1002 +# - 1003 exposePrimary: - enabled: true -# type: ClusterIP # annotations: # service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp # service.beta.kubernetes.io/aws-load-balancer-type: nlb + enabled: true # externalTrafficPolicy: Cluster # internalTrafficPolicy: Cluster # labels: # rack: rack-22 # loadBalancerSourceRanges: # - 10.0.0.0/8 - -# expose: -# enabled: false # type: ClusterIP +# expose: # annotations: # service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp # service.beta.kubernetes.io/aws-load-balancer-type: nlb +# enabled: false # externalTrafficPolicy: Cluster # internalTrafficPolicy: Cluster # labels: # rack: rack-22 # loadBalancerSourceRanges: # - 10.0.0.0/8 - +# type: ClusterIP volumeSpec: -# emptyDir: { } +# emptyDir: {} # hostPath: # path: /data # type: Directory persistentVolumeClaim: -# storageClassName: standard -# accessModes: [ "ReadWriteOnce" ] +# accessModes: +# - ReadWriteOnce resources: requests: storage: 2Gi - gracePeriod: 600 -# configuration: | +# storageClassName: standard +# configuration: |- # max_connections=250 # innodb_buffer_pool_size={{containerMemoryLimit * 3/4}} - # sidecars: -# - name: noop-memory -# image: busybox -# command: ["sleep", "30d"] -# volumeMounts: -# - name: "memory-vol" -# mountPath: "/var/log/app/memory" -# resources: -# requests: -# memory: 16M -# - name: noop-pvc -# image: busybox -# command: ["sleep", "30d"] -# volumeMounts: -# - name: "pvc-vol" -# mountPath: "/var/log/app/pvc" -# sidecarVolumes: -# - name: "memory-vol" -# emptyDir: -# medium: "Memory" -# sidecarPVCs: -# - name: pvc-vol -# spec: +# - command: +# - sleep +# - 30d +# image: busybox +# imagePullPolicy: Always +# lifecycle: {} +# livenessProbe: {} +# name: noop-memory +# readinessProbe: {} # resources: # requests: -# storage: 1Gi -# containerSecurityContext: -# privileged: true -# podSecurityContext: -# fsGroup: 1001 -# supplementalGroups: [1001, 1002, 1003] - +# memory: 16M +# securityContext: {} +# startupProbe: {} +# volumeMounts: +# - mountPath: /var/log/app/memory +# name: memory-vol +# - command: +# - sleep +# - 30d +# image: busybox +# imagePullPolicy: Always +# lifecycle: {} +# livenessProbe: {} +# name: noop-pvc +# readinessProbe: {} +# resources: +# requests: +# memory: 16M +# securityContext: {} +# startupProbe: {} +# volumeMounts: +# - mountPath: /var/log/app/memory +# name: memory-vol +# sidecarVolumes: +# - emptyDir: +# medium: Memory +# name: memory-vol +# sidecarPVCs: +# - name: pvc-vol +# spec: +# resources: +# requests: +# storage: 1Gi proxy: haproxy: enabled: true - +# expose: +# annotations: +# service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp +# service.beta.kubernetes.io/aws-load-balancer-type: nlb +# externalTrafficPolicy: Cluster +# internalTrafficPolicy: Cluster +# labels: +# rack: rack-22 +# loadBalancerSourceRanges: +# - 10.0.0.0/8 +# type: ClusterIP size: 3 - image: perconalab/percona-server-mysql-operator:main-haproxy imagePullPolicy: Always +# imagePullSecrets: +# - name: my-secret-1 +# - name: my-secret-2 # runtimeClassName: image-rc -# schedulerName: mycustom-scheduler -# priorityClassName: high-priority -# nodeSelector: -# disktype: ssd -# serviceAccountName: percona-server-mysql-operator-orchestrator # tolerations: -# - key: "node.alpha.kubernetes.io/unreachable" -# operator: "Exists" -# effect: "NoExecute" -# tolerationSeconds: 6000 -# imagePullSecrets: -# - name: "my-secret-1" -# - name: "my-secret-2" - +# - effect: NoExecute +# key: node.alpha.kubernetes.io/unreachable +# operator: Exists +# tolerationSeconds: 6000 +# annotations: +# service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp +# service.beta.kubernetes.io/aws-load-balancer-type: nlb +# labels: +# rack: rack-22 +# nodeSelector: +# topology.kubernetes.io/zone: us-east-1a +# priorityClassName: high-priority +# schedulerName: default-scheduler +# serviceAccountName: some-service-account + gracePeriod: 30 +# initContainer: +# containerSecurityContext: +# privileged: false +# runAsGroup: 1001 +# runAsUser: 1001 +# image: perconalab/percona-server-mysql-operator:main +# resources: +# limits: +# cpu: 100m +# memory: 100M +# requests: +# cpu: 200m +# memory: 200M +# env: +# - name: HA_CONNECTION_TIMEOUT +# value: "600" +# envFrom: +# - secretRef: +# name: haproxy-env-secret podDisruptionBudget: maxUnavailable: 1 # minAvailable: 0 resources: - requests: - memory: 1Gi - cpu: 600m # limits: -# memory: 1Gi # cpu: 700m - -# env: -# - name: HA_CONNECTION_TIMEOUT -# value: "1000" -# -# envFrom: -# - secretRef: -# name: haproxy-env-secret - +# memory: 1Gi + requests: + cpu: 600m + memory: 1Gi # startupProbe: -# initialDelaySeconds: 15 -# timeoutSeconds: 43200 -# periodSeconds: 10 -# failureThreshold: 1 +# failureThreshold: 3 +# periodSeconds: 5 # successThreshold: 1 -# -# readinessProbe: # timeoutSeconds: 3 -# periodSeconds: 5 +# readinessProbe: # failureThreshold: 3 +# initialDelaySeconds: 15 +# periodSeconds: 5 # successThreshold: 1 -# +# timeoutSeconds: 1 # livenessProbe: -# timeoutSeconds: 3 -# periodSeconds: 5 -# failureThreshold: 3 +# failureThreshold: 4 +# initialDelaySeconds: 60 +# periodSeconds: 30 # successThreshold: 1 - - gracePeriod: 30 - -# configuration: | -# -# the actual default configuration file can be found here https://github.com/percona/percona-server-mysql-operator/blob/main/build/haproxy-global.cfg +# timeoutSeconds: 3 + affinity: +# advanced: +# nodeAffinity: +# requiredDuringSchedulingIgnoredDuringExecution: +# nodeSelectorTerms: +# - matchExpressions: +# - key: kubernetes.io/e2e-az-name +# operator: In +# values: +# - e2e-az1 +# - e2e-az2 + antiAffinityTopologyKey: kubernetes.io/hostname +# topologySpreadConstraints: +# - labelSelector: +# matchLabels: +# app.kubernetes.io/name: percona-server +# maxSkew: 1 +# topologyKey: kubernetes.io/hostname +# whenUnsatisfiable: DoNotSchedule +# containerSecurityContext: +# privileged: false +# runAsGroup: 1001 +# runAsUser: 1001 +# podSecurityContext: +# fsGroup: 1001 +# supplementalGroups: +# - 1001 +# - 1002 +# - 1003 +# configuration: |- +# # the actual default configuration file can be found here https://github.com/percona/percona-server-mysql-operator/blob/main/build/haproxy-global.cfg # # global # maxconn 2048 @@ -316,29 +386,9 @@ spec: # bind *:8404 # mode http # http-request use-service prometheus-exporter if { path /metrics } - - affinity: - antiAffinityTopologyKey: "kubernetes.io/hostname" -# advanced: -# nodeAffinity: -# requiredDuringSchedulingIgnoredDuringExecution: -# nodeSelectorTerms: -# - matchExpressions: -# - key: kubernetes.io/e2e-az-name -# operator: In -# values: -# - e2e-az1 -# - e2e-az2 -# topologySpreadConstraints: -# - labelSelector: -# matchLabels: -# app.kubernetes.io/name: percona-server -# maxSkew: 1 -# topologyKey: kubernetes.io/hostname -# whenUnsatisfiable: DoNotSchedule - + router: + enabled: false # expose: -# type: ClusterIP # annotations: # service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp # service.beta.kubernetes.io/aws-load-balancer-type: nlb @@ -348,383 +398,477 @@ spec: # rack: rack-22 # loadBalancerSourceRanges: # - 10.0.0.0/8 -# containerSecurityContext: -# privileged: true -# podSecurityContext: -# fsGroup: 1001 -# supplementalGroups: [1001, 1002, 1003] - - router: - enabled: false +# type: ClusterIP + size: 3 image: perconalab/percona-server-mysql-operator:main-router8.4 imagePullPolicy: Always +# imagePullSecrets: +# - name: my-secret-1 +# - name: my-secret-2 # runtimeClassName: image-rc -# schedulerName: mycustom-scheduler -# priorityClassName: high-priority -# nodeSelector: -# disktype: ssd -# serviceAccountName: percona-server-mysql-operator-orchestrator -# startupProbe: -# initialDelaySeconds: 15 -# timeoutSeconds: 43200 -# periodSeconds: 10 -# failureThreshold: 1 -# successThreshold: 1 -# readinessProbe: -# timeoutSeconds: 3 -# periodSeconds: 5 -# failureThreshold: 3 -# successThreshold: 1 -# livenessProbe: -# timeoutSeconds: 3 -# periodSeconds: 5 -# failureThreshold: 3 -# successThreshold: 1 # tolerations: -# - key: "node.alpha.kubernetes.io/unreachable" -# operator: "Exists" -# effect: "NoExecute" -# tolerationSeconds: 6000 -# imagePullSecrets: -# - name: "my-secret-1" -# - name: "my-secret-2" +# - effect: NoExecute +# key: node.alpha.kubernetes.io/unreachable +# operator: Exists +# tolerationSeconds: 6000 +# annotations: +# service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp +# service.beta.kubernetes.io/aws-load-balancer-type: nlb +# labels: +# rack: rack-22 +# nodeSelector: +# topology.kubernetes.io/zone: us-east-1a +# priorityClassName: high-priority +# schedulerName: default-scheduler +# serviceAccountName: some-service-account + gracePeriod: 30 # initContainer: -# image: perconalab/percona-server-mysql-operator:main # containerSecurityContext: # privileged: false -# runAsUser: 1001 # runAsGroup: 1001 +# runAsUser: 1001 +# image: perconalab/percona-server-mysql-operator:main # resources: -# requests: -# memory: 100M -# cpu: 100m # limits: -# memory: 200M +# cpu: 100m +# memory: 100M +# requests: # cpu: 200m -# ports: -# - name: http -# port: 8443 -# targetPort: 0 -# - name: rw-default -# port: 3306 -# targetPort: 6446 -# - name: read-write -# port: 6446 -# targetPort: 0 -# - name: read-only -# port: 6447 -# targetPort: 0 -# - name: x-read-write -# port: 6448 -# targetPort: 0 -# - name: x-read-only -# port: 6449 -# targetPort: 0 -# - name: x-default -# port: 33060 -# targetPort: 0 -# - name: rw-admin -# port: 33062 -# targetPort: 0 -# - name: custom-port -# port: 1111 -# targetPort: 6446 - - size: 3 - - podDisruptionBudget: +# memory: 200M +# env: +# - name: ROUTER_ENV +# value: VALUE +# envFrom: +# - secretRef: +# name: router-env-secret + podDisruptionBudget: maxUnavailable: 1 # minAvailable: 0 resources: - requests: - memory: 256M limits: memory: 256M - + requests: + memory: 256M +# startupProbe: +# failureThreshold: 1 +# initialDelaySeconds: 5 +# periodSeconds: 5 +# successThreshold: 1 +# timeoutSeconds: 3 +# readinessProbe: +# failureThreshold: 3 +# periodSeconds: 5 +# successThreshold: 1 +# timeoutSeconds: 3 +# livenessProbe: +# failureThreshold: 3 +# periodSeconds: 5 +# successThreshold: 1 +# timeoutSeconds: 3 affinity: - antiAffinityTopologyKey: "kubernetes.io/hostname" # advanced: # nodeAffinity: # requiredDuringSchedulingIgnoredDuringExecution: # nodeSelectorTerms: -# - matchExpressions: -# - key: kubernetes.io/e2e-az-name -# operator: In -# values: -# - e2e-az1 -# - e2e-az2 +# - matchExpressions: +# - key: kubernetes.io/e2e-az-name +# operator: In +# values: +# - e2e-az1 +# - e2e-az2 + antiAffinityTopologyKey: kubernetes.io/hostname # topologySpreadConstraints: -# - labelSelector: -# matchLabels: -# app.kubernetes.io/name: percona-server -# maxSkew: 1 -# topologyKey: kubernetes.io/hostname -# whenUnsatisfiable: DoNotSchedule - - gracePeriod: 30 - -# configuration: | -# [default] -# logging_folder=/tmp/router/log -# [logger] -# level=DEBUG - -# expose: -# type: ClusterIP -# annotations: -# service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp -# service.beta.kubernetes.io/aws-load-balancer-type: nlb -# externalTrafficPolicy: Cluster -# internalTrafficPolicy: Cluster -# labels: -# rack: rack-22 -# loadBalancerSourceRanges: -# - 10.0.0.0/8 +# - labelSelector: +# matchLabels: +# app.kubernetes.io/name: percona-server +# maxSkew: 1 +# topologyKey: kubernetes.io/hostname +# whenUnsatisfiable: DoNotSchedule # containerSecurityContext: # privileged: false -# runAsUser: 1001 # runAsGroup: 1001 +# runAsUser: 1001 # podSecurityContext: # fsGroup: 1001 -# supplementalGroups: [1001, 1002, 1003] - +# supplementalGroups: +# - 1001 +# - 1002 +# - 1003 +# ports: +# - name: http +# port: 8443 +# targetPort: 0 +# - name: rw-default +# port: 3306 +# targetPort: 6446 +# - name: read-write +# port: 6446 +# targetPort: 0 +# - name: read-only +# port: 6447 +# targetPort: 0 +# - name: x-read-write +# port: 6448 +# targetPort: 0 +# - name: x-read-only +# port: 6449 +# targetPort: 0 +# - name: x-default +# port: 33060 +# targetPort: 0 +# - name: rw-admin +# port: 33062 +# targetPort: 0 +# - name: custom-port +# port: 1111 +# targetPort: 6446 +# configuration: |- +# [default] +# logging_folder=/tmp/router/log +# [logger] +# level=DEBUG orchestrator: enabled: false +# expose: +# annotations: +# service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp +# service.beta.kubernetes.io/aws-load-balancer-type: nlb +# externalTrafficPolicy: Cluster +# internalTrafficPolicy: Cluster +# labels: +# rack: rack-22 +# loadBalancerSourceRanges: +# - 10.0.0.0/8 +# type: ClusterIP + size: 3 image: perconalab/percona-server-mysql-operator:main-orchestrator imagePullPolicy: Always +# imagePullSecrets: +# - name: my-secret-1 +# - name: my-secret-2 # runtimeClassName: image-rc -# schedulerName: mycustom-scheduler -# priorityClassName: high-priority -# nodeSelector: -# disktype: ssd -# startupProbe: -# initialDelaySeconds: 15 -# timeoutSeconds: 43200 -# periodSeconds: 10 -# failureThreshold: 1 -# successThreshold: 1 -# readinessProbe: -# timeoutSeconds: 3 -# periodSeconds: 5 -# failureThreshold: 3 -# successThreshold: 1 -# livenessProbe: -# timeoutSeconds: 3 -# periodSeconds: 5 -# failureThreshold: 3 -# successThreshold: 1 # tolerations: -# - key: "node.alpha.kubernetes.io/unreachable" -# operator: "Exists" -# effect: "NoExecute" -# tolerationSeconds: 6000 -# imagePullSecrets: -# - name: "my-secret-1" -# - name: "my-secret-2" +# - effect: NoExecute +# key: node.alpha.kubernetes.io/unreachable +# operator: Exists +# tolerationSeconds: 6000 +# annotations: +# service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp +# service.beta.kubernetes.io/aws-load-balancer-type: nlb +# labels: +# rack: rack-22 +# nodeSelector: +# topology.kubernetes.io/zone: us-east-1a +# priorityClassName: high-priority +# schedulerName: default-scheduler # serviceAccountName: percona-server-mysql-operator-orchestrator + gracePeriod: 30 # initContainer: -# image: perconalab/percona-server-mysql-operator:main # containerSecurityContext: # privileged: false -# runAsUser: 1001 # runAsGroup: 1001 +# runAsUser: 1001 +# image: perconalab/percona-server-mysql-operator:main # resources: -# requests: -# memory: 100M -# cpu: 100m # limits: -# memory: 200M +# cpu: 100m +# memory: 100M +# requests: # cpu: 200m - - size: 3 - +# memory: 200M +# env: +# - name: ORC_ENV +# value: VALUE +# envFrom: +# - secretRef: +# name: orc-env-secret + podDisruptionBudget: + maxUnavailable: 1 +# minAvailable: 0 + resources: + limits: + memory: 256M + requests: + memory: 128M +# startupProbe: +# failureThreshold: 3 +# periodSeconds: 5 +# successThreshold: 1 +# timeoutSeconds: 3 +# readinessProbe: +# failureThreshold: 3 +# periodSeconds: 5 +# successThreshold: 1 +# timeoutSeconds: 3 +# livenessProbe: +# failureThreshold: 3 +# periodSeconds: 5 +# successThreshold: 1 +# timeoutSeconds: 3 affinity: - antiAffinityTopologyKey: "kubernetes.io/hostname" # advanced: # nodeAffinity: # requiredDuringSchedulingIgnoredDuringExecution: # nodeSelectorTerms: -# - matchExpressions: -# - key: kubernetes.io/e2e-az-name -# operator: In -# values: -# - e2e-az1 -# - e2e-az2 +# - matchExpressions: +# - key: kubernetes.io/e2e-az-name +# operator: In +# values: +# - e2e-az1 +# - e2e-az2 + antiAffinityTopologyKey: kubernetes.io/hostname # topologySpreadConstraints: -# - labelSelector: -# matchLabels: -# app.kubernetes.io/name: percona-server -# maxSkew: 1 -# topologyKey: kubernetes.io/hostname -# whenUnsatisfiable: DoNotSchedule - -# expose: -# type: ClusterIP -# annotations: -# service.beta.kubernetes.io/aws-load-balancer-backend-protocol: tcp -# service.beta.kubernetes.io/aws-load-balancer-type: nlb -# externalTrafficPolicy: Cluster -# internalTrafficPolicy: Cluster -# labels: -# rack: rack-22 -# loadBalancerSourceRanges: -# - 10.0.0.0/8 +# - labelSelector: +# matchLabels: +# app.kubernetes.io/name: percona-server +# maxSkew: 1 +# topologyKey: kubernetes.io/hostname +# whenUnsatisfiable: DoNotSchedule # containerSecurityContext: # privileged: false -# runAsUser: 1001 # runAsGroup: 1001 +# runAsUser: 1001 # podSecurityContext: -# fsGroup: 1001 -# supplementalGroups: [1001, 1002, 1003] - - podDisruptionBudget: - maxUnavailable: 1 -# minAvailable: 0 - gracePeriod: 30 - - resources: - requests: - memory: 128M - limits: - memory: 256M - +# supplementalGroups: +# - 1001 + configuration: "" pmm: enabled: false image: perconalab/pmm-client:3-dev-latest imagePullPolicy: Always -# readinessProbe: -# initialDelaySeconds: 15 -# timeoutSeconds: 15 -# periodSeconds: 30 -# successThreshold: 1 -# failureThreshold: 5 -# livenessProbe: -# initialDelaySeconds: 300 -# timeoutSeconds: 5 -# periodSeconds: 10 -# successThreshold: 1 -# failureThreshold: 3 -# mysqlParams: "--disable-tablestats-limit=2000" + serverHost: monitoring-service +# mysqlParams: PMM_ADMIN_CUSTOM_PARAMS +# containerSecurityContext: +# privileged: false +# runAsGroup: 1001 +# runAsUser: 1001 resources: - requests: - memory: 150M - cpu: 300m # limits: -# memory: 256M # cpu: 400m - - serverHost: monitoring-service - +# memory: 256M + requests: + cpu: 300m + memory: 150M + livenessProbe: + failureThreshold: 3 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 3 + readinessProbe: + failureThreshold: 3 + periodSeconds: 5 + successThreshold: 1 + timeoutSeconds: 3 backup: enabled: true + pitr: + enabled: false # sourcePod: ps-cluster1-mysql-1 image: perconalab/percona-server-mysql-operator:main-backup8.4 + imagePullPolicy: Always +# imagePullSecrets: +# - name: my-secret-1 +# - name: my-secret-2 # schedule: -# - name: "sat-night-backup" -# schedule: "0 0 * * 6" -# keep: 3 +# - keep: 3 +# name: sat-night-backup +# schedule: 0 0 * * 6 # storageName: s3-us-west -# - name: "daily-backup" -# schedule: "0 0 * * *" -# keep: 5 +# - keep: 5 +# name: daily-backup +# schedule: 0 0 * * * # storageName: s3 # backoffLimit: 6 - imagePullPolicy: Always -# imagePullSecrets: -# - name: "my-secret-1" -# - name: "my-secret-2" +# serviceAccountName: some-service-account # initContainer: -# image: perconalab/percona-server-mysql-operator:main # containerSecurityContext: # privileged: false -# runAsUser: 1001 # runAsGroup: 1001 +# runAsUser: 1001 +# image: perconalab/percona-server-mysql-operator:main # resources: -# requests: -# memory: 100M -# cpu: 100m # limits: -# memory: 200M +# cpu: 100m +# memory: 100M +# requests: # cpu: 200m +# memory: 200M # containerSecurityContext: -# privileged: true +# privileged: false +# runAsGroup: 1001 +# runAsUser: 1001 +# resources: +# limits: +# cpu: 100m +# memory: 100M +# requests: +# cpu: 200m +# memory: 200M storages: # azure-blob: -# type: azure # azure: # container: CONTAINER-NAME -# prefix: PREFIX-NAME -# endpointUrl: https://accountName.blob.core.windows.net # credentialsSecret: SECRET-NAME - s3-us-west: - type: s3 - verifyTLS: true -# nodeSelector: -# storage: tape -# backupWorker: 'True' +# endpointUrl: https://accountName.blob.core.windows.net +# prefix: PREFIX-NAME +# storageClass: Cool +# containerOptions: +# args: +# xbcloud: +# - --someflag=abc +# xbstream: +# - --someflag=abc +# xtrabackup: +# - --someflag=abc +# env: +# - name: CUSTOM_VAR +# value: "false" +# containerSecurityContext: +# privileged: false +# runAsGroup: 1001 +# runAsUser: 1001 +# podSecurityContext: +# fsGroup: 1001 +# supplementalGroups: +# - 1001 +# - 1002 +# - 1003 # resources: +# limits: +# cpu: 100m +# memory: 100M # requests: -# memory: 1Gi -# cpu: 600m +# cpu: 200m +# memory: 200M +# tolerations: +# - effect: NoExecute +# key: node.alpha.kubernetes.io/unreachable +# operator: Exists +# tolerationSeconds: 6000 +# topologySpreadConstraints: +# - labelSelector: +# matchLabels: +# app.kubernetes.io/name: percona-server +# maxSkew: 1 +# topologyKey: kubernetes.io/hostname +# whenUnsatisfiable: DoNotSchedule +# type: azure +# verifyTLS: null + s3-us-west: # affinity: # nodeAffinity: # requiredDuringSchedulingIgnoredDuringExecution: # nodeSelectorTerms: -# - matchExpressions: -# - key: backupWorker -# operator: In -# values: -# - 'True' -# topologySpreadConstraints: -# - labelSelector: -# matchLabels: -# app.kubernetes.io/name: percona-server -# maxSkew: 1 -# topologyKey: kubernetes.io/hostname -# whenUnsatisfiable: DoNotSchedule -# tolerations: -# - key: "backupWorker" -# operator: "Equal" -# value: "True" -# effect: "NoSchedule" +# - matchExpressions: +# - key: kubernetes.io/e2e-az-name +# operator: In +# values: +# - e2e-az1 +# - e2e-az2 # annotations: # testName: scheduled-backup -# labels: -# backupWorker: 'True' -# schedulerName: 'default-scheduler' -# priorityClassName: 'high-priority' -# containerSecurityContext: -# privileged: true -# podSecurityContext: -# fsGroup: 1001 -# supplementalGroups: [1001, 1002, 1003] -# runtimeClassName: image-rc # containerOptions: -# env: -# - name: CUSTOM_VAR -# value: "false" # args: -# xtrabackup: -# - "--someflag=abc" # xbcloud: -# - "--someflag=abc" +# - --someflag=abc # xbstream: -# - "--someflag=abc" +# - --someflag=abc +# xtrabackup: +# - --someflag=abc +# env: +# - name: CUSTOM_VAR +# value: "false" +# containerSecurityContext: +# privileged: false +# runAsGroup: 1001 +# runAsUser: 1001 +# labels: +# backupWorker: "True" +# nodeSelector: +# topology.kubernetes.io/zone: us-east-1a +# podSecurityContext: +# fsGroup: 1001 +# supplementalGroups: +# - 1001 +# - 1002 +# - 1003 +# priorityClassName: high-priority +# resources: +# limits: +# cpu: 100m +# memory: 100M +# requests: +# cpu: 200m +# memory: 200M +# runtimeClassName: image-rc s3: bucket: S3-BACKUP-BUCKET-NAME-HERE credentialsSecret: ps-cluster1-s3-credentials -# - "--someflag=abc" +# endpointUrl: https://s3.amazonaws.com +# prefix: PREFIX_NAME region: us-west-2 -# prefix: "" - +# schedulerName: default-scheduler +# tolerations: +# - effect: NoExecute +# key: node.alpha.kubernetes.io/unreachable +# operator: Exists +# tolerationSeconds: 6000 +# topologySpreadConstraints: +# - labelSelector: +# matchLabels: +# app.kubernetes.io/name: percona-server +# maxSkew: 1 +# topologyKey: kubernetes.io/hostname +# whenUnsatisfiable: DoNotSchedule + type: s3 + verifyTLS: true +# volumeSpec: +# emptyDir: {} +# hostPath: +# path: /data +# type: Directory +# persistentVolumeClaim: +# accessModes: +# - ReadWriteOnce +# resources: +# requests: +# storage: 2Gi +# storageClassName: standard toolkit: image: perconalab/percona-server-mysql-operator:main-toolkit imagePullPolicy: Always +# imagePullSecrets: +# - name: my-secret-1 +# - name: my-secret-2 +# env: +# - name: TOOLKIT_ENV +# value: VALUE +# envFrom: +# - secretRef: +# name: toolkit-env-secret # resources: -# requests: -# memory: 150M -# cpu: 100m # limits: -# memory: 256M # cpu: 400m - +# memory: 256M +# requests: +# cpu: 100m +# memory: 150M +# containerSecurityContext: +# privileged: false +# runAsGroup: 1001 +# runAsUser: 1001 +# startupProbe: +# failureThreshold: 3 +# periodSeconds: 5 +# successThreshold: 1 +# timeoutSeconds: 3 +# readinessProbe: +# failureThreshold: 3 +# periodSeconds: 5 +# successThreshold: 1 +# timeoutSeconds: 3 +# livenessProbe: +# failureThreshold: 3 +# periodSeconds: 5 +# successThreshold: 1 +# timeoutSeconds: 3 diff --git a/deploy/crd.yaml b/deploy/crd.yaml index 5176c735a..72b79d9cc 100644 --- a/deploy/crd.yaml +++ b/deploy/crd.yaml @@ -961,8 +961,6 @@ spec: type: string region: type: string - storageClass: - type: string required: - bucket - credentialsSecret @@ -2008,8 +2006,6 @@ spec: type: string region: type: string - storageClass: - type: string required: - bucket - credentialsSecret @@ -3765,8 +3761,6 @@ spec: type: string region: type: string - storageClass: - type: string required: - bucket - credentialsSecret @@ -3842,117 +3836,6 @@ spec: - whenUnsatisfiable type: object type: array - volumeSpec: - properties: - emptyDir: - properties: - medium: - type: string - sizeLimit: - 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 - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - persistentVolumeClaim: - properties: - accessModes: - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object - type: object writeTimeout: format: int32 type: integer @@ -4810,8 +4693,6 @@ spec: type: string region: type: string - storageClass: - type: string required: - bucket - credentialsSecret @@ -9389,117 +9270,6 @@ spec: - whenUnsatisfiable type: object type: array - volumeSpec: - properties: - emptyDir: - properties: - medium: - type: string - sizeLimit: - 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 - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - persistentVolumeClaim: - properties: - accessModes: - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object - type: object required: - image - size @@ -11030,117 +10800,6 @@ spec: - whenUnsatisfiable type: object type: array - volumeSpec: - properties: - emptyDir: - properties: - medium: - type: string - sizeLimit: - 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 - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - persistentVolumeClaim: - properties: - accessModes: - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object - type: object required: - image - size @@ -12410,117 +12069,6 @@ spec: - whenUnsatisfiable type: object type: array - volumeSpec: - properties: - emptyDir: - properties: - medium: - type: string - sizeLimit: - 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 - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - persistentVolumeClaim: - properties: - accessModes: - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object - type: object required: - image - size diff --git a/deploy/cw-bundle.yaml b/deploy/cw-bundle.yaml index 0373447c5..0e655bd01 100644 --- a/deploy/cw-bundle.yaml +++ b/deploy/cw-bundle.yaml @@ -961,8 +961,6 @@ spec: type: string region: type: string - storageClass: - type: string required: - bucket - credentialsSecret @@ -2008,8 +2006,6 @@ spec: type: string region: type: string - storageClass: - type: string required: - bucket - credentialsSecret @@ -3765,8 +3761,6 @@ spec: type: string region: type: string - storageClass: - type: string required: - bucket - credentialsSecret @@ -3842,117 +3836,6 @@ spec: - whenUnsatisfiable type: object type: array - volumeSpec: - properties: - emptyDir: - properties: - medium: - type: string - sizeLimit: - 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 - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - persistentVolumeClaim: - properties: - accessModes: - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object - type: object writeTimeout: format: int32 type: integer @@ -4810,8 +4693,6 @@ spec: type: string region: type: string - storageClass: - type: string required: - bucket - credentialsSecret @@ -9389,117 +9270,6 @@ spec: - whenUnsatisfiable type: object type: array - volumeSpec: - properties: - emptyDir: - properties: - medium: - type: string - sizeLimit: - 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 - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - persistentVolumeClaim: - properties: - accessModes: - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object - type: object required: - image - size @@ -11030,117 +10800,6 @@ spec: - whenUnsatisfiable type: object type: array - volumeSpec: - properties: - emptyDir: - properties: - medium: - type: string - sizeLimit: - 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 - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - persistentVolumeClaim: - properties: - accessModes: - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object - type: object required: - image - size @@ -12410,117 +12069,6 @@ spec: - whenUnsatisfiable type: object type: array - volumeSpec: - properties: - emptyDir: - properties: - medium: - type: string - sizeLimit: - 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 - type: object - hostPath: - properties: - path: - type: string - type: - type: string - required: - - path - type: object - persistentVolumeClaim: - properties: - accessModes: - items: - type: string - type: array - x-kubernetes-list-type: atomic - dataSource: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - required: - - kind - - name - type: object - x-kubernetes-map-type: atomic - dataSourceRef: - properties: - apiGroup: - type: string - kind: - type: string - name: - type: string - namespace: - type: string - required: - - kind - - name - type: object - resources: - properties: - 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 - 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 - type: object - type: object - selector: - properties: - matchExpressions: - items: - properties: - key: - type: string - operator: - type: string - values: - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - type: object - type: object - x-kubernetes-map-type: atomic - storageClassName: - type: string - volumeAttributesClassName: - type: string - volumeMode: - type: string - volumeName: - type: string - type: object - type: object required: - image - size diff --git a/pkg/controller/ps/version_test.go b/pkg/controller/ps/version_test.go index 3d83ae60f..faa4d7304 100644 --- a/pkg/controller/ps/version_test.go +++ b/pkg/controller/ps/version_test.go @@ -74,18 +74,18 @@ func TestReconcileVersions(t *testing.T) { }, MySQL: apiv1.MySQLSpec{ ClusterType: apiv1.ClusterTypeGR, - PodSpec: apiv1.PodSpec{ - Size: 3, - VolumeSpec: &apiv1.VolumeSpec{ - PersistentVolumeClaim: &corev1.PersistentVolumeClaimSpec{ - Resources: corev1.VolumeResourceRequirements{ - Requests: map[corev1.ResourceName]resource.Quantity{ - corev1.ResourceStorage: q, - }, + VolumeSpec: &apiv1.VolumeSpec{ + PersistentVolumeClaim: &corev1.PersistentVolumeClaimSpec{ + Resources: corev1.VolumeResourceRequirements{ + Requests: map[corev1.ResourceName]resource.Quantity{ + corev1.ResourceStorage: q, }, }, }, }, + PodSpec: apiv1.PodSpec{ + Size: 3, + }, }, Proxy: apiv1.ProxySpec{ HAProxy: &apiv1.HAProxySpec{ @@ -118,18 +118,18 @@ func TestReconcileVersions(t *testing.T) { }, MySQL: apiv1.MySQLSpec{ ClusterType: apiv1.ClusterTypeGR, - PodSpec: apiv1.PodSpec{ - Size: 3, - VolumeSpec: &apiv1.VolumeSpec{ - PersistentVolumeClaim: &corev1.PersistentVolumeClaimSpec{ - Resources: corev1.VolumeResourceRequirements{ - Requests: map[corev1.ResourceName]resource.Quantity{ - corev1.ResourceStorage: q, - }, + VolumeSpec: &apiv1.VolumeSpec{ + PersistentVolumeClaim: &corev1.PersistentVolumeClaimSpec{ + Resources: corev1.VolumeResourceRequirements{ + Requests: map[corev1.ResourceName]resource.Quantity{ + corev1.ResourceStorage: q, }, }, }, }, + PodSpec: apiv1.PodSpec{ + Size: 3, + }, }, Proxy: apiv1.ProxySpec{ HAProxy: &apiv1.HAProxySpec{ @@ -162,18 +162,18 @@ func TestReconcileVersions(t *testing.T) { }, MySQL: apiv1.MySQLSpec{ ClusterType: apiv1.ClusterTypeGR, - PodSpec: apiv1.PodSpec{ - Size: 3, - VolumeSpec: &apiv1.VolumeSpec{ - PersistentVolumeClaim: &corev1.PersistentVolumeClaimSpec{ - Resources: corev1.VolumeResourceRequirements{ - Requests: map[corev1.ResourceName]resource.Quantity{ - corev1.ResourceStorage: q, - }, + VolumeSpec: &apiv1.VolumeSpec{ + PersistentVolumeClaim: &corev1.PersistentVolumeClaimSpec{ + Resources: corev1.VolumeResourceRequirements{ + Requests: map[corev1.ResourceName]resource.Quantity{ + corev1.ResourceStorage: q, }, }, }, }, + PodSpec: apiv1.PodSpec{ + Size: 3, + }, }, Proxy: apiv1.ProxySpec{ HAProxy: &apiv1.HAProxySpec{ @@ -207,18 +207,18 @@ func TestReconcileVersions(t *testing.T) { }, MySQL: apiv1.MySQLSpec{ ClusterType: apiv1.ClusterTypeGR, - PodSpec: apiv1.PodSpec{ - Size: 3, - VolumeSpec: &apiv1.VolumeSpec{ - PersistentVolumeClaim: &corev1.PersistentVolumeClaimSpec{ - Resources: corev1.VolumeResourceRequirements{ - Requests: map[corev1.ResourceName]resource.Quantity{ - corev1.ResourceStorage: q, - }, + VolumeSpec: &apiv1.VolumeSpec{ + PersistentVolumeClaim: &corev1.PersistentVolumeClaimSpec{ + Resources: corev1.VolumeResourceRequirements{ + Requests: map[corev1.ResourceName]resource.Quantity{ + corev1.ResourceStorage: q, }, }, }, }, + PodSpec: apiv1.PodSpec{ + Size: 3, + }, }, Proxy: apiv1.ProxySpec{ HAProxy: &apiv1.HAProxySpec{ @@ -349,18 +349,18 @@ func TestGetVersion(t *testing.T) { }, MySQL: apiv1.MySQLSpec{ ClusterType: apiv1.ClusterTypeGR, - PodSpec: apiv1.PodSpec{ - Size: 3, - VolumeSpec: &apiv1.VolumeSpec{ - PersistentVolumeClaim: &corev1.PersistentVolumeClaimSpec{ - Resources: corev1.VolumeResourceRequirements{ - Requests: map[corev1.ResourceName]resource.Quantity{ - corev1.ResourceStorage: q, - }, + VolumeSpec: &apiv1.VolumeSpec{ + PersistentVolumeClaim: &corev1.PersistentVolumeClaimSpec{ + Resources: corev1.VolumeResourceRequirements{ + Requests: map[corev1.ResourceName]resource.Quantity{ + corev1.ResourceStorage: q, }, }, }, }, + PodSpec: apiv1.PodSpec{ + Size: 3, + }, }, Proxy: apiv1.ProxySpec{ HAProxy: &apiv1.HAProxySpec{ diff --git a/pkg/mysql/mysql_test.go b/pkg/mysql/mysql_test.go index 67177c9b8..702869748 100644 --- a/pkg/mysql/mysql_test.go +++ b/pkg/mysql/mysql_test.go @@ -182,19 +182,19 @@ func TestStatefulsetVolumes(t *testing.T) { }{ "pvc configured": { mysqlSpec: apiv1.MySQLSpec{ - PodSpec: apiv1.PodSpec{ - Size: 3, - TerminationGracePeriodSeconds: ptr.To(int64(30)), - VolumeSpec: &apiv1.VolumeSpec{ - PersistentVolumeClaim: &corev1.PersistentVolumeClaimSpec{ - Resources: corev1.VolumeResourceRequirements{ - Requests: map[corev1.ResourceName]resource.Quantity{ - corev1.ResourceStorage: resource.MustParse("1Gi"), - }, + VolumeSpec: &apiv1.VolumeSpec{ + PersistentVolumeClaim: &corev1.PersistentVolumeClaimSpec{ + Resources: corev1.VolumeResourceRequirements{ + Requests: map[corev1.ResourceName]resource.Quantity{ + corev1.ResourceStorage: resource.MustParse("1Gi"), }, }, }, }, + PodSpec: apiv1.PodSpec{ + Size: 3, + TerminationGracePeriodSeconds: ptr.To(int64(30)), + }, }, expectedStatefulSet: appsv1.StatefulSet{ ObjectMeta: metav1.ObjectMeta{ @@ -224,12 +224,12 @@ func TestStatefulsetVolumes(t *testing.T) { }, "host path configured": { mysqlSpec: apiv1.MySQLSpec{ + VolumeSpec: &apiv1.VolumeSpec{ + HostPath: &corev1.HostPathVolumeSource{}, + }, PodSpec: apiv1.PodSpec{ Size: 3, TerminationGracePeriodSeconds: ptr.To(int64(30)), - VolumeSpec: &apiv1.VolumeSpec{ - HostPath: &corev1.HostPathVolumeSource{}, - }, }, }, expectedStatefulSet: appsv1.StatefulSet{ @@ -266,12 +266,12 @@ func TestStatefulsetVolumes(t *testing.T) { }, "empty dir configured": { mysqlSpec: apiv1.MySQLSpec{ + VolumeSpec: &apiv1.VolumeSpec{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + }, PodSpec: apiv1.PodSpec{ Size: 3, TerminationGracePeriodSeconds: ptr.To(int64(30)), - VolumeSpec: &apiv1.VolumeSpec{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - }, }, }, expectedStatefulSet: appsv1.StatefulSet{ @@ -308,13 +308,13 @@ func TestStatefulsetVolumes(t *testing.T) { }, "both entry dir and host path provided - only host path is actually configured due to higher priority": { mysqlSpec: apiv1.MySQLSpec{ + VolumeSpec: &apiv1.VolumeSpec{ + EmptyDir: &corev1.EmptyDirVolumeSource{}, + HostPath: &corev1.HostPathVolumeSource{}, + }, PodSpec: apiv1.PodSpec{ Size: 3, TerminationGracePeriodSeconds: ptr.To(int64(30)), - VolumeSpec: &apiv1.VolumeSpec{ - EmptyDir: &corev1.EmptyDirVolumeSource{}, - HostPath: &corev1.HostPathVolumeSource{}, - }, }, }, expectedStatefulSet: appsv1.StatefulSet{ diff --git a/pkg/xtrabackup/xtrabackup.go b/pkg/xtrabackup/xtrabackup.go index 76cb2c435..83d18981f 100644 --- a/pkg/xtrabackup/xtrabackup.go +++ b/pkg/xtrabackup/xtrabackup.go @@ -670,10 +670,6 @@ func SetStorageS3(job *batchv1.Job, s3 *apiv1.BackupStorageS3Spec) error { Name: "S3_BUCKET", Value: bucket, }, - { - Name: "S3_STORAGE_CLASS", - Value: s3.StorageClass, - }, } for i := range spec.Containers { @@ -880,7 +876,6 @@ func GetBackupConfig(ctx context.Context, cl client.Client, cr *apiv1.PerconaSer conf.S3.Bucket = bucket conf.S3.Region = s3.Region conf.S3.EndpointURL = s3.EndpointURL - conf.S3.StorageClass = s3.StorageClass conf.Type = apiv1.BackupStorageS3 case apiv1.BackupStorageGCS: gcs := storage.GCS diff --git a/pkg/xtrabackup/xtrabackup_test.go b/pkg/xtrabackup/xtrabackup_test.go index 38c090dd6..9fb12fd50 100644 --- a/pkg/xtrabackup/xtrabackup_test.go +++ b/pkg/xtrabackup/xtrabackup_test.go @@ -37,7 +37,6 @@ func TestJob(t *testing.T) { CredentialsSecret: "secret", Region: "region", EndpointURL: "endpoint", - StorageClass: "storage-class", }, }, } @@ -233,7 +232,6 @@ func TestDeleteJob(t *testing.T) { CredentialsSecret: "secret", Region: "region", EndpointURL: "endpoint", - StorageClass: "storage-class", }, }, } @@ -403,7 +401,6 @@ func TestRestoreJob(t *testing.T) { CredentialsSecret: "secret", Region: "region", EndpointURL: "endpoint", - StorageClass: "storage-class", }, }, }