Skip to content

Commit 9ba9d57

Browse files
✨Change NewBundle method to build bundles through working with options (#3312)
* change NewBundle method to build bundles through working with options Signed-off-by: Nikhil Sharma <[email protected]> * make changes in docs for the changed pattern for NewBundleWithOptions func Signed-off-by: Nikhil Sharma <[email protected]> --------- Signed-off-by: Nikhil Sharma <[email protected]>
1 parent ff3fa67 commit 9ba9d57

File tree

7 files changed

+171
-27
lines changed

7 files changed

+171
-27
lines changed

cmd/main.go

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,16 @@ func main() {
4646
"Please, check the migration guide to learn how to upgrade your project"
4747

4848
// Bundle plugin which built the golang projects scaffold by Kubebuilder go/v3
49-
gov3Bundle, _ := plugin.NewBundle(golang.DefaultNameQualifier, plugin.Version{Number: 3},
50-
deprecateMessageGoV3Bundle,
51-
kustomizecommonv1.Plugin{},
52-
golangv3.Plugin{},
49+
gov3Bundle, _ := plugin.NewBundleWithOptions(plugin.WithName(golang.DefaultNameQualifier),
50+
plugin.WithVersion(plugin.Version{Number: 3}),
51+
plugin.WithDeprecationMessage(deprecateMessageGoV3Bundle),
52+
plugin.WithPlugins(kustomizecommonv1.Plugin{}, golangv3.Plugin{}),
5353
)
5454

5555
// Bundle plugin which built the golang projects scaffold by Kubebuilder go/v4 with kustomize alpha-v2
56-
gov4Bundle, _ := plugin.NewBundle(golang.DefaultNameQualifier, plugin.Version{Number: 4},
57-
"",
58-
kustomizecommonv2alpha.Plugin{},
59-
golangv4.Plugin{},
56+
gov4Bundle, _ := plugin.NewBundleWithOptions(plugin.WithName(golang.DefaultNameQualifier),
57+
plugin.WithVersion(plugin.Version{Number: 4}),
58+
plugin.WithPlugins(kustomizecommonv2alpha.Plugin{}, golangv4.Plugin{}),
6059
)
6160

6261
fs := machinery.Filesystem{

docs/book/src/plugins/creating-plugins.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,10 @@ Note that Kubebuilder provides the `kustomize.common.kubebuilder.io` to help in
5757
In this way, currently, you can [Extend the CLI][extending-cli] and use the `Bundle Plugin` to create your language plugins such as:
5858

5959
```go
60-
mylanguagev1Bundle, _ := plugin.NewBundle(language.DefaultNameQualifier, plugin.Version{Number: 1},
61-
kustomizecommonv1.Plugin{}, // extend the common base from Kubebuilder
62-
mylanguagev1.Plugin{}, // your plugin language which will do the scaffolds for the specific language on top of the common base
60+
mylanguagev1Bundle, _ := plugin.NewBundle(plugin.WithName(language.DefaultNameQualifier),
61+
plugin.WithVersion(plugin.Version{Number: 1}),
62+
plugin.WithPlugins(kustomizecommonv1.Plugin{}, mylanguagev1.Plugin{}), // extend the common base from Kubebuilder
63+
// your plugin language which will do the scaffolds for the specific language on top of the common base
6364
)
6465
```
6566

@@ -169,9 +170,10 @@ See [example of deploy-image][example-of-deploy-image-3].
169170
Alternatively, you can create a plugin bundle to include the target plugins. For instance:
170171

171172
```go
172-
mylanguagev1Bundle, _ := plugin.NewBundle(language.DefaultNameQualifier, plugin.Version{Number: 1},
173-
kustomizecommonv1.Plugin{}, // extend the common base from Kuebebuilder
174-
mylanguagev1.Plugin{}, // your plugin language which will do the scaffolds for the specific language on top of the common base
173+
mylanguagev1Bundle, _ := plugin.NewBundle(plugin.WithName(language.DefaultNameQualifier),
174+
plugin.WithVersion(plugin.Version{Number: 1}),
175+
plugin.WithPlugins(kustomizecommonv1.Plugin{}, mylanguagev1.Plugin{}), // extend the common base from Kuebebuilder
176+
// your plugin language which will do the scaffolds for the specific language on top of the common base
175177
)
176178
```
177179

docs/book/src/plugins/extending-cli.md

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,9 @@ var (
4242
// GetPluginsCLI returns the plugins based CLI configured to be used in your CLI binary
4343
func GetPluginsCLI() (*cli.CLI) {
4444
// Bundle plugin which built the golang projects scaffold by Kubebuilder go/v3
45-
gov3Bundle, _ := plugin.NewBundle(golang.DefaultNameQualifier, plugin.Version{Number: 3},
46-
kustomizecommonv1.Plugin{},
47-
golangv3.Plugin{},
45+
gov3Bundle, _ := plugin.NewBundle(plugin.WithName(golang.DefaultNameQualifier),
46+
plugin.WithVersion(plugin.Version{Number: 3}),
47+
plugin.WithPlugins(kustomizecommonv1.Plugin{}, golangv3.Plugin{}),
4848
)
4949

5050

@@ -175,10 +175,9 @@ Once a plugin is deprecated, have it implement a [Deprecated][deprecate-plugin-d
175175

176176
```go
177177
// see that will be like myplugin.example/v1`
178-
myPluginBundle, _ := plugin.NewBundle(`<plugin-name>`,`<plugin-version>`,
179-
pluginA.Plugin{},
180-
pluginB.Plugin{},
181-
pluginC.Plugin{},
178+
myPluginBundle, _ := plugin.NewBundle(plugin.WithName(`<plugin-name>`),
179+
plugin.WithVersion(`<plugin-version>`),
180+
plugin.WithPlugins(pluginA.Plugin{}, pluginB.Plugin{}, pluginC.Plugin{}),
182181
)
183182

184183
```

docs/book/src/plugins/kustomize-v1.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,10 @@ all that is language specific and kustomize for its configuration, see:
5959
// Bundle plugin which built the golang projects scaffold by Kubebuilder go/v3
6060
// The follow code is creating a new plugin with its name and version via composition
6161
// You can define that one plugin is composite by 1 or Many others plugins
62-
gov3Bundle, _ := plugin.NewBundle(golang.DefaultNameQualifier, plugin.Version{Number: 3},
63-
kustomizecommonv1.Plugin{}, // scaffold the config/ directory and all kustomize files
64-
golangv3.Plugin{}, // Scaffold the Golang files and all that specific for the language e.g. go.mod, apis, controllers
62+
gov3Bundle, _ := plugin.NewBundle(plugin.WithName(golang.DefaultNameQualifier),
63+
plugin.WithVersion(plugin.Version{Number: 3}),
64+
plugin.WithPlugins(kustomizecommonv1.Plugin{}, golangv3.Plugin{}), // scaffold the config/ directory and all kustomize files
65+
// Scaffold the Golang files and all that specific for the language e.g. go.mod, apis, controllers
6566
)
6667
```
6768

docs/book/src/plugins/kustomize-v2.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,10 @@ import (
4444
// Bundle plugin which built the golang projects scaffold by Kubebuilder go/v3
4545
// The follow code is creating a new plugin with its name and version via composition
4646
// You can define that one plugin is composite by 1 or Many others plugins
47-
gov3Bundle, _ := plugin.NewBundle(golang.DefaultNameQualifier, plugin.Version{Number: 3},
48-
kustomizecommonv2.Plugin{}, // scaffold the config/ directory and all kustomize files
49-
golangv4.Plugin{}, // Scaffold the Golang files and all that specific for the language e.g. go.mod, apis, controllers
47+
gov3Bundle, _ := plugin.NewBundle(plugin.WithName(golang.DefaultNameQualifier),
48+
plugin.WithVersion(plugin.Version{Number: 3}),
49+
plugin.WithPlugins(kustomizecommonv2.Plugin{}, golangv3.Plugin{}), // scaffold the config/ directory and all kustomize files
50+
// Scaffold the Golang files and all that specific for the language e.g. go.mod, apis, controllers
5051
)
5152
```
5253

pkg/plugin/bundle.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,33 @@ type bundle struct {
3131
deprecateWarning string
3232
}
3333

34+
type BundleOption func(*bundle)
35+
36+
func WithName(name string) BundleOption {
37+
return func(opts *bundle) {
38+
opts.name = name
39+
}
40+
}
41+
42+
func WithVersion(version Version) BundleOption {
43+
return func(opts *bundle) {
44+
opts.version = version
45+
}
46+
}
47+
48+
func WithPlugins(plugins ...Plugin) BundleOption {
49+
return func(opts *bundle) {
50+
opts.plugins = plugins
51+
}
52+
}
53+
54+
func WithDeprecationMessage(msg string) BundleOption {
55+
return func(opts *bundle) {
56+
opts.deprecateWarning = msg
57+
}
58+
59+
}
60+
3461
// NewBundle creates a new Bundle with the provided name and version, and that wraps the provided plugins.
3562
// The list of supported project versions is computed from the provided plugins.
3663
func NewBundle(name string, version Version, deprecateWarning string, plugins ...Plugin) (Bundle, error) {
@@ -60,6 +87,41 @@ func NewBundle(name string, version Version, deprecateWarning string, plugins ..
6087
}, nil
6188
}
6289

90+
// NewBundleWithOptions creates a new Bundle with the provided BundleOptions.
91+
// The list of supported project versions is computed from the provided plugins in options.
92+
func NewBundleWithOptions(opts ...BundleOption) (Bundle, error) {
93+
bundleOpts := bundle{}
94+
95+
for _, opts := range opts {
96+
opts(&bundleOpts)
97+
}
98+
99+
supportedProjectVersions := CommonSupportedProjectVersions(bundleOpts.plugins...)
100+
if len(supportedProjectVersions) == 0 {
101+
return nil, fmt.Errorf("in order to bundle plugins, they must all support at least one common project version")
102+
}
103+
104+
// Plugins may be bundles themselves, so unbundle here
105+
// NOTE(Adirio): unbundling here ensures that Bundle.Plugin always returns a flat list of Plugins instead of also
106+
// including Bundles, and therefore we don't have to use a recursive algorithm when resolving.
107+
allPlugins := make([]Plugin, 0, len(bundleOpts.plugins))
108+
for _, plugin := range bundleOpts.plugins {
109+
if pluginBundle, isBundle := plugin.(Bundle); isBundle {
110+
allPlugins = append(allPlugins, pluginBundle.Plugins()...)
111+
} else {
112+
allPlugins = append(allPlugins, plugin)
113+
}
114+
}
115+
116+
return bundle{
117+
name: bundleOpts.name,
118+
version: bundleOpts.version,
119+
plugins: allPlugins,
120+
supportedProjectVersions: supportedProjectVersions,
121+
deprecateWarning: bundleOpts.deprecateWarning,
122+
}, nil
123+
}
124+
63125
// Name implements Plugin
64126
func (b bundle) Name() string {
65127
return b.name

pkg/plugin/bundle_test.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,4 +118,84 @@ var _ = Describe("Bundle", func() {
118118
}
119119
})
120120
})
121+
122+
Context("NewBundleWithOptions", func() {
123+
It("should succeed for plugins with common supported project versions", func() {
124+
for _, plugins := range [][]Plugin{
125+
{p1, p2},
126+
{p1, p3},
127+
{p1, p4},
128+
{p2, p3},
129+
{p3, p4},
130+
131+
{p1, p2, p3},
132+
{p1, p3, p4},
133+
} {
134+
b, err := NewBundleWithOptions(WithName(name),
135+
WithVersion(version),
136+
WithDeprecationMessage(""),
137+
WithPlugins(plugins...),
138+
)
139+
Expect(err).NotTo(HaveOccurred())
140+
Expect(b.Name()).To(Equal(name))
141+
Expect(b.Version().Compare(version)).To(Equal(0))
142+
versions := b.SupportedProjectVersions()
143+
sort.Slice(versions, func(i int, j int) bool {
144+
return versions[i].Compare(versions[j]) == -1
145+
})
146+
expectedVersions := CommonSupportedProjectVersions(plugins...)
147+
sort.Slice(expectedVersions, func(i int, j int) bool {
148+
return expectedVersions[i].Compare(expectedVersions[j]) == -1
149+
})
150+
Expect(versions).To(Equal(expectedVersions))
151+
Expect(b.Plugins()).To(Equal(plugins))
152+
}
153+
})
154+
155+
It("should accept bundles as input", func() {
156+
var a, b Bundle
157+
var err error
158+
plugins := []Plugin{p1, p2, p3}
159+
a, err = NewBundleWithOptions(WithName("a"),
160+
WithVersion(version),
161+
WithDeprecationMessage(""),
162+
WithPlugins(p1, p2),
163+
)
164+
Expect(err).NotTo(HaveOccurred())
165+
b, err = NewBundleWithOptions(WithName("b"),
166+
WithVersion(version),
167+
WithDeprecationMessage(""),
168+
WithPlugins(a, p3),
169+
)
170+
Expect(err).NotTo(HaveOccurred())
171+
versions := b.SupportedProjectVersions()
172+
sort.Slice(versions, func(i int, j int) bool {
173+
return versions[i].Compare(versions[j]) == -1
174+
})
175+
expectedVersions := CommonSupportedProjectVersions(plugins...)
176+
sort.Slice(expectedVersions, func(i int, j int) bool {
177+
return expectedVersions[i].Compare(expectedVersions[j]) == -1
178+
})
179+
Expect(versions).To(Equal(expectedVersions))
180+
Expect(b.Plugins()).To(Equal(plugins))
181+
})
182+
183+
It("should fail for plugins with no common supported project version", func() {
184+
for _, plugins := range [][]Plugin{
185+
{p2, p4},
186+
187+
{p1, p2, p4},
188+
{p2, p3, p4},
189+
190+
{p1, p2, p3, p4},
191+
} {
192+
_, err := NewBundleWithOptions(WithName(name),
193+
WithVersion(version),
194+
WithDeprecationMessage(""),
195+
WithPlugins(plugins...),
196+
)
197+
Expect(err).To(HaveOccurred())
198+
}
199+
})
200+
})
121201
})

0 commit comments

Comments
 (0)