From 6de170f6cfb2f26bdd6ff9401b053aab3ece1c4e Mon Sep 17 00:00:00 2001 From: Richard Robert Reitz Date: Mon, 6 Oct 2025 16:45:53 +0200 Subject: [PATCH] feat(cli): Added output of diff when updating outboundConnections in the desired manifest --- internal/apply/planner.go | 35 +++++++++++++++++++++-------------- internal/apply/types.go | 33 ++++++++++++++++++++++----------- 2 files changed, 43 insertions(+), 25 deletions(-) diff --git a/internal/apply/planner.go b/internal/apply/planner.go index 93caf18..f247e16 100644 --- a/internal/apply/planner.go +++ b/internal/apply/planner.go @@ -384,17 +384,20 @@ func (p *EdgeConnectPlanner) compareAppStates(current, desired *AppState) ([]str } // Compare outbound connections - if !p.compareOutboundConnections(current.OutboundConnections, desired.OutboundConnections) { - changes = append(changes, "Outbound connections changed") + outboundChanges := p.compareOutboundConnections(current.OutboundConnections, desired.OutboundConnections) + if len(outboundChanges) > 0 { + changes = append(changes, "Outbound connections changed:") + changes = append(changes, outboundChanges...) } return changes, manifestChanged } // compareOutboundConnections compares two sets of outbound connections for equality -func (p *EdgeConnectPlanner) compareOutboundConnections(current, desired []SecurityRule) bool { - makeMap := func(rules []SecurityRule) map[string]struct{} { - m := make(map[string]struct{}, len(rules)) +func (p *EdgeConnectPlanner) compareOutboundConnections(current, desired []SecurityRule) []string { + var changes []string + makeMap := func(rules []SecurityRule) map[string]SecurityRule { + m := make(map[string]SecurityRule, len(rules)) for _, r := range rules { key := fmt.Sprintf("%s:%d-%d:%s", strings.ToLower(r.Protocol), @@ -402,7 +405,7 @@ func (p *EdgeConnectPlanner) compareOutboundConnections(current, desired []Secur r.PortRangeMax, r.RemoteCIDR, ) - m[key] = struct{}{} + m[key] = r } return m } @@ -410,17 +413,21 @@ func (p *EdgeConnectPlanner) compareOutboundConnections(current, desired []Secur currentMap := makeMap(current) desiredMap := makeMap(desired) - if len(currentMap) != len(desiredMap) { - return false - } - - for k := range currentMap { - if _, exists := desiredMap[k]; !exists { - return false + // Find added and modified rules + for key, rule := range desiredMap { + if _, exists := currentMap[key]; !exists { + changes = append(changes, fmt.Sprintf(" - Added outbound connection: %s %d-%d to %s", rule.Protocol, rule.PortRangeMin, rule.PortRangeMax, rule.RemoteCIDR)) } } - return true + // Find removed rules + for key, rule := range currentMap { + if _, exists := desiredMap[key]; !exists { + changes = append(changes, fmt.Sprintf(" - Removed outbound connection: %s %d-%d to %s", rule.Protocol, rule.PortRangeMin, rule.PortRangeMax, rule.RemoteCIDR)) + } + } + + return changes } // compareInstanceStates compares current and desired instance states and returns changes diff --git a/internal/apply/types.go b/internal/apply/types.go index cd2a93a..6f7ef4e 100644 --- a/internal/apply/types.go +++ b/internal/apply/types.go @@ -4,6 +4,7 @@ package apply import ( "fmt" + "strings" "time" "edp.buildth.ing/DevFW-CICD/edge-connect-client/internal/config" @@ -353,40 +354,50 @@ func (dp *DeploymentPlan) GenerateSummary() string { return "No changes required - configuration matches current state" } - summary := fmt.Sprintf("Deployment plan for '%s':\n", dp.ConfigName) + var sb strings.Builder + sb.WriteString(fmt.Sprintf("Deployment plan for '%s':\n", dp.ConfigName)) // App actions if dp.AppAction.Type != ActionNone { - summary += fmt.Sprintf("- %s application '%s'\n", dp.AppAction.Type, dp.AppAction.Desired.Name) + sb.WriteString(fmt.Sprintf("- %s application '%s'\n", dp.AppAction.Type, dp.AppAction.Desired.Name)) if len(dp.AppAction.Changes) > 0 { for _, change := range dp.AppAction.Changes { - summary += fmt.Sprintf(" - %s\n", change) + sb.WriteString(fmt.Sprintf(" - %s\n", change)) } } } // Instance actions createCount := 0 - updateCount := 0 + updateActions := []InstanceAction{} for _, action := range dp.InstanceActions { switch action.Type { case ActionCreate: createCount++ case ActionUpdate: - updateCount++ + updateActions = append(updateActions, action) } } if createCount > 0 { - summary += fmt.Sprintf("- CREATE %d instance(s) across %d cloudlet(s)\n", createCount, len(dp.GetTargetCloudlets())) - } - if updateCount > 0 { - summary += fmt.Sprintf("- UPDATE %d instance(s)\n", updateCount) + sb.WriteString(fmt.Sprintf("- CREATE %d instance(s) across %d cloudlet(s)\n", createCount, len(dp.GetTargetCloudlets()))) } - summary += fmt.Sprintf("Estimated duration: %s", dp.EstimatedDuration.String()) + if len(updateActions) > 0 { + sb.WriteString(fmt.Sprintf("- UPDATE %d instance(s)\n", len(updateActions))) + for _, action := range updateActions { + if len(action.Changes) > 0 { + sb.WriteString(fmt.Sprintf(" - Instance '%s':\n", action.InstanceName)) + for _, change := range action.Changes { + sb.WriteString(fmt.Sprintf(" - %s\n", change)) + } + } + } + } - return summary + sb.WriteString(fmt.Sprintf("Estimated duration: %s", dp.EstimatedDuration.String())) + + return sb.String() } // Validate checks if the deployment plan is valid and safe to execute