From ae87ddf3a6bf921b64869fa7ddb297d5dd5934b7 Mon Sep 17 00:00:00 2001 From: Piotr Janus Date: Fri, 27 Jun 2025 14:59:14 +0200 Subject: [PATCH 1/9] add merged source for diff --- internal/cac/api/source.go | 3 +++ internal/cac/app.go | 28 ++++++++++++++++++++++++++++ internal/cac/diff/diff.go | 34 ++++++++++++++++++++-------------- 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/internal/cac/api/source.go b/internal/cac/api/source.go index f291e56..457c259 100644 --- a/internal/cac/api/source.go +++ b/internal/cac/api/source.go @@ -13,6 +13,7 @@ var ErrUnknownSource = errors.New("unknown source") const ( SourceLocal SourceType = "local" SourceRemote SourceType = "remote" + SourceMerged SourceType = "merged" ) func SourceFromString(s string) (SourceType, error) { @@ -21,6 +22,8 @@ func SourceFromString(s string) (SourceType, error) { return SourceLocal, nil case "remote": return SourceRemote, nil + case "merged": + return SourceMerged, nil } return "", ErrUnknownSource diff --git a/internal/cac/app.go b/internal/cac/app.go index 8c874ed..f6b9f02 100644 --- a/internal/cac/app.go +++ b/internal/cac/app.go @@ -117,6 +117,34 @@ func (a *Application) PickSource(source string, tenant bool) (api.Source, error) } return c, nil + case api.SourceMerged: + var ( + c *client.Client + err error + ) + + ms, err := storage.InitMultiStorage(conf.Storage, constructor) + + if err != nil { + return nil, err + } + + storages := ms.Storages + + if c, err = client.InitClient(conf.Client); err != nil { + return nil, err + } + + if !tenant { + storages = append(storages, c) + } else { + storages = append(storages, c.Tenant()) + } + + return &storage.MultiStorage{ + Storages: storages, + Config: ms.Config, + }, nil } return nil, api.ErrUnknownSource diff --git a/internal/cac/diff/diff.go b/internal/cac/diff/diff.go index 4af34f8..475c2da 100644 --- a/internal/cac/diff/diff.go +++ b/internal/cac/diff/diff.go @@ -2,12 +2,14 @@ package diff import ( "context" + "regexp" + "github.com/cloudentity/acp-client-go/clients/hub/models" "github.com/cloudentity/cac/internal/cac/api" "github.com/cloudentity/cac/internal/cac/utils" "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" "golang.org/x/exp/slog" - "regexp" ) type Options struct { @@ -87,7 +89,7 @@ var fieldsFilter = func(fields []string) cmp.Option { var filerVolatileFields = fieldsFilter(volatileFields) var filterSecretFields = fieldsFilter(secretFields) -func Diff(ctx context.Context, source api.Source, target api.Source, workspace string, opts ...Option) (string, error) { +func Diff(ctx context.Context, left api.Source, right api.Source, workspace string, opts ...Option) (string, error) { var ( server1 models.Rfc7396PatchOperation server2 models.Rfc7396PatchOperation @@ -112,18 +114,18 @@ func Diff(ctx context.Context, source api.Source, target api.Source, workspace s readOpts = append(readOpts, api.WithSecrets(true)) } - if server1, err = source.Read(ctx, readOpts...); err != nil { + if server1, err = left.Read(ctx, readOpts...); err != nil { return "", err } - if server2, err = target.Read(ctx, readOpts...); err != nil { + if server2, err = right.Read(ctx, readOpts...); err != nil { return "", err } return Tree(server1, server2, opts...) } -func Tree(source models.Rfc7396PatchOperation, target models.Rfc7396PatchOperation, opts ...Option) (string, error) { +func Tree(left models.Rfc7396PatchOperation, right models.Rfc7396PatchOperation, opts ...Option) (string, error) { var ( options = &Options{} diffOpts = cmp.Options{} @@ -134,22 +136,22 @@ func Tree(source models.Rfc7396PatchOperation, target models.Rfc7396PatchOperati opt(options) } - utils.CleanPatch(source) - utils.CleanPatch(target) + utils.CleanPatch(left) + utils.CleanPatch(right) // marshaling structs to json and back to get proper field names in the comparison - if source, err = utils.NormalizePatch(source); err != nil { + if left, err = utils.NormalizePatch(left); err != nil { return "", err } - if target, err = utils.NormalizePatch(target); err != nil { + if right, err = utils.NormalizePatch(right); err != nil { return "", err } if options.PresentAtSource { - for k := range target { - if tm, ok := target[k].(map[string]any); ok { - OnlyPresentKeys(source[k], tm) + for k := range right { + if tm, ok := right[k].(map[string]any); ok { + OnlyPresentKeys(left[k], tm) } } } @@ -162,10 +164,14 @@ func Tree(source models.Rfc7396PatchOperation, target models.Rfc7396PatchOperati diffOpts = append(diffOpts, filterSecretFields) } - var out = cmp.Diff(target, source, diffOpts) + diffOpts = append(diffOpts, cmpopts.SortSlices(func(a, b string) bool { + return a < b + })) + + out := cmp.Diff(right, left, diffOpts) if options.Color { - return colorize(out), nil + out = colorize(out) } return out, nil From ef34e51b78529b9f5c0355e516783d976af5c10a Mon Sep 17 00:00:00 2001 From: Piotr Janus Date: Thu, 3 Jul 2025 15:38:59 +0200 Subject: [PATCH 2/9] try float as string --- internal/cac/diff/diff.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/internal/cac/diff/diff.go b/internal/cac/diff/diff.go index 475c2da..d62aa8a 100644 --- a/internal/cac/diff/diff.go +++ b/internal/cac/diff/diff.go @@ -3,6 +3,7 @@ package diff import ( "context" "regexp" + "strconv" "github.com/cloudentity/acp-client-go/clients/hub/models" "github.com/cloudentity/cac/internal/cac/api" @@ -166,6 +167,8 @@ func Tree(left models.Rfc7396PatchOperation, right models.Rfc7396PatchOperation, diffOpts = append(diffOpts, cmpopts.SortSlices(func(a, b string) bool { return a < b + }), cmpopts.EquateEmpty(), cmpopts.AcyclicTransformer("FloatAsString", func(i float64) string { + return strconv.FormatFloat(i, 'f', -1, 64) })) out := cmp.Diff(right, left, diffOpts) From d85523af7e3e0608c9c1d90fc738582caede353f Mon Sep 17 00:00:00 2001 From: Piotr Janus Date: Thu, 3 Jul 2025 15:50:25 +0200 Subject: [PATCH 3/9] revert: try float as string --- internal/cac/diff/diff.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/internal/cac/diff/diff.go b/internal/cac/diff/diff.go index d62aa8a..475c2da 100644 --- a/internal/cac/diff/diff.go +++ b/internal/cac/diff/diff.go @@ -3,7 +3,6 @@ package diff import ( "context" "regexp" - "strconv" "github.com/cloudentity/acp-client-go/clients/hub/models" "github.com/cloudentity/cac/internal/cac/api" @@ -167,8 +166,6 @@ func Tree(left models.Rfc7396PatchOperation, right models.Rfc7396PatchOperation, diffOpts = append(diffOpts, cmpopts.SortSlices(func(a, b string) bool { return a < b - }), cmpopts.EquateEmpty(), cmpopts.AcyclicTransformer("FloatAsString", func(i float64) string { - return strconv.FormatFloat(i, 'f', -1, 64) })) out := cmp.Diff(right, left, diffOpts) From 68df5fe2f9e61fbeed915a9d13ed32db619f76e6 Mon Sep 17 00:00:00 2001 From: Piotr Janus Date: Thu, 18 Sep 2025 22:26:11 +0200 Subject: [PATCH 4/9] update readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index c788594..0f0b817 100644 --- a/README.md +++ b/README.md @@ -221,6 +221,8 @@ Global Flags: --profile string Configuration profile ``` +> **Note:** Use `--source merged` flag to show only the changes between your local configuration and the remote branch, instead of displaying the complete configuration difference. + Sample execution ``` From 261465a28299c14484e2379321e3167a3e65857b Mon Sep 17 00:00:00 2001 From: Piotr Janus Date: Thu, 18 Sep 2025 22:33:50 +0200 Subject: [PATCH 5/9] update readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0f0b817..6fde689 100644 --- a/README.md +++ b/README.md @@ -221,7 +221,7 @@ Global Flags: --profile string Configuration profile ``` -> **Note:** Use `--source merged` flag to show only the changes between your local configuration and the remote branch, instead of displaying the complete configuration difference. +> **Note:** Use `--source merged` flag to show only the changes that will be applied to the remote branch, instead of displaying the complete configuration difference. It ignores all skipped entities and fields. Sample execution From f7063e1309677a6c7471b22a364d9b7c97caee1a Mon Sep 17 00:00:00 2001 From: Piotr Janus Date: Thu, 18 Sep 2025 22:37:24 +0200 Subject: [PATCH 6/9] revert some unnecesary changes --- internal/cac/diff/diff.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/internal/cac/diff/diff.go b/internal/cac/diff/diff.go index 475c2da..766e8ce 100644 --- a/internal/cac/diff/diff.go +++ b/internal/cac/diff/diff.go @@ -89,7 +89,7 @@ var fieldsFilter = func(fields []string) cmp.Option { var filerVolatileFields = fieldsFilter(volatileFields) var filterSecretFields = fieldsFilter(secretFields) -func Diff(ctx context.Context, left api.Source, right api.Source, workspace string, opts ...Option) (string, error) { +func Diff(ctx context.Context, source api.Source, target api.Source, workspace string, opts ...Option) (string, error) { var ( server1 models.Rfc7396PatchOperation server2 models.Rfc7396PatchOperation @@ -114,18 +114,18 @@ func Diff(ctx context.Context, left api.Source, right api.Source, workspace stri readOpts = append(readOpts, api.WithSecrets(true)) } - if server1, err = left.Read(ctx, readOpts...); err != nil { + if server1, err = source.Read(ctx, readOpts...); err != nil { return "", err } - if server2, err = right.Read(ctx, readOpts...); err != nil { + if server2, err = target.Read(ctx, readOpts...); err != nil { return "", err } return Tree(server1, server2, opts...) } -func Tree(left models.Rfc7396PatchOperation, right models.Rfc7396PatchOperation, opts ...Option) (string, error) { +func Tree(source models.Rfc7396PatchOperation, target models.Rfc7396PatchOperation, opts ...Option) (string, error) { var ( options = &Options{} diffOpts = cmp.Options{} @@ -136,22 +136,22 @@ func Tree(left models.Rfc7396PatchOperation, right models.Rfc7396PatchOperation, opt(options) } - utils.CleanPatch(left) - utils.CleanPatch(right) + utils.CleanPatch(source) + utils.CleanPatch(target) // marshaling structs to json and back to get proper field names in the comparison - if left, err = utils.NormalizePatch(left); err != nil { + if source, err = utils.NormalizePatch(source); err != nil { return "", err } - if right, err = utils.NormalizePatch(right); err != nil { + if target, err = utils.NormalizePatch(target); err != nil { return "", err } if options.PresentAtSource { - for k := range right { - if tm, ok := right[k].(map[string]any); ok { - OnlyPresentKeys(left[k], tm) + for k := range target { + if tm, ok := target[k].(map[string]any); ok { + OnlyPresentKeys(source[k], tm) } } } @@ -168,7 +168,7 @@ func Tree(left models.Rfc7396PatchOperation, right models.Rfc7396PatchOperation, return a < b })) - out := cmp.Diff(right, left, diffOpts) + out := cmp.Diff(target, source, diffOpts) if options.Color { out = colorize(out) From 3e3289b973fc2659979ffb6252371458239b9e1e Mon Sep 17 00:00:00 2001 From: Piotr Janus Date: Thu, 18 Sep 2025 22:39:22 +0200 Subject: [PATCH 7/9] sort slices comment --- internal/cac/diff/diff.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/cac/diff/diff.go b/internal/cac/diff/diff.go index 766e8ce..c90778b 100644 --- a/internal/cac/diff/diff.go +++ b/internal/cac/diff/diff.go @@ -164,6 +164,7 @@ func Tree(source models.Rfc7396PatchOperation, target models.Rfc7396PatchOperati diffOpts = append(diffOpts, filterSecretFields) } + // sorting slices to avoid diffs due to different order diffOpts = append(diffOpts, cmpopts.SortSlices(func(a, b string) bool { return a < b })) From e7fc4b83876790b962ca13dc09646e0e69a1bc14 Mon Sep 17 00:00:00 2001 From: Piotr Janus Date: Thu, 18 Sep 2025 22:57:17 +0200 Subject: [PATCH 8/9] apply defaults from root config to profiles --- internal/cac/config/config.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/cac/config/config.go b/internal/cac/config/config.go index 212194d..e4abd6e 100644 --- a/internal/cac/config/config.go +++ b/internal/cac/config/config.go @@ -114,6 +114,7 @@ func InitConfig(path string) (_ *RootConfiguration, err error) { for name, profile := range config.Profiles { profile.SetImplicitValues(name, config.Default) + config.Profiles[name] = profile } return config, nil From ce6c0cf5e820e6914d3ad83e21a95acb0d902427 Mon Sep 17 00:00:00 2001 From: Piotr Janus Date: Thu, 18 Sep 2025 22:58:53 +0200 Subject: [PATCH 9/9] revert --- internal/cac/config/config.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/cac/config/config.go b/internal/cac/config/config.go index e4abd6e..212194d 100644 --- a/internal/cac/config/config.go +++ b/internal/cac/config/config.go @@ -114,7 +114,6 @@ func InitConfig(path string) (_ *RootConfiguration, err error) { for name, profile := range config.Profiles { profile.SetImplicitValues(name, config.Default) - config.Profiles[name] = profile } return config, nil