diff --git a/Makefile b/Makefile index c8aba6682e..9ecc9a2abf 100644 --- a/Makefile +++ b/Makefile @@ -36,8 +36,9 @@ default: build docker-push: docker docker push "${DOCKER_REPO}/tidb-operator:${IMAGE_TAG}" docker push "${DOCKER_REPO}/tidb-backup-manager:${IMAGE_TAG}" + docker push "${DOCKER_REPO}/br-federation-manager:${IMAGE_TAG}" -docker: operator-docker backup-docker +docker: operator-docker backup-docker br-federation-docker ifeq ($(NO_BUILD),y) operator-docker: @@ -51,7 +52,7 @@ else docker build --tag "${DOCKER_REPO}/tidb-operator:${IMAGE_TAG}" --build-arg=TARGETARCH=$(GOARCH) images/tidb-operator endif -build: controller-manager scheduler discovery admission-webhook backup-manager +build: controller-manager scheduler discovery admission-webhook backup-manager br-federation-manager controller-manager: ifeq ($(E2E),y) @@ -88,6 +89,13 @@ else $(GO_BUILD) -ldflags '$(LDFLAGS)' -o images/tidb-backup-manager/bin/$(GOARCH)/tidb-backup-manager cmd/backup-manager/main.go endif +br-federation-manager: +ifeq ($(E2E),y) + $(GO_TEST) -ldflags '$(LDFLAGS)' -c -o images/br-federation-manager/bin/br-federation-manager ./cmd/br-federation-manager +else + $(GO_BUILD) -ldflags '$(LDFLAGS)' -o images/br-federation-manager/bin/$(GOARCH)/br-federation-manager ./cmd/br-federation-manager +endif + ifeq ($(NO_BUILD),y) backup-docker: @echo "NO_BUILD=y, skip build for $@" @@ -100,6 +108,18 @@ else docker build --tag "${DOCKER_REPO}/tidb-backup-manager:${IMAGE_TAG}" --build-arg=TARGETARCH=$(GOARCH) images/tidb-backup-manager endif +ifeq ($(NO_BUILD),y) +br-federation-docker: + @echo "NO_BUILD=y, skip build for $@" +else +br-federation-docker: br-federation-manager +endif +ifeq ($(E2E),y) + docker build --tag "${DOCKER_REPO}/br-federation-manager:${IMAGE_TAG}" -f images/br-federation-manager/Dockerfile.e2e images/br-federation-manager +else + docker build --tag "${DOCKER_REPO}/br-federation-manager:${IMAGE_TAG}" --build-arg=TARGETARCH=$(GOARCH) images/br-federation-manager +endif + e2e-docker-push: e2e-docker docker push "${DOCKER_REPO}/tidb-operator-e2e:${IMAGE_TAG}" diff --git a/charts/br-federation/.helmignore b/charts/br-federation/.helmignore new file mode 100644 index 0000000000..f0c1319444 --- /dev/null +++ b/charts/br-federation/.helmignore @@ -0,0 +1,21 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/charts/br-federation/Chart.yaml b/charts/br-federation/Chart.yaml new file mode 100644 index 0000000000..be875dbf1f --- /dev/null +++ b/charts/br-federation/Chart.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +description: br-federation Helm chart for Kubernetes +name: br-federation +version: v1-canary +appVersion: v1-canary +home: https://github.com/pingcap/tidb-operator +sources: + - https://github.com/pingcap/tidb-operator +keywords: + - operator + - newsql + - htap + - database + - mysql + - raft +maintainers: +- name: csuzhangxc + email: zhangxuecheng@pingcap.com +- name: WangLe1321 + email: le.wang@pingcap.com diff --git a/charts/br-federation/templates/NOTES.txt b/charts/br-federation/templates/NOTES.txt new file mode 100644 index 0000000000..f2c0b39d78 --- /dev/null +++ b/charts/br-federation/templates/NOTES.txt @@ -0,0 +1,3 @@ +Make sure br-federation components are running: + + kubectl get pods --namespace {{ .Release.Namespace }} -l app.kubernetes.io/instance={{ .Release.Name }} diff --git a/charts/br-federation/templates/_helpers.tpl b/charts/br-federation/templates/_helpers.tpl new file mode 100644 index 0000000000..22e513b4cd --- /dev/null +++ b/charts/br-federation/templates/_helpers.tpl @@ -0,0 +1,24 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "chart.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +*/}} +{{- define "br-federation.fullname" -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "helm-toolkit.utils.template" -}} +{{- $name := index . 0 -}} +{{- $context := index . 1 -}} +{{- $last := base $context.Template.Name }} +{{- $wtf := $context.Template.Name | replace $last $name -}} +{{ include $wtf $context }} +{{- end }} diff --git a/charts/br-federation/templates/controller-manager-deployment.yaml b/charts/br-federation/templates/controller-manager-deployment.yaml new file mode 100644 index 0000000000..fa08cf741d --- /dev/null +++ b/charts/br-federation/templates/controller-manager-deployment.yaml @@ -0,0 +1,125 @@ +{{- if (hasKey .Values.brFederationManager "create" | ternary .Values.brFederationManager.create true) }} +apiVersion: apps/v1 +kind: Deployment +metadata: + {{- if eq .Values.appendReleaseSuffix true}} + name: br-federation-manager-{{.Release.Name }} + {{- else }} + name: br-federation-manager + {{- end }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ template "chart.name" . }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: br-federation-manager + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} +spec: + replicas: {{ .Values.brFederationManager.replicas }} + selector: + matchLabels: + app.kubernetes.io/name: {{ template "chart.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: br-federation-manager + template: + metadata: + labels: + app.kubernetes.io/name: {{ template "chart.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: br-federation-manager +{{- if .Values.brFederationManager.podAnnotations }} + annotations: +{{ toYaml .Values.brFederationManager.podAnnotations | indent 8 }} +{{ end }} + spec: + {{- if .Values.brFederationManager.serviceAccount }} + {{- if eq .Values.appendReleaseSuffix true}} + serviceAccount: {{ .Values.brFederationManager.serviceAccount }}-{{ .Release.Name }} + {{- else }} + serviceAccount: {{ .Values.brFederationManager.serviceAccount }} + {{- end }} + {{- end }} + {{- if .Values.imagePullSecrets }} + imagePullSecrets: + {{ toYaml .Values.imagePullSecrets | indent 6 }} + {{- end }} + containers: + - name: br-federation-manager + image: {{ .Values.image }} + imagePullPolicy: {{ .Values.imagePullPolicy | default "IfNotPresent" }} + {{- if .Values.brFederationManager.resources }} + resources: +{{ toYaml .Values.brFederationManager.resources | indent 12 }} + {{- end }} + livenessProbe: + tcpSocket: + port: 6060 + initialDelaySeconds: 30 + periodSeconds: 10 + failureThreshold: 10 + command: + - /usr/local/bin/br-federation-manager + - -v={{ .Values.brFederationManager.logLevel }} + {{- if .Values.brFederationManager.workers }} + - -workers={{ .Values.brFederationManager.workers | default 5 }} + {{- end }} + {{- if .Values.brFederationManager.leaderLeaseDuration }} + - -leader-lease-duration={{ .Values.brFederationManager.leaderLeaseDuration }} + {{- end }} + {{- if .Values.brFederationManager.leaderRenewDeadline }} + - -leader-renew-deadline={{ .Values.brFederationManager.leaderRenewDeadline }} + {{- end }} + {{- if .Values.brFederationManager.leaderRetryPeriod }} + - -leader-retry-period={{ .Values.brFederationManager.leaderRetryPeriod }} + {{- end }} + {{- if .Values.brFederationManager.kubeClientQPS }} + - -kube-client-qps={{ .Values.brFederationManager.kubeClientQPS }} + {{- end }} + {{- if .Values.brFederationManager.kubeClientBurst }} + - -kube-client-burst={{ .Values.brFederationManager.kubeClientBurst }} + {{- end }} + env: + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: TZ + value: {{ .Values.timezone | default "UTC" }} + {{- if eq .Values.appendReleaseSuffix true}} + - name: HELM_RELEASE + value: {{ .Release.Name }} + {{- end }} + {{- with .Values.brFederationManager.env }} +{{ toYaml . | indent 10 }} + {{- end }} + volumeMounts: + - name: federation-kubeconfig + mountPath: /etc/br-federation/federation-kubeconfig + readOnly: true + volumes: + - name: federation-kubeconfig + secret: + secretName: {{ .Values.brFederationManager.federationKubeconfigSecret }} + {{- with .Values.brFederationManager.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + + {{- with .Values.brFederationManager.affinity }} + affinity: +{{ toYaml . | indent 8 }} + {{- end }} + + {{- with .Values.brFederationManager.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} + + {{- if .Values.brFederationManager.priorityClassName }} + priorityClassName: {{ .Values.brFederationManager.priorityClassName }} + {{- end }} + {{- with .Values.brFederationManager.securityContext }} + securityContext: +{{ toYaml . | indent 8 }} + {{- end}} +{{- end }} diff --git a/charts/br-federation/templates/controller-manager-rbac.yaml b/charts/br-federation/templates/controller-manager-rbac.yaml new file mode 100644 index 0000000000..44e8ecb8b8 --- /dev/null +++ b/charts/br-federation/templates/controller-manager-rbac.yaml @@ -0,0 +1,58 @@ +{{- if and .Values.rbac.create (hasKey .Values.brFederationManager "create" | ternary .Values.brFederationManager.create true) }} +kind: ServiceAccount +apiVersion: v1 +metadata: + {{- if eq .Values.appendReleaseSuffix true}} + name: {{ .Values.brFederationManager.serviceAccount }}-{{ .Release.Name }} + {{- else }} + name: {{ .Values.brFederationManager.serviceAccount }} + {{- end }} + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ template "chart.name" . }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: br-federation-manager + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ .Release.Name }}:br-federation-manager + labels: + app.kubernetes.io/name: {{ template "chart.name" . }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: br-federation-manager + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} +rules: +- apiGroups: [""] + resources: ["endpoints"] + verbs: ["create", "get", "list", "watch", "update", "delete"] +- apiGroups: ["federation.pingcap.com"] + resources: ["*"] + verbs: ["*"] +--- +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ .Release.Name }}:br-federation-manager + labels: + app.kubernetes.io/name: {{ template "chart.name" . }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/component: br-federation-manager + helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} +subjects: +- kind: ServiceAccount + {{- if eq .Values.appendReleaseSuffix true}} + name: {{ .Values.brFederationManager.serviceAccount }}-{{ .Release.Name }} + {{- else }} + name: {{ .Values.brFederationManager.serviceAccount }} + {{- end }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: {{ .Release.Name }}:br-federation-manager + apiGroup: rbac.authorization.k8s.io +{{- end }} diff --git a/charts/br-federation/values.yaml b/charts/br-federation/values.yaml new file mode 100644 index 0000000000..3234847dc2 --- /dev/null +++ b/charts/br-federation/values.yaml @@ -0,0 +1,77 @@ +# Default values for br-federation + +rbac: + create: true + +# timezone is the default system timzone +timezone: UTC + +image: pingcap/br-federation-manager:v1.5.0-beta.1 +imagePullPolicy: IfNotPresent +# imagePullSecrets: [] + +appendReleaseSuffix: false + +brFederationManager: + create: true + # With rbac.create=false, the user is responsible for creating this account + # With rbac.create=true, this service account will be created + # Also see rbac.create + serviceAccount: br-federation-manager + + # Secret name of the kubeconfig for the federation Kubernetes clusters + # The data item key is the cluster name, and the data item value is the base64 encoded kubeconfig + federationKubeconfigSecret: br-federation-kubeconfig + + logLevel: 2 + replicas: 1 + resources: + requests: + cpu: 80m + memory: 50Mi + # REF: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/ + # priorityClassName: system-cluster-critical + + + # REF: https://pkg.go.dev/k8s.io/client-go/tools/leaderelection#LeaderElectionConfig + ## leaderLeaseDuration is the duration that non-leader candidates will wait to force acquire leadership + # leaderLeaseDuration: 15s + ## leaderRenewDeadline is the duration that the acting master will retry refreshing leadership before giving up + # leaderRenewDeadline: 10s + ## leaderRetryPeriod is the duration the LeaderElector clients should wait between tries of actions + # leaderRetryPeriod: 2s + + ## number of workers that are allowed to sync concurrently. default 5 + # workers: 5 + + ## affinity defines pod scheduling rules,affinity default settings is empty. + ## please read the affinity document before set your scheduling rule: + ## ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity + affinity: {} + ## nodeSelector ensure pods only assigning to nodes which have each of the indicated key-value pairs as labels + ## ref:https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector + nodeSelector: {} + ## Tolerations are applied to pods, and allow pods to schedule onto nodes with matching taints. + ## refer to https://kubernetes.io/docs/concepts/configuration/taint-and-toleration + tolerations: [] + ## Env define environments for the controller manager. + ## NOTE that the following env names is reserved: + ## - NAMESPACE + ## - TZ + ## - HELM_RELEASE + env: [] + # - name: AWS_REGION + # value: us-west-2 + # SecurityContext is security config of this component, it will set template.spec.securityContext + # Refer to https://kubernetes.io/docs/tasks/configure-pod-container/security-context + securityContext: {} + # runAsUser: 1000 + # runAsGroup: 2000 + # fsGroup: 2000 + # PodAnnotations will set template.metadata.annotations + # Refer to https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/ + podAnnotations: {} + ## KubeClientQPS indicates the maximum QPS to the kubenetes API server from client. + # kubeClientQPS: 5 + ## Maximum burst for throttle. + # kubeClientBurst: 10 diff --git a/cmd/br-federation-manager/main.go b/cmd/br-federation-manager/main.go new file mode 100644 index 0000000000..e562c5de77 --- /dev/null +++ b/cmd/br-federation-manager/main.go @@ -0,0 +1,263 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "context" + "flag" + "net/http" + _ "net/http/pprof" + "os" + "os/signal" + "path/filepath" + "reflect" + "syscall" + + "github.com/prometheus/client_golang/prometheus/promhttp" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/tools/leaderelection" + "k8s.io/client-go/tools/leaderelection/resourcelock" + "k8s.io/client-go/tools/record" + "k8s.io/component-base/logs" + "k8s.io/klog/v2" + "sigs.k8s.io/controller-runtime/pkg/client" + + fedversioned "github.com/pingcap/tidb-operator/pkg/client/clientset/versioned" + "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned" + "github.com/pingcap/tidb-operator/pkg/controller" + "github.com/pingcap/tidb-operator/pkg/controller/fedvolumebackup" + "github.com/pingcap/tidb-operator/pkg/controller/fedvolumebackupschedule" + "github.com/pingcap/tidb-operator/pkg/controller/fedvolumerestore" + "github.com/pingcap/tidb-operator/pkg/metrics" + "github.com/pingcap/tidb-operator/pkg/version" +) + +func main() { + var cfg *rest.Config + cliCfg := controller.DefaultBrFedCLIConfig() + cliCfg.AddFlag(flag.CommandLine) + flag.Parse() + + if cliCfg.PrintVersion { + version.PrintVersionInfo() + os.Exit(0) + } + + logs.InitLogs() + defer logs.FlushLogs() + + version.LogVersionInfo() + flag.VisitAll(func(flag *flag.Flag) { + klog.V(1).Infof("FLAG: --%s=%q", flag.Name, flag.Value) + }) + + hostName, err := os.Hostname() + if err != nil { + klog.Fatalf("failed to get hostname: %v", err) + } + + ns := os.Getenv("NAMESPACE") + if ns == "" { + klog.Fatal("NAMESPACE environment variable not set") + } + + helmRelease := os.Getenv("HELM_RELEASE") + if helmRelease == "" { + klog.Info("HELM_RELEASE environment variable not set") + } + + kubconfig := os.Getenv("KUBECONFIG") + if kubconfig != "" { + cfg, err = clientcmd.BuildConfigFromFlags("", kubconfig) + } else { + cfg, err = rest.InClusterConfig() + } + if err != nil { + klog.Fatalf("failed to get config: %v", err) + } + + // If they are zero, the created client will use the default values: 5, 10. + cfg.QPS = float32(cliCfg.KubeClientQPS) + cfg.Burst = cliCfg.KubeClientBurst + + cli, err := versioned.NewForConfig(cfg) + if err != nil { + klog.Fatalf("failed to create Clientset: %v", err) + } + var kubeCli kubernetes.Interface + kubeCli, err = kubernetes.NewForConfig(cfg) + if err != nil { + klog.Fatalf("failed to get kubernetes Clientset: %v", err) + } + // TODO: optimize the read of genericCli with the shared cache + genericCli, err := client.New(cfg, client.Options{Scheme: Scheme}) + if err != nil { + klog.Fatalf("failed to get the generic kube-apiserver client: %v", err) + } + + // init kube clients to the federation K8s clusters + fedClients, err := initFederationKubeClients(cliCfg) + if err != nil { + klog.Fatalf("failed to init federation kube clients: %v", err) + } + + deps := controller.NewBrFedDependencies(cliCfg, cli, kubeCli, genericCli, fedClients) + + onStarted := func(ctx context.Context) { + // Define some nested types to simplify the codebase + type Controller interface { + Run(int, <-chan struct{}) + Name() string + } + type InformerFactory interface { + Start(stopCh <-chan struct{}) + WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + } + + initMetrics := func(c Controller) { + metrics.ActiveWorkers.WithLabelValues(c.Name()).Set(0) + } + + // Initialize all controllers + controllers := []Controller{ + fedvolumebackup.NewController(deps), + fedvolumerestore.NewController(deps), + fedvolumebackupschedule.NewController(deps), + } + + // Start informer factories after all controllers are initialized. + informerFactories := []InformerFactory{ + deps.InformerFactory, + deps.KubeInformerFactory, + deps.LabelFilterKubeInformerFactory, + } + for _, f := range informerFactories { + f.Start(ctx.Done()) + for v, synced := range f.WaitForCacheSync(wait.NeverStop) { + if !synced { + klog.Fatalf("error syncing informer for %v", v) + } + } + } + klog.Info("cache of informer factories sync successfully") + + // Start syncLoop for all controllers + for _, controller := range controllers { + c := controller + initMetrics(c) + go wait.Forever(func() { c.Run(cliCfg.Workers, ctx.Done()) }, cliCfg.WaitDuration) + } + } + onStopped := func() { + klog.Fatal("leader election lost") + } + + endPointsName := "br-federation-manager" + if helmRelease != "" { + endPointsName += "-" + helmRelease + } + // leader election for multiple br-federation-manager instances + go wait.Forever(func() { + leaderelection.RunOrDie(context.TODO(), leaderelection.LeaderElectionConfig{ + Lock: &resourcelock.EndpointsLock{ + EndpointsMeta: metav1.ObjectMeta{ + Namespace: ns, + Name: endPointsName, + }, + Client: kubeCli.CoreV1(), + LockConfig: resourcelock.ResourceLockConfig{ + Identity: hostName, + EventRecorder: &record.FakeRecorder{}, + }, + }, + LeaseDuration: cliCfg.LeaseDuration, + RenewDeadline: cliCfg.RenewDeadline, + RetryPeriod: cliCfg.RetryPeriod, + Callbacks: leaderelection.LeaderCallbacks{ + OnStartedLeading: onStarted, + OnStoppedLeading: onStopped, + }, + }) + }, cliCfg.WaitDuration) + + srv := createHTTPServer() + sc := make(chan os.Signal, 1) + signal.Notify(sc, + syscall.SIGHUP, + syscall.SIGINT, + syscall.SIGTERM, + syscall.SIGQUIT, + ) + + go func() { + sig := <-sc + klog.Infof("got signal %s to exit", sig) + if err2 := srv.Shutdown(context.Background()); err2 != nil { + klog.Fatal("fail to shutdown the HTTP server", err2) + } + }() + + if err = srv.ListenAndServe(); err != http.ErrServerClosed { + klog.Fatal(err) + } + klog.Infof("br-federation-manager exited") +} + +func initFederationKubeClients(cliCfg *controller.BrFedCLIConfig) (map[string]*fedversioned.Clientset, error) { + files, err := os.ReadDir(cliCfg.FederationKubeConfigPath) + if err != nil { + return nil, err + } + + clients := make(map[string]*fedversioned.Clientset) + for _, f := range files { + if f.IsDir() || f.Name() == "..data" { + continue + } + + cfg, err := clientcmd.BuildConfigFromFlags("", filepath.Join(cliCfg.FederationKubeConfigPath, f.Name())) + if err != nil { + return nil, err // return error if any kube client init failed + } + + // we use the same QPS and Burst as for the API server which is running this manager now + cfg.QPS = float32(cliCfg.KubeClientQPS) + cfg.Burst = cliCfg.KubeClientBurst + + cli, err := fedversioned.NewForConfig(cfg) + if err != nil { + return nil, err + } + clients[f.Name()] = cli + } + + return clients, nil +} + +func createHTTPServer() *http.Server { + serverMux := http.NewServeMux() + // HTTP path for pprof + serverMux.Handle("/", http.DefaultServeMux) + // HTTP path for prometheus. + serverMux.Handle("/metrics", promhttp.Handler()) + + return &http.Server{ + Addr: ":6060", + Handler: serverMux, + } +} diff --git a/cmd/br-federation-manager/main_test.go b/cmd/br-federation-manager/main_test.go new file mode 100644 index 0000000000..7e639dc08a --- /dev/null +++ b/cmd/br-federation-manager/main_test.go @@ -0,0 +1,40 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "os" + "strings" + "testing" +) + +var _ = func() bool { + testing.Init() + return true +}() + +func TestRunMain(t *testing.T) { + var args []string + for _, arg := range os.Args { + switch { + case arg == "E2E": + case strings.HasPrefix(arg, "-test."): + default: + args = append(args, arg) + } + } + + os.Args = args + main() +} diff --git a/cmd/br-federation-manager/scheme.go b/cmd/br-federation-manager/scheme.go new file mode 100644 index 0000000000..277f03708d --- /dev/null +++ b/cmd/br-federation-manager/scheme.go @@ -0,0 +1,33 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + fedscheme "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + kubescheme "k8s.io/client-go/kubernetes/scheme" +) + +// Scheme gathers the schemes of native resources and custom resources used by br-federation-manager +// in favor of the generic controller-runtime/client +var Scheme = runtime.NewScheme() + +func init() { + v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(fedscheme.AddToScheme(Scheme)) + utilruntime.Must(kubescheme.AddToScheme(Scheme)) +} diff --git a/docs/api-references/federation-docs.md b/docs/api-references/federation-docs.md new file mode 100644 index 0000000000..8565e7d5f4 --- /dev/null +++ b/docs/api-references/federation-docs.md @@ -0,0 +1,454 @@ +--- +title: TiDB Operator API Document +summary: Reference of TiDB Operator API +category: how-to +--- +

API Document

+

federation.pingcap.com/v1alpha1

+Resource Types: + +

VolumeBackup

+

+

VolumeBackup is the control script’s spec

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+apiVersion
+string
+ +federation.pingcap.com/v1alpha1 + +
+kind
+string +
VolumeBackup
+metadata
+ + +Kubernetes meta/v1.ObjectMeta + + +
+Refer to the Kubernetes API documentation for the fields of the +metadata field. +
+spec
+ + +VolumeBackupSpec + + +
+
+
+ +
+
+status
+ + +VolumeBackupStatus + + +
+
+

VolumeBackupSchedule

+

+

VolumeBackupSchedule is the control script’s spec

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+apiVersion
+string
+ +federation.pingcap.com/v1alpha1 + +
+kind
+string +
VolumeBackupSchedule
+metadata
+ + +Kubernetes meta/v1.ObjectMeta + + +
+Refer to the Kubernetes API documentation for the fields of the +metadata field. +
+spec
+ + +VolumeBackupScheduleSpec + + +
+
+
+ +
+
+status
+ + +VolumeBackupScheduleStatus + + +
+
+

VolumeRestore

+

+

VolumeRestore is the control script’s spec

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+apiVersion
+string
+ +federation.pingcap.com/v1alpha1 + +
+kind
+string +
VolumeRestore
+metadata
+ + +Kubernetes meta/v1.ObjectMeta + + +
+Refer to the Kubernetes API documentation for the fields of the +metadata field. +
+spec
+ + +VolumeRestoreSpec + + +
+
+
+ +
+
+status
+ + +VolumeRestoreStatus + + +
+
+

VolumeBackupCondition

+

+(Appears on: +VolumeBackupStatus) +

+

+

VolumeBackupCondition describes the observed state of a VolumeBackup at a certain point.

+

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+status
+ + +Kubernetes core/v1.ConditionStatus + + +
+
+lastTransitionTime
+ + +Kubernetes meta/v1.Time + + +
+
+reason
+ +string + +
+
+message
+ +string + +
+
+

VolumeBackupScheduleSpec

+

+(Appears on: +VolumeBackupSchedule) +

+

+

VolumeBackupScheduleSpec describes the attributes that a user creates on a volume backup schedule.

+

+

VolumeBackupScheduleStatus

+

+(Appears on: +VolumeBackupSchedule) +

+

+

VolumeBackupScheduleStatus represents the current status of a volume backup schedule.

+

+

VolumeBackupSpec

+

+(Appears on: +VolumeBackup) +

+

+

VolumeBackupSpec describes the attributes that a user creates on a volume backup.

+

+

VolumeBackupStatus

+

+(Appears on: +VolumeBackup) +

+

+

VolumeBackupStatus represents the current status of a volume backup.

+

+ + + + + + + + + + + + + +
FieldDescription
+conditions
+ + +[]VolumeBackupCondition + + +
+
+

VolumeRestoreCondition

+

+(Appears on: +VolumeRestoreStatus) +

+

+

VolumeRestoreCondition describes the observed state of a VolumeRestore at a certain point.

+

+ + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+status
+ + +Kubernetes core/v1.ConditionStatus + + +
+
+lastTransitionTime
+ + +Kubernetes meta/v1.Time + + +
+
+reason
+ +string + +
+
+message
+ +string + +
+
+

VolumeRestoreSpec

+

+(Appears on: +VolumeRestore) +

+

+

VolumeRestoreSpec describes the attributes that a user creates on a volume restore.

+

+

VolumeRestoreStatus

+

+(Appears on: +VolumeRestore) +

+

+

VolumeRestoreStatus represents the current status of a volume restore.

+

+ + + + + + + + + + + + + +
FieldDescription
+conditions
+ + +[]VolumeRestoreCondition + + +
+
+
+

+Generated with gen-crd-api-reference-docs +

diff --git a/hack/update-api-references.sh b/hack/update-api-references.sh index fb9d0fdc62..44da3c360e 100755 --- a/hack/update-api-references.sh +++ b/hack/update-api-references.sh @@ -25,6 +25,8 @@ source hack/lib.sh hack::ensure_gen_crd_api_references_docs DOCS_PATH="$ROOT/docs/api-references" + +echo "Generating API references docs ..." API_DIR="${ROOT}/pkg/apis/pingcap/v1alpha1" pushd ${API_DIR} >/dev/null @@ -34,3 +36,14 @@ pushd ${API_DIR} >/dev/null -api-dir "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" \ -out-file "$DOCS_PATH/docs.md" popd >/dev/null + +echo "Generating API references docs for federation ..." +API_DIR="${ROOT}/pkg/apis/federation/pingcap/v1alpha1" + +pushd ${API_DIR} >/dev/null + GOROOT=$(go env GOROOT) ${DOCS_BIN} \ + -config "$DOCS_PATH/config.json" \ + -template-dir "$DOCS_PATH/template" \ + -api-dir "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" \ + -out-file "$DOCS_PATH/federation-docs.md" +popd >/dev/null diff --git a/hack/update-codegen.sh b/hack/update-codegen.sh index fdd6ee29d9..c085ae41dd 100755 --- a/hack/update-codegen.sh +++ b/hack/update-codegen.sh @@ -31,5 +31,12 @@ GOBIN=$OUTPUT_BIN bash $ROOT/hack/generate-groups.sh "deepcopy,client,informer,l --output-base $ROOT \ --go-header-file ./hack/boilerplate/boilerplate.generatego.txt +GOBIN=$OUTPUT_BIN bash $ROOT/hack/generate-groups.sh "deepcopy,client,informer,lister" \ + github.com/pingcap/tidb-operator/pkg/client/federation \ + github.com/pingcap/tidb-operator/pkg/apis/federation \ + pingcap:v1alpha1 \ + --output-base $ROOT \ + --go-header-file ./hack/boilerplate/boilerplate.generatego.txt + # then we merge generated code with our code base and clean up cp -r github.com/pingcap/tidb-operator/pkg $ROOT && rm -rf github.com diff --git a/hack/update-crd.sh b/hack/update-crd.sh index 55b5f0e29a..05d09b2a83 100755 --- a/hack/update-crd.sh +++ b/hack/update-crd.sh @@ -28,7 +28,9 @@ source hack/lib.sh CONTROLLER_GEN=${OUTPUT_BIN}/controller-gen hack::ensure_controller_gen -API_PACKAGES="github.com/pingcap/tidb-operator/pkg/apis/..." +echo "Generating CRDs ..." + +API_PACKAGES="github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1/..." CRD_OUTPUT_DIR=${ROOT}/manifests/crd CRD_OPTIONS="preserveUnknownFields=false,allowDangerousTypes=true,maxDescLen=0" @@ -50,3 +52,30 @@ done # merge all CRDs find ${CRD_OUTPUT_DIR}/v1 -name "*.yaml" | sort | xargs cat > ${ROOT}/manifests/crd.yaml find ${CRD_OUTPUT_DIR}/v1beta1 -name "*.yaml" | sort | xargs cat > ${ROOT}/manifests/crd_v1beta1.yaml + + +# generate CRDs for federation into separate files so that most users don't need to install them +echo "Generating CRDs for federation ..." + +API_PACKAGES="github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1/..." +CRD_OUTPUT_DIR=${ROOT}/manifests/crd/federation +CRD_OPTIONS="preserveUnknownFields=false,allowDangerousTypes=true,maxDescLen=0" + +# generate CRDs +${CONTROLLER_GEN} \ + crd:crdVersions=v1beta1,${CRD_OPTIONS} \ + paths=${API_PACKAGES} \ + output:crd:dir=${CRD_OUTPUT_DIR}/v1beta1 +${CONTROLLER_GEN} \ + crd:crdVersions=v1,${CRD_OPTIONS} \ + paths=${API_PACKAGES} \ + output:crd:dir=${CRD_OUTPUT_DIR}/v1 + +for file in ${SKIP_CRD_FILES[@]}; do + rm -f ${CRD_OUTPUT_DIR}/v1beta1/${file} + rm -f ${CRD_OUTPUT_DIR}/v1/${file} +done + +# merge all CRDs +find ${CRD_OUTPUT_DIR}/v1 -name "*.yaml" | sort | xargs cat > ${ROOT}/manifests/federation-crd.yaml +find ${CRD_OUTPUT_DIR}/v1beta1 -name "*.yaml" | sort | xargs cat > ${ROOT}/manifests/federation-crd_v1beta1.yaml diff --git a/hack/update-openapi-spec.sh b/hack/update-openapi-spec.sh index beba384ef9..7c678f5667 100755 --- a/hack/update-openapi-spec.sh +++ b/hack/update-openapi-spec.sh @@ -26,3 +26,7 @@ hack::ensure_openapi $OUTPUT_BIN/openapi-gen --go-header-file=./hack/boilerplate/boilerplate.generatego.txt \ -i github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1,k8s.io/apimachinery/pkg/apis/meta/v1,k8s.io/api/core/v1 \ -p apis/pingcap/v1alpha1 -O openapi_generated -o ./pkg + +$OUTPUT_BIN/openapi-gen --go-header-file=./hack/boilerplate/boilerplate.generatego.txt \ + -i github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1 \ + -p apis/federation/pingcap/v1alpha1 -O openapi_generated -o ./pkg diff --git a/hack/verify-api-references.sh b/hack/verify-api-references.sh index a58e009c42..74a665ac10 100755 --- a/hack/verify-api-references.sh +++ b/hack/verify-api-references.sh @@ -23,9 +23,13 @@ cd $ROOT targetDocs="$ROOT/docs/api-references/docs.md" verifyDocs_tmp=$(mktemp) trap "rm -f $verifyDocs_tmp" EXIT - cp "$targetDocs" "${verifyDocs_tmp}" +targetFedDocs="$ROOT/docs/api-references/federation-docs.md" +verifyFedDocs_tmp=$(mktemp) +trap "rm -f $verifyFedDocs_tmp" EXIT +cp "$targetFedDocs" "${verifyFedDocs_tmp}" + hack/update-api-references.sh echo "diffing $targetDocs with $verifyDocs_tmp" >&2 @@ -36,3 +40,13 @@ if [[ -n "${diff}" ]]; then echo "Run ./hack/update-api-references.sh" >&2 exit 1 fi + +# verify for federation +echo "diffing $targetFedDocs with $verifyFedDocs_tmp" >&2 +diff=$(diff "$targetFedDocs" "$verifyFedDocs_tmp") || true +if [[ -n "${diff}" ]]; then + echo "${diff}" >&2 + echo >&2 + echo "Run ./hack/update-api-references.sh" >&2 + exit 1 +fi diff --git a/hack/verify-crd.sh b/hack/verify-crd.sh index 8c7ed46bee..6f956d716f 100755 --- a/hack/verify-crd.sh +++ b/hack/verify-crd.sh @@ -41,3 +41,19 @@ for version in v1beta1 v1; do fi done done + +# verify for federation +for version in v1beta1 v1; do + for file in `ls $TARGET_DIR/federation/$version`; do + targetFile=$TARGET_DIR/federation/$version/$file + verifyFile=$VERIFY_TMP_DIR/federation/$version/$file + echo "diffing $targetFile with $verifyFile" >&2 + diff=$(diff "$targetFile" "$verifyFile") || true + if [[ -n "${diff}" ]]; then + echo "${diff}" >&2 + echo >&2 + echo "Run ./hack/update-crd.sh" >&2 + exit 1 + fi + done +done diff --git a/hack/verify-openapi-spec.sh b/hack/verify-openapi-spec.sh index bd23bd974c..16cc9d21c0 100755 --- a/hack/verify-openapi-spec.sh +++ b/hack/verify-openapi-spec.sh @@ -23,9 +23,13 @@ cd $ROOT target="pkg/apis/pingcap/v1alpha1/openapi_generated.go" verify_tmp=$(mktemp) trap "rm -f $verify_tmp" EXIT - cp "$target" "${verify_tmp}" +targetFed="pkg/apis/federation/pingcap/v1alpha1/openapi_generated.go" +verifyFed_tmp=$(mktemp) +trap "rm -f $verifyFed_tmp" EXIT +cp "$targetFed" "${verifyFed_tmp}" + hack/update-openapi-spec.sh echo "diffing $target with $verify_tmp" >&2 @@ -36,3 +40,12 @@ if [[ -n "${diff}" ]]; then echo "Run ./hack/update-openapi-spec.sh" >&2 exit 1 fi + +echo "diffing $targetFed with $verifyFed_tmp" >&2 +diff=$(diff "$targetFed" "$verifyFed_tmp") || true +if [[ -n "${diff}" ]]; then + echo "${diff}" >&2 + echo >&2 + echo "Run ./hack/update-openapi-spec.sh" >&2 + exit 1 +fi diff --git a/images/br-federation-manager/Dockerfile b/images/br-federation-manager/Dockerfile new file mode 100644 index 0000000000..9ae82b78b2 --- /dev/null +++ b/images/br-federation-manager/Dockerfile @@ -0,0 +1,5 @@ +FROM alpine:3.14 + +ARG TARGETARCH +RUN apk add tzdata bind-tools --no-cache +ADD bin/${TARGETARCH}/br-federation-manager /usr/local/bin/br-federation-manager diff --git a/images/br-federation-manager/Dockerfile.e2e b/images/br-federation-manager/Dockerfile.e2e new file mode 100644 index 0000000000..3bc5cb9756 --- /dev/null +++ b/images/br-federation-manager/Dockerfile.e2e @@ -0,0 +1,5 @@ +FROM alpine:3.14 + +ARG TARGETARCH +RUN apk add tzdata bind-tools --no-cache +ADD bin/br-federation-manager /usr/local/bin/br-federation-manager diff --git a/manifests/crd/federation/v1/federation.pingcap.com_volumebackups.yaml b/manifests/crd/federation/v1/federation.pingcap.com_volumebackups.yaml new file mode 100644 index 0000000000..0ee18b3336 --- /dev/null +++ b/manifests/crd/federation/v1/federation.pingcap.com_volumebackups.yaml @@ -0,0 +1,65 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: volumebackups.federation.pingcap.com +spec: + group: federation.pingcap.com + names: + kind: VolumeBackup + listKind: VolumeBackupList + plural: volumebackups + shortNames: + - vbk + singular: volumebackup + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + type: object + status: + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + nullable: true + type: string + message: + type: string + reason: + type: string + status: + type: string + required: + - status + type: object + nullable: true + type: array + type: object + required: + - metadata + - spec + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/manifests/crd/federation/v1/federation.pingcap.com_volumebackupschedules.yaml b/manifests/crd/federation/v1/federation.pingcap.com_volumebackupschedules.yaml new file mode 100644 index 0000000000..748bab61d9 --- /dev/null +++ b/manifests/crd/federation/v1/federation.pingcap.com_volumebackupschedules.yaml @@ -0,0 +1,46 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: volumebackupschedules.federation.pingcap.com +spec: + group: federation.pingcap.com + names: + kind: VolumeBackupSchedule + listKind: VolumeBackupScheduleList + plural: volumebackupschedules + shortNames: + - vbks + singular: volumebackupschedule + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + type: object + status: + type: object + required: + - metadata + - spec + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/manifests/crd/federation/v1/federation.pingcap.com_volumerestores.yaml b/manifests/crd/federation/v1/federation.pingcap.com_volumerestores.yaml new file mode 100644 index 0000000000..3f57ee7f5a --- /dev/null +++ b/manifests/crd/federation/v1/federation.pingcap.com_volumerestores.yaml @@ -0,0 +1,65 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: volumerestores.federation.pingcap.com +spec: + group: federation.pingcap.com + names: + kind: VolumeRestore + listKind: VolumeRestoreList + plural: volumerestores + shortNames: + - vrt + singular: volumerestore + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + type: object + status: + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + nullable: true + type: string + message: + type: string + reason: + type: string + status: + type: string + required: + - status + type: object + nullable: true + type: array + type: object + required: + - metadata + - spec + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/manifests/crd/federation/v1beta1/federation.pingcap.com_volumebackups.yaml b/manifests/crd/federation/v1beta1/federation.pingcap.com_volumebackups.yaml new file mode 100644 index 0000000000..546fc9a90b --- /dev/null +++ b/manifests/crd/federation/v1beta1/federation.pingcap.com_volumebackups.yaml @@ -0,0 +1,67 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: volumebackups.federation.pingcap.com +spec: + group: federation.pingcap.com + names: + kind: VolumeBackup + listKind: VolumeBackupList + plural: volumebackups + shortNames: + - vbk + singular: volumebackup + preserveUnknownFields: false + scope: Namespaced + validation: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + type: object + status: + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + nullable: true + type: string + message: + type: string + reason: + type: string + status: + type: string + required: + - status + type: object + nullable: true + type: array + type: object + required: + - metadata + - spec + type: object + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/manifests/crd/federation/v1beta1/federation.pingcap.com_volumebackupschedules.yaml b/manifests/crd/federation/v1beta1/federation.pingcap.com_volumebackupschedules.yaml new file mode 100644 index 0000000000..29d26b06e9 --- /dev/null +++ b/manifests/crd/federation/v1beta1/federation.pingcap.com_volumebackupschedules.yaml @@ -0,0 +1,48 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: volumebackupschedules.federation.pingcap.com +spec: + group: federation.pingcap.com + names: + kind: VolumeBackupSchedule + listKind: VolumeBackupScheduleList + plural: volumebackupschedules + shortNames: + - vbks + singular: volumebackupschedule + preserveUnknownFields: false + scope: Namespaced + validation: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + type: object + status: + type: object + required: + - metadata + - spec + type: object + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/manifests/crd/federation/v1beta1/federation.pingcap.com_volumerestores.yaml b/manifests/crd/federation/v1beta1/federation.pingcap.com_volumerestores.yaml new file mode 100644 index 0000000000..2d31fb2c84 --- /dev/null +++ b/manifests/crd/federation/v1beta1/federation.pingcap.com_volumerestores.yaml @@ -0,0 +1,67 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: volumerestores.federation.pingcap.com +spec: + group: federation.pingcap.com + names: + kind: VolumeRestore + listKind: VolumeRestoreList + plural: volumerestores + shortNames: + - vrt + singular: volumerestore + preserveUnknownFields: false + scope: Namespaced + validation: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + type: object + status: + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + nullable: true + type: string + message: + type: string + reason: + type: string + status: + type: string + required: + - status + type: object + nullable: true + type: array + type: object + required: + - metadata + - spec + type: object + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/manifests/federation-crd.yaml b/manifests/federation-crd.yaml new file mode 100644 index 0000000000..52b8a31bab --- /dev/null +++ b/manifests/federation-crd.yaml @@ -0,0 +1,176 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: volumebackups.federation.pingcap.com +spec: + group: federation.pingcap.com + names: + kind: VolumeBackup + listKind: VolumeBackupList + plural: volumebackups + shortNames: + - vbk + singular: volumebackup + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + type: object + status: + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + nullable: true + type: string + message: + type: string + reason: + type: string + status: + type: string + required: + - status + type: object + nullable: true + type: array + type: object + required: + - metadata + - spec + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: volumebackupschedules.federation.pingcap.com +spec: + group: federation.pingcap.com + names: + kind: VolumeBackupSchedule + listKind: VolumeBackupScheduleList + plural: volumebackupschedules + shortNames: + - vbks + singular: volumebackupschedule + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + type: object + status: + type: object + required: + - metadata + - spec + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: volumerestores.federation.pingcap.com +spec: + group: federation.pingcap.com + names: + kind: VolumeRestore + listKind: VolumeRestoreList + plural: volumerestores + shortNames: + - vrt + singular: volumerestore + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + type: object + status: + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + nullable: true + type: string + message: + type: string + reason: + type: string + status: + type: string + required: + - status + type: object + nullable: true + type: array + type: object + required: + - metadata + - spec + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/manifests/federation-crd_v1beta1.yaml b/manifests/federation-crd_v1beta1.yaml new file mode 100644 index 0000000000..9439e128a6 --- /dev/null +++ b/manifests/federation-crd_v1beta1.yaml @@ -0,0 +1,182 @@ + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: volumebackups.federation.pingcap.com +spec: + group: federation.pingcap.com + names: + kind: VolumeBackup + listKind: VolumeBackupList + plural: volumebackups + shortNames: + - vbk + singular: volumebackup + preserveUnknownFields: false + scope: Namespaced + validation: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + type: object + status: + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + nullable: true + type: string + message: + type: string + reason: + type: string + status: + type: string + required: + - status + type: object + nullable: true + type: array + type: object + required: + - metadata + - spec + type: object + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: volumebackupschedules.federation.pingcap.com +spec: + group: federation.pingcap.com + names: + kind: VolumeBackupSchedule + listKind: VolumeBackupScheduleList + plural: volumebackupschedules + shortNames: + - vbks + singular: volumebackupschedule + preserveUnknownFields: false + scope: Namespaced + validation: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + type: object + status: + type: object + required: + - metadata + - spec + type: object + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] + +--- +apiVersion: apiextensions.k8s.io/v1beta1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.6.2 + creationTimestamp: null + name: volumerestores.federation.pingcap.com +spec: + group: federation.pingcap.com + names: + kind: VolumeRestore + listKind: VolumeRestoreList + plural: volumerestores + shortNames: + - vrt + singular: volumerestore + preserveUnknownFields: false + scope: Namespaced + validation: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + type: object + status: + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + nullable: true + type: string + message: + type: string + reason: + type: string + status: + type: string + required: + - status + type: object + nullable: true + type: array + type: object + required: + - metadata + - spec + type: object + version: v1alpha1 + versions: + - name: v1alpha1 + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/pkg/apis/federation/pingcap/v1alpha1/doc.go b/pkg/apis/federation/pingcap/v1alpha1/doc.go new file mode 100644 index 0000000000..b34cfdc624 --- /dev/null +++ b/pkg/apis/federation/pingcap/v1alpha1/doc.go @@ -0,0 +1,21 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// +k8s:deepcopy-gen=package,register + +// Package v1alpha1 is the v1alpha1 version of the federation API. +// +groupName=federation.pingcap.com + +// We use a separate package for federation so that most users do not need to install these CRDs. + +package v1alpha1 diff --git a/pkg/apis/federation/pingcap/v1alpha1/openapi_generated.go b/pkg/apis/federation/pingcap/v1alpha1/openapi_generated.go new file mode 100644 index 0000000000..47520f4712 --- /dev/null +++ b/pkg/apis/federation/pingcap/v1alpha1/openapi_generated.go @@ -0,0 +1,328 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by openapi-gen. DO NOT EDIT. + +// This file was autogenerated by openapi-gen. Do not edit it manually! + +package v1alpha1 + +import ( + spec "github.com/go-openapi/spec" + common "k8s.io/kube-openapi/pkg/common" +) + +func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { + return map[string]common.OpenAPIDefinition{ + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeBackup": schema_apis_federation_pingcap_v1alpha1_VolumeBackup(ref), + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeBackupList": schema_apis_federation_pingcap_v1alpha1_VolumeBackupList(ref), + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeBackupSchedule": schema_apis_federation_pingcap_v1alpha1_VolumeBackupSchedule(ref), + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeBackupScheduleList": schema_apis_federation_pingcap_v1alpha1_VolumeBackupScheduleList(ref), + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeBackupScheduleSpec": schema_apis_federation_pingcap_v1alpha1_VolumeBackupScheduleSpec(ref), + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeBackupSpec": schema_apis_federation_pingcap_v1alpha1_VolumeBackupSpec(ref), + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeRestore": schema_apis_federation_pingcap_v1alpha1_VolumeRestore(ref), + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeRestoreList": schema_apis_federation_pingcap_v1alpha1_VolumeRestoreList(ref), + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeRestoreSpec": schema_apis_federation_pingcap_v1alpha1_VolumeRestoreSpec(ref), + } +} + +func schema_apis_federation_pingcap_v1alpha1_VolumeBackup(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "VolumeBackup is the control script's spec", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeBackupSpec"), + }, + }, + }, + Required: []string{"spec"}, + }, + }, + Dependencies: []string{ + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeBackupSpec"}, + } +} + +func schema_apis_federation_pingcap_v1alpha1_VolumeBackupList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "VolumeBackupList is VolumeBackup list", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeBackup"), + }, + }, + }, + }, + }, + }, + Required: []string{"metadata", "items"}, + }, + }, + Dependencies: []string{ + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeBackup", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_apis_federation_pingcap_v1alpha1_VolumeBackupSchedule(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "VolumeBackupSchedule is the control script's spec", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeBackupScheduleSpec"), + }, + }, + }, + Required: []string{"spec"}, + }, + }, + Dependencies: []string{ + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeBackupScheduleSpec"}, + } +} + +func schema_apis_federation_pingcap_v1alpha1_VolumeBackupScheduleList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "VolumeBackupScheduleList is VolumeBackupSchedule list", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeBackupSchedule"), + }, + }, + }, + }, + }, + }, + Required: []string{"metadata", "items"}, + }, + }, + Dependencies: []string{ + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeBackupSchedule", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_apis_federation_pingcap_v1alpha1_VolumeBackupScheduleSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "VolumeBackupScheduleSpec describes the attributes that a user creates on a volume backup schedule.", + Type: []string{"object"}, + }, + }, + } +} + +func schema_apis_federation_pingcap_v1alpha1_VolumeBackupSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "VolumeBackupSpec describes the attributes that a user creates on a volume backup.", + Type: []string{"object"}, + }, + }, + } +} + +func schema_apis_federation_pingcap_v1alpha1_VolumeRestore(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "VolumeRestore is the control script's spec", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeRestoreSpec"), + }, + }, + }, + Required: []string{"spec"}, + }, + }, + Dependencies: []string{ + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeRestoreSpec"}, + } +} + +func schema_apis_federation_pingcap_v1alpha1_VolumeRestoreList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "VolumeRestoreList is VolumeRestore list", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Description: "Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds", + Type: []string{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + Description: "APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources", + Type: []string{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeRestore"), + }, + }, + }, + }, + }, + }, + Required: []string{"metadata", "items"}, + }, + }, + Dependencies: []string{ + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1.VolumeRestore", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_apis_federation_pingcap_v1alpha1_VolumeRestoreSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "VolumeRestoreSpec describes the attributes that a user creates on a volume restore.", + Type: []string{"object"}, + }, + }, + } +} diff --git a/pkg/apis/federation/pingcap/v1alpha1/register.go b/pkg/apis/federation/pingcap/v1alpha1/register.go new file mode 100644 index 0000000000..ff96e7c772 --- /dev/null +++ b/pkg/apis/federation/pingcap/v1alpha1/register.go @@ -0,0 +1,63 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +var ( + // SchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + // AddToScheme applies all the stored functions to the scheme. + AddToScheme = localSchemeBuilder.AddToScheme + // Scheme is the scheme instance of operator + Scheme *runtime.Scheme + + groupName = "federation.pingcap.com" +) + +// SchemeGroupVersion is group version used to register these objects +var SchemeGroupVersion = schema.GroupVersion{Group: groupName, Version: "v1alpha1"} + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes) +} + +// Resource takes an unqualified resource and returns back a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +// Adds the list of known types to api.Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + Scheme = scheme + scheme.AddKnownTypes(SchemeGroupVersion, + &VolumeBackup{}, + &VolumeBackupList{}, + &VolumeBackupSchedule{}, + &VolumeBackupScheduleList{}, + &VolumeRestore{}, + &VolumeRestoreList{}, + ) + + metav1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/pkg/apis/federation/pingcap/v1alpha1/types.go b/pkg/apis/federation/pingcap/v1alpha1/types.go new file mode 100644 index 0000000000..8242b58c35 --- /dev/null +++ b/pkg/apis/federation/pingcap/v1alpha1/types.go @@ -0,0 +1,159 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package v1alpha1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// TODO(federation): add `kubebuilder:printcolumn` after fileds are defined + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VolumeBackup is the control script's spec +// +// +k8s:openapi-gen=true +// +kubebuilder:resource:shortName="vbk" +// +genclient:noStatus +type VolumeBackup struct { + metav1.TypeMeta `json:",inline"` + // +k8s:openapi-gen=false + metav1.ObjectMeta `json:"metadata"` + + Spec VolumeBackupSpec `json:"spec"` + + // +k8s:openapi-gen=false + Status VolumeBackupStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VolumeBackupList is VolumeBackup list +// +k8s:openapi-gen=true +type VolumeBackupList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + Items []VolumeBackup `json:"items"` +} + +// VolumeBackupSpec describes the attributes that a user creates on a volume backup. +// +k8s:openapi-gen=true +type VolumeBackupSpec struct { +} + +// VolumeBackupStatus represents the current status of a volume backup. +type VolumeBackupStatus struct { + // +nullable + Conditions []VolumeBackupCondition `json:"conditions,omitempty"` +} + +// VolumeBackupCondition describes the observed state of a VolumeBackup at a certain point. +type VolumeBackupCondition struct { + Status corev1.ConditionStatus `json:"status"` + + // +nullable + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + Reason string `json:"reason,omitempty"` + Message string `json:"message,omitempty"` +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VolumeBackupSchedule is the control script's spec +// +// +k8s:openapi-gen=true +// +kubebuilder:resource:shortName="vbks" +// +genclient:noStatus +type VolumeBackupSchedule struct { + metav1.TypeMeta `json:",inline"` + // +k8s:openapi-gen=false + metav1.ObjectMeta `json:"metadata"` + + Spec VolumeBackupScheduleSpec `json:"spec"` + + // +k8s:openapi-gen=false + Status VolumeBackupScheduleStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VolumeBackupScheduleList is VolumeBackupSchedule list +// +k8s:openapi-gen=true +type VolumeBackupScheduleList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + Items []VolumeBackupSchedule `json:"items"` +} + +// VolumeBackupScheduleSpec describes the attributes that a user creates on a volume backup schedule. +// +k8s:openapi-gen=true +type VolumeBackupScheduleSpec struct { +} + +// VolumeBackupScheduleStatus represents the current status of a volume backup schedule. +type VolumeBackupScheduleStatus struct { +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VolumeRestore is the control script's spec +// +// +k8s:openapi-gen=true +// +kubebuilder:resource:shortName="vrt" +// +genclient:noStatus +type VolumeRestore struct { + metav1.TypeMeta `json:",inline"` + // +k8s:openapi-gen=false + metav1.ObjectMeta `json:"metadata"` + + Spec VolumeRestoreSpec `json:"spec"` + + // +k8s:openapi-gen=false + Status VolumeRestoreStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// VolumeRestoreList is VolumeRestore list +// +k8s:openapi-gen=true +type VolumeRestoreList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata"` + Items []VolumeRestore `json:"items"` +} + +// VolumeRestoreSpec describes the attributes that a user creates on a volume restore. +// +k8s:openapi-gen=true +type VolumeRestoreSpec struct { +} + +// VolumeRestoreStatus represents the current status of a volume restore. +type VolumeRestoreStatus struct { + // +nullable + Conditions []VolumeRestoreCondition `json:"conditions,omitempty"` +} + +// VolumeRestoreCondition describes the observed state of a VolumeRestore at a certain point. +type VolumeRestoreCondition struct { + Status corev1.ConditionStatus `json:"status"` + + // +nullable + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` + Reason string `json:"reason,omitempty"` + Message string `json:"message,omitempty"` +} diff --git a/pkg/apis/federation/pingcap/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/federation/pingcap/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..6eeccc0ef7 --- /dev/null +++ b/pkg/apis/federation/pingcap/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,350 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by deepcopy-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeBackup) DeepCopyInto(out *VolumeBackup) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeBackup. +func (in *VolumeBackup) DeepCopy() *VolumeBackup { + if in == nil { + return nil + } + out := new(VolumeBackup) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VolumeBackup) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeBackupCondition) DeepCopyInto(out *VolumeBackupCondition) { + *out = *in + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeBackupCondition. +func (in *VolumeBackupCondition) DeepCopy() *VolumeBackupCondition { + if in == nil { + return nil + } + out := new(VolumeBackupCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeBackupList) DeepCopyInto(out *VolumeBackupList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VolumeBackup, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeBackupList. +func (in *VolumeBackupList) DeepCopy() *VolumeBackupList { + if in == nil { + return nil + } + out := new(VolumeBackupList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VolumeBackupList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeBackupSchedule) DeepCopyInto(out *VolumeBackupSchedule) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + out.Status = in.Status + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeBackupSchedule. +func (in *VolumeBackupSchedule) DeepCopy() *VolumeBackupSchedule { + if in == nil { + return nil + } + out := new(VolumeBackupSchedule) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VolumeBackupSchedule) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeBackupScheduleList) DeepCopyInto(out *VolumeBackupScheduleList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VolumeBackupSchedule, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeBackupScheduleList. +func (in *VolumeBackupScheduleList) DeepCopy() *VolumeBackupScheduleList { + if in == nil { + return nil + } + out := new(VolumeBackupScheduleList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VolumeBackupScheduleList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeBackupScheduleSpec) DeepCopyInto(out *VolumeBackupScheduleSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeBackupScheduleSpec. +func (in *VolumeBackupScheduleSpec) DeepCopy() *VolumeBackupScheduleSpec { + if in == nil { + return nil + } + out := new(VolumeBackupScheduleSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeBackupScheduleStatus) DeepCopyInto(out *VolumeBackupScheduleStatus) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeBackupScheduleStatus. +func (in *VolumeBackupScheduleStatus) DeepCopy() *VolumeBackupScheduleStatus { + if in == nil { + return nil + } + out := new(VolumeBackupScheduleStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeBackupSpec) DeepCopyInto(out *VolumeBackupSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeBackupSpec. +func (in *VolumeBackupSpec) DeepCopy() *VolumeBackupSpec { + if in == nil { + return nil + } + out := new(VolumeBackupSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeBackupStatus) DeepCopyInto(out *VolumeBackupStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]VolumeBackupCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeBackupStatus. +func (in *VolumeBackupStatus) DeepCopy() *VolumeBackupStatus { + if in == nil { + return nil + } + out := new(VolumeBackupStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeRestore) DeepCopyInto(out *VolumeRestore) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeRestore. +func (in *VolumeRestore) DeepCopy() *VolumeRestore { + if in == nil { + return nil + } + out := new(VolumeRestore) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VolumeRestore) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeRestoreCondition) DeepCopyInto(out *VolumeRestoreCondition) { + *out = *in + in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeRestoreCondition. +func (in *VolumeRestoreCondition) DeepCopy() *VolumeRestoreCondition { + if in == nil { + return nil + } + out := new(VolumeRestoreCondition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeRestoreList) DeepCopyInto(out *VolumeRestoreList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]VolumeRestore, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeRestoreList. +func (in *VolumeRestoreList) DeepCopy() *VolumeRestoreList { + if in == nil { + return nil + } + out := new(VolumeRestoreList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *VolumeRestoreList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeRestoreSpec) DeepCopyInto(out *VolumeRestoreSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeRestoreSpec. +func (in *VolumeRestoreSpec) DeepCopy() *VolumeRestoreSpec { + if in == nil { + return nil + } + out := new(VolumeRestoreSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VolumeRestoreStatus) DeepCopyInto(out *VolumeRestoreStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]VolumeRestoreCondition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VolumeRestoreStatus. +func (in *VolumeRestoreStatus) DeepCopy() *VolumeRestoreStatus { + if in == nil { + return nil + } + out := new(VolumeRestoreStatus) + in.DeepCopyInto(out) + return out +} diff --git a/pkg/apis/label/label.go b/pkg/apis/label/label.go index c0311bdce4..e6957c88ee 100644 --- a/pkg/apis/label/label.go +++ b/pkg/apis/label/label.go @@ -59,7 +59,7 @@ const ( // RestoreLabelKey is restore key RestoreLabelKey string = "tidb.pingcap.com/restore" - // BackupProtectionFinalizer is the name of finalizer on backups + // BackupProtectionFinalizer is the name of finalizer on backups or federation backups BackupProtectionFinalizer string = "tidb.pingcap.com/backup-protection" // AutoScalingGroupLabelKey describes the autoscaling group of the TiDB diff --git a/pkg/client/federation/clientset/versioned/clientset.go b/pkg/client/federation/clientset/versioned/clientset.go new file mode 100644 index 0000000000..c0c2fe3d0c --- /dev/null +++ b/pkg/client/federation/clientset/versioned/clientset.go @@ -0,0 +1,94 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package versioned + +import ( + "fmt" + + federationv1alpha1 "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1" + discovery "k8s.io/client-go/discovery" + rest "k8s.io/client-go/rest" + flowcontrol "k8s.io/client-go/util/flowcontrol" +) + +type Interface interface { + Discovery() discovery.DiscoveryInterface + FederationV1alpha1() federationv1alpha1.FederationV1alpha1Interface +} + +// Clientset contains the clients for groups. Each group has exactly one +// version included in a Clientset. +type Clientset struct { + *discovery.DiscoveryClient + federationV1alpha1 *federationv1alpha1.FederationV1alpha1Client +} + +// FederationV1alpha1 retrieves the FederationV1alpha1Client +func (c *Clientset) FederationV1alpha1() federationv1alpha1.FederationV1alpha1Interface { + return c.federationV1alpha1 +} + +// Discovery retrieves the DiscoveryClient +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + if c == nil { + return nil + } + return c.DiscoveryClient +} + +// NewForConfig creates a new Clientset for the given config. +// If config's RateLimiter is not set and QPS and Burst are acceptable, +// NewForConfig will generate a rate-limiter in configShallowCopy. +func NewForConfig(c *rest.Config) (*Clientset, error) { + configShallowCopy := *c + if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { + if configShallowCopy.Burst <= 0 { + return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0") + } + configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) + } + var cs Clientset + var err error + cs.federationV1alpha1, err = federationv1alpha1.NewForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + + cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfig(&configShallowCopy) + if err != nil { + return nil, err + } + return &cs, nil +} + +// NewForConfigOrDie creates a new Clientset for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *Clientset { + var cs Clientset + cs.federationV1alpha1 = federationv1alpha1.NewForConfigOrDie(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClientForConfigOrDie(c) + return &cs +} + +// New creates a new Clientset for the given RESTClient. +func New(c rest.Interface) *Clientset { + var cs Clientset + cs.federationV1alpha1 = federationv1alpha1.New(c) + + cs.DiscoveryClient = discovery.NewDiscoveryClient(c) + return &cs +} diff --git a/pkg/client/federation/clientset/versioned/doc.go b/pkg/client/federation/clientset/versioned/doc.go new file mode 100644 index 0000000000..19edbe1dd7 --- /dev/null +++ b/pkg/client/federation/clientset/versioned/doc.go @@ -0,0 +1,17 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated clientset. +package versioned diff --git a/pkg/client/federation/clientset/versioned/fake/clientset_generated.go b/pkg/client/federation/clientset/versioned/fake/clientset_generated.go new file mode 100644 index 0000000000..0ac7474689 --- /dev/null +++ b/pkg/client/federation/clientset/versioned/fake/clientset_generated.go @@ -0,0 +1,79 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + clientset "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned" + federationv1alpha1 "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1" + fakefederationv1alpha1 "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/fake" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/discovery" + fakediscovery "k8s.io/client-go/discovery/fake" + "k8s.io/client-go/testing" +) + +// NewSimpleClientset returns a clientset that will respond with the provided objects. +// It's backed by a very simple object tracker that processes creates, updates and deletions as-is, +// without applying any validations and/or defaults. It shouldn't be considered a replacement +// for a real clientset and is mostly useful in simple unit tests. +func NewSimpleClientset(objects ...runtime.Object) *Clientset { + o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) + for _, obj := range objects { + if err := o.Add(obj); err != nil { + panic(err) + } + } + + cs := &Clientset{tracker: o} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + gvr := action.GetResource() + ns := action.GetNamespace() + watch, err := o.Watch(gvr, ns) + if err != nil { + return false, nil, err + } + return true, watch, nil + }) + + return cs +} + +// Clientset implements clientset.Interface. Meant to be embedded into a +// struct to get a default implementation. This makes faking out just the method +// you want to test easier. +type Clientset struct { + testing.Fake + discovery *fakediscovery.FakeDiscovery + tracker testing.ObjectTracker +} + +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + return c.discovery +} + +func (c *Clientset) Tracker() testing.ObjectTracker { + return c.tracker +} + +var _ clientset.Interface = &Clientset{} + +// FederationV1alpha1 retrieves the FederationV1alpha1Client +func (c *Clientset) FederationV1alpha1() federationv1alpha1.FederationV1alpha1Interface { + return &fakefederationv1alpha1.FakeFederationV1alpha1{Fake: &c.Fake} +} diff --git a/pkg/client/federation/clientset/versioned/fake/doc.go b/pkg/client/federation/clientset/versioned/fake/doc.go new file mode 100644 index 0000000000..28ae66a70a --- /dev/null +++ b/pkg/client/federation/clientset/versioned/fake/doc.go @@ -0,0 +1,17 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated fake clientset. +package fake diff --git a/pkg/client/federation/clientset/versioned/fake/register.go b/pkg/client/federation/clientset/versioned/fake/register.go new file mode 100644 index 0000000000..99d6d46bdf --- /dev/null +++ b/pkg/client/federation/clientset/versioned/fake/register.go @@ -0,0 +1,53 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + federationv1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" +) + +var scheme = runtime.NewScheme() +var codecs = serializer.NewCodecFactory(scheme) + +var localSchemeBuilder = runtime.SchemeBuilder{ + federationv1alpha1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(scheme)) +} diff --git a/pkg/client/federation/clientset/versioned/scheme/doc.go b/pkg/client/federation/clientset/versioned/scheme/doc.go new file mode 100644 index 0000000000..c1f8b3a163 --- /dev/null +++ b/pkg/client/federation/clientset/versioned/scheme/doc.go @@ -0,0 +1,17 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +// This package contains the scheme of the automatically generated clientset. +package scheme diff --git a/pkg/client/federation/clientset/versioned/scheme/register.go b/pkg/client/federation/clientset/versioned/scheme/register.go new file mode 100644 index 0000000000..b21cdb06a2 --- /dev/null +++ b/pkg/client/federation/clientset/versioned/scheme/register.go @@ -0,0 +1,53 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package scheme + +import ( + federationv1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" +) + +var Scheme = runtime.NewScheme() +var Codecs = serializer.NewCodecFactory(Scheme) +var ParameterCodec = runtime.NewParameterCodec(Scheme) +var localSchemeBuilder = runtime.SchemeBuilder{ + federationv1alpha1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(Scheme)) +} diff --git a/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/doc.go b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/doc.go new file mode 100644 index 0000000000..4a7fe7662b --- /dev/null +++ b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/doc.go @@ -0,0 +1,17 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/fake/doc.go b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/fake/doc.go new file mode 100644 index 0000000000..385e3174d3 --- /dev/null +++ b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/fake/doc.go @@ -0,0 +1,17 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_pingcap_client.go b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_pingcap_client.go new file mode 100644 index 0000000000..40e7a119c3 --- /dev/null +++ b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_pingcap_client.go @@ -0,0 +1,45 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1alpha1 "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1" + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" +) + +type FakeFederationV1alpha1 struct { + *testing.Fake +} + +func (c *FakeFederationV1alpha1) VolumeBackups(namespace string) v1alpha1.VolumeBackupInterface { + return &FakeVolumeBackups{c, namespace} +} + +func (c *FakeFederationV1alpha1) VolumeBackupSchedules(namespace string) v1alpha1.VolumeBackupScheduleInterface { + return &FakeVolumeBackupSchedules{c, namespace} +} + +func (c *FakeFederationV1alpha1) VolumeRestores(namespace string) v1alpha1.VolumeRestoreInterface { + return &FakeVolumeRestores{c, namespace} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeFederationV1alpha1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_volumebackup.go b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_volumebackup.go new file mode 100644 index 0000000000..9fbcdb8b66 --- /dev/null +++ b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_volumebackup.go @@ -0,0 +1,127 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeVolumeBackups implements VolumeBackupInterface +type FakeVolumeBackups struct { + Fake *FakeFederationV1alpha1 + ns string +} + +var volumebackupsResource = schema.GroupVersionResource{Group: "federation.pingcap.com", Version: "v1alpha1", Resource: "volumebackups"} + +var volumebackupsKind = schema.GroupVersionKind{Group: "federation.pingcap.com", Version: "v1alpha1", Kind: "VolumeBackup"} + +// Get takes name of the volumeBackup, and returns the corresponding volumeBackup object, and an error if there is any. +func (c *FakeVolumeBackups) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.VolumeBackup, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(volumebackupsResource, c.ns, name), &v1alpha1.VolumeBackup{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.VolumeBackup), err +} + +// List takes label and field selectors, and returns the list of VolumeBackups that match those selectors. +func (c *FakeVolumeBackups) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.VolumeBackupList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(volumebackupsResource, volumebackupsKind, c.ns, opts), &v1alpha1.VolumeBackupList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.VolumeBackupList{ListMeta: obj.(*v1alpha1.VolumeBackupList).ListMeta} + for _, item := range obj.(*v1alpha1.VolumeBackupList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested volumeBackups. +func (c *FakeVolumeBackups) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(volumebackupsResource, c.ns, opts)) + +} + +// Create takes the representation of a volumeBackup and creates it. Returns the server's representation of the volumeBackup, and an error, if there is any. +func (c *FakeVolumeBackups) Create(ctx context.Context, volumeBackup *v1alpha1.VolumeBackup, opts v1.CreateOptions) (result *v1alpha1.VolumeBackup, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(volumebackupsResource, c.ns, volumeBackup), &v1alpha1.VolumeBackup{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.VolumeBackup), err +} + +// Update takes the representation of a volumeBackup and updates it. Returns the server's representation of the volumeBackup, and an error, if there is any. +func (c *FakeVolumeBackups) Update(ctx context.Context, volumeBackup *v1alpha1.VolumeBackup, opts v1.UpdateOptions) (result *v1alpha1.VolumeBackup, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(volumebackupsResource, c.ns, volumeBackup), &v1alpha1.VolumeBackup{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.VolumeBackup), err +} + +// Delete takes name of the volumeBackup and deletes it. Returns an error if one occurs. +func (c *FakeVolumeBackups) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(volumebackupsResource, c.ns, name), &v1alpha1.VolumeBackup{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeVolumeBackups) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(volumebackupsResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.VolumeBackupList{}) + return err +} + +// Patch applies the patch and returns the patched volumeBackup. +func (c *FakeVolumeBackups) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.VolumeBackup, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(volumebackupsResource, c.ns, name, pt, data, subresources...), &v1alpha1.VolumeBackup{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.VolumeBackup), err +} diff --git a/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_volumebackupschedule.go b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_volumebackupschedule.go new file mode 100644 index 0000000000..7431f7f560 --- /dev/null +++ b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_volumebackupschedule.go @@ -0,0 +1,127 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeVolumeBackupSchedules implements VolumeBackupScheduleInterface +type FakeVolumeBackupSchedules struct { + Fake *FakeFederationV1alpha1 + ns string +} + +var volumebackupschedulesResource = schema.GroupVersionResource{Group: "federation.pingcap.com", Version: "v1alpha1", Resource: "volumebackupschedules"} + +var volumebackupschedulesKind = schema.GroupVersionKind{Group: "federation.pingcap.com", Version: "v1alpha1", Kind: "VolumeBackupSchedule"} + +// Get takes name of the volumeBackupSchedule, and returns the corresponding volumeBackupSchedule object, and an error if there is any. +func (c *FakeVolumeBackupSchedules) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.VolumeBackupSchedule, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(volumebackupschedulesResource, c.ns, name), &v1alpha1.VolumeBackupSchedule{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.VolumeBackupSchedule), err +} + +// List takes label and field selectors, and returns the list of VolumeBackupSchedules that match those selectors. +func (c *FakeVolumeBackupSchedules) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.VolumeBackupScheduleList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(volumebackupschedulesResource, volumebackupschedulesKind, c.ns, opts), &v1alpha1.VolumeBackupScheduleList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.VolumeBackupScheduleList{ListMeta: obj.(*v1alpha1.VolumeBackupScheduleList).ListMeta} + for _, item := range obj.(*v1alpha1.VolumeBackupScheduleList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested volumeBackupSchedules. +func (c *FakeVolumeBackupSchedules) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(volumebackupschedulesResource, c.ns, opts)) + +} + +// Create takes the representation of a volumeBackupSchedule and creates it. Returns the server's representation of the volumeBackupSchedule, and an error, if there is any. +func (c *FakeVolumeBackupSchedules) Create(ctx context.Context, volumeBackupSchedule *v1alpha1.VolumeBackupSchedule, opts v1.CreateOptions) (result *v1alpha1.VolumeBackupSchedule, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(volumebackupschedulesResource, c.ns, volumeBackupSchedule), &v1alpha1.VolumeBackupSchedule{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.VolumeBackupSchedule), err +} + +// Update takes the representation of a volumeBackupSchedule and updates it. Returns the server's representation of the volumeBackupSchedule, and an error, if there is any. +func (c *FakeVolumeBackupSchedules) Update(ctx context.Context, volumeBackupSchedule *v1alpha1.VolumeBackupSchedule, opts v1.UpdateOptions) (result *v1alpha1.VolumeBackupSchedule, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(volumebackupschedulesResource, c.ns, volumeBackupSchedule), &v1alpha1.VolumeBackupSchedule{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.VolumeBackupSchedule), err +} + +// Delete takes name of the volumeBackupSchedule and deletes it. Returns an error if one occurs. +func (c *FakeVolumeBackupSchedules) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(volumebackupschedulesResource, c.ns, name), &v1alpha1.VolumeBackupSchedule{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeVolumeBackupSchedules) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(volumebackupschedulesResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.VolumeBackupScheduleList{}) + return err +} + +// Patch applies the patch and returns the patched volumeBackupSchedule. +func (c *FakeVolumeBackupSchedules) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.VolumeBackupSchedule, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(volumebackupschedulesResource, c.ns, name, pt, data, subresources...), &v1alpha1.VolumeBackupSchedule{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.VolumeBackupSchedule), err +} diff --git a/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_volumerestore.go b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_volumerestore.go new file mode 100644 index 0000000000..542b5e6363 --- /dev/null +++ b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/fake/fake_volumerestore.go @@ -0,0 +1,127 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeVolumeRestores implements VolumeRestoreInterface +type FakeVolumeRestores struct { + Fake *FakeFederationV1alpha1 + ns string +} + +var volumerestoresResource = schema.GroupVersionResource{Group: "federation.pingcap.com", Version: "v1alpha1", Resource: "volumerestores"} + +var volumerestoresKind = schema.GroupVersionKind{Group: "federation.pingcap.com", Version: "v1alpha1", Kind: "VolumeRestore"} + +// Get takes name of the volumeRestore, and returns the corresponding volumeRestore object, and an error if there is any. +func (c *FakeVolumeRestores) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.VolumeRestore, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(volumerestoresResource, c.ns, name), &v1alpha1.VolumeRestore{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.VolumeRestore), err +} + +// List takes label and field selectors, and returns the list of VolumeRestores that match those selectors. +func (c *FakeVolumeRestores) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.VolumeRestoreList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(volumerestoresResource, volumerestoresKind, c.ns, opts), &v1alpha1.VolumeRestoreList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.VolumeRestoreList{ListMeta: obj.(*v1alpha1.VolumeRestoreList).ListMeta} + for _, item := range obj.(*v1alpha1.VolumeRestoreList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested volumeRestores. +func (c *FakeVolumeRestores) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(volumerestoresResource, c.ns, opts)) + +} + +// Create takes the representation of a volumeRestore and creates it. Returns the server's representation of the volumeRestore, and an error, if there is any. +func (c *FakeVolumeRestores) Create(ctx context.Context, volumeRestore *v1alpha1.VolumeRestore, opts v1.CreateOptions) (result *v1alpha1.VolumeRestore, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(volumerestoresResource, c.ns, volumeRestore), &v1alpha1.VolumeRestore{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.VolumeRestore), err +} + +// Update takes the representation of a volumeRestore and updates it. Returns the server's representation of the volumeRestore, and an error, if there is any. +func (c *FakeVolumeRestores) Update(ctx context.Context, volumeRestore *v1alpha1.VolumeRestore, opts v1.UpdateOptions) (result *v1alpha1.VolumeRestore, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(volumerestoresResource, c.ns, volumeRestore), &v1alpha1.VolumeRestore{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.VolumeRestore), err +} + +// Delete takes name of the volumeRestore and deletes it. Returns an error if one occurs. +func (c *FakeVolumeRestores) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteAction(volumerestoresResource, c.ns, name), &v1alpha1.VolumeRestore{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeVolumeRestores) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(volumerestoresResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.VolumeRestoreList{}) + return err +} + +// Patch applies the patch and returns the patched volumeRestore. +func (c *FakeVolumeRestores) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.VolumeRestore, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(volumerestoresResource, c.ns, name, pt, data, subresources...), &v1alpha1.VolumeRestore{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.VolumeRestore), err +} diff --git a/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/generated_expansion.go b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/generated_expansion.go new file mode 100644 index 0000000000..ecf9f49463 --- /dev/null +++ b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/generated_expansion.go @@ -0,0 +1,22 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +type VolumeBackupExpansion interface{} + +type VolumeBackupScheduleExpansion interface{} + +type VolumeRestoreExpansion interface{} diff --git a/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/pingcap_client.go b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/pingcap_client.go new file mode 100644 index 0000000000..8aa5c0626b --- /dev/null +++ b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/pingcap_client.go @@ -0,0 +1,96 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned/scheme" + rest "k8s.io/client-go/rest" +) + +type FederationV1alpha1Interface interface { + RESTClient() rest.Interface + VolumeBackupsGetter + VolumeBackupSchedulesGetter + VolumeRestoresGetter +} + +// FederationV1alpha1Client is used to interact with features provided by the federation.pingcap.com group. +type FederationV1alpha1Client struct { + restClient rest.Interface +} + +func (c *FederationV1alpha1Client) VolumeBackups(namespace string) VolumeBackupInterface { + return newVolumeBackups(c, namespace) +} + +func (c *FederationV1alpha1Client) VolumeBackupSchedules(namespace string) VolumeBackupScheduleInterface { + return newVolumeBackupSchedules(c, namespace) +} + +func (c *FederationV1alpha1Client) VolumeRestores(namespace string) VolumeRestoreInterface { + return newVolumeRestores(c, namespace) +} + +// NewForConfig creates a new FederationV1alpha1Client for the given config. +func NewForConfig(c *rest.Config) (*FederationV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientFor(&config) + if err != nil { + return nil, err + } + return &FederationV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new FederationV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *FederationV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new FederationV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *FederationV1alpha1Client { + return &FederationV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := v1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FederationV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/volumebackup.go b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/volumebackup.go new file mode 100644 index 0000000000..0e155f541d --- /dev/null +++ b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/volumebackup.go @@ -0,0 +1,175 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + v1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + scheme "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// VolumeBackupsGetter has a method to return a VolumeBackupInterface. +// A group's client should implement this interface. +type VolumeBackupsGetter interface { + VolumeBackups(namespace string) VolumeBackupInterface +} + +// VolumeBackupInterface has methods to work with VolumeBackup resources. +type VolumeBackupInterface interface { + Create(ctx context.Context, volumeBackup *v1alpha1.VolumeBackup, opts v1.CreateOptions) (*v1alpha1.VolumeBackup, error) + Update(ctx context.Context, volumeBackup *v1alpha1.VolumeBackup, opts v1.UpdateOptions) (*v1alpha1.VolumeBackup, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.VolumeBackup, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.VolumeBackupList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.VolumeBackup, err error) + VolumeBackupExpansion +} + +// volumeBackups implements VolumeBackupInterface +type volumeBackups struct { + client rest.Interface + ns string +} + +// newVolumeBackups returns a VolumeBackups +func newVolumeBackups(c *FederationV1alpha1Client, namespace string) *volumeBackups { + return &volumeBackups{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the volumeBackup, and returns the corresponding volumeBackup object, and an error if there is any. +func (c *volumeBackups) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.VolumeBackup, err error) { + result = &v1alpha1.VolumeBackup{} + err = c.client.Get(). + Namespace(c.ns). + Resource("volumebackups"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of VolumeBackups that match those selectors. +func (c *volumeBackups) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.VolumeBackupList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.VolumeBackupList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("volumebackups"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested volumeBackups. +func (c *volumeBackups) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("volumebackups"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a volumeBackup and creates it. Returns the server's representation of the volumeBackup, and an error, if there is any. +func (c *volumeBackups) Create(ctx context.Context, volumeBackup *v1alpha1.VolumeBackup, opts v1.CreateOptions) (result *v1alpha1.VolumeBackup, err error) { + result = &v1alpha1.VolumeBackup{} + err = c.client.Post(). + Namespace(c.ns). + Resource("volumebackups"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(volumeBackup). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a volumeBackup and updates it. Returns the server's representation of the volumeBackup, and an error, if there is any. +func (c *volumeBackups) Update(ctx context.Context, volumeBackup *v1alpha1.VolumeBackup, opts v1.UpdateOptions) (result *v1alpha1.VolumeBackup, err error) { + result = &v1alpha1.VolumeBackup{} + err = c.client.Put(). + Namespace(c.ns). + Resource("volumebackups"). + Name(volumeBackup.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(volumeBackup). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the volumeBackup and deletes it. Returns an error if one occurs. +func (c *volumeBackups) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("volumebackups"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *volumeBackups) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("volumebackups"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched volumeBackup. +func (c *volumeBackups) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.VolumeBackup, err error) { + result = &v1alpha1.VolumeBackup{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("volumebackups"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/volumebackupschedule.go b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/volumebackupschedule.go new file mode 100644 index 0000000000..4c7d85845c --- /dev/null +++ b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/volumebackupschedule.go @@ -0,0 +1,175 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + v1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + scheme "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// VolumeBackupSchedulesGetter has a method to return a VolumeBackupScheduleInterface. +// A group's client should implement this interface. +type VolumeBackupSchedulesGetter interface { + VolumeBackupSchedules(namespace string) VolumeBackupScheduleInterface +} + +// VolumeBackupScheduleInterface has methods to work with VolumeBackupSchedule resources. +type VolumeBackupScheduleInterface interface { + Create(ctx context.Context, volumeBackupSchedule *v1alpha1.VolumeBackupSchedule, opts v1.CreateOptions) (*v1alpha1.VolumeBackupSchedule, error) + Update(ctx context.Context, volumeBackupSchedule *v1alpha1.VolumeBackupSchedule, opts v1.UpdateOptions) (*v1alpha1.VolumeBackupSchedule, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.VolumeBackupSchedule, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.VolumeBackupScheduleList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.VolumeBackupSchedule, err error) + VolumeBackupScheduleExpansion +} + +// volumeBackupSchedules implements VolumeBackupScheduleInterface +type volumeBackupSchedules struct { + client rest.Interface + ns string +} + +// newVolumeBackupSchedules returns a VolumeBackupSchedules +func newVolumeBackupSchedules(c *FederationV1alpha1Client, namespace string) *volumeBackupSchedules { + return &volumeBackupSchedules{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the volumeBackupSchedule, and returns the corresponding volumeBackupSchedule object, and an error if there is any. +func (c *volumeBackupSchedules) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.VolumeBackupSchedule, err error) { + result = &v1alpha1.VolumeBackupSchedule{} + err = c.client.Get(). + Namespace(c.ns). + Resource("volumebackupschedules"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of VolumeBackupSchedules that match those selectors. +func (c *volumeBackupSchedules) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.VolumeBackupScheduleList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.VolumeBackupScheduleList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("volumebackupschedules"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested volumeBackupSchedules. +func (c *volumeBackupSchedules) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("volumebackupschedules"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a volumeBackupSchedule and creates it. Returns the server's representation of the volumeBackupSchedule, and an error, if there is any. +func (c *volumeBackupSchedules) Create(ctx context.Context, volumeBackupSchedule *v1alpha1.VolumeBackupSchedule, opts v1.CreateOptions) (result *v1alpha1.VolumeBackupSchedule, err error) { + result = &v1alpha1.VolumeBackupSchedule{} + err = c.client.Post(). + Namespace(c.ns). + Resource("volumebackupschedules"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(volumeBackupSchedule). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a volumeBackupSchedule and updates it. Returns the server's representation of the volumeBackupSchedule, and an error, if there is any. +func (c *volumeBackupSchedules) Update(ctx context.Context, volumeBackupSchedule *v1alpha1.VolumeBackupSchedule, opts v1.UpdateOptions) (result *v1alpha1.VolumeBackupSchedule, err error) { + result = &v1alpha1.VolumeBackupSchedule{} + err = c.client.Put(). + Namespace(c.ns). + Resource("volumebackupschedules"). + Name(volumeBackupSchedule.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(volumeBackupSchedule). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the volumeBackupSchedule and deletes it. Returns an error if one occurs. +func (c *volumeBackupSchedules) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("volumebackupschedules"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *volumeBackupSchedules) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("volumebackupschedules"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched volumeBackupSchedule. +func (c *volumeBackupSchedules) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.VolumeBackupSchedule, err error) { + result = &v1alpha1.VolumeBackupSchedule{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("volumebackupschedules"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/volumerestore.go b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/volumerestore.go new file mode 100644 index 0000000000..dab92d22bb --- /dev/null +++ b/pkg/client/federation/clientset/versioned/typed/pingcap/v1alpha1/volumerestore.go @@ -0,0 +1,175 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + v1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + scheme "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// VolumeRestoresGetter has a method to return a VolumeRestoreInterface. +// A group's client should implement this interface. +type VolumeRestoresGetter interface { + VolumeRestores(namespace string) VolumeRestoreInterface +} + +// VolumeRestoreInterface has methods to work with VolumeRestore resources. +type VolumeRestoreInterface interface { + Create(ctx context.Context, volumeRestore *v1alpha1.VolumeRestore, opts v1.CreateOptions) (*v1alpha1.VolumeRestore, error) + Update(ctx context.Context, volumeRestore *v1alpha1.VolumeRestore, opts v1.UpdateOptions) (*v1alpha1.VolumeRestore, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.VolumeRestore, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.VolumeRestoreList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.VolumeRestore, err error) + VolumeRestoreExpansion +} + +// volumeRestores implements VolumeRestoreInterface +type volumeRestores struct { + client rest.Interface + ns string +} + +// newVolumeRestores returns a VolumeRestores +func newVolumeRestores(c *FederationV1alpha1Client, namespace string) *volumeRestores { + return &volumeRestores{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the volumeRestore, and returns the corresponding volumeRestore object, and an error if there is any. +func (c *volumeRestores) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.VolumeRestore, err error) { + result = &v1alpha1.VolumeRestore{} + err = c.client.Get(). + Namespace(c.ns). + Resource("volumerestores"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of VolumeRestores that match those selectors. +func (c *volumeRestores) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.VolumeRestoreList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.VolumeRestoreList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("volumerestores"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested volumeRestores. +func (c *volumeRestores) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("volumerestores"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a volumeRestore and creates it. Returns the server's representation of the volumeRestore, and an error, if there is any. +func (c *volumeRestores) Create(ctx context.Context, volumeRestore *v1alpha1.VolumeRestore, opts v1.CreateOptions) (result *v1alpha1.VolumeRestore, err error) { + result = &v1alpha1.VolumeRestore{} + err = c.client.Post(). + Namespace(c.ns). + Resource("volumerestores"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(volumeRestore). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a volumeRestore and updates it. Returns the server's representation of the volumeRestore, and an error, if there is any. +func (c *volumeRestores) Update(ctx context.Context, volumeRestore *v1alpha1.VolumeRestore, opts v1.UpdateOptions) (result *v1alpha1.VolumeRestore, err error) { + result = &v1alpha1.VolumeRestore{} + err = c.client.Put(). + Namespace(c.ns). + Resource("volumerestores"). + Name(volumeRestore.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(volumeRestore). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the volumeRestore and deletes it. Returns an error if one occurs. +func (c *volumeRestores) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("volumerestores"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *volumeRestores) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("volumerestores"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched volumeRestore. +func (c *volumeRestores) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.VolumeRestore, err error) { + result = &v1alpha1.VolumeRestore{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("volumerestores"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/client/federation/informers/externalversions/factory.go b/pkg/client/federation/informers/externalversions/factory.go new file mode 100644 index 0000000000..28bf8b7323 --- /dev/null +++ b/pkg/client/federation/informers/externalversions/factory.go @@ -0,0 +1,177 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package externalversions + +import ( + reflect "reflect" + sync "sync" + time "time" + + versioned "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned" + internalinterfaces "github.com/pingcap/tidb-operator/pkg/client/federation/informers/externalversions/internalinterfaces" + pingcap "github.com/pingcap/tidb-operator/pkg/client/federation/informers/externalversions/pingcap" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" +) + +// SharedInformerOption defines the functional option type for SharedInformerFactory. +type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory + +type sharedInformerFactory struct { + client versioned.Interface + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc + lock sync.Mutex + defaultResync time.Duration + customResync map[reflect.Type]time.Duration + + informers map[reflect.Type]cache.SharedIndexInformer + // startedInformers is used for tracking which informers have been started. + // This allows Start() to be called multiple times safely. + startedInformers map[reflect.Type]bool +} + +// WithCustomResyncConfig sets a custom resync period for the specified informer types. +func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + for k, v := range resyncConfig { + factory.customResync[reflect.TypeOf(k)] = v + } + return factory + } +} + +// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. +func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.tweakListOptions = tweakListOptions + return factory + } +} + +// WithNamespace limits the SharedInformerFactory to the specified namespace. +func WithNamespace(namespace string) SharedInformerOption { + return func(factory *sharedInformerFactory) *sharedInformerFactory { + factory.namespace = namespace + return factory + } +} + +// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. +func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync) +} + +// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. +// Listers obtained via this SharedInformerFactory will be subject to the same filters +// as specified here. +// Deprecated: Please use NewSharedInformerFactoryWithOptions instead +func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { + return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) +} + +// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. +func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { + factory := &sharedInformerFactory{ + client: client, + namespace: v1.NamespaceAll, + defaultResync: defaultResync, + informers: make(map[reflect.Type]cache.SharedIndexInformer), + startedInformers: make(map[reflect.Type]bool), + customResync: make(map[reflect.Type]time.Duration), + } + + // Apply all options + for _, opt := range options { + factory = opt(factory) + } + + return factory +} + +// Start initializes all requested informers. +func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { + f.lock.Lock() + defer f.lock.Unlock() + + for informerType, informer := range f.informers { + if !f.startedInformers[informerType] { + go informer.Run(stopCh) + f.startedInformers[informerType] = true + } + } +} + +// WaitForCacheSync waits for all started informers' cache were synced. +func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { + informers := func() map[reflect.Type]cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informers := map[reflect.Type]cache.SharedIndexInformer{} + for informerType, informer := range f.informers { + if f.startedInformers[informerType] { + informers[informerType] = informer + } + } + return informers + }() + + res := map[reflect.Type]bool{} + for informType, informer := range informers { + res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) + } + return res +} + +// InternalInformerFor returns the SharedIndexInformer for obj using an internal +// client. +func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { + f.lock.Lock() + defer f.lock.Unlock() + + informerType := reflect.TypeOf(obj) + informer, exists := f.informers[informerType] + if exists { + return informer + } + + resyncPeriod, exists := f.customResync[informerType] + if !exists { + resyncPeriod = f.defaultResync + } + + informer = newFunc(f.client, resyncPeriod) + f.informers[informerType] = informer + + return informer +} + +// SharedInformerFactory provides shared informers for resources in all known +// API group versions. +type SharedInformerFactory interface { + internalinterfaces.SharedInformerFactory + ForResource(resource schema.GroupVersionResource) (GenericInformer, error) + WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool + + Federation() pingcap.Interface +} + +func (f *sharedInformerFactory) Federation() pingcap.Interface { + return pingcap.New(f, f.namespace, f.tweakListOptions) +} diff --git a/pkg/client/federation/informers/externalversions/generic.go b/pkg/client/federation/informers/externalversions/generic.go new file mode 100644 index 0000000000..1c5ac0d290 --- /dev/null +++ b/pkg/client/federation/informers/externalversions/generic.go @@ -0,0 +1,63 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package externalversions + +import ( + "fmt" + + v1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + schema "k8s.io/apimachinery/pkg/runtime/schema" + cache "k8s.io/client-go/tools/cache" +) + +// GenericInformer is type of SharedIndexInformer which will locate and delegate to other +// sharedInformers based on type +type GenericInformer interface { + Informer() cache.SharedIndexInformer + Lister() cache.GenericLister +} + +type genericInformer struct { + informer cache.SharedIndexInformer + resource schema.GroupResource +} + +// Informer returns the SharedIndexInformer. +func (f *genericInformer) Informer() cache.SharedIndexInformer { + return f.informer +} + +// Lister returns the GenericLister. +func (f *genericInformer) Lister() cache.GenericLister { + return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) +} + +// ForResource gives generic access to a shared informer of the matching type +// TODO extend this to unknown resources with a client pool +func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { + switch resource { + // Group=federation.pingcap.com, Version=v1alpha1 + case v1alpha1.SchemeGroupVersion.WithResource("volumebackups"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Federation().V1alpha1().VolumeBackups().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("volumebackupschedules"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Federation().V1alpha1().VolumeBackupSchedules().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("volumerestores"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Federation().V1alpha1().VolumeRestores().Informer()}, nil + + } + + return nil, fmt.Errorf("no informer found for %v", resource) +} diff --git a/pkg/client/federation/informers/externalversions/internalinterfaces/factory_interfaces.go b/pkg/client/federation/informers/externalversions/internalinterfaces/factory_interfaces.go new file mode 100644 index 0000000000..a0c811d099 --- /dev/null +++ b/pkg/client/federation/informers/externalversions/internalinterfaces/factory_interfaces.go @@ -0,0 +1,37 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package internalinterfaces + +import ( + time "time" + + versioned "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + cache "k8s.io/client-go/tools/cache" +) + +// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. +type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer + +// SharedInformerFactory a small interface to allow for adding an informer without an import cycle +type SharedInformerFactory interface { + Start(stopCh <-chan struct{}) + InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer +} + +// TweakListOptionsFunc is a function that transforms a v1.ListOptions. +type TweakListOptionsFunc func(*v1.ListOptions) diff --git a/pkg/client/federation/informers/externalversions/pingcap/interface.go b/pkg/client/federation/informers/externalversions/pingcap/interface.go new file mode 100644 index 0000000000..1e7f073e21 --- /dev/null +++ b/pkg/client/federation/informers/externalversions/pingcap/interface.go @@ -0,0 +1,43 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package pingcap + +import ( + internalinterfaces "github.com/pingcap/tidb-operator/pkg/client/federation/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/pingcap/tidb-operator/pkg/client/federation/informers/externalversions/pingcap/v1alpha1" +) + +// Interface provides access to each of this group's versions. +type Interface interface { + // V1alpha1 provides access to shared informers for resources in V1alpha1. + V1alpha1() v1alpha1.Interface +} + +type group struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// V1alpha1 returns a new v1alpha1.Interface. +func (g *group) V1alpha1() v1alpha1.Interface { + return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) +} diff --git a/pkg/client/federation/informers/externalversions/pingcap/v1alpha1/interface.go b/pkg/client/federation/informers/externalversions/pingcap/v1alpha1/interface.go new file mode 100644 index 0000000000..78cfa28b9a --- /dev/null +++ b/pkg/client/federation/informers/externalversions/pingcap/v1alpha1/interface.go @@ -0,0 +1,56 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + internalinterfaces "github.com/pingcap/tidb-operator/pkg/client/federation/informers/externalversions/internalinterfaces" +) + +// Interface provides access to all the informers in this group version. +type Interface interface { + // VolumeBackups returns a VolumeBackupInformer. + VolumeBackups() VolumeBackupInformer + // VolumeBackupSchedules returns a VolumeBackupScheduleInformer. + VolumeBackupSchedules() VolumeBackupScheduleInformer + // VolumeRestores returns a VolumeRestoreInformer. + VolumeRestores() VolumeRestoreInformer +} + +type version struct { + factory internalinterfaces.SharedInformerFactory + namespace string + tweakListOptions internalinterfaces.TweakListOptionsFunc +} + +// New returns a new Interface. +func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { + return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} +} + +// VolumeBackups returns a VolumeBackupInformer. +func (v *version) VolumeBackups() VolumeBackupInformer { + return &volumeBackupInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// VolumeBackupSchedules returns a VolumeBackupScheduleInformer. +func (v *version) VolumeBackupSchedules() VolumeBackupScheduleInformer { + return &volumeBackupScheduleInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + +// VolumeRestores returns a VolumeRestoreInformer. +func (v *version) VolumeRestores() VolumeRestoreInformer { + return &volumeRestoreInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} diff --git a/pkg/client/federation/informers/externalversions/pingcap/v1alpha1/volumebackup.go b/pkg/client/federation/informers/externalversions/pingcap/v1alpha1/volumebackup.go new file mode 100644 index 0000000000..963a74f282 --- /dev/null +++ b/pkg/client/federation/informers/externalversions/pingcap/v1alpha1/volumebackup.go @@ -0,0 +1,87 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + pingcapv1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + versioned "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned" + internalinterfaces "github.com/pingcap/tidb-operator/pkg/client/federation/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/pingcap/tidb-operator/pkg/client/federation/listers/pingcap/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// VolumeBackupInformer provides access to a shared informer and lister for +// VolumeBackups. +type VolumeBackupInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.VolumeBackupLister +} + +type volumeBackupInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewVolumeBackupInformer constructs a new informer for VolumeBackup type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewVolumeBackupInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredVolumeBackupInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredVolumeBackupInformer constructs a new informer for VolumeBackup type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredVolumeBackupInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.FederationV1alpha1().VolumeBackups(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.FederationV1alpha1().VolumeBackups(namespace).Watch(context.TODO(), options) + }, + }, + &pingcapv1alpha1.VolumeBackup{}, + resyncPeriod, + indexers, + ) +} + +func (f *volumeBackupInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredVolumeBackupInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *volumeBackupInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&pingcapv1alpha1.VolumeBackup{}, f.defaultInformer) +} + +func (f *volumeBackupInformer) Lister() v1alpha1.VolumeBackupLister { + return v1alpha1.NewVolumeBackupLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/federation/informers/externalversions/pingcap/v1alpha1/volumebackupschedule.go b/pkg/client/federation/informers/externalversions/pingcap/v1alpha1/volumebackupschedule.go new file mode 100644 index 0000000000..aea6bfbd89 --- /dev/null +++ b/pkg/client/federation/informers/externalversions/pingcap/v1alpha1/volumebackupschedule.go @@ -0,0 +1,87 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + pingcapv1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + versioned "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned" + internalinterfaces "github.com/pingcap/tidb-operator/pkg/client/federation/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/pingcap/tidb-operator/pkg/client/federation/listers/pingcap/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// VolumeBackupScheduleInformer provides access to a shared informer and lister for +// VolumeBackupSchedules. +type VolumeBackupScheduleInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.VolumeBackupScheduleLister +} + +type volumeBackupScheduleInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewVolumeBackupScheduleInformer constructs a new informer for VolumeBackupSchedule type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewVolumeBackupScheduleInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredVolumeBackupScheduleInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredVolumeBackupScheduleInformer constructs a new informer for VolumeBackupSchedule type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredVolumeBackupScheduleInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.FederationV1alpha1().VolumeBackupSchedules(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.FederationV1alpha1().VolumeBackupSchedules(namespace).Watch(context.TODO(), options) + }, + }, + &pingcapv1alpha1.VolumeBackupSchedule{}, + resyncPeriod, + indexers, + ) +} + +func (f *volumeBackupScheduleInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredVolumeBackupScheduleInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *volumeBackupScheduleInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&pingcapv1alpha1.VolumeBackupSchedule{}, f.defaultInformer) +} + +func (f *volumeBackupScheduleInformer) Lister() v1alpha1.VolumeBackupScheduleLister { + return v1alpha1.NewVolumeBackupScheduleLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/federation/informers/externalversions/pingcap/v1alpha1/volumerestore.go b/pkg/client/federation/informers/externalversions/pingcap/v1alpha1/volumerestore.go new file mode 100644 index 0000000000..4ec15da08b --- /dev/null +++ b/pkg/client/federation/informers/externalversions/pingcap/v1alpha1/volumerestore.go @@ -0,0 +1,87 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + pingcapv1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + versioned "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned" + internalinterfaces "github.com/pingcap/tidb-operator/pkg/client/federation/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/pingcap/tidb-operator/pkg/client/federation/listers/pingcap/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// VolumeRestoreInformer provides access to a shared informer and lister for +// VolumeRestores. +type VolumeRestoreInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.VolumeRestoreLister +} + +type volumeRestoreInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewVolumeRestoreInformer constructs a new informer for VolumeRestore type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewVolumeRestoreInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredVolumeRestoreInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredVolumeRestoreInformer constructs a new informer for VolumeRestore type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredVolumeRestoreInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.FederationV1alpha1().VolumeRestores(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.FederationV1alpha1().VolumeRestores(namespace).Watch(context.TODO(), options) + }, + }, + &pingcapv1alpha1.VolumeRestore{}, + resyncPeriod, + indexers, + ) +} + +func (f *volumeRestoreInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredVolumeRestoreInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *volumeRestoreInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&pingcapv1alpha1.VolumeRestore{}, f.defaultInformer) +} + +func (f *volumeRestoreInformer) Lister() v1alpha1.VolumeRestoreLister { + return v1alpha1.NewVolumeRestoreLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/federation/listers/pingcap/v1alpha1/expansion_generated.go b/pkg/client/federation/listers/pingcap/v1alpha1/expansion_generated.go new file mode 100644 index 0000000000..0775b85e0d --- /dev/null +++ b/pkg/client/federation/listers/pingcap/v1alpha1/expansion_generated.go @@ -0,0 +1,40 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +// VolumeBackupListerExpansion allows custom methods to be added to +// VolumeBackupLister. +type VolumeBackupListerExpansion interface{} + +// VolumeBackupNamespaceListerExpansion allows custom methods to be added to +// VolumeBackupNamespaceLister. +type VolumeBackupNamespaceListerExpansion interface{} + +// VolumeBackupScheduleListerExpansion allows custom methods to be added to +// VolumeBackupScheduleLister. +type VolumeBackupScheduleListerExpansion interface{} + +// VolumeBackupScheduleNamespaceListerExpansion allows custom methods to be added to +// VolumeBackupScheduleNamespaceLister. +type VolumeBackupScheduleNamespaceListerExpansion interface{} + +// VolumeRestoreListerExpansion allows custom methods to be added to +// VolumeRestoreLister. +type VolumeRestoreListerExpansion interface{} + +// VolumeRestoreNamespaceListerExpansion allows custom methods to be added to +// VolumeRestoreNamespaceLister. +type VolumeRestoreNamespaceListerExpansion interface{} diff --git a/pkg/client/federation/listers/pingcap/v1alpha1/volumebackup.go b/pkg/client/federation/listers/pingcap/v1alpha1/volumebackup.go new file mode 100644 index 0000000000..5b131b1588 --- /dev/null +++ b/pkg/client/federation/listers/pingcap/v1alpha1/volumebackup.go @@ -0,0 +1,96 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// VolumeBackupLister helps list VolumeBackups. +// All objects returned here must be treated as read-only. +type VolumeBackupLister interface { + // List lists all VolumeBackups in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.VolumeBackup, err error) + // VolumeBackups returns an object that can list and get VolumeBackups. + VolumeBackups(namespace string) VolumeBackupNamespaceLister + VolumeBackupListerExpansion +} + +// volumeBackupLister implements the VolumeBackupLister interface. +type volumeBackupLister struct { + indexer cache.Indexer +} + +// NewVolumeBackupLister returns a new VolumeBackupLister. +func NewVolumeBackupLister(indexer cache.Indexer) VolumeBackupLister { + return &volumeBackupLister{indexer: indexer} +} + +// List lists all VolumeBackups in the indexer. +func (s *volumeBackupLister) List(selector labels.Selector) (ret []*v1alpha1.VolumeBackup, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.VolumeBackup)) + }) + return ret, err +} + +// VolumeBackups returns an object that can list and get VolumeBackups. +func (s *volumeBackupLister) VolumeBackups(namespace string) VolumeBackupNamespaceLister { + return volumeBackupNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// VolumeBackupNamespaceLister helps list and get VolumeBackups. +// All objects returned here must be treated as read-only. +type VolumeBackupNamespaceLister interface { + // List lists all VolumeBackups in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.VolumeBackup, err error) + // Get retrieves the VolumeBackup from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.VolumeBackup, error) + VolumeBackupNamespaceListerExpansion +} + +// volumeBackupNamespaceLister implements the VolumeBackupNamespaceLister +// interface. +type volumeBackupNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all VolumeBackups in the indexer for a given namespace. +func (s volumeBackupNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.VolumeBackup, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.VolumeBackup)) + }) + return ret, err +} + +// Get retrieves the VolumeBackup from the indexer for a given namespace and name. +func (s volumeBackupNamespaceLister) Get(name string) (*v1alpha1.VolumeBackup, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("volumebackup"), name) + } + return obj.(*v1alpha1.VolumeBackup), nil +} diff --git a/pkg/client/federation/listers/pingcap/v1alpha1/volumebackupschedule.go b/pkg/client/federation/listers/pingcap/v1alpha1/volumebackupschedule.go new file mode 100644 index 0000000000..2efc1720c1 --- /dev/null +++ b/pkg/client/federation/listers/pingcap/v1alpha1/volumebackupschedule.go @@ -0,0 +1,96 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// VolumeBackupScheduleLister helps list VolumeBackupSchedules. +// All objects returned here must be treated as read-only. +type VolumeBackupScheduleLister interface { + // List lists all VolumeBackupSchedules in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.VolumeBackupSchedule, err error) + // VolumeBackupSchedules returns an object that can list and get VolumeBackupSchedules. + VolumeBackupSchedules(namespace string) VolumeBackupScheduleNamespaceLister + VolumeBackupScheduleListerExpansion +} + +// volumeBackupScheduleLister implements the VolumeBackupScheduleLister interface. +type volumeBackupScheduleLister struct { + indexer cache.Indexer +} + +// NewVolumeBackupScheduleLister returns a new VolumeBackupScheduleLister. +func NewVolumeBackupScheduleLister(indexer cache.Indexer) VolumeBackupScheduleLister { + return &volumeBackupScheduleLister{indexer: indexer} +} + +// List lists all VolumeBackupSchedules in the indexer. +func (s *volumeBackupScheduleLister) List(selector labels.Selector) (ret []*v1alpha1.VolumeBackupSchedule, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.VolumeBackupSchedule)) + }) + return ret, err +} + +// VolumeBackupSchedules returns an object that can list and get VolumeBackupSchedules. +func (s *volumeBackupScheduleLister) VolumeBackupSchedules(namespace string) VolumeBackupScheduleNamespaceLister { + return volumeBackupScheduleNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// VolumeBackupScheduleNamespaceLister helps list and get VolumeBackupSchedules. +// All objects returned here must be treated as read-only. +type VolumeBackupScheduleNamespaceLister interface { + // List lists all VolumeBackupSchedules in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.VolumeBackupSchedule, err error) + // Get retrieves the VolumeBackupSchedule from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.VolumeBackupSchedule, error) + VolumeBackupScheduleNamespaceListerExpansion +} + +// volumeBackupScheduleNamespaceLister implements the VolumeBackupScheduleNamespaceLister +// interface. +type volumeBackupScheduleNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all VolumeBackupSchedules in the indexer for a given namespace. +func (s volumeBackupScheduleNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.VolumeBackupSchedule, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.VolumeBackupSchedule)) + }) + return ret, err +} + +// Get retrieves the VolumeBackupSchedule from the indexer for a given namespace and name. +func (s volumeBackupScheduleNamespaceLister) Get(name string) (*v1alpha1.VolumeBackupSchedule, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("volumebackupschedule"), name) + } + return obj.(*v1alpha1.VolumeBackupSchedule), nil +} diff --git a/pkg/client/federation/listers/pingcap/v1alpha1/volumerestore.go b/pkg/client/federation/listers/pingcap/v1alpha1/volumerestore.go new file mode 100644 index 0000000000..706f1057eb --- /dev/null +++ b/pkg/client/federation/listers/pingcap/v1alpha1/volumerestore.go @@ -0,0 +1,96 @@ +// Copyright PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// VolumeRestoreLister helps list VolumeRestores. +// All objects returned here must be treated as read-only. +type VolumeRestoreLister interface { + // List lists all VolumeRestores in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.VolumeRestore, err error) + // VolumeRestores returns an object that can list and get VolumeRestores. + VolumeRestores(namespace string) VolumeRestoreNamespaceLister + VolumeRestoreListerExpansion +} + +// volumeRestoreLister implements the VolumeRestoreLister interface. +type volumeRestoreLister struct { + indexer cache.Indexer +} + +// NewVolumeRestoreLister returns a new VolumeRestoreLister. +func NewVolumeRestoreLister(indexer cache.Indexer) VolumeRestoreLister { + return &volumeRestoreLister{indexer: indexer} +} + +// List lists all VolumeRestores in the indexer. +func (s *volumeRestoreLister) List(selector labels.Selector) (ret []*v1alpha1.VolumeRestore, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.VolumeRestore)) + }) + return ret, err +} + +// VolumeRestores returns an object that can list and get VolumeRestores. +func (s *volumeRestoreLister) VolumeRestores(namespace string) VolumeRestoreNamespaceLister { + return volumeRestoreNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// VolumeRestoreNamespaceLister helps list and get VolumeRestores. +// All objects returned here must be treated as read-only. +type VolumeRestoreNamespaceLister interface { + // List lists all VolumeRestores in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.VolumeRestore, err error) + // Get retrieves the VolumeRestore from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.VolumeRestore, error) + VolumeRestoreNamespaceListerExpansion +} + +// volumeRestoreNamespaceLister implements the VolumeRestoreNamespaceLister +// interface. +type volumeRestoreNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all VolumeRestores in the indexer for a given namespace. +func (s volumeRestoreNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.VolumeRestore, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.VolumeRestore)) + }) + return ret, err +} + +// Get retrieves the VolumeRestore from the indexer for a given namespace and name. +func (s volumeRestoreNamespaceLister) Get(name string) (*v1alpha1.VolumeRestore, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("volumerestore"), name) + } + return obj.(*v1alpha1.VolumeRestore), nil +} diff --git a/pkg/controller/br_fed_config.go b/pkg/controller/br_fed_config.go new file mode 100644 index 0000000000..25e2f39361 --- /dev/null +++ b/pkg/controller/br_fed_config.go @@ -0,0 +1,77 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package controller + +import ( + "flag" + "time" +) + +const ( + defaultFederationKubeConfigPath = "/etc/br-federation/federation-kubeconfig" +) + +// BrFedCLIConfig is used to save the configuration of br-federation-manager read from command line. +type BrFedCLIConfig struct { + PrintVersion bool + // The number of workers that are allowed to sync concurrently. + // Larger number = more responsive management, but more CPU + // (and network) load + Workers int + + LeaseDuration time.Duration + RenewDeadline time.Duration + RetryPeriod time.Duration + WaitDuration time.Duration + // ResyncDuration is the resync time of informer + ResyncDuration time.Duration + + // KubeClientQPS indicates the maximum QPS to the kubenetes API server from client. + KubeClientQPS float64 + KubeClientBurst int + + // FederationKubeConfigPath is the path to the directory containing the federation kubeconfig files + FederationKubeConfigPath string +} + +// DefaultBrFedCLIConfig returns the default command line configuration +func DefaultBrFedCLIConfig() *BrFedCLIConfig { + return &BrFedCLIConfig{ + Workers: 5, + LeaseDuration: 15 * time.Second, + RenewDeadline: 10 * time.Second, + RetryPeriod: 2 * time.Second, + WaitDuration: 5 * time.Second, + ResyncDuration: 30 * time.Second, + + FederationKubeConfigPath: defaultFederationKubeConfigPath, + } +} + +// AddFlag adds a flag for setting global feature gates to the specified FlagSet. +func (c *BrFedCLIConfig) AddFlag(_ *flag.FlagSet) { + flag.BoolVar(&c.PrintVersion, "V", false, "Show version and quit") + flag.BoolVar(&c.PrintVersion, "version", false, "Show version and quit") + flag.IntVar(&c.Workers, "workers", c.Workers, "The number of workers that are allowed to sync concurrently. Larger number = more responsive management, but more CPU (and network) load") + flag.DurationVar(&c.ResyncDuration, "resync-duration", c.ResyncDuration, "Resync time of informer") + + // see https://pkg.go.dev/k8s.io/client-go/tools/leaderelection#LeaderElectionConfig for the config + flag.DurationVar(&c.LeaseDuration, "leader-lease-duration", c.LeaseDuration, "leader-lease-duration is the duration that non-leader candidates will wait to force acquire leadership") + flag.DurationVar(&c.RenewDeadline, "leader-renew-deadline", c.RenewDeadline, "leader-renew-deadline is the duration that the acting master will retry refreshing leadership before giving up") + flag.DurationVar(&c.RetryPeriod, "leader-retry-period", c.RetryPeriod, "leader-retry-period is the duration the LeaderElector clients should wait between tries of actions") + flag.Float64Var(&c.KubeClientQPS, "kube-client-qps", c.KubeClientQPS, "The maximum QPS to the kubenetes API server from client") + flag.IntVar(&c.KubeClientBurst, "kube-client-burst", c.KubeClientBurst, "The maximum burst for throttle to the kubenetes API server from client") + + flag.StringVar(&c.FederationKubeConfigPath, "federation-kubeconfig-path", c.FederationKubeConfigPath, "The path to the directory containing the federation kubeconfig files") +} diff --git a/pkg/controller/br_fed_dependences.go b/pkg/controller/br_fed_dependences.go new file mode 100644 index 0000000000..faf69b9e91 --- /dev/null +++ b/pkg/controller/br_fed_dependences.go @@ -0,0 +1,133 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package controller + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + kubeinformers "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes" + eventv1 "k8s.io/client-go/kubernetes/typed/core/v1" + "k8s.io/client-go/tools/record" + "k8s.io/klog/v2" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + fedversioned "github.com/pingcap/tidb-operator/pkg/client/clientset/versioned" + "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned" + informers "github.com/pingcap/tidb-operator/pkg/client/federation/informers/externalversions" + listers "github.com/pingcap/tidb-operator/pkg/client/federation/listers/pingcap/v1alpha1" +) + +type BrFedControls struct { + FedVolumeBackupControl FedVolumeBackupControlInterface +} + +// BrFedDependencies is used to store all shared dependent resources to avoid +// pass parameters everywhere. +type BrFedDependencies struct { + // CLIConfig represents all parameters read from command line + CLIConfig *BrFedCLIConfig + // Operator client interface + Clientset versioned.Interface + // Kubernetes client interface + KubeClientset kubernetes.Interface + GenericClient client.Client + InformerFactory informers.SharedInformerFactory + KubeInformerFactory kubeinformers.SharedInformerFactory + LabelFilterKubeInformerFactory kubeinformers.SharedInformerFactory + Recorder record.EventRecorder + + // Listers + VolumeBackupLister listers.VolumeBackupLister + VolumeRestoreLister listers.VolumeRestoreLister + VolumeBackupScheduleLister listers.VolumeBackupScheduleLister + + // Controls + BrFedControls + + // FedClientset is the clientset for the federation clusters + FedClientset map[string]*fedversioned.Clientset +} + +// NewBrFedDependencies is used to construct the dependencies +func NewBrFedDependencies(cliCfg *BrFedCLIConfig, clientset versioned.Interface, kubeClientset kubernetes.Interface, + genericCli client.Client, fedClientset map[string]*fedversioned.Clientset) *BrFedDependencies { + tweakListOptionsFunc := func(options *metav1.ListOptions) { + if len(options.LabelSelector) > 0 { + options.LabelSelector += ",app.kubernetes.io/managed-by=tidb-operator" + } else { + options.LabelSelector = "app.kubernetes.io/managed-by=tidb-operator" + } + } + tweakListOptions := kubeinformers.WithTweakListOptions(tweakListOptionsFunc) + + // Initialize the informer factories + informerFactory := informers.NewSharedInformerFactoryWithOptions(clientset, cliCfg.ResyncDuration) + kubeInformerFactory := kubeinformers.NewSharedInformerFactoryWithOptions(kubeClientset, cliCfg.ResyncDuration) + labelFilterKubeInformerFactory := kubeinformers.NewSharedInformerFactoryWithOptions(kubeClientset, cliCfg.ResyncDuration, tweakListOptions) + + // Initialize the event recorder + eventBroadcaster := record.NewBroadcasterWithCorrelatorOptions(record.CorrelatorOptions{QPS: 1}) + eventBroadcaster.StartLogging(klog.V(2).Infof) + eventBroadcaster.StartRecordingToSink(&eventv1.EventSinkImpl{ + Interface: eventv1.New(kubeClientset.CoreV1().RESTClient()).Events("")}) + recorder := eventBroadcaster.NewRecorder(v1alpha1.Scheme, corev1.EventSource{Component: "br-federation-manager"}) + + deps := newBrFedDependencies(cliCfg, clientset, kubeClientset, genericCli, informerFactory, kubeInformerFactory, labelFilterKubeInformerFactory, recorder, fedClientset) + deps.BrFedControls = newRealBrFedControls(cliCfg, clientset, kubeClientset, genericCli, informerFactory, kubeInformerFactory, recorder) + return deps +} + +func newBrFedDependencies( + cliCfg *BrFedCLIConfig, + clientset versioned.Interface, + kubeClientset kubernetes.Interface, + genericCli client.Client, + informerFactory informers.SharedInformerFactory, + kubeInformerFactory kubeinformers.SharedInformerFactory, + labelFilterKubeInformerFactory kubeinformers.SharedInformerFactory, + recorder record.EventRecorder, + fedClientset map[string]*fedversioned.Clientset) *BrFedDependencies { + return &BrFedDependencies{ + CLIConfig: cliCfg, + Clientset: clientset, + KubeClientset: kubeClientset, + GenericClient: genericCli, + InformerFactory: informerFactory, + KubeInformerFactory: kubeInformerFactory, + LabelFilterKubeInformerFactory: labelFilterKubeInformerFactory, + Recorder: recorder, + + // Listers + VolumeBackupLister: informerFactory.Federation().V1alpha1().VolumeBackups().Lister(), + VolumeRestoreLister: informerFactory.Federation().V1alpha1().VolumeRestores().Lister(), + VolumeBackupScheduleLister: informerFactory.Federation().V1alpha1().VolumeBackupSchedules().Lister(), + + FedClientset: fedClientset, + } +} + +func newRealBrFedControls( + cliCfg *BrFedCLIConfig, + clientset versioned.Interface, + kubeClientset kubernetes.Interface, + genericCli client.Client, + informerFactory informers.SharedInformerFactory, + kubeInformerFactory kubeinformers.SharedInformerFactory, + recorder record.EventRecorder) BrFedControls { + return BrFedControls{ + FedVolumeBackupControl: NewRealFedVolumeBackupControl(clientset, recorder), + } +} diff --git a/pkg/controller/controller_utils.go b/pkg/controller/controller_utils.go index cd081e77ac..b2c141dd35 100644 --- a/pkg/controller/controller_utils.go +++ b/pkg/controller/controller_utils.go @@ -20,6 +20,7 @@ import ( "regexp" "github.com/dustin/go-humanize" + fedv1alpha1 "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" "github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1" "github.com/pingcap/tidb-operator/pkg/scheme" "github.com/pingcap/tidb-operator/pkg/util" @@ -64,6 +65,15 @@ var ( // tidbDashboardKind contains the schema.GroupVersionKind for TidbDashboard controller type. tidbDashboardKind = v1alpha1.SchemeGroupVersion.WithKind("TidbDashboard") + + // FedVolumeBackupControllerKind contains the schema.GroupVersionKind for federation VolumeBackup controller type. + FedVolumeBackupControllerKind = fedv1alpha1.SchemeGroupVersion.WithKind("VolumeBackup") + + // FedVolumeRestoreControllerKind contains the schema.GroupVersionKind for federation VolumeRestore controller type. + FedVolumeRestoreControllerKind = fedv1alpha1.SchemeGroupVersion.WithKind("VolumeRestore") + + // FedVolumeBackupScheduleControllerKind contains the schema.GroupVersionKind for federation VolumeBackupSchedule controller type. + FedVolumeBackupScheduleControllerKind = fedv1alpha1.SchemeGroupVersion.WithKind("VolumeBackupSchedule") ) // RequeueError is used to requeue the item, this error type should't be considered as a real error diff --git a/pkg/controller/fed_volume_backup_control.go b/pkg/controller/fed_volume_backup_control.go new file mode 100644 index 0000000000..0de42e3bb4 --- /dev/null +++ b/pkg/controller/fed_volume_backup_control.go @@ -0,0 +1,156 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package controller + +import ( + "context" + "fmt" + "strings" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/tools/record" + "k8s.io/klog/v2" + + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/apis/label" + "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned" + informers "github.com/pingcap/tidb-operator/pkg/client/federation/informers/externalversions/pingcap/v1alpha1" + listers "github.com/pingcap/tidb-operator/pkg/client/federation/listers/pingcap/v1alpha1" +) + +// FedVolumeBackupControlInterface manages federaton VolumeBackups used in VolumeBackupSchedule +type FedVolumeBackupControlInterface interface { + CreateVolumeBackup(backup *v1alpha1.VolumeBackup) (*v1alpha1.VolumeBackup, error) + DeleteVolumeBackup(backup *v1alpha1.VolumeBackup) error +} + +type realFedVolumeBackupControl struct { + cli versioned.Interface + recorder record.EventRecorder +} + +// NewRealFedVolumeBackupControl creates a new FedVolumeBackupControlInterface +func NewRealFedVolumeBackupControl( + cli versioned.Interface, + recorder record.EventRecorder, +) FedVolumeBackupControlInterface { + return &realFedVolumeBackupControl{ + cli: cli, + recorder: recorder, + } +} + +func (c *realFedVolumeBackupControl) CreateVolumeBackup(volumeBackup *v1alpha1.VolumeBackup) (*v1alpha1.VolumeBackup, error) { + ns := volumeBackup.GetNamespace() + backupName := volumeBackup.GetName() + + bsName := volumeBackup.GetLabels()[label.BackupScheduleLabelKey] + volumeBackup, err := c.cli.FederationV1alpha1().VolumeBackups(ns).Create(context.TODO(), volumeBackup, metav1.CreateOptions{}) + if err != nil { + klog.Errorf("failed to create VolumeBackup: [%s/%s] for volumeBackupSchedule/%s, err: %v", ns, backupName, bsName, err) + } else { + klog.V(4).Infof("create VolumeBackup: [%s/%s] for volumeBackupSchedule/%s successfully", ns, backupName, bsName) + } + c.recordVolumeBackupEvent("create", volumeBackup, err) + return volumeBackup, err +} + +func (c *realFedVolumeBackupControl) DeleteVolumeBackup(volumeBackup *v1alpha1.VolumeBackup) error { + ns := volumeBackup.GetNamespace() + backupName := volumeBackup.GetName() + + bsName := volumeBackup.GetLabels()[label.BackupScheduleLabelKey] + err := c.cli.FederationV1alpha1().VolumeBackups(ns).Delete(context.TODO(), backupName, metav1.DeleteOptions{}) + if err != nil { + klog.Errorf("failed to delete VolumeBackup: [%s/%s] for volumeBackupSchedule/%s, err: %v", ns, backupName, bsName, err) + } else { + klog.V(4).Infof("delete Volumebackup: [%s/%s] successfully, volumeBackupSchedule/%s", ns, backupName, bsName) + } + c.recordVolumeBackupEvent("delete", volumeBackup, err) + return err +} + +func (c *realFedVolumeBackupControl) recordVolumeBackupEvent(verb string, volumeBackup *v1alpha1.VolumeBackup, err error) { + backupName := volumeBackup.GetName() + ns := volumeBackup.GetNamespace() + + bsName := volumeBackup.GetLabels()[label.BackupScheduleLabelKey] + if err == nil { + reason := fmt.Sprintf("Successful%s", strings.Title(verb)) + msg := fmt.Sprintf("%s VolumeBackup %s/%s for volumeBackupSchedule/%s successful", + strings.ToLower(verb), ns, backupName, bsName) + c.recorder.Event(volumeBackup, corev1.EventTypeNormal, reason, msg) + } else { + reason := fmt.Sprintf("Failed%s", strings.Title(verb)) + msg := fmt.Sprintf("%s VolumeBackup %s/%s for volumeBackupSchedule/%s failed error: %s", + strings.ToLower(verb), ns, backupName, bsName, err) + c.recorder.Event(volumeBackup, corev1.EventTypeWarning, reason, msg) + } +} + +var _ FedVolumeBackupControlInterface = &realFedVolumeBackupControl{} + +// FakeFedVolumeBackupControl is a fake FedVolumeBackupControlInterface +type FakeFedVolumeBackupControl struct { + volumeBackupLister listers.VolumeBackupLister + volumeBackupIndexer cache.Indexer + createVolumeBackupTracker RequestTracker + deleteVolumeBackupTracker RequestTracker +} + +// NewFakeBackupControl returns a FakeBackupControl +func NewFakeFedVolumeBackupControl(volumeBackupInformer informers.VolumeBackupInformer) *FakeFedVolumeBackupControl { + return &FakeFedVolumeBackupControl{ + volumeBackupInformer.Lister(), + volumeBackupInformer.Informer().GetIndexer(), + RequestTracker{}, + RequestTracker{}, + } +} + +// SetCreateVolumeBackupError sets the error attributes of createVolumeBackupTracker +func (fbc *FakeFedVolumeBackupControl) SetCreateVolumeBackupError(err error, after int) { + fbc.createVolumeBackupTracker.SetError(err).SetAfter(after) +} + +// SetDeleteVolumeBackupError sets the error attributes of deleteVolumeBackupTracker +func (fbc *FakeFedVolumeBackupControl) SetDeleteVolumeBackupError(err error, after int) { + fbc.deleteVolumeBackupTracker.SetError(err).SetAfter(after) +} + +// CreateVolumeBackup adds the volumeBackup to VolumeBackupIndexer +func (fbc *FakeFedVolumeBackupControl) CreateVolumeBackup(volumeBackup *v1alpha1.VolumeBackup) (*v1alpha1.VolumeBackup, error) { + defer fbc.createVolumeBackupTracker.Inc() + if fbc.createVolumeBackupTracker.ErrorReady() { + defer fbc.createVolumeBackupTracker.Reset() + return volumeBackup, fbc.createVolumeBackupTracker.GetError() + } + + return volumeBackup, fbc.volumeBackupIndexer.Add(volumeBackup) +} + +// DeleteVolumeBackup deletes the volumeBackup from VolumeBackupIndexer +func (fbc *FakeFedVolumeBackupControl) DeleteVolumeBackup(volumeBackup *v1alpha1.VolumeBackup) error { + defer fbc.createVolumeBackupTracker.Inc() + if fbc.createVolumeBackupTracker.ErrorReady() { + defer fbc.createVolumeBackupTracker.Reset() + return fbc.createVolumeBackupTracker.GetError() + } + + return fbc.volumeBackupIndexer.Delete(volumeBackup) +} + +var _ BackupControlInterface = &FakeBackupControl{} diff --git a/pkg/controller/fedvolumebackup/fed_volume_backup_control.go b/pkg/controller/fedvolumebackup/fed_volume_backup_control.go new file mode 100644 index 0000000000..9ad843b5ea --- /dev/null +++ b/pkg/controller/fedvolumebackup/fed_volume_backup_control.go @@ -0,0 +1,171 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package fedvolumebackup + +import ( + "context" + "fmt" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/tools/cache" + "k8s.io/klog/v2" + "k8s.io/kubernetes/pkg/util/slice" + + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/apis/label" + "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned" + informers "github.com/pingcap/tidb-operator/pkg/client/federation/informers/externalversions/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/controller" + "github.com/pingcap/tidb-operator/pkg/fedvolumebackup" +) + +// ControlInterface implements the control logic for updating VolumeBackup +// It is implemented as an interface to allow for extensions that provide different semantics. +// Currently, there is only one implementation. +type ControlInterface interface { + // UpdateBackup implements the control logic for VolumeBackup's creation, deletion + UpdateBackup(volumeBackup *v1alpha1.VolumeBackup) error + // UpdateStatus updates the status for a VolumeBackup, include condition and status info + // NOTE(federation): add a separate struct for newStatus as non-federation backup control did if needed + UpdateStatus(volumeBackup *v1alpha1.VolumeBackup, newStatus *v1alpha1.VolumeBackupStatus) error +} + +// NewDefaultVolumeBackupControl returns a new instance of the default VolumeBackup ControlInterface implementation. +func NewDefaultVolumeBackupControl( + cli versioned.Interface, + backupManager fedvolumebackup.BackupManager) ControlInterface { + return &defaultBackupControl{ + cli, + backupManager, + } +} + +type defaultBackupControl struct { + cli versioned.Interface + backupManager fedvolumebackup.BackupManager +} + +// UpdateBackup executes the core logic loop for a VolumeBackup. +func (c *defaultBackupControl) UpdateBackup(volumeBackup *v1alpha1.VolumeBackup) error { + volumeBackup.SetGroupVersionKind(controller.FedVolumeBackupControllerKind) + if err := c.addProtectionFinalizer(volumeBackup); err != nil { + return err + } + + if err := c.removeProtectionFinalizer(volumeBackup); err != nil { + return err + } + + return c.updateBackup(volumeBackup) +} + +// UpdateStatus updates the status for a VolumeBackup, include condition and status info +func (c *defaultBackupControl) UpdateStatus(volumeBackup *v1alpha1.VolumeBackup, newStatus *v1alpha1.VolumeBackupStatus) error { + return c.backupManager.UpdateStatus(volumeBackup, newStatus) +} + +func (c *defaultBackupControl) updateBackup(volumeBackup *v1alpha1.VolumeBackup) error { + return c.backupManager.Sync(volumeBackup) +} + +// addProtectionFinalizer will be called when the VolumeBackup CR is created +func (c *defaultBackupControl) addProtectionFinalizer(volumeBackup *v1alpha1.VolumeBackup) error { + ns := volumeBackup.GetNamespace() + name := volumeBackup.GetName() + + if needToAddFinalizer(volumeBackup) { + volumeBackup.Finalizers = append(volumeBackup.Finalizers, label.BackupProtectionFinalizer) + _, err := c.cli.FederationV1alpha1().VolumeBackups(ns).Update(context.TODO(), volumeBackup, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("add VolumeBackup %s/%s protection finalizers failed, err: %v", ns, name, err) + } + } + return nil +} + +func (c *defaultBackupControl) removeProtectionFinalizer(volumeBackup *v1alpha1.VolumeBackup) error { + ns := volumeBackup.GetNamespace() + name := volumeBackup.GetName() + + if needToRemoveFinalizer(volumeBackup) { + volumeBackup.Finalizers = slice.RemoveString(volumeBackup.Finalizers, label.BackupProtectionFinalizer, nil) + _, err := c.cli.FederationV1alpha1().VolumeBackups(ns).Update(context.TODO(), volumeBackup, metav1.UpdateOptions{}) + if err != nil { + return fmt.Errorf("remove VolumeBackup %s/%s protection finalizers failed, err: %v", ns, name, err) + } + klog.Infof("remove VolumeBackup %s/%s protection finalizers success", ns, name) + return controller.RequeueErrorf(fmt.Sprintf("VolumeBackup %s/%s has been cleaned up", ns, name)) + } + return nil +} + +func needToAddFinalizer(volumeBackup *v1alpha1.VolumeBackup) bool { + // TODO(federation): add something like non-federation's `IsCleanCandidate` check if needed + return volumeBackup.DeletionTimestamp == nil && + !slice.ContainsString(volumeBackup.Finalizers, label.BackupProtectionFinalizer, nil) +} + +func needToRemoveFinalizer(volumeBackup *v1alpha1.VolumeBackup) bool { + // TODO(federation): add something like non-federation's + // `IsCleanCandidate`, `IsBackupClean`, `NeedNotClean` check if needed + return isDeletionCandidate(volumeBackup) +} + +func isDeletionCandidate(volumeBackup *v1alpha1.VolumeBackup) bool { + return volumeBackup.DeletionTimestamp != nil && slice.ContainsString(volumeBackup.Finalizers, label.BackupProtectionFinalizer, nil) +} + +var _ ControlInterface = &defaultBackupControl{} + +// FakeBackupControl is a fake BackupControlInterface +type FakeBackupControl struct { + backupIndexer cache.Indexer + updateBackupTracker controller.RequestTracker + condition *v1alpha1.VolumeBackupCondition +} + +// NewFakeBackupControl returns a FakeBackupControl +func NewFakeBackupControl(backupInformer informers.VolumeBackupInformer) *FakeBackupControl { + return &FakeBackupControl{ + backupInformer.Informer().GetIndexer(), + controller.RequestTracker{}, + nil, + } +} + +// SetUpdateBackupError sets the error attributes of updateBackupTracker +func (c *FakeBackupControl) SetUpdateBackupError(err error, after int) { + c.updateBackupTracker.SetError(err).SetAfter(after) +} + +// UpdateBackup adds the VolumeBackup to BackupIndexer +func (c *FakeBackupControl) UpdateBackup(volumeBackup *v1alpha1.VolumeBackup) error { + defer c.updateBackupTracker.Inc() + if c.updateBackupTracker.ErrorReady() { + defer c.updateBackupTracker.Reset() + return c.updateBackupTracker.GetError() + } + + return c.backupIndexer.Add(volumeBackup) +} + +// UpdateStatus updates the status for a VolumeBackup, include condition and status info +func (c *FakeBackupControl) UpdateStatus(_ *v1alpha1.VolumeBackup, newStatus *v1alpha1.VolumeBackupStatus) error { + if len(newStatus.Conditions) > 0 { + c.condition = &newStatus.Conditions[0] + } + return nil +} + +var _ ControlInterface = &FakeBackupControl{} diff --git a/pkg/controller/fedvolumebackup/fed_volume_backup_controller.go b/pkg/controller/fedvolumebackup/fed_volume_backup_controller.go new file mode 100644 index 0000000000..e195c9592b --- /dev/null +++ b/pkg/controller/fedvolumebackup/fed_volume_backup_controller.go @@ -0,0 +1,176 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package fedvolumebackup + +import ( + "fmt" + "time" + + perrors "github.com/pingcap/errors" + "k8s.io/apimachinery/pkg/api/errors" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog/v2" + + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/controller" + "github.com/pingcap/tidb-operator/pkg/fedvolumebackup/backup" + "github.com/pingcap/tidb-operator/pkg/metrics" +) + +// Controller controls VolumeBackup. +type Controller struct { + deps *controller.BrFedDependencies + // control returns an interface capable of syncing a VolumeBackup. + // Abstracted out for testing. + control ControlInterface + // VolumeBackups that need to be synced. + queue workqueue.RateLimitingInterface +} + +// NewController creates a VolumeBackup controller. +func NewController(deps *controller.BrFedDependencies) *Controller { + c := &Controller{ + deps: deps, + control: NewDefaultVolumeBackupControl(deps.Clientset, backup.NewBackupManager(deps)), + queue: workqueue.NewNamedRateLimitingQueue( + controller.NewControllerRateLimiter(1*time.Second, 100*time.Second), + "volumeBackup", + ), + } + + volumeBackupInformer := deps.InformerFactory.Federation().V1alpha1().VolumeBackups() + volumeBackupInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: c.updateBackup, + UpdateFunc: func(old, cur interface{}) { + c.updateBackup(cur) + }, + DeleteFunc: c.updateBackup, + }) + + return c +} + +// Name returns VolumeBackup controller name. +func (c *Controller) Name() string { + return "volumeBackup" +} + +// Run runs the VolumeBackup controller. +func (c *Controller) Run(workers int, stopCh <-chan struct{}) { + defer utilruntime.HandleCrash() + defer c.queue.ShutDown() + + klog.Info("Starting volumeBackup controller") + defer klog.Info("Shutting down volumeBackup controller") + + for i := 0; i < workers; i++ { + go wait.Until(c.worker, time.Second, stopCh) + } + + <-stopCh +} + +// worker runs a worker goroutine that invokes processNextWorkItem until the the controller's queue is closed +func (c *Controller) worker() { + for c.processNextWorkItem() { + } +} + +// processNextWorkItem dequeues items, processes them, and marks them done. It enforces that the syncHandler is never +// invoked concurrently with the same key. +func (c *Controller) processNextWorkItem() bool { + metrics.ActiveWorkers.WithLabelValues(c.Name()).Add(1) + defer metrics.ActiveWorkers.WithLabelValues(c.Name()).Add(-1) + + key, quit := c.queue.Get() + if quit { + return false + } + defer c.queue.Done(key) + if err := c.sync(key.(string)); err != nil { + if perrors.Find(err, controller.IsRequeueError) != nil { + klog.Infof("VolumeBackup: %v, still need sync: %v, requeuing", key.(string), err) + c.queue.AddRateLimited(key) + } else if perrors.Find(err, controller.IsIgnoreError) != nil { + klog.V(4).Infof("VolumeBackup: %v, ignore err: %v", key.(string), err) + } else { + utilruntime.HandleError(fmt.Errorf("VolumeBackup: %v, sync failed, err: %v, requeuing", key.(string), err)) + c.queue.AddRateLimited(key) + } + } else { + c.queue.Forget(key) + } + return true +} + +// sync syncs the given VolumeBackup. +func (c *Controller) sync(key string) error { + startTime := time.Now() + defer func() { + duration := time.Since(startTime) + metrics.ReconcileTime.WithLabelValues(c.Name()).Observe(duration.Seconds()) + klog.V(4).Infof("Finished syncing VolumeBackup %q (%v)", key, duration) + }() + + ns, name, err := cache.SplitMetaNamespaceKey(key) + if err != nil { + return err + } + volumeBackup, err := c.deps.VolumeBackupLister.VolumeBackups(ns).Get(name) + if errors.IsNotFound(err) { + klog.Infof("VolumeBackup has been deleted %v", key) + return nil + } + if err != nil { + return err + } + + return c.syncBackup(volumeBackup.DeepCopy()) +} + +func (c *Controller) syncBackup(volumeBackup *v1alpha1.VolumeBackup) error { + return c.control.UpdateBackup(volumeBackup) +} + +func (c *Controller) updateBackup(cur interface{}) { + newVolumeBackup := cur.(*v1alpha1.VolumeBackup) + ns := newVolumeBackup.GetNamespace() + name := newVolumeBackup.GetName() + + if newVolumeBackup.DeletionTimestamp != nil { + // the backup is being deleted, we need to do some cleanup work, enqueue backup. + klog.Infof("VolumeBackup %s/%s is being deleted", ns, name) + c.enqueueBackup(newVolumeBackup) + return + } + + // TODO(federation): check something like non-federation's + // `IsBackupInvalid`, `IsBackupComplete`, `IsBackupFailed`, `IsBackupScheduled`, `IsBackupRunning`, `IsBackupPrepared`, `IsLogBackupStopped + + klog.V(4).Infof("VolumeBackup object %s/%s enqueue", ns, name) + c.enqueueBackup(newVolumeBackup) +} + +// enqueueBackup enqueues the given VolumeBackup in the work queue. +func (c *Controller) enqueueBackup(obj interface{}) { + key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj) + if err != nil { + utilruntime.HandleError(fmt.Errorf("cound't get key for object %+v: %v", obj, err)) + return + } + c.queue.Add(key) +} diff --git a/pkg/controller/fedvolumebackupschedule/fed_volume_backup_schedule_control.go b/pkg/controller/fedvolumebackupschedule/fed_volume_backup_schedule_control.go new file mode 100644 index 0000000000..ad568e2eaf --- /dev/null +++ b/pkg/controller/fedvolumebackupschedule/fed_volume_backup_schedule_control.go @@ -0,0 +1,86 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package fedvolumebackupschedule + +import ( + "k8s.io/client-go/tools/cache" + + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned" + informers "github.com/pingcap/tidb-operator/pkg/client/federation/informers/externalversions/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/controller" + "github.com/pingcap/tidb-operator/pkg/fedvolumebackup" +) + +// ControlInterface implements the control logic for updating VolumeBackupSchedule +// It is implemented as an interface to allow for extensions that provide different semantics. +// Currently, there is only one implementation. +type ControlInterface interface { + // UpdateBackupSchedule implements the control logic for VolumeBackupSchedule + UpdateBackupSchedule(volumeBackupSchedule *v1alpha1.VolumeBackupSchedule) error +} + +// NewDefaultVolumeBackupScheduleControl returns a new instance of the default VolumeBackupSchedue ControlInterface implementation. +func NewDefaultVolumeBackupScheduleControl( + cli versioned.Interface, + backupScheduleManager fedvolumebackup.BackupScheduleManager) ControlInterface { + return &defaultBackupScheduleControl{ + cli, + backupScheduleManager, + } +} + +type defaultBackupScheduleControl struct { + cli versioned.Interface + bsManager fedvolumebackup.BackupScheduleManager +} + +// UpdateBackupSchedule executes the core logic loop for a VolumeBackupSchedule. +func (c *defaultBackupScheduleControl) UpdateBackupSchedule(volumeBackupSchedule *v1alpha1.VolumeBackupSchedule) error { + return c.bsManager.Sync(volumeBackupSchedule) +} + +var _ ControlInterface = &defaultBackupScheduleControl{} + +// FakeBackupScheduleControl is a fake BackupScheduleControlInterface +type FakeBackupScheduleControl struct { + bsIndexer cache.Indexer + updateBsTracker controller.RequestTracker +} + +// NewFakeBackupScheduleControl returns a FakeBackupScheduleControl +func NewFakeBackupScheduleControl(bsInformer informers.VolumeBackupScheduleInformer) *FakeBackupScheduleControl { + return &FakeBackupScheduleControl{ + bsInformer.Informer().GetIndexer(), + controller.RequestTracker{}, + } +} + +// SetUpdateBackupError sets the error attributes of updateBackupTracker +func (c *FakeBackupScheduleControl) SetUpdateBackupError(err error, after int) { + c.updateBsTracker.SetError(err).SetAfter(after) +} + +// UpdateBackupSchedule updates the VolumeBackupSchedule to BackupScheduleIndexer +func (c *FakeBackupScheduleControl) UpdateBackupSchedule(volumeBackupSchedule *v1alpha1.VolumeBackupSchedule) error { + defer c.updateBsTracker.Inc() + if c.updateBsTracker.ErrorReady() { + defer c.updateBsTracker.Reset() + return c.updateBsTracker.GetError() + } + + return c.bsIndexer.Add(volumeBackupSchedule) +} + +var _ ControlInterface = &FakeBackupScheduleControl{} diff --git a/pkg/controller/fedvolumebackupschedule/fed_volume_backup_schedule_controller.go b/pkg/controller/fedvolumebackupschedule/fed_volume_backup_schedule_controller.go new file mode 100644 index 0000000000..d3db48aa16 --- /dev/null +++ b/pkg/controller/fedvolumebackupschedule/fed_volume_backup_schedule_controller.go @@ -0,0 +1,166 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package fedvolumebackupschedule + +import ( + "fmt" + "time" + + perrors "github.com/pingcap/errors" + "k8s.io/apimachinery/pkg/api/errors" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog/v2" + + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/controller" + "github.com/pingcap/tidb-operator/pkg/fedvolumebackup/backupschedule" + "github.com/pingcap/tidb-operator/pkg/metrics" +) + +// Controller controls VolumeBackupSchedule. +type Controller struct { + deps *controller.BrFedDependencies + // control returns an interface capable of syncing a VolumeBackupSchedule. + // Abstracted out for testing. + control ControlInterface + // VolumeBackupSchedules that need to be synced. + queue workqueue.RateLimitingInterface +} + +// NewController creates a VolumeBackupSchedule controller. +func NewController(deps *controller.BrFedDependencies) *Controller { + c := &Controller{ + deps: deps, + control: NewDefaultVolumeBackupScheduleControl(deps.Clientset, backupschedule.NewBackupScheduleManager(deps)), + queue: workqueue.NewNamedRateLimitingQueue( + controller.NewControllerRateLimiter(1*time.Second, 100*time.Second), + "volumeBackupSchedule", + ), + } + + volumeBackupScheduleInformer := deps.InformerFactory.Federation().V1alpha1().VolumeBackupSchedules() + volumeBackupScheduleInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: c.updateBackupSchedule, + UpdateFunc: func(old, cur interface{}) { + c.updateBackupSchedule(cur) + }, + DeleteFunc: c.updateBackupSchedule, + }) + + return c +} + +// Name returns VolumeBackupSchedule controller name. +func (c *Controller) Name() string { + return "volumeBackupSchedule" +} + +// Run runs the VolumeBackupSchedule controller. +func (c *Controller) Run(workers int, stopCh <-chan struct{}) { + defer utilruntime.HandleCrash() + defer c.queue.ShutDown() + + klog.Info("Starting volumeBackupSchedule controller") + defer klog.Info("Shutting down volumeBackupSchedule controller") + + for i := 0; i < workers; i++ { + go wait.Until(c.worker, time.Second, stopCh) + } + + <-stopCh +} + +// worker runs a worker goroutine that invokes processNextWorkItem until the the controller's queue is closed +func (c *Controller) worker() { + for c.processNextWorkItem() { + } +} + +// processNextWorkItem dequeues items, processes them, and marks them done. It enforces that the syncHandler is never +// invoked concurrently with the same key. +func (c *Controller) processNextWorkItem() bool { + metrics.ActiveWorkers.WithLabelValues(c.Name()).Add(1) + defer metrics.ActiveWorkers.WithLabelValues(c.Name()).Add(-1) + + key, quit := c.queue.Get() + if quit { + return false + } + defer c.queue.Done(key) + if err := c.sync(key.(string)); err != nil { + if perrors.Find(err, controller.IsRequeueError) != nil { + klog.Infof("VolumeBackupSchedule: %v, still need sync: %v, requeuing", key.(string), err) + c.queue.AddRateLimited(key) + } else if perrors.Find(err, controller.IsIgnoreError) != nil { + klog.V(4).Infof("VolumeBackupSchedule: %v, ignore err: %v", key.(string), err) + } else { + utilruntime.HandleError(fmt.Errorf("VolumeBackupSchedule: %v, sync failed, err: %v, requeuing", key.(string), err)) + c.queue.AddRateLimited(key) + } + } else { + c.queue.Forget(key) + } + return true +} + +// sync syncs the given VolumeBackupSchedule. +func (c *Controller) sync(key string) error { + startTime := time.Now() + defer func() { + duration := time.Since(startTime) + metrics.ReconcileTime.WithLabelValues(c.Name()).Observe(duration.Seconds()) + klog.V(4).Infof("Finished syncing VolumeBackupSchedule %q (%v)", key, duration) + }() + + ns, name, err := cache.SplitMetaNamespaceKey(key) + if err != nil { + return err + } + volumeBackupSchedule, err := c.deps.VolumeBackupScheduleLister.VolumeBackupSchedules(ns).Get(name) + if errors.IsNotFound(err) { + klog.Infof("VolumeBackupSchedule has been deleted %v", key) + return nil + } + if err != nil { + return err + } + + return c.syncBackupSchedule(volumeBackupSchedule.DeepCopy()) +} + +func (c *Controller) syncBackupSchedule(volumeBackupSchedule *v1alpha1.VolumeBackupSchedule) error { + return c.control.UpdateBackupSchedule(volumeBackupSchedule) +} + +func (c *Controller) updateBackupSchedule(cur interface{}) { + newVolumeBackupSchedule := cur.(*v1alpha1.VolumeBackupSchedule) + ns := newVolumeBackupSchedule.GetNamespace() + name := newVolumeBackupSchedule.GetName() + klog.V(4).Infof("VolumeBackupSchedule object %s/%s enqueue", ns, name) + + c.enqueueBackupSchedule(newVolumeBackupSchedule) +} + +// enqueueBackupSchedule enqueues the given VolumeBackupSchedule in the work queue. +func (c *Controller) enqueueBackupSchedule(obj interface{}) { + key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj) + if err != nil { + utilruntime.HandleError(fmt.Errorf("cound't get key for object %+v: %v", obj, err)) + return + } + c.queue.Add(key) +} diff --git a/pkg/controller/fedvolumerestore/fed_volume_restore_control.go b/pkg/controller/fedvolumerestore/fed_volume_restore_control.go new file mode 100644 index 0000000000..44f5d77b3e --- /dev/null +++ b/pkg/controller/fedvolumerestore/fed_volume_restore_control.go @@ -0,0 +1,102 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package fedvolumerestore + +import ( + "k8s.io/client-go/tools/cache" + + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/client/federation/clientset/versioned" + informers "github.com/pingcap/tidb-operator/pkg/client/federation/informers/externalversions/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/controller" + "github.com/pingcap/tidb-operator/pkg/fedvolumebackup" +) + +// ControlInterface implements the control logic for updating VolumeRestore +// It is implemented as an interface to allow for extensions that provide different semantics. +// Currently, there is only one implementation. +type ControlInterface interface { + // UpdateRestore implements the control logic for VolumeRestore's creation, deletion + UpdateRestore(volumeRestore *v1alpha1.VolumeRestore) error + // UpdateCondition updates the condition for a VolumeRestore + UpdateCondition(volumeRestore *v1alpha1.VolumeRestore, condition *v1alpha1.VolumeRestoreCondition) error +} + +// NewDefaultVolumeRestoreControl returns a new instance of the default VolumeRestore ControlInterface implementation. +func NewDefaultVolumeRestoreControl( + cli versioned.Interface, + restoreManager fedvolumebackup.RestoreManager) ControlInterface { + return &defaultRestoreControl{ + cli, + restoreManager, + } +} + +type defaultRestoreControl struct { + cli versioned.Interface + restoreManager fedvolumebackup.RestoreManager +} + +// UpdateRestore executes the core logic loop for a VolumeRestore. +func (c *defaultRestoreControl) UpdateRestore(volumeRestore *v1alpha1.VolumeRestore) error { + volumeRestore.SetGroupVersionKind(controller.FedVolumeRestoreControllerKind) + return c.restoreManager.Sync(volumeRestore) +} + +// UpdateCondition updates the condition for a VolumeRestore +func (c *defaultRestoreControl) UpdateCondition(volumeRestore *v1alpha1.VolumeRestore, condition *v1alpha1.VolumeRestoreCondition) error { + return c.restoreManager.UpdateCondition(volumeRestore, condition) +} + +var _ ControlInterface = &defaultRestoreControl{} + +// FakeRestoreControl is a fake RestoreControlInterface +type FakeRestoreControl struct { + restoreIndexer cache.Indexer + updateRestoreTracker controller.RequestTracker + condition *v1alpha1.VolumeRestoreCondition +} + +// NewFakeRestoreControl returns a FakeRestoreControl +func NewFakeRestoreControl(restoreInformer informers.VolumeRestoreInformer) *FakeRestoreControl { + return &FakeRestoreControl{ + restoreInformer.Informer().GetIndexer(), + controller.RequestTracker{}, + nil, + } +} + +// SetUpdateRestoreError sets the error attributes of updateRestoreTracker +func (c *FakeRestoreControl) SetUpdateRestoreError(err error, after int) { + c.updateRestoreTracker.SetError(err).SetAfter(after) +} + +// UpdateRestore adds the VolumeRestore to RestoreIndexer +func (c *FakeRestoreControl) UpdateRestore(volumeRestore *v1alpha1.VolumeRestore) error { + defer c.updateRestoreTracker.Inc() + if c.updateRestoreTracker.ErrorReady() { + defer c.updateRestoreTracker.Reset() + return c.updateRestoreTracker.GetError() + } + + return c.restoreIndexer.Add(volumeRestore) +} + +// UpdateStatus updates the condition for a VolumeRestore, include condition and status info +func (c *FakeRestoreControl) UpdateCondition(_ *v1alpha1.VolumeRestore, condition *v1alpha1.VolumeRestoreCondition) error { + c.condition = condition + return nil +} + +var _ ControlInterface = &FakeRestoreControl{} diff --git a/pkg/controller/fedvolumerestore/fed_volume_restore_controller.go b/pkg/controller/fedvolumerestore/fed_volume_restore_controller.go new file mode 100644 index 0000000000..53287b9d98 --- /dev/null +++ b/pkg/controller/fedvolumerestore/fed_volume_restore_controller.go @@ -0,0 +1,169 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package fedvolumerestore + +import ( + "fmt" + "time" + + perrors "github.com/pingcap/errors" + "k8s.io/apimachinery/pkg/api/errors" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog/v2" + + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/controller" + "github.com/pingcap/tidb-operator/pkg/fedvolumebackup/restore" + "github.com/pingcap/tidb-operator/pkg/metrics" +) + +// Controller controls VolumeRestore. +type Controller struct { + deps *controller.BrFedDependencies + // control returns an interface capable of syncing a VolumeRestore. + // Abstracted out for testing. + control ControlInterface + // VolumeRestores that need to be synced. + queue workqueue.RateLimitingInterface +} + +// NewController creates a VolumeRestore controller. +func NewController(deps *controller.BrFedDependencies) *Controller { + c := &Controller{ + deps: deps, + control: NewDefaultVolumeRestoreControl(deps.Clientset, restore.NewRestoreManager(deps)), + queue: workqueue.NewNamedRateLimitingQueue( + controller.NewControllerRateLimiter(1*time.Second, 100*time.Second), + "volumeRestore", + ), + } + + volumeRestoreInformer := deps.InformerFactory.Federation().V1alpha1().VolumeRestores() + volumeRestoreInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: c.updateRestore, + UpdateFunc: func(old, cur interface{}) { + c.updateRestore(cur) + }, + DeleteFunc: c.updateRestore, + }) + + return c +} + +// Name returns VolumeRestore controller name. +func (c *Controller) Name() string { + return "volumeRestore" +} + +// Run runs the VolumeRestore controller. +func (c *Controller) Run(workers int, stopCh <-chan struct{}) { + defer utilruntime.HandleCrash() + defer c.queue.ShutDown() + + klog.Info("Starting volumeRestore controller") + defer klog.Info("Shutting down volumeRestore controller") + + for i := 0; i < workers; i++ { + go wait.Until(c.worker, time.Second, stopCh) + } + + <-stopCh +} + +// worker runs a worker goroutine that invokes processNextWorkItem until the the controller's queue is closed +func (c *Controller) worker() { + for c.processNextWorkItem() { + } +} + +// processNextWorkItem dequeues items, processes them, and marks them done. It enforces that the syncHandler is never +// invoked concurrently with the same key. +func (c *Controller) processNextWorkItem() bool { + metrics.ActiveWorkers.WithLabelValues(c.Name()).Add(1) + defer metrics.ActiveWorkers.WithLabelValues(c.Name()).Add(-1) + + key, quit := c.queue.Get() + if quit { + return false + } + defer c.queue.Done(key) + if err := c.sync(key.(string)); err != nil { + if perrors.Find(err, controller.IsRequeueError) != nil { + klog.Infof("VolumeRestore: %v, still need sync: %v, requeuing", key.(string), err) + c.queue.AddRateLimited(key) + } else if perrors.Find(err, controller.IsIgnoreError) != nil { + klog.V(4).Infof("VolumeRestore: %v, ignore err: %v", key.(string), err) + } else { + utilruntime.HandleError(fmt.Errorf("VolumeRestore: %v, sync failed, err: %v, requeuing", key.(string), err)) + c.queue.AddRateLimited(key) + } + } else { + c.queue.Forget(key) + } + return true +} + +// sync syncs the given VolumeRestore. +func (c *Controller) sync(key string) error { + startTime := time.Now() + defer func() { + duration := time.Since(startTime) + metrics.ReconcileTime.WithLabelValues(c.Name()).Observe(duration.Seconds()) + klog.V(4).Infof("Finished syncing VolumeRestore %q (%v)", key, duration) + }() + + ns, name, err := cache.SplitMetaNamespaceKey(key) + if err != nil { + return err + } + volumeRestore, err := c.deps.VolumeRestoreLister.VolumeRestores(ns).Get(name) + if errors.IsNotFound(err) { + klog.Infof("VolumeRestore has been deleted %v", key) + return nil + } + if err != nil { + return err + } + + return c.syncRestore(volumeRestore.DeepCopy()) +} + +func (c *Controller) syncRestore(volumeRestore *v1alpha1.VolumeRestore) error { + return c.control.UpdateRestore(volumeRestore) +} + +func (c *Controller) updateRestore(cur interface{}) { + newVolumeRestore := cur.(*v1alpha1.VolumeRestore) + ns := newVolumeRestore.GetNamespace() + name := newVolumeRestore.GetName() + + // TODO(federation): check something like non-federation's + // `IsRestoreInvalid`, `IsRestoreComplete`, `IsRestoreFailed`, `IsRestoreDataComplete`, `IsRestoreVolumeComplete`, `IsRestoreScheduled`, `IsRestoreRunning` + + klog.V(4).Infof("VolumeRestore object %s/%s enqueue", ns, name) + c.enqueueRestore(newVolumeRestore) +} + +// enqueueRestore enqueues the given VolumeRestore in the work queue. +func (c *Controller) enqueueRestore(obj interface{}) { + key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(obj) + if err != nil { + utilruntime.HandleError(fmt.Errorf("cound't get key for object %+v: %v", obj, err)) + return + } + c.queue.Add(key) +} diff --git a/pkg/fedvolumebackup/backup.go b/pkg/fedvolumebackup/backup.go new file mode 100644 index 0000000000..60911fdfa1 --- /dev/null +++ b/pkg/fedvolumebackup/backup.go @@ -0,0 +1,40 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package fedvolumebackup + +import ( + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" +) + +// BackupManager implements the logic for manage federation VolumeBackup. +type BackupManager interface { + // Sync implements the logic for syncing VolumeBackup. + Sync(volumeBackup *v1alpha1.VolumeBackup) error + // UpdateStatus updates the status for a VolumeBackup, include condition and status info. + UpdateStatus(volumeBackup *v1alpha1.VolumeBackup, newStatus *v1alpha1.VolumeBackupStatus) error +} + +// RestoreManager implements the logic for manage federation VolumeRestore. +type RestoreManager interface { + // Sync implements the logic for syncing VolumeRestore. + Sync(volumeRestore *v1alpha1.VolumeRestore) error + // UpdateCondition updates the condition for a VolumeRestore. + UpdateCondition(volumeRestore *v1alpha1.VolumeRestore, condition *v1alpha1.VolumeRestoreCondition) error +} + +// BackupScheduleManager implements the logic for manage federation VolumeBackupSchedule. +type BackupScheduleManager interface { + // Sync implements the logic for syncing VolumeBackupSchedule. + Sync(volumeBackup *v1alpha1.VolumeBackupSchedule) error +} diff --git a/pkg/fedvolumebackup/backup/backup_manager.go b/pkg/fedvolumebackup/backup/backup_manager.go new file mode 100644 index 0000000000..e210a6affb --- /dev/null +++ b/pkg/fedvolumebackup/backup/backup_manager.go @@ -0,0 +1,103 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package backup + +import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/klog/v2" + + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/controller" + "github.com/pingcap/tidb-operator/pkg/fedvolumebackup" +) + +type backupManager struct { + deps *controller.BrFedDependencies +} + +// NewBackupManager return backupManager +func NewBackupManager(deps *controller.BrFedDependencies) fedvolumebackup.BackupManager { + return &backupManager{ + deps: deps, + } +} + +func (bm *backupManager) Sync(volumeBackup *v1alpha1.VolumeBackup) error { + // because a finalizer is installed on the VolumeBackup on creation, when the VolumeBackup is deleted, + // volumeBackup.DeletionTimestamp will be set, controller will be informed with an onUpdate event, + // this is the moment that we can do clean up work. + // TODO(federation): do clean up work + + if volumeBackup.DeletionTimestamp != nil { + // volumeBackup is being deleted, don't do more things, return directly. + return nil + } + + return bm.syncBackup(volumeBackup) +} + +// UpdateStatus updates the status for a Backup, include condition and status info. +func (bm *backupManager) UpdateStatus(backup *v1alpha1.VolumeBackup, newStatus *v1alpha1.VolumeBackupStatus) error { + // TODO(federation): update status + return nil +} + +func (bm *backupManager) syncBackup(volumeBackup *v1alpha1.VolumeBackup) error { + ns := volumeBackup.GetNamespace() + name := volumeBackup.GetName() + + // TODO(federation): implement the main logic of backup + klog.Infof("sync VolumeBackup %s/%s", ns, name) + + // TODO(federation): remove the following code + for k8sName, k8sClient := range bm.deps.FedClientset { + bkList, err := k8sClient.PingcapV1alpha1().Backups("default").List(context.TODO(), metav1.ListOptions{}) + if err != nil { + klog.Errorf("failed to list backups in %s: %v", k8sName, err) + continue + } + for _, bk := range bkList.Items { + klog.Infof("get backup %s/%s", bk.Namespace, bk.Name) + } + } + + return nil +} + +var _ fedvolumebackup.BackupManager = &backupManager{} + +type FakeBackupManager struct { + err error +} + +func NewFakeBackupManager() *FakeBackupManager { + return &FakeBackupManager{} +} + +func (m *FakeBackupManager) SetSyncError(err error) { + m.err = err +} + +func (m *FakeBackupManager) Sync(_ *v1alpha1.VolumeBackup) error { + return m.err +} + +// UpdateStatus updates the status for a Backup, include condition and status info. +func (m *FakeBackupManager) UpdateStatus(_ *v1alpha1.VolumeBackup, newStatus *v1alpha1.VolumeBackupStatus) error { + return nil +} + +var _ fedvolumebackup.BackupManager = &FakeBackupManager{} diff --git a/pkg/fedvolumebackup/backupschedule/backup_schedule_manager.go b/pkg/fedvolumebackup/backupschedule/backup_schedule_manager.go new file mode 100644 index 0000000000..deeb552f97 --- /dev/null +++ b/pkg/fedvolumebackup/backupschedule/backup_schedule_manager.go @@ -0,0 +1,68 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package backupschedule + +import ( + "time" + + "k8s.io/klog/v2" + + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/controller" + "github.com/pingcap/tidb-operator/pkg/fedvolumebackup" +) + +type nowFn func() time.Time + +type backupScheduleManager struct { + deps *controller.BrFedDependencies + now nowFn +} + +// NewBackupScheduleManager return backupScheduleManager +func NewBackupScheduleManager(deps *controller.BrFedDependencies) fedvolumebackup.BackupScheduleManager { + return &backupScheduleManager{ + deps: deps, + now: time.Now, + } +} + +func (bm *backupScheduleManager) Sync(volumeBackupSchedule *v1alpha1.VolumeBackupSchedule) error { + ns := volumeBackupSchedule.GetNamespace() + name := volumeBackupSchedule.GetName() + // TODO(federation): implement the main logic of backupSchedule + klog.Infof("sync VolumeBackupSchedule %s/%s", ns, name) + + return nil +} + +var _ fedvolumebackup.BackupScheduleManager = &backupScheduleManager{} + +type FakeBackupScheduleManager struct { + err error +} + +func NewFakeBackupScheduleManager() *FakeBackupScheduleManager { + return &FakeBackupScheduleManager{} +} + +func (m *FakeBackupScheduleManager) SetSyncError(err error) { + m.err = err +} + +func (m *FakeBackupScheduleManager) Sync(_ *v1alpha1.VolumeBackupSchedule) error { + return m.err +} + +var _ fedvolumebackup.BackupScheduleManager = &FakeBackupScheduleManager{} diff --git a/pkg/fedvolumebackup/restore/restore_manager.go b/pkg/fedvolumebackup/restore/restore_manager.go new file mode 100644 index 0000000000..d241b920e2 --- /dev/null +++ b/pkg/fedvolumebackup/restore/restore_manager.go @@ -0,0 +1,78 @@ +// Copyright 2023 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package restore + +import ( + "k8s.io/klog/v2" + + "github.com/pingcap/tidb-operator/pkg/apis/federation/pingcap/v1alpha1" + "github.com/pingcap/tidb-operator/pkg/controller" + "github.com/pingcap/tidb-operator/pkg/fedvolumebackup" +) + +type restoreManager struct { + deps *controller.BrFedDependencies +} + +// NewRestoreManager return restoreManager +func NewRestoreManager(deps *controller.BrFedDependencies) fedvolumebackup.RestoreManager { + return &restoreManager{ + deps: deps, + } +} + +func (bm *restoreManager) Sync(volumeRestore *v1alpha1.VolumeRestore) error { + return bm.syncRestore(volumeRestore) +} + +// UpdateCondition updates the condition for a Restore. +func (bm *restoreManager) UpdateCondition(volumeRestore *v1alpha1.VolumeRestore, condition *v1alpha1.VolumeRestoreCondition) error { + // TODO(federation): update condition + return nil +} + +func (bm *restoreManager) syncRestore(volumeRestore *v1alpha1.VolumeRestore) error { + ns := volumeRestore.GetNamespace() + name := volumeRestore.GetName() + + // TODO(federation): implement the main logic of restore + klog.Infof("sync VolumeRestore %s/%s", ns, name) + + return nil +} + +var _ fedvolumebackup.RestoreManager = &restoreManager{} + +type FakeRestoreManager struct { + err error +} + +func NewFakeRestoreManager() *FakeRestoreManager { + return &FakeRestoreManager{} +} + +func (m *FakeRestoreManager) SetSyncError(err error) { + m.err = err +} + +func (m *FakeRestoreManager) Sync(_ *v1alpha1.VolumeRestore) error { + return m.err +} + +// UpdateStatus updates the condition for a Restore. +func (m *FakeRestoreManager) UpdateCondition(_ *v1alpha1.VolumeRestore, condition *v1alpha1.VolumeRestoreCondition) error { + return nil +} + +var _ fedvolumebackup.RestoreManager = &FakeRestoreManager{}