Demonstrate config diff in simple consumer
This commit is contained in:
@@ -4,6 +4,7 @@ Run the maintained example with:
|
||||
|
||||
```sh
|
||||
go run . config show
|
||||
go run . config diff --config fixtures/before.yml --against-config fixtures/after.yml
|
||||
go run . greet
|
||||
go run . greet --count=0 --tag=first --tag second
|
||||
```
|
||||
@@ -11,4 +12,6 @@ go run . greet --count=0 --tag=first --tag second
|
||||
The `config` family comes from one typed ConfigKit scope. The custom `greet`
|
||||
command uses CommandKit's typed bindings and shows the difference between an
|
||||
omitted `--count` and an explicitly supplied zero, plus ordered repeated tags.
|
||||
The configuration is synthetic and stays in memory.
|
||||
With no `--config`, application settings use the in-memory default. A supplied
|
||||
configuration and overlay are passed to ConfigKit unchanged. The comparison
|
||||
command loads the two local fixtures and reports `changes.greeting: Goodbye`.
|
||||
|
||||
1
integrations/ckconfig/examples/simple/fixtures/after.yml
Normal file
1
integrations/ckconfig/examples/simple/fixtures/after.yml
Normal file
@@ -0,0 +1 @@
|
||||
greeting: Goodbye
|
||||
@@ -0,0 +1 @@
|
||||
greeting: Hello
|
||||
@@ -20,10 +20,19 @@ type greetInput struct {
|
||||
Tags commandkit.Supplied[[]string]
|
||||
}
|
||||
|
||||
func loadAppConfiguration(_ context.Context, _ ckconfig.Selection) (*configkit.Result[appConfiguration], error) {
|
||||
return configkit.Load[appConfiguration](configkit.Mapping("simple application settings", map[string]any{
|
||||
func loadAppConfiguration(_ context.Context, selection ckconfig.Selection) (*configkit.Result[appConfiguration], error) {
|
||||
source := configkit.Mapping("simple application settings", map[string]any{
|
||||
"greeting": "Hello",
|
||||
}))
|
||||
})
|
||||
if selection.Config.Set {
|
||||
source = configkit.File(selection.Config.Value)
|
||||
}
|
||||
options := configkit.Options[appConfiguration]{}
|
||||
if selection.Overlay.Set {
|
||||
options.Overlay = selection.Overlay.Value
|
||||
options.Filesystem = &configkit.FilesystemContext{Root: ".", BaseDir: "."}
|
||||
}
|
||||
return configkit.Load(source, options)
|
||||
}
|
||||
|
||||
func newApp() (*commandkit.App, error) {
|
||||
|
||||
81
integrations/ckconfig/examples/simple/main_test.go
Normal file
81
integrations/ckconfig/examples/simple/main_test.go
Normal file
@@ -0,0 +1,81 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
commandkit "gitea.maximumdirect.net/eric/CommandKit"
|
||||
"gitea.maximumdirect.net/eric/CommandKit/integrations/ckconfig"
|
||||
"go.yaml.in/yaml/v4"
|
||||
)
|
||||
|
||||
func TestSimpleAppComparesFixturesAndKeepsDefaultCommands(t *testing.T) {
|
||||
app, err := newApp()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var output bytes.Buffer
|
||||
outcome := app.Execute(context.Background(), []string{"config", "diff", "--config", "fixtures/before.yml", "--against-config", "fixtures/after.yml"}, commandkit.Streams{Out: &output, Err: io.Discard})
|
||||
if outcome.Kind != commandkit.OutcomeSuccess {
|
||||
t.Fatalf("fixture comparison outcome = %#v", outcome)
|
||||
}
|
||||
var report yaml.Node
|
||||
if err := yaml.Unmarshal(output.Bytes(), &report); err != nil {
|
||||
t.Fatalf("comparison report is not YAML: %q: %v", output.String(), err)
|
||||
}
|
||||
changes := field(report.Content[0], "changes")
|
||||
greeting := field(changes, "greeting")
|
||||
if greeting == nil || greeting.Value != "Goodbye" {
|
||||
t.Fatalf("fixture comparison report = %q", output.String())
|
||||
}
|
||||
|
||||
output.Reset()
|
||||
outcome = app.Execute(context.Background(), []string{"config", "diff", "--config", "fixtures/before.yml", "--against-config", "fixtures/before.yml"}, commandkit.Streams{Out: &output, Err: io.Discard})
|
||||
if outcome.Kind != commandkit.OutcomeSuccess {
|
||||
t.Fatalf("equal fixture comparison outcome = %#v", outcome)
|
||||
}
|
||||
if reportNode, err := decodeReport(output.Bytes()); err != nil || len(field(reportNode, "additions").Content) != 0 || len(field(reportNode, "changes").Content) != 0 || len(field(reportNode, "deletions").Content) != 0 {
|
||||
t.Fatalf("equal fixture report = %q, decode error %v", output.String(), err)
|
||||
}
|
||||
|
||||
output.Reset()
|
||||
outcome = app.Execute(context.Background(), []string{"config", "show"}, commandkit.Streams{Out: &output, Err: io.Discard})
|
||||
if outcome.Kind != commandkit.OutcomeSuccess || output.String() != "greeting: Hello\n" {
|
||||
t.Fatalf("default show outcome/output = %#v / %q", outcome, output.String())
|
||||
}
|
||||
|
||||
output.Reset()
|
||||
outcome = app.Execute(context.Background(), []string{"greet"}, commandkit.Streams{Out: &output, Err: io.Discard})
|
||||
if outcome.Kind != commandkit.OutcomeSuccess || len(output.String()) == 0 || output.String()[:5] != "Hello" {
|
||||
t.Fatalf("default greeting outcome/output = %#v / %q", outcome, output.String())
|
||||
}
|
||||
}
|
||||
|
||||
func TestSimpleLoaderDoesNotReplaceExplicitEmptyConfiguration(t *testing.T) {
|
||||
_, err := loadAppConfiguration(context.Background(), ckconfig.Selection{Config: commandkit.Supplied[string]{Set: true}})
|
||||
if err == nil {
|
||||
t.Fatal("explicit empty configuration fell back to the default source")
|
||||
}
|
||||
}
|
||||
|
||||
func field(mapping *yaml.Node, name string) *yaml.Node {
|
||||
if mapping == nil || mapping.Kind != yaml.MappingNode {
|
||||
return nil
|
||||
}
|
||||
for index := 0; index+1 < len(mapping.Content); index += 2 {
|
||||
if mapping.Content[index].Value == name {
|
||||
return mapping.Content[index+1]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeReport(data []byte) (*yaml.Node, error) {
|
||||
var document yaml.Node
|
||||
if err := yaml.Unmarshal(data, &document); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return document.Content[0], nil
|
||||
}
|
||||
Reference in New Issue
Block a user