package ckconfig import ( "fmt" "text/template" commandkit "go.maximumdirect.net/commandkit" ) 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() report := validationReport{Scopes: make([]validationScope, 0, len(plan.scopes))} outcome := commandkit.Success() for _, selected := range plan.scopes { if err := invocation.Context.Err(); err != nil { outcome = configFailure("Configuration validation was canceled.", commandkit.Explanation{}, err) break } name := selected.scope.scope.Name if selected.scope.scope.Acquire == nil { 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, 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 { report.Scopes = append(report.Scopes, validationScope{Scope: name, Outcome: "canceled"}) outcome = configFailure("Configuration validation was canceled.", acquired.Explanation, err) break } report.Scopes = append(report.Scopes, validationScope{Scope: name, Outcome: "valid"}) } if len(report.Scopes) > 0 { _ = reporter.Report(commandkit.Report{Value: report, TextTemplate: validationTextTemplate}) } return outcome }