Move configuration reports to shared rendering
This commit is contained in:
@@ -1,83 +1,58 @@
|
||||
package ckconfig
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
commandkit "go.maximumdirect.net/commandkit"
|
||||
"go.yaml.in/yaml/v4"
|
||||
)
|
||||
|
||||
type validationReport struct {
|
||||
Scopes []validationScope `json:"scopes"`
|
||||
}
|
||||
|
||||
type validationScope struct {
|
||||
Scope string `json:"scope"`
|
||||
Outcome string `json:"outcome"`
|
||||
}
|
||||
|
||||
var validationTextTemplate = template.Must(commandkit.ParseTextTemplate("validation", "{{range .Scopes}}{{.Scope}}: {{.Outcome}}\n{{end}}", nil))
|
||||
|
||||
func runConfigValidation[I, S any](invocation commandkit.Invocation, plan *configOperationPlan[I, S], state S) commandkit.Outcome {
|
||||
reporter := invocation.Reporter()
|
||||
writtenRecord := false
|
||||
report := validationReport{Scopes: make([]validationScope, 0, len(plan.scopes))}
|
||||
outcome := commandkit.Success()
|
||||
for _, selected := range plan.scopes {
|
||||
if err := invocation.Context.Err(); err != nil {
|
||||
return configFailure("Configuration validation was canceled.", commandkit.Explanation{}, err)
|
||||
outcome = configFailure("Configuration validation was canceled.", commandkit.Explanation{}, err)
|
||||
break
|
||||
}
|
||||
name := selected.scope.scope.Name
|
||||
if selected.scope.scope.Acquire == nil {
|
||||
message := fmt.Sprintf("Configuration scope %q has no acquisition callback.", selected.scope.scope.Name)
|
||||
return commandkit.Failure(message)
|
||||
report.Scopes = append(report.Scopes, validationScope{Scope: name, Outcome: "failed"})
|
||||
outcome = commandkit.Failure(fmt.Sprintf("Configuration scope %q has no acquisition callback.", name))
|
||||
break
|
||||
}
|
||||
acquired, acquireErr := selected.scope.scope.Acquire(invocation.Context, Request{
|
||||
Operation: Validate,
|
||||
Selection: plan.selection,
|
||||
}, selected.input, state)
|
||||
if acquireErr != nil {
|
||||
return configAcquisitionFailure(reporter, "validate", selected.scope.scope.Name, acquired, acquireErr)
|
||||
acquired, err := selected.scope.scope.Acquire(invocation.Context, Request{Operation: Validate, Selection: plan.selection}, selected.input, state)
|
||||
if err != nil {
|
||||
status := "failed"
|
||||
if invocation.Context.Err() != nil {
|
||||
status = "canceled"
|
||||
}
|
||||
report.Scopes = append(report.Scopes, validationScope{Scope: name, Outcome: status})
|
||||
outcome = configAcquisitionFailure(reporter, "validate", name, acquired, err)
|
||||
break
|
||||
}
|
||||
queueConfigDiagnostics(reporter, acquired.Diagnostics)
|
||||
if err := invocation.Context.Err(); err != nil {
|
||||
return configFailure("Configuration validation was canceled.", acquired.Explanation, err)
|
||||
report.Scopes = append(report.Scopes, validationScope{Scope: name, Outcome: "canceled"})
|
||||
outcome = configFailure("Configuration validation was canceled.", acquired.Explanation, err)
|
||||
break
|
||||
}
|
||||
|
||||
err := reporter.RenderOutput(func(writer io.Writer) error {
|
||||
record, err := validationSuccessRecord(selected.scope.scope.Name, plan.format)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if plan.format == "yaml" && !writtenRecord {
|
||||
if _, err := io.WriteString(writer, "scopes:\n"); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
_, err = writer.Write(record)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
if ctxErr := invocation.Context.Err(); ctxErr != nil {
|
||||
return configFailure("Configuration validation was canceled.", acquired.Explanation, ctxErr)
|
||||
}
|
||||
return commandkit.Success()
|
||||
}
|
||||
writtenRecord = true
|
||||
report.Scopes = append(report.Scopes, validationScope{Scope: name, Outcome: "valid"})
|
||||
}
|
||||
return commandkit.Success()
|
||||
}
|
||||
|
||||
func validationSuccessRecord(scope, format string) ([]byte, error) {
|
||||
if format == "text" {
|
||||
return []byte(scope + ": valid\n"), nil
|
||||
}
|
||||
encoded, err := yaml.Marshal(struct {
|
||||
Name string `yaml:"name"`
|
||||
Valid bool `yaml:"valid"`
|
||||
}{Name: scope, Valid: true})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lines := strings.Split(strings.TrimSuffix(string(encoded), "\n"), "\n")
|
||||
var record bytes.Buffer
|
||||
for index, line := range lines {
|
||||
if index == 0 {
|
||||
record.WriteString(" - ")
|
||||
} else {
|
||||
record.WriteString(" ")
|
||||
}
|
||||
record.WriteString(line)
|
||||
record.WriteByte('\n')
|
||||
}
|
||||
return record.Bytes(), nil
|
||||
if len(report.Scopes) > 0 {
|
||||
_ = reporter.Report(commandkit.Report{Value: report, TextTemplate: validationTextTemplate})
|
||||
}
|
||||
return outcome
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user