Port native configuration reports
This commit is contained in:
@@ -5,93 +5,51 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
commandkit "gitea.maximumdirect.net/eric/CommandKit"
|
||||
"go.yaml.in/yaml/v4"
|
||||
)
|
||||
|
||||
func configOperationDeclared[C any](scopes []ConfigScope[C], operation ConfigOperation) bool {
|
||||
for _, scope := range scopes {
|
||||
if containsOperation(scope.Operations, operation) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func newConfigValidateCommand[C any](prepared *preparedConfigSuite[C]) (Command, error) {
|
||||
spec := CommandSpec[configInput[C]]{
|
||||
Name: string(ConfigValidate),
|
||||
Summary: "Validate selected configuration scopes.",
|
||||
Flags: configInputFlags(prepared.suite, "text"),
|
||||
CheckInput: func(input configInput[C]) error {
|
||||
_, err := preflightConfig(prepared, input, ConfigValidate)
|
||||
return err
|
||||
},
|
||||
Run: func(invocation Invocation, input configInput[C]) Outcome {
|
||||
return runConfigValidation(invocation, prepared, input)
|
||||
},
|
||||
}
|
||||
return NewCommand(spec)
|
||||
}
|
||||
|
||||
func runConfigValidation[C any](invocation Invocation, prepared *preparedConfigSuite[C], input configInput[C]) Outcome {
|
||||
if err := invocation.Context.Err(); err != nil {
|
||||
return Failure(err)
|
||||
}
|
||||
scopeNames, err := selectConfigScopes(prepared, input, ConfigValidate)
|
||||
if err != nil {
|
||||
return Failure(err)
|
||||
}
|
||||
contexts := contextsForScopes(prepared, input, scopeNames)
|
||||
diagnostics := make([]Diagnostic, 0)
|
||||
func runConfigValidation[I, S any](invocation commandkit.Invocation, plan *configOperationPlan[I, S], state S) commandkit.Outcome {
|
||||
diagnostics := make([]commandkit.Diagnostic, 0)
|
||||
writtenRecord := false
|
||||
for _, name := range scopeNames {
|
||||
scope, ok := findConfigScope(prepared, name)
|
||||
if !ok || scope.Acquire == nil {
|
||||
return validationFailure(fmt.Errorf("configuration scope %q has no acquisition callback", name), diagnostics, writtenRecord)
|
||||
}
|
||||
for _, selected := range plan.scopes {
|
||||
if err := invocation.Context.Err(); err != nil {
|
||||
return validationFailure(err, diagnostics, writtenRecord)
|
||||
return configOperationFailure(err, diagnostics, writtenRecord)
|
||||
}
|
||||
acquired, acquireErr := scope.Acquire(invocation.Context, ConfigRequest{Operation: ConfigValidate, Selection: input.Selection}, contexts[name])
|
||||
if selected.scope.scope.Acquire == nil {
|
||||
return configOperationFailure(fmt.Errorf("configuration scope %q has no acquisition callback", selected.scope.scope.Name), diagnostics, writtenRecord)
|
||||
}
|
||||
acquired, acquireErr := selected.scope.scope.Acquire(invocation.Context, Request{
|
||||
Operation: Validate,
|
||||
Selection: plan.selection,
|
||||
}, selected.input, state)
|
||||
diagnostics = append(diagnostics, acquired.Diagnostics...)
|
||||
if acquireErr != nil {
|
||||
return validationFailure(acquireErr, diagnostics, writtenRecord)
|
||||
return configOperationFailure(acquireErr, diagnostics, writtenRecord)
|
||||
}
|
||||
|
||||
if err := invocation.Context.Err(); err != nil {
|
||||
return validationFailure(err, diagnostics, writtenRecord)
|
||||
return configOperationFailure(err, diagnostics, writtenRecord)
|
||||
}
|
||||
|
||||
record, err := validationSuccessRecord(name, input.Format)
|
||||
record, err := validationSuccessRecord(selected.scope.scope.Name, plan.format)
|
||||
if err != nil {
|
||||
return validationFailure(err, diagnostics, writtenRecord)
|
||||
return configOperationFailure(err, diagnostics, writtenRecord)
|
||||
}
|
||||
if input.Format == "yaml" && !writtenRecord {
|
||||
if err := writeReport(invocation.Streams.Out, []byte("scopes:\n")); err != nil {
|
||||
outcome := validationFailure(err, diagnostics, true)
|
||||
outcome.DeliveryError = err
|
||||
return outcome
|
||||
if plan.format == "yaml" && !writtenRecord {
|
||||
if err := writeConfigReport(invocation.Streams.Out, []byte("scopes:\n")); err != nil {
|
||||
return configDeliveryFailure(err, diagnostics, true)
|
||||
}
|
||||
}
|
||||
if err := writeReport(invocation.Streams.Out, record); err != nil {
|
||||
outcome := validationFailure(err, diagnostics, true)
|
||||
outcome.DeliveryError = err
|
||||
return outcome
|
||||
if err := writeConfigReport(invocation.Streams.Out, record); err != nil {
|
||||
return configDeliveryFailure(err, diagnostics, true)
|
||||
}
|
||||
writtenRecord = true
|
||||
}
|
||||
outcome := Success()
|
||||
outcome := commandkit.Success()
|
||||
outcome.Diagnostics = diagnostics
|
||||
return outcome
|
||||
}
|
||||
|
||||
func validationFailure(cause error, diagnostics []Diagnostic, reportStarted bool) Outcome {
|
||||
outcome := Failure(cause)
|
||||
outcome.Diagnostics = diagnostics
|
||||
outcome.ReportIncomplete = reportStarted
|
||||
return outcome
|
||||
}
|
||||
|
||||
func validationSuccessRecord(scope, format string) ([]byte, error) {
|
||||
if format == "text" {
|
||||
return []byte(scope + ": valid\n"), nil
|
||||
|
||||
Reference in New Issue
Block a user