From 614b4426c2d876a5d0925e1cadad4fef1518afbf Mon Sep 17 00:00:00 2001 From: Matthew Rich Date: Wed, 25 Sep 2024 04:41:26 +0000 Subject: [PATCH] add cli subcommands --- internal/client/client.go | 47 +++++++++++++++++++++++++++++--- internal/client/client_test.go | 50 ++++++++++++++++++++++++++++------ 2 files changed, 85 insertions(+), 12 deletions(-) diff --git a/internal/client/client.go b/internal/client/client.go index 174cf09..5f18cc0 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -9,6 +9,7 @@ _ "decl/internal/fan" _ "decl/internal/config" _ "decl/internal/resource" "decl/internal/fs" + "decl/internal/builtin" _ "errors" "fmt" "context" @@ -34,6 +35,16 @@ func NewClient() *App { return a } +// Load compiled-in config documents. +func (a *App) BuiltInConfiguration() (err error) { + var defaultConfigurations []data.Document + if defaultConfigurations, err = builtin.BuiltInDocuments(); len(defaultConfigurations) > 0 { + slog.Info("Client.BuiltInConfiguration()", "documents", defaultConfigurations, "error", err) + a.Config.AppendConfigurations(defaultConfigurations) + } + return +} + // Load config documents from default system config path. Ignore if missing. func (a *App) SystemConfiguration(configPath string) (err error) { var extractor data.Converter @@ -48,6 +59,7 @@ func (a *App) SystemConfiguration(configPath string) (err error) { u := folio.URI(fmt.Sprintf("file://%s", path)) if ! file.IsDir() { + slog.Info("Client.SystemConfiguration()", "uri", u) if extractor, loadErr = folio.DocumentRegistry.ConverterTypes.New(string(u)); loadErr == nil { if sourceResource, loadErr = u.NewResource(nil); loadErr == nil { if loaded, loadErr = extractor.(data.ManyExtractor).ExtractMany(sourceResource, nil); loadErr == nil { @@ -153,11 +165,14 @@ func (a *App) Apply(ctx context.Context, deleteResources bool) (err error) { } d.ResolveIds(ctx) + _ = d.Apply("stat") + if ! d.CheckConstraints() { - slog.Info("Client.Apply() document constrains failed", "requires", d) + slog.Info("Client.Apply() document constraints failed", "requires", d) continue } + slog.Info("Client.Apply()", "document", d, "state", overrideState, "error", err) if e := d.(*folio.Document).Apply(overrideState); e != nil { slog.Info("Client.Apply() error", "error", e) return e @@ -256,9 +271,12 @@ func (a *App) DiffCmd(docs []string) (err error) { output := os.Stdout var leftDocuments, rightDocuments []data.Document + var rightSource folio.URI //leftSource := folio.URI(docs[0]) - rightSource := folio.URI(docs[1]) + if len(docs) > 1 { + rightSource = folio.URI(docs[1]) + } if leftDocuments, err = a.ImportSource(docs[0]); err == nil { if rightSource.IsEmpty() { @@ -266,13 +284,34 @@ func (a *App) DiffCmd(docs []string) (err error) { _, err = doc.DiffState(output) } } else { - rightDocuments, err = a.ImportSource(docs[1]) - err = a.Diff(leftDocuments, rightDocuments) + if rightDocuments, err = a.ImportSource(docs[1]); err == nil { + err = a.Diff(leftDocuments, rightDocuments) + } } } return err } +func (a *App) ConfigCmd(docs []string, includeSystemConfig bool) (err error) { + if err = a.BuiltInConfiguration(); err != nil { + slog.Warn("BuiltInConfiguration()", "error", err) + } + + if err = a.Import(docs); err != nil { + return + } + + if err = a.LoadDocumentImports(); err != nil { + return + } + + if includeSystemConfig { + _, err = a.emitter.Emit(a.Config, nil) + } + _, err = a.emitter.(data.ManyEmitter).EmitMany(a.Documents, nil) + return +} + func (a *App) Quiet() (err error) { output := os.Stdout for _, d := range a.Documents { diff --git a/internal/client/client_test.go b/internal/client/client_test.go index 884da13..88cf9f7 100644 --- a/internal/client/client_test.go +++ b/internal/client/client_test.go @@ -28,8 +28,7 @@ var ProcessTestGroupName string func TestMain(m *testing.M) { LoggerConfig() - var err error - err = TempDir.Create() + err := TempDir.Create() if err != nil || TempDir == "" { log.Fatal(err) } @@ -161,12 +160,12 @@ func TestClientEmit(t *testing.T) { func BenchmarkClientSystemConfigurations(b *testing.B) { assert.Nil(b, TempDir.Mkdir("benchconfig", 0700)) ConfDir := tempdir.Path(TempDir.FilePath("benchconfig")) - ConfDir.CreateFile("cfg.jx.yaml", ` + assert.Nil(b, ConfDir.CreateFile("cfg.jx.yaml", ` configurations: - name: files values: prefix: /usr -`) +`)) configDirURI := fmt.Sprintf("file://%s", ConfDir) @@ -174,7 +173,7 @@ configurations: b.Run("systemconfiguration", func(b *testing.B) { for i := 0; i < b.N; i++ { c := NewClient() - c.SystemConfiguration(configDirURI) + _ = c.SystemConfiguration(configDirURI) } }) programLevel.Set(slog.LevelDebug) @@ -187,12 +186,12 @@ func TestClientSystemConfiguration(t *testing.T) { assert.Nil(t, TempDir.Mkdir("config", 0700)) ConfDir := tempdir.Path(TempDir.FilePath("config")) - ConfDir.CreateFile("cfg.jx.yaml", ` + assert.Nil(t, ConfDir.CreateFile("cfg.jx.yaml", ` configurations: - name: files values: prefix: /usr -`) +`)) //configDirURI := fmt.Sprintf("file://%s", ConfDir) configErr := c.SystemConfiguration(string(ConfDir)) @@ -207,5 +206,40 @@ configurations: value, valueErr := cfg.GetValue("prefix") assert.Nil(t, valueErr) assert.Equal(t, "/usr", value.(string)) - return +} + +func TestClientApply(t *testing.T) { + ctx := context.Background() + c := NewClient() + assert.NotNil(t, c) + + assert.Nil(t, TempDir.Mkdir("apply", 0700)) + ApplyDir := tempdir.Path(TempDir.FilePath("apply")) + + DocSource := ApplyDir.FilePath("res.jx.yaml") + TestFile := ApplyDir.FilePath("testfile.txt") + assert.Nil(t, ApplyDir.CreateFile("res.jx.yaml", fmt.Sprintf(` +resources: +- type: file + transition: create + attributes: + path: %s + content: | + a test string + owner: %s + group: %s + mode: 0644 +`, TestFile, ProcessTestUserName, ProcessTestGroupName))) + + + assert.Nil(t, c.Import([]string{DocSource})) + assert.Nil(t, c.LoadDocumentImports()) + + assert.Nil(t, c.Apply(ctx, false)) + + assert.FileExists(t, TestFile) + + assert.Nil(t, c.Apply(ctx, true)) + + assert.NoFileExists(t, TestFile) }