2015-05-15 05:12:50 +00:00
|
|
|
|
package main
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
"io/ioutil"
|
|
|
|
|
"os"
|
|
|
|
|
"os/exec"
|
2015-11-09 04:44:56 +00:00
|
|
|
|
"path/filepath"
|
2015-05-15 05:12:50 +00:00
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/drone/drone-plugin-go/plugin"
|
|
|
|
|
)
|
|
|
|
|
|
2015-11-19 15:44:25 +00:00
|
|
|
|
type Save struct {
|
|
|
|
|
// Absolute or relative path
|
2015-11-27 21:27:01 +00:00
|
|
|
|
File string `json:"destination"`
|
2015-11-19 15:44:25 +00:00
|
|
|
|
// Only save specified tags (optional)
|
2015-11-27 21:27:01 +00:00
|
|
|
|
Tags StrSlice `json:"tag"`
|
2015-11-09 04:44:56 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-15 05:12:50 +00:00
|
|
|
|
type Docker struct {
|
2015-10-28 00:53:51 +00:00
|
|
|
|
Storage string `json:"storage_driver"`
|
|
|
|
|
Registry string `json:"registry"`
|
2015-11-18 17:44:27 +00:00
|
|
|
|
Mirror string `json:"mirror"`
|
2015-10-28 00:53:51 +00:00
|
|
|
|
Insecure bool `json:"insecure"`
|
|
|
|
|
Username string `json:"username"`
|
|
|
|
|
Password string `json:"password"`
|
|
|
|
|
Email string `json:"email"`
|
|
|
|
|
Auth string `json:"auth"`
|
|
|
|
|
Repo string `json:"repo"`
|
|
|
|
|
Tag StrSlice `json:"tag"`
|
|
|
|
|
File string `json:"file"`
|
|
|
|
|
Context string `json:"context"`
|
2015-11-27 21:27:01 +00:00
|
|
|
|
Bip string `json:"bip"`
|
2015-10-28 00:53:51 +00:00
|
|
|
|
Dns []string `json:"dns"`
|
2015-11-19 15:44:25 +00:00
|
|
|
|
Load string `json:"load"`
|
|
|
|
|
Save Save `json:"save"`
|
2015-05-15 05:12:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func main() {
|
2015-09-02 22:30:42 +00:00
|
|
|
|
workspace := plugin.Workspace{}
|
|
|
|
|
build := plugin.Build{}
|
2015-05-15 05:12:50 +00:00
|
|
|
|
vargs := Docker{}
|
|
|
|
|
|
2015-09-02 22:30:42 +00:00
|
|
|
|
plugin.Param("workspace", &workspace)
|
|
|
|
|
plugin.Param("build", &build)
|
2015-05-15 05:12:50 +00:00
|
|
|
|
plugin.Param("vargs", &vargs)
|
2015-09-02 22:30:42 +00:00
|
|
|
|
plugin.MustParse()
|
2015-05-15 05:12:50 +00:00
|
|
|
|
|
2015-09-04 20:01:18 +00:00
|
|
|
|
// in case someone uses the shorthand repository name
|
|
|
|
|
// with a custom registry, we should concatinate so that
|
|
|
|
|
// we have the fully qualified image name.
|
2015-10-21 12:27:34 +00:00
|
|
|
|
if strings.Count(vargs.Repo, "/") <= 1 && len(vargs.Registry) != 0 && !strings.HasPrefix(vargs.Repo, vargs.Registry) {
|
2015-09-04 20:01:18 +00:00
|
|
|
|
vargs.Repo = fmt.Sprintf("%s/%s", vargs.Registry, vargs.Repo)
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-04 19:08:59 +00:00
|
|
|
|
// Set the Registry value
|
|
|
|
|
if len(vargs.Registry) == 0 {
|
|
|
|
|
vargs.Registry = "https://index.docker.io/v1/"
|
2015-05-15 06:58:43 +00:00
|
|
|
|
}
|
2015-10-16 07:37:17 +00:00
|
|
|
|
// Set the Dockerfile name
|
|
|
|
|
if len(vargs.File) == 0 {
|
2015-10-24 21:32:54 +00:00
|
|
|
|
vargs.File = "Dockerfile"
|
2015-10-16 07:37:17 +00:00
|
|
|
|
}
|
|
|
|
|
// Set the Context value
|
2015-10-15 11:16:09 +00:00
|
|
|
|
if len(vargs.Context) == 0 {
|
|
|
|
|
vargs.Context = "."
|
2015-05-15 06:20:26 +00:00
|
|
|
|
}
|
2015-09-04 19:08:59 +00:00
|
|
|
|
// Set the Tag value
|
2015-10-28 00:53:51 +00:00
|
|
|
|
if vargs.Tag.Len() == 0 {
|
|
|
|
|
vargs.Tag = StrSlice{[]string{"latest"}}
|
2015-09-04 19:08:59 +00:00
|
|
|
|
}
|
2015-11-19 15:44:25 +00:00
|
|
|
|
// Get absolute path for 'save' file
|
|
|
|
|
if len(vargs.Save.File) != 0 {
|
2015-11-27 21:27:01 +00:00
|
|
|
|
if !filepath.IsAbs(vargs.Save.File) {
|
2015-11-19 15:44:25 +00:00
|
|
|
|
vargs.Save.File = filepath.Join(workspace.Path, vargs.Save.File)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// Get absolute path for 'load' file
|
|
|
|
|
if len(vargs.Load) != 0 {
|
2015-11-27 21:27:01 +00:00
|
|
|
|
if !filepath.IsAbs(vargs.Load) {
|
2015-11-19 15:44:25 +00:00
|
|
|
|
vargs.Load = filepath.Join(workspace.Path, vargs.Load)
|
2015-11-09 04:44:56 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2015-05-15 06:20:26 +00:00
|
|
|
|
|
2015-05-15 05:12:50 +00:00
|
|
|
|
go func() {
|
2015-09-04 19:08:59 +00:00
|
|
|
|
args := []string{"-d"}
|
2015-05-15 06:20:26 +00:00
|
|
|
|
|
2015-09-04 19:14:09 +00:00
|
|
|
|
if len(vargs.Storage) != 0 {
|
|
|
|
|
args = append(args, "-s", vargs.Storage)
|
|
|
|
|
}
|
2015-09-03 05:14:57 +00:00
|
|
|
|
if vargs.Insecure && len(vargs.Registry) != 0 {
|
|
|
|
|
args = append(args, "--insecure-registry", vargs.Registry)
|
|
|
|
|
}
|
2015-11-18 17:44:27 +00:00
|
|
|
|
if len(vargs.Mirror) != 0 {
|
|
|
|
|
args = append(args, "--registry-mirror", vargs.Mirror)
|
|
|
|
|
}
|
2015-11-27 21:27:01 +00:00
|
|
|
|
if len(vargs.Bip) != 0 {
|
|
|
|
|
args = append(args, "--bip", vargs.Bip)
|
|
|
|
|
}
|
2015-09-03 05:14:57 +00:00
|
|
|
|
|
2015-09-04 01:17:51 +00:00
|
|
|
|
for _, value := range vargs.Dns {
|
|
|
|
|
args = append(args, "--dns", value)
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-04 19:08:59 +00:00
|
|
|
|
cmd := exec.Command("/usr/bin/docker", args...)
|
2015-09-04 07:28:10 +00:00
|
|
|
|
if os.Getenv("DOCKER_LAUNCH_DEBUG") == "true" {
|
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
|
} else {
|
|
|
|
|
cmd.Stdout = ioutil.Discard
|
|
|
|
|
cmd.Stderr = ioutil.Discard
|
|
|
|
|
}
|
2015-05-15 06:20:26 +00:00
|
|
|
|
trace(cmd)
|
2015-05-15 05:12:50 +00:00
|
|
|
|
cmd.Run()
|
|
|
|
|
}()
|
|
|
|
|
|
2015-09-04 19:08:59 +00:00
|
|
|
|
// ping Docker until available
|
|
|
|
|
for i := 0; i < 3; i++ {
|
|
|
|
|
cmd := exec.Command("/usr/bin/docker", "info")
|
|
|
|
|
cmd.Stdout = ioutil.Discard
|
|
|
|
|
cmd.Stderr = ioutil.Discard
|
|
|
|
|
err := cmd.Run()
|
|
|
|
|
if err == nil {
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
time.Sleep(time.Second * 5)
|
2015-05-15 05:12:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-15 16:56:27 +00:00
|
|
|
|
// Login to Docker
|
2015-09-03 05:14:57 +00:00
|
|
|
|
if len(vargs.Username) != 0 {
|
2015-09-04 19:08:59 +00:00
|
|
|
|
cmd := exec.Command("/usr/bin/docker", "login", "-u", vargs.Username, "-p", vargs.Password, "-e", vargs.Email, vargs.Registry)
|
2015-09-03 05:14:57 +00:00
|
|
|
|
cmd.Dir = workspace.Path
|
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
|
err := cmd.Run()
|
|
|
|
|
if err != nil {
|
2015-09-04 20:01:18 +00:00
|
|
|
|
fmt.Println("Login failed.")
|
2015-09-03 05:14:57 +00:00
|
|
|
|
os.Exit(1)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
fmt.Printf("A username was not specified. Assuming anoynmous publishing.\n")
|
2015-05-15 05:12:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-05-16 00:18:07 +00:00
|
|
|
|
// Docker environment info
|
2015-09-04 19:08:59 +00:00
|
|
|
|
cmd := exec.Command("/usr/bin/docker", "version")
|
2015-05-16 00:18:07 +00:00
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
|
trace(cmd)
|
|
|
|
|
cmd.Run()
|
2015-09-04 19:08:59 +00:00
|
|
|
|
cmd = exec.Command("/usr/bin/docker", "info")
|
2015-05-16 00:18:07 +00:00
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
|
trace(cmd)
|
|
|
|
|
cmd.Run()
|
|
|
|
|
|
2015-11-19 15:44:25 +00:00
|
|
|
|
// Restore from tarred image repository
|
|
|
|
|
if len(vargs.Load) != 0 {
|
|
|
|
|
if _, err := os.Stat(vargs.Load); err != nil {
|
|
|
|
|
fmt.Printf("Archive %s does not exist. Building from scratch.\n", vargs.Load)
|
2015-11-09 04:44:56 +00:00
|
|
|
|
} else {
|
2015-11-19 15:44:25 +00:00
|
|
|
|
cmd := exec.Command("/usr/bin/docker", "load", "-i", vargs.Load)
|
2015-11-09 04:44:56 +00:00
|
|
|
|
cmd.Dir = workspace.Path
|
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
|
trace(cmd)
|
|
|
|
|
err := cmd.Run()
|
|
|
|
|
if err != nil {
|
|
|
|
|
os.Exit(1)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-15 16:56:27 +00:00
|
|
|
|
// Build the container
|
2015-10-28 00:53:51 +00:00
|
|
|
|
name := fmt.Sprintf("%s:%s", vargs.Repo, vargs.Tag.Slice()[0])
|
|
|
|
|
cmd = exec.Command("/usr/bin/docker", "build", "--pull=true", "--rm=true", "-f", vargs.File, "-t", name, vargs.Context)
|
2015-09-02 22:30:42 +00:00
|
|
|
|
cmd.Dir = workspace.Path
|
2015-05-15 05:12:50 +00:00
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
|
cmd.Stderr = os.Stderr
|
2015-05-15 16:56:27 +00:00
|
|
|
|
trace(cmd)
|
2015-09-03 05:14:57 +00:00
|
|
|
|
err := cmd.Run()
|
2015-05-15 05:12:50 +00:00
|
|
|
|
if err != nil {
|
|
|
|
|
os.Exit(1)
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-28 00:53:51 +00:00
|
|
|
|
// Creates image tags
|
|
|
|
|
for _, tag := range vargs.Tag.Slice()[1:] {
|
|
|
|
|
name_ := fmt.Sprintf("%s:%s", vargs.Repo, tag)
|
|
|
|
|
cmd = exec.Command("/usr/bin/docker", "tag", name, name_)
|
|
|
|
|
cmd.Dir = workspace.Path
|
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
|
trace(cmd)
|
|
|
|
|
err = cmd.Run()
|
|
|
|
|
if err != nil {
|
|
|
|
|
os.Exit(1)
|
|
|
|
|
}
|
2015-05-15 05:12:50 +00:00
|
|
|
|
}
|
2015-10-28 00:53:51 +00:00
|
|
|
|
|
|
|
|
|
// Push the image and tags to the registry
|
|
|
|
|
for _, tag := range vargs.Tag.Slice() {
|
|
|
|
|
name_ := fmt.Sprintf("%s:%s", vargs.Repo, tag)
|
|
|
|
|
cmd = exec.Command("/usr/bin/docker", "push", name_)
|
|
|
|
|
cmd.Dir = workspace.Path
|
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
|
trace(cmd)
|
|
|
|
|
err = cmd.Run()
|
|
|
|
|
if err != nil {
|
|
|
|
|
os.Exit(1)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-11-19 15:44:25 +00:00
|
|
|
|
// Save to tarred image repository
|
|
|
|
|
if len(vargs.Save.File) != 0 {
|
|
|
|
|
// if the destination directory does not exist, create it
|
|
|
|
|
dir := filepath.Dir(vargs.Save.File)
|
2015-11-09 04:44:56 +00:00
|
|
|
|
os.MkdirAll(dir, 0755)
|
|
|
|
|
|
2015-11-19 15:44:25 +00:00
|
|
|
|
cmd = exec.Command("/usr/bin/docker", "save", "-o", vargs.Save.File)
|
2015-11-09 04:44:56 +00:00
|
|
|
|
|
2015-11-19 15:44:25 +00:00
|
|
|
|
// Limit saving to the given tags
|
|
|
|
|
if vargs.Save.Tags.Len() != 0 {
|
|
|
|
|
for _, tag := range vargs.Save.Tags.Slice() {
|
2015-11-09 04:44:56 +00:00
|
|
|
|
name_ := fmt.Sprintf("%s:%s", vargs.Repo, tag)
|
|
|
|
|
cmd.Args = append(cmd.Args, name_)
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
cmd.Args = append(cmd.Args, vargs.Repo)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cmd.Dir = workspace.Path
|
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
|
trace(cmd)
|
|
|
|
|
err := cmd.Run()
|
|
|
|
|
if err != nil {
|
|
|
|
|
os.Exit(1)
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-05-15 05:12:50 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Trace writes each command to standard error (preceded by a ‘$ ’) before it
|
|
|
|
|
// is executed. Used for debugging your build.
|
|
|
|
|
func trace(cmd *exec.Cmd) {
|
|
|
|
|
fmt.Println("$", strings.Join(cmd.Args, " "))
|
|
|
|
|
}
|
2015-05-16 00:18:07 +00:00
|
|
|
|
|
|
|
|
|
// authorize is a helper function that authorizes the Docker client
|
|
|
|
|
// by manually creating the Docker authentication file.
|
|
|
|
|
func authorize(d *Docker) error {
|
|
|
|
|
var path = "/root/.dockercfg" // TODO should probably use user.Home() for good measure
|
|
|
|
|
var data = fmt.Sprintf(dockerconf, d.Registry, d.Auth, d.Email)
|
|
|
|
|
return ioutil.WriteFile(path, []byte(data), 0644)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var dockerconf = `
|
|
|
|
|
{
|
|
|
|
|
"%s": {
|
|
|
|
|
"auth": "%s",
|
|
|
|
|
"email": "%s"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
`
|