fork: initial release

This commit is contained in:
Robert Kaussow
2021-01-10 23:47:55 +01:00
parent 9c86f98ea5
commit 89b0b6823a
53 changed files with 803 additions and 2903 deletions

View File

@@ -1,60 +0,0 @@
package main
import (
"fmt"
"os"
"os/exec"
"strings"
"github.com/joho/godotenv"
)
func main() {
// Load env-file if it exists first
if env := os.Getenv("PLUGIN_ENV_FILE"); env != "" {
godotenv.Load(env)
}
var (
repo = getenv("PLUGIN_REPO")
registry = getenv("PLUGIN_REGISTRY")
username = getenv("SERVICE_PRINCIPAL_CLIENT_ID")
password = getenv("SERVICE_PRINCIPAL_CLIENT_SECRET")
)
// default registry value
if registry == "" {
registry = "azurecr.io"
}
// must use the fully qualified repo name. If the
// repo name does not have the registry prefix we
// should prepend.
if !strings.HasPrefix(repo, registry) {
repo = fmt.Sprintf("%s/%s", registry, repo)
}
os.Setenv("PLUGIN_REPO", repo)
os.Setenv("PLUGIN_REGISTRY", registry)
os.Setenv("DOCKER_USERNAME", username)
os.Setenv("DOCKER_PASSWORD", password)
// invoke the base docker plugin binary
cmd := exec.Command("drone-docker")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
os.Exit(1)
}
}
func getenv(key ...string) (s string) {
for _, k := range key {
s = os.Getenv(k)
if s != "" {
return
}
}
return
}

View File

@@ -1,317 +0,0 @@
package main
import (
"os"
"github.com/joho/godotenv"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
docker "github.com/drone-plugins/drone-docker"
)
var (
version = "unknown"
)
func main() {
// Load env-file if it exists first
if env := os.Getenv("PLUGIN_ENV_FILE"); env != "" {
godotenv.Load(env)
}
app := cli.NewApp()
app.Name = "docker plugin"
app.Usage = "docker plugin"
app.Action = run
app.Version = version
app.Flags = []cli.Flag{
cli.BoolFlag{
Name: "dry-run",
Usage: "dry run disables docker push",
EnvVar: "PLUGIN_DRY_RUN",
},
cli.StringFlag{
Name: "remote.url",
Usage: "git remote url",
EnvVar: "DRONE_REMOTE_URL",
},
cli.StringFlag{
Name: "commit.sha",
Usage: "git commit sha",
EnvVar: "DRONE_COMMIT_SHA",
Value: "00000000",
},
cli.StringFlag{
Name: "commit.ref",
Usage: "git commit ref",
EnvVar: "DRONE_COMMIT_REF",
},
cli.StringFlag{
Name: "daemon.mirror",
Usage: "docker daemon registry mirror",
EnvVar: "PLUGIN_MIRROR,DOCKER_PLUGIN_MIRROR",
},
cli.StringFlag{
Name: "daemon.storage-driver",
Usage: "docker daemon storage driver",
EnvVar: "PLUGIN_STORAGE_DRIVER",
},
cli.StringFlag{
Name: "daemon.storage-path",
Usage: "docker daemon storage path",
Value: "/var/lib/docker",
EnvVar: "PLUGIN_STORAGE_PATH",
},
cli.StringFlag{
Name: "daemon.bip",
Usage: "docker daemon bride ip address",
EnvVar: "PLUGIN_BIP",
},
cli.StringFlag{
Name: "daemon.mtu",
Usage: "docker daemon custom mtu setting",
EnvVar: "PLUGIN_MTU",
},
cli.StringSliceFlag{
Name: "daemon.dns",
Usage: "docker daemon dns server",
EnvVar: "PLUGIN_CUSTOM_DNS",
},
cli.StringSliceFlag{
Name: "daemon.dns-search",
Usage: "docker daemon dns search domains",
EnvVar: "PLUGIN_CUSTOM_DNS_SEARCH",
},
cli.BoolFlag{
Name: "daemon.insecure",
Usage: "docker daemon allows insecure registries",
EnvVar: "PLUGIN_INSECURE",
},
cli.BoolFlag{
Name: "daemon.ipv6",
Usage: "docker daemon IPv6 networking",
EnvVar: "PLUGIN_IPV6",
},
cli.BoolFlag{
Name: "daemon.experimental",
Usage: "docker daemon Experimental mode",
EnvVar: "PLUGIN_EXPERIMENTAL",
},
cli.BoolFlag{
Name: "daemon.debug",
Usage: "docker daemon executes in debug mode",
EnvVar: "PLUGIN_DEBUG,DOCKER_LAUNCH_DEBUG",
},
cli.BoolFlag{
Name: "daemon.off",
Usage: "don't start the docker daemon",
EnvVar: "PLUGIN_DAEMON_OFF",
},
cli.StringFlag{
Name: "dockerfile",
Usage: "build dockerfile",
Value: "Dockerfile",
EnvVar: "PLUGIN_DOCKERFILE",
},
cli.StringFlag{
Name: "context",
Usage: "build context",
Value: ".",
EnvVar: "PLUGIN_CONTEXT",
},
cli.StringSliceFlag{
Name: "tags",
Usage: "build tags",
Value: &cli.StringSlice{"latest"},
EnvVar: "PLUGIN_TAG,PLUGIN_TAGS",
FilePath: ".tags",
},
cli.BoolFlag{
Name: "tags.auto",
Usage: "default build tags",
EnvVar: "PLUGIN_DEFAULT_TAGS,PLUGIN_AUTO_TAG",
},
cli.StringFlag{
Name: "tags.suffix",
Usage: "default build tags with suffix",
EnvVar: "PLUGIN_DEFAULT_SUFFIX,PLUGIN_AUTO_TAG_SUFFIX",
},
cli.StringSliceFlag{
Name: "args",
Usage: "build args",
EnvVar: "PLUGIN_BUILD_ARGS",
},
cli.StringSliceFlag{
Name: "args-from-env",
Usage: "build args",
EnvVar: "PLUGIN_BUILD_ARGS_FROM_ENV",
},
cli.BoolFlag{
Name: "quiet",
Usage: "quiet docker build",
EnvVar: "PLUGIN_QUIET",
},
cli.StringFlag{
Name: "target",
Usage: "build target",
EnvVar: "PLUGIN_TARGET",
},
cli.StringSliceFlag{
Name: "cache-from",
Usage: "images to consider as cache sources",
EnvVar: "PLUGIN_CACHE_FROM",
},
cli.BoolFlag{
Name: "squash",
Usage: "squash the layers at build time",
EnvVar: "PLUGIN_SQUASH",
},
cli.BoolTFlag{
Name: "pull-image",
Usage: "force pull base image at build time",
EnvVar: "PLUGIN_PULL_IMAGE",
},
cli.BoolFlag{
Name: "compress",
Usage: "compress the build context using gzip",
EnvVar: "PLUGIN_COMPRESS",
},
cli.StringFlag{
Name: "repo",
Usage: "docker repository",
EnvVar: "PLUGIN_REPO",
},
cli.StringSliceFlag{
Name: "custom-labels",
Usage: "additional k=v labels",
EnvVar: "PLUGIN_CUSTOM_LABELS",
},
cli.StringSliceFlag{
Name: "label-schema",
Usage: "label-schema labels",
EnvVar: "PLUGIN_LABEL_SCHEMA",
},
cli.StringFlag{
Name: "docker.registry",
Usage: "docker registry",
Value: "https://index.docker.io/v1/",
EnvVar: "PLUGIN_REGISTRY,DOCKER_REGISTRY",
},
cli.StringFlag{
Name: "docker.username",
Usage: "docker username",
EnvVar: "PLUGIN_USERNAME,DOCKER_USERNAME",
},
cli.StringFlag{
Name: "docker.password",
Usage: "docker password",
EnvVar: "PLUGIN_PASSWORD,DOCKER_PASSWORD",
},
cli.StringFlag{
Name: "docker.email",
Usage: "docker email",
EnvVar: "PLUGIN_EMAIL,DOCKER_EMAIL",
},
cli.StringFlag{
Name: "docker.config",
Usage: "docker json dockerconfig content",
EnvVar: "PLUGIN_CONFIG,DOCKER_PLUGIN_CONFIG",
},
cli.BoolTFlag{
Name: "docker.purge",
Usage: "docker should cleanup images",
EnvVar: "PLUGIN_PURGE",
},
cli.StringFlag{
Name: "repo.branch",
Usage: "repository default branch",
EnvVar: "DRONE_REPO_BRANCH",
},
cli.BoolFlag{
Name: "no-cache",
Usage: "do not use cached intermediate containers",
EnvVar: "PLUGIN_NO_CACHE",
},
cli.StringSliceFlag{
Name: "add-host",
Usage: "additional host:IP mapping",
EnvVar: "PLUGIN_ADD_HOST",
},
}
if err := app.Run(os.Args); err != nil {
logrus.Fatal(err)
}
}
func run(c *cli.Context) error {
plugin := docker.Plugin{
Dryrun: c.Bool("dry-run"),
Cleanup: c.BoolT("docker.purge"),
Login: docker.Login{
Registry: c.String("docker.registry"),
Username: c.String("docker.username"),
Password: c.String("docker.password"),
Email: c.String("docker.email"),
Config: c.String("docker.config"),
},
Build: docker.Build{
Remote: c.String("remote.url"),
Name: c.String("commit.sha"),
Dockerfile: c.String("dockerfile"),
Context: c.String("context"),
Tags: c.StringSlice("tags"),
Args: c.StringSlice("args"),
ArgsEnv: c.StringSlice("args-from-env"),
Target: c.String("target"),
Squash: c.Bool("squash"),
Pull: c.BoolT("pull-image"),
CacheFrom: c.StringSlice("cache-from"),
Compress: c.Bool("compress"),
Repo: c.String("repo"),
Labels: c.StringSlice("custom-labels"),
LabelSchema: c.StringSlice("label-schema"),
NoCache: c.Bool("no-cache"),
AddHost: c.StringSlice("add-host"),
Quiet: c.Bool("quiet"),
},
Daemon: docker.Daemon{
Registry: c.String("docker.registry"),
Mirror: c.String("daemon.mirror"),
StorageDriver: c.String("daemon.storage-driver"),
StoragePath: c.String("daemon.storage-path"),
Insecure: c.Bool("daemon.insecure"),
Disabled: c.Bool("daemon.off"),
IPv6: c.Bool("daemon.ipv6"),
Debug: c.Bool("daemon.debug"),
Bip: c.String("daemon.bip"),
DNS: c.StringSlice("daemon.dns"),
DNSSearch: c.StringSlice("daemon.dns-search"),
MTU: c.String("daemon.mtu"),
Experimental: c.Bool("daemon.experimental"),
},
}
if c.Bool("tags.auto") {
if docker.UseDefaultTag( // return true if tag event or default branch
c.String("commit.ref"),
c.String("repo.branch"),
) {
tag, err := docker.DefaultTagSuffix(
c.String("commit.ref"),
c.String("tags.suffix"),
)
if err != nil {
logrus.Printf("cannot build docker image for %s, invalid semantic version", c.String("commit.ref"))
return err
}
plugin.Build.Tags = tag
} else {
logrus.Printf("skipping automated docker build for %s", c.String("commit.ref"))
return nil
}
}
return plugin.Exec()
}

View File

@@ -1,203 +0,0 @@
package main
import (
"encoding/base64"
"fmt"
"io/ioutil"
"log"
"os"
"os/exec"
"strconv"
"strings"
"github.com/joho/godotenv"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/credentials/stscreds"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ecr"
)
const defaultRegion = "us-east-1"
func main() {
// Load env-file if it exists first
if env := os.Getenv("PLUGIN_ENV_FILE"); env != "" {
godotenv.Load(env)
}
var (
repo = getenv("PLUGIN_REPO")
registry = getenv("PLUGIN_REGISTRY")
region = getenv("PLUGIN_REGION", "ECR_REGION", "AWS_REGION")
key = getenv("PLUGIN_ACCESS_KEY", "ECR_ACCESS_KEY", "AWS_ACCESS_KEY_ID")
secret = getenv("PLUGIN_SECRET_KEY", "ECR_SECRET_KEY", "AWS_SECRET_ACCESS_KEY")
create = parseBoolOrDefault(false, getenv("PLUGIN_CREATE_REPOSITORY", "ECR_CREATE_REPOSITORY"))
lifecyclePolicy = getenv("PLUGIN_LIFECYCLE_POLICY")
repositoryPolicy = getenv("PLUGIN_REPOSITORY_POLICY")
assumeRole = getenv("PLUGIN_ASSUME_ROLE")
)
// set the region
if region == "" {
region = defaultRegion
}
os.Setenv("AWS_REGION", region)
if key != "" && secret != "" {
os.Setenv("AWS_ACCESS_KEY_ID", key)
os.Setenv("AWS_SECRET_ACCESS_KEY", secret)
}
sess, err := session.NewSession(&aws.Config{Region: &region})
if err != nil {
log.Fatal(fmt.Sprintf("error creating aws session: %v", err))
}
svc := getECRClient(sess, assumeRole)
username, password, defaultRegistry, err := getAuthInfo(svc)
if registry == "" {
registry = defaultRegistry
}
if err != nil {
log.Fatal(fmt.Sprintf("error getting ECR auth: %v", err))
}
if !strings.HasPrefix(repo, registry) {
repo = fmt.Sprintf("%s/%s", registry, repo)
}
if create {
err = ensureRepoExists(svc, trimHostname(repo, registry))
if err != nil {
log.Fatal(fmt.Sprintf("error creating ECR repo: %v", err))
}
}
if lifecyclePolicy != "" {
p, err := ioutil.ReadFile(lifecyclePolicy)
if err != nil {
log.Fatal(err)
}
if err := uploadLifeCyclePolicy(svc, string(p), trimHostname(repo, registry)); err != nil {
log.Fatal(fmt.Sprintf("error uploading ECR lifecycle policy: %v", err))
}
}
if repositoryPolicy != "" {
p, err := ioutil.ReadFile(repositoryPolicy)
if err != nil {
log.Fatal(err)
}
if err := uploadRepositoryPolicy(svc, string(p), trimHostname(repo, registry)); err != nil {
log.Fatal(fmt.Sprintf("error uploading ECR repository policy. %v", err))
}
}
os.Setenv("PLUGIN_REPO", repo)
os.Setenv("PLUGIN_REGISTRY", registry)
os.Setenv("DOCKER_USERNAME", username)
os.Setenv("DOCKER_PASSWORD", password)
// invoke the base docker plugin binary
cmd := exec.Command("drone-docker")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err = cmd.Run(); err != nil {
os.Exit(1)
}
}
func trimHostname(repo, registry string) string {
repo = strings.TrimPrefix(repo, registry)
repo = strings.TrimLeft(repo, "/")
return repo
}
func ensureRepoExists(svc *ecr.ECR, name string) (err error) {
input := &ecr.CreateRepositoryInput{}
input.SetRepositoryName(name)
_, err = svc.CreateRepository(input)
if err != nil {
if aerr, ok := err.(awserr.Error); ok && aerr.Code() == ecr.ErrCodeRepositoryAlreadyExistsException {
// eat it, we skip checking for existing to save two requests
err = nil
}
}
return
}
func uploadLifeCyclePolicy(svc *ecr.ECR, lifecyclePolicy string, name string) (err error) {
input := &ecr.PutLifecyclePolicyInput{}
input.SetLifecyclePolicyText(lifecyclePolicy)
input.SetRepositoryName(name)
_, err = svc.PutLifecyclePolicy(input)
return err
}
func uploadRepositoryPolicy(svc *ecr.ECR, repositoryPolicy string, name string) (err error) {
input := &ecr.SetRepositoryPolicyInput{}
input.SetPolicyText(repositoryPolicy)
input.SetRepositoryName(name)
_, err = svc.SetRepositoryPolicy(input)
return err
}
func getAuthInfo(svc *ecr.ECR) (username, password, registry string, err error) {
var result *ecr.GetAuthorizationTokenOutput
var decoded []byte
result, err = svc.GetAuthorizationToken(&ecr.GetAuthorizationTokenInput{})
if err != nil {
return
}
auth := result.AuthorizationData[0]
token := *auth.AuthorizationToken
decoded, err = base64.StdEncoding.DecodeString(token)
if err != nil {
return
}
registry = strings.TrimPrefix(*auth.ProxyEndpoint, "https://")
creds := strings.Split(string(decoded), ":")
username = creds[0]
password = creds[1]
return
}
func parseBoolOrDefault(defaultValue bool, s string) (result bool) {
var err error
result, err = strconv.ParseBool(s)
if err != nil {
result = false
}
return
}
func getenv(key ...string) (s string) {
for _, k := range key {
s = os.Getenv(k)
if s != "" {
return
}
}
return
}
func getECRClient(sess *session.Session, role string) *ecr.ECR {
if role == "" {
return ecr.New(sess)
}
return ecr.New(sess, &aws.Config{
Credentials: stscreds.NewCredentials(sess, role),
})
}

View File

@@ -1,20 +0,0 @@
package main
import "testing"
func TestTrimHostname(t *testing.T) {
registry := "000000000000.dkr.ecr.us-east-1.amazonaws.com"
// map full repo path to expected repo name
repos := map[string]string{
registry + "/repo": "repo",
registry + "/namespace/repo": "namespace/repo",
registry + "/namespace/namespace/repo": "namespace/namespace/repo",
}
for repo, name := range repos {
splitName := trimHostname(repo, registry)
if splitName != name {
t.Errorf("%s is not equal to %s.", splitName, name)
}
}
}

View File

@@ -1,74 +0,0 @@
package main
import (
"encoding/base64"
"os"
"os/exec"
"path"
"strings"
"github.com/joho/godotenv"
)
// gcr default username
const username = "_json_key"
func main() {
// Load env-file if it exists first
if env := os.Getenv("PLUGIN_ENV_FILE"); env != "" {
godotenv.Load(env)
}
var (
repo = getenv("PLUGIN_REPO")
registry = getenv("PLUGIN_REGISTRY")
password = getenv(
"PLUGIN_JSON_KEY",
"GCR_JSON_KEY",
"GOOGLE_CREDENTIALS",
"TOKEN",
)
)
// decode the token if base64 encoded
decoded, err := base64.StdEncoding.DecodeString(password)
if err == nil {
password = string(decoded)
}
// default registry value
if registry == "" {
registry = "gcr.io"
}
// must use the fully qualified repo name. If the
// repo name does not have the registry prefix we
// should prepend.
if !strings.HasPrefix(repo, registry) {
repo = path.Join(registry, repo)
}
os.Setenv("PLUGIN_REPO", repo)
os.Setenv("PLUGIN_REGISTRY", registry)
os.Setenv("DOCKER_USERNAME", username)
os.Setenv("DOCKER_PASSWORD", password)
// invoke the base docker plugin binary
cmd := exec.Command("drone-docker")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
if err != nil {
os.Exit(1)
}
}
func getenv(key ...string) (s string) {
for _, k := range key {
s = os.Getenv(k)
if s != "" {
return
}
}
return
}

View File

@@ -1,53 +0,0 @@
package main
import (
"os"
"os/exec"
"path"
"github.com/joho/godotenv"
)
func main() {
// Load env-file if it exists first
if env := os.Getenv("PLUGIN_ENV_FILE"); env != "" {
godotenv.Load(env)
}
var (
registry = "registry.heroku.com"
process = getenv("PLUGIN_PROCESS_TYPE")
app = getenv("PLUGIN_APP")
email = getenv("PLUGIN_EMAIL", "HEROKU_EMAIL")
key = getenv("PLUGIN_API_KEY", "HEROKU_API_KEY")
)
if process == "" {
process = "web"
}
os.Setenv("PLUGIN_REGISTRY", registry)
os.Setenv("PLUGIN_REPO", path.Join(registry, app, process))
os.Setenv("DOCKER_PASSWORD", key)
os.Setenv("DOCKER_USERNAME", email)
os.Setenv("DOCKER_EMAIL", email)
cmd := exec.Command("drone-docker")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
os.Exit(1)
}
}
func getenv(key ...string) (s string) {
for _, k := range key {
s = os.Getenv(k)
if s != "" {
return
}
}
return
}