Remove cmd/docker and other directories in cli/ in accordance with the new Moby project scope

Starting with this commit, integration tests should no longer rely on
the docker cli, they should be API tests instead. For the existing tests
the scripts will use a frozen version of the docker cli with a
DOCKER_API_VERSION frozen to 1.30, which should ensure that the CI remains
green at all times.

To help contributors develop and test manually with a modified docker
cli, this commit also adds a DOCKER_CLI_PATH environment variable to the
Makefile. This allows to set the path of a custom cli that will be
available inside the development container and used to run the
integration tests.

Signed-off-by: Arnaud Porterie (icecrime) <arnaud.porterie@docker.com>
Signed-off-by: Tibor Vass <tibor@docker.com>
This commit is contained in:
Arnaud Porterie (icecrime) 2017-04-17 18:18:46 -05:00 committed by Tibor Vass
parent 0808cf04cb
commit 3e911ff825
3 changed files with 0 additions and 302 deletions

View File

@ -1,4 +0,0 @@
FROM scratch
COPY docs /docs
# CMD cannot be nil so we set it to empty string
CMD [""]

View File

@ -1,86 +0,0 @@
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"github.com/docker/docker/cli/command"
"github.com/docker/docker/cli/command/commands"
"github.com/docker/docker/pkg/term"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)
const descriptionSourcePath = "docs/reference/commandline/"
func generateCliYaml(opts *options) error {
stdin, stdout, stderr := term.StdStreams()
dockerCli := command.NewDockerCli(stdin, stdout, stderr)
cmd := &cobra.Command{Use: "docker"}
commands.AddCommands(cmd, dockerCli)
source := filepath.Join(opts.source, descriptionSourcePath)
if err := loadLongDescription(cmd, source); err != nil {
return err
}
cmd.DisableAutoGenTag = true
return GenYamlTree(cmd, opts.target)
}
func loadLongDescription(cmd *cobra.Command, path ...string) error {
for _, cmd := range cmd.Commands() {
if cmd.Name() == "" {
continue
}
fullpath := filepath.Join(path[0], strings.Join(append(path[1:], cmd.Name()), "_")+".md")
if cmd.HasSubCommands() {
loadLongDescription(cmd, path[0], cmd.Name())
}
if _, err := os.Stat(fullpath); err != nil {
log.Printf("WARN: %s does not exist, skipping\n", fullpath)
continue
}
content, err := ioutil.ReadFile(fullpath)
if err != nil {
return err
}
description, examples := parseMDContent(string(content))
cmd.Long = description
cmd.Example = examples
}
return nil
}
type options struct {
source string
target string
}
func parseArgs() (*options, error) {
opts := &options{}
cwd, _ := os.Getwd()
flags := pflag.NewFlagSet(os.Args[0], pflag.ContinueOnError)
flags.StringVar(&opts.source, "root", cwd, "Path to project root")
flags.StringVar(&opts.target, "target", "/tmp", "Target path for generated yaml files")
err := flags.Parse(os.Args[1:])
return opts, err
}
func main() {
opts, err := parseArgs()
if err != nil {
fmt.Fprintln(os.Stderr, err.Error())
}
fmt.Printf("Project root: %s\n", opts.source)
fmt.Printf("Generating yaml files into %s\n", opts.target)
if err := generateCliYaml(opts); err != nil {
fmt.Fprintf(os.Stderr, "Failed to generate yaml files: %s\n", err.Error())
}
}

View File

@ -1,212 +0,0 @@
package main
import (
"fmt"
"io"
"os"
"path/filepath"
"sort"
"strings"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"gopkg.in/yaml.v2"
)
type cmdOption struct {
Option string
Shorthand string `yaml:",omitempty"`
DefaultValue string `yaml:"default_value,omitempty"`
Description string `yaml:",omitempty"`
}
type cmdDoc struct {
Name string `yaml:"command"`
SeeAlso []string `yaml:"parent,omitempty"`
Version string `yaml:"engine_version,omitempty"`
Aliases string `yaml:",omitempty"`
Short string `yaml:",omitempty"`
Long string `yaml:",omitempty"`
Usage string `yaml:",omitempty"`
Pname string `yaml:",omitempty"`
Plink string `yaml:",omitempty"`
Cname []string `yaml:",omitempty"`
Clink []string `yaml:",omitempty"`
Options []cmdOption `yaml:",omitempty"`
InheritedOptions []cmdOption `yaml:"inherited_options,omitempty"`
Example string `yaml:"examples,omitempty"`
}
// GenYamlTree creates yaml structured ref files
func GenYamlTree(cmd *cobra.Command, dir string) error {
identity := func(s string) string { return s }
emptyStr := func(s string) string { return "" }
return GenYamlTreeCustom(cmd, dir, emptyStr, identity)
}
// GenYamlTreeCustom creates yaml structured ref files
func GenYamlTreeCustom(cmd *cobra.Command, dir string, filePrepender, linkHandler func(string) string) error {
for _, c := range cmd.Commands() {
if !c.IsAvailableCommand() || c.IsHelpCommand() {
continue
}
if err := GenYamlTreeCustom(c, dir, filePrepender, linkHandler); err != nil {
return err
}
}
basename := strings.Replace(cmd.CommandPath(), " ", "_", -1) + ".yaml"
filename := filepath.Join(dir, basename)
f, err := os.Create(filename)
if err != nil {
return err
}
defer f.Close()
if _, err := io.WriteString(f, filePrepender(filename)); err != nil {
return err
}
if err := GenYamlCustom(cmd, f, linkHandler); err != nil {
return err
}
return nil
}
// GenYamlCustom creates custom yaml output
func GenYamlCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error {
cliDoc := cmdDoc{}
cliDoc.Name = cmd.CommandPath()
// Check experimental: ok := cmd.Tags["experimental"]
cliDoc.Aliases = strings.Join(cmd.Aliases, ", ")
cliDoc.Short = cmd.Short
cliDoc.Long = cmd.Long
if len(cliDoc.Long) == 0 {
cliDoc.Long = cliDoc.Short
}
if cmd.Runnable() {
cliDoc.Usage = cmd.UseLine()
}
if len(cmd.Example) > 0 {
cliDoc.Example = cmd.Example
}
flags := cmd.NonInheritedFlags()
if flags.HasFlags() {
cliDoc.Options = genFlagResult(flags)
}
flags = cmd.InheritedFlags()
if flags.HasFlags() {
cliDoc.InheritedOptions = genFlagResult(flags)
}
if hasSeeAlso(cmd) {
if cmd.HasParent() {
parent := cmd.Parent()
cliDoc.Pname = parent.CommandPath()
link := cliDoc.Pname + ".yaml"
cliDoc.Plink = strings.Replace(link, " ", "_", -1)
cmd.VisitParents(func(c *cobra.Command) {
if c.DisableAutoGenTag {
cmd.DisableAutoGenTag = c.DisableAutoGenTag
}
})
}
children := cmd.Commands()
sort.Sort(byName(children))
for _, child := range children {
if !child.IsAvailableCommand() || child.IsHelpCommand() {
continue
}
currentChild := cliDoc.Name + " " + child.Name()
cliDoc.Cname = append(cliDoc.Cname, cliDoc.Name+" "+child.Name())
link := currentChild + ".yaml"
cliDoc.Clink = append(cliDoc.Clink, strings.Replace(link, " ", "_", -1))
}
}
final, err := yaml.Marshal(&cliDoc)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if _, err := fmt.Fprintln(w, string(final)); err != nil {
return err
}
return nil
}
func genFlagResult(flags *pflag.FlagSet) []cmdOption {
var result []cmdOption
flags.VisitAll(func(flag *pflag.Flag) {
// Todo, when we mark a shorthand is deprecated, but specify an empty message.
// The flag.ShorthandDeprecated is empty as the shorthand is deprecated.
// Using len(flag.ShorthandDeprecated) > 0 can't handle this, others are ok.
if !(len(flag.ShorthandDeprecated) > 0) && len(flag.Shorthand) > 0 {
opt := cmdOption{
Option: flag.Name,
Shorthand: flag.Shorthand,
DefaultValue: flag.DefValue,
Description: forceMultiLine(flag.Usage),
}
result = append(result, opt)
} else {
opt := cmdOption{
Option: flag.Name,
DefaultValue: forceMultiLine(flag.DefValue),
Description: forceMultiLine(flag.Usage),
}
result = append(result, opt)
}
})
return result
}
// Temporary workaround for yaml lib generating incorrect yaml with long strings
// that do not contain \n.
func forceMultiLine(s string) string {
if len(s) > 60 && !strings.Contains(s, "\n") {
s = s + "\n"
}
return s
}
// Small duplication for cobra utils
func hasSeeAlso(cmd *cobra.Command) bool {
if cmd.HasParent() {
return true
}
for _, c := range cmd.Commands() {
if !c.IsAvailableCommand() || c.IsHelpCommand() {
continue
}
return true
}
return false
}
func parseMDContent(mdString string) (description string, examples string) {
parsedContent := strings.Split(mdString, "\n## ")
for _, s := range parsedContent {
if strings.Index(s, "Description") == 0 {
description = strings.Trim(s, "Description\n")
}
if strings.Index(s, "Examples") == 0 {
examples = strings.Trim(s, "Examples\n")
}
}
return
}
type byName []*cobra.Command
func (s byName) Len() int { return len(s) }
func (s byName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() }