Skip to content

Commit dfb18f0

Browse files
committed
add IfNotExistsAction to machinery for optional file handling
1 parent 869ca6b commit dfb18f0

File tree

6 files changed

+49
-10
lines changed

6 files changed

+49
-10
lines changed

pkg/cli/cmd_helpers.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,6 @@ func (factory *executionHooksFactory) preRunEFunc(
293293
}
294294

295295
// Pre-scaffold hook.
296-
//nolint:revive
297296
if err := factory.forEach(func(subcommand plugin.Subcommand) error {
298297
if subcommand, hasPreScaffold := subcommand.(plugin.HasPreScaffold); hasPreScaffold {
299298
return subcommand.PreScaffold(factory.fs)
@@ -311,7 +310,6 @@ func (factory *executionHooksFactory) preRunEFunc(
311310
func (factory *executionHooksFactory) runEFunc() func(*cobra.Command, []string) error {
312311
return func(*cobra.Command, []string) error {
313312
// Scaffold hook.
314-
//nolint:revive
315313
if err := factory.forEach(func(subcommand plugin.Subcommand) error {
316314
return subcommand.Scaffold(factory.fs)
317315
}, "unable to scaffold with"); err != nil {
@@ -331,7 +329,6 @@ func (factory *executionHooksFactory) postRunEFunc() func(*cobra.Command, []stri
331329
}
332330

333331
// Post-scaffold hook.
334-
//nolint:revive
335332
if err := factory.forEach(func(subcommand plugin.Subcommand) error {
336333
if subcommand, hasPostScaffold := subcommand.(plugin.HasPostScaffold); hasPostScaffold {
337334
return subcommand.PostScaffold()

pkg/machinery/file.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,17 @@ const (
3030
OverwriteFile
3131
)
3232

33+
// IfNotExistsAction determines what to do if a file to be updated does not exist
34+
type IfNotExistsAction int
35+
36+
const (
37+
// ErrorIfNotExist returns an error and stops processing (default behavior)
38+
ErrorIfNotExist IfNotExistsAction = iota
39+
40+
// IgnoreFile skips the file and logs a message if it does not exist
41+
IgnoreFile
42+
)
43+
3344
// File describes a file that will be written
3445
type File struct {
3546
// Path is the file to write
@@ -40,4 +51,7 @@ type File struct {
4051

4152
// IfExistsAction determines what to do if the file exists
4253
IfExistsAction IfExistsAction
54+
55+
// IfNotExistsAction determines what to do if the file is missing (optional updates only)
56+
IfNotExistsAction IfNotExistsAction
4357
}

pkg/machinery/interfaces.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ type Inserter interface {
5959
GetCodeFragments() CodeFragmentsMap
6060
}
6161

62+
// HasIfNotExistsAction allows a template to define an action if the file is missing
63+
type HasIfNotExistsAction interface {
64+
GetIfNotExistsAction() IfNotExistsAction
65+
}
66+
6267
// HasDomain allows the domain to be used on a template
6368
type HasDomain interface {
6469
// InjectDomain sets the template domain

pkg/machinery/mixins.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,14 @@ func (m *ResourceMixin) InjectResource(res *resource.Resource) {
153153
m.Resource = res
154154
}
155155
}
156+
157+
// IfNotExistsActionMixin provides file builders with an if-not-exists-action field
158+
type IfNotExistsActionMixin struct {
159+
// IfNotExistsAction determines what to do if the file does not exist
160+
IfNotExistsAction IfNotExistsAction
161+
}
162+
163+
// GetIfNotExistsAction implements Inserter
164+
func (m *IfNotExistsActionMixin) GetIfNotExistsAction() IfNotExistsAction {
165+
return m.IfNotExistsAction
166+
}

pkg/machinery/scaffold.go

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -237,13 +237,21 @@ func doTemplate(t Template) ([]byte, error) {
237237
func (s Scaffold) updateFileModel(i Inserter, models map[string]*File) error {
238238
m, err := s.loadPreviousModel(i, models)
239239
if err != nil {
240-
// TODO(kubebuilder/issues/4960): Create Machinery implementation to allow defining IfNotExistsAction
241-
// If the file path starts with test/, warn and skip
242-
// Workaround to allow projects be backwards compatible with previous versions
243-
if strings.HasPrefix(i.GetPath(), "test/") {
244-
log.Warnf("Skipping missing test file: %s", i.GetPath())
245-
log.Warn("The code fragments will not be inserted.")
246-
return nil
240+
if os.IsNotExist(err) {
241+
if withOptionalBehavior, ok := i.(HasIfNotExistsAction); ok {
242+
switch withOptionalBehavior.GetIfNotExistsAction() {
243+
case IgnoreFile:
244+
log.Warn("Skipping missing file", "file", i.GetPath())
245+
log.Warn("The code fragments will not be inserted.")
246+
return nil
247+
case ErrorIfNotExist:
248+
return err
249+
default:
250+
return err
251+
}
252+
}
253+
// If HasIfNotExistsAction is not implemented, return the original error
254+
return err
247255
}
248256
return fmt.Errorf("failed to load previous model for %s: %w", i.GetPath(), err)
249257
}

pkg/plugins/golang/v4/scaffolds/internal/templates/webhooks/webhook_test_template.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ type WebhookTest struct {
3434
machinery.MultiGroupMixin
3535
machinery.BoilerplateMixin
3636
machinery.ResourceMixin
37+
machinery.IfNotExistsActionMixin
3738

3839
Force bool
3940

@@ -78,7 +79,10 @@ func (f *WebhookTest) SetTemplateDefaults() error {
7879

7980
if f.Force {
8081
f.IfExistsAction = machinery.OverwriteFile
82+
} else {
83+
f.IfExistsAction = machinery.Error
8184
}
85+
f.IfNotExistsAction = machinery.IgnoreFile
8286

8387
return nil
8488
}

0 commit comments

Comments
 (0)