Merge pull request #28164 from anusha-ragunathan/plugin-build

Add plugin create functionality.
This commit is contained in:
Victor Vieux 2016-11-09 17:49:51 -08:00 committed by GitHub
commit 1a34843c0c
2 changed files with 126 additions and 0 deletions

View File

@ -28,6 +28,7 @@ func NewPluginCommand(dockerCli *command.DockerCli) *cobra.Command {
newRemoveCommand(dockerCli), newRemoveCommand(dockerCli),
newSetCommand(dockerCli), newSetCommand(dockerCli),
newPushCommand(dockerCli), newPushCommand(dockerCli),
newCreateCommand(dockerCli),
) )
return cmd return cmd
} }

125
command/plugin/create.go Normal file
View File

@ -0,0 +1,125 @@
package plugin
import (
"encoding/json"
"fmt"
"io"
"os"
"path/filepath"
"github.com/Sirupsen/logrus"
"github.com/docker/docker/api/types"
"github.com/docker/docker/cli"
"github.com/docker/docker/cli/command"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/reference"
"github.com/spf13/cobra"
"golang.org/x/net/context"
)
// validateTag checks if the given repoName can be resolved.
func validateTag(rawRepo string) error {
_, err := reference.ParseNamed(rawRepo)
return err
}
// validateManifest ensures that a valid manifest.json is available in the given path
func validateManifest(path string) error {
dt, err := os.Open(filepath.Join(path, "manifest.json"))
if err != nil {
return err
}
m := types.PluginManifest{}
err = json.NewDecoder(dt).Decode(&m)
dt.Close()
return err
}
// validateContextDir validates the given dir and returns abs path on success.
func validateContextDir(contextDir string) (string, error) {
absContextDir, err := filepath.Abs(contextDir)
stat, err := os.Lstat(absContextDir)
if err != nil {
return "", err
}
if !stat.IsDir() {
return "", fmt.Errorf("context must be a directory")
}
return absContextDir, nil
}
type pluginCreateOptions struct {
repoName string
context string
compress bool
}
func newCreateCommand(dockerCli *command.DockerCli) *cobra.Command {
options := pluginCreateOptions{}
cmd := &cobra.Command{
Use: "create [OPTIONS] reponame[:tag] PATH-TO-ROOTFS (rootfs + manifest.json)",
Short: "Create a plugin from a rootfs and manifest",
Args: cli.RequiresMinArgs(2),
RunE: func(cmd *cobra.Command, args []string) error {
options.repoName = args[0]
options.context = args[1]
return runCreate(dockerCli, options)
},
}
flags := cmd.Flags()
flags.BoolVar(&options.compress, "compress", false, "Compress the context using gzip")
return cmd
}
func runCreate(dockerCli *command.DockerCli, options pluginCreateOptions) error {
var (
createCtx io.ReadCloser
err error
)
if err := validateTag(options.repoName); err != nil {
return err
}
absContextDir, err := validateContextDir(options.context)
if err != nil {
return err
}
if err := validateManifest(options.context); err != nil {
return err
}
compression := archive.Uncompressed
if options.compress {
logrus.Debugf("compression enabled")
compression = archive.Gzip
}
createCtx, err = archive.TarWithOptions(absContextDir, &archive.TarOptions{
Compression: compression,
})
if err != nil {
return err
}
ctx := context.Background()
createOptions := types.PluginCreateOptions{RepoName: options.repoName}
if err = dockerCli.Client().PluginCreate(ctx, createCtx, createOptions); err != nil {
return err
}
fmt.Fprintln(dockerCli.Out(), options.repoName)
return nil
}