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:
parent
fd8e98aee9
commit
99770ce2bc
33 changed files with 655 additions and 575 deletions
|
@ -1,6 +1,7 @@
|
||||||
# Change Log
|
# Change Log
|
||||||
|
|
||||||
## [master](https://github.com/arangodb/kube-arangodb/tree/master) (N/A)
|
## [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)
|
## [1.0.1](https://github.com/arangodb/kube-arangodb/tree/1.0.1) (2020-03-25)
|
||||||
- Added Customizable Affinity settings for ArangoDB Member Pods
|
- Added Customizable Affinity settings for ArangoDB Member Pods
|
||||||
|
|
|
@ -59,6 +59,8 @@ const (
|
||||||
ConditionTypeBootstrapSucceded ConditionType = "BootstrapSucceded"
|
ConditionTypeBootstrapSucceded ConditionType = "BootstrapSucceded"
|
||||||
// ConditionTypeTerminating indicates that the member is terminating but not yet terminated.
|
// ConditionTypeTerminating indicates that the member is terminating but not yet terminated.
|
||||||
ConditionTypeTerminating ConditionType = "Terminating"
|
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.
|
// Condition represents one current condition of a deployment or deployment member.
|
||||||
|
@ -79,6 +81,10 @@ type Condition struct {
|
||||||
Message string `json:"message,omitempty"`
|
Message string `json:"message,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c Condition) IsTrue() bool {
|
||||||
|
return c.Status == v1.ConditionTrue
|
||||||
|
}
|
||||||
|
|
||||||
// ConditionList is a list of conditions.
|
// ConditionList is a list of conditions.
|
||||||
// Each type is allowed only once.
|
// Each type is allowed only once.
|
||||||
type ConditionList []Condition
|
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`.
|
// IsTrue return true when a condition with given type exists and its status is `True`.
|
||||||
func (list ConditionList) IsTrue(conditionType ConditionType) bool {
|
func (list ConditionList) IsTrue(conditionType ConditionType) bool {
|
||||||
c, found := list.Get(conditionType)
|
c, found := list.Get(conditionType)
|
||||||
return found && c.Status == v1.ConditionTrue
|
return found && c.IsTrue()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get a condition by type.
|
// Get a condition by type.
|
||||||
// Returns true if found, false if not found.
|
// Returns true if found, false if not found.
|
||||||
func (list ConditionList) Get(conditionType ConditionType) (Condition, bool) {
|
func (list ConditionList) Get(conditionType ConditionType) (Condition, bool) {
|
||||||
|
// Covers nil and empty lists
|
||||||
|
if len(list) == 0 {
|
||||||
|
return Condition{}, false
|
||||||
|
}
|
||||||
|
|
||||||
for _, x := range list {
|
for _, x := range list {
|
||||||
if x.Type == conditionType {
|
if x.Type == conditionType {
|
||||||
return x, true
|
return x, true
|
||||||
|
|
|
@ -93,3 +93,13 @@ func (d *ArangoDeployment) ForeachServerGroup(cb ServerGroupFunc, status *Deploy
|
||||||
}
|
}
|
||||||
return nil
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -23,6 +23,9 @@
|
||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/sha256"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util"
|
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||||
|
@ -413,3 +416,13 @@ func (s DeploymentSpec) ResetImmutableFields(target *DeploymentSpec) []string {
|
||||||
}
|
}
|
||||||
return resetFields
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -33,6 +33,9 @@ type DeploymentStatus struct {
|
||||||
// Reason contains a human readable reason for reaching the current state (can be empty)
|
// Reason contains a human readable reason for reaching the current state (can be empty)
|
||||||
Reason string `json:"reason,omitempty"` // Reason for current state
|
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)
|
// ServiceName holds the name of the Service a client can use (inside the k8s cluster)
|
||||||
// to access ArangoDB.
|
// to access ArangoDB.
|
||||||
ServiceName string `json:"serviceName,omitempty"`
|
ServiceName string `json:"serviceName,omitempty"`
|
||||||
|
|
|
@ -25,6 +25,7 @@ package v1
|
||||||
import (
|
import (
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util"
|
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||||
"github.com/dchest/uniuri"
|
"github.com/dchest/uniuri"
|
||||||
|
"k8s.io/apimachinery/pkg/api/equality"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -66,6 +67,8 @@ const (
|
||||||
ActionTypePVCResize ActionType = "PVCResize"
|
ActionTypePVCResize ActionType = "PVCResize"
|
||||||
// ActionTypePVCResized waits for PVC to resize for defined time
|
// ActionTypePVCResized waits for PVC to resize for defined time
|
||||||
ActionTypePVCResized ActionType = "PVCResized"
|
ActionTypePVCResized ActionType = "PVCResized"
|
||||||
|
// UpToDateUpdateResized define up to date annotation in spec
|
||||||
|
UpToDateUpdate ActionType = "UpToDateUpdate"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -92,6 +95,8 @@ type Action struct {
|
||||||
Reason string `json:"reason,omitempty"`
|
Reason string `json:"reason,omitempty"`
|
||||||
// Image used in can of a SetCurrentImage action.
|
// Image used in can of a SetCurrentImage action.
|
||||||
Image string `json:"image,omitempty"`
|
Image string `json:"image,omitempty"`
|
||||||
|
// Params additional parameters used for action
|
||||||
|
Params map[string]interface{} `json:"params,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal compares two Actions
|
// Equal compares two Actions
|
||||||
|
@ -103,7 +108,30 @@ func (a Action) Equal(other Action) bool {
|
||||||
util.TimeCompareEqual(a.CreationTime, other.CreationTime) &&
|
util.TimeCompareEqual(a.CreationTime, other.CreationTime) &&
|
||||||
util.TimeCompareEqualPointer(a.StartTime, other.StartTime) &&
|
util.TimeCompareEqualPointer(a.StartTime, other.StartTime) &&
|
||||||
a.Reason == other.Reason &&
|
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.
|
// NewAction instantiates a new Action.
|
||||||
|
|
|
@ -103,6 +103,10 @@ func (d *Deployment) GetStatus() (api.DeploymentStatus, int32) {
|
||||||
d.status.mutex.Lock()
|
d.status.mutex.Lock()
|
||||||
defer d.status.mutex.Unlock()
|
defer d.status.mutex.Unlock()
|
||||||
|
|
||||||
|
return d.getStatus()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Deployment) getStatus() (api.DeploymentStatus, int32) {
|
||||||
version := d.status.version
|
version := d.status.version
|
||||||
return *d.status.last.DeepCopy(), version
|
return *d.status.last.DeepCopy(), version
|
||||||
}
|
}
|
||||||
|
@ -115,6 +119,10 @@ func (d *Deployment) UpdateStatus(status api.DeploymentStatus, lastVersion int32
|
||||||
d.status.mutex.Lock()
|
d.status.mutex.Lock()
|
||||||
defer d.status.mutex.Unlock()
|
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 {
|
if d.status.version != lastVersion {
|
||||||
// Status is obsolete
|
// Status is obsolete
|
||||||
d.deps.Log.Error().
|
d.deps.Log.Error().
|
||||||
|
@ -483,3 +491,18 @@ func (d *Deployment) GetMetricsExporterImage() string {
|
||||||
func (d *Deployment) GetArangoImage() string {
|
func (d *Deployment) GetArangoImage() string {
|
||||||
return d.config.ArangoImage
|
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...)
|
||||||
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
"github.com/arangodb/kube-arangodb/pkg/apis/deployment"
|
"github.com/arangodb/kube-arangodb/pkg/apis/deployment"
|
||||||
|
|
||||||
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
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
|
return nextInterval
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inspect secret hashes
|
if inspectNextInterval, err := d.inspectDeploymentWithError(ctx, nextInterval); err != nil {
|
||||||
if err := d.resources.ValidateSecretHashes(); err != nil {
|
nextInterval = inspectNextInterval
|
||||||
hasError = true
|
hasError = true
|
||||||
d.CreateEvent(k8sutil.NewErrorEvent("Secret hash validation failed", err, d.apiObject))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for LicenseKeySecret
|
d.CreateEvent(k8sutil.NewErrorEvent("Reconcilation failed", err, d.apiObject))
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -231,6 +106,170 @@ func (d *Deployment) inspectDeployment(lastInterval util.Interval) util.Interval
|
||||||
return nextInterval.ReduceTo(maxInspectionInterval)
|
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.
|
// triggerInspection ensures that an inspection is run soon.
|
||||||
func (d *Deployment) triggerInspection() {
|
func (d *Deployment) triggerInspection() {
|
||||||
d.inspectTrigger.Trigger()
|
d.inspectTrigger.Trigger()
|
||||||
|
|
|
@ -24,7 +24,12 @@ package reconcile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Action executes a single Plan item.
|
// Action executes a single Plan item.
|
||||||
|
@ -41,3 +46,30 @@ type Action interface {
|
||||||
// Return the MemberID used / created in this action
|
// Return the MemberID used / created in this action
|
||||||
MemberID() string
|
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
|
||||||
|
}
|
||||||
|
|
|
@ -24,28 +24,34 @@ package reconcile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
"github.com/rs/zerolog/log"
|
"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.
|
// planned AddMember action.
|
||||||
func NewAddMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
func newAddMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
||||||
return &actionAddMember{
|
a := &actionAddMember{}
|
||||||
log: log,
|
|
||||||
action: action,
|
a.actionImpl = newActionImpl(log, action, actionCtx, addMemberTimeout, &a.newMemberID)
|
||||||
actionCtx: actionCtx,
|
|
||||||
}
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// actionAddMember implements an AddMemberAction.
|
// actionAddMember implements an AddMemberAction.
|
||||||
type actionAddMember struct {
|
type actionAddMember struct {
|
||||||
log zerolog.Logger
|
// actionImpl implement timeout and member id functions
|
||||||
action api.Action
|
actionImpl
|
||||||
actionCtx ActionContext
|
|
||||||
|
// actionEmptyCheckProgress implement check progress with empty implementation
|
||||||
|
actionEmptyCheckProgress
|
||||||
|
|
||||||
newMemberID string
|
newMemberID string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,20 +67,3 @@ func (a *actionAddMember) Start(ctx context.Context) (bool, error) {
|
||||||
a.newMemberID = newID
|
a.newMemberID = newID
|
||||||
return true, nil
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ package reconcile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
driver "github.com/arangodb/go-driver"
|
driver "github.com/arangodb/go-driver"
|
||||||
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||||
|
@ -33,21 +32,24 @@ import (
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/arangod"
|
"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.
|
// planned CleanOutMember action.
|
||||||
func NewCleanOutMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
func newCleanOutMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
||||||
return &actionCleanoutMember{
|
a := &actionCleanoutMember{}
|
||||||
log: log,
|
|
||||||
action: action,
|
a.actionImpl = newActionImplDefRef(log, action, actionCtx, cleanoutMemberTimeout)
|
||||||
actionCtx: actionCtx,
|
|
||||||
}
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// actionCleanoutMember implements an CleanOutMemberAction.
|
// actionCleanoutMember implements an CleanOutMemberAction.
|
||||||
type actionCleanoutMember struct {
|
type actionCleanoutMember struct {
|
||||||
log zerolog.Logger
|
// actionImpl implement timeout and member id functions
|
||||||
action api.Action
|
actionImpl
|
||||||
actionCtx ActionContext
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start performs the start of the action.
|
// Start performs the start of the action.
|
||||||
|
@ -154,13 +156,3 @@ func (a *actionCleanoutMember) CheckProgress(ctx context.Context) (bool, bool, e
|
||||||
// Cleanout completed
|
// Cleanout completed
|
||||||
return true, false, nil
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -109,6 +109,8 @@ type ActionContext interface {
|
||||||
DisableScalingCluster() error
|
DisableScalingCluster() error
|
||||||
// EnableScalingCluster enables scaling DBservers and coordinators
|
// EnableScalingCluster enables scaling DBservers and coordinators
|
||||||
EnableScalingCluster() error
|
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.
|
// newActionContext creates a new ActionContext implementation.
|
||||||
|
@ -125,6 +127,12 @@ type actionContext struct {
|
||||||
context Context
|
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) {
|
func (ac *actionContext) GetPv(pvName string) (*v1.PersistentVolume, error) {
|
||||||
return ac.context.GetPv(pvName)
|
return ac.context.GetPv(pvName)
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,27 +22,32 @@ package reconcile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||||
|
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
)
|
)
|
||||||
|
|
||||||
// actionDisableScalingCluster implements disabling scaling DBservers and coordinators.
|
func init() {
|
||||||
type actionDisableScalingCluster struct {
|
registerAction(api.ActionTypeDisableClusterScaling, newDisableScalingCluster)
|
||||||
log zerolog.Logger
|
|
||||||
action api.Action
|
|
||||||
actionCtx ActionContext
|
|
||||||
newMemberID string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDisableScalingCluster creates the new action with disabling scaling DBservers and coordinators.
|
// newDisableScalingCluster creates the new action with disabling scaling DBservers and coordinators.
|
||||||
func NewDisableScalingCluster(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
func newDisableScalingCluster(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
||||||
return &actionDisableScalingCluster{
|
a := &actionDisableScalingCluster{}
|
||||||
log: log,
|
|
||||||
action: action,
|
a.actionImpl = newActionImpl(log, action, actionCtx, 0, util.NewString(""))
|
||||||
actionCtx: actionCtx,
|
|
||||||
}
|
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
|
// Start disables scaling DBservers and coordinators
|
||||||
|
@ -53,18 +58,3 @@ func (a *actionDisableScalingCluster) Start(ctx context.Context) (bool, error) {
|
||||||
}
|
}
|
||||||
return true, nil
|
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 ""
|
|
||||||
}
|
|
||||||
|
|
|
@ -22,27 +22,32 @@ package reconcile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||||
|
"github.com/arangodb/kube-arangodb/pkg/util"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
)
|
)
|
||||||
|
|
||||||
// actionEnableScalingCluster implements enabling scaling DBservers and coordinators.
|
func init() {
|
||||||
type actionEnableScalingCluster struct {
|
registerAction(api.ActionTypeEnableClusterScaling, newEnableScalingCluster)
|
||||||
log zerolog.Logger
|
|
||||||
action api.Action
|
|
||||||
actionCtx ActionContext
|
|
||||||
newMemberID string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEnableScalingCluster creates the new action with enabling scaling DBservers and coordinators.
|
// newEnableScalingCluster creates the new action with enabling scaling DBservers and coordinators.
|
||||||
func NewEnableScalingCluster(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
func newEnableScalingCluster(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
||||||
return &actionEnableScalingCluster{
|
a := &actionEnableScalingCluster{}
|
||||||
log: log,
|
|
||||||
action: action,
|
a.actionImpl = newActionImpl(log, action, actionCtx, 0, util.NewString(""))
|
||||||
actionCtx: actionCtx,
|
|
||||||
}
|
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
|
// Start enables scaling DBservers and coordinators
|
||||||
|
@ -53,18 +58,3 @@ func (a *actionEnableScalingCluster) Start(ctx context.Context) (bool, error) {
|
||||||
}
|
}
|
||||||
return true, nil
|
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 ""
|
|
||||||
}
|
|
||||||
|
|
84
pkg/deployment/reconcile/action_helper.go
Normal file
84
pkg/deployment/reconcile/action_helper.go
Normal 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
|
||||||
|
}
|
|
@ -24,7 +24,6 @@ package reconcile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
|
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
|
||||||
core "k8s.io/api/core/v1"
|
core "k8s.io/api/core/v1"
|
||||||
|
@ -34,21 +33,24 @@ import (
|
||||||
"github.com/rs/zerolog"
|
"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.
|
// planned RotateMember action.
|
||||||
func NewPVCResizeAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
func newPVCResizeAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
||||||
return &actionPVCResize{
|
a := &actionPVCResize{}
|
||||||
log: log,
|
|
||||||
action: action,
|
a.actionImpl = newActionImplDefRef(log, action, actionCtx, pvcResizeTimeout)
|
||||||
actionCtx: actionCtx,
|
|
||||||
}
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// actionRotateMember implements an RotateMember.
|
// actionRotateMember implements an RotateMember.
|
||||||
type actionPVCResize struct {
|
type actionPVCResize struct {
|
||||||
log zerolog.Logger
|
// actionImpl implement timeout and member id functions
|
||||||
action api.Action
|
actionImpl
|
||||||
actionCtx ActionContext
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start performs the start of the action.
|
// 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
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ package reconcile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
|
"github.com/arangodb/kube-arangodb/pkg/util/k8sutil"
|
||||||
core "k8s.io/api/core/v1"
|
core "k8s.io/api/core/v1"
|
||||||
|
@ -34,28 +33,27 @@ import (
|
||||||
"github.com/rs/zerolog"
|
"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.
|
// planned RotateMember action.
|
||||||
func NewPVCResizedAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
func newPVCResizedAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
||||||
return &actionPVCResized{
|
a := &actionPVCResized{}
|
||||||
log: log,
|
|
||||||
action: action,
|
a.actionImpl = newActionImplDefRef(log, action, actionCtx, pvcResizedTimeout)
|
||||||
actionCtx: actionCtx,
|
|
||||||
}
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// actionRotateMember implements an RotateMember.
|
// actionRotateMember implements an RotateMember.
|
||||||
type actionPVCResized struct {
|
type actionPVCResized struct {
|
||||||
log zerolog.Logger
|
// actionImpl implement timeout and member id functions
|
||||||
action api.Action
|
actionImpl
|
||||||
actionCtx ActionContext
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start performs the start of the action.
|
// actionEmptyStart empty start function
|
||||||
// Returns true if the action is completely finished, false in case
|
actionEmptyStart
|
||||||
// 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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckProgress checks the progress of the action.
|
// 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
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ package reconcile
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
|
||||||
|
|
||||||
kubeErrors "k8s.io/apimachinery/pkg/api/errors"
|
kubeErrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
|
||||||
|
@ -34,21 +33,27 @@ import (
|
||||||
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
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.
|
// planned RecreateMember action.
|
||||||
func NewRecreateMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
func newRecreateMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
||||||
return &actionRecreateMember{
|
a := &actionRecreateMember{}
|
||||||
log: log,
|
|
||||||
action: action,
|
a.actionImpl = newActionImplDefRef(log, action, actionCtx, recreateMemberTimeout)
|
||||||
actionCtx: actionCtx,
|
|
||||||
}
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// actionRecreateMember implements an RecreateMemberAction.
|
// actionRecreateMember implements an RecreateMemberAction.
|
||||||
type actionRecreateMember struct {
|
type actionRecreateMember struct {
|
||||||
log zerolog.Logger
|
// actionImpl implement timeout and member id functions
|
||||||
action api.Action
|
actionImpl
|
||||||
actionCtx ActionContext
|
|
||||||
|
// actionEmptyCheckProgress implement check progress with empty implementation
|
||||||
|
actionEmptyCheckProgress
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start performs the start of the action.
|
// Start performs the start of the action.
|
||||||
|
@ -80,20 +85,3 @@ func (a *actionRecreateMember) Start(ctx context.Context) (bool, error) {
|
||||||
|
|
||||||
return true, nil
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -25,7 +25,6 @@ package reconcile
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
|
@ -35,21 +34,27 @@ import (
|
||||||
"github.com/arangodb/kube-arangodb/pkg/util/arangod"
|
"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.
|
// planned RemoveMember action.
|
||||||
func NewRemoveMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
func newRemoveMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
||||||
return &actionRemoveMember{
|
a := &actionRemoveMember{}
|
||||||
log: log,
|
|
||||||
action: action,
|
a.actionImpl = newActionImplDefRef(log, action, actionCtx, removeMemberTimeout)
|
||||||
actionCtx: actionCtx,
|
|
||||||
}
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// actionRemoveMember implements an RemoveMemberAction.
|
// actionRemoveMember implements an RemoveMemberAction.
|
||||||
type actionRemoveMember struct {
|
type actionRemoveMember struct {
|
||||||
log zerolog.Logger
|
// actionImpl implement timeout and member id functions
|
||||||
action api.Action
|
actionImpl
|
||||||
actionCtx ActionContext
|
|
||||||
|
// actionEmptyCheckProgress implement check progress with empty implementation
|
||||||
|
actionEmptyCheckProgress
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start performs the start of the action.
|
// Start performs the start of the action.
|
||||||
|
@ -114,20 +119,3 @@ func (a *actionRemoveMember) Start(ctx context.Context) (bool, error) {
|
||||||
}
|
}
|
||||||
return true, nil
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -30,21 +30,27 @@ import (
|
||||||
"github.com/rs/zerolog"
|
"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.
|
// planned RenewTLSCACertificate action.
|
||||||
func NewRenewTLSCACertificateAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
func newRenewTLSCACertificateAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
||||||
return &renewTLSCACertificateAction{
|
a := &renewTLSCACertificateAction{}
|
||||||
log: log,
|
|
||||||
action: action,
|
a.actionImpl = newActionImplDefRef(log, action, actionCtx, renewTLSCACertificateTimeout)
|
||||||
actionCtx: actionCtx,
|
|
||||||
}
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// renewTLSCACertificateAction implements a RenewTLSCACertificate action.
|
// renewTLSCACertificateAction implements a RenewTLSCACertificate action.
|
||||||
type renewTLSCACertificateAction struct {
|
type renewTLSCACertificateAction struct {
|
||||||
log zerolog.Logger
|
// actionImpl implement timeout and member id functions
|
||||||
action api.Action
|
actionImpl
|
||||||
actionCtx ActionContext
|
|
||||||
|
// actionEmptyCheckProgress implement check progress with empty implementation
|
||||||
|
actionEmptyCheckProgress
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start performs the start of the action.
|
// Start performs the start of the action.
|
||||||
|
|
|
@ -24,27 +24,32 @@ package reconcile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||||
"github.com/rs/zerolog"
|
"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.
|
// planned RenewTLSCertificate action.
|
||||||
func NewRenewTLSCertificateAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
func newRenewTLSCertificateAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
||||||
return &renewTLSCertificateAction{
|
a := &renewTLSCertificateAction{}
|
||||||
log: log,
|
|
||||||
action: action,
|
a.actionImpl = newActionImplDefRef(log, action, actionCtx, renewTLSCertificateTimeout)
|
||||||
actionCtx: actionCtx,
|
|
||||||
}
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// renewTLSCertificateAction implements a RenewTLSCertificate action.
|
// renewTLSCertificateAction implements a RenewTLSCertificate action.
|
||||||
type renewTLSCertificateAction struct {
|
type renewTLSCertificateAction struct {
|
||||||
log zerolog.Logger
|
// actionImpl implement timeout and member id functions
|
||||||
action api.Action
|
actionImpl
|
||||||
actionCtx ActionContext
|
|
||||||
|
// actionEmptyCheckProgress implement check progress with empty implementation
|
||||||
|
actionEmptyCheckProgress
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start performs the start of the action.
|
// Start performs the start of the action.
|
||||||
|
@ -64,19 +69,3 @@ func (a *renewTLSCertificateAction) Start(ctx context.Context) (bool, error) {
|
||||||
}
|
}
|
||||||
return false, nil
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -24,27 +24,29 @@ package reconcile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||||
"github.com/rs/zerolog"
|
"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.
|
// planned RotateMember action.
|
||||||
func NewRotateMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
func newRotateMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
||||||
return &actionRotateMember{
|
a := &actionRotateMember{}
|
||||||
log: log,
|
|
||||||
action: action,
|
a.actionImpl = newActionImplDefRef(log, action, actionCtx, rotateMemberTimeout)
|
||||||
actionCtx: actionCtx,
|
|
||||||
}
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// actionRotateMember implements an RotateMember.
|
// actionRotateMember implements an RotateMember.
|
||||||
type actionRotateMember struct {
|
type actionRotateMember struct {
|
||||||
log zerolog.Logger
|
// actionImpl implement timeout and member id functions
|
||||||
action api.Action
|
actionImpl
|
||||||
actionCtx ActionContext
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start performs the start of the action.
|
// 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
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -24,27 +24,29 @@ package reconcile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||||
"github.com/rs/zerolog"
|
"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.
|
// planned RotateStartMember action.
|
||||||
func NewRotateStartMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
func newRotateStartMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
||||||
return &actionRotateStartMember{
|
a := &actionRotateStartMember{}
|
||||||
log: log,
|
|
||||||
action: action,
|
a.actionImpl = newActionImplDefRef(log, action, actionCtx, rotateMemberTimeout)
|
||||||
actionCtx: actionCtx,
|
|
||||||
}
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// actionRotateStartMember implements an RotateStartMember.
|
// actionRotateStartMember implements an RotateStartMember.
|
||||||
type actionRotateStartMember struct {
|
type actionRotateStartMember struct {
|
||||||
log zerolog.Logger
|
// actionImpl implement timeout and member id functions
|
||||||
action api.Action
|
actionImpl
|
||||||
actionCtx ActionContext
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start performs the start of the action.
|
// Start performs the start of the action.
|
||||||
|
@ -116,13 +118,3 @@ func (a *actionRotateStartMember) CheckProgress(ctx context.Context) (bool, bool
|
||||||
}
|
}
|
||||||
return true, false, nil
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -24,27 +24,32 @@ package reconcile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||||
"github.com/rs/zerolog"
|
"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.
|
// planned RotateStopMember action.
|
||||||
func NewRotateStopMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
func newRotateStopMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
||||||
return &actionRotateStopMember{
|
a := &actionRotateStopMember{}
|
||||||
log: log,
|
|
||||||
action: action,
|
a.actionImpl = newActionImplDefRef(log, action, actionCtx, rotateMemberTimeout)
|
||||||
actionCtx: actionCtx,
|
|
||||||
}
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// actionRotateStopMember implements an RotateStopMember.
|
// actionRotateStopMember implements an RotateStopMember.
|
||||||
type actionRotateStopMember struct {
|
type actionRotateStopMember struct {
|
||||||
log zerolog.Logger
|
// actionImpl implement timeout and member id functions
|
||||||
action api.Action
|
actionImpl
|
||||||
actionCtx ActionContext
|
|
||||||
|
// actionEmptyCheckProgress implement check progress with empty implementation
|
||||||
|
actionEmptyCheckProgress
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start performs the start of the action.
|
// Start performs the start of the action.
|
||||||
|
@ -65,19 +70,3 @@ func (a *actionRotateStopMember) Start(ctx context.Context) (bool, error) {
|
||||||
}
|
}
|
||||||
return false, nil
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -24,31 +24,29 @@ package reconcile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||||
"github.com/rs/zerolog"
|
"github.com/rs/zerolog"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
func init() {
|
||||||
shutdownTimeout = time.Second * 15
|
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.
|
// planned ShutdownMember action.
|
||||||
func NewShutdownMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
func newShutdownMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
||||||
return &actionShutdownMember{
|
a := &actionShutdownMember{}
|
||||||
log: log,
|
|
||||||
action: action,
|
a.actionImpl = newActionImplDefRef(log, action, actionCtx, shutdownMemberTimeout)
|
||||||
actionCtx: actionCtx,
|
|
||||||
}
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// actionShutdownMember implements an ShutdownMemberAction.
|
// actionShutdownMember implements an ShutdownMemberAction.
|
||||||
type actionShutdownMember struct {
|
type actionShutdownMember struct {
|
||||||
log zerolog.Logger
|
// actionImpl implement timeout and member id functions
|
||||||
action api.Action
|
actionImpl
|
||||||
actionCtx ActionContext
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start performs the start of the action.
|
// 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
|
// Member still not shutdown, retry soon
|
||||||
return false, false, nil
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -24,27 +24,29 @@ package reconcile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||||
"github.com/rs/zerolog"
|
"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.
|
// planned SetCurrentImage action.
|
||||||
func NewSetCurrentImageAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
func newSetCurrentImageAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
||||||
return &setCurrentImageAction{
|
a := &setCurrentImageAction{}
|
||||||
log: log,
|
|
||||||
action: action,
|
a.actionImpl = newActionImplDefRef(log, action, actionCtx, upgradeMemberTimeout)
|
||||||
actionCtx: actionCtx,
|
|
||||||
}
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// setCurrentImageAction implements an SetCurrentImage.
|
// setCurrentImageAction implements an SetCurrentImage.
|
||||||
type setCurrentImageAction struct {
|
type setCurrentImageAction struct {
|
||||||
log zerolog.Logger
|
// actionImpl implement timeout and member id functions
|
||||||
action api.Action
|
actionImpl
|
||||||
actionCtx ActionContext
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start performs the start of the action.
|
// 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")
|
log.Info().Str("image", a.action.Image).Msg("Changed current image")
|
||||||
return true, false, nil
|
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 ""
|
|
||||||
}
|
|
||||||
|
|
|
@ -24,27 +24,29 @@ package reconcile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
||||||
"github.com/rs/zerolog"
|
"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.
|
// planned UpgradeMember action.
|
||||||
func NewUpgradeMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
func newUpgradeMemberAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
||||||
return &actionUpgradeMember{
|
a := &actionUpgradeMember{}
|
||||||
log: log,
|
|
||||||
action: action,
|
a.actionImpl = newActionImplDefRef(log, action, actionCtx, upgradeMemberTimeout)
|
||||||
actionCtx: actionCtx,
|
|
||||||
}
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// actionUpgradeMember implements an UpgradeMember.
|
// actionUpgradeMember implements an UpgradeMember.
|
||||||
type actionUpgradeMember struct {
|
type actionUpgradeMember struct {
|
||||||
log zerolog.Logger
|
// actionImpl implement timeout and member id functions
|
||||||
action api.Action
|
actionImpl
|
||||||
actionCtx ActionContext
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start performs the start of the action.
|
// 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
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -24,7 +24,6 @@ package reconcile
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"time"
|
|
||||||
|
|
||||||
driver "github.com/arangodb/go-driver"
|
driver "github.com/arangodb/go-driver"
|
||||||
"github.com/arangodb/go-driver/agency"
|
"github.com/arangodb/go-driver/agency"
|
||||||
|
@ -34,21 +33,24 @@ import (
|
||||||
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
|
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.
|
// planned WaitForMemberUp action.
|
||||||
func NewWaitForMemberUpAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
func newWaitForMemberUpAction(log zerolog.Logger, action api.Action, actionCtx ActionContext) Action {
|
||||||
return &actionWaitForMemberUp{
|
a := &actionWaitForMemberUp{}
|
||||||
log: log,
|
|
||||||
action: action,
|
a.actionImpl = newActionImplDefRef(log, action, actionCtx, waitForMemberUpTimeout)
|
||||||
actionCtx: actionCtx,
|
|
||||||
}
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
// actionWaitForMemberUp implements an WaitForMemberUp.
|
// actionWaitForMemberUp implements an WaitForMemberUp.
|
||||||
type actionWaitForMemberUp struct {
|
type actionWaitForMemberUp struct {
|
||||||
log zerolog.Logger
|
// actionImpl implement timeout and member id functions
|
||||||
action api.Action
|
actionImpl
|
||||||
actionCtx ActionContext
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start performs the start of the action.
|
// Start performs the start of the action.
|
||||||
|
@ -189,13 +191,3 @@ func (a *actionWaitForMemberUp) checkProgressArangoSync(ctx context.Context) (bo
|
||||||
}
|
}
|
||||||
return true, false, nil
|
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
|
|
||||||
}
|
|
||||||
|
|
|
@ -116,4 +116,6 @@ type Context interface {
|
||||||
RenderPodForMember(spec api.DeploymentSpec, status api.DeploymentStatus, memberID string, imageInfo api.ImageInfo) (*v1.Pod, error)
|
RenderPodForMember(spec api.DeploymentSpec, status api.DeploymentStatus, memberID string, imageInfo api.ImageInfo) (*v1.Pod, error)
|
||||||
// SelectImage select currently used image by pod
|
// SelectImage select currently used image by pod
|
||||||
SelectImage(spec api.DeploymentSpec, status api.DeploymentStatus) (api.ImageInfo, bool)
|
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
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ PlanBuilderContext = &testContext{}
|
var _ PlanBuilderContext = &testContext{}
|
||||||
|
var _ Context = &testContext{}
|
||||||
|
|
||||||
type testContext struct {
|
type testContext struct {
|
||||||
Pods []core.Pod
|
Pods []core.Pod
|
||||||
|
@ -54,6 +55,10 @@ type testContext struct {
|
||||||
RecordedEvent *k8sutil.Event
|
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) {
|
func (c *testContext) RenderPodForMember(spec api.DeploymentSpec, status api.DeploymentStatus, memberID string, imageInfo api.ImageInfo) (*core.Pod, error) {
|
||||||
panic("implement me")
|
panic("implement me")
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,47 +157,14 @@ func (d *Reconciler) ExecutePlan(ctx context.Context) (bool, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// startAction performs the start of the given action
|
// createAction create action object based on action type
|
||||||
// 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 (d *Reconciler) createAction(ctx context.Context, log zerolog.Logger, action api.Action) Action {
|
func (d *Reconciler) createAction(ctx context.Context, log zerolog.Logger, action api.Action) Action {
|
||||||
actionCtx := newActionContext(log, d.context)
|
actionCtx := newActionContext(log, d.context)
|
||||||
switch action.Type {
|
|
||||||
case api.ActionTypeAddMember:
|
f, ok := getActionFactory(action.Type)
|
||||||
return NewAddMemberAction(log, action, actionCtx)
|
if !ok {
|
||||||
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:
|
|
||||||
panic(fmt.Sprintf("Unknown action type '%s'", action.Type))
|
panic(fmt.Sprintf("Unknown action type '%s'", action.Type))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return f(log, action, actionCtx)
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,4 +37,7 @@ const (
|
||||||
shutdownMemberTimeout = time.Minute * 30
|
shutdownMemberTimeout = time.Minute * 30
|
||||||
upgradeMemberTimeout = time.Hour * 6
|
upgradeMemberTimeout = time.Hour * 6
|
||||||
waitForMemberUpTimeout = time.Minute * 15
|
waitForMemberUpTimeout = time.Minute * 15
|
||||||
|
upToDateUpdateTimeout = time.Minute
|
||||||
|
|
||||||
|
shutdownTimeout = time.Second * 15
|
||||||
)
|
)
|
||||||
|
|
|
@ -92,4 +92,6 @@ type Context interface {
|
||||||
GetDatabaseClient(ctx context.Context) (driver.Client, error)
|
GetDatabaseClient(ctx context.Context) (driver.Client, error)
|
||||||
// GetAgency returns a connection to the entire agency.
|
// GetAgency returns a connection to the entire agency.
|
||||||
GetAgency(ctx context.Context) (agency.Agency, error)
|
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
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue