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

[Feature] Add action progress (#1103)

This commit is contained in:
Tomasz Mielech 2022-09-29 11:20:43 +02:00 committed by ajanikow
parent 3c02016fe0
commit 1c913aa2b9
No known key found for this signature in database
GPG key ID: D59E36FB488484FA
6 changed files with 89 additions and 7 deletions

View file

@ -1,6 +1,7 @@
# Change Log
## [master](https://github.com/arangodb/kube-arangodb/tree/master) (N/A)
- (Feature) Add action progress
## [1.2.19](https://github.com/arangodb/kube-arangodb/tree/1.2.19) (2022-10-05)
- (Bugfix) Prevent changes when UID is wrong

View file

@ -97,6 +97,8 @@ type Action struct {
Locals PlanLocals `json:"locals,omitempty"`
// ID reference of the task involved in this action (if any)
TaskID types.UID `json:"taskID,omitempty"`
// Progress describes what is a status of the current action.
Progress string `json:"progress,omitempty"`
}
// Equal compares two Actions
@ -112,7 +114,8 @@ func (a Action) Equal(other Action) bool {
a.Image == other.Image &&
equality.Semantic.DeepEqual(a.Params, other.Params) &&
a.Locals.Equal(other.Locals) &&
a.TaskID == other.TaskID
a.TaskID == other.TaskID &&
a.Progress == other.Progress
}
// AddParam returns copy of action with set parameter

View file

@ -97,6 +97,8 @@ type Action struct {
Locals PlanLocals `json:"locals,omitempty"`
// ID reference of the task involved in this action (if any)
TaskID types.UID `json:"taskID,omitempty"`
// Progress describes what is a status of the current action.
Progress string `json:"progress,omitempty"`
}
// Equal compares two Actions
@ -112,7 +114,8 @@ func (a Action) Equal(other Action) bool {
a.Image == other.Image &&
equality.Semantic.DeepEqual(a.Params, other.Params) &&
a.Locals.Equal(other.Locals) &&
a.TaskID == other.TaskID
a.TaskID == other.TaskID &&
a.Progress == other.Progress
}
// AddParam returns copy of action with set parameter

View file

@ -60,6 +60,7 @@ type ActionContext interface {
Metrics() *Metrics
ActionLocalsContext
ActionProgressor
// GetMemberStatusByID returns the current member status
// for the member with given id.
@ -113,6 +114,14 @@ type ActionLocalsContext interface {
BackoffExecution(action api.Action, key api.PlanLocalKey, duration time.Duration) bool
}
// ActionProgressor describe functions to follow a progress of an action.
type ActionProgressor interface {
// GetProgress returns progress of an action.
GetProgress() string
// SetProgress sets progress of an action.
SetProgress(progress string)
}
// newActionContext creates a new ActionContext implementation.
func newActionContext(log logging.Logger, context Context, metrics *Metrics) ActionContext {
return &actionContext{
@ -128,6 +137,7 @@ type actionContext struct {
log logging.Logger
cachedStatus inspectorInterface.Inspector
locals api.PlanLocals
Progress string
metrics *Metrics
}
@ -183,6 +193,16 @@ func (ac *actionContext) SetTime(key api.PlanLocalKey, t time.Time) bool {
return ac.Add(key, t.Format(util.TimeLayout), true)
}
// SetProgress sets progress to an action.
func (ac *actionContext) SetProgress(progress string) {
ac.Progress = progress
}
// GetProgress gets progress of an action.
func (ac *actionContext) GetProgress() string {
return ac.Progress
}
func (ac *actionContext) GetTime(action api.Action, key api.PlanLocalKey) (time.Time, bool) {
s, ok := ac.locals.GetWithParent(action.Locals, key)
if !ok {

View file

@ -22,10 +22,13 @@ package reconcile
import (
"context"
"net/http"
driver "github.com/arangodb/go-driver"
api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1"
"github.com/arangodb/kube-arangodb/pkg/deployment/client"
"github.com/arangodb/kube-arangodb/pkg/deployment/resources"
"github.com/arangodb/kube-arangodb/pkg/util/errors"
"github.com/arangodb/kube-arangodb/pkg/util/globals"
)
@ -84,7 +87,7 @@ func (a *actionWaitForMemberUp) CheckProgress(ctx context.Context) (bool, bool,
if a.action.Group == api.ServerGroupAgents {
return a.checkProgressAgent()
}
return a.checkProgressCluster()
return a.checkProgressCluster(ctx)
}
}
@ -138,7 +141,7 @@ func (a *actionWaitForMemberUp) checkProgressAgent() (bool, bool, error) {
// checkProgressCluster checks the progress of the action in the case
// of a cluster deployment (coordinator/dbserver).
func (a *actionWaitForMemberUp) checkProgressCluster() (bool, bool, error) {
func (a *actionWaitForMemberUp) checkProgressCluster(ctx context.Context) (bool, bool, error) {
h, _ := a.actionCtx.GetMembersState().Health()
if h.Error != nil {
a.log.Err(h.Error).Debug("Cluster health is missing")
@ -153,13 +156,32 @@ func (a *actionWaitForMemberUp) checkProgressCluster() (bool, bool, error) {
a.log.Str("status", string(sh.Status)).Debug("Member set status not yet good")
return false, false, nil
}
// Wait for the member to become ready from a kubernetes point of view
// otherwise the coordinators may be rotated to fast and thus none of them
// is ready resulting in a short downtime
if m, found := a.actionCtx.GetMemberStatusByID(a.MemberID()); !found {
m, found := a.actionCtx.GetMemberStatusByID(a.MemberID())
if !found {
a.log.Error("No such member")
return false, true, nil
} else if !m.Conditions.IsTrue(api.ConditionTypeReady) {
}
imageInfo, found := a.actionCtx.GetCurrentImageInfo()
if !found {
a.log.Info("Image not found")
return false, false, nil
}
if resources.IsServerProgressAvailable(a.action.Group, imageInfo) {
if status, err := a.getServerStatus(ctx); err == nil {
progress, _ := status.GetProgress()
a.actionCtx.SetProgress(progress)
} else {
a.log.Err(err).Warn("Failed to get server status to establish a progress")
}
}
if !m.Conditions.IsTrue(api.ConditionTypeReady) {
a.log.Debug("Member not yet ready")
return false, false, nil
}
@ -181,3 +203,36 @@ func (a *actionWaitForMemberUp) checkProgressArangoSync(ctx context.Context) (bo
}
return true, false, nil
}
func (a actionWaitForMemberUp) getServerStatus(ctx context.Context) (client.ServerStatus, error) {
cli, err := a.actionCtx.GetMembersState().GetMemberClient(a.action.MemberID)
if err != nil {
return client.ServerStatus{}, err
}
conn := cli.Connection()
req, err := conn.NewRequest("GET", "_admin/status")
if err != nil {
return client.ServerStatus{}, err
}
ctxChild, cancel := globals.GetGlobalTimeouts().ArangoD().WithTimeout(ctx)
defer cancel()
resp, err := conn.Do(ctxChild, req)
if err != nil {
return client.ServerStatus{}, err
}
if err := resp.CheckStatus(http.StatusOK); err != nil {
return client.ServerStatus{}, err
}
var result client.ServerStatus
if err := resp.ParseBody("", &result); err != nil {
return client.ServerStatus{}, err
}
return result, nil
}

View file

@ -294,7 +294,7 @@ func (d *Reconciler) executePlan(ctx context.Context, statusPlan api.Plan, pg pl
}
plan[0].Locals.Merge(actionContext.CurrentLocals())
plan[0].Progress = actionContext.GetProgress()
return plan, recall, false, nil
}
}