Skip to content

Commit 0ff98dc

Browse files
committed
change apply to continue on error
1 parent 12fe2d5 commit 0ff98dc

File tree

6 files changed

+281
-57
lines changed

6 files changed

+281
-57
lines changed

pkg/apply/applier_test.go

Lines changed: 19 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -708,43 +708,35 @@ type fakeInfoHelper struct {
708708
// TODO(mortent): This has too much code in common with the
709709
// infoHelper implementation. We need to find a better way to structure
710710
// this.
711-
func (f *fakeInfoHelper) UpdateInfos(infos []*resource.Info) error {
711+
func (f *fakeInfoHelper) UpdateInfo(info *resource.Info) error {
712712
mapper, err := f.factory.ToRESTMapper()
713713
if err != nil {
714714
return err
715715
}
716-
for _, info := range infos {
717-
gvk := info.Object.GetObjectKind().GroupVersionKind()
718-
mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version)
719-
if err != nil {
720-
return err
721-
}
722-
info.Mapping = mapping
716+
gvk := info.Object.GetObjectKind().GroupVersionKind()
717+
mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version)
718+
if err != nil {
719+
return err
720+
}
721+
info.Mapping = mapping
723722

724-
c, err := f.getClient(gvk.GroupVersion())
725-
if err != nil {
726-
return err
727-
}
728-
info.Client = c
723+
c, err := f.getClient(gvk.GroupVersion())
724+
if err != nil {
725+
return err
729726
}
727+
info.Client = c
730728
return nil
731729
}
732730

733-
func (f *fakeInfoHelper) BuildInfos(objs []*unstructured.Unstructured) ([]*resource.Info, error) {
734-
var infos []*resource.Info
735-
for _, obj := range objs {
736-
infos = append(infos, &resource.Info{
737-
Name: obj.GetName(),
738-
Namespace: obj.GetNamespace(),
739-
Source: "unstructured",
740-
Object: obj,
741-
})
742-
}
743-
err := f.UpdateInfos(infos)
744-
if err != nil {
745-
return nil, err
731+
func (f *fakeInfoHelper) BuildInfo(obj *unstructured.Unstructured) (*resource.Info, error) {
732+
info := &resource.Info{
733+
Name: obj.GetName(),
734+
Namespace: obj.GetNamespace(),
735+
Source: "unstructured",
736+
Object: obj,
746737
}
747-
return infos, nil
738+
err := f.UpdateInfo(info)
739+
return info, err
748740
}
749741

750742
func (f *fakeInfoHelper) getClient(gv schema.GroupVersion) (resource.RESTClient, error) {

pkg/apply/error/error.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// Copyright 2019 The Kubernetes Authors.
2+
// SPDX-License-Identifier: Apache-2.0
3+
package error
4+
5+
type UnknwonTypeError struct {
6+
err error
7+
}
8+
9+
func (e *UnknwonTypeError) Error() string {
10+
return e.err.Error()
11+
}
12+
13+
func NewUnknwonTypeError(err error) *UnknwonTypeError {
14+
return &UnknwonTypeError{err: err}
15+
}
16+
17+
type ApplyRunError struct {
18+
err error
19+
}
20+
21+
func (e *ApplyRunError) Error() string {
22+
return e.err.Error()
23+
}
24+
25+
func NewApplyRunError(err error) *ApplyRunError {
26+
return &ApplyRunError{err: err}
27+
}
28+
29+
type InitializeApplyOptionError struct {
30+
err error
31+
}
32+
33+
func (e *InitializeApplyOptionError) Error() string {
34+
return e.err.Error()
35+
}
36+
37+
func NewInitializeApplyOptionError(err error) *InitializeApplyOptionError {
38+
return &InitializeApplyOptionError{err: err}
39+
}

pkg/apply/info/info_helper.go

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ import (
1515

1616
// InfoHelper provides functions for interacting with Info objects.
1717
type InfoHelper interface {
18-
// UpdateInfos sets the mapping and client for the provided Info
18+
// UpdateInfo sets the mapping and client for the provided Info
1919
// objects. This must be called at a time when all needed resource
2020
// types are available in the RESTMapper.
21-
UpdateInfos(infos []*resource.Info) error
21+
UpdateInfo(infos *resource.Info) error
2222

23-
BuildInfos(objs []*unstructured.Unstructured) ([]*resource.Info, error)
23+
BuildInfo(obj *unstructured.Unstructured) (*resource.Info, error)
2424
}
2525

2626
func NewInfoHelper(factory util.Factory) *infoHelper {
@@ -55,6 +55,26 @@ func (ih *infoHelper) UpdateInfos(infos []*resource.Info) error {
5555
return nil
5656
}
5757

58+
func (ih *infoHelper) UpdateInfo(info *resource.Info) error {
59+
mapper, err := ih.factory.ToRESTMapper()
60+
if err != nil {
61+
return err
62+
}
63+
gvk := info.Object.GetObjectKind().GroupVersionKind()
64+
mapping, err := mapper.RESTMapping(gvk.GroupKind(), gvk.Version)
65+
if err != nil {
66+
return err
67+
}
68+
info.Mapping = mapping
69+
70+
c, err := ih.getClient(gvk.GroupVersion())
71+
if err != nil {
72+
return err
73+
}
74+
info.Client = c
75+
return nil
76+
}
77+
5878
func (ih *infoHelper) BuildInfos(objs []*unstructured.Unstructured) ([]*resource.Info, error) {
5979
infos, err := object.UnstructuredsToInfos(objs)
6080
if err != nil {
@@ -67,6 +87,15 @@ func (ih *infoHelper) BuildInfos(objs []*unstructured.Unstructured) ([]*resource
6787
return infos, nil
6888
}
6989

90+
func (ih *infoHelper) BuildInfo(obj *unstructured.Unstructured) (*resource.Info, error) {
91+
info, err := object.UnstructuredToInfo(obj)
92+
if err != nil {
93+
return nil, err
94+
}
95+
err = ih.UpdateInfo(info)
96+
return info, err
97+
}
98+
7099
func (ih *infoHelper) ToRESTMapper() (meta.RESTMapper, error) {
71100
return ih.factory.ToRESTMapper()
72101
}

pkg/apply/task/apply_task.go

Lines changed: 41 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"k8s.io/kubectl/pkg/cmd/delete"
1616
"k8s.io/kubectl/pkg/cmd/util"
1717
"k8s.io/kubectl/pkg/util/slice"
18+
applyerror "sigs.k8s.io/cli-utils/pkg/apply/error"
1819
"sigs.k8s.io/cli-utils/pkg/apply/event"
1920
"sigs.k8s.io/cli-utils/pkg/apply/info"
2021
"sigs.k8s.io/cli-utils/pkg/apply/taskrunner"
@@ -72,7 +73,8 @@ func (a *ApplyTask) Start(taskContext *taskrunner.TaskContext) {
7273
// the resource set.
7374
objs, objsWithCRD, err := a.filterCRsWithCRDInSet(objects)
7475
if err != nil {
75-
a.sendTaskResult(taskContext, err)
76+
taskContext.EventChannel() <- createApplyFailedEvent(object.ObjMetadata{}, err)
77+
a.sendTaskResult(taskContext)
7678
return
7779
}
7880

@@ -97,15 +99,7 @@ func (a *ApplyTask) Start(taskContext *taskrunner.TaskContext) {
9799
// for that here. It could happen if this is dry-run and we removed
98100
// all resources in the previous step.
99101
if len(objects) == 0 {
100-
a.sendTaskResult(taskContext, nil)
101-
return
102-
}
103-
104-
// Set the client and mapping fields on the provided
105-
// infos so they can be applied to the cluster.
106-
infos, err := a.InfoHelper.BuildInfos(objects)
107-
if err != nil {
108-
a.sendTaskResult(taskContext, err)
102+
a.sendTaskResult(taskContext)
109103
return
110104
}
111105

@@ -114,15 +108,31 @@ func (a *ApplyTask) Start(taskContext *taskrunner.TaskContext) {
114108
ao, err := applyOptionsFactoryFunc(taskContext.EventChannel(),
115109
a.ServerSideOptions, a.DryRunStrategy, a.Factory)
116110
if err != nil {
117-
a.sendTaskResult(taskContext, err)
111+
taskContext.EventChannel() <- createApplyFailedEvent(object.ObjMetadata{},
112+
applyerror.NewInitializeApplyOptionError(err))
113+
a.sendTaskResult(taskContext)
118114
return
119115
}
120-
ao.SetObjects(infos)
121-
err = ao.Run()
122-
if err != nil {
123-
a.sendTaskResult(taskContext, err)
124-
return
116+
117+
var infos []*resource.Info
118+
for _, obj := range objects {
119+
// Set the client and mapping fields on the provided
120+
// info so they can be applied to the cluster.
121+
info, err := a.InfoHelper.BuildInfo(obj)
122+
if err != nil {
123+
taskContext.EventChannel() <- createApplyFailedEvent(object.UnstructuredToObjMeta(obj),
124+
applyerror.NewUnknwonTypeError(err))
125+
continue
126+
}
127+
infos = append(infos, info)
128+
ao.SetObjects([]*resource.Info{info})
129+
err = ao.Run()
130+
if err != nil {
131+
taskContext.EventChannel() <- createApplyFailedEvent(object.UnstructuredToObjMeta(obj),
132+
applyerror.NewApplyRunError(err))
133+
}
125134
}
135+
126136
// Fetch the Generation from all Infos after they have been
127137
// applied.
128138
for _, inf := range infos {
@@ -140,7 +150,7 @@ func (a *ApplyTask) Start(taskContext *taskrunner.TaskContext) {
140150
taskContext.ResourceApplied(id, uid, gen)
141151
}
142152
}
143-
a.sendTaskResult(taskContext, nil)
153+
a.sendTaskResult(taskContext)
144154
}()
145155
}
146156

@@ -187,9 +197,9 @@ func newApplyOptions(eventChannel chan event.Event, serverSideOptions common.Ser
187197
}, nil
188198
}
189199

190-
func (a *ApplyTask) sendTaskResult(taskContext *taskrunner.TaskContext, err error) {
200+
func (a *ApplyTask) sendTaskResult(taskContext *taskrunner.TaskContext) {
191201
taskContext.TaskChannel() <- taskrunner.TaskResult{
192-
Err: err,
202+
Err: nil,
193203
}
194204
}
195205

@@ -277,3 +287,15 @@ func buildCRDsInfo(crds []*unstructured.Unstructured) *crdsInfo {
277287

278288
// ClearTimeout is not supported by the ApplyTask.
279289
func (a *ApplyTask) ClearTimeout() {}
290+
291+
// createApplyFailedEvent is a helper function to package an apply failure event.
292+
func createApplyFailedEvent(id object.ObjMetadata, err error) event.Event {
293+
return event.Event{
294+
Type: event.ApplyType,
295+
ApplyEvent: event.ApplyEvent{
296+
Type: event.ApplyEventFailed,
297+
Identifier: id,
298+
Error: err,
299+
},
300+
}
301+
}

0 commit comments

Comments
 (0)