2026-10-11 01:39:23 +00:00
|
|
|
package ckconfig
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
2026-10-26 14:32:03 +00:00
|
|
|
"io"
|
2026-10-11 01:39:23 +00:00
|
|
|
|
|
|
|
|
commandkit "gitea.maximumdirect.net/eric/CommandKit"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func runConfigOperation[I, S any](invocation commandkit.Invocation, operation Operation, input *configCommandInput[I, S]) commandkit.Outcome {
|
|
|
|
|
if input == nil || input.plan == nil {
|
2026-10-26 03:16:02 +00:00
|
|
|
return commandkit.Failure("Configuration operation was not prepared.")
|
2026-10-11 01:39:23 +00:00
|
|
|
}
|
|
|
|
|
if err := invocation.Context.Err(); err != nil {
|
2026-10-26 03:16:02 +00:00
|
|
|
return configFailure("Configuration operation was canceled.", commandkit.Explanation{}, err)
|
2026-10-11 01:39:23 +00:00
|
|
|
}
|
|
|
|
|
plan := input.plan
|
|
|
|
|
var state S
|
|
|
|
|
if plan.prepared.newState != nil {
|
|
|
|
|
state = plan.prepared.newState()
|
|
|
|
|
}
|
|
|
|
|
switch operation {
|
|
|
|
|
case Validate:
|
|
|
|
|
return runConfigValidation(invocation, plan, state)
|
|
|
|
|
case Show:
|
|
|
|
|
return runConfigShow(invocation, plan, state)
|
|
|
|
|
case Sources:
|
|
|
|
|
return runConfigSources(invocation, plan, state)
|
|
|
|
|
case Explain:
|
|
|
|
|
return runConfigExplanation(invocation, plan, state)
|
2026-10-11 21:51:54 +00:00
|
|
|
case Diff:
|
|
|
|
|
return runConfigDiff(invocation, plan, state)
|
2026-10-11 01:39:23 +00:00
|
|
|
default:
|
2026-10-26 03:16:02 +00:00
|
|
|
return commandkit.Failure(fmt.Sprintf("Unsupported configuration operation %q.", operation))
|
2026-10-11 01:39:23 +00:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-10-26 03:16:02 +00:00
|
|
|
func queueConfigDiagnostics(reporter *commandkit.Reporter, diagnostics []commandkit.Diagnostic) {
|
|
|
|
|
deferred := reporter.AtEnd()
|
|
|
|
|
for _, diagnostic := range diagnostics {
|
|
|
|
|
if diagnostic.Write == nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
switch diagnostic.Severity {
|
|
|
|
|
case commandkit.SeverityInfo:
|
|
|
|
|
_ = deferred.Info("", diagnostic.Write)
|
|
|
|
|
case commandkit.SeverityDebug:
|
|
|
|
|
_ = deferred.Debug("", diagnostic.Write)
|
|
|
|
|
case commandkit.SeverityProgress:
|
|
|
|
|
_ = reporter.Progress("", diagnostic.Write)
|
|
|
|
|
default:
|
|
|
|
|
_ = deferred.Warn("", diagnostic.Write)
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-10-11 01:39:23 +00:00
|
|
|
}
|
|
|
|
|
|
2026-10-26 03:16:02 +00:00
|
|
|
func configFailure(message string, explanation commandkit.Explanation, cause error) commandkit.Outcome {
|
|
|
|
|
if explanation.Message != "" || len(explanation.Details) > 0 {
|
|
|
|
|
message = explanation.Message
|
|
|
|
|
}
|
|
|
|
|
outcome := commandkit.Failure(message, explanation.Details...)
|
|
|
|
|
if cause != nil {
|
|
|
|
|
outcome = outcome.WithCause(cause)
|
|
|
|
|
}
|
2026-10-11 01:39:23 +00:00
|
|
|
return outcome
|
|
|
|
|
}
|
2026-10-26 03:16:02 +00:00
|
|
|
|
|
|
|
|
func configAcquisitionFailure(
|
|
|
|
|
reporter *commandkit.Reporter,
|
|
|
|
|
operation, scope string,
|
|
|
|
|
acquired commandkit.Acquired[View],
|
|
|
|
|
cause error,
|
|
|
|
|
) commandkit.Outcome {
|
|
|
|
|
queueConfigDiagnostics(reporter, acquired.Diagnostics)
|
|
|
|
|
message := fmt.Sprintf("Unable to %s configuration scope %q.", operation, scope)
|
|
|
|
|
return configFailure(message, acquired.Explanation, cause)
|
|
|
|
|
}
|
2026-10-26 14:32:03 +00:00
|
|
|
|
|
|
|
|
// Preserve the preparation/delivery cancellation checkpoint for buffered reports.
|
|
|
|
|
func renderPreparedConfigReport(invocation commandkit.Invocation, explanation commandkit.Explanation, prepare func() ([]byte, error)) commandkit.Outcome {
|
|
|
|
|
var canceled error
|
|
|
|
|
renderErr := invocation.Reporter().RenderOutput(func(writer io.Writer) error {
|
|
|
|
|
report, err := prepare()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
if canceled = invocation.Context.Err(); canceled != nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
_, err = writer.Write(report)
|
|
|
|
|
return err
|
|
|
|
|
})
|
|
|
|
|
if canceled == nil && renderErr != nil {
|
|
|
|
|
canceled = invocation.Context.Err()
|
|
|
|
|
}
|
|
|
|
|
if canceled != nil {
|
|
|
|
|
return configFailure("Configuration report preparation was canceled.", explanation, canceled)
|
|
|
|
|
}
|
|
|
|
|
return commandkit.Success()
|
|
|
|
|
}
|