Skip to content

Commit

Permalink
✨Change NewBundle method to build bundles through working with opti…
Browse files Browse the repository at this point in the history
…ons (#3312)

* change NewBundle method to build bundles through working with options

Signed-off-by: Nikhil Sharma <nikhilsharma230303@gmail.com>

* make changes in docs for the changed pattern for NewBundleWithOptions func

Signed-off-by: Nikhil Sharma <nikhilsharma230303@gmail.com>

---------

Signed-off-by: Nikhil Sharma <nikhilsharma230303@gmail.com>
  • Loading branch information
NikhilSharmaWe committed Apr 22, 2023
1 parent ff3fa67 commit 9ba9d57
Show file tree
Hide file tree
Showing 7 changed files with 171 additions and 27 deletions.
15 changes: 7 additions & 8 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,16 @@ func main() {
"Please, check the migration guide to learn how to upgrade your project"

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

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

fs := machinery.Filesystem{
Expand Down
14 changes: 8 additions & 6 deletions docs/book/src/plugins/creating-plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ Note that Kubebuilder provides the `kustomize.common.kubebuilder.io` to help in
In this way, currently, you can [Extend the CLI][extending-cli] and use the `Bundle Plugin` to create your language plugins such as:

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

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

```go
mylanguagev1Bundle, _ := plugin.NewBundle(language.DefaultNameQualifier, plugin.Version{Number: 1},
kustomizecommonv1.Plugin{}, // extend the common base from Kuebebuilder
mylanguagev1.Plugin{}, // your plugin language which will do the scaffolds for the specific language on top of the common base
mylanguagev1Bundle, _ := plugin.NewBundle(plugin.WithName(language.DefaultNameQualifier),
plugin.WithVersion(plugin.Version{Number: 1}),
plugin.WithPlugins(kustomizecommonv1.Plugin{}, mylanguagev1.Plugin{}), // extend the common base from Kuebebuilder
// your plugin language which will do the scaffolds for the specific language on top of the common base
)
```

Expand Down
13 changes: 6 additions & 7 deletions docs/book/src/plugins/extending-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,9 @@ var (
// GetPluginsCLI returns the plugins based CLI configured to be used in your CLI binary
func GetPluginsCLI() (*cli.CLI) {
// Bundle plugin which built the golang projects scaffold by Kubebuilder go/v3
gov3Bundle, _ := plugin.NewBundle(golang.DefaultNameQualifier, plugin.Version{Number: 3},
kustomizecommonv1.Plugin{},
golangv3.Plugin{},
gov3Bundle, _ := plugin.NewBundle(plugin.WithName(golang.DefaultNameQualifier),
plugin.WithVersion(plugin.Version{Number: 3}),
plugin.WithPlugins(kustomizecommonv1.Plugin{}, golangv3.Plugin{}),
)


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

```go
// see that will be like myplugin.example/v1`
myPluginBundle, _ := plugin.NewBundle(`<plugin-name>`,`<plugin-version>`,
pluginA.Plugin{},
pluginB.Plugin{},
pluginC.Plugin{},
myPluginBundle, _ := plugin.NewBundle(plugin.WithName(`<plugin-name>`),
plugin.WithVersion(`<plugin-version>`),
plugin.WithPlugins(pluginA.Plugin{}, pluginB.Plugin{}, pluginC.Plugin{}),
)

```
Expand Down
7 changes: 4 additions & 3 deletions docs/book/src/plugins/kustomize-v1.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@ all that is language specific and kustomize for its configuration, see:
// Bundle plugin which built the golang projects scaffold by Kubebuilder go/v3
// The follow code is creating a new plugin with its name and version via composition
// You can define that one plugin is composite by 1 or Many others plugins
gov3Bundle, _ := plugin.NewBundle(golang.DefaultNameQualifier, plugin.Version{Number: 3},
kustomizecommonv1.Plugin{}, // scaffold the config/ directory and all kustomize files
golangv3.Plugin{}, // Scaffold the Golang files and all that specific for the language e.g. go.mod, apis, controllers
gov3Bundle, _ := plugin.NewBundle(plugin.WithName(golang.DefaultNameQualifier),
plugin.WithVersion(plugin.Version{Number: 3}),
plugin.WithPlugins(kustomizecommonv1.Plugin{}, golangv3.Plugin{}), // scaffold the config/ directory and all kustomize files
// Scaffold the Golang files and all that specific for the language e.g. go.mod, apis, controllers
)
```

Expand Down
7 changes: 4 additions & 3 deletions docs/book/src/plugins/kustomize-v2.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ import (
// Bundle plugin which built the golang projects scaffold by Kubebuilder go/v3
// The follow code is creating a new plugin with its name and version via composition
// You can define that one plugin is composite by 1 or Many others plugins
gov3Bundle, _ := plugin.NewBundle(golang.DefaultNameQualifier, plugin.Version{Number: 3},
kustomizecommonv2.Plugin{}, // scaffold the config/ directory and all kustomize files
golangv4.Plugin{}, // Scaffold the Golang files and all that specific for the language e.g. go.mod, apis, controllers
gov3Bundle, _ := plugin.NewBundle(plugin.WithName(golang.DefaultNameQualifier),
plugin.WithVersion(plugin.Version{Number: 3}),
plugin.WithPlugins(kustomizecommonv2.Plugin{}, golangv3.Plugin{}), // scaffold the config/ directory and all kustomize files
// Scaffold the Golang files and all that specific for the language e.g. go.mod, apis, controllers
)
```

Expand Down
62 changes: 62 additions & 0 deletions pkg/plugin/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,33 @@ type bundle struct {
deprecateWarning string
}

type BundleOption func(*bundle)

func WithName(name string) BundleOption {
return func(opts *bundle) {
opts.name = name
}
}

func WithVersion(version Version) BundleOption {
return func(opts *bundle) {
opts.version = version
}
}

func WithPlugins(plugins ...Plugin) BundleOption {
return func(opts *bundle) {
opts.plugins = plugins
}
}

func WithDeprecationMessage(msg string) BundleOption {
return func(opts *bundle) {
opts.deprecateWarning = msg
}

}

// NewBundle creates a new Bundle with the provided name and version, and that wraps the provided plugins.
// The list of supported project versions is computed from the provided plugins.
func NewBundle(name string, version Version, deprecateWarning string, plugins ...Plugin) (Bundle, error) {
Expand Down Expand Up @@ -60,6 +87,41 @@ func NewBundle(name string, version Version, deprecateWarning string, plugins ..
}, nil
}

// NewBundleWithOptions creates a new Bundle with the provided BundleOptions.
// The list of supported project versions is computed from the provided plugins in options.
func NewBundleWithOptions(opts ...BundleOption) (Bundle, error) {
bundleOpts := bundle{}

for _, opts := range opts {
opts(&bundleOpts)
}

supportedProjectVersions := CommonSupportedProjectVersions(bundleOpts.plugins...)
if len(supportedProjectVersions) == 0 {
return nil, fmt.Errorf("in order to bundle plugins, they must all support at least one common project version")
}

// Plugins may be bundles themselves, so unbundle here
// NOTE(Adirio): unbundling here ensures that Bundle.Plugin always returns a flat list of Plugins instead of also
// including Bundles, and therefore we don't have to use a recursive algorithm when resolving.
allPlugins := make([]Plugin, 0, len(bundleOpts.plugins))
for _, plugin := range bundleOpts.plugins {
if pluginBundle, isBundle := plugin.(Bundle); isBundle {
allPlugins = append(allPlugins, pluginBundle.Plugins()...)
} else {
allPlugins = append(allPlugins, plugin)
}
}

return bundle{
name: bundleOpts.name,
version: bundleOpts.version,
plugins: allPlugins,
supportedProjectVersions: supportedProjectVersions,
deprecateWarning: bundleOpts.deprecateWarning,
}, nil
}

// Name implements Plugin
func (b bundle) Name() string {
return b.name
Expand Down
80 changes: 80 additions & 0 deletions pkg/plugin/bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,4 +118,84 @@ var _ = Describe("Bundle", func() {
}
})
})

Context("NewBundleWithOptions", func() {
It("should succeed for plugins with common supported project versions", func() {
for _, plugins := range [][]Plugin{
{p1, p2},
{p1, p3},
{p1, p4},
{p2, p3},
{p3, p4},

{p1, p2, p3},
{p1, p3, p4},
} {
b, err := NewBundleWithOptions(WithName(name),
WithVersion(version),
WithDeprecationMessage(""),
WithPlugins(plugins...),
)
Expect(err).NotTo(HaveOccurred())
Expect(b.Name()).To(Equal(name))
Expect(b.Version().Compare(version)).To(Equal(0))
versions := b.SupportedProjectVersions()
sort.Slice(versions, func(i int, j int) bool {
return versions[i].Compare(versions[j]) == -1
})
expectedVersions := CommonSupportedProjectVersions(plugins...)
sort.Slice(expectedVersions, func(i int, j int) bool {
return expectedVersions[i].Compare(expectedVersions[j]) == -1
})
Expect(versions).To(Equal(expectedVersions))
Expect(b.Plugins()).To(Equal(plugins))
}
})

It("should accept bundles as input", func() {
var a, b Bundle
var err error
plugins := []Plugin{p1, p2, p3}
a, err = NewBundleWithOptions(WithName("a"),
WithVersion(version),
WithDeprecationMessage(""),
WithPlugins(p1, p2),
)
Expect(err).NotTo(HaveOccurred())
b, err = NewBundleWithOptions(WithName("b"),
WithVersion(version),
WithDeprecationMessage(""),
WithPlugins(a, p3),
)
Expect(err).NotTo(HaveOccurred())
versions := b.SupportedProjectVersions()
sort.Slice(versions, func(i int, j int) bool {
return versions[i].Compare(versions[j]) == -1
})
expectedVersions := CommonSupportedProjectVersions(plugins...)
sort.Slice(expectedVersions, func(i int, j int) bool {
return expectedVersions[i].Compare(expectedVersions[j]) == -1
})
Expect(versions).To(Equal(expectedVersions))
Expect(b.Plugins()).To(Equal(plugins))
})

It("should fail for plugins with no common supported project version", func() {
for _, plugins := range [][]Plugin{
{p2, p4},

{p1, p2, p4},
{p2, p3, p4},

{p1, p2, p3, p4},
} {
_, err := NewBundleWithOptions(WithName(name),
WithVersion(version),
WithDeprecationMessage(""),
WithPlugins(plugins...),
)
Expect(err).To(HaveOccurred())
}
})
})
})

0 comments on commit 9ba9d57

Please sign in to comment.