Skip to content

Commit

Permalink
feat: pass config between KB and external plugin
Browse files Browse the repository at this point in the history
  • Loading branch information
Eileen-Yu committed Feb 15, 2024
1 parent 2302f6e commit 65ae4a3
Show file tree
Hide file tree
Showing 11 changed files with 172 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ import (
"io"
"os"

"v1/scaffolds"

"sigs.k8s.io/kubebuilder/v3/pkg/plugin/external"
"v1/scaffolds"
)

// Run will run the actual steps of the plugin
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ go 1.21
require (
github.com/spf13/pflag v1.0.5
sigs.k8s.io/kubebuilder/v3 v3.14.0
sigs.k8s.io/yaml v1.4.0
)

require (
Expand All @@ -14,3 +15,5 @@ require (
golang.org/x/text v0.14.0 // indirect
golang.org/x/tools v0.17.0 // indirect
)

replace sigs.k8s.io/kubebuilder/v3 => ../../../../../../../
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEe
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/gobuffalo/flect v1.0.2 h1:eqjPGSo2WmjgY2XlpGwo2NXgL3RucAKo4k4qQMNA5sA=
github.com/gobuffalo/flect v1.0.2/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/pprof v0.0.0-20230907193218-d3ddc7976beb h1:LCMfzVg3sflxTs4UvuP4D8CkoZnfHLe2qzqgDn/4OHs=
Expand Down Expand Up @@ -38,11 +39,10 @@ golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
sigs.k8s.io/kubebuilder/v3 v3.14.0 h1:DVrHb6ADfGQKk/4NiMFOO7XIJK58maXhYIwlHSFy84I=
sigs.k8s.io/kubebuilder/v3 v3.14.0/go.mod h1:vh/9c7elEE2h0wB+Gxy1t63f8WuPrLO1ExoQR6ms8L0=
sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E=
sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY=
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@ limitations under the License.
package scaffolds

import (
"v1/scaffolds/internal/templates"

"github.com/spf13/pflag"

"sigs.k8s.io/kubebuilder/v3/pkg/model/resource"
"sigs.k8s.io/kubebuilder/v3/pkg/plugin"
"sigs.k8s.io/kubebuilder/v3/pkg/plugin/external"
"v1/scaffolds/internal/templates"
)

var InitFlags = []external.Flag{
Expand Down Expand Up @@ -58,6 +57,31 @@ func InitCmd(pr *external.PluginRequest) external.PluginResponse {
flags.Parse(pr.Args)
domain, _ := flags.GetString("domain")

// Update the project config
cfg := pr.Config

pluginChain := cfg.GetPluginChain()
pluginChain = append(pluginChain, pflag.Arg(0))
cfg.SetPluginChain(pluginChain)

if cfg.GetProjectName() == "" {
cfg.SetProjectName("externalplugin")
}

rsc := resource.Resource{
GVK: resource.GVK{
Group: "group",
Version: "v1",
Kind: "Externalpluginsample",
Domain: "my.domain",
},
}

cfg.UpdateResource(rsc)

// Update the PluginResponse with the modified updated config
pluginResponse.Config = cfg

initFile := templates.NewInitFile(templates.WithDomain(domain))

// Phase 2 Plugins uses the concept of a "universe" to represent the filesystem for a plugin.
Expand Down
11 changes: 10 additions & 1 deletion pkg/plugin/external/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ limitations under the License.

package external

import "sigs.k8s.io/kubebuilder/v3/pkg/plugin"
import (
"sigs.k8s.io/kubebuilder/v3/pkg/config"
"sigs.k8s.io/kubebuilder/v3/pkg/plugin"
)

// PluginRequest contains all information kubebuilder received from the CLI
// and plugins executed before it.
Expand All @@ -35,6 +38,9 @@ type PluginRequest struct {
// Universe represents the modified file contents that gets updated over a series of plugin runs
// across the plugin chain. Initially, it starts out as empty.
Universe map[string]string `json:"universe"`

// Config stores the project configuration file.
Config config.Config `json:"config"`
}

// PluginResponse is returned to kubebuilder by the plugin and contains all files
Expand Down Expand Up @@ -63,6 +69,9 @@ type PluginResponse struct {
// Flags contains the plugin specific flags that the plugin returns to Kubebuilder when it receives
// a request for a list of supported flags from Kubebuilder
Flags []Flag `json:"flags,omitempty"`

// Config stores the project configuration file.
Config config.Config `json:"config"`
}

// Flag is meant to represent a CLI flag that is used by Kubebuilder to define flags that are parsed
Expand Down
25 changes: 22 additions & 3 deletions pkg/plugins/external/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,11 @@ limitations under the License.
package external

import (
"github.com/spf13/afero"
"github.com/spf13/pflag"

"sigs.k8s.io/kubebuilder/v3/pkg/config"
"sigs.k8s.io/kubebuilder/v3/pkg/config/store/yaml"
"sigs.k8s.io/kubebuilder/v3/pkg/machinery"
"sigs.k8s.io/kubebuilder/v3/pkg/model/resource"
"sigs.k8s.io/kubebuilder/v3/pkg/plugin"
Expand All @@ -32,8 +35,9 @@ const (
)

type createAPISubcommand struct {
Path string
Args []string
Path string
Args []string
config config.Config
}

func (p *createAPISubcommand) InjectResource(*resource.Resource) error {
Expand All @@ -50,16 +54,31 @@ func (p *createAPISubcommand) BindFlags(fs *pflag.FlagSet) {
}

func (p *createAPISubcommand) Scaffold(fs machinery.Filesystem) error {
cfg := yaml.New(machinery.Filesystem{FS: afero.NewOsFs()})
if err := cfg.Load(); err != nil {
return err
}

req := external.PluginRequest{
APIVersion: defaultAPIVersion,
Command: "create api",
Args: p.Args,
Config: cfg.Config(),
}

err := handlePluginResponse(fs, req, p.Path)
err := handlePluginResponse(fs, req, p.Path, p)
if err != nil {
return err
}

return nil
}

func (p *createAPISubcommand) InjectConfig(c config.Config) error {
p.config = c
return nil
}

func (p *createAPISubcommand) GetConfig() config.Config {
return p.config
}
17 changes: 14 additions & 3 deletions pkg/plugins/external/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package external
import (
"github.com/spf13/pflag"

"sigs.k8s.io/kubebuilder/v3/pkg/config"
"sigs.k8s.io/kubebuilder/v3/pkg/machinery"
"sigs.k8s.io/kubebuilder/v3/pkg/plugin"
"sigs.k8s.io/kubebuilder/v3/pkg/plugin/external"
Expand All @@ -27,8 +28,9 @@ import (
var _ plugin.EditSubcommand = &editSubcommand{}

type editSubcommand struct {
Path string
Args []string
Path string
Args []string
config config.Config
}

func (p *editSubcommand) UpdateMetadata(_ plugin.CLIMetadata, subcmdMeta *plugin.SubcommandMetadata) {
Expand All @@ -46,10 +48,19 @@ func (p *editSubcommand) Scaffold(fs machinery.Filesystem) error {
Args: p.Args,
}

err := handlePluginResponse(fs, req, p.Path)
err := handlePluginResponse(fs, req, p.Path, p)
if err != nil {
return err
}

return nil
}

func (p *editSubcommand) InjectConfig(c config.Config) error {
p.config = c
return nil
}

func (p *editSubcommand) GetConfig() config.Config {
return p.config
}
15 changes: 14 additions & 1 deletion pkg/plugins/external/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (

"github.com/spf13/afero"
"github.com/spf13/pflag"
"sigs.k8s.io/kubebuilder/v3/pkg/config"
"sigs.k8s.io/kubebuilder/v3/pkg/machinery"
"sigs.k8s.io/kubebuilder/v3/pkg/plugin"
"sigs.k8s.io/kubebuilder/v3/pkg/plugin/external"
Expand All @@ -51,6 +52,12 @@ type ExecOutputGetter interface {

type execOutputGetter struct{}

// PluginConfigHandler is an interface to update the config modified by external plugin.
type PluginConfigHandler interface {
GetConfig() config.Config
InjectConfig(config.Config) error
}

func (e *execOutputGetter) GetExecOutput(request []byte, path string) ([]byte, error) {
cmd := exec.Command(path) //nolint:gosec
cmd.Stdin = bytes.NewBuffer(request)
Expand Down Expand Up @@ -149,7 +156,8 @@ func getUniverseMap(fs machinery.Filesystem) (map[string]string, error) {
return universe, nil
}

func handlePluginResponse(fs machinery.Filesystem, req external.PluginRequest, path string) error {
// nolint:lll
func handlePluginResponse(fs machinery.Filesystem, req external.PluginRequest, path string, p PluginConfigHandler) error {
var err error

req.Universe, err = getUniverseMap(fs)
Expand All @@ -167,6 +175,11 @@ func handlePluginResponse(fs machinery.Filesystem, req external.PluginRequest, p
return fmt.Errorf("error getting current directory: %v", err)
}

// update the config
if err := p.InjectConfig(res.Config); err != nil {
return fmt.Errorf("error injecting the updated config from PluginResponse: %w", err)
}

for filename, data := range res.Universe {
path := filepath.Join(currentDir, filename)
dir := filepath.Dir(path)
Expand Down
47 changes: 44 additions & 3 deletions pkg/plugins/external/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,13 @@ limitations under the License.
package external

import (
"os"

"github.com/spf13/afero"
"github.com/spf13/pflag"

"sigs.k8s.io/kubebuilder/v3/pkg/config"
"sigs.k8s.io/kubebuilder/v3/pkg/config/store/yaml"
"sigs.k8s.io/kubebuilder/v3/pkg/machinery"
"sigs.k8s.io/kubebuilder/v3/pkg/plugin"
"sigs.k8s.io/kubebuilder/v3/pkg/plugin/external"
Expand All @@ -27,8 +32,9 @@ import (
var _ plugin.InitSubcommand = &initSubcommand{}

type initSubcommand struct {
Path string
Args []string
Path string
Args []string
config config.Config
}

func (p *initSubcommand) UpdateMetadata(_ plugin.CLIMetadata, subcmdMeta *plugin.SubcommandMetadata) {
Expand All @@ -40,16 +46,51 @@ func (p *initSubcommand) BindFlags(fs *pflag.FlagSet) {
}

func (p *initSubcommand) Scaffold(fs machinery.Filesystem) error {
fileName := "PROJECT"

if _, err := os.Stat(fileName); os.IsNotExist(err) {
file, err := os.Create(fileName)
if err != nil {
return err
}
defer func() {
if cerr := file.Close(); cerr != nil {
if err == nil {
err = cerr
}
}
}()
}

cfg := yaml.New(machinery.Filesystem{FS: afero.NewOsFs()})
if err := cfg.New(config.Version{Number: 3}); err != nil {
return err
}

if err := cfg.Load(); err != nil {
return err
}

req := external.PluginRequest{
APIVersion: defaultAPIVersion,
Command: "init",
Args: p.Args,
Config: cfg.Config(),
}

err := handlePluginResponse(fs, req, p.Path)
err := handlePluginResponse(fs, req, p.Path, p)
if err != nil {
return err
}

return nil
}

func (p *initSubcommand) InjectConfig(c config.Config) error {
p.config = c
return nil
}

func (p *initSubcommand) GetConfig() config.Config {
return p.config
}
17 changes: 14 additions & 3 deletions pkg/plugins/external/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package external
import (
"github.com/spf13/pflag"

"sigs.k8s.io/kubebuilder/v3/pkg/config"
"sigs.k8s.io/kubebuilder/v3/pkg/machinery"
"sigs.k8s.io/kubebuilder/v3/pkg/model/resource"
"sigs.k8s.io/kubebuilder/v3/pkg/plugin"
Expand All @@ -28,8 +29,9 @@ import (
var _ plugin.CreateWebhookSubcommand = &createWebhookSubcommand{}

type createWebhookSubcommand struct {
Path string
Args []string
Path string
Args []string
config config.Config
}

func (p *createWebhookSubcommand) InjectResource(*resource.Resource) error {
Expand All @@ -52,10 +54,19 @@ func (p *createWebhookSubcommand) Scaffold(fs machinery.Filesystem) error {
Args: p.Args,
}

err := handlePluginResponse(fs, req, p.Path)
err := handlePluginResponse(fs, req, p.Path, p)
if err != nil {
return err
}

return nil
}

func (p *createWebhookSubcommand) InjectConfig(c config.Config) error {
p.config = c
return nil
}

func (p *createWebhookSubcommand) GetConfig() config.Config {
return p.config
}
Loading

0 comments on commit 65ae4a3

Please sign in to comment.