2014-06-19 00:39:33 +00:00
package publish
import (
"fmt"
"strconv"
2014-06-23 20:58:38 +00:00
"strings"
2014-06-19 00:39:33 +00:00
"github.com/drone/drone/pkg/build/buildfile"
"github.com/drone/drone/pkg/build/repo"
)
type Docker struct {
2014-06-27 22:22:45 +00:00
// The path to the dockerfile to create the image from. If the path is empty or no
// path is specified then the docker file will be built from the base directory.
2014-06-19 00:39:33 +00:00
Dockerfile string ` yaml:"docker_file" `
// Connection information for the docker server that will build the image
2014-08-07 22:50:51 +00:00
DockerServer string ` yaml:"docker_server" `
2014-08-08 08:15:32 +00:00
DockerServerPort int ` yaml:"docker_port" `
2014-06-19 00:39:33 +00:00
// The Docker client version to download. This must match the docker version on the server
DockerVersion string ` yaml:"docker_version" `
2014-08-07 22:50:51 +00:00
// Optional Arguments to allow finer-grained control of registry
// endpoints
RegistryHost string ` yaml:"registry_host" `
RegistryProtocol string ` yaml:"registry_protocol" `
RegistryPort int ` yaml:"registry_port" `
2014-08-08 08:15:32 +00:00
RegistryLogin bool ` yaml:"registry_login" `
2014-08-07 22:50:51 +00:00
RegistryLoginUri string ` yaml:"registry_login_uri" `
2014-08-08 08:15:32 +00:00
// Allow setting Repo + Image names for delivery
// NOTE: RepoName is not compatible with private Registries
RepoName string ` yaml:"repo_name" `
2014-08-07 22:50:51 +00:00
ImageName string ` yaml:"image_name" `
2014-06-19 00:39:33 +00:00
// Authentication credentials for index.docker.io
Username string ` yaml:"username" `
Password string ` yaml:"password" `
2014-08-08 08:15:32 +00:00
Email string ` yaml:"email" `
2014-06-19 00:39:33 +00:00
2014-08-07 22:50:51 +00:00
// Keep the build on the Docker host after pushing?
KeepBuild bool ` yaml:"keep_build" `
2014-08-08 08:15:32 +00:00
// Do we want to override "latest" automatically with this build?
PushLatest bool ` yaml:"push_latest" `
2014-08-07 22:50:51 +00:00
2014-06-19 00:39:33 +00:00
Branch string ` yaml:"branch,omitempty" `
2014-08-07 22:50:51 +00:00
Tag string ` yaml:"custom_tag" `
2014-06-19 00:39:33 +00:00
}
// Write adds commands to the buildfile to do the following:
// 1. Install the docker client in the Drone container.
// 2. Build a docker image based on the dockerfile defined in the config.
// 3. Push that docker image to index.docker.io.
// 4. Delete the docker image on the server it was build on so we conserve disk space.
func ( d * Docker ) Write ( f * buildfile . Buildfile , r * repo . Repo ) {
2014-08-07 22:50:51 +00:00
if len ( d . DockerServer ) == 0 || d . DockerServerPort == 0 || len ( d . DockerVersion ) == 0 ||
len ( d . ImageName ) == 0 {
2014-08-08 08:15:32 +00:00
f . WriteCmdSilent ( ` echo -e "Docker Plugin: Missing argument(s)"\n\n ` )
if len ( d . DockerServer ) == 0 { f . WriteCmdSilent ( ` echo -e "\tdocker_server not defined in yaml ` ) }
if d . DockerServerPort == 0 { f . WriteCmdSilent ( ` echo -e "\tdocker_port not defined in yaml ` ) }
if len ( d . DockerVersion ) == 0 { f . WriteCmdSilent ( ` echo -e "\tdocker_version not defined in yaml ` ) }
if len ( d . ImageName ) == 0 { f . WriteCmdSilent ( ` echo -e "\timage_name not defined in yaml ` ) }
2014-06-19 00:39:33 +00:00
return
}
2014-08-08 08:15:32 +00:00
if len ( d . RepoName ) > 0 && len ( d . RegistryHost ) > 0 {
f . WriteCmdSilent ( ` echo -e "Docker Plugin: Invalid Arguments Specified\n\n cannot combine repo_name and registry_host\n\t(It's not possible to host sub-repo's on private registries)\n" ` )
return
}
// Ensure correct apt-get has the https method-driver as per (http://askubuntu.com/questions/165676/)
f . WriteCmd ( "sudo apt-get install apt-transport-https" )
2014-08-07 22:50:51 +00:00
2014-06-19 00:39:33 +00:00
// Install Docker on the container
2014-07-22 21:51:37 +00:00
f . WriteCmd ( "sudo sh -c \"echo deb https://get.docker.io/ubuntu docker main\\ > " +
2014-06-19 00:39:33 +00:00
"/etc/apt/sources.list.d/docker.list\"" )
2014-07-30 22:52:33 +00:00
f . WriteCmd ( "sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys " +
2014-07-22 21:51:37 +00:00
"36A1D7869245C8950F966E92D8576A8BA88D21E9" )
2014-06-19 00:39:33 +00:00
f . WriteCmd ( "sudo apt-get update" )
f . WriteCmd ( "sudo apt-get --yes install lxc-docker-" + d . DockerVersion )
2014-08-07 22:50:51 +00:00
// Format our Build Server Endpoint
dockerServerUrl := d . DockerServer + ":" + strconv . Itoa ( d . DockerServerPort )
// Construct Image BaseName
// e.g. "docker.mycompany.com/myimage" for private registries
2014-08-08 08:15:32 +00:00
// "myuser/myimage" for index.docker.io
2014-08-07 22:50:51 +00:00
imageBaseName := ""
if len ( d . RegistryHost ) > 0 {
imageBaseName = fmt . Sprintf ( "%s/%s" , d . RegistryHost , d . ImageName )
} else {
2014-08-08 08:15:32 +00:00
if len ( d . RepoName ) > 0 {
imageBaseName = fmt . Sprintf ( "%s/%s" , d . RepoName , d . ImageName )
} else {
imageBaseName = fmt . Sprintf ( "%s/%s" , d . Username , d . ImageName )
}
2014-08-07 22:50:51 +00:00
}
registryLoginEndpoint := ""
// Gather information to build our Registry Endpoint for private registries
if len ( d . RegistryHost ) > 0 {
// Set Protocol
if len ( d . RegistryProtocol ) > 0 {
registryLoginEndpoint = fmt . Sprintf ( "%s://%s" , d . RegistryProtocol , d . RegistryHost )
} else {
registryLoginEndpoint = fmt . Sprintf ( "http://%s" , d . RegistryHost )
}
// Set Port
if d . RegistryPort > 0 {
registryLoginEndpoint = fmt . Sprintf ( "%s:%d" , registryLoginEndpoint , d . RegistryPort )
}
// Set Login URI
if len ( d . RegistryLoginUri ) > 0 {
registryLoginEndpoint = fmt . Sprintf ( "%s/%s" , registryLoginEndpoint , strings . TrimPrefix ( d . RegistryLoginUri , "/" ) )
} else {
registryLoginEndpoint = fmt . Sprintf ( "%s/v1/" , registryLoginEndpoint )
}
}
2014-06-27 22:22:45 +00:00
dockerPath := "."
if len ( d . Dockerfile ) != 0 {
dockerPath = fmt . Sprintf ( "- < %s" , d . Dockerfile )
}
2014-08-07 22:50:51 +00:00
// Run the command commands to build and deploy the image.
// Are we setting a custom tag, or do we use the git hash?
imageTag := ""
if len ( d . Tag ) > 0 {
imageTag = d . Tag
} else {
imageTag = "$(git rev-parse --short HEAD)"
}
f . WriteCmd ( fmt . Sprintf ( "docker -H %s build -t %s:%s %s" , dockerServerUrl , imageBaseName , imageTag , dockerPath ) )
2014-06-19 00:39:33 +00:00
2014-08-07 22:50:51 +00:00
// Login?
if len ( d . RegistryHost ) > 0 && d . RegistryLogin == true {
f . WriteCmdSilent ( fmt . Sprintf ( "docker -H %s login -u %s -p %s -e %s %s" ,
dockerServerUrl , d . Username , d . Password , d . Email , registryLoginEndpoint ) )
} else if len ( d . RegistryHost ) == 0 {
// Assume that because no private registry is specified it requires auth
// for index.docker.io
f . WriteCmdSilent ( fmt . Sprintf ( "docker -H %s login -u %s -p %s -e %s" ,
dockerServerUrl , d . Username , d . Password , d . Email ) )
}
2014-08-08 08:15:32 +00:00
// Are we overriding the "latest" tag?
if d . PushLatest {
2014-08-07 22:50:51 +00:00
f . WriteCmd ( fmt . Sprintf ( "docker -H %s tag %s:%s %s:latest" ,
dockerServerUrl , imageBaseName , imageTag , imageBaseName ) )
2014-08-08 08:15:32 +00:00
}
2014-08-07 22:50:51 +00:00
f . WriteCmd ( fmt . Sprintf ( "docker -H %s push %s" , dockerServerUrl , imageBaseName ) )
2014-06-19 00:39:33 +00:00
2014-07-22 21:51:37 +00:00
// Delete the image from the docker server we built on.
2014-08-07 22:50:51 +00:00
if ! d . KeepBuild {
f . WriteCmd ( fmt . Sprintf ( "docker -H %s rmi %s:%s" ,
dockerServerUrl , imageBaseName , imageTag ) )
f . WriteCmd ( fmt . Sprintf ( "docker -H %s rmi %s:latest" ,
dockerServerUrl , imageBaseName ) )
}
2014-06-19 00:39:33 +00:00
}