Merge pull request #14790 from hqhq/hq_golint_build

Fix golint warnings for builder
This commit is contained in:
Alexander Morozov 2015-07-22 08:17:04 -07:00
commit a751c0a52f
13 changed files with 131 additions and 107 deletions

View File

@ -688,7 +688,7 @@ func (s *Server) postCommit(version version.Version, w http.ResponseWriter, r *h
return err return err
} }
commitCfg := &builder.BuilderCommitConfig{ commitCfg := &builder.CommitConfig{
Pause: pause, Pause: pause,
Repo: r.Form.Get("repo"), Repo: r.Form.Get("repo"),
Tag: r.Form.Get("tag"), Tag: r.Form.Get("tag"),
@ -1276,11 +1276,11 @@ func (s *Server) postBuild(version version.Version, w http.ResponseWriter, r *ht
buildConfig.AuthConfigs = authConfigs buildConfig.AuthConfigs = authConfigs
buildConfig.MemorySwap = int64ValueOrZero(r, "memswap") buildConfig.MemorySwap = int64ValueOrZero(r, "memswap")
buildConfig.Memory = int64ValueOrZero(r, "memory") buildConfig.Memory = int64ValueOrZero(r, "memory")
buildConfig.CpuShares = int64ValueOrZero(r, "cpushares") buildConfig.CPUShares = int64ValueOrZero(r, "cpushares")
buildConfig.CpuPeriod = int64ValueOrZero(r, "cpuperiod") buildConfig.CPUPeriod = int64ValueOrZero(r, "cpuperiod")
buildConfig.CpuQuota = int64ValueOrZero(r, "cpuquota") buildConfig.CPUQuota = int64ValueOrZero(r, "cpuquota")
buildConfig.CpuSetCpus = r.FormValue("cpusetcpus") buildConfig.CPUSetCpus = r.FormValue("cpusetcpus")
buildConfig.CpuSetMems = r.FormValue("cpusetmems") buildConfig.CPUSetMems = r.FormValue("cpusetmems")
buildConfig.CgroupParent = r.FormValue("cgroupparent") buildConfig.CgroupParent = r.FormValue("cgroupparent")
// Job cancellation. Note: not all job types support this. // Job cancellation. Note: not all job types support this.

View File

@ -5,6 +5,7 @@ import (
"strings" "strings"
) )
// FlagType is the type of the build flag
type FlagType int type FlagType int
const ( const (
@ -12,28 +13,32 @@ const (
stringType stringType
) )
type BuilderFlags struct { // BFlags contains all flags information for the builder
type BFlags struct {
Args []string // actual flags/args from cmd line Args []string // actual flags/args from cmd line
flags map[string]*Flag flags map[string]*Flag
used map[string]*Flag used map[string]*Flag
Err error Err error
} }
// Flag contains all information for a flag
type Flag struct { type Flag struct {
bf *BuilderFlags bf *BFlags
name string name string
flagType FlagType flagType FlagType
Value string Value string
} }
func NewBuilderFlags() *BuilderFlags { // NewBFlags return the new BFlags struct
return &BuilderFlags{ func NewBFlags() *BFlags {
return &BFlags{
flags: make(map[string]*Flag), flags: make(map[string]*Flag),
used: make(map[string]*Flag), used: make(map[string]*Flag),
} }
} }
func (bf *BuilderFlags) AddBool(name string, def bool) *Flag { // AddBool adds a bool flag to BFlags
func (bf *BFlags) AddBool(name string, def bool) *Flag {
flag := bf.addFlag(name, boolType) flag := bf.addFlag(name, boolType)
if flag == nil { if flag == nil {
return nil return nil
@ -46,7 +51,8 @@ func (bf *BuilderFlags) AddBool(name string, def bool) *Flag {
return flag return flag
} }
func (bf *BuilderFlags) AddString(name string, def string) *Flag { // AddString adds a string flag to BFlags
func (bf *BFlags) AddString(name string, def string) *Flag {
flag := bf.addFlag(name, stringType) flag := bf.addFlag(name, stringType)
if flag == nil { if flag == nil {
return nil return nil
@ -55,7 +61,7 @@ func (bf *BuilderFlags) AddString(name string, def string) *Flag {
return flag return flag
} }
func (bf *BuilderFlags) addFlag(name string, flagType FlagType) *Flag { func (bf *BFlags) addFlag(name string, flagType FlagType) *Flag {
if _, ok := bf.flags[name]; ok { if _, ok := bf.flags[name]; ok {
bf.Err = fmt.Errorf("Duplicate flag defined: %s", name) bf.Err = fmt.Errorf("Duplicate flag defined: %s", name)
return nil return nil
@ -71,6 +77,7 @@ func (bf *BuilderFlags) addFlag(name string, flagType FlagType) *Flag {
return newFlag return newFlag
} }
// IsUsed checks if the flag is used
func (fl *Flag) IsUsed() bool { func (fl *Flag) IsUsed() bool {
if _, ok := fl.bf.used[fl.name]; ok { if _, ok := fl.bf.used[fl.name]; ok {
return true return true
@ -78,6 +85,7 @@ func (fl *Flag) IsUsed() bool {
return false return false
} }
// IsTrue checks if a bool flag is true
func (fl *Flag) IsTrue() bool { func (fl *Flag) IsTrue() bool {
if fl.flagType != boolType { if fl.flagType != boolType {
// Should never get here // Should never get here
@ -86,7 +94,8 @@ func (fl *Flag) IsTrue() bool {
return fl.Value == "true" return fl.Value == "true"
} }
func (bf *BuilderFlags) Parse() error { // Parse parses and checks if the BFlags is valid
func (bf *BFlags) Parse() error {
// If there was an error while defining the possible flags // If there was an error while defining the possible flags
// go ahead and bubble it back up here since we didn't do it // go ahead and bubble it back up here since we didn't do it
// earlier in the processing // earlier in the processing

View File

@ -10,7 +10,7 @@ func TestBuilderFlags(t *testing.T) {
// --- // ---
bf := NewBuilderFlags() bf := NewBFlags()
bf.Args = []string{} bf.Args = []string{}
if err := bf.Parse(); err != nil { if err := bf.Parse(); err != nil {
t.Fatalf("Test1 of %q was supposed to work: %s", bf.Args, err) t.Fatalf("Test1 of %q was supposed to work: %s", bf.Args, err)
@ -18,7 +18,7 @@ func TestBuilderFlags(t *testing.T) {
// --- // ---
bf = NewBuilderFlags() bf = NewBFlags()
bf.Args = []string{"--"} bf.Args = []string{"--"}
if err := bf.Parse(); err != nil { if err := bf.Parse(); err != nil {
t.Fatalf("Test2 of %q was supposed to work: %s", bf.Args, err) t.Fatalf("Test2 of %q was supposed to work: %s", bf.Args, err)
@ -26,7 +26,7 @@ func TestBuilderFlags(t *testing.T) {
// --- // ---
bf = NewBuilderFlags() bf = NewBFlags()
flStr1 := bf.AddString("str1", "") flStr1 := bf.AddString("str1", "")
flBool1 := bf.AddBool("bool1", false) flBool1 := bf.AddBool("bool1", false)
bf.Args = []string{} bf.Args = []string{}
@ -43,7 +43,7 @@ func TestBuilderFlags(t *testing.T) {
// --- // ---
bf = NewBuilderFlags() bf = NewBFlags()
flStr1 = bf.AddString("str1", "HI") flStr1 = bf.AddString("str1", "HI")
flBool1 = bf.AddBool("bool1", false) flBool1 = bf.AddBool("bool1", false)
bf.Args = []string{} bf.Args = []string{}
@ -67,7 +67,7 @@ func TestBuilderFlags(t *testing.T) {
// --- // ---
bf = NewBuilderFlags() bf = NewBFlags()
flStr1 = bf.AddString("str1", "HI") flStr1 = bf.AddString("str1", "HI")
bf.Args = []string{"--str1"} bf.Args = []string{"--str1"}
@ -77,7 +77,7 @@ func TestBuilderFlags(t *testing.T) {
// --- // ---
bf = NewBuilderFlags() bf = NewBFlags()
flStr1 = bf.AddString("str1", "HI") flStr1 = bf.AddString("str1", "HI")
bf.Args = []string{"--str1="} bf.Args = []string{"--str1="}
@ -92,7 +92,7 @@ func TestBuilderFlags(t *testing.T) {
// --- // ---
bf = NewBuilderFlags() bf = NewBFlags()
flStr1 = bf.AddString("str1", "HI") flStr1 = bf.AddString("str1", "HI")
bf.Args = []string{"--str1=BYE"} bf.Args = []string{"--str1=BYE"}
@ -107,7 +107,7 @@ func TestBuilderFlags(t *testing.T) {
// --- // ---
bf = NewBuilderFlags() bf = NewBFlags()
flBool1 = bf.AddBool("bool1", false) flBool1 = bf.AddBool("bool1", false)
bf.Args = []string{"--bool1"} bf.Args = []string{"--bool1"}
@ -121,7 +121,7 @@ func TestBuilderFlags(t *testing.T) {
// --- // ---
bf = NewBuilderFlags() bf = NewBFlags()
flBool1 = bf.AddBool("bool1", false) flBool1 = bf.AddBool("bool1", false)
bf.Args = []string{"--bool1=true"} bf.Args = []string{"--bool1=true"}
@ -135,7 +135,7 @@ func TestBuilderFlags(t *testing.T) {
// --- // ---
bf = NewBuilderFlags() bf = NewBFlags()
flBool1 = bf.AddBool("bool1", false) flBool1 = bf.AddBool("bool1", false)
bf.Args = []string{"--bool1=false"} bf.Args = []string{"--bool1=false"}
@ -149,7 +149,7 @@ func TestBuilderFlags(t *testing.T) {
// --- // ---
bf = NewBuilderFlags() bf = NewBFlags()
flBool1 = bf.AddBool("bool1", false) flBool1 = bf.AddBool("bool1", false)
bf.Args = []string{"--bool1=false1"} bf.Args = []string{"--bool1=false1"}
@ -159,7 +159,7 @@ func TestBuilderFlags(t *testing.T) {
// --- // ---
bf = NewBuilderFlags() bf = NewBFlags()
flBool1 = bf.AddBool("bool1", false) flBool1 = bf.AddBool("bool1", false)
bf.Args = []string{"--bool2"} bf.Args = []string{"--bool2"}
@ -169,7 +169,7 @@ func TestBuilderFlags(t *testing.T) {
// --- // ---
bf = NewBuilderFlags() bf = NewBFlags()
flStr1 = bf.AddString("str1", "HI") flStr1 = bf.AddString("str1", "HI")
flBool1 = bf.AddBool("bool1", false) flBool1 = bf.AddBool("bool1", false)
bf.Args = []string{"--bool1", "--str1=BYE"} bf.Args = []string{"--bool1", "--str1=BYE"}

View File

@ -1,6 +1,7 @@
// This package contains the set of Dockerfile commands. // Package command contains the set of Dockerfile commands.
package command package command
// Define constants for the command strings
const ( const (
Env = "env" Env = "env"
Label = "label" Label = "label"

View File

@ -30,7 +30,7 @@ const (
) )
// dispatch with no layer / parsing. This is effectively not a command. // dispatch with no layer / parsing. This is effectively not a command.
func nullDispatch(b *Builder, args []string, attributes map[string]bool, original string) error { func nullDispatch(b *builder, args []string, attributes map[string]bool, original string) error {
return nil return nil
} }
@ -39,7 +39,7 @@ func nullDispatch(b *Builder, args []string, attributes map[string]bool, origina
// Sets the environment variable foo to bar, also makes interpolation // Sets the environment variable foo to bar, also makes interpolation
// in the dockerfile available from the next statement on via ${foo}. // in the dockerfile available from the next statement on via ${foo}.
// //
func env(b *Builder, args []string, attributes map[string]bool, original string) error { func env(b *builder, args []string, attributes map[string]bool, original string) error {
if len(args) == 0 { if len(args) == 0 {
return fmt.Errorf("ENV requires at least one argument") return fmt.Errorf("ENV requires at least one argument")
} }
@ -98,7 +98,7 @@ func env(b *Builder, args []string, attributes map[string]bool, original string)
// MAINTAINER some text <maybe@an.email.address> // MAINTAINER some text <maybe@an.email.address>
// //
// Sets the maintainer metadata. // Sets the maintainer metadata.
func maintainer(b *Builder, args []string, attributes map[string]bool, original string) error { func maintainer(b *builder, args []string, attributes map[string]bool, original string) error {
if len(args) != 1 { if len(args) != 1 {
return fmt.Errorf("MAINTAINER requires exactly one argument") return fmt.Errorf("MAINTAINER requires exactly one argument")
} }
@ -115,7 +115,7 @@ func maintainer(b *Builder, args []string, attributes map[string]bool, original
// //
// Sets the Label variable foo to bar, // Sets the Label variable foo to bar,
// //
func label(b *Builder, args []string, attributes map[string]bool, original string) error { func label(b *builder, args []string, attributes map[string]bool, original string) error {
if len(args) == 0 { if len(args) == 0 {
return fmt.Errorf("LABEL requires at least one argument") return fmt.Errorf("LABEL requires at least one argument")
} }
@ -151,7 +151,7 @@ func label(b *Builder, args []string, attributes map[string]bool, original strin
// Add the file 'foo' to '/path'. Tarball and Remote URL (git, http) handling // Add the file 'foo' to '/path'. Tarball and Remote URL (git, http) handling
// exist here. If you do not wish to have this automatic handling, use COPY. // exist here. If you do not wish to have this automatic handling, use COPY.
// //
func add(b *Builder, args []string, attributes map[string]bool, original string) error { func add(b *builder, args []string, attributes map[string]bool, original string) error {
if len(args) < 2 { if len(args) < 2 {
return fmt.Errorf("ADD requires at least two arguments") return fmt.Errorf("ADD requires at least two arguments")
} }
@ -167,7 +167,7 @@ func add(b *Builder, args []string, attributes map[string]bool, original string)
// //
// Same as 'ADD' but without the tar and remote url handling. // Same as 'ADD' but without the tar and remote url handling.
// //
func dispatchCopy(b *Builder, args []string, attributes map[string]bool, original string) error { func dispatchCopy(b *builder, args []string, attributes map[string]bool, original string) error {
if len(args) < 2 { if len(args) < 2 {
return fmt.Errorf("COPY requires at least two arguments") return fmt.Errorf("COPY requires at least two arguments")
} }
@ -183,7 +183,7 @@ func dispatchCopy(b *Builder, args []string, attributes map[string]bool, origina
// //
// This sets the image the dockerfile will build on top of. // This sets the image the dockerfile will build on top of.
// //
func from(b *Builder, args []string, attributes map[string]bool, original string) error { func from(b *builder, args []string, attributes map[string]bool, original string) error {
if len(args) != 1 { if len(args) != 1 {
return fmt.Errorf("FROM requires one argument") return fmt.Errorf("FROM requires one argument")
} }
@ -231,7 +231,7 @@ func from(b *Builder, args []string, attributes map[string]bool, original string
// special cases. search for 'OnBuild' in internals.go for additional special // special cases. search for 'OnBuild' in internals.go for additional special
// cases. // cases.
// //
func onbuild(b *Builder, args []string, attributes map[string]bool, original string) error { func onbuild(b *builder, args []string, attributes map[string]bool, original string) error {
if len(args) == 0 { if len(args) == 0 {
return fmt.Errorf("ONBUILD requires at least one argument") return fmt.Errorf("ONBUILD requires at least one argument")
} }
@ -258,7 +258,7 @@ func onbuild(b *Builder, args []string, attributes map[string]bool, original str
// //
// Set the working directory for future RUN/CMD/etc statements. // Set the working directory for future RUN/CMD/etc statements.
// //
func workdir(b *Builder, args []string, attributes map[string]bool, original string) error { func workdir(b *builder, args []string, attributes map[string]bool, original string) error {
if len(args) != 1 { if len(args) != 1 {
return fmt.Errorf("WORKDIR requires exactly one argument") return fmt.Errorf("WORKDIR requires exactly one argument")
} }
@ -315,7 +315,7 @@ func workdir(b *Builder, args []string, attributes map[string]bool, original str
// RUN echo hi # cmd /S /C echo hi (Windows) // RUN echo hi # cmd /S /C echo hi (Windows)
// RUN [ "echo", "hi" ] # echo hi // RUN [ "echo", "hi" ] # echo hi
// //
func run(b *Builder, args []string, attributes map[string]bool, original string) error { func run(b *builder, args []string, attributes map[string]bool, original string) error {
if b.image == "" && !b.noBaseImage { if b.image == "" && !b.noBaseImage {
return fmt.Errorf("Please provide a source image with `from` prior to run") return fmt.Errorf("Please provide a source image with `from` prior to run")
} }
@ -324,7 +324,7 @@ func run(b *Builder, args []string, attributes map[string]bool, original string)
return err return err
} }
args = handleJsonArgs(args, attributes) args = handleJSONArgs(args, attributes)
if !attributes["json"] { if !attributes["json"] {
if runtime.GOOS != "windows" { if runtime.GOOS != "windows" {
@ -386,12 +386,12 @@ func run(b *Builder, args []string, attributes map[string]bool, original string)
// Set the default command to run in the container (which may be empty). // Set the default command to run in the container (which may be empty).
// Argument handling is the same as RUN. // Argument handling is the same as RUN.
// //
func cmd(b *Builder, args []string, attributes map[string]bool, original string) error { func cmd(b *builder, args []string, attributes map[string]bool, original string) error {
if err := b.BuilderFlags.Parse(); err != nil { if err := b.BuilderFlags.Parse(); err != nil {
return err return err
} }
cmdSlice := handleJsonArgs(args, attributes) cmdSlice := handleJSONArgs(args, attributes)
if !attributes["json"] { if !attributes["json"] {
if runtime.GOOS != "windows" { if runtime.GOOS != "windows" {
@ -422,12 +422,12 @@ func cmd(b *Builder, args []string, attributes map[string]bool, original string)
// Handles command processing similar to CMD and RUN, only b.Config.Entrypoint // Handles command processing similar to CMD and RUN, only b.Config.Entrypoint
// is initialized at NewBuilder time instead of through argument parsing. // is initialized at NewBuilder time instead of through argument parsing.
// //
func entrypoint(b *Builder, args []string, attributes map[string]bool, original string) error { func entrypoint(b *builder, args []string, attributes map[string]bool, original string) error {
if err := b.BuilderFlags.Parse(); err != nil { if err := b.BuilderFlags.Parse(); err != nil {
return err return err
} }
parsed := handleJsonArgs(args, attributes) parsed := handleJSONArgs(args, attributes)
switch { switch {
case attributes["json"]: case attributes["json"]:
@ -463,7 +463,7 @@ func entrypoint(b *Builder, args []string, attributes map[string]bool, original
// Expose ports for links and port mappings. This all ends up in // Expose ports for links and port mappings. This all ends up in
// b.Config.ExposedPorts for runconfig. // b.Config.ExposedPorts for runconfig.
// //
func expose(b *Builder, args []string, attributes map[string]bool, original string) error { func expose(b *builder, args []string, attributes map[string]bool, original string) error {
portsTab := args portsTab := args
if len(args) == 0 { if len(args) == 0 {
@ -504,9 +504,9 @@ func expose(b *Builder, args []string, attributes map[string]bool, original stri
// Set the user to 'foo' for future commands and when running the // Set the user to 'foo' for future commands and when running the
// ENTRYPOINT/CMD at container run time. // ENTRYPOINT/CMD at container run time.
// //
func user(b *Builder, args []string, attributes map[string]bool, original string) error { func user(b *builder, args []string, attributes map[string]bool, original string) error {
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
return fmt.Errorf("USER is not supported on Windows.") return fmt.Errorf("USER is not supported on Windows")
} }
if len(args) != 1 { if len(args) != 1 {
@ -525,9 +525,9 @@ func user(b *Builder, args []string, attributes map[string]bool, original string
// //
// Expose the volume /foo for use. Will also accept the JSON array form. // Expose the volume /foo for use. Will also accept the JSON array form.
// //
func volume(b *Builder, args []string, attributes map[string]bool, original string) error { func volume(b *builder, args []string, attributes map[string]bool, original string) error {
if runtime.GOOS == "windows" { if runtime.GOOS == "windows" {
return fmt.Errorf("VOLUME is not supported on Windows.") return fmt.Errorf("VOLUME is not supported on Windows")
} }
if len(args) == 0 { if len(args) == 0 {
return fmt.Errorf("VOLUME requires at least one argument") return fmt.Errorf("VOLUME requires at least one argument")

View File

@ -53,10 +53,10 @@ var replaceEnvAllowed = map[string]struct{}{
command.User: {}, command.User: {},
} }
var evaluateTable map[string]func(*Builder, []string, map[string]bool, string) error var evaluateTable map[string]func(*builder, []string, map[string]bool, string) error
func init() { func init() {
evaluateTable = map[string]func(*Builder, []string, map[string]bool, string) error{ evaluateTable = map[string]func(*builder, []string, map[string]bool, string) error{
command.Env: env, command.Env: env,
command.Label: label, command.Label: label,
command.Maintainer: maintainer, command.Maintainer: maintainer,
@ -74,9 +74,9 @@ func init() {
} }
} }
// internal struct, used to maintain configuration of the Dockerfile's // builder is an internal struct, used to maintain configuration of the Dockerfile's
// processing as it evaluates the parsing result. // processing as it evaluates the parsing result.
type Builder struct { type builder struct {
Daemon *daemon.Daemon Daemon *daemon.Daemon
// effectively stdio for the run. Because it is not stdio, I said // effectively stdio for the run. Because it is not stdio, I said
@ -115,7 +115,7 @@ type Builder struct {
image string // image name for commit processing image string // image name for commit processing
maintainer string // maintainer name. could probably be removed. maintainer string // maintainer name. could probably be removed.
cmdSet bool // indicates is CMD was set in current Dockerfile cmdSet bool // indicates is CMD was set in current Dockerfile
BuilderFlags *BuilderFlags // current cmd's BuilderFlags - temporary BuilderFlags *BFlags // current cmd's BuilderFlags - temporary
context tarsum.TarSum // the context is a tarball that is uploaded by the client context tarsum.TarSum // the context is a tarball that is uploaded by the client
contextPath string // the path of the temporary directory the local context is unpacked to (server side) contextPath string // the path of the temporary directory the local context is unpacked to (server side)
noBaseImage bool // indicates that this build does not start from any base image, but is being built from an empty file system. noBaseImage bool // indicates that this build does not start from any base image, but is being built from an empty file system.
@ -148,7 +148,7 @@ type Builder struct {
// processing. // processing.
// * Print a happy message and return the image ID. // * Print a happy message and return the image ID.
// //
func (b *Builder) Run(context io.Reader) (string, error) { func (b *builder) Run(context io.Reader) (string, error) {
if err := b.readContext(context); err != nil { if err := b.readContext(context); err != nil {
return "", err return "", err
} }
@ -199,7 +199,7 @@ func (b *Builder) Run(context io.Reader) (string, error) {
// Reads a Dockerfile from the current context. It assumes that the // Reads a Dockerfile from the current context. It assumes that the
// 'filename' is a relative path from the root of the context // 'filename' is a relative path from the root of the context
func (b *Builder) readDockerfile() error { func (b *builder) readDockerfile() error {
// If no -f was specified then look for 'Dockerfile'. If we can't find // If no -f was specified then look for 'Dockerfile'. If we can't find
// that then look for 'dockerfile'. If neither are found then default // that then look for 'dockerfile'. If neither are found then default
// back to 'Dockerfile' and use that in the error message. // back to 'Dockerfile' and use that in the error message.
@ -277,7 +277,7 @@ func (b *Builder) readDockerfile() error {
// such as `RUN` in ONBUILD RUN foo. There is special case logic in here to // such as `RUN` in ONBUILD RUN foo. There is special case logic in here to
// deal with that, at least until it becomes more of a general concern with new // deal with that, at least until it becomes more of a general concern with new
// features. // features.
func (b *Builder) dispatch(stepN int, ast *parser.Node) error { func (b *builder) dispatch(stepN int, ast *parser.Node) error {
cmd := ast.Value cmd := ast.Value
attrs := ast.Attributes attrs := ast.Attributes
original := ast.Original original := ast.Original
@ -340,7 +340,7 @@ func (b *Builder) dispatch(stepN int, ast *parser.Node) error {
// XXX yes, we skip any cmds that are not valid; the parser should have // XXX yes, we skip any cmds that are not valid; the parser should have
// picked these out already. // picked these out already.
if f, ok := evaluateTable[cmd]; ok { if f, ok := evaluateTable[cmd]; ok {
b.BuilderFlags = NewBuilderFlags() b.BuilderFlags = NewBFlags()
b.BuilderFlags.Args = flags b.BuilderFlags.Args = flags
return f(b, strList, attrs, original) return f(b, strList, attrs, original)
} }

View File

@ -40,7 +40,7 @@ import (
"github.com/docker/docker/runconfig" "github.com/docker/docker/runconfig"
) )
func (b *Builder) readContext(context io.Reader) (err error) { func (b *builder) readContext(context io.Reader) (err error) {
tmpdirPath, err := ioutil.TempDir("", "docker-build") tmpdirPath, err := ioutil.TempDir("", "docker-build")
if err != nil { if err != nil {
return return
@ -73,7 +73,7 @@ func (b *Builder) readContext(context io.Reader) (err error) {
return return
} }
func (b *Builder) commit(id string, autoCmd *runconfig.Command, comment string) error { func (b *builder) commit(id string, autoCmd *runconfig.Command, comment string) error {
if b.disableCommit { if b.disableCommit {
return nil return nil
} }
@ -143,7 +143,7 @@ type copyInfo struct {
tmpDir string tmpDir string
} }
func (b *Builder) runContextCommand(args []string, allowRemote bool, allowDecompression bool, cmdName string) error { func (b *builder) runContextCommand(args []string, allowRemote bool, allowDecompression bool, cmdName string) error {
if b.context == nil { if b.context == nil {
return fmt.Errorf("No context given. Impossible to use %s", cmdName) return fmt.Errorf("No context given. Impossible to use %s", cmdName)
} }
@ -261,7 +261,7 @@ func (b *Builder) runContextCommand(args []string, allowRemote bool, allowDecomp
return nil return nil
} }
func calcCopyInfo(b *Builder, cmdName string, cInfos *[]*copyInfo, origPath string, destPath string, allowRemote bool, allowDecompression bool, allowWildcards bool) error { func calcCopyInfo(b *builder, cmdName string, cInfos *[]*copyInfo, origPath string, destPath string, allowRemote bool, allowDecompression bool, allowWildcards bool) error {
// Work in daemon-specific OS filepath semantics. However, we save // Work in daemon-specific OS filepath semantics. However, we save
// the the origPath passed in here, as it might also be a URL which // the the origPath passed in here, as it might also be a URL which
@ -398,7 +398,7 @@ func calcCopyInfo(b *Builder, cmdName string, cInfos *[]*copyInfo, origPath stri
} }
// Deal with wildcards // Deal with wildcards
if allowWildcards && ContainsWildcards(origPath) { if allowWildcards && containsWildcards(origPath) {
for _, fileInfo := range b.context.GetSums() { for _, fileInfo := range b.context.GetSums() {
if fileInfo.Name() == "" { if fileInfo.Name() == "" {
continue continue
@ -475,7 +475,7 @@ func calcCopyInfo(b *Builder, cmdName string, cInfos *[]*copyInfo, origPath stri
return nil return nil
} }
func ContainsWildcards(name string) bool { func containsWildcards(name string) bool {
for i := 0; i < len(name); i++ { for i := 0; i < len(name); i++ {
ch := name[i] ch := name[i]
if ch == '\\' { if ch == '\\' {
@ -487,7 +487,7 @@ func ContainsWildcards(name string) bool {
return false return false
} }
func (b *Builder) pullImage(name string) (*image.Image, error) { func (b *builder) pullImage(name string) (*image.Image, error) {
remote, tag := parsers.ParseRepositoryTag(name) remote, tag := parsers.ParseRepositoryTag(name)
if tag == "" { if tag == "" {
tag = "latest" tag = "latest"
@ -525,7 +525,7 @@ func (b *Builder) pullImage(name string) (*image.Image, error) {
return image, nil return image, nil
} }
func (b *Builder) processImageFrom(img *image.Image) error { func (b *builder) processImageFrom(img *image.Image) error {
b.image = img.ID b.image = img.ID
if img.Config != nil { if img.Config != nil {
@ -577,7 +577,7 @@ func (b *Builder) processImageFrom(img *image.Image) error {
// in the current server `b.Daemon`. If an image is found, probeCache returns // in the current server `b.Daemon`. If an image is found, probeCache returns
// `(true, nil)`. If no image is found, it returns `(false, nil)`. If there // `(true, nil)`. If no image is found, it returns `(false, nil)`. If there
// is any error, it returns `(false, err)`. // is any error, it returns `(false, err)`.
func (b *Builder) probeCache() (bool, error) { func (b *builder) probeCache() (bool, error) {
if !b.UtilizeCache || b.cacheBusted { if !b.UtilizeCache || b.cacheBusted {
return false, nil return false, nil
} }
@ -600,7 +600,7 @@ func (b *Builder) probeCache() (bool, error) {
return true, nil return true, nil
} }
func (b *Builder) create() (*daemon.Container, error) { func (b *builder) create() (*daemon.Container, error) {
if b.image == "" && !b.noBaseImage { if b.image == "" && !b.noBaseImage {
return nil, fmt.Errorf("Please provide a source image with `from` prior to run") return nil, fmt.Errorf("Please provide a source image with `from` prior to run")
} }
@ -643,7 +643,7 @@ func (b *Builder) create() (*daemon.Container, error) {
return c, nil return c, nil
} }
func (b *Builder) run(c *daemon.Container) error { func (b *builder) run(c *daemon.Container) error {
var errCh chan error var errCh chan error
if b.Verbose { if b.Verbose {
errCh = c.Attach(nil, b.OutStream, b.ErrStream) errCh = c.Attach(nil, b.OutStream, b.ErrStream)
@ -683,7 +683,7 @@ func (b *Builder) run(c *daemon.Container) error {
return nil return nil
} }
func (b *Builder) checkPathForAddition(orig string) error { func (b *builder) checkPathForAddition(orig string) error {
origPath := filepath.Join(b.contextPath, orig) origPath := filepath.Join(b.contextPath, orig)
origPath, err := filepath.EvalSymlinks(origPath) origPath, err := filepath.EvalSymlinks(origPath)
if err != nil { if err != nil {
@ -708,7 +708,7 @@ func (b *Builder) checkPathForAddition(orig string) error {
return nil return nil
} }
func (b *Builder) addContext(container *daemon.Container, orig, dest string, decompress bool) error { func (b *builder) addContext(container *daemon.Container, orig, dest string, decompress bool) error {
var ( var (
err error err error
destExists = true destExists = true
@ -791,7 +791,7 @@ func copyAsDirectory(source, destination string, destExisted bool) error {
return fixPermissions(source, destination, 0, 0, destExisted) return fixPermissions(source, destination, 0, 0, destExisted)
} }
func (b *Builder) clearTmp() { func (b *builder) clearTmp() {
for c := range b.TmpContainers { for c := range b.TmpContainers {
rmConfig := &daemon.ContainerRmConfig{ rmConfig := &daemon.ContainerRmConfig{
ForceRemove: true, ForceRemove: true,

View File

@ -44,6 +44,7 @@ var validCommitCommands = map[string]bool{
"workdir": true, "workdir": true,
} }
// Config contains all configs for a build job
type Config struct { type Config struct {
DockerfileName string DockerfileName string
RemoteURL string RemoteURL string
@ -55,11 +56,11 @@ type Config struct {
Pull bool Pull bool
Memory int64 Memory int64
MemorySwap int64 MemorySwap int64
CpuShares int64 CPUShares int64
CpuPeriod int64 CPUPeriod int64
CpuQuota int64 CPUQuota int64
CpuSetCpus string CPUSetCpus string
CpuSetMems string CPUSetMems string
CgroupParent string CgroupParent string
AuthConfigs map[string]cliconfig.AuthConfig AuthConfigs map[string]cliconfig.AuthConfig
@ -72,18 +73,20 @@ type Config struct {
cancelOnce sync.Once cancelOnce sync.Once
} }
// When called, causes the Job.WaitCancelled channel to unblock. // Cancel signals the build job to cancel
func (b *Config) Cancel() { func (b *Config) Cancel() {
b.cancelOnce.Do(func() { b.cancelOnce.Do(func() {
close(b.cancelled) close(b.cancelled)
}) })
} }
// Returns a channel which is closed ("never blocks") when the job is cancelled. // WaitCancelled returns a channel which is closed ("never blocks") when
// the job is cancelled.
func (b *Config) WaitCancelled() <-chan struct{} { func (b *Config) WaitCancelled() <-chan struct{} {
return b.cancelled return b.cancelled
} }
// NewBuildConfig returns a new Config struct
func NewBuildConfig() *Config { func NewBuildConfig() *Config {
return &Config{ return &Config{
AuthConfigs: map[string]cliconfig.AuthConfig{}, AuthConfigs: map[string]cliconfig.AuthConfig{},
@ -91,6 +94,8 @@ func NewBuildConfig() *Config {
} }
} }
// Build is the main interface of the package, it gathers the Builder
// struct and calls builder.Run() to do all the real build job.
func Build(d *daemon.Daemon, buildConfig *Config) error { func Build(d *daemon.Daemon, buildConfig *Config) error {
var ( var (
repoName string repoName string
@ -173,7 +178,7 @@ func Build(d *daemon.Daemon, buildConfig *Config) error {
defer context.Close() defer context.Close()
builder := &Builder{ builder := &builder{
Daemon: d, Daemon: d,
OutStream: &streamformatter.StdoutFormater{ OutStream: &streamformatter.StdoutFormater{
Writer: buildConfig.Stdout, Writer: buildConfig.Stdout,
@ -192,11 +197,11 @@ func Build(d *daemon.Daemon, buildConfig *Config) error {
StreamFormatter: sf, StreamFormatter: sf,
AuthConfigs: buildConfig.AuthConfigs, AuthConfigs: buildConfig.AuthConfigs,
dockerfileName: buildConfig.DockerfileName, dockerfileName: buildConfig.DockerfileName,
cpuShares: buildConfig.CpuShares, cpuShares: buildConfig.CPUShares,
cpuPeriod: buildConfig.CpuPeriod, cpuPeriod: buildConfig.CPUPeriod,
cpuQuota: buildConfig.CpuQuota, cpuQuota: buildConfig.CPUQuota,
cpuSetCpus: buildConfig.CpuSetCpus, cpuSetCpus: buildConfig.CPUSetCpus,
cpuSetMems: buildConfig.CpuSetMems, cpuSetMems: buildConfig.CPUSetMems,
cgroupParent: buildConfig.CgroupParent, cgroupParent: buildConfig.CgroupParent,
memory: buildConfig.Memory, memory: buildConfig.Memory,
memorySwap: buildConfig.MemorySwap, memorySwap: buildConfig.MemorySwap,
@ -218,6 +223,11 @@ func Build(d *daemon.Daemon, buildConfig *Config) error {
return nil return nil
} }
// BuildFromConfig will do build directly from parameter 'changes', which comes
// from Dockerfile entries, it will:
//
// - call parse.Parse() to get AST root from Dockerfile entries
// - do build by calling builder.dispatch() to call all entries' handling routines
func BuildFromConfig(d *daemon.Daemon, c *runconfig.Config, changes []string) (*runconfig.Config, error) { func BuildFromConfig(d *daemon.Daemon, c *runconfig.Config, changes []string) (*runconfig.Config, error) {
ast, err := parser.Parse(bytes.NewBufferString(strings.Join(changes, "\n"))) ast, err := parser.Parse(bytes.NewBufferString(strings.Join(changes, "\n")))
if err != nil { if err != nil {
@ -231,7 +241,7 @@ func BuildFromConfig(d *daemon.Daemon, c *runconfig.Config, changes []string) (*
} }
} }
builder := &Builder{ builder := &builder{
Daemon: d, Daemon: d,
Config: c, Config: c,
OutStream: ioutil.Discard, OutStream: ioutil.Discard,
@ -248,7 +258,8 @@ func BuildFromConfig(d *daemon.Daemon, c *runconfig.Config, changes []string) (*
return builder.Config, nil return builder.Config, nil
} }
type BuilderCommitConfig struct { // CommitConfig contains build configs for commit operation
type CommitConfig struct {
Pause bool Pause bool
Repo string Repo string
Tag string Tag string
@ -258,7 +269,8 @@ type BuilderCommitConfig struct {
Config *runconfig.Config Config *runconfig.Config
} }
func Commit(name string, d *daemon.Daemon, c *BuilderCommitConfig) (string, error) { // Commit will create a new image from a container's changes
func Commit(name string, d *daemon.Daemon, c *CommitConfig) (string, error) {
container, err := d.Get(name) container, err := d.Get(name)
if err != nil { if err != nil {
return "", err return "", err

View File

@ -151,7 +151,7 @@ func parseNameVal(rest string, key string) (*Node, map[string]bool, error) {
if !strings.Contains(words[0], "=") { if !strings.Contains(words[0], "=") {
node := &Node{} node := &Node{}
rootnode = node rootnode = node
strs := TOKEN_WHITESPACE.Split(rest, 2) strs := tokenWhitespace.Split(rest, 2)
if len(strs) < 2 { if len(strs) < 2 {
return nil, nil, fmt.Errorf(key + " must have two arguments") return nil, nil, fmt.Errorf(key + " must have two arguments")
@ -205,7 +205,7 @@ func parseStringsWhitespaceDelimited(rest string) (*Node, map[string]bool, error
node := &Node{} node := &Node{}
rootnode := node rootnode := node
prevnode := node prevnode := node
for _, str := range TOKEN_WHITESPACE.Split(rest, -1) { // use regexp for _, str := range tokenWhitespace.Split(rest, -1) { // use regexp
prevnode = node prevnode = node
node.Value = str node.Value = str
node.Next = &Node{} node.Next = &Node{}
@ -232,13 +232,13 @@ func parseString(rest string) (*Node, map[string]bool, error) {
// parseJSON converts JSON arrays to an AST. // parseJSON converts JSON arrays to an AST.
func parseJSON(rest string) (*Node, map[string]bool, error) { func parseJSON(rest string) (*Node, map[string]bool, error) {
var myJson []interface{} var myJSON []interface{}
if err := json.NewDecoder(strings.NewReader(rest)).Decode(&myJson); err != nil { if err := json.NewDecoder(strings.NewReader(rest)).Decode(&myJSON); err != nil {
return nil, nil, err return nil, nil, err
} }
var top, prev *Node var top, prev *Node
for _, str := range myJson { for _, str := range myJSON {
s, ok := str.(string) s, ok := str.(string)
if !ok { if !ok {
return nil, nil, errDockerfileNotStringArray return nil, nil, errDockerfileNotStringArray

View File

@ -1,4 +1,4 @@
// This package implements a parser and parse tree dumper for Dockerfiles. // Package parser implements a parser and parse tree dumper for Dockerfiles.
package parser package parser
import ( import (
@ -33,10 +33,10 @@ type Node struct {
} }
var ( var (
dispatch map[string]func(string) (*Node, map[string]bool, error) dispatch map[string]func(string) (*Node, map[string]bool, error)
TOKEN_WHITESPACE = regexp.MustCompile(`[\t\v\f\r ]+`) tokenWhitespace = regexp.MustCompile(`[\t\v\f\r ]+`)
TOKEN_LINE_CONTINUATION = regexp.MustCompile(`\\[ \t]*$`) tokenLineContinuation = regexp.MustCompile(`\\[ \t]*$`)
TOKEN_COMMENT = regexp.MustCompile(`^#.*$`) tokenComment = regexp.MustCompile(`^#.*$`)
) )
func init() { func init() {
@ -70,8 +70,8 @@ func parseLine(line string) (string, *Node, error) {
return "", nil, nil return "", nil, nil
} }
if TOKEN_LINE_CONTINUATION.MatchString(line) { if tokenLineContinuation.MatchString(line) {
line = TOKEN_LINE_CONTINUATION.ReplaceAllString(line, "") line = tokenLineContinuation.ReplaceAllString(line, "")
return line, nil, nil return line, nil, nil
} }
@ -96,8 +96,8 @@ func parseLine(line string) (string, *Node, error) {
return "", node, nil return "", node, nil
} }
// The main parse routine. Handles an io.ReadWriteCloser and returns the root // Parse is the main parse routine.
// of the AST. // It handles an io.ReadWriteCloser and returns the root of the AST.
func Parse(rwc io.Reader) (*Node, error) { func Parse(rwc io.Reader) (*Node, error) {
root := &Node{} root := &Node{}
scanner := bufio.NewScanner(rwc) scanner := bufio.NewScanner(rwc)

View File

@ -7,8 +7,8 @@ import (
"unicode" "unicode"
) )
// dumps the AST defined by `node` as a list of sexps. Returns a string // Dump dumps the AST defined by `node` as a list of sexps.
// suitable for printing. // Returns a string suitable for printing.
func (node *Node) Dump() string { func (node *Node) Dump() string {
str := "" str := ""
str += node.Value str += node.Value
@ -59,7 +59,7 @@ func splitCommand(line string) (string, []string, string, error) {
var flags []string var flags []string
// Make sure we get the same results irrespective of leading/trailing spaces // Make sure we get the same results irrespective of leading/trailing spaces
cmdline := TOKEN_WHITESPACE.Split(strings.TrimSpace(line), 2) cmdline := tokenWhitespace.Split(strings.TrimSpace(line), 2)
cmd := strings.ToLower(cmdline[0]) cmd := strings.ToLower(cmdline[0])
if len(cmdline) == 2 { if len(cmdline) == 2 {
@ -77,8 +77,8 @@ func splitCommand(line string) (string, []string, string, error) {
// this function. // this function.
func stripComments(line string) string { func stripComments(line string) string {
// string is already trimmed at this point // string is already trimmed at this point
if TOKEN_COMMENT.MatchString(line) { if tokenComment.MatchString(line) {
return TOKEN_COMMENT.ReplaceAllString(line, "") return tokenComment.ReplaceAllString(line, "")
} }
return line return line

View File

@ -18,6 +18,8 @@ type shellWord struct {
pos int pos int
} }
// ProcessWord will use the 'env' list of environment variables,
// and replace any env var references in 'word'.
func ProcessWord(word string, env []string) (string, error) { func ProcessWord(word string, env []string) (string, error) {
sw := &shellWord{ sw := &shellWord{
word: word, word: word,

View File

@ -13,7 +13,7 @@ func selectAcceptableMIME(ct string) string {
return mimeRe.FindString(ct) return mimeRe.FindString(ct)
} }
func handleJsonArgs(args []string, attributes map[string]bool) []string { func handleJSONArgs(args []string, attributes map[string]bool) []string {
if len(args) == 0 { if len(args) == 0 {
return []string{} return []string{}
} }