Skip to content

Commit ccf7d7f

Browse files
feat: Print skip reasons in live plan output
This change captures the skip reason generated by cli-utils and prints it in the output of the kpt live plan command, improving the developer experience. Assisted-by: Antigravity:Gemini 3.1 Pro (High) Signed-off-by: Vishnu Kothakapu <vishnukothakapu27@gmail.com>
1 parent 6dfff20 commit ccf7d7f

3 files changed

Lines changed: 93 additions & 44 deletions

File tree

commands/alpha/live/plan/command.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,10 @@ func printText(plan *kptplanner.Plan, objs []*unstructured.Unstructured, ioStrea
178178
printEntry(" ", action, ioStreams)
179179
findAndPrintDiff(action.Original, action.Updated, ContentPrefix, ioStreams)
180180
case kptplanner.Skip:
181-
// TODO: provide more information about why the resource was skipped.
182181
printEntryWithColor("=", print.YELLOW, action, ioStreams)
182+
if action.SkipReason != "" {
183+
printWithPrefix(action.SkipReason, ContentPrefix, ioStreams)
184+
}
183185
case kptplanner.Error:
184186
printEntry("!", action, ioStreams)
185187
printWithPrefix(action.Error, ContentPrefix, ioStreams)

pkg/live/planner/cluster.go

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -110,14 +110,15 @@ type Plan struct {
110110
}
111111

112112
type Action struct {
113-
Type ActionType
114-
Group string
115-
Kind string
116-
Name string
117-
Namespace string
118-
Original *unstructured.Unstructured
119-
Updated *unstructured.Unstructured
120-
Error string
113+
Type ActionType
114+
Group string
115+
Kind string
116+
Name string
117+
Namespace string
118+
Original *unstructured.Unstructured
119+
Updated *unstructured.Unstructured
120+
Error string
121+
SkipReason string
121122
}
122123

123124
type Options struct {
@@ -195,63 +196,65 @@ func (r *ClusterPlanner) dryRunForPlan(
195196
}
196197

197198
func handleApplyEvent(e event.Event, a Action) Action {
199+
if e.ApplyEvent.Status == event.ApplySkipped {
200+
a.Type = Skip
201+
if e.ApplyEvent.Error != nil {
202+
a.SkipReason = e.ApplyEvent.Error.Error()
203+
}
204+
return a
205+
}
198206
if e.ApplyEvent.Error != nil {
199207
a.Type = Error
200208
a.Error = e.ApplyEvent.Error.Error()
201-
} else {
202-
switch e.ApplyEvent.Status {
203-
case event.ApplySkipped:
204-
a.Type = Skip
205-
case event.ApplySuccessful:
206-
a.Updated = e.ApplyEvent.Resource
207-
if a.Original != nil {
208-
// TODO: Unclear if we should diff the full resources here. It doesn't work
209-
// well with client-side apply as the managedFields property shows up as
210-
// changes. It also means there is a race with controllers that might change
211-
// the status of resources.
212-
if reflect.DeepEqual(a.Original, a.Updated) {
213-
a.Type = Unchanged
214-
} else {
215-
a.Type = Update
216-
}
209+
} else if e.ApplyEvent.Status == event.ApplySuccessful {
210+
a.Updated = e.ApplyEvent.Resource
211+
if a.Original != nil {
212+
// TODO: Unclear if we should diff the full resources here. It doesn't work
213+
// well with client-side apply as the managedFields property shows up as
214+
// changes. It also means there is a race with controllers that might change
215+
// the status of resources.
216+
if reflect.DeepEqual(a.Original, a.Updated) {
217+
a.Type = Unchanged
217218
} else {
218-
a.Type = Create
219+
a.Type = Update
219220
}
221+
} else {
222+
a.Type = Create
220223
}
221224
}
222225
return a
223226
}
224227

225228
func handlePruneEvent(e event.Event, a Action) Action {
229+
if e.PruneEvent.Status == event.PruneSkipped {
230+
a.Type = Skip
231+
if e.PruneEvent.Error != nil {
232+
a.SkipReason = e.PruneEvent.Error.Error()
233+
}
234+
return a
235+
}
226236
if e.PruneEvent.Error != nil {
227237
a.Type = Error
228238
a.Error = e.PruneEvent.Error.Error()
229-
} else {
230-
switch e.PruneEvent.Status {
231-
case event.PruneSuccessful:
232-
a.Type = Delete
233-
// Lifecycle directives can cause resources to remain in the
234-
// live state even if they would normally be pruned.
235-
// TODO: Handle reason for skipped resources that has recently
236-
// been added to the actuation library.
237-
case event.PruneSkipped:
238-
a.Type = Skip
239-
}
239+
} else if e.PruneEvent.Status == event.PruneSuccessful {
240+
a.Type = Delete
240241
}
241242
return a
242243
}
243244

244245
func handleDeleteEvent(e event.Event, a Action) Action {
246+
if e.DeleteEvent.Status == event.DeleteSkipped {
247+
a.Type = Skip
248+
if e.DeleteEvent.Error != nil {
249+
a.SkipReason = e.DeleteEvent.Error.Error()
250+
}
251+
return a
252+
}
245253
if e.DeleteEvent.Error != nil {
246254
a.Type = Error
247255
a.Error = e.DeleteEvent.Error.Error()
248-
} else {
249-
switch e.DeleteEvent.Status {
250-
case event.DeleteSuccessful:
251-
a.Type = Delete
252-
case event.DeleteSkipped:
253-
a.Type = Skip
254-
}
256+
} else if e.DeleteEvent.Status == event.DeleteSuccessful {
257+
a.Type = Delete
255258
}
256259
return a
257260
}

pkg/live/planner/cluster_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package planner
1616

1717
import (
1818
"context"
19+
"fmt"
1920
"testing"
2021

2122
"github.com/google/go-cmp/cmp"
@@ -93,6 +94,49 @@ func TestClusterPlanner(t *testing.T) {
9394
},
9495
},
9596
},
97+
"skipped resource with reason": {
98+
resources: []*unstructured.Unstructured{
99+
testutil.Unstructured(t, deploymentYAML),
100+
},
101+
clusterResources: []*unstructured.Unstructured{},
102+
events: []event.Event{
103+
{
104+
Type: event.InitType,
105+
InitEvent: event.InitEvent{
106+
ActionGroups: event.ActionGroupList{
107+
{
108+
Action: event.ApplyAction,
109+
Name: "apply-1",
110+
Identifiers: []object.ObjMetadata{
111+
testutil.ToIdentifier(t, deploymentYAML),
112+
},
113+
},
114+
},
115+
},
116+
},
117+
{
118+
Type: event.ApplyType,
119+
ApplyEvent: event.ApplyEvent{
120+
GroupName: "apply-1",
121+
Identifier: testutil.ToIdentifier(t, deploymentYAML),
122+
Status: event.ApplySkipped,
123+
Error: fmt.Errorf("some skip reason"),
124+
},
125+
},
126+
},
127+
expectedPlan: &Plan{
128+
Actions: []Action{
129+
{
130+
Type: Skip,
131+
Name: "foo",
132+
Namespace: "default",
133+
Group: "apps",
134+
Kind: "Deployment",
135+
SkipReason: "some skip reason",
136+
},
137+
},
138+
},
139+
},
96140
}
97141

98142
for tn := range testCases {

0 commit comments

Comments
 (0)