diff --git a/cmd/image/image.go b/cmd/image/image.go new file mode 100644 index 00000000..87465c30 --- /dev/null +++ b/cmd/image/image.go @@ -0,0 +1,52 @@ +/* +Copyright © 2020 The k3d Author(s) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +package image + +import ( + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +// NewCmdImage returns a new cobra command +func NewCmdImage() *cobra.Command { + + // create new cobra command + cmd := &cobra.Command{ + Use: "image", + Short: "Handle container images.", + Long: `Handle container images.`, + Run: func(cmd *cobra.Command, args []string) { + if err := cmd.Help(); err != nil { + log.Errorln("Couldn't get help text") + log.Fatalln(err) + } + }, + } + + // add subcommands + cmd.AddCommand(NewCmdImageImport()) + + // add flags + + // done + return cmd +} diff --git a/cmd/image/imageImport.go b/cmd/image/imageImport.go new file mode 100644 index 00000000..8b50b6a2 --- /dev/null +++ b/cmd/image/imageImport.go @@ -0,0 +1,97 @@ +/* +Copyright © 2020 The k3d Author(s) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +package image + +import ( + "github.com/spf13/cobra" + + "github.com/rancher/k3d/v3/cmd/util" + "github.com/rancher/k3d/v3/pkg/runtimes" + "github.com/rancher/k3d/v3/pkg/tools" + k3d "github.com/rancher/k3d/v3/pkg/types" + + log "github.com/sirupsen/logrus" +) + +// NewCmdImageImport returns a new cobra command +func NewCmdImageImport() *cobra.Command { + + loadImageOpts := k3d.LoadImageOpts{} + + // create new command + cmd := &cobra.Command{ + Use: "import [IMAGE | ARCHIVE [IMAGE | ARCHIVE...]]", + Short: "Import image(s) from docker into k3d cluster(s).", + Long: `Import image(s) from docker into k3d cluster(s).`, + Aliases: []string{"images"}, + Args: cobra.MinimumNArgs(1), + Run: func(cmd *cobra.Command, args []string) { + images, clusters := parseLoadImageCmd(cmd, args) + log.Debugf("Load images [%+v] from runtime [%s] into clusters [%+v]", images, runtimes.SelectedRuntime, clusters) + for _, cluster := range clusters { + log.Infof("Loading images into '%s'", cluster.Name) + if err := tools.LoadImagesIntoCluster(cmd.Context(), runtimes.SelectedRuntime, images, &cluster, loadImageOpts); err != nil { + log.Errorf("Failed to load images into cluster '%s'", cluster.Name) + log.Errorln(err) + } + } + log.Info("DONE") + }, + } + + /********* + * Flags * + *********/ + cmd.Flags().StringArrayP("cluster", "c", []string{k3d.DefaultClusterName}, "Select clusters to load the image to.") + if err := cmd.RegisterFlagCompletionFunc("cluster", util.ValidArgsAvailableClusters); err != nil { + log.Fatalln("Failed to register flag completion for '--cluster'", err) + } + + cmd.Flags().BoolVarP(&loadImageOpts.KeepTar, "keep-tarball", "k", false, "Do not delete the tarball containing the saved images from the shared volume") + + /* Subcommands */ + + // done + return cmd +} + +// parseLoadImageCmd parses the command input into variables required to create a cluster +func parseLoadImageCmd(cmd *cobra.Command, args []string) ([]string, []k3d.Cluster) { + + // --cluster + clusterNames, err := cmd.Flags().GetStringArray("cluster") + if err != nil { + log.Fatalln(err) + } + clusters := []k3d.Cluster{} + for _, clusterName := range clusterNames { + clusters = append(clusters, k3d.Cluster{Name: clusterName}) + } + + // images + images := args + if len(images) == 0 { + log.Fatalln("No images specified!") + } + + return images, clusters +} diff --git a/cmd/root.go b/cmd/root.go index 3a0e4c37..63532686 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -34,6 +34,7 @@ import ( "github.com/rancher/k3d/v3/cmd/create" "github.com/rancher/k3d/v3/cmd/delete" "github.com/rancher/k3d/v3/cmd/get" + "github.com/rancher/k3d/v3/cmd/image" "github.com/rancher/k3d/v3/cmd/kubeconfig" "github.com/rancher/k3d/v3/cmd/load" "github.com/rancher/k3d/v3/cmd/node" @@ -94,18 +95,19 @@ func init() { rootCmd.Flags().BoolVar(&flags.version, "version", false, "Show k3d and default k3s version") // add subcommands - rootCmd.AddCommand(NewCmdCompletion()) - rootCmd.AddCommand(create.NewCmdCreate()) - rootCmd.AddCommand(delete.NewCmdDelete()) - rootCmd.AddCommand(get.NewCmdGet()) - rootCmd.AddCommand(stop.NewCmdStop()) - rootCmd.AddCommand(start.NewCmdStart()) - rootCmd.AddCommand(load.NewCmdLoad()) - if os.Getenv("K3D_NEW_SYNTAX") == "1" { rootCmd.AddCommand(cluster.NewCmdCluster()) rootCmd.AddCommand(kubeconfig.NewCmdKubeconfig()) rootCmd.AddCommand(node.NewCmdNode()) + rootCmd.AddCommand(image.NewCmdImage()) + } else { + rootCmd.AddCommand(NewCmdCompletion()) + rootCmd.AddCommand(create.NewCmdCreate()) + rootCmd.AddCommand(delete.NewCmdDelete()) + rootCmd.AddCommand(get.NewCmdGet()) + rootCmd.AddCommand(stop.NewCmdStop()) + rootCmd.AddCommand(start.NewCmdStart()) + rootCmd.AddCommand(load.NewCmdLoad()) } rootCmd.AddCommand(&cobra.Command{