170 lines
7.5 KiB
Go
170 lines
7.5 KiB
Go
package ckconfig
|
|
|
|
import (
|
|
"fmt"
|
|
"text/template"
|
|
|
|
commandkit "go.maximumdirect.net/commandkit"
|
|
configkit "go.maximumdirect.net/configkit"
|
|
)
|
|
|
|
type sourceReport struct {
|
|
Scope string `json:"scope" yaml:"scope"`
|
|
Sources []sourceDTO `json:"sources" yaml:"sources"`
|
|
}
|
|
|
|
type sourceDTO struct {
|
|
ID string `json:"id" yaml:"id"`
|
|
Label string `json:"label" yaml:"label"`
|
|
Path string `json:"path" yaml:"path"`
|
|
Destination string `json:"destination" yaml:"destination"`
|
|
Placement string `json:"placement" yaml:"placement"`
|
|
DestinationIsFallback bool `json:"destination_is_fallback" yaml:"destination_is_fallback"`
|
|
Layer string `json:"layer" yaml:"layer"`
|
|
Kind string `json:"kind" yaml:"kind"`
|
|
UnderlayIndex int `json:"underlay_index" yaml:"underlay_index"`
|
|
ImportedFrom *locationDTO `json:"imported_from" yaml:"imported_from"`
|
|
VersionEvidence *sourceVersionEvidenceDTO `json:"version_evidence" yaml:"version_evidence"`
|
|
EmptyImportSelections []emptyImportSelectionDTO `json:"empty_import_selections" yaml:"empty_import_selections"`
|
|
}
|
|
|
|
type emptyImportSelectionDTO struct {
|
|
Path string `json:"path" yaml:"path"`
|
|
Location locationDTO `json:"location" yaml:"location"`
|
|
Selector string `json:"selector" yaml:"selector"`
|
|
}
|
|
|
|
type locationDTO struct {
|
|
SourceID string `json:"source_id" yaml:"source_id"`
|
|
Line int `json:"line" yaml:"line"`
|
|
Column int `json:"column" yaml:"column"`
|
|
}
|
|
|
|
type sourceVersionEvidenceDTO struct {
|
|
Path string `json:"path" yaml:"path"`
|
|
Version versionDTO `json:"version" yaml:"version"`
|
|
Location *locationDTO `json:"location" yaml:"location"`
|
|
Redacted bool `json:"redacted" yaml:"redacted"`
|
|
}
|
|
|
|
type versionDTO struct {
|
|
Present bool `json:"present" yaml:"present"`
|
|
Null bool `json:"null" yaml:"null"`
|
|
Text string `json:"text" yaml:"text"`
|
|
}
|
|
|
|
func runConfigSources[I, S any](invocation commandkit.Invocation, plan *configOperationPlan[I, S], state S) commandkit.Outcome {
|
|
selected := plan.scopes[0]
|
|
name := selected.scope.scope.Name
|
|
reporter := invocation.Reporter()
|
|
if err := invocation.Context.Err(); err != nil {
|
|
return configFailure("Configuration source listing was canceled.", commandkit.Explanation{}, err)
|
|
}
|
|
if selected.scope.scope.Acquire == nil {
|
|
cause := fmt.Errorf("configuration scope %q has no acquisition callback", name)
|
|
return configFailure(fmt.Sprintf("Unable to list sources for configuration scope %q.", name), commandkit.Explanation{}, cause)
|
|
}
|
|
acquired, acquireErr := selected.scope.scope.Acquire(invocation.Context, Request{
|
|
Operation: Sources,
|
|
Selection: plan.selection,
|
|
}, selected.input, state)
|
|
queueConfigAcquisition(reporter, acquired)
|
|
if acquireErr != nil {
|
|
return configFailure(fmt.Sprintf("Unable to list sources for configuration scope %q.", name), acquired.Explanation, acquireErr)
|
|
}
|
|
if err := invocation.Context.Err(); err != nil {
|
|
return configFailure("Configuration source listing was canceled.", acquired.Explanation, err)
|
|
}
|
|
if acquired.Value.Sources == nil {
|
|
cause := fmt.Errorf("configuration scope %q did not provide a source reader", name)
|
|
return configFailure("Configuration scope did not provide source information.", acquired.Explanation, cause)
|
|
}
|
|
|
|
sources := acquired.Value.Sources.Sources()
|
|
document := sourceReport{Scope: name, Sources: make([]sourceDTO, 0, len(sources))}
|
|
for _, source := range sources {
|
|
placement := "mapping"
|
|
if source.PlacementMode == configkit.PlacementModeSequenceItem {
|
|
placement = "sequence_item"
|
|
}
|
|
item := sourceDTO{
|
|
ID: source.ID,
|
|
Label: source.Label,
|
|
Path: source.Path,
|
|
Destination: source.Destination.String(),
|
|
Placement: placement,
|
|
DestinationIsFallback: source.DestinationIsFallback,
|
|
Layer: string(source.Layer),
|
|
Kind: string(source.Kind),
|
|
UnderlayIndex: source.UnderlayIndex,
|
|
EmptyImportSelections: make([]emptyImportSelectionDTO, 0, len(source.EmptyImportSelections)),
|
|
}
|
|
if source.ImportedFrom != nil {
|
|
item.ImportedFrom = &locationDTO{SourceID: source.ImportedFrom.SourceID, Line: source.ImportedFrom.Line, Column: source.ImportedFrom.Column}
|
|
}
|
|
if source.VersionEvidence != nil {
|
|
check := source.VersionEvidence
|
|
item.VersionEvidence = &sourceVersionEvidenceDTO{
|
|
Path: check.Path.String(),
|
|
Version: versionDTO{
|
|
Present: check.Version.Present,
|
|
Null: check.Version.Null,
|
|
Text: check.Version.Text,
|
|
},
|
|
Redacted: check.Redacted,
|
|
}
|
|
if check.Location != nil {
|
|
item.VersionEvidence.Location = &locationDTO{SourceID: check.Location.SourceID, Line: check.Location.Line, Column: check.Location.Column}
|
|
}
|
|
}
|
|
for _, selection := range source.EmptyImportSelections {
|
|
item.EmptyImportSelections = append(item.EmptyImportSelections, emptyImportSelectionDTO{Path: selection.Path.String(), Location: locationDTO{SourceID: selection.Location.SourceID, Line: selection.Location.Line, Column: selection.Location.Column}, Selector: string(selection.Selector)})
|
|
}
|
|
document.Sources = append(document.Sources, item)
|
|
}
|
|
if err := invocation.Context.Err(); err != nil {
|
|
return configFailure("Configuration source listing was canceled.", acquired.Explanation, err)
|
|
}
|
|
_ = reporter.Report(commandkit.Report{Value: document, TextTemplate: sourceTextTemplate})
|
|
return commandkit.Success()
|
|
}
|
|
|
|
var sourceTextTemplate = template.Must(commandkit.ParseTextTemplate("sources", `Scope: {{printf "%q" .Scope}}
|
|
{{if .Sources}}Sources:
|
|
{{range .Sources}} - id: {{printf "%q" .ID}}
|
|
label: {{printf "%q" .Label}}
|
|
path: {{printf "%q" .Path}}
|
|
destination: {{printf "%q" .Destination}}
|
|
placement: {{printf "%q" .Placement}}
|
|
destination_is_fallback: {{.DestinationIsFallback}}
|
|
layer: {{printf "%q" .Layer}}
|
|
kind: {{printf "%q" .Kind}}
|
|
underlay_index: {{.UnderlayIndex}}
|
|
{{if .ImportedFrom}} imported_from: {source_id: {{printf "%q" .ImportedFrom.SourceID}}, line: {{.ImportedFrom.Line}}, column: {{.ImportedFrom.Column}}}
|
|
{{else}} imported_from: null
|
|
{{end}}{{if .VersionEvidence}} version_evidence:
|
|
path: {{printf "%q" .VersionEvidence.Path}}
|
|
version:
|
|
present: {{.VersionEvidence.Version.Present}}
|
|
null: {{.VersionEvidence.Version.Null}}
|
|
text: {{printf "%q" .VersionEvidence.Version.Text}}
|
|
{{if .VersionEvidence.Location}} location: {source_id: {{printf "%q" .VersionEvidence.Location.SourceID}}, line: {{.VersionEvidence.Location.Line}}, column: {{.VersionEvidence.Location.Column}}}
|
|
{{else}} location: null
|
|
{{end}} redacted: {{.VersionEvidence.Redacted}}
|
|
{{else}} version_evidence: null
|
|
{{end}}{{if .EmptyImportSelections}} empty_import_selections:
|
|
{{range .EmptyImportSelections}} - path: {{printf "%q" .Path}}
|
|
location: {source_id: {{printf "%q" .Location.SourceID}}, line: {{.Location.Line}}, column: {{.Location.Column}}}
|
|
selector: {{printf "%q" .Selector}}
|
|
{{end}}{{else}} empty_import_selections: []
|
|
{{end}}{{end}}{{else}}Sources: []
|
|
{{end}}`, nil))
|
|
|
|
func locationReports(locations []configkit.Location) []locationDTO {
|
|
report := make([]locationDTO, 0, len(locations))
|
|
for _, location := range locations {
|
|
report = append(report, locationDTO{SourceID: location.SourceID, Line: location.Line, Column: location.Column})
|
|
}
|
|
return report
|
|
}
|