1
0
Fork 0
mirror of https://github.com/arangodb/kube-arangodb.git synced 2024-12-14 11:57:37 +00:00

[Feature] Add UpToDate Condition (#540)

This commit is contained in:
Adam Janikowski 2020-04-01 15:38:03 +02:00 committed by GitHub
parent fd8e98aee9
commit 99770ce2bc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 655 additions and 575 deletions

View file

@ -1,6 +1,7 @@
# Change Log
## [master](https://github.com/arangodb/kube-arangodb/tree/master) (N/A)
- Added UpToDate condition in ArangoDeployment Status
## [1.0.1](https://github.com/arangodb/kube-arangodb/tree/1.0.1) (2020-03-25)
- Added Customizable Affinity settings for ArangoDB Member Pods

View file

@ -59,6 +59,8 @@ const (
ConditionTypeBootstrapSucceded ConditionType = "BootstrapSucceded"
// ConditionTypeTerminating indicates that the member is terminating but not yet terminated.
ConditionTypeTerminating ConditionType = "Terminating"
// ConditionTypeTerminating indicates that the deployment is up to date.
ConditionTypeUpToDate ConditionType = "UpToDate"
)
// Condition represents one current condition of a deployment or deployment member.
@ -79,6 +81,10 @@ type Condition struct {
Message string `json:"message,omitempty"`
}
func (c Condition) IsTrue() bool {
return c.Status == v1.ConditionTrue
}
// ConditionList is a list of conditions.
// Each type is allowed only once.
type ConditionList []Condition
@ -116,12 +122,17 @@ func (c Condition) Equal(other Condition) bool {
// IsTrue return true when a condition with given type exists and its status is `True`.
func (list ConditionList) IsTrue(conditionType ConditionType) bool {
c, found := list.Get(conditionType)
return found && c.Status == v1.ConditionTrue
return found && c.IsTrue()
}
// Get a condition by type.
// Returns true if found, false if not found.
func (list ConditionList) Get(conditionType ConditionType) (Condition, bool) {
// Covers nil and empty lists
if len(list) == 0 {
return Condition{}, false
}
for _, x := range list {
if x.Type == conditionType {
return x, true

View file

@ -93,3 +93,13 @@ func (d *ArangoDeployment) ForeachServerGroup(cb ServerGroupFunc, status *Deploy
}
return nil
}
// IsUpToDate checks if applied version match current version in spec
func (d ArangoDeployment) IsUpToDate() (bool, error) {
sha, err := d.Spec.Checksum()
if err != nil {
return false, err
}
return sha == d.Status.AppliedVersion && d.Status.Conditions.IsTrue(ConditionTypeUpToDate), nil
}

View file

@ -23,6 +23,9 @@
package v1
import (
"crypto/sha256"
"encoding/json"
"fmt"
"reflect"
"github.com/arangodb/kube-arangodb/pkg/util"
@ -413,3 +416,13 @@ func (s DeploymentSpec) ResetImmutableFields(target *DeploymentSpec) []string {
}
return resetFields
}
// Checksum return checksum of current ArangoDeployment Spec section
func (s DeploymentSpec) Checksum() (string, error) {
data, err := json.Marshal(s)
if err != nil {
return "", err
}
return fmt.Sprintf("%0x", sha256.Sum256(data)), nil
}

View file

@ -33,6 +33,9 @@ type DeploymentStatus struct {
// Reason contains a human readable reason for reaching the current state (can be empty)
Reason string `json:"reason,omitempty"` // Reason for current state
// AppliedVersion defines checksum of applied spec
AppliedVersion string `json:"appliedVersion"`
// ServiceName holds the name of the Service a client can use (inside the k8s cluster)
// to access ArangoDB.
ServiceName string `json:"serviceName,omitempty"`

View file

@ -25,6 +25,7 @@ package v1
import (
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/dchest/uniuri"
"k8s.io/apimachinery/pkg/api/equality"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@ -66,6 +67,8 @@ const (
ActionTypePVCResize ActionType = "PVCResize"
// ActionTypePVCResized waits for PVC to resize for defined time
ActionTypePVCResized ActionType = "PVCResized"
// UpToDateUpdateResized define up to date annotation in spec
UpToDateUpdate ActionType = "UpToDateUpdate"
)
const (
@ -92,6 +95,8 @@ type Action struct {
Reason string `json:"reason,omitempty"`
// Image used in can of a SetCurrentImage action.
Image string `json:"image,omitempty"`
// Params additional parameters used for action
Params map[string]interface{} `json:"params,omitempty"`
}
// Equal compares two Actions
@ -103,7 +108,30 @@ func (a Action) Equal(other Action) bool {
util.TimeCompareEqual(a.CreationTime, other.CreationTime) &&
util.TimeCompareEqualPointer(a.StartTime, other.StartTime) &&
a.Reason == other.Reason &&
a.Image == other.Image
a.Image == other.Image &&
equality.Semantic.DeepEqual(a.Params, other.Params)
}
// AddParam returns copy of action with set parameter
func (a Action) AddParam(key string, value interface{}) Action {
if a.Params == nil {
a.Params = map[string]interface{}{}
}
a.Params[key] = value
return a
}
// GetParam returns action parameter
func (a Action) GetParam(key string) (interface{}, bool) {
if a.Params == nil {
return nil, false
}
i, ok := a.Params[key]
return i, ok
}
// NewAction instantiates a new Action.

View file

@ -103,6 +103,10 @@ func (d *Deployment) GetStatus() (api.DeploymentStatus, int32) {
d.status.mutex.Lock()
defer d.status.mutex.Unlock()
return d.getStatus()
}
func (d *Deployment) getStatus() (api.DeploymentStatus, int32) {
version := d.status.version
return *d.status.last.DeepCopy(), version
}
@ -115,6 +119,10 @@ func (d *Deployment) UpdateStatus(status api.DeploymentStatus, lastVersion int32
d.status.mutex.Lock()
defer d.status.mutex.Unlock()
return d.updateStatus(status, lastVersion, force...)
}
func (d *Deployment) updateStatus(status api.DeploymentStatus, lastVersion int32, force ...bool) error {
if d.status.version != lastVersion {
// Status is obsolete
d.deps.Log.Error().
@ -483,3 +491,18 @@ func (d *Deployment) GetMetricsExporterImage() string {
func (d *Deployment) GetArangoImage() string {
return d.config.ArangoImage
}
func (d *Deployment) WithStatusUpdate(action func(s *api.DeploymentStatus) bool, force ...bool) error {
d.status.mutex.Lock()
defer d.status.mutex.Unlock()
status, version := d.getStatus()
changed := action(&status)
if !changed {
return nil
}
return d.updateStatus(status, version, force...)
}

View file

@ -26,6 +26,8 @@ import (
"context"
"time"
"github.com/pkg/errors"
"github.com/arangodb/kube-arangodb/pkg/apis/deployment"
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
@ -84,138 +86,11 @@ func (d *Deployment) inspectDeployment(lastInterval util.Interval) util.Interval
return nextInterval
}
// Inspect secret hashes
if err := d.resources.ValidateSecretHashes(); err != nil {
if inspectNextInterval, err := d.inspectDeploymentWithError(ctx, nextInterval); err != nil {
nextInterval = inspectNextInterval
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("Secret hash validation failed", err, d.apiObject))
}
// Check for LicenseKeySecret
if err := d.resources.ValidateLicenseKeySecret(); err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("License Key Secret invalid", err, d.apiObject))
}
// Is the deployment in a good state?
status, _ := d.GetStatus()
if status.Conditions.IsTrue(api.ConditionTypeSecretsChanged) {
log.Debug().Msg("Condition SecretsChanged is true. Revert secrets before we can continue")
return nextInterval
}
// Ensure we have image info
if retrySoon, err := d.ensureImages(d.apiObject); err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("Image detection failed", err, d.apiObject))
} else if retrySoon {
nextInterval = minInspectionInterval
}
// Inspection of generated resources needed
if x, err := d.resources.InspectPods(ctx); err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("Pod inspection failed", err, d.apiObject))
} else {
nextInterval = nextInterval.ReduceTo(x)
}
if x, err := d.resources.InspectPVCs(ctx); err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("PVC inspection failed", err, d.apiObject))
} else {
nextInterval = nextInterval.ReduceTo(x)
}
// Check members for resilience
if err := d.resilience.CheckMemberFailure(); err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("Member failure detection failed", err, d.apiObject))
}
// Immediate actions
if err := d.reconciler.CheckDeployment(); err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("Reconciler immediate actions failed", err, d.apiObject))
}
// Create scale/update plan
if err := d.reconciler.CreatePlan(); err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("Plan creation failed", err, d.apiObject))
}
// Execute current step of scale/update plan
retrySoon, err := d.reconciler.ExecutePlan(ctx)
if err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("Plan execution failed", err, d.apiObject))
}
if retrySoon {
nextInterval = minInspectionInterval
}
// Ensure all resources are created
if err := d.resources.EnsureSecrets(); err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("Secret creation failed", err, d.apiObject))
}
if err := d.resources.EnsureServices(); err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("Service creation failed", err, d.apiObject))
}
if d.haveServiceMonitorCRD {
if err := d.resources.EnsureServiceMonitor(); err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("Service monitor creation failed", err, d.apiObject))
}
}
if err := d.resources.EnsurePVCs(); err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("PVC creation failed", err, d.apiObject))
}
if err := d.resources.EnsurePods(); err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("Pod creation failed", err, d.apiObject))
}
if err := d.resources.EnsurePDBs(); err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("PDB creation failed", err, d.apiObject))
}
if err := d.resources.EnsureAnnotations(); err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("Annotation update failed", err, d.apiObject))
}
// Create access packages
if err := d.createAccessPackages(); err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("AccessPackage creation failed", err, d.apiObject))
}
// Ensure deployment bootstrap
if err := d.EnsureBootstrap(); err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("Bootstrap failed", err, d.apiObject))
}
// Inspect deployment for obsolete members
if err := d.resources.CleanupRemovedMembers(); err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("Removed member cleanup failed", err, d.apiObject))
}
if err := d.backup.CheckRestore(); err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("Restore operation failed", err, d.apiObject))
}
// At the end of the inspect, we cleanup terminated pods.
if x, err := d.resources.CleanupTerminatedPods(); err != nil {
hasError = true
d.CreateEvent(k8sutil.NewErrorEvent("Pod cleanup failed", err, d.apiObject))
} else {
nextInterval = nextInterval.ReduceTo(x)
d.CreateEvent(k8sutil.NewErrorEvent("Reconcilation failed", err, d.apiObject))
}
}
@ -231,6 +106,170 @@ func (d *Deployment) inspectDeployment(lastInterval util.Interval) util.Interval
return nextInterval.ReduceTo(maxInspectionInterval)
}
func (d *Deployment) inspectDeploymentWithError(ctx context.Context, lastInterval util.Interval) (nextInterval util.Interval, inspectError error) {
// Ensure that spec and status checksum are same
spec := d.GetSpec()
status, _ := d.getStatus()
nextInterval = lastInterval
inspectError = nil
checksum, err := spec.Checksum()
if err != nil {
return minInspectionInterval, errors.Wrapf(err, "Calculation of spec failed")
} else {
condition, exists := status.Conditions.Get(api.ConditionTypeUpToDate)
if (checksum != status.AppliedVersion && (!exists || condition.IsTrue())) ||
(checksum == status.AppliedVersion && (!exists || !condition.IsTrue())) {
if err = d.WithStatusUpdate(func(s *api.DeploymentStatus) bool {
if checksum == status.AppliedVersion {
return s.Conditions.Update(api.ConditionTypeUpToDate, true, "Everything is UpToDate", "Spec applied")
}
return s.Conditions.Update(api.ConditionTypeUpToDate, false, "Spec Changed", "Spec Object changed. Waiting until plan will be applied")
}); err != nil {
return minInspectionInterval, errors.Wrapf(err, "Unable to update UpToDate condition")
}
return minInspectionInterval, nil // Retry ASAP
}
}
// Inspect secret hashes
if err := d.resources.ValidateSecretHashes(); err != nil {
return minInspectionInterval, errors.Wrapf(err, "Secret hash validation failed")
}
// Check for LicenseKeySecret
if err := d.resources.ValidateLicenseKeySecret(); err != nil {
return minInspectionInterval, errors.Wrapf(err, "License Key Secret invalid")
}
// Is the deployment in a good state?
if status.Conditions.IsTrue(api.ConditionTypeSecretsChanged) {
return minInspectionInterval, errors.Errorf("Secrets changed")
}
// Ensure we have image info
if retrySoon, err := d.ensureImages(d.apiObject); err != nil {
return minInspectionInterval, errors.Wrapf(err, "Image detection failed")
} else if retrySoon {
return minInspectionInterval, nil
}
// Inspection of generated resources needed
if x, err := d.resources.InspectPods(ctx); err != nil {
return minInspectionInterval, errors.Wrapf(err, "Pod inspection failed")
} else {
nextInterval = nextInterval.ReduceTo(x)
}
if x, err := d.resources.InspectPVCs(ctx); err != nil {
return minInspectionInterval, errors.Wrapf(err, "PVC inspection failed")
} else {
nextInterval = nextInterval.ReduceTo(x)
}
// Check members for resilience
if err := d.resilience.CheckMemberFailure(); err != nil {
return minInspectionInterval, errors.Wrapf(err, "Member failure detection failed")
}
// Immediate actions
if err := d.reconciler.CheckDeployment(); err != nil {
return minInspectionInterval, errors.Wrapf(err, "Reconciler immediate actions failed")
}
if interval, err := d.ensureResources(nextInterval); err != nil {
return minInspectionInterval, errors.Wrapf(err, "Reconciler resource recreation failed")
} else {
nextInterval = interval
}
// Create scale/update plan
if err := d.reconciler.CreatePlan(); err != nil {
return minInspectionInterval, errors.Wrapf(err, "Plan creation failed")
}
// Execute current step of scale/update plan
retrySoon, err := d.reconciler.ExecutePlan(ctx)
if err != nil {
return minInspectionInterval, errors.Wrapf(err, "Plan execution failed")
}
if retrySoon {
nextInterval = minInspectionInterval
} else {
// Do not retry - so plan is empty
if status.AppliedVersion != checksum {
if err := d.WithStatusUpdate(func(s *api.DeploymentStatus) bool {
s.AppliedVersion = checksum
return true
}); err != nil {
return minInspectionInterval, errors.Wrapf(err, "Unable to update UpToDate condition")
}
return minInspectionInterval, nil
}
}
// Create access packages
if err := d.createAccessPackages(); err != nil {
return minInspectionInterval, errors.Wrapf(err, "AccessPackage creation failed")
}
// Ensure deployment bootstrap
if err := d.EnsureBootstrap(); err != nil {
return minInspectionInterval, errors.Wrapf(err, "Bootstrap failed")
}
// Inspect deployment for obsolete members
if err := d.resources.CleanupRemovedMembers(); err != nil {
return minInspectionInterval, errors.Wrapf(err, "Removed member cleanup failed")
}
if err := d.backup.CheckRestore(); err != nil {
return minInspectionInterval, errors.Wrapf(err, "Restore operation failed")
}
// At the end of the inspect, we cleanup terminated pods.
if x, err := d.resources.CleanupTerminatedPods(); err != nil {
return minInspectionInterval, errors.Wrapf(err, "Pod cleanup failed")
} else {
nextInterval = nextInterval.ReduceTo(x)
}
return
}
func (d *Deployment) ensureResources(lastInterval util.Interval) (util.Interval, error) {
// Ensure all resources are created
if err := d.resources.EnsureSecrets(); err != nil {
return minInspectionInterval, errors.Wrapf(err, "Secret creation failed")
}
if err := d.resources.EnsureServices(); err != nil {
return minInspectionInterval, errors.Wrapf(err, "Service creation failed")
}
if d.haveServiceMonitorCRD {
if err := d.resources.EnsureServiceMonitor(); err != nil {
return minInspectionInterval, errors.Wrapf(err, "Service monitor creation failed")
}
}
if err := d.resources.EnsurePVCs(); err != nil {
return minInspectionInterval, errors.Wrapf(err, "PVC creation failed")
}
if err := d.resources.EnsurePods(); err != nil {
return minInspectionInterval, errors.Wrapf(err, "Pod creation failed")
}
if err := d.resources.EnsurePDBs(); err != nil {
return minInspectionInterval, errors.Wrapf(err, "PDB creation failed")
}
if err := d.resources.EnsureAnnotations(); err != nil {
return minInspectionInterval, errors.Wrapf(err, "Annotation update failed")
}
return lastInterval, nil
}
// triggerInspection ensures that an inspection is run soon.
func (d *Deployment) triggerInspection() {
d.inspectTrigger.Trigger()

View file

@ -24,7 +24,12 @@ package reconcile
import (
"context"
"fmt"
"sync"
"time"
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
"github.com/rs/zerolog"
)
// Action executes a single Plan item.
@ -41,3 +46,30 @@ type Action interface {
// Return the MemberID used / created in this action
MemberID() string
}
type actionFactory func(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action
var (
actions = map[api.ActionType]actionFactory{}
actionsLock sync.Mutex
)
func registerAction(t api.ActionType, f actionFactory) {
actionsLock.Lock()
defer actionsLock.Unlock()
_, ok := actions[t]
if ok {
panic(fmt.Sprintf("Action already defined %s", t))
}
actions[t] = f
}
func getActionFactory(t api.ActionType) (actionFactory, bool) {
actionsLock.Lock()
defer actionsLock.Unlock()
f, ok := actions[t]
return f, ok
}

View file

@ -24,28 +24,34 @@ package reconcile
import (
"context"
"time"
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
// NewAddMemberAction creates a new Action that implements the given
func init() {
registerAction(api.ActionTypeAddMember, newAddMemberAction)
}
// newAddMemberAction creates a new Action that implements the given
// planned AddMember action.
func NewAddMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
return &actionAddMember{
log: log,
action: action,
actionCtx: actionCtx,
}
func newAddMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
a := &actionAddMember{}
a.actionImpl = newActionImpl(log, action, actionCtx, addMemberTimeout, &a.newMemberID)
return a
}
// actionAddMember implements an AddMemberAction.
type actionAddMember struct {
log zerolog.Logger
action api.Action
actionCtx ActionContext
// actionImpl implement timeout and member id functions
actionImpl
// actionEmptyCheckProgress implement check progress with empty implementation
actionEmptyCheckProgress
newMemberID string
}
@ -61,20 +67,3 @@ func (a *actionAddMember) Start(ctx context.Context) (bool, error) {
a.newMemberID = newID
return true, nil
}
// CheckProgress checks the progress of the action.
// Returns true if the action is completely finished, false otherwise.
func (a *actionAddMember) CheckProgress(ctx context.Context) (bool, bool, error) {
// Nothing todo
return true, false, nil
}
// Timeout returns the amount of time after which this action will timeout.
func (a *actionAddMember) Timeout() time.Duration {
return addMemberTimeout
}
// Return the MemberID used / created in this action
func (a *actionAddMember) MemberID() string {
return a.newMemberID
}

View file

@ -24,7 +24,6 @@ package reconcile
import (
"context"
"time"
driver "github.com/arangodb/go-driver"
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
@ -33,21 +32,24 @@ import (
"github.com/arangodb/kube-arangodb/pkg/util/arangod"
)
// NewCleanOutMemberAction creates a new Action that implements the given
func init() {
registerAction(api.ActionTypeCleanOutMember, newCleanOutMemberAction)
}
// newCleanOutMemberAction creates a new Action that implements the given
// planned CleanOutMember action.
func NewCleanOutMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
return &actionCleanoutMember{
log: log,
action: action,
actionCtx: actionCtx,
}
func newCleanOutMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
a := &actionCleanoutMember{}
a.actionImpl = newActionImplDefRef(log, action, actionCtx, cleanoutMemberTimeout)
return a
}
// actionCleanoutMember implements an CleanOutMemberAction.
type actionCleanoutMember struct {
log zerolog.Logger
action api.Action
actionCtx ActionContext
// actionImpl implement timeout and member id functions
actionImpl
}
// Start performs the start of the action.
@ -154,13 +156,3 @@ func (a *actionCleanoutMember) CheckProgress(ctx context.Context) (bool, bool, e
// Cleanout completed
return true, false, nil
}
// Timeout returns the amount of time after which this action will timeout.
func (a *actionCleanoutMember) Timeout() time.Duration {
return cleanoutMemberTimeout
}
// Return the MemberID used / created in this action
func (a *actionCleanoutMember) MemberID() string {
return a.action.MemberID
}

View file

@ -109,6 +109,8 @@ type ActionContext interface {
DisableScalingCluster() error
// EnableScalingCluster enables scaling DBservers and coordinators
EnableScalingCluster() error
// WithStatusUpdate update status of ArangoDeployment with defined modifier. If action returns True action is taken
UpdateClusterCondition(conditionType api.ConditionType, status bool, reason, message string) error
}
// newActionContext creates a new ActionContext implementation.
@ -125,6 +127,12 @@ type actionContext struct {
context Context
}
func (ac *actionContext) UpdateClusterCondition(conditionType api.ConditionType, status bool, reason, message string) error {
return ac.context.WithStatusUpdate(func(s *api.DeploymentStatus) bool {
return s.Conditions.Update(conditionType, status, reason, message)
})
}
func (ac *actionContext) GetPv(pvName string) (*v1.PersistentVolume, error) {
return ac.context.GetPv(pvName)
}

View file

@ -22,27 +22,32 @@ package reconcile
import (
"context"
"time"
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/rs/zerolog"
)
// actionDisableScalingCluster implements disabling scaling DBservers and coordinators.
type actionDisableScalingCluster struct {
log zerolog.Logger
action api.Action
actionCtx ActionContext
newMemberID string
func init() {
registerAction(api.ActionTypeDisableClusterScaling, newDisableScalingCluster)
}
// NewDisableScalingCluster creates the new action with disabling scaling DBservers and coordinators.
func NewDisableScalingCluster(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
return &actionDisableScalingCluster{
log: log,
action: action,
actionCtx: actionCtx,
}
// newDisableScalingCluster creates the new action with disabling scaling DBservers and coordinators.
func newDisableScalingCluster(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
a := &actionDisableScalingCluster{}
a.actionImpl = newActionImpl(log, action, actionCtx, 0, util.NewString(""))
return a
}
// actionDisableScalingCluster implements disabling scaling DBservers and coordinators.
type actionDisableScalingCluster struct {
// actionImpl implement timeout and member id functions
actionImpl
// actionEmptyCheckProgress implement check progress with empty implementation
actionEmptyCheckProgress
}
// Start disables scaling DBservers and coordinators
@ -53,18 +58,3 @@ func (a *actionDisableScalingCluster) Start(ctx context.Context) (bool, error) {
}
return true, nil
}
// CheckProgress does not matter. Everything is done in 'Start' function
func (a *actionDisableScalingCluster) CheckProgress(ctx context.Context) (bool, bool, error) {
return true, false, nil
}
// Timeout does not matter. Everything is done in 'Start' function
func (a *actionDisableScalingCluster) Timeout() time.Duration {
return 0
}
// MemberID is not used
func (a *actionDisableScalingCluster) MemberID() string {
return ""
}

View file

@ -22,27 +22,32 @@ package reconcile
import (
"context"
"time"
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
"github.com/arangodb/kube-arangodb/pkg/util"
"github.com/rs/zerolog"
)
// actionEnableScalingCluster implements enabling scaling DBservers and coordinators.
type actionEnableScalingCluster struct {
log zerolog.Logger
action api.Action
actionCtx ActionContext
newMemberID string
func init() {
registerAction(api.ActionTypeEnableClusterScaling, newEnableScalingCluster)
}
// NewEnableScalingCluster creates the new action with enabling scaling DBservers and coordinators.
func NewEnableScalingCluster(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
return &actionEnableScalingCluster{
log: log,
action: action,
actionCtx: actionCtx,
}
// newEnableScalingCluster creates the new action with enabling scaling DBservers and coordinators.
func newEnableScalingCluster(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
a := &actionEnableScalingCluster{}
a.actionImpl = newActionImpl(log, action, actionCtx, 0, util.NewString(""))
return a
}
// actionEnableScalingCluster implements enabling scaling DBservers and coordinators.
type actionEnableScalingCluster struct {
// actionImpl implement timeout and member id functions
actionImpl
// actionEmptyCheckProgress implement check progress with empty implementation
actionEmptyCheckProgress
}
// Start enables scaling DBservers and coordinators
@ -53,18 +58,3 @@ func (a *actionEnableScalingCluster) Start(ctx context.Context) (bool, error) {
}
return true, nil
}
// CheckProgress does not matter. Everything is done in 'Start' function
func (a *actionEnableScalingCluster) CheckProgress(ctx context.Context) (bool, bool, error) {
return true, false, nil
}
// Timeout does not matter. Everything is done in 'Start' function
func (a *actionEnableScalingCluster) Timeout() time.Duration {
return 0
}
// MemberID is not used
func (a *actionEnableScalingCluster) MemberID() string {
return ""
}

View file

@ -0,0 +1,84 @@
//
// DISCLAIMER
//
// Copyright 2020 ArangoDB GmbH, Cologne, Germany
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// Copyright holder is ArangoDB GmbH, Cologne, Germany
//
// Author Adam Janikowski
//
package reconcile
import (
"context"
"time"
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
"github.com/rs/zerolog"
)
type actionEmptyCheckProgress struct {
}
// CheckProgress define optional check progress for action
// Returns: ready, abort, error.
func (e actionEmptyCheckProgress) CheckProgress(ctx context.Context) (bool, bool, error) {
return true, false, nil
}
type actionEmptyStart struct {
}
func (e actionEmptyStart) Start(ctx context.Context) (bool, error) {
return false, nil
}
func newActionImplDefRef(log zerolog.Logger, action api.Action, actionCtx ActionContext, timeout time.Duration) actionImpl {
return newActionImpl(log, action, actionCtx, timeout, &action.MemberID)
}
func newActionImpl(log zerolog.Logger, action api.Action, actionCtx ActionContext, timeout time.Duration, memberIDRef *string) actionImpl {
if memberIDRef == nil {
panic("Action cannot have nil reference to member!")
}
return actionImpl{
log: log,
action: action,
actionCtx: actionCtx,
timeout: timeout,
memberIDRef: memberIDRef,
}
}
type actionImpl struct {
log zerolog.Logger
action api.Action
actionCtx ActionContext
timeout time.Duration
memberIDRef *string
}
// Timeout returns the amount of time after which this action will timeout.
func (a actionImpl) Timeout() time.Duration {
return a.timeout
}
// Return the MemberID used / created in this action
func (a actionImpl) MemberID() string {
return *a.memberIDRef
}

View file

@ -24,7 +24,6 @@ package reconcile
import (
"context"
"time"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
core "k8s.io/api/core/v1"
@ -34,21 +33,24 @@ import (
"github.com/rs/zerolog"
)
// NewRotateMemberAction creates a new Action that implements the given
func init() {
registerAction(api.ActionTypePVCResize, newPVCResizeAction)
}
// newRotateMemberAction creates a new Action that implements the given
// planned RotateMember action.
func NewPVCResizeAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
return &actionPVCResize{
log: log,
action: action,
actionCtx: actionCtx,
}
func newPVCResizeAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
a := &actionPVCResize{}
a.actionImpl = newActionImplDefRef(log, action, actionCtx, pvcResizeTimeout)
return a
}
// actionRotateMember implements an RotateMember.
type actionPVCResize struct {
log zerolog.Logger
action api.Action
actionCtx ActionContext
// actionImpl implement timeout and member id functions
actionImpl
}
// Start performs the start of the action.
@ -147,13 +149,3 @@ func (a *actionPVCResize) CheckProgress(ctx context.Context) (bool, bool, error)
return false, false, nil
}
// Timeout returns the amount of time after which this action will timeout.
func (a *actionPVCResize) Timeout() time.Duration {
return pvcResizeTimeout
}
// Return the MemberID used / created in this action
func (a *actionPVCResize) MemberID() string {
return a.action.MemberID
}

View file

@ -24,7 +24,6 @@ package reconcile
import (
"context"
"time"
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
core "k8s.io/api/core/v1"
@ -34,28 +33,27 @@ import (
"github.com/rs/zerolog"
)
// NewRotateMemberAction creates a new Action that implements the given
func init() {
registerAction(api.ActionTypePVCResized, newPVCResizedAction)
}
// newRotateMemberAction creates a new Action that implements the given
// planned RotateMember action.
func NewPVCResizedAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
return &actionPVCResized{
log: log,
action: action,
actionCtx: actionCtx,
}
func newPVCResizedAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
a := &actionPVCResized{}
a.actionImpl = newActionImplDefRef(log, action, actionCtx, pvcResizedTimeout)
return a
}
// actionRotateMember implements an RotateMember.
type actionPVCResized struct {
log zerolog.Logger
action api.Action
actionCtx ActionContext
}
// actionImpl implement timeout and member id functions
actionImpl
// Start performs the start of the action.
// Returns true if the action is completely finished, false in case
// the start time needs to be recorded and a ready condition needs to be checked.
func (a *actionPVCResized) Start(ctx context.Context) (bool, error) {
return false, nil
// actionEmptyStart empty start function
actionEmptyStart
}
// CheckProgress checks the progress of the action.
@ -94,13 +92,3 @@ func (a *actionPVCResized) CheckProgress(ctx context.Context) (bool, bool, error
return false, false, nil
}
// Timeout returns the amount of time after which this action will timeout.
func (a *actionPVCResized) Timeout() time.Duration {
return pvcResizedTimeout
}
// Return the MemberID used / created in this action
func (a *actionPVCResized) MemberID() string {
return a.action.MemberID
}

View file

@ -25,7 +25,6 @@ package reconcile
import (
"context"
"fmt"
"time"
kubeErrors "k8s.io/apimachinery/pkg/api/errors"
@ -34,21 +33,27 @@ import (
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
)
// NewRecreateMemberAction creates a new Action that implements the given
func init() {
registerAction(api.ActionTypeRecreateMember, newRecreateMemberAction)
}
// newRecreateMemberAction creates a new Action that implements the given
// planned RecreateMember action.
func NewRecreateMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
return &actionRecreateMember{
log: log,
action: action,
actionCtx: actionCtx,
}
func newRecreateMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
a := &actionRecreateMember{}
a.actionImpl = newActionImplDefRef(log, action, actionCtx, recreateMemberTimeout)
return a
}
// actionRecreateMember implements an RecreateMemberAction.
type actionRecreateMember struct {
log zerolog.Logger
action api.Action
actionCtx ActionContext
// actionImpl implement timeout and member id functions
actionImpl
// actionEmptyCheckProgress implement check progress with empty implementation
actionEmptyCheckProgress
}
// Start performs the start of the action.
@ -80,20 +85,3 @@ func (a *actionRecreateMember) Start(ctx context.Context) (bool, error) {
return true, nil
}
// CheckProgress checks the progress of the action.
// Returns true if the action is completely finished, false otherwise.
func (a *actionRecreateMember) CheckProgress(ctx context.Context) (bool, bool, error) {
// Nothing todo
return true, false, nil
}
// Timeout returns the amount of time after which this action will timeout.
func (a *actionRecreateMember) Timeout() time.Duration {
return recreateMemberTimeout
}
// Return the MemberID used / created in this action
func (a *actionRecreateMember) MemberID() string {
return a.action.MemberID
}

View file

@ -25,7 +25,6 @@ package reconcile
import (
"context"
"fmt"
"time"
"github.com/pkg/errors"
"github.com/rs/zerolog"
@ -35,21 +34,27 @@ import (
"github.com/arangodb/kube-arangodb/pkg/util/arangod"
)
// NewRemoveMemberAction creates a new Action that implements the given
func init() {
registerAction(api.ActionTypeRemoveMember, newRemoveMemberAction)
}
// newRemoveMemberAction creates a new Action that implements the given
// planned RemoveMember action.
func NewRemoveMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
return &actionRemoveMember{
log: log,
action: action,
actionCtx: actionCtx,
}
func newRemoveMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
a := &actionRemoveMember{}
a.actionImpl = newActionImplDefRef(log, action, actionCtx, removeMemberTimeout)
return a
}
// actionRemoveMember implements an RemoveMemberAction.
type actionRemoveMember struct {
log zerolog.Logger
action api.Action
actionCtx ActionContext
// actionImpl implement timeout and member id functions
actionImpl
// actionEmptyCheckProgress implement check progress with empty implementation
actionEmptyCheckProgress
}
// Start performs the start of the action.
@ -114,20 +119,3 @@ func (a *actionRemoveMember) Start(ctx context.Context) (bool, error) {
}
return true, nil
}
// CheckProgress checks the progress of the action.
// Returns true if the action is completely finished, false otherwise.
func (a *actionRemoveMember) CheckProgress(ctx context.Context) (bool, bool, error) {
// Nothing todo
return true, false, nil
}
// Timeout returns the amount of time after which this action will timeout.
func (a *actionRemoveMember) Timeout() time.Duration {
return removeMemberTimeout
}
// Return the MemberID used / created in this action
func (a *actionRemoveMember) MemberID() string {
return a.action.MemberID
}

View file

@ -30,21 +30,27 @@ import (
"github.com/rs/zerolog"
)
// NewRenewTLSCACertificateAction creates a new Action that implements the given
func init() {
registerAction(api.ActionTypeRenewTLSCACertificate, newRenewTLSCACertificateAction)
}
// newRenewTLSCACertificateAction creates a new Action that implements the given
// planned RenewTLSCACertificate action.
func NewRenewTLSCACertificateAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
return &renewTLSCACertificateAction{
log: log,
action: action,
actionCtx: actionCtx,
}
func newRenewTLSCACertificateAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
a := &renewTLSCACertificateAction{}
a.actionImpl = newActionImplDefRef(log, action, actionCtx, renewTLSCACertificateTimeout)
return a
}
// renewTLSCACertificateAction implements a RenewTLSCACertificate action.
type renewTLSCACertificateAction struct {
log zerolog.Logger
action api.Action
actionCtx ActionContext
// actionImpl implement timeout and member id functions
actionImpl
// actionEmptyCheckProgress implement check progress with empty implementation
actionEmptyCheckProgress
}
// Start performs the start of the action.

View file

@ -24,27 +24,32 @@ package reconcile
import (
"context"
"time"
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
"github.com/rs/zerolog"
)
// NewRenewTLSCertificateAction creates a new Action that implements the given
func init() {
registerAction(api.ActionTypeRenewTLSCertificate, newRenewTLSCertificateAction)
}
// newRenewTLSCertificateAction creates a new Action that implements the given
// planned RenewTLSCertificate action.
func NewRenewTLSCertificateAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
return &renewTLSCertificateAction{
log: log,
action: action,
actionCtx: actionCtx,
}
func newRenewTLSCertificateAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
a := &renewTLSCertificateAction{}
a.actionImpl = newActionImplDefRef(log, action, actionCtx, renewTLSCertificateTimeout)
return a
}
// renewTLSCertificateAction implements a RenewTLSCertificate action.
type renewTLSCertificateAction struct {
log zerolog.Logger
action api.Action
actionCtx ActionContext
// actionImpl implement timeout and member id functions
actionImpl
// actionEmptyCheckProgress implement check progress with empty implementation
actionEmptyCheckProgress
}
// Start performs the start of the action.
@ -64,19 +69,3 @@ func (a *renewTLSCertificateAction) Start(ctx context.Context) (bool, error) {
}
return false, nil
}
// CheckProgress checks the progress of the action.
// Returns true if the action is completely finished, false otherwise.
func (a *renewTLSCertificateAction) CheckProgress(ctx context.Context) (bool, bool, error) {
return true, false, nil
}
// Timeout returns the amount of time after which this action will timeout.
func (a *renewTLSCertificateAction) Timeout() time.Duration {
return renewTLSCertificateTimeout
}
// Return the MemberID used / created in this action
func (a *renewTLSCertificateAction) MemberID() string {
return a.action.MemberID
}

View file

@ -24,27 +24,29 @@ package reconcile
import (
"context"
"time"
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
"github.com/rs/zerolog"
)
// NewRotateMemberAction creates a new Action that implements the given
func init() {
registerAction(api.ActionTypeRotateMember, newRotateMemberAction)
}
// newRotateMemberAction creates a new Action that implements the given
// planned RotateMember action.
func NewRotateMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
return &actionRotateMember{
log: log,
action: action,
actionCtx: actionCtx,
}
func newRotateMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
a := &actionRotateMember{}
a.actionImpl = newActionImplDefRef(log, action, actionCtx, rotateMemberTimeout)
return a
}
// actionRotateMember implements an RotateMember.
type actionRotateMember struct {
log zerolog.Logger
action api.Action
actionCtx ActionContext
// actionImpl implement timeout and member id functions
actionImpl
}
// Start performs the start of the action.
@ -123,13 +125,3 @@ func (a *actionRotateMember) CheckProgress(ctx context.Context) (bool, bool, err
}
return true, false, nil
}
// Timeout returns the amount of time after which this action will timeout.
func (a *actionRotateMember) Timeout() time.Duration {
return rotateMemberTimeout
}
// Return the MemberID used / created in this action
func (a *actionRotateMember) MemberID() string {
return a.action.MemberID
}

View file

@ -24,27 +24,29 @@ package reconcile
import (
"context"
"time"
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
"github.com/rs/zerolog"
)
// NewRotateStartMemberAction creates a new Action that implements the given
func init() {
registerAction(api.ActionTypeRotateStartMember, newRotateStartMemberAction)
}
// newRotateStartMemberAction creates a new Action that implements the given
// planned RotateStartMember action.
func NewRotateStartMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
return &actionRotateStartMember{
log: log,
action: action,
actionCtx: actionCtx,
}
func newRotateStartMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
a := &actionRotateStartMember{}
a.actionImpl = newActionImplDefRef(log, action, actionCtx, rotateMemberTimeout)
return a
}
// actionRotateStartMember implements an RotateStartMember.
type actionRotateStartMember struct {
log zerolog.Logger
action api.Action
actionCtx ActionContext
// actionImpl implement timeout and member id functions
actionImpl
}
// Start performs the start of the action.
@ -116,13 +118,3 @@ func (a *actionRotateStartMember) CheckProgress(ctx context.Context) (bool, bool
}
return true, false, nil
}
// Timeout returns the amount of time after which this action will timeout.
func (a *actionRotateStartMember) Timeout() time.Duration {
return rotateMemberTimeout
}
// Return the MemberID used / created in this action
func (a *actionRotateStartMember) MemberID() string {
return a.action.MemberID
}

View file

@ -24,27 +24,32 @@ package reconcile
import (
"context"
"time"
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
"github.com/rs/zerolog"
)
// NewRotateStopMemberAction creates a new Action that implements the given
func init() {
registerAction(api.ActionTypeRotateStopMember, newRotateStopMemberAction)
}
// newRotateStopMemberAction creates a new Action that implements the given
// planned RotateStopMember action.
func NewRotateStopMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
return &actionRotateStopMember{
log: log,
action: action,
actionCtx: actionCtx,
}
func newRotateStopMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
a := &actionRotateStopMember{}
a.actionImpl = newActionImplDefRef(log, action, actionCtx, rotateMemberTimeout)
return a
}
// actionRotateStopMember implements an RotateStopMember.
type actionRotateStopMember struct {
log zerolog.Logger
action api.Action
actionCtx ActionContext
// actionImpl implement timeout and member id functions
actionImpl
// actionEmptyCheckProgress implement check progress with empty implementation
actionEmptyCheckProgress
}
// Start performs the start of the action.
@ -65,19 +70,3 @@ func (a *actionRotateStopMember) Start(ctx context.Context) (bool, error) {
}
return false, nil
}
// CheckProgress checks the progress of the action.
// Returns: ready, abort, error.
func (a *actionRotateStopMember) CheckProgress(ctx context.Context) (bool, bool, error) {
return true, false, nil
}
// Timeout returns the amount of time after which this action will timeout.
func (a *actionRotateStopMember) Timeout() time.Duration {
return rotateMemberTimeout
}
// Return the MemberID used / created in this action
func (a *actionRotateStopMember) MemberID() string {
return a.action.MemberID
}

View file

@ -24,31 +24,29 @@ package reconcile
import (
"context"
"time"
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
"github.com/rs/zerolog"
)
const (
shutdownTimeout = time.Second * 15
)
func init() {
registerAction(api.ActionTypeShutdownMember, newShutdownMemberAction)
}
// NewShutdownMemberAction creates a new Action that implements the given
// newShutdownMemberAction creates a new Action that implements the given
// planned ShutdownMember action.
func NewShutdownMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
return &actionShutdownMember{
log: log,
action: action,
actionCtx: actionCtx,
}
func newShutdownMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
a := &actionShutdownMember{}
a.actionImpl = newActionImplDefRef(log, action, actionCtx, shutdownMemberTimeout)
return a
}
// actionShutdownMember implements an ShutdownMemberAction.
type actionShutdownMember struct {
log zerolog.Logger
action api.Action
actionCtx ActionContext
// actionImpl implement timeout and member id functions
actionImpl
}
// Start performs the start of the action.
@ -115,13 +113,3 @@ func (a *actionShutdownMember) CheckProgress(ctx context.Context) (bool, bool, e
// Member still not shutdown, retry soon
return false, false, nil
}
// Timeout returns the amount of time after which this action will timeout.
func (a *actionShutdownMember) Timeout() time.Duration {
return shutdownMemberTimeout
}
// Return the MemberID used / created in this action
func (a *actionShutdownMember) MemberID() string {
return a.action.MemberID
}

View file

@ -24,27 +24,29 @@ package reconcile
import (
"context"
"time"
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
"github.com/rs/zerolog"
)
// NewSetCurrentImageAction creates a new Action that implements the given
func init() {
registerAction(api.ActionTypeSetCurrentImage, newSetCurrentImageAction)
}
// newSetCurrentImageAction creates a new Action that implements the given
// planned SetCurrentImage action.
func NewSetCurrentImageAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
return &setCurrentImageAction{
log: log,
action: action,
actionCtx: actionCtx,
}
func newSetCurrentImageAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
a := &setCurrentImageAction{}
a.actionImpl = newActionImplDefRef(log, action, actionCtx, upgradeMemberTimeout)
return a
}
// setCurrentImageAction implements an SetCurrentImage.
type setCurrentImageAction struct {
log zerolog.Logger
action api.Action
actionCtx ActionContext
// actionImpl implement timeout and member id functions
actionImpl
}
// Start performs the start of the action.
@ -73,13 +75,3 @@ func (a *setCurrentImageAction) CheckProgress(ctx context.Context) (bool, bool,
log.Info().Str("image", a.action.Image).Msg("Changed current image")
return true, false, nil
}
// Timeout returns the amount of time after which this action will timeout.
func (a *setCurrentImageAction) Timeout() time.Duration {
return upgradeMemberTimeout
}
// Return the MemberID used / created in this action
func (a *setCurrentImageAction) MemberID() string {
return ""
}

View file

@ -24,27 +24,29 @@ package reconcile
import (
"context"
"time"
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
"github.com/rs/zerolog"
)
// NewUpgradeMemberAction creates a new Action that implements the given
func init() {
registerAction(api.ActionTypeUpgradeMember, newUpgradeMemberAction)
}
// newUpgradeMemberAction creates a new Action that implements the given
// planned UpgradeMember action.
func NewUpgradeMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
return &actionUpgradeMember{
log: log,
action: action,
actionCtx: actionCtx,
}
func newUpgradeMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
a := &actionUpgradeMember{}
a.actionImpl = newActionImplDefRef(log, action, actionCtx, upgradeMemberTimeout)
return a
}
// actionUpgradeMember implements an UpgradeMember.
type actionUpgradeMember struct {
log zerolog.Logger
action api.Action
actionCtx ActionContext
// actionImpl implement timeout and member id functions
actionImpl
}
// Start performs the start of the action.
@ -128,13 +130,3 @@ func (a *actionUpgradeMember) CheckProgress(ctx context.Context) (bool, bool, er
}
return isUpgrading, false, nil
}
// Timeout returns the amount of time after which this action will timeout.
func (a *actionUpgradeMember) Timeout() time.Duration {
return upgradeMemberTimeout
}
// Return the MemberID used / created in this action
func (a *actionUpgradeMember) MemberID() string {
return a.action.MemberID
}

View file

@ -24,7 +24,6 @@ package reconcile
import (
"context"
"time"
driver "github.com/arangodb/go-driver"
"github.com/arangodb/go-driver/agency"
@ -34,21 +33,24 @@ import (
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
)
// NewWaitForMemberUpAction creates a new Action that implements the given
func init() {
registerAction(api.ActionTypeWaitForMemberUp, newWaitForMemberUpAction)
}
// newWaitForMemberUpAction creates a new Action that implements the given
// planned WaitForMemberUp action.
func NewWaitForMemberUpAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
return &actionWaitForMemberUp{
log: log,
action: action,
actionCtx: actionCtx,
}
func newWaitForMemberUpAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
a := &actionWaitForMemberUp{}
a.actionImpl = newActionImplDefRef(log, action, actionCtx, waitForMemberUpTimeout)
return a
}
// actionWaitForMemberUp implements an WaitForMemberUp.
type actionWaitForMemberUp struct {
log zerolog.Logger
action api.Action
actionCtx ActionContext
// actionImpl implement timeout and member id functions
actionImpl
}
// Start performs the start of the action.
@ -189,13 +191,3 @@ func (a *actionWaitForMemberUp) checkProgressArangoSync(ctx context.Context) (bo
}
return true, false, nil
}
// Timeout returns the amount of time after which this action will timeout.
func (a *actionWaitForMemberUp) Timeout() time.Duration {
return waitForMemberUpTimeout
}
// Return the MemberID used / created in this action
func (a *actionWaitForMemberUp) MemberID() string {
return a.action.MemberID
}

View file

@ -116,4 +116,6 @@ type Context interface {
RenderPodForMember(spec api.DeploymentSpec, status api.DeploymentStatus, memberID string, imageInfo api.ImageInfo) (*v1.Pod, error)
// SelectImage select currently used image by pod
SelectImage(spec api.DeploymentSpec, status api.DeploymentStatus) (api.ImageInfo, bool)
// WithStatusUpdate update status of ArangoDeployment with defined modifier. If action returns True action is taken
WithStatusUpdate(action func(s *api.DeploymentStatus) bool, force ...bool) error
}

View file

@ -44,6 +44,7 @@ import (
)
var _ PlanBuilderContext = &testContext{}
var _ Context = &testContext{}
type testContext struct {
Pods []core.Pod
@ -54,6 +55,10 @@ type testContext struct {
RecordedEvent *k8sutil.Event
}
func (c *testContext) WithStatusUpdate(action func(s *api.DeploymentStatus) bool, force ...bool) error {
panic("implement me")
}
func (c *testContext) RenderPodForMember(spec api.DeploymentSpec, status api.DeploymentStatus, memberID string, imageInfo api.ImageInfo) (*core.Pod, error) {
panic("implement me")
}

View file

@ -157,47 +157,14 @@ func (d *Reconciler) ExecutePlan(ctx context.Context) (bool, error) {
}
}
// startAction performs the start of the given action
// Returns true if the action is completely finished, false in case
// the start time needs to be recorded and a ready condition needs to be checked.
// createAction create action object based on action type
func (d *Reconciler) createAction(ctx context.Context, log zerolog.Logger, action api.Action) Action {
actionCtx := newActionContext(log, d.context)
switch action.Type {
case api.ActionTypeAddMember:
return NewAddMemberAction(log, action, actionCtx)
case api.ActionTypeRemoveMember:
return NewRemoveMemberAction(log, action, actionCtx)
case api.ActionTypeRecreateMember:
return NewRecreateMemberAction(log, action, actionCtx)
case api.ActionTypeCleanOutMember:
return NewCleanOutMemberAction(log, action, actionCtx)
case api.ActionTypeShutdownMember:
return NewShutdownMemberAction(log, action, actionCtx)
case api.ActionTypeRotateMember:
return NewRotateMemberAction(log, action, actionCtx)
case api.ActionTypeRotateStartMember:
return NewRotateStartMemberAction(log, action, actionCtx)
case api.ActionTypeRotateStopMember:
return NewRotateStopMemberAction(log, action, actionCtx)
case api.ActionTypeUpgradeMember:
return NewUpgradeMemberAction(log, action, actionCtx)
case api.ActionTypeWaitForMemberUp:
return NewWaitForMemberUpAction(log, action, actionCtx)
case api.ActionTypeRenewTLSCertificate:
return NewRenewTLSCertificateAction(log, action, actionCtx)
case api.ActionTypeRenewTLSCACertificate:
return NewRenewTLSCACertificateAction(log, action, actionCtx)
case api.ActionTypeSetCurrentImage:
return NewSetCurrentImageAction(log, action, actionCtx)
case api.ActionTypeDisableClusterScaling:
return NewDisableScalingCluster(log, action, actionCtx)
case api.ActionTypeEnableClusterScaling:
return NewEnableScalingCluster(log, action, actionCtx)
case api.ActionTypePVCResize:
return NewPVCResizeAction(log, action, actionCtx)
case api.ActionTypePVCResized:
return NewPVCResizedAction(log, action, actionCtx)
default:
f, ok := getActionFactory(action.Type)
if !ok {
panic(fmt.Sprintf("Unknown action type '%s'", action.Type))
}
return f(log, action, actionCtx)
}

View file

@ -37,4 +37,7 @@ const (
shutdownMemberTimeout = time.Minute * 30
upgradeMemberTimeout = time.Hour * 6
waitForMemberUpTimeout = time.Minute * 15
upToDateUpdateTimeout = time.Minute
shutdownTimeout = time.Second * 15
)

View file

@ -92,4 +92,6 @@ type Context interface {
GetDatabaseClient(ctx context.Context) (driver.Client, error)
// GetAgency returns a connection to the entire agency.
GetAgency(ctx context.Context) (agency.Agency, error)
// WithStatusUpdate update status of ArangoDeployment with defined modifier. If action returns True action is taken
WithStatusUpdate(action func(s *api.DeploymentStatus) bool, force ...bool) error
}