Removed recovery operations from agent

This commit is contained in:
Martin Montes
2024-07-28 13:41:30 +02:00
parent e34860822e
commit c036f1019e
10 changed files with 2 additions and 227 deletions

View File

@ -37,7 +37,6 @@ var (
kubernetesAuth bool
kubernetesTrustedName string
kubernetesTrustedNamespace string
recoveryTimeout time.Duration
gracefulShutdownTimeout time.Duration
)
@ -56,8 +55,6 @@ func init() {
RootCmd.Flags().StringVar(&kubernetesTrustedName, "kubernetes-trusted-name", "", "Trusted Kubernetes ServiceAccount name to be verified")
RootCmd.Flags().StringVar(&kubernetesTrustedNamespace, "kubernetes-trusted-namespace", "", "Trusted Kubernetes ServiceAccount "+
"namespace to be verified")
RootCmd.Flags().DurationVar(&recoveryTimeout, "recovery-timeout", 1*time.Minute, "Timeout to obtain sequence number "+
"during the Galera cluster recovery process")
RootCmd.Flags().DurationVar(&gracefulShutdownTimeout, "graceful-shutdown-timeout", 5*time.Second, "Timeout to gracefully terminate "+
"in-flight requests")
}
@ -102,7 +99,6 @@ var RootCmd = &cobra.Command{
fileManager,
state,
&handlerLogger,
handler.WithRecoveryTimeout(recoveryTimeout),
)
routerOpts := []router.Option{

View File

@ -1,6 +1,6 @@
##@ Build
DOCKER_ARGS ?=
DOCKER_ARGS ?= --load
.PHONY: build
build: ## Build binary.

View File

@ -171,7 +171,6 @@ func (b *Builder) maxscaleCommand(mxs *mariadbv1alpha1.MaxScale) (*command.Comma
func (b *Builder) galeraAgentContainer(mariadb *mariadbv1alpha1.MariaDB) (*corev1.Container, error) {
galera := ptr.Deref(mariadb.Spec.Galera, mariadbv1alpha1.Galera{})
recovery := ptr.Deref(galera.Recovery, mariadbv1alpha1.GaleraRecovery{})
agent := galera.Agent
container, err := b.buildContainer(agent.Image, agent.ImagePullPolicy, &agent.ContainerTemplate)
@ -197,9 +196,6 @@ func (b *Builder) galeraAgentContainer(mariadb *mariadbv1alpha1.MariaDB) (*corev
if agent.GracefulShutdownTimeout != nil {
args = append(args, fmt.Sprintf("--graceful-shutdown-timeout=%s", agent.GracefulShutdownTimeout.Duration))
}
if recovery.Enabled && recovery.PodRecoveryTimeout != nil {
args = append(args, fmt.Sprintf("--recovery-timeout=%s", recovery.PodRecoveryTimeout.Duration))
}
if ptr.Deref(agent.KubernetesAuth, mariadbv1alpha1.KubernetesAuth{}).Enabled {
args = append(args, []string{
"--kubernetes-auth",

View File

@ -12,7 +12,6 @@ import (
type Client struct {
Bootstrap *Bootstrap
State *State
Recovery *Recovery
}
func NewClient(baseUrl string, opts ...mdbhttp.Option) (*Client, error) {
@ -24,7 +23,6 @@ func NewClient(baseUrl string, opts ...mdbhttp.Option) (*Client, error) {
return &Client{
Bootstrap: NewBootstrap(httpClient),
State: NewState(httpClient),
Recovery: NewRecovery(httpClient),
}, nil
}

View File

@ -1,46 +0,0 @@
package client
import (
"context"
"github.com/mariadb-operator/mariadb-operator/pkg/galera/recovery"
mdbhttp "github.com/mariadb-operator/mariadb-operator/pkg/http"
)
type Recovery struct {
client *mdbhttp.Client
}
func NewRecovery(client *mdbhttp.Client) *Recovery {
return &Recovery{
client: client,
}
}
func (r *Recovery) Enable(ctx context.Context) error {
res, err := r.client.Put(ctx, "/api/recovery", nil, nil)
if err != nil {
return err
}
return handleResponse(res, nil)
}
func (r *Recovery) Start(ctx context.Context) (*recovery.Bootstrap, error) {
res, err := r.client.Post(ctx, "/api/recovery", nil, nil)
if err != nil {
return nil, err
}
var bootstrap recovery.Bootstrap
if err := handleResponse(res, &bootstrap); err != nil {
return nil, err
}
return &bootstrap, nil
}
func (r *Recovery) Disable(ctx context.Context) error {
res, err := r.client.Delete(ctx, "/api/recovery", nil, nil)
if err != nil {
return err
}
return handleResponse(res, nil)
}

View File

@ -59,11 +59,6 @@ func (b *Bootstrap) Enable(w http.ResponseWriter, r *http.Request) {
defer b.locker.Unlock()
b.logger.V(1).Info("enabling bootstrap")
if err := b.fileManager.DeleteConfigFile(recovery.RecoveryFileName); err != nil && !os.IsNotExist(err) {
b.responseWriter.WriteErrorf(w, "error deleting existing recovery config: %v", err)
return
}
if err := b.setSafeToBootstrap(&bootstrap); err != nil {
b.responseWriter.WriteErrorf(w, "error setting safe to bootstrap: %v", err)
return

View File

@ -14,16 +14,14 @@ import (
type Handler struct {
Bootstrap *Bootstrap
State *State
Recovery *Recovery
Probe *Probe
}
func NewHandler(mariadbKey types.NamespacedName, client ctrlclient.Client, fileManager *filemanager.FileManager,
initState *state.State, logger *logr.Logger, recoveryOpts ...RecoveryOption) *Handler {
initState *state.State, logger *logr.Logger) *Handler {
mux := &sync.RWMutex{}
bootstrapLogger := logger.WithName("bootstrap")
stateLogger := logger.WithName("state")
recoveryLogger := logger.WithName("recovery")
probeLogger := logger.WithName("probe")
bootstrap := NewBootstrap(
@ -39,13 +37,6 @@ func NewHandler(mariadbKey types.NamespacedName, client ctrlclient.Client, fileM
mux.RLocker(),
&stateLogger,
)
recovery := NewRecover(
fileManager,
mdbhttp.NewResponseWriter(&recoveryLogger),
mux,
&recoveryLogger,
recoveryOpts...,
)
probe := NewProbe(
mariadbKey,
client,
@ -56,7 +47,6 @@ func NewHandler(mariadbKey types.NamespacedName, client ctrlclient.Client, fileM
return &Handler{
Bootstrap: bootstrap,
State: state,
Recovery: recovery,
Probe: probe,
}
}

View File

@ -1,141 +0,0 @@
package handler
import (
"context"
"fmt"
"net/http"
"os"
"sync"
"time"
"github.com/go-logr/logr"
"github.com/mariadb-operator/mariadb-operator/pkg/galera/errors"
"github.com/mariadb-operator/mariadb-operator/pkg/galera/filemanager"
"github.com/mariadb-operator/mariadb-operator/pkg/galera/recovery"
mdbhttp "github.com/mariadb-operator/mariadb-operator/pkg/http"
"k8s.io/apimachinery/pkg/util/wait"
)
type Recovery struct {
fileManager *filemanager.FileManager
responseWriter *mdbhttp.ResponseWriter
locker sync.Locker
logger *logr.Logger
timeout time.Duration
}
type RecoveryOption func(*Recovery)
func WithRecoveryTimeout(timeout time.Duration) RecoveryOption {
return func(r *Recovery) {
r.timeout = timeout
}
}
func NewRecover(fileManager *filemanager.FileManager, responseWriter *mdbhttp.ResponseWriter, locker sync.Locker,
logger *logr.Logger, opts ...RecoveryOption) *Recovery {
recovery := &Recovery{
fileManager: fileManager,
responseWriter: responseWriter,
locker: locker,
logger: logger,
timeout: 1 * time.Minute,
}
for _, setOpts := range opts {
setOpts(recovery)
}
return recovery
}
func (r *Recovery) Enable(w http.ResponseWriter, req *http.Request) {
r.locker.Lock()
defer r.locker.Unlock()
r.logger.V(1).Info("enabling recovery")
if err := r.fileManager.DeleteConfigFile(recovery.BootstrapFileName); err != nil && !os.IsNotExist(err) {
r.responseWriter.WriteErrorf(w, "error deleting existing bootstrap config: %v", err)
return
}
if err := r.fileManager.DeleteStateFile(recovery.RecoveryLogFileName); err != nil && !os.IsNotExist(err) {
r.responseWriter.WriteErrorf(w, "error deleting existing recovery log: %v", err)
return
}
if err := r.fileManager.WriteConfigFile(recovery.RecoveryFileName, []byte(recovery.RecoveryFile)); err != nil {
r.responseWriter.WriteErrorf(w, "error writing recovery config: %v", err)
return
}
w.WriteHeader(http.StatusOK)
}
func (r *Recovery) Start(w http.ResponseWriter, req *http.Request) {
r.locker.Lock()
defer r.locker.Unlock()
r.logger.V(1).Info("starting recovery")
exists, err := r.fileManager.ConfigFileExists(recovery.RecoveryFileName)
if err != nil {
r.responseWriter.WriteErrorf(w, "error checking recovery config: %v", err)
return
}
if !exists {
r.responseWriter.Write(w, errors.NewAPIError("recovery config not found"), http.StatusNotFound)
return
}
recoveryCtx, cancel := context.WithTimeout(req.Context(), r.timeout)
defer cancel()
bootstrap, err := r.pollUntilRecovered(recoveryCtx)
if err != nil {
r.responseWriter.WriteErrorf(w, "error recovering galera: %v", err)
return
}
r.responseWriter.WriteOK(w, bootstrap)
}
func (r *Recovery) Disable(w http.ResponseWriter, req *http.Request) {
r.locker.Lock()
defer r.locker.Unlock()
r.logger.V(1).Info("disabling recovery")
if err := r.fileManager.DeleteConfigFile(recovery.RecoveryFileName); err != nil {
if os.IsNotExist(err) {
r.responseWriter.Write(w, errors.NewAPIError("recovery config not found"), http.StatusNotFound)
return
}
r.responseWriter.WriteErrorf(w, "error deleting recovery config: %v", err)
return
}
w.WriteHeader(http.StatusOK)
}
func (r *Recovery) pollUntilRecovered(ctx context.Context) (*recovery.Bootstrap, error) {
var bootstrap *recovery.Bootstrap
err := wait.PollUntilContextCancel(ctx, 1*time.Second, true, func(context.Context) (bool, error) {
b, err := r.recover()
if err != nil {
r.logger.Error(err, "error recovering galera from recovery log")
return false, nil
}
bootstrap = b
return true, nil
})
if err != nil {
return nil, err
}
return bootstrap, nil
}
func (r *Recovery) recover() (*recovery.Bootstrap, error) {
bytes, err := r.fileManager.ReadStateFile(recovery.RecoveryLogFileName)
if err != nil {
return nil, fmt.Errorf("error reading Galera state file: %v", err)
}
var bootstrap recovery.Bootstrap
if err := bootstrap.Unmarshal(bytes); err != nil {
return nil, fmt.Errorf("error unmarshaling bootstrap: %v", err)
}
return &bootstrap, nil
}

View File

@ -87,11 +87,6 @@ func apiRouter(h *handler.Handler, k8sClient ctrlclient.Client, logger logr.Logg
r.Route("/state", func(r chi.Router) {
r.Get("/galera", h.State.GetGaleraState)
})
r.Route("/recovery", func(r chi.Router) {
r.Put("/", h.Recovery.Enable)
r.Post("/", h.Recovery.Start)
r.Delete("/", h.Recovery.Disable)
})
return r
}

View File

@ -16,14 +16,6 @@ const (
BootstrapFileName = "1-bootstrap.cnf"
BootstrapFile = `[galera]
wsrep_new_cluster="ON"`
RecoveryFileName = "2-recovery.cnf"
RecoveryLogFileName = "mariadb.err"
)
var (
RecoveryFile = fmt.Sprintf(`[galera]
log_error=%s
wsrep_recover="ON"`, RecoveryLogFileName)
)
type GaleraRecoverer interface {