Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat add plugins #16

Merged
merged 4 commits into from
Aug 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 12 additions & 3 deletions cmd/multikf/cmd_connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,21 @@ func NewConnectCommand(logger log.Logger, ioStreams genericclioptions.IOStreams)
}

func newConnectKubeflowCommand(logger log.Logger, ioStreams genericclioptions.IOStreams) *cobra.Command {
var (
port int // dedicated port
)
handle := func(machineName string) error {
m, err := findMachineByName(machineName, logger)
if err != nil {
return err
}
destPort, err := machine.FindFreePort()
if err != nil {
return err
destPort := port
if !(destPort > 1024 && destPort < 65536) {
logger.V(0).Infof("invaid customized port, use random\n")
destPort, err = machine.FindFreePort()
if err != nil {
return err
}
}
logger.V(0).Infof("now you can open http://localhost:%d\n", destPort)
return m.GetKubeCli().Portforward(m.GetKubeConfig(), "svc/istio-ingressgateway", "istio-system", 80, destPort)
Expand All @@ -37,5 +44,7 @@ func newConnectKubeflowCommand(logger log.Logger, ioStreams genericclioptions.IO
return handle(args[0])
},
}

cmd.Flags().IntVar(&port, "port", 0, "customized port number for connect, ranged should be 65535> >1024, default is 0 (random)")
return cmd
}
89 changes: 89 additions & 0 deletions cmd/multikf/cmd_plugins.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package multikf

import (
"github.com/footprintai/multikf/pkg/machine/plugins"
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
"sigs.k8s.io/kind/pkg/log"
)

func NewPluginCommand(logger log.Logger, ioStreams genericclioptions.IOStreams) *cobra.Command {
cmd := &cobra.Command{
Use: "plugin",
Short: "plugin",
Long: `enable plugins to the underlying k8s`,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
},
}
cmd.AddCommand(newAddPluginCommand(logger, ioStreams))
cmd.AddCommand(newRemovePluginCommand(logger, ioStreams))
return cmd
}

func newAddPluginCommand(logger log.Logger, ioStreams genericclioptions.IOStreams) *cobra.Command {
var (
withKubeflow bool // install with kubeflow components
withKubeflowVersion string // with kubeflow version
withKubeflowDefaultPassword string // with kubeflow defaultpassword
)

handle := func(machineName string) error {
m, err := findMachineByName(machineName, logger)
if err != nil {
return err
}
var installedPlugins []plugins.Plugin
if withKubeflow {
installedPlugins = append(installedPlugins,
kubeflowPlugin{
withKubeflowDefaultPassword: withKubeflowDefaultPassword,
kubeflowVersion: plugins.NewTypePluginVersion(withKubeflowVersion),
},
)
}
return plugins.AddPlugins(m, installedPlugins...)
}
cmd := &cobra.Command{
Use: "add <machine-name> --with_kubeflow",
Short: "add kubeflow plugins to the machine",
RunE: func(cmd *cobra.Command, args []string) error {
return handle(args[0])
},
}

cmd.Flags().BoolVar(&withKubeflow, "with_kubeflow", true, "install kubeflow modules (default: true)")
cmd.Flags().StringVar(&withKubeflowVersion, "kubeflow_version", "v1.4", "kubeflow version v1.4/v1.5.1")
cmd.Flags().StringVar(&withKubeflowDefaultPassword, "with_password", "12341234", "with a specific password for default user (default: 12341234)")

return cmd
}

func newRemovePluginCommand(logger log.Logger, ioStreams genericclioptions.IOStreams) *cobra.Command {
var (
removeKubeflow bool // remove kubeflow components
removeKubeflowVersion string // with kubeflow version
)

handle := func(machineName string) error {
m, err := findMachineByName(machineName, logger)
if err != nil {
return err
}
var removingPlugins []plugins.Plugin
if removeKubeflow {
removingPlugins = append(removingPlugins, kubeflowPlugin{kubeflowVersion: plugins.NewTypePluginVersion(removeKubeflowVersion)})
}
return plugins.RemovePlugins(m, removingPlugins...)
}
cmd := &cobra.Command{
Use: "remove <machine-name> --remove_kubeflow",
Short: "rmeove kubeflow plugins to the machine",
RunE: func(cmd *cobra.Command, args []string) error {
return handle(args[0])
},
}

cmd.Flags().BoolVar(&removeKubeflow, "remove_kubeflow", false, "remove kubeflow modules (default: false)")
cmd.Flags().StringVar(&removeKubeflowVersion, "kubeflow_version", "v1.4", "kubeflow version v1.4/v1.5.1")
return cmd
}
1 change: 1 addition & 0 deletions cmd/multikf/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func NewRootCommand(logger log.Logger, ioStreams genericclioptions.IOStreams) *c
cmd.AddCommand(NewListCommand(logger, ioStreams))
cmd.AddCommand(NewDeleteCommand(logger, ioStreams))
cmd.AddCommand(NewConnectCommand(logger, ioStreams))
cmd.AddCommand(NewPluginCommand(logger, ioStreams))

cmd.PersistentFlags().StringVar(&guestRootDir, "dir", ".multikfdir", "multikf root dir")
cmd.PersistentFlags().BoolVar(&verbose, "verbose", true, "verbose (default: true)")
Expand Down
14 changes: 14 additions & 0 deletions pkg/machine/kubectl/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,20 @@ func (cli *CLI) InstallKubeflow(kubeConfigFile string, kfmanifestFile string) er
return nil
}

func (cli *CLI) RemoveKubeflow(kubeConfigFile string, kfmanifestFile string) error {
cmdAndArgs := []string{
cli.localKubectlBinaryPath,
"delete",
"-f",
kfmanifestFile,
"--kubeconfig",
kubeConfigFile,
}
sr, _, err := cli.runCmd(cmdAndArgs)
ioutil.StderrOnError(sr)
return err
}

func (cli *CLI) PatchKubeflow(kubeConfigFile string) error {
multiCmdAndArgs := [][]string{
[]string{
Expand Down
4 changes: 2 additions & 2 deletions pkg/machine/plugins/kubeflow/kubeflow_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import (
"golang.org/x/crypto/bcrypt"
)

func NewKubeflow14Template() *KubeflowFileTemplate {
func NewKubeflow14Template() pkgtemplate.TemplateExecutor {
return newKubeflowTemplateWithTemplate("kubeflow-manifest-v1.4.1.yaml", kfmanifests.KF14TemplateString)
}

func NewKubeflow15Template() *KubeflowFileTemplate {
func NewKubeflow15Template() pkgtemplate.TemplateExecutor {
return newKubeflowTemplateWithTemplate("kubeflow-manifest-v1.5.1.yaml", kfmanifests.KF15TemplateString)
}

Expand Down
85 changes: 63 additions & 22 deletions pkg/machine/plugins/plugins.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

"github.com/footprintai/multikf/pkg/machine"
kubeflowplugin "github.com/footprintai/multikf/pkg/machine/plugins/kubeflow"
"github.com/footprintai/multikf/pkg/template"
templatefs "github.com/footprintai/multikf/pkg/template/fs"
)

Expand All @@ -21,21 +22,26 @@ func (t TypePluginVersion) String() string {
return string(t)
}

type kubeflowTemplateMakerFunc func() *kubeflowplugin.KubeflowFileTemplate
var (
TypePluginVersionKF14 = NewTypePluginVersion("v1.4")
TypePluginVersionKF151 = NewTypePluginVersion("v1.5.1")
)

type templateMakerFunc func() template.TemplateExecutor

var (
noVersion = NewTypePluginVersion("v0.0.0")
availableVersions = map[TypePluginVersion]kubeflowTemplateMakerFunc{
NewTypePluginVersion("v1.4"): kubeflowplugin.NewKubeflow14Template,
NewTypePluginVersion("v1.5.1"): kubeflowplugin.NewKubeflow15Template,
availableVersions = map[TypePluginVersion]templateMakerFunc{
TypePluginVersionKF14: kubeflowplugin.NewKubeflow14Template,
TypePluginVersionKF151: kubeflowplugin.NewKubeflow15Template,
}
)

func NewTypePluginVersion(s string) TypePluginVersion {
return TypePluginVersion(s)
}

func KubeflowPluginVersionTemplate(s TypePluginVersion) (TypePluginVersion, *kubeflowplugin.KubeflowFileTemplate) {
func KubeflowPluginVersionTemplate(s TypePluginVersion) (TypePluginVersion, template.TemplateExecutor) {
templateMaker, hasVersion := availableVersions[s]
if !hasVersion {
return noVersion, nil
Expand All @@ -48,35 +54,60 @@ type Plugin interface {
PluginVersion() TypePluginVersion
}

func AddPlugins(m machine.MachineCURD, plugins ...Plugin) error {
pluginAndFiles := map[TypePlugin]string{}
type TypeHostFilePath string

func (t TypeHostFilePath) String() string {
return string(t)
}

memFs := templatefs.NewMemoryFilesFs()
func NewTypeHostFilePath(s string) TypeHostFilePath {
return TypeHostFilePath(s)
}

func generatePluginsManifestsMapping(m machine.MachineCURD, dumpToFile bool, plugins ...Plugin) (map[Plugin]template.TemplateExecutor, error) {
pluginAndTmpls := map[Plugin]template.TemplateExecutor{}
for _, plugin := range plugins {
switch plugin.PluginType() {
case TypePluginKubeflow:
// handle kubeflow plugins
_, tmpl := KubeflowPluginVersionTemplate(plugin.PluginVersion())
if tmpl == nil {
return errors.New("plugins: no version found")
}
if err := memFs.Generate(plugin, tmpl); err != nil {
return err
return nil, errors.New("plugins: no version found")
}
pluginAndFiles[plugin.PluginType()] = tmpl.Filename()
pluginAndTmpls[plugin] = tmpl
default:
return errors.New("plugins: no available plugins")
return nil, errors.New("plugins: no available plugins")
}
}
if err := templatefs.NewFolder(m.HostDir()).DumpFiles(true, memFs.FS()); err != nil {
return err
if dumpToFile {
memFs := templatefs.NewMemoryFilesFs()
for plugin, tmpl := range pluginAndTmpls {
if err := memFs.Generate(plugin, tmpl); err != nil {
return nil, err
}
}
// TODO: check whether we want to overwrite exsiting or not
if err := templatefs.NewFolder(m.HostDir()).DumpFiles(true, memFs.FS()); err != nil {
return nil, err
}
}
return pluginAndTmpls, nil
}

func AddPlugins(m machine.MachineCURD, plugins ...Plugin) error {
var err error
_, hasKf := pluginAndFiles[TypePluginKubeflow]
if hasKf {
err = m.GetKubeCli().InstallKubeflow(m.GetKubeConfig(), filepath.Join(m.HostDir(), pluginAndFiles[TypePluginKubeflow]))
if err == nil {
err = m.GetKubeCli().PatchKubeflow(m.GetKubeConfig())
pluginAndTmpls, err := generatePluginsManifestsMapping(m, true, plugins...)
if err != nil {
return nil
}
for plugin, tmpl := range pluginAndTmpls {
if plugin.PluginType() == TypePluginKubeflow {
err = m.GetKubeCli().InstallKubeflow(m.GetKubeConfig(), filepath.Join(m.HostDir(), tmpl.Filename()))
if err == nil {
if plugin.PluginVersion() == TypePluginVersionKF14 {
err = m.GetKubeCli().PatchKubeflow(m.GetKubeConfig())
}
}
}
}
if err != nil {
Expand All @@ -86,6 +117,16 @@ func AddPlugins(m machine.MachineCURD, plugins ...Plugin) error {
}

func RemovePlugins(m machine.MachineCURD, plugins ...Plugin) error {
return errors.New("plugins: not imp")
var err error
pluginAndTmpls, err := generatePluginsManifestsMapping(m, false, plugins...)
if err != nil {
return err
}
for plugin, tmpl := range pluginAndTmpls {
if plugin.PluginType() == TypePluginKubeflow {
err = m.GetKubeCli().RemoveKubeflow(m.GetKubeConfig(), filepath.Join(m.HostDir(), tmpl.Filename()))
}
}
return err

}
1 change: 1 addition & 0 deletions pkg/template/fs/memfs.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io/fs"

"github.com/footprintai/multikf/pkg/template"

//log "github.com/golang/glog"
"github.com/spf13/afero"
)
Expand Down