Implement single-owner managed takeover
This commit is contained in:
@@ -21,6 +21,7 @@ const (
|
||||
ActionFailConflict Action = "fail_conflict"
|
||||
ActionFailUnmanaged Action = "fail_unmanaged"
|
||||
ActionForceReplace Action = "force_replace"
|
||||
ActionReplaceTakeover Action = "replace_takeover"
|
||||
)
|
||||
|
||||
type Request struct {
|
||||
@@ -36,6 +37,7 @@ type Request struct {
|
||||
Links *config.Links
|
||||
State config.StatePolicy
|
||||
Reconciliation config.ReconciliationPolicy
|
||||
Takeover config.TakeoverPolicy
|
||||
Transformers TransformerResolver
|
||||
Transfer config.TransferPolicy
|
||||
DistributorVersion string
|
||||
@@ -96,10 +98,14 @@ func Build(ctx context.Context, req Request) (Plan, error) {
|
||||
if err != nil {
|
||||
return Plan{}, err
|
||||
}
|
||||
comparison := compareDestination(req, status)
|
||||
action, reason := actionForComparison(comparison, req.Transfer, req.Force)
|
||||
reconciliation := normalizeReconciliation(req.Reconciliation)
|
||||
stateMode := normalizeState(req.State).Mode
|
||||
comparison := compareDestination(req, status)
|
||||
action, reason := actionForComparison(comparison, req.Transfer, req.Force)
|
||||
if takeoverActionAllowed(req, status, comparison, stateMode, action) {
|
||||
action = ActionReplaceTakeover
|
||||
reason = comparison.Reason
|
||||
}
|
||||
plan := Plan{
|
||||
PipelineID: req.PipelineID,
|
||||
DestinationID: req.DestinationID,
|
||||
@@ -162,6 +168,11 @@ func validateRequest(req Request) error {
|
||||
default:
|
||||
return fmt.Errorf("state.mode must be %s or %s", config.StateModeSingleOwner, config.StateModeSharedRoot)
|
||||
}
|
||||
switch normalizeTakeover(req.Takeover).Mode {
|
||||
case config.TakeoverModeSamePipeline, config.TakeoverModeSameSource, config.TakeoverModeAnyManaged, config.TakeoverModeNever:
|
||||
default:
|
||||
return fmt.Errorf("takeover.mode must be %s, %s, %s, or %s", config.TakeoverModeSamePipeline, config.TakeoverModeSameSource, config.TakeoverModeAnyManaged, config.TakeoverModeNever)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -179,6 +190,13 @@ func normalizeState(policy config.StatePolicy) config.StatePolicy {
|
||||
return policy
|
||||
}
|
||||
|
||||
func normalizeTakeover(policy config.TakeoverPolicy) config.TakeoverPolicy {
|
||||
if policy.Mode == "" {
|
||||
policy.Mode = config.TakeoverModeSamePipeline
|
||||
}
|
||||
return policy
|
||||
}
|
||||
|
||||
func compareDestination(req Request, status state.DestinationStatus) state.Comparison {
|
||||
if normalizeState(req.State).Mode == config.StateModeSharedRoot {
|
||||
scope := state.CurrentOwnerScope(req.PipelineID, req.DestinationID)
|
||||
@@ -207,24 +225,6 @@ func compareDestination(req Request, status state.DestinationStatus) state.Compa
|
||||
return comparison
|
||||
}
|
||||
comparison := state.Compare(req.SourceBundle.Manifest, req.PipelineID, req.DestinationID, status)
|
||||
if req.PathMapping != config.PathMappingFixed || comparison.Outcome != state.OutcomeDifferentSourceConflict || status.State == nil {
|
||||
return comparison
|
||||
}
|
||||
destinationManifest := status.State.Source.Manifest
|
||||
if destinationManifest.Created.Before(req.SourceBundle.Manifest.Created) {
|
||||
return state.Comparison{Outcome: state.OutcomeDestinationOlder, Reason: "fixed destination source is older than selected source"}
|
||||
}
|
||||
if destinationManifest.Created.After(req.SourceBundle.Manifest.Created) {
|
||||
return state.Comparison{
|
||||
Outcome: state.OutcomeDestinationNewer,
|
||||
Reason: "fixed destination source is newer than selected source",
|
||||
Detail: state.ComparisonDetail{
|
||||
Kind: state.ComparisonDetailDestinationNewer,
|
||||
CurrentSourceID: req.SourceBundle.Manifest.ID,
|
||||
DestinationSourceID: destinationManifest.ID,
|
||||
},
|
||||
}
|
||||
}
|
||||
return comparison
|
||||
}
|
||||
|
||||
@@ -296,7 +296,7 @@ func planSharedRootOwner(ctx context.Context, req Request, status state.Destinat
|
||||
|
||||
func isWriteAction(action Action) bool {
|
||||
switch action {
|
||||
case ActionPublishNew, ActionReplaceOlder, ActionForceReplace:
|
||||
case ActionPublishNew, ActionReplaceOlder, ActionReplaceTakeover, ActionForceReplace:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
@@ -439,3 +439,32 @@ func actionForComparison(comparison state.Comparison, transfer config.TransferPo
|
||||
return ActionFailConflict, "unsupported comparison outcome"
|
||||
}
|
||||
}
|
||||
|
||||
func takeoverActionAllowed(req Request, status state.DestinationStatus, comparison state.Comparison, stateMode string, action Action) bool {
|
||||
if stateMode != config.StateModeSingleOwner || status.State == nil {
|
||||
return false
|
||||
}
|
||||
if action == ActionForceReplace {
|
||||
return false
|
||||
}
|
||||
switch comparison.Detail.Kind {
|
||||
case state.ComparisonDetailPipelineIDMismatch,
|
||||
state.ComparisonDetailDestinationIDMismatch,
|
||||
state.ComparisonDetailDifferentSourceID:
|
||||
default:
|
||||
return false
|
||||
}
|
||||
takeover := normalizeTakeover(req.Takeover)
|
||||
switch takeover.Mode {
|
||||
case config.TakeoverModeSamePipeline:
|
||||
return status.State.PipelineID == req.PipelineID
|
||||
case config.TakeoverModeSameSource:
|
||||
return status.State.Source.Manifest.ID == req.SourceBundle.Manifest.ID
|
||||
case config.TakeoverModeAnyManaged:
|
||||
return true
|
||||
case config.TakeoverModeNever:
|
||||
return false
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user