func (p Plan) After(action ...Action) Plan {
	n := Plan{}
	n = append(n, p...)
	n = append(n, action...)
	return n
}
Add add action at the end of plan
package v2alpha1
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"
)
type ActionPriority int
const (
	ActionPriorityNormal ActionPriority = iota
	ActionPriorityHigh
)
type ActionType string
func (a ActionType) String() string {
	return string(a)
}
func (a ActionType) Priority() ActionPriority {
	switch a {
	case ActionTypeMemberPhaseUpdate, ActionTypeMemberRIDUpdate, ActionTypeSetMemberCondition:
		return ActionPriorityHigh
	default:
		return ActionPriorityNormal
	}
}
const (
	ActionTypeIdle ActionType = "Idle"
	ActionTypeAddMember ActionType = "AddMember"
	ActionTypeMarkToRemoveMember ActionType = "MarkToRemoveMember"
	ActionTypeRemoveMember ActionType = "RemoveMember"
	ActionTypeRecreateMember ActionType = "RecreateMember"
	ActionTypeCleanOutMember ActionType = "CleanOutMember"
	ActionTypeShutdownMember ActionType = "ShutdownMember"
	ActionTypeResignLeadership ActionType = "ResignLeadership"
	ActionTypeRotateMember ActionType = "RotateMember"
	ActionTypeRotateStartMember ActionType = "RotateStartMember"
	ActionTypeRotateStopMember ActionType = "RotateStopMember"
	ActionTypeUpgradeMember ActionType = "UpgradeMember"
	ActionTypeWaitForMemberUp ActionType = "WaitForMemberUp"
	ActionTypeWaitForMemberInSync ActionType = "WaitForMemberInSync"
	ActionTypeRenewTLSCertificate ActionType = "RenewTLSCertificate"
	ActionTypeRenewTLSCACertificate ActionType = "RenewTLSCACertificate"
	ActionTypeAppendTLSCACertificate ActionType = "AppendTLSCACertificate"
	ActionTypeCleanTLSCACertificate ActionType = "CleanTLSCACertificate"
	ActionTypeCleanTLSKeyfileCertificate ActionType = "CleanTLSKeyfileCertificate"
	ActionTypeRefreshTLSKeyfileCertificate ActionType = "RefreshTLSKeyfileCertificate"
	ActionTypeTLSKeyStatusUpdate ActionType = "TLSKeyStatusUpdate"
	ActionTypeTLSPropagated ActionType = "TLSPropagated"
	ActionTypeUpdateTLSSNI ActionType = "UpdateTLSSNI"
	ActionTypeSetCurrentImage ActionType = "SetCurrentImage"
	ActionTypeSetMemberCurrentImage ActionType = "SetMemberCurrentImage"
	ActionTypeDisableClusterScaling ActionType = "ScalingDisabled"
	ActionTypeEnableClusterScaling ActionType = "ScalingEnabled"
	ActionTypePVCResize ActionType = "PVCResize"
	ActionTypePVCResized ActionType = "PVCResized"
	UpToDateUpdate ActionType = "UpToDateUpdate"
	ActionTypeBackupRestore ActionType = "BackupRestore"
	ActionTypeBackupRestoreClean ActionType = "BackupRestoreClean"
	ActionTypeEncryptionKeyAdd ActionType = "EncryptionKeyAdd"
	ActionTypeEncryptionKeyRemove ActionType = "EncryptionKeyRemove"
	ActionTypeEncryptionKeyRefresh ActionType = "EncryptionKeyRefresh"
	ActionTypeEncryptionKeyStatusUpdate ActionType = "EncryptionKeyStatusUpdate"
	ActionTypeEncryptionKeyPropagated ActionType = "EncryptionKeyPropagated"
	ActionTypeJWTStatusUpdate ActionType = "JWTStatusUpdate"
	ActionTypeJWTSetActive ActionType = "JWTSetActive"
	ActionTypeJWTAdd ActionType = "JWTAdd"
	ActionTypeJWTClean ActionType = "JWTClean"
	ActionTypeJWTRefresh ActionType = "JWTRefresh"
	ActionTypeJWTPropagated ActionType = "JWTPropagated"
	ActionTypeClusterMemberCleanup ActionType = "ClusterMemberCleanup"
	ActionTypeEnableMaintenance ActionType = "EnableMaintenance"
	ActionTypeDisableMaintenance ActionType = "DisableMaintenance"
	ActionTypeSetMaintenanceCondition ActionType = "SetMaintenanceCondition"
	ActionTypeBootstrapUpdate ActionType = "BootstrapUpdate"
	ActionTypeBootstrapSetPassword ActionType = "BootstrapSetPassword"
	ActionTypeMemberPhaseUpdate ActionType = "MemberPhaseUpdate"
	ActionTypeSetMemberCondition ActionType = "SetMemberCondition"
	ActionTypeMemberRIDUpdate ActionType = "MemberRIDUpdate"
	ActionTypeArangoMemberUpdatePodSpec ActionType = "ArangoMemberUpdatePodSpec"
	ActionTypeArangoMemberUpdatePodStatus ActionType = "ArangoMemberUpdatePodStatus"
	ActionTypeRuntimeContainerImageUpdate ActionType = "RuntimeContainerImageUpdate"
	ActionTypeRuntimeContainerArgsLogLevelUpdate ActionType = "RuntimeContainerArgsLogLevelUpdate"
	ActionTypeTopologyEnable           ActionType = "TopologyEnable"
	ActionTypeTopologyDisable          ActionType = "TopologyDisable"
	ActionTypeTopologyZonesUpdate      ActionType = "TopologyZonesUpdate"
	ActionTypeTopologyMemberAssignment ActionType = "TopologyMemberAssignment"
)
const (
	MemberIDPreviousAction = "@previous"
)
type Action struct {
	ID string `json:"id"`
	Type ActionType `json:"type"`
	MemberID string `json:"memberID,omitempty"`
	Group ServerGroup `json:"group,omitempty"`
	CreationTime metav1.Time `json:"creationTime"`
	StartTime *metav1.Time `json:"startTime,omitempty"`
	Reason string `json:"reason,omitempty"`
	Image string `json:"image,omitempty"`
	Params map[string]string `json:"params,omitempty"`
}
func (a Action) Equal(other Action) bool {
	return a.ID == other.ID &&
		a.Type == other.Type &&
		a.MemberID == other.MemberID &&
		a.Group == other.Group &&
		util.TimeCompareEqual(a.CreationTime, other.CreationTime) &&
		util.TimeCompareEqualPointer(a.StartTime, other.StartTime) &&
		a.Reason == other.Reason &&
		a.Image == other.Image &&
		equality.Semantic.DeepEqual(a.Params, other.Params)
}
func (a Action) AddParam(key, value string) Action {
	if a.Params == nil {
		a.Params = map[string]string{}
	}
	a.Params[key] = value
	return a
}
func (a Action) GetParam(key string) (string, bool) {
	if a.Params == nil {
		return "", false
	}
	i, ok := a.Params[key]
	return i, ok
}
func NewAction(actionType ActionType, group ServerGroup, memberID string, reason ...string) Action {
	a := Action{
		ID:           uniuri.New(),
		Type:         actionType,
		MemberID:     memberID,
		Group:        group,
		CreationTime: metav1.Now(),
	}
	if len(reason) != 0 {
		a.Reason = reason[0]
	}
	return a
}
type ActionBuilder interface {
	NewAction(actionType ActionType, reason ...string) Action
}
type actionBuilder struct {
	group    ServerGroup
	memberID string
}
func (a actionBuilder) NewAction(actionType ActionType, reason ...string) Action {
	return NewAction(actionType, a.group, a.memberID, reason...)
}
func NewActionBuilder(group ServerGroup, memberID string) ActionBuilder {
	return actionBuilder{
		group:    group,
		memberID: memberID,
	}
}
func (a Action) SetImage(image string) Action {
	a.Image = image
	return a
}
func AsPlan(a []Action) Plan {
	return a
}
type Plan []Action
func (p Plan) Equal(other Plan) bool {
	if len(p) != len(other) {
		return false
	}
	for i := 0; i < len(p); i++ {
		if !p[i].Equal(other[i]) {
			return false
		}
	}
	return true
}
func (p Plan) IsEmpty() bool {
	return len(p) == 0
}