Compare commits

...

58 Commits

Author SHA1 Message Date
Raghav c7770b6668 golang image upgrade to 1.18 (#54) 2022-07-08 12:36:10 +05:30
Shubham Agrawal adee644baf Publish kaniko 1.8.1 version images (#52) 2022-04-12 23:21:29 +05:30
TP Honey f5669f55eb Merge pull request #51 from aman-harness/patch-1
Upgraded golang version to 1.17.8
2022-04-12 16:36:19 +01:00
Aman Singh 984d34fe9f Upgraded golang version to 1.17.8 2022-04-12 20:41:54 +05:30
Peter Novotnak 89b4f6b0c9 Skip unused stages flag (#49)
* skip unused stages flag

* re-add smithy
2022-04-09 10:57:17 +05:30
Shubham Agrawal c39a1155b5 Making prepend of registry url to repo name optional (#48) 2022-04-05 14:39:12 +05:30
ymage ea64d40995 Remove prepending of v1RegistryURL to the repo (#47)
* Default registry value is not  but v1RegistryURL

* Handle test (not sure about its relevancy

Co-authored-by: Ymage <heltem+git@o2php.com>
2022-04-04 10:58:10 +05:30
Shubham Agrawal 0cd3e162fa Remove auto tagging for version 1.8 (#46) 2022-03-31 16:24:40 +05:30
Shubham Agrawal f492271f45 Fix manifest yml (#45) 2022-03-31 15:39:44 +05:30
Shubham Agrawal 7c6c33d174 Fix drone yml (#44) 2022-03-31 15:32:23 +05:30
Shubham Agrawal a11da49965 Publish plugin with latest kaniko 1.8.0 image (#43) 2022-03-31 14:53:50 +05:30
HC Saustrup fae9271dc7 fix: Build.Repo and Build.CacheRepo now uses buildRepo() (#40) 2022-03-15 12:13:05 +05:30
JimZhang 8bd45524d4 add flag --registry-mirrors (#42) 2022-03-15 11:45:57 +05:30
Aman Singh 427f9abb99 Upgraded golang version (#41) 2022-03-14 22:19:32 +05:30
Yuxuan 'fishy' Wang dbdf13277d Fix typo in README (#39)
From de43f3afb6, both the code and the
commit message used singular form of expand_tag, but the example in the
README used the plural form of expand_tags. Based on that I assume the
singular form was the intention and the plural form in the README was a
typo (the plural form does not work because the code only checks for the
singular form env var).
2022-02-25 23:19:37 +05:30
Sinkerine c38eb07dea Fix the broken link in readme (#38) 2022-02-10 18:36:36 +05:30
Sinkerine de43f3afb6 Port the auto tag feature from docker plugin (#36)
* Port the auto tag feature from https://plugins.drone.io/drone-plugins/drone-docker

The logic is forked from https://github.com/drone-plugins/drone-docker code base
with necessary modification. I've tested it e2e for DockerHub on my Drone server
via this plugin image https://hub.docker.com/repository/docker/15cm/drone-kaniko,
for both tag pushes and commit pushes.

With this change the .drone.yml in this repo should work as intended.

Other changes:
- Rename the existing "auto tag" flags/code to "expand tag" for a less
misleading naming.
- ATTENTION: make a breaking change to set default value of "--tags" to empty.
Rationale is to expect most users to use the auto tagging feature. When power
users want to specify tags, they should always explicitly set tags instead of
being surprised by the default "latest" tag.

* Change how --auto-tag flag works with other flags

The --auto-tag has to be a breaking change. This commit limit the breaking
impact to the users who enable the flag. Behaviors of flag combination after
this commit:
* --auto-tag=false: No changes.
* --auto-tag=false,--expand-tag=true,tags=1.0.0:
  * Old behavior: Should not happen. --expand-tag didn't exist.
  * New Behavior: Build with [1,1.0,1.0.0] tags.
* --auto-tag=true
  * Old behavior: Build with the "latest" tag.
  * New behavior: Build with auto detected tags. Abort if auto detection failed.
* --auto-tag=true,tags=latest: same as "--auto-tag=true".
* --auto-tag=true,tags=1.0.0:
  * Old behavior: Build with [1,1.0,1.0.0] tags.
  * New behavior: Abort the build with an error message.
* --auto-tag=true,--expand-tag=true,tags=1.0.0: Abort the build with an error message.

Also added a test for the integration of the BUILD struct and the tagger
package, which is used by kaniko.go.

* Update readme to note that expand-tag and auto-tag don't support artifacts
2022-02-10 13:06:14 +05:30
Shubham Agrawal bebe65a6c2 Revert "Upgrade kaniko version to 1.7.0 (#37)"
This reverts commit 0a4b18dbcb.

Kaniko 1.7.0 version is unable to push latest tag on gcr:
https://github.com/GoogleContainerTools/kaniko/issues/1786#issuecomment-951369997
2022-02-08 17:16:47 +05:30
Shubham Agrawal 0a4b18dbcb Upgrade kaniko version to 1.7.0 (#37) 2022-02-07 19:55:05 +05:30
JimZhang d381ac6700 Fix "--cache-ttl" flag missing unit in duration (#35) 2022-02-07 19:13:29 +05:30
Kyle Lemons 39f3398dfe Make plugins/kaniko behave the same as plugins/kaniko-{ecr,gcr} by prefixing the registry to the repo (#31) 2022-01-20 00:41:45 +05:30
Shubham Agrawal 59e09c14de Add support for custom platform (#32) 2021-12-01 17:10:28 +05:30
Shubham Agrawal 5e7bcabe6a Make json key optional for GCR push (#30) 2021-10-18 17:06:53 +05:30
Kyle Lemons 0a35538489 Add support for automatic tagging (:1, :1.2, :1.2.3, etc) for semantic versions (#22) 2021-10-18 00:05:18 +05:30
Michael Boke 2172c5b7cb updated kaniko executer version to 1.6.0 to solve the docker registry authentication issues (#28) 2021-10-12 16:39:32 +05:30
Shubham Agrawal 9388a47a4c Updated go version for security fixes (#29) 2021-10-12 16:38:58 +05:30
Colin Hoglund 609d203bed support dockerhub credentials when pulling with kaniko-ecr (#27) 2021-09-16 10:12:03 +05:30
Simas Čepaitis e86d4583a7 Add ECR policy management support (#26) 2021-09-08 15:19:52 +05:30
Colin Hoglund 6b4393acf8 Do not require username/password with no_push: true (#25)
* allow --no-push to build without authentication

* linting

* setup no-push auth when credentials are not empty
2021-09-01 11:45:50 +05:30
Colin Hoglund 00a65ec0b5 Add support for creating ECR repos (#24) 2021-08-28 18:37:26 +05:30
Shubham Agrawal dbd6efc157 Add option to provide log verbosity (#23) 2021-08-20 16:38:35 +05:30
Rauny e65b7b3ada add flag --no-push (#21) 2021-04-29 20:53:43 +05:30
Aleksandar Radisavljevic df81f82f84 Add support for printing published docker image metadata to a file (#17) 2021-04-29 15:35:57 +05:30
Rauny 43db3f2ccc add support for public ecr (#20) 2021-04-27 00:05:18 +05:30
Shubham Agrawal 71f15eb3f4 Make cache repo relative to registry for ecr/gcr (#19) 2021-04-21 12:55:13 +05:30
Shubham Agrawal 4612825d41 Allow remote caching of docker layers in kaniko build (#16) 2021-04-08 00:05:53 +05:30
Shubham Agrawal 0933926fe2 Updated drone yml to update docker latest image (#15) 2021-03-19 17:46:22 +05:30
Shubham Agrawal 658478d5ae Add snapshot mode support (#13) 2021-03-02 21:15:44 +05:30
Beniamin 9cca954ec6 add skip-tls-verify flag for insecure private registries (#11)
Co-authored-by: beniamin.calota <beniamin.calota@emag.ro>
2021-02-18 13:49:21 +05:30
Shubham Agrawal 3e4dad8cae Merge pull request #10 from drone/fix_pipeline
Fix pipeline yaml with auto tag suffix
2021-01-30 00:10:51 +05:30
Shubham Agrawal 69d5e73564 Fix pipeline yaml with auto tag suffix 2021-01-30 00:09:22 +05:30
Shubham Agrawal b33681a9b9 Merge pull request #9 from drone/improve_err
Log error if dockerfile does not exist at provided path
2021-01-29 14:41:19 +05:30
Shubham Agrawal cdd1510210 Log error if dockerfile does not exist at provided path 2021-01-29 14:39:06 +05:30
Shubham Agrawal fa7726153d Merge pull request #8 from drone/ecr_iam
Make access key & secret optional in case of iam role usage on EKS cluster
2021-01-20 00:28:57 +05:30
Shubham Agrawal 49309bfa42 Make access key & secret optional in case of iam role usage on EKS cluster 2021-01-20 00:25:23 +05:30
Shubham Agrawal 428642719b Merge pull request #7 from drone/fix_label
Fix label usage
2021-01-18 21:15:01 +05:30
Shubham Agrawal 33f15bdebe Fix label usage 2021-01-18 21:12:53 +05:30
Shubham Agrawal 10df8f28b9 Merge pull request #6 from drone/fix_ecr
Fix kaniko ecr publish
2020-12-02 15:20:00 +05:30
Shubham Agrawal 17072a25f1 Fix ecr publish 2020-12-02 15:17:28 +05:30
Shubham Agrawal 26c93eccd1 Merge pull request #5 from drone/fix_gcr
Fix kaniko-gcr docker file
2020-11-26 23:50:20 +05:30
Shubham Agrawal ee562a4a1b Fix kaniko-gcr docker file 2020-11-26 23:47:00 +05:30
Shubham Agrawal e200b5c566 Merge pull request #4 from drone/v2_registry
fix docker v2 registry issue
2020-11-26 16:32:29 +05:30
Shubham Agrawal 2c637d285e fix docker v2 registry issue 2020-11-26 16:29:05 +05:30
Shubham Agrawal 4be32f2451 Merge pull request #3 from drone/fix_build_script
fix build script
2020-11-26 11:47:54 +05:30
Shubham Agrawal 5ba1a0ead7 fix build script 2020-11-26 11:45:10 +05:30
Shubham Agrawal ef7bb68898 Merge pull request #2 from drone/fix_image
Fix docker file used for kaniko-docker image
2020-11-25 23:44:38 +05:30
Shubham Agrawal 9a7b245d90 Fix docker file for kaniko-docker 2020-11-25 23:42:56 +05:30
Shubham Agrawal 0d853fd119 Merge pull request #1 from drone/version_update
Updated kaniko base image to v1.3.0
2020-11-24 12:07:33 +05:30
34 changed files with 1874 additions and 109 deletions
+178 -2
View File
@@ -4,7 +4,7 @@ name: default
steps:
- name: build
image: golang
image: golang:1.18
commands:
- go test ./...
- sh scripts/build.sh
@@ -14,30 +14,206 @@ steps:
settings:
repo: plugins/kaniko
auto_tag: true
dockerfile: docker/gcr/Dockerfile.linux.amd64
auto_tag_suffix: linux-amd64
daemon_off: false
dockerfile: docker/docker/Dockerfile.linux.amd64
username:
from_secret: docker_username
password:
from_secret: docker_password
when:
event:
exclude:
- pull_request
- name: gcr
image: plugins/docker
settings:
repo: plugins/kaniko-gcr
auto_tag: true
auto_tag_suffix: linux-amd64
daemon_off: false
dockerfile: docker/gcr/Dockerfile.linux.amd64
username:
from_secret: docker_username
password:
from_secret: docker_password
when:
event:
exclude:
- pull_request
- name: ecr
image: plugins/docker
settings:
repo: plugins/kaniko-ecr
auto_tag: true
auto_tag_suffix: linux-amd64
daemon_off: false
dockerfile: docker/ecr/Dockerfile.linux.amd64
username:
from_secret: docker_username
password:
from_secret: docker_password
when:
event:
exclude:
- pull_request
- name: docker-kaniko-v1-8
image: plugins/docker
settings:
repo: plugins/kaniko
auto_tag: true
auto_tag_suffix: linux-amd64-kaniko1.8.1
daemon_off: false
dockerfile: docker/docker/Dockerfile.linux.amd64.kaniko1.8.1
username:
from_secret: docker_username
password:
from_secret: docker_password
when:
event:
exclude:
- pull_request
- name: gcr-kaniko-v1-8
image: plugins/docker
settings:
repo: plugins/kaniko-gcr
auto_tag: true
auto_tag_suffix: linux-amd64-kaniko1.8.1
daemon_off: false
dockerfile: docker/gcr/Dockerfile.linux.amd64.kaniko1.8.1
username:
from_secret: docker_username
password:
from_secret: docker_password
when:
event:
exclude:
- pull_request
- name: ecr-kaniko-v1-8
image: plugins/docker
settings:
repo: plugins/kaniko-ecr
auto_tag: true
auto_tag_suffix: linux-amd64-kaniko1.8.1
daemon_off: false
dockerfile: docker/ecr/Dockerfile.linux.amd64.kaniko1.8.1
username:
from_secret: docker_username
password:
from_secret: docker_password
when:
event:
exclude:
- pull_request
---
kind: pipeline
type: docker
name: notifications-docker
platform:
os: linux
arch: amd64
steps:
- name: manifest-docker
pull: always
image: plugins/manifest
settings:
auto_tag: true
ignore_missing: true
password:
from_secret: docker_password
spec: docker/docker/manifest.tmpl
username:
from_secret: docker_username
- name: manifest-gcr
pull: always
image: plugins/manifest
settings:
auto_tag: true
ignore_missing: true
password:
from_secret: docker_password
spec: docker/gcr/manifest.tmpl
username:
from_secret: docker_username
- name: manifest-ecr
pull: always
image: plugins/manifest
settings:
auto_tag: true
ignore_missing: true
password:
from_secret: docker_password
spec: docker/ecr/manifest.tmpl
username:
from_secret: docker_username
trigger:
ref:
- refs/heads/main
- "refs/tags/**"
depends_on:
- default
---
kind: pipeline
type: docker
name: notifications-docker-kaniko1-8
platform:
os: linux
arch: amd64
steps:
- name: manifest-docker
pull: always
image: plugins/manifest
settings:
auto_tag: false
ignore_missing: true
password:
from_secret: docker_password
spec: docker/docker/manifest-kaniko1.8.1.tmpl
username:
from_secret: docker_username
- name: manifest-gcr
pull: always
image: plugins/manifest
settings:
auto_tag: false
ignore_missing: true
password:
from_secret: docker_password
spec: docker/gcr/manifest-kaniko1.8.1.tmpl
username:
from_secret: docker_username
- name: manifest-ecr
pull: always
image: plugins/manifest
settings:
auto_tag: false
ignore_missing: true
password:
from_secret: docker_password
spec: docker/ecr/manifest-kaniko1.8.1.tmpl
username:
from_secret: docker_username
trigger:
ref:
- refs/heads/main
- "refs/tags/**"
depends_on:
- default
+1
View File
@@ -1,3 +1,4 @@
release
coverage.out
vendor
.idea
+79 -2
View File
@@ -25,7 +25,7 @@ Build the Docker images with the following commands:
docker build \
--label org.label-schema.build-date=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
--label org.label-schema.vcs-ref=$(git rev-parse --short HEAD) \
--file docker/docker/Dockerfile.linux.amd64 --tag plugins/kaniko-docker .
--file docker/docker/Dockerfile.linux.amd64 --tag plugins/kaniko .
docker build \
--label org.label-schema.build-date=$(date -u +"%Y-%m-%dT%H:%M:%SZ") \
@@ -39,6 +39,7 @@ docker build \
```
## Usage
### Manual Tagging
```console
docker run --rm \
@@ -49,5 +50,81 @@ docker run --rm \
-e PLUGIN_PASSWORD=bar \
-v $(pwd):/drone \
-w /drone \
plugins/kaniko-docker
plugins/kaniko:linux-amd64
```
With expanded tagging enabled, semantic versions can be passed to PLUGIN_TAGS directly for expansion.
**Note**: this feature only works for build labels. Artifact labels are not supported.
```console
docker run --rm \
-e PLUGIN_TAGS=v1.2.3,latest \
-e PLUGIN_EXPAND_TAG=true \
-v $(pwd):/drone \
-w /drone \
plugins/kaniko:linux-amd64
```
would both be equivalent to
```
PLUGIN_TAGS=1,1.2,1.2.3,latest
```
This allows for passing `$DRONE_TAG` directly as a tag for repos that use [semver](https://semver.org) tags.
To avoid confusion between repo tags and image tags, `PLUGIN_EXPAND_TAG` also recognizes a semantic version
without the `v` prefix. As such, the following is also equivalent to the above:
```console
docker run --rm \
-e PLUGIN_TAGS=1.2.3,latest \
-e PLUGIN_EXPAND_TAG=true \
-v $(pwd):/drone \
-w /drone \
plugins/kaniko:linux-amd64
```
### Auto Tagging
The [auto tag feature](https://plugins.drone.io/drone-plugins/drone-docker) of docker plugin is also supported.
When auto tagging is enabled, if any of the case is matched below, a docker build will be pushed with auto generated tags. Otherwise the docker build will be skipped.
**Note**: this feature only works for build labels. Artifact labels are not supported.
#### Git Tag Push:
```console
docker run --rm \
-e DRONE_COMMIT_REF=refs/tags/v1.2.3 \
-e PLUGIN_REPO=foo/bar \
-e PLUGIN_USERNAME=foo \
-e PLUGIN_PASSWORD=bar \
-e PLUGIN_AUTO_TAG=true \
-v $(pwd):/drone \
-w /drone \
plugins/kaniko:linux-amd64
```
Tags to push:
- 1.2.3
- 1.2
- 1
#### Git Commit Push in default branch:
```console
docker run --rm \
-e DRONE_COMMIT_REF=refs/heads/master \
-e DRONE_REPO_BRANCH=main \
-e PLUGIN_REPO=foo/bar \
-e PLUGIN_USERNAME=foo \
-e PLUGIN_PASSWORD=bar \
-e PLUGIN_AUTO_TAG=true \
-v $(pwd):/drone \
-w /drone \
plugins/kaniko:linux-amd64
```
Tags to push:
- latest
+157 -12
View File
@@ -5,6 +5,7 @@ import (
"fmt"
"io/ioutil"
"os"
"strings"
"github.com/joho/godotenv"
"github.com/pkg/errors"
@@ -12,12 +13,19 @@ import (
"github.com/urfave/cli"
kaniko "github.com/drone/drone-kaniko"
"github.com/drone/drone-kaniko/pkg/artifact"
)
const (
// Docker file path
dockerPath string = "/kaniko/.docker"
dockerConfigPath string = "/kaniko/.docker/config.json"
v1RegistryURL string = "https://index.docker.io/v1/" // Default registry
v2RegistryURL string = "https://index.docker.io/v2/" // v2 registry is not supported
v2HubRegistryURL string = "https://registry.hub.docker.com/v2/"
defaultDigestFile string = "/kaniko/digest-file"
)
var (
@@ -27,7 +35,9 @@ var (
func main() {
// Load env-file if it exists first
if env := os.Getenv("PLUGIN_ENV_FILE"); env != "" {
godotenv.Load(env)
if err := godotenv.Load(env); err != nil {
logrus.Fatal(err)
}
}
app := cli.NewApp()
@@ -48,6 +58,16 @@ func main() {
Value: ".",
EnvVar: "PLUGIN_CONTEXT",
},
cli.StringFlag{
Name: "drone-commit-ref",
Usage: "git commit ref passed by Drone",
EnvVar: "DRONE_COMMIT_REF",
},
cli.StringFlag{
Name: "drone-repo-branch",
Usage: "git repository default branch passed by Drone",
EnvVar: "DRONE_REPO_BRANCH",
},
cli.StringSliceFlag{
Name: "tags",
Usage: "build tags",
@@ -55,6 +75,26 @@ func main() {
EnvVar: "PLUGIN_TAGS",
FilePath: ".tags",
},
cli.BoolFlag{
Name: "expand-repo",
Usage: "Prepends the registry url to the repo if registry url is not specified in repo name",
EnvVar: "PLUGIN_EXPAND_REPO",
},
cli.BoolFlag{
Name: "expand-tag",
Usage: "enable for semver tagging",
EnvVar: "PLUGIN_EXPAND_TAG",
},
cli.BoolFlag{
Name: "auto-tag",
Usage: "enable auto generation of build tags",
EnvVar: "PLUGIN_AUTO_TAG",
},
cli.StringFlag{
Name: "auto-tag-suffix",
Usage: "the suffix of auto build tags",
EnvVar: "PLUGIN_AUTO_TAG_SUFFIX",
},
cli.StringSliceFlag{
Name: "args",
Usage: "build args",
@@ -78,9 +118,14 @@ func main() {
cli.StringFlag{
Name: "registry",
Usage: "docker registry",
Value: "https://index.docker.io/v1/",
Value: v1RegistryURL,
EnvVar: "PLUGIN_REGISTRY",
},
cli.StringSliceFlag{
Name: "registry-mirrors",
Usage: "docker registry mirrors",
EnvVar: "PLUGIN_REGISTRY_MIRRORS",
},
cli.StringFlag{
Name: "username",
Usage: "docker username",
@@ -91,6 +136,56 @@ func main() {
Usage: "docker password",
EnvVar: "PLUGIN_PASSWORD",
},
cli.BoolFlag{
Name: "skip-tls-verify",
Usage: "Skip registry tls verify",
EnvVar: "PLUGIN_SKIP_TLS_VERIFY",
},
cli.StringFlag{
Name: "snapshot-mode",
Usage: "Specify one of full, redo or time as snapshot mode",
EnvVar: "PLUGIN_SNAPSHOT_MODE",
},
cli.BoolFlag{
Name: "enable-cache",
Usage: "Set this flag to opt into caching with kaniko",
EnvVar: "PLUGIN_ENABLE_CACHE",
},
cli.StringFlag{
Name: "cache-repo",
Usage: "Remote repository that will be used to store cached layers. enable-cache needs to be set to use this flag",
EnvVar: "PLUGIN_CACHE_REPO",
},
cli.IntFlag{
Name: "cache-ttl",
Usage: "Cache timeout in hours. Defaults to two weeks.",
EnvVar: "PLUGIN_CACHE_TTL",
},
cli.StringFlag{
Name: "artifact-file",
Usage: "Artifact file location that will be generated by the plugin. This file will include information of docker images that are uploaded by the plugin.",
EnvVar: "PLUGIN_ARTIFACT_FILE",
},
cli.BoolFlag{
Name: "no-push",
Usage: "Set this flag if you only want to build the image, without pushing to a registry",
EnvVar: "PLUGIN_NO_PUSH",
},
cli.StringFlag{
Name: "verbosity",
Usage: "Set this flag with value as oneof <panic|fatal|error|warn|info|debug|trace> to set the logging level for kaniko. Defaults to info.",
EnvVar: "PLUGIN_VERBOSITY",
},
cli.StringFlag{
Name: "platform",
Usage: "Allows to build with another default platform than the host, similarly to docker build --platform",
EnvVar: "PLUGIN_PLATFORM",
},
cli.BoolFlag{
Name: "skip-unused-stages",
Usage: "build only used stages",
EnvVar: "PLUGIN_SKIP_UNUSED_STAGES",
},
}
if err := app.Run(os.Args); err != nil {
@@ -99,20 +194,48 @@ func main() {
}
func run(c *cli.Context) error {
err := createDockerCfgFile(c.String("username"), c.String("password"), c.String("registry"))
if err != nil {
return err
username := c.String("username")
noPush := c.Bool("no-push")
// only setup auth when pushing or credentials are defined
if !noPush || username != "" {
if err := createDockerCfgFile(username, c.String("password"), c.String("registry")); err != nil {
return err
}
}
plugin := kaniko.Plugin{
Build: kaniko.Build{
Dockerfile: c.String("dockerfile"),
Context: c.String("context"),
Tags: c.StringSlice("tags"),
Args: c.StringSlice("args"),
Target: c.String("target"),
Repo: c.String("repo"),
Labels: c.StringSlice("custom-labels"),
DroneCommitRef: c.String("drone-commit-ref"),
DroneRepoBranch: c.String("drone-repo-branch"),
Dockerfile: c.String("dockerfile"),
Context: c.String("context"),
Tags: c.StringSlice("tags"),
AutoTag: c.Bool("auto-tag"),
AutoTagSuffix: c.String("auto-tag-suffix"),
ExpandTag: c.Bool("expand-tag"),
Args: c.StringSlice("args"),
Target: c.String("target"),
Repo: buildRepo(c.String("registry"), c.String("repo"), c.Bool("expand-repo")),
Mirrors: c.StringSlice("registry-mirrors"),
Labels: c.StringSlice("custom-labels"),
SkipTlsVerify: c.Bool("skip-tls-verify"),
SnapshotMode: c.String("snapshot-mode"),
EnableCache: c.Bool("enable-cache"),
CacheRepo: buildRepo(c.String("registry"), c.String("cache-repo"), c.Bool("expand-repo")),
CacheTTL: c.Int("cache-ttl"),
DigestFile: defaultDigestFile,
NoPush: noPush,
Verbosity: c.String("verbosity"),
Platform: c.String("platform"),
SkipUnusedStages: c.Bool("skip-unused-stages"),
},
Artifact: kaniko.Artifact{
Tags: c.StringSlice("tags"),
Repo: buildRepo(c.String("registry"), c.String("repo"), c.Bool("expand-repo")),
Registry: c.String("registry"),
ArtifactFile: c.String("artifact-file"),
RegistryType: artifact.Docker,
},
}
return plugin.Exec()
@@ -130,6 +253,12 @@ func createDockerCfgFile(username, password, registry string) error {
return fmt.Errorf("Registry must be specified")
}
if registry == v2RegistryURL || registry == v2HubRegistryURL {
fmt.Println("Docker v2 registry is not supported in kaniko. Refer issue: https://github.com/GoogleContainerTools/kaniko/issues/1209")
fmt.Printf("Using v1 registry instead: %s\n", v1RegistryURL)
registry = v1RegistryURL
}
err := os.MkdirAll(dockerPath, 0600)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to create %s directory", dockerPath))
@@ -144,3 +273,19 @@ func createDockerCfgFile(username, password, registry string) error {
}
return nil
}
func buildRepo(registry, repo string, expandRepo bool) string {
if !expandRepo || registry == "" || registry == v1RegistryURL {
// No custom registry, just return the repo name
return repo
}
// Trim off trailing slash to prevent double slash when combining with repo
registry = strings.TrimSuffix(registry, "/")
if strings.HasPrefix(repo, registry+"/") {
// Repo already includes the registry prefix
// For backward compatibility, we won't add the prefix again.
return repo
}
// Prefix the repo with the registry
return registry + "/" + repo
}
+37
View File
@@ -0,0 +1,37 @@
package main
import "testing"
func Test_buildRepo(t *testing.T) {
tests := []struct {
name string
registry string
repo string
want string
}{
{
name: "dockerhub",
repo: "golang",
want: "golang",
},
{
name: "internal",
registry: "artifactory.example.com",
repo: "service",
want: "artifactory.example.com/service",
},
{
name: "backward_compatibility",
registry: "artifactory.example.com",
repo: "artifactory.example.com/service",
want: "artifactory.example.com/service",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := buildRepo(tt.registry, tt.repo, true); got != tt.want {
t.Errorf("buildRepo(%q, %q) = %v, want %v", tt.registry, tt.repo, got, tt.want)
}
})
}
}
+304 -26
View File
@@ -1,22 +1,34 @@
package main
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
"os"
"strings"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/ecr"
"github.com/aws/aws-sdk-go-v2/service/ecrpublic"
"github.com/aws/smithy-go"
kaniko "github.com/drone/drone-kaniko"
"github.com/drone/drone-kaniko/pkg/artifact"
"github.com/drone/drone-kaniko/pkg/docker"
"github.com/joho/godotenv"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"github.com/urfave/cli"
kaniko "github.com/drone/drone-kaniko"
)
const (
accessKeyEnv string = "AWS_ACCESS_KEY_ID"
secretKeyEnv string = "AWS_SECRET_ACCESS_KEY"
dockerConfigPath string = "/kaniko/.docker/config.json"
ecrPublicDomain string = "public.ecr.aws"
defaultDigestFile string = "/kaniko/digest-file"
)
var (
@@ -26,7 +38,9 @@ var (
func main() {
// Load env-file if it exists first
if env := os.Getenv("PLUGIN_ENV_FILE"); env != "" {
godotenv.Load(env)
if err := godotenv.Load(env); err != nil {
logrus.Fatal(err)
}
}
app := cli.NewApp()
@@ -41,12 +55,32 @@ func main() {
Value: "Dockerfile",
EnvVar: "PLUGIN_DOCKERFILE",
},
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: "context",
Usage: "build context",
Value: ".",
EnvVar: "PLUGIN_CONTEXT",
},
cli.StringFlag{
Name: "drone-commit-ref",
Usage: "git commit ref passed by Drone",
EnvVar: "DRONE_COMMIT_REF",
},
cli.StringFlag{
Name: "drone-repo-branch",
Usage: "git repository default branch passed by Drone",
EnvVar: "DRONE_REPO_BRANCH",
},
cli.StringSliceFlag{
Name: "tags",
Usage: "build tags",
@@ -54,6 +88,21 @@ func main() {
EnvVar: "PLUGIN_TAGS",
FilePath: ".tags",
},
cli.BoolFlag{
Name: "expand-tag",
Usage: "enable for semver tagging",
EnvVar: "PLUGIN_EXPAND_TAG",
},
cli.BoolFlag{
Name: "auto-tag",
Usage: "enable auto generation of build tags",
EnvVar: "PLUGIN_AUTO_TAG",
},
cli.StringFlag{
Name: "auto-tag-suffix",
Usage: "the suffix of auto build tags",
EnvVar: "PLUGIN_AUTO_TAG_SUFFIX",
},
cli.StringSliceFlag{
Name: "args",
Usage: "build args",
@@ -69,6 +118,17 @@ func main() {
Usage: "docker repository",
EnvVar: "PLUGIN_REPO",
},
cli.BoolFlag{
Name: "create-repository",
Usage: "create ECR repository",
EnvVar: "PLUGIN_CREATE_REPOSITORY",
},
cli.StringFlag{
Name: "region",
Usage: "AWS region",
Value: "us-east-1",
EnvVar: "PLUGIN_REGION",
},
cli.StringSliceFlag{
Name: "custom-labels",
Usage: "additional k=v labels",
@@ -79,6 +139,11 @@ func main() {
Usage: "ECR registry",
EnvVar: "PLUGIN_REGISTRY",
},
cli.StringSliceFlag{
Name: "registry-mirrors",
Usage: "docker registry mirrors",
EnvVar: "PLUGIN_REGISTRY_MIRRORS",
},
cli.StringFlag{
Name: "access-key",
Usage: "ECR access key",
@@ -89,6 +154,61 @@ func main() {
Usage: "ECR secret key",
EnvVar: "PLUGIN_SECRET_KEY",
},
cli.StringFlag{
Name: "snapshot-mode",
Usage: "Specify one of full, redo or time as snapshot mode",
EnvVar: "PLUGIN_SNAPSHOT_MODE",
},
cli.StringFlag{
Name: "lifecycle-policy",
Usage: "Path to lifecycle policy file",
EnvVar: "PLUGIN_LIFECYCLE_POLICY",
},
cli.StringFlag{
Name: "repository-policy",
Usage: "Path to repository policy file",
EnvVar: "PLUGIN_REPOSITORY_POLICY",
},
cli.BoolFlag{
Name: "enable-cache",
Usage: "Set this flag to opt into caching with kaniko",
EnvVar: "PLUGIN_ENABLE_CACHE",
},
cli.StringFlag{
Name: "cache-repo",
Usage: "Remote repository that will be used to store cached layers. Cache repo should be present in specified registry. enable-cache needs to be set to use this flag",
EnvVar: "PLUGIN_CACHE_REPO",
},
cli.IntFlag{
Name: "cache-ttl",
Usage: "Cache timeout in hours. Defaults to two weeks.",
EnvVar: "PLUGIN_CACHE_TTL",
},
cli.StringFlag{
Name: "artifact-file",
Usage: "Artifact file location that will be generated by the plugin. This file will include information of docker images that are uploaded by the plugin.",
EnvVar: "PLUGIN_ARTIFACT_FILE",
},
cli.BoolFlag{
Name: "no-push",
Usage: "Set this flag if you only want to build the image, without pushing to a registry",
EnvVar: "PLUGIN_NO_PUSH",
},
cli.StringFlag{
Name: "verbosity",
Usage: "Set this flag with value as oneof <panic|fatal|error|warn|info|debug|trace> to set the logging level for kaniko. Defaults to info.",
EnvVar: "PLUGIN_VERBOSITY",
},
cli.StringFlag{
Name: "platform",
Usage: "Allows to build with another default platform than the host, similarly to docker build --platform",
EnvVar: "PLUGIN_PLATFORM",
},
cli.BoolFlag{
Name: "skip-unused-stages",
Usage: "build only used stages",
EnvVar: "PLUGIN_SKIP_UNUSED_STAGES",
},
}
if err := app.Run(os.Args); err != nil {
@@ -97,50 +217,208 @@ func main() {
}
func run(c *cli.Context) error {
err := setupECRAuth(c.String("access-key"), c.String("secret-key"), c.String("registry"))
repo := c.String("repo")
registry := c.String("registry")
region := c.String("region")
noPush := c.Bool("no-push")
dockerConfig, err := createDockerConfig(
c.String("docker-username"),
c.String("docker-password"),
c.String("access-key"),
c.String("secret-key"),
registry,
noPush,
)
if err != nil {
return err
}
jsonBytes, err := json.Marshal(dockerConfig)
if err != nil {
return err
}
if err := ioutil.WriteFile(dockerConfigPath, jsonBytes, 0644); err != nil {
return err
}
// only create repository when pushing and create-repository is true
if !noPush && c.Bool("create-repository") {
if err := createRepository(region, repo, registry); err != nil {
return err
}
}
if c.IsSet("lifecycle-policy") {
contents, err := ioutil.ReadFile(c.String("lifecycle-policy"))
if err != nil {
logrus.Fatal(err)
}
if err := uploadLifeCyclePolicy(region, repo, string(contents)); err != nil {
logrus.Fatal(fmt.Sprintf("error uploading ECR lifecycle policy: %v", err))
}
}
if c.IsSet("repository-policy") {
contents, err := ioutil.ReadFile(c.String("repository-policy"))
if err != nil {
logrus.Fatal(err)
}
if err := uploadRepositoryPolicy(region, repo, registry, string(contents)); err != nil {
logrus.Fatal(fmt.Sprintf("error uploading ECR lifecycle policy: %v", err))
}
}
plugin := kaniko.Plugin{
Build: kaniko.Build{
Dockerfile: c.String("dockerfile"),
Context: c.String("context"),
Tags: c.StringSlice("tags"),
Args: c.StringSlice("args"),
Target: c.String("target"),
Repo: c.String("repo"),
Labels: c.StringSlice("custom-labels"),
DroneCommitRef: c.String("drone-commit-ref"),
DroneRepoBranch: c.String("drone-repo-branch"),
Dockerfile: c.String("dockerfile"),
Context: c.String("context"),
Tags: c.StringSlice("tags"),
AutoTag: c.Bool("auto-tag"),
AutoTagSuffix: c.String("auto-tag-suffix"),
ExpandTag: c.Bool("expand-tag"),
Args: c.StringSlice("args"),
Target: c.String("target"),
Repo: fmt.Sprintf("%s/%s", c.String("registry"), c.String("repo")),
Mirrors: c.StringSlice("registry-mirrors"),
Labels: c.StringSlice("custom-labels"),
SnapshotMode: c.String("snapshot-mode"),
EnableCache: c.Bool("enable-cache"),
CacheRepo: fmt.Sprintf("%s/%s", c.String("registry"), c.String("cache-repo")),
CacheTTL: c.Int("cache-ttl"),
DigestFile: defaultDigestFile,
NoPush: noPush,
Verbosity: c.String("verbosity"),
Platform: c.String("platform"),
SkipUnusedStages: c.Bool("skip-unused-stages"),
},
Artifact: kaniko.Artifact{
Tags: c.StringSlice("tags"),
Repo: c.String("repo"),
Registry: c.String("registry"),
ArtifactFile: c.String("artifact-file"),
RegistryType: artifact.ECR,
},
}
return plugin.Exec()
}
func setupECRAuth(accessKey, secretKey, registry string) error {
if accessKey == "" {
return fmt.Errorf("Access key must be specified")
func createDockerConfig(dockerUsername, dockerPassword, accessKey, secretKey, registry string, noPush bool) (*docker.Config, error) {
dockerConfig := docker.NewConfig()
if dockerUsername != "" {
dockerConfig.SetAuth(docker.RegistryV1, dockerUsername, dockerPassword)
}
if secretKey == "" {
return fmt.Errorf("Secret key must be specified")
// only setup auth when pushing or credentials are defined
if !noPush || accessKey != "" {
if registry == "" {
return nil, fmt.Errorf("registry must be specified")
}
// If IAM role is used, access key & secret key are not required
if accessKey != "" && secretKey != "" {
err := os.Setenv(accessKeyEnv, accessKey)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("failed to set %s environment variable", accessKeyEnv))
}
err = os.Setenv(secretKeyEnv, secretKey)
if err != nil {
return nil, errors.Wrap(err, fmt.Sprintf("failed to set %s environment variable", secretKeyEnv))
}
}
dockerConfig.SetCredHelper(ecrPublicDomain, "ecr-login")
dockerConfig.SetCredHelper(registry, "ecr-login")
}
return dockerConfig, nil
}
func createRepository(region, repo, registry string) error {
if registry == "" {
return fmt.Errorf("Registry must be specified")
return fmt.Errorf("registry must be specified")
}
err := os.Setenv(accessKeyEnv, accessKey)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to set %s environment variable", accessKeyEnv))
if repo == "" {
return fmt.Errorf("repo must be specified")
}
err = os.Setenv(secretKeyEnv, secretKey)
cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(region))
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to set %s environment variable", secretKeyEnv))
return errors.Wrap(err, "failed to load aws config")
}
jsonBytes := []byte(fmt.Sprintf(`{"credStore": "ecr-login", "credHelpers": {"%s": "ecr-login"}}`, registry))
err = ioutil.WriteFile(dockerConfigPath, jsonBytes, 0644)
if err != nil {
return errors.Wrap(err, "failed to create docker config file")
var createErr error
//create public repo
//if registry string starts with public domain (ex: public.ecr.aws/example-registry)
if isRegistryPublic(registry) {
svc := ecrpublic.NewFromConfig(cfg)
_, createErr = svc.CreateRepository(context.TODO(), &ecrpublic.CreateRepositoryInput{RepositoryName: &repo})
//create private repo
} else {
svc := ecr.NewFromConfig(cfg)
_, createErr = svc.CreateRepository(context.TODO(), &ecr.CreateRepositoryInput{RepositoryName: &repo})
}
var apiError smithy.APIError
if errors.As(createErr, &apiError) && apiError.ErrorCode() != "RepositoryAlreadyExistsException" {
return errors.Wrap(createErr, "failed to create repository")
}
return nil
}
func uploadLifeCyclePolicy(region, repo, lifecyclePolicy string) (err error) {
cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(region))
if err != nil {
return errors.Wrap(err, "failed to load aws config")
}
svc := ecr.NewFromConfig(cfg)
input := &ecr.PutLifecyclePolicyInput{
LifecyclePolicyText: aws.String(lifecyclePolicy),
RepositoryName: aws.String(repo),
}
_, err = svc.PutLifecyclePolicy(context.TODO(), input)
return err
}
func uploadRepositoryPolicy(region, repo, registry, repositoryPolicy string) (err error) {
cfg, err := config.LoadDefaultConfig(context.TODO(), config.WithRegion(region))
if err != nil {
return errors.Wrap(err, "failed to load aws config")
}
if isRegistryPublic(registry) {
svc := ecrpublic.NewFromConfig(cfg)
input := &ecrpublic.SetRepositoryPolicyInput{
PolicyText: aws.String(repositoryPolicy),
RepositoryName: aws.String(repo),
}
_, err = svc.SetRepositoryPolicy(context.TODO(), input)
} else {
svc := ecr.NewFromConfig(cfg)
input := &ecr.SetRepositoryPolicyInput{
PolicyText: aws.String(repositoryPolicy),
RepositoryName: aws.String(repo),
}
_, err = svc.SetRepositoryPolicy(context.TODO(), input)
}
return err
}
func isRegistryPublic(registry string) bool {
return strings.HasPrefix(registry, ecrPublicDomain)
}
+31
View File
@@ -0,0 +1,31 @@
package main
import (
"reflect"
"testing"
"github.com/drone/drone-kaniko/pkg/docker"
)
func TestCreateDockerConfig(t *testing.T) {
got, err := createDockerConfig(
"docker-username",
"docker-password",
"access-key",
"secret-key",
"ecr-registry",
false,
)
if err != nil {
t.Error("failed to create docker config")
}
want := docker.NewConfig()
want.SetAuth(docker.RegistryV1, "docker-username", "docker-password")
want.SetCredHelper(docker.RegistryECRPublic, "ecr-login")
want.SetCredHelper("ecr-registry", "ecr-login")
if !reflect.DeepEqual(want, got) {
t.Errorf("not equal:\n want: %#v\n got: %#v", want, got)
}
}
+120 -19
View File
@@ -11,12 +11,15 @@ import (
"github.com/urfave/cli"
kaniko "github.com/drone/drone-kaniko"
"github.com/drone/drone-kaniko/pkg/artifact"
)
const (
// GCR JSON key file path
gcrKeyPath string = "/kaniko/gcr.json"
gcrKeyPath string = "/kaniko/config.json"
gcrEnvVariable string = "GOOGLE_APPLICATION_CREDENTIALS"
defaultDigestFile string = "/kaniko/digest-file"
)
var (
@@ -26,7 +29,9 @@ var (
func main() {
// Load env-file if it exists first
if env := os.Getenv("PLUGIN_ENV_FILE"); env != "" {
godotenv.Load(env)
if err := godotenv.Load(env); err != nil {
logrus.Fatal(err)
}
}
app := cli.NewApp()
@@ -47,6 +52,16 @@ func main() {
Value: ".",
EnvVar: "PLUGIN_CONTEXT",
},
cli.StringFlag{
Name: "drone-commit-ref",
Usage: "git commit ref passed by Drone",
EnvVar: "DRONE_COMMIT_REF",
},
cli.StringFlag{
Name: "drone-repo-branch",
Usage: "git repository default branch passed by Drone",
EnvVar: "DRONE_REPO_BRANCH",
},
cli.StringSliceFlag{
Name: "tags",
Usage: "build tags",
@@ -54,6 +69,21 @@ func main() {
EnvVar: "PLUGIN_TAGS",
FilePath: ".tags",
},
cli.BoolFlag{
Name: "expand-tag",
Usage: "enable for semver tagging",
EnvVar: "PLUGIN_EXPAND_TAG",
},
cli.BoolFlag{
Name: "auto-tag",
Usage: "enable auto generation of build tags",
EnvVar: "PLUGIN_AUTO_TAG",
},
cli.StringFlag{
Name: "auto-tag-suffix",
Usage: "the suffix of auto build tags",
EnvVar: "PLUGIN_AUTO_TAG_SUFFIX",
},
cli.StringSliceFlag{
Name: "args",
Usage: "build args",
@@ -80,11 +110,61 @@ func main() {
Value: "gcr.io",
EnvVar: "PLUGIN_REGISTRY",
},
cli.StringSliceFlag{
Name: "registry-mirrors",
Usage: "docker registry mirrors",
EnvVar: "PLUGIN_REGISTRY_MIRRORS",
},
cli.StringFlag{
Name: "json-key",
Usage: "docker username",
EnvVar: "PLUGIN_JSON_KEY",
},
cli.StringFlag{
Name: "snapshot-mode",
Usage: "Specify one of full, redo or time as snapshot mode",
EnvVar: "PLUGIN_SNAPSHOT_MODE",
},
cli.BoolFlag{
Name: "enable-cache",
Usage: "Set this flag to opt into caching with kaniko",
EnvVar: "PLUGIN_ENABLE_CACHE",
},
cli.StringFlag{
Name: "cache-repo",
Usage: "Remote repository that will be used to store cached layers. Cache repo should be present in specified registry. enable-cache needs to be set to use this flag",
EnvVar: "PLUGIN_CACHE_REPO",
},
cli.IntFlag{
Name: "cache-ttl",
Usage: "Cache timeout in hours. Defaults to two weeks.",
EnvVar: "PLUGIN_CACHE_TTL",
},
cli.StringFlag{
Name: "artifact-file",
Usage: "Artifact file location that will be generated by the plugin. This file will include information of docker images that are uploaded by the plugin.",
EnvVar: "PLUGIN_ARTIFACT_FILE",
},
cli.BoolFlag{
Name: "no-push",
Usage: "Set this flag if you only want to build the image, without pushing to a registry",
EnvVar: "PLUGIN_NO_PUSH",
},
cli.StringFlag{
Name: "verbosity",
Usage: "Set this flag as --verbosity=<panic|fatal|error|warn|info|debug|trace> to set the logging level for kaniko. Defaults to info.",
EnvVar: "PLUGIN_VERBOSITY",
},
cli.StringFlag{
Name: "platform",
Usage: "Allows to build with another default platform than the host, similarly to docker build --platform",
EnvVar: "PLUGIN_PLATFORM",
},
cli.BoolFlag{
Name: "skip-unused-stages",
Usage: "build only used stages",
EnvVar: "PLUGIN_SKIP_UNUSED_STAGES",
},
}
if err := app.Run(os.Args); err != nil {
@@ -93,34 +173,55 @@ func main() {
}
func run(c *cli.Context) error {
err := setupGCRAuth(c.String("json-key"))
if err != nil {
return err
}
noPush := c.Bool("no-push")
jsonKey := c.String("json-key")
if c.String("repo") == "" {
return fmt.Errorf("repo must be specified")
// JSON key may not be set in the following cases:
// 1. Image does not need to be pushed to GCR.
// 2. Workload identity is set on GKE in which pod will inherit the credentials via service account.
if jsonKey != "" {
if err := setupGCRAuth(jsonKey); err != nil {
return err
}
}
plugin := kaniko.Plugin{
Build: kaniko.Build{
Dockerfile: c.String("dockerfile"),
Context: c.String("context"),
Tags: c.StringSlice("tags"),
Args: c.StringSlice("args"),
Target: c.String("target"),
Repo: fmt.Sprintf("%s/%s", c.String("registry"), c.String("repo")),
Labels: c.StringSlice("custom-labels"),
DroneCommitRef: c.String("drone-commit-ref"),
DroneRepoBranch: c.String("drone-repo-branch"),
Dockerfile: c.String("dockerfile"),
Context: c.String("context"),
Tags: c.StringSlice("tags"),
AutoTag: c.Bool("auto-tag"),
AutoTagSuffix: c.String("auto-tag-suffix"),
ExpandTag: c.Bool("expand-tag"),
Args: c.StringSlice("args"),
Target: c.String("target"),
Repo: fmt.Sprintf("%s/%s", c.String("registry"), c.String("repo")),
Mirrors: c.StringSlice("registry-mirrors"),
Labels: c.StringSlice("custom-labels"),
SnapshotMode: c.String("snapshot-mode"),
EnableCache: c.Bool("enable-cache"),
CacheRepo: fmt.Sprintf("%s/%s", c.String("registry"), c.String("cache-repo")),
CacheTTL: c.Int("cache-ttl"),
DigestFile: defaultDigestFile,
NoPush: noPush,
Verbosity: c.String("verbosity"),
Platform: c.String("platform"),
SkipUnusedStages: c.Bool("skip-unused-stages"),
},
Artifact: kaniko.Artifact{
Tags: c.StringSlice("tags"),
Repo: c.String("repo"),
Registry: c.String("registry"),
ArtifactFile: c.String("artifact-file"),
RegistryType: artifact.GCR,
},
}
return plugin.Exec()
}
func setupGCRAuth(jsonKey string) error {
if jsonKey == "" {
return fmt.Errorf("GCR JSON key must be specified")
}
err := ioutil.WriteFile(gcrKeyPath, []byte(jsonKey), 0644)
if err != nil {
return errors.Wrap(err, "failed to write GCR JSON key")
+1 -4
View File
@@ -1,7 +1,4 @@
FROM gcr.io/kaniko-project/executor:amd64-v1.3.0
ENV HOME /root
ENV USER root
FROM gcr.io/kaniko-project/executor:v1.6.0
ADD release/linux/amd64/kaniko-docker /kaniko/
ENTRYPOINT ["/kaniko/kaniko-docker"]
@@ -0,0 +1,4 @@
FROM gcr.io/kaniko-project/executor:v1.8.1
ADD release/linux/amd64/kaniko-docker /kaniko/
ENTRYPOINT ["/kaniko/kaniko-docker"]
+1 -1
View File
@@ -1,4 +1,4 @@
FROM gcr.io/kaniko-project/executor:arm64-v1.3.0
FROM gcr.io/kaniko-project/executor:arm64-v1.6.0
ENV HOME /root
ENV USER root
+13
View File
@@ -0,0 +1,13 @@
image: plugins/kaniko:{{#if build.tag}}{{trimPrefix "v" build.tag}}-kaniko1.8.1{{else}}latest-kaniko1.8.1{{/if}}
{{#if build.tags}}
tags:
{{#each build.tags}}
- {{this}}
{{/each}}
{{/if}}
manifests:
-
image: plugins/kaniko:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64-kaniko1.8.1
platform:
architecture: amd64
os: linux
+1 -4
View File
@@ -1,7 +1,4 @@
FROM gcr.io/kaniko-project/executor:amd64-v1.3.0
ENV HOME /root
ENV USER root
FROM gcr.io/kaniko-project/executor:v1.6.0
ADD release/linux/amd64/kaniko-ecr /kaniko/
ENTRYPOINT ["/kaniko/kaniko-ecr"]
@@ -0,0 +1,4 @@
FROM gcr.io/kaniko-project/executor:v1.8.1
ADD release/linux/amd64/kaniko-ecr /kaniko/
ENTRYPOINT ["/kaniko/kaniko-ecr"]
+1 -1
View File
@@ -1,4 +1,4 @@
FROM gcr.io/kaniko-project/executor:arm64-v1.3.0
FROM gcr.io/kaniko-project/executor:arm64-v1.6.0
ENV HOME /root
ENV USER root
+13
View File
@@ -0,0 +1,13 @@
image: plugins/kaniko-ecr:{{#if build.tag}}{{trimPrefix "v" build.tag}}-kaniko1.8.1{{else}}latest-kaniko1.8.1{{/if}}
{{#if build.tags}}
tags:
{{#each build.tags}}
- {{this}}
{{/each}}
{{/if}}
manifests:
-
image: plugins/kaniko-ecr:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64-kaniko1.8.1
platform:
architecture: amd64
os: linux
+2 -5
View File
@@ -1,7 +1,4 @@
FROM gcr.io/kaniko-project/executor:amd64-v1.3.0
ENV HOME /root
ENV USER root
FROM gcr.io/kaniko-project/executor:v1.6.0
ADD release/linux/amd64/kaniko-gcr /kaniko/
ENTRYPOINT ["/kaniko/kaniko-gcr"]
ENTRYPOINT ["/kaniko/kaniko-gcr"]
@@ -0,0 +1,4 @@
FROM gcr.io/kaniko-project/executor:v1.8.1
ADD release/linux/amd64/kaniko-gcr /kaniko/
ENTRYPOINT ["/kaniko/kaniko-gcr"]
+2 -2
View File
@@ -1,7 +1,7 @@
FROM gcr.io/kaniko-project/executor:arm64-v1.3.0
FROM gcr.io/kaniko-project/executor:arm64-v1.6.0
ENV HOME /root
ENV USER root
ADD release/linux/arm64/kaniko-gcr /kaniko/
ENTRYPOINT ["/kaniko/kaniko-gcr"]
ENTRYPOINT ["/kaniko/kaniko-gcr"]
+13
View File
@@ -0,0 +1,13 @@
image: plugins/kaniko-gcr:{{#if build.tag}}{{trimPrefix "v" build.tag}}-kaniko1.8.1{{else}}latest-kaniko1.8.1{{/if}}
{{#if build.tags}}
tags:
{{#each build.tags}}
- {{this}}
{{/each}}
{{/if}}
manifests:
-
image: plugins/kaniko-gcr:{{#if build.tag}}{{trimPrefix "v" build.tag}}-{{/if}}linux-amd64-kaniko1.8.1
platform:
architecture: amd64
os: linux
+25 -1
View File
@@ -1,10 +1,34 @@
module github.com/drone/drone-kaniko
require (
github.com/aws/aws-sdk-go-v2 v1.8.1
github.com/aws/aws-sdk-go-v2/config v1.6.1
github.com/aws/aws-sdk-go-v2/service/ecr v1.4.3
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.4.3
github.com/aws/smithy-go v1.7.0
github.com/coreos/go-semver v0.3.0
github.com/google/go-cmp v0.5.6
github.com/joho/godotenv v1.3.0
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.3.0
github.com/urfave/cli v1.22.2
golang.org/x/mod v0.4.2
)
go 1.13
require (
github.com/aws/aws-sdk-go-v2/credentials v1.3.3 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.4.1 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.2.1 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.2.3 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.3.3 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.6.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/konsorten/go-windows-terminal-sequences v1.0.1 // indirect
github.com/russross/blackfriday/v2 v2.0.1 // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 // indirect
golang.org/x/sys v0.0.0-20190412213103-97732733099d // indirect
)
go 1.18
+52 -4
View File
@@ -1,8 +1,40 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/aws/aws-sdk-go-v2 v1.8.1 h1:GcFgQl7MsBygmeeqXyV1ivrTEmsVz/rdFJaTcltG9ag=
github.com/aws/aws-sdk-go-v2 v1.8.1/go.mod h1:xEFuWz+3TYdlPRuo+CqATbeDWIWyaT5uAPwPaWtgse0=
github.com/aws/aws-sdk-go-v2/config v1.6.1 h1:qrZINaORyr78syO1zfD4l7r4tZjy0Z1l0sy4jiysyOM=
github.com/aws/aws-sdk-go-v2/config v1.6.1/go.mod h1:t/y3UPu0XEDy0cEw6mvygaBQaPzWiYAxfP2SzgtvclA=
github.com/aws/aws-sdk-go-v2/credentials v1.3.3 h1:A13QPatmUl41SqUfnuT3V0E3XiNGL6qNTOINbE8cZL4=
github.com/aws/aws-sdk-go-v2/credentials v1.3.3/go.mod h1:oVieKMT3m9BSfqhOfuQ+E0j/yN84ZAJ7Qv8Sfume/ak=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.4.1 h1:rc+fRGvlKbeSd9IFhFS1KWBs0XjTkq0CfK5xqyLgIp0=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.4.1/go.mod h1:+GTydg3uHmVlQdkRoetz6VHKbOMEYof70m19IpMLifc=
github.com/aws/aws-sdk-go-v2/internal/ini v1.2.1 h1:IkqRRUZTKaS16P2vpX+FNc2jq3JWa3c478gykQp4ow4=
github.com/aws/aws-sdk-go-v2/internal/ini v1.2.1/go.mod h1:Pv3WenDjI0v2Jl7UaMFIIbPOBbhn33RmmAmGgkXDoqY=
github.com/aws/aws-sdk-go-v2/service/ecr v1.4.3 h1:d356GPVp5MzJ4n/xCBc26wLmRti0DoWO4WzNfxSesrY=
github.com/aws/aws-sdk-go-v2/service/ecr v1.4.3/go.mod h1:HlFOVFXSvCfI2oUmd/Vv1IZKJhEVFQru38BBupEYWxs=
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.4.3 h1:EU9GrpMtGLCklSMLjuU6AZGG5wu6aiowxIgbfWwxrgs=
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.4.3/go.mod h1:AAI7iB1GPqxjyKHbzLpBJdmH9/dPr34pxeLFdkKsONA=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.2.3 h1:VxFCgxsqWe7OThOwJ5IpFX3xrObtuIH9Hg/NW7oot1Y=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.2.3/go.mod h1:7gcsONBmFoCcKrAqrm95trrMd2+C/ReYKP7Vfu8yHHA=
github.com/aws/aws-sdk-go-v2/service/sso v1.3.3 h1:K2gCnGvAASpz+jqP9iyr+F/KNjmTYf8aWOtTQzhmZ5w=
github.com/aws/aws-sdk-go-v2/service/sso v1.3.3/go.mod h1:Jgw5O+SK7MZ2Yi9Yvzb4PggAPYaFSliiQuWR0hNjexk=
github.com/aws/aws-sdk-go-v2/service/sts v1.6.2 h1:l504GWCoQi1Pk68vSUFGLmDIEMzRfVGNgLakDK+Uj58=
github.com/aws/aws-sdk-go-v2/service/sts v1.6.2/go.mod h1:RBhoMJB8yFToaCnbe0jNq5Dcdy0jp6LhHqg55rjClkM=
github.com/aws/smithy-go v1.7.0 h1:+cLHMRrDZvQ4wk+KuQ9yH6eEg6KZEJ9RI2IkDqnygCg=
github.com/aws/smithy-go v1.7.0/go.mod h1:SObp3lf9smib00L/v3U2eAKG8FyQ7iLrJnQiAmR5n+E=
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
@@ -17,16 +49,32 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5I
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.3.0 h1:hI/7Q+DtNZ2kINb6qt/lS+IyXnHQe9e90POfeewL/ME=
github.com/sirupsen/logrus v1.3.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793 h1:u+LnwYTOOW7Ukr/fppxEb1Nwz0AtPflrblfvUudpo+I=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33 h1:I6FyU15t786LL7oL/hn43zqTuEGr4PN7F4XJ1p4E3Y8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d h1:+R4KGOnez64A81RvjARKc4UT5/tI9ujCIVX+P5KiHuI=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+188 -14
View File
@@ -2,43 +2,159 @@ package kaniko
import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"strings"
"github.com/drone/drone-kaniko/pkg/artifact"
"github.com/drone/drone-kaniko/pkg/tagger"
"golang.org/x/mod/semver"
)
type (
// Build defines Docker build parameters.
Build struct {
Dockerfile string // Docker build Dockerfile
Context string // Docker build context
Tags []string // Docker build tags
Args []string // Docker build args
Target string // Docker build target
Repo string // Docker build repository
Labels []string // Label map
DroneCommitRef string // Drone git commit reference
DroneRepoBranch string // Drone repo branch
Dockerfile string // Docker build Dockerfile
Context string // Docker build context
Tags []string // Docker build tags
AutoTag bool // Set this to auto detect tags from git commits and semver-tagged labels
AutoTagSuffix string // Suffix to append to the auto detect tags
ExpandTag bool // Set this to expand the `Tags` into semver-tagged labels
Args []string // Docker build args
Target string // Docker build target
Repo string // Docker build repository
Mirrors []string // Docker repository mirrors
Labels []string // Label map
SkipTlsVerify bool // Docker skip tls certificate verify for registry
SnapshotMode string // Kaniko snapshot mode
EnableCache bool // Whether to enable kaniko cache
CacheRepo string // Remote repository that will be used to store cached layers
CacheTTL int // Cache timeout in hours
DigestFile string // Digest file location
NoPush bool // Set this flag if you only want to build the image, without pushing to a registry
Verbosity string // Log level
Platform string // Allows to build with another default platform than the host, similarly to docker build --platform
SkipUnusedStages bool // Build only used stages
}
// Artifact defines content of artifact file
Artifact struct {
Tags []string // Docker artifact tags
Repo string // Docker artifact repository
Registry string // Docker artifact registry
RegistryType artifact.RegistryTypeEnum // Rocker artifact registry type
ArtifactFile string // Artifact file location
}
// Plugin defines the Docker plugin parameters.
Plugin struct {
Build Build // Docker build configuration
Build Build // Docker build configuration
Artifact Artifact // Artifact file content
}
)
// labelsForTag returns the labels to use for the given tag, subject to the value of ExpandTag.
//
// Build information (e.g. +linux_amd64) is carried through to all labels.
// Pre-release information (e.g. -rc1) suppresses major and major+minor auto-labels.
func (b Build) labelsForTag(tag string) (labels []string) {
// We strip "v" off of the beginning of semantic versions, as they are not used in docker tags
const VersionPrefix = "v"
// Semantic Versions don't allow underscores, so replace them with dashes.
// https://semver.org/
semverTag := strings.ReplaceAll(tag, "_", "-")
// Allow tags of the form "1.2.3" as well as "v1.2.3" to avoid confusion.
if withV := VersionPrefix + semverTag; !semver.IsValid(semverTag) && semver.IsValid(withV) {
semverTag = withV
}
// Pass through tags if expand-tag is not set, or if the tag is not a semantic version
if !b.ExpandTag || !semver.IsValid(semverTag) {
return []string{tag}
}
tag = semverTag
// If the version is pre-release, only the full release should be tagged, not the major/minor versions.
if semver.Prerelease(tag) != "" {
return []string{
strings.TrimPrefix(tag, VersionPrefix),
}
}
// tagFor carries any build information from the semantic version through to major and minor tags.
labelFor := func(base string) string {
return strings.TrimPrefix(base, VersionPrefix) + semver.Build(tag)
}
return []string{
labelFor(semver.Major(tag)),
labelFor(semver.MajorMinor(tag)),
labelFor(semver.Canonical(tag)),
}
}
// Returns the auto detected tags. See the AutoTag section of
// https://plugins.drone.io/drone-plugins/drone-docker/ for more info.
func (b Build) AutoTags() (tags []string, err error) {
if len(b.Tags) > 1 || len(b.Tags) == 1 && b.Tags[0] != "latest" {
err = fmt.Errorf("The auto-tag flag does not work with user provided tags %s", b.Tags)
return
}
// We have tried the best to prevent enabling auto-tag and passing in
// user specified at the same time. Starts to auto detect tags.
// Note: passing in a "latest" tag with auto-tag enabled won't trigger the
// early returns above, because we cannot tell if the tag is provided by
// the default value or by the users.
commitRef := b.DroneCommitRef
if !tagger.UseAutoTag(commitRef, b.DroneRepoBranch) {
err = fmt.Errorf("Could not auto detect the tag. Skipping automated docker build for commit %s", commitRef)
return
}
tags, err = tagger.AutoTagsSuffix(commitRef, b.AutoTagSuffix)
if err != nil {
err = fmt.Errorf("Invalid semantic version when auto detecting the tag. Skipping automated docker build for %s.", commitRef)
}
return
}
// Exec executes the plugin step
func (p Plugin) Exec() error {
if p.Build.Repo == "" {
if !p.Build.NoPush && p.Build.Repo == "" {
return fmt.Errorf("repository name to publish image must be specified")
}
if _, err := os.Stat(p.Build.Dockerfile); os.IsNotExist(err) {
return fmt.Errorf("dockerfile does not exist at path: %s", p.Build.Dockerfile)
}
var tags = p.Build.Tags
if p.Build.AutoTag && p.Build.ExpandTag {
return fmt.Errorf("The auto-tag flag conflicts with the expand-tag flag")
}
if p.Build.AutoTag {
var err error
tags, err = p.Build.AutoTags()
if err != nil {
return err
}
}
cmdArgs := []string{
fmt.Sprintf("--dockerfile=%s", p.Build.Dockerfile),
fmt.Sprintf("--context=dir://%s", p.Build.Context),
}
// Set the destination repository
for _, tag := range p.Build.Tags {
cmdArgs = append(cmdArgs, fmt.Sprintf("--destination=%s:%s", p.Build.Repo, tag))
if !p.Build.NoPush {
for _, tag := range tags {
for _, label := range p.Build.labelsForTag(tag) {
cmdArgs = append(cmdArgs, fmt.Sprintf("--destination=%s:%s", p.Build.Repo, label))
}
}
}
// Set the build arguments
for _, arg := range p.Build.Args {
@@ -46,20 +162,78 @@ func (p Plugin) Exec() error {
}
// Set the labels
for _, label := range p.Build.Labels {
cmdArgs = append(cmdArgs, fmt.Sprintf("--label %s", label))
cmdArgs = append(cmdArgs, fmt.Sprintf("--label=%s", label))
}
// Set repository mirrors
for _, mirror := range p.Build.Mirrors {
cmdArgs = append(cmdArgs, fmt.Sprintf("--registry-mirror=%s", mirror))
}
if p.Build.Target != "" {
cmdArgs = append(cmdArgs, fmt.Sprintf("--target=%s", p.Build.Target))
}
if p.Build.SkipTlsVerify {
cmdArgs = append(cmdArgs, "--skip-tls-verify=true")
}
if p.Build.SnapshotMode != "" {
cmdArgs = append(cmdArgs, fmt.Sprintf("--snapshotMode=%s", p.Build.SnapshotMode))
}
if p.Build.EnableCache {
cmdArgs = append(cmdArgs, "--cache=true")
if p.Build.CacheRepo != "" {
cmdArgs = append(cmdArgs, fmt.Sprintf("--cache-repo=%s", p.Build.CacheRepo))
}
}
if p.Build.CacheTTL != 0 {
cmdArgs = append(cmdArgs, fmt.Sprintf("--cache-ttl=%dh", p.Build.CacheTTL))
}
if p.Build.DigestFile != "" {
cmdArgs = append(cmdArgs, fmt.Sprintf("--digest-file=%s", p.Build.DigestFile))
}
if p.Build.NoPush {
cmdArgs = append(cmdArgs, "--no-push")
}
if p.Build.Verbosity != "" {
cmdArgs = append(cmdArgs, fmt.Sprintf("--verbosity=%s", p.Build.Verbosity))
}
if p.Build.Platform != "" {
cmdArgs = append(cmdArgs, fmt.Sprintf("--customPlatform=%s", p.Build.Platform))
}
if p.Build.SkipUnusedStages {
cmdArgs = append(cmdArgs, "--skip-unused-stages")
}
cmd := exec.Command("/kaniko/executor", cmdArgs...)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
trace(cmd)
err := cmd.Run()
return err
if err != nil {
return err
}
if p.Build.DigestFile != "" && p.Artifact.ArtifactFile != "" {
content, err := ioutil.ReadFile(p.Build.DigestFile)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to read digest file contents at path: %s with error: %s\n", p.Build.DigestFile, err)
}
err = artifact.WritePluginArtifactFile(p.Artifact.RegistryType, p.Artifact.ArtifactFile, p.Artifact.Registry, p.Artifact.Repo, string(content), p.Artifact.Tags)
if err != nil {
fmt.Fprintf(os.Stderr, "failed to write plugin artifact file at path: %s with error: %s\n", p.Artifact.ArtifactFile, err)
}
}
return nil
}
// trace writes each command to stdout with the command wrapped in an xml
+140
View File
@@ -1 +1,141 @@
package kaniko
import (
"testing"
"github.com/google/go-cmp/cmp"
)
func TestBuild_labelsForTag(t *testing.T) {
tests := []struct {
name string
tag string
expandTags []string
}{
{
name: "semver",
tag: "v1.2.3",
expandTags: []string{"1", "1.2", "1.2.3"},
},
{
name: "no_patch",
tag: "v1.2",
expandTags: []string{"1", "1.2", "1.2.0"},
},
{
name: "only_major",
tag: "v1",
expandTags: []string{"1", "1.0", "1.0.0"},
},
{
name: "full_with_build",
tag: "v1.2.3+build-info",
expandTags: []string{"1+build-info", "1.2+build-info", "1.2.3+build-info"},
},
{
name: "build_with_underscores",
tag: "v1.2.3+linux_amd64",
expandTags: []string{"1+linux-amd64", "1.2+linux-amd64", "1.2.3+linux-amd64"},
},
{
name: "prerelease",
tag: "v1.2.3-rc1",
expandTags: []string{"1.2.3-rc1"},
},
{
name: "prerelease_with_build",
tag: "v1.2.3-rc1+bld",
expandTags: []string{"1.2.3-rc1+bld"},
},
{
name: "invalid_build",
tag: "v1+bld", // can only include build detail with all three elements
expandTags: []string{"v1+bld"},
},
{
name: "accidental_non_semver",
tag: "1.2.3",
expandTags: []string{"1", "1.2", "1.2.3"},
},
{
name: "non_semver",
tag: "latest",
expandTags: []string{"latest"},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
tags := Build{ExpandTag: true}.labelsForTag(tt.tag)
if got, want := tags, tt.expandTags; !cmp.Equal(got, want) {
t.Errorf("tagsFor(%q) = %q, want %q", tt.tag, got, want)
}
})
}
}
func TestBuild_AutoTags(t *testing.T) {
tests := []struct {
name string
repoBranch string
commitRef string
autoTagSuffix string
expectedTags []string
}{
{
name: "commit push",
repoBranch: "master",
commitRef: "refs/heads/master",
autoTagSuffix: "",
expectedTags: []string{"latest"},
},
{
name: "tag push",
repoBranch: "master",
commitRef: "refs/tags/v1.0.0",
autoTagSuffix: "",
expectedTags: []string{
"1",
"1.0",
"1.0.0",
},
},
{
name: "tag push",
repoBranch: "master",
commitRef: "refs/tags/v1.0.0",
autoTagSuffix: "linux-amd64",
expectedTags: []string{
"1-linux-amd64",
"1.0-linux-amd64",
"1.0.0-linux-amd64",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
b := Build{DroneCommitRef: tt.commitRef, DroneRepoBranch: tt.repoBranch, AutoTag: true}
if tt.autoTagSuffix != "" {
b.AutoTagSuffix = tt.autoTagSuffix
}
tags, err := b.AutoTags()
if err != nil {
t.Errorf("Unexpected err %q", err)
}
if got, want := tags, tt.expectedTags; !cmp.Equal(got, want) {
t.Errorf("auto detected tags = %q, wanted = %q", got, want)
}
})
}
t.Run("auto-tag cannot be enabled with user provided tags", func(t *testing.T) {
b := Build{
DroneCommitRef: "refs/tags/v1.0.0",
DroneRepoBranch: "master",
AutoTag: true,
Tags: []string{"v1"},
}
_, err := b.AutoTags()
if err == nil {
t.Errorf("Expect error for invalid flags")
}
})
}
+76
View File
@@ -0,0 +1,76 @@
package artifact
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"github.com/pkg/errors"
)
const (
dockerArtifactV1 string = "docker/v1"
)
type RegistryTypeEnum string
const (
Docker RegistryTypeEnum = "Docker"
ECR RegistryTypeEnum = "ECR"
GCR RegistryTypeEnum = "GCR"
)
type (
Image struct {
Image string `json:"image"`
Digest string `json:"digest"`
}
Data struct {
RegistryType RegistryTypeEnum `json:"registryType"`
RegistryUrl string `json:"registryUrl"`
Images []Image `json:"images"`
}
DockerArtifact struct {
Kind string `json:"kind"`
Data Data `json:"data"`
}
)
func WritePluginArtifactFile(registryType RegistryTypeEnum, artifactFilePath, registryUrl, imageName, digest string, tags []string) error {
var images []Image
for _, tag := range tags {
images = append(images, Image{
Image: fmt.Sprintf("%s:%s", imageName, tag),
Digest: digest,
})
}
data := Data{
RegistryType: registryType,
RegistryUrl: registryUrl,
Images: images,
}
dockerArtifact := DockerArtifact{
Kind: dockerArtifactV1,
Data: data,
}
b, err := json.MarshalIndent(dockerArtifact, "", "\t")
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to marshal output %+v", dockerArtifact))
}
dir := filepath.Dir(artifactFilePath)
err = os.MkdirAll(dir, 0644)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to create %s directory for artifact file", dir))
}
err = ioutil.WriteFile(artifactFilePath, b, 0644)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("failed to write artifact to artifact file %s", artifactFilePath))
}
return nil
}
+17
View File
@@ -0,0 +1,17 @@
{
"kind": "docker/v1",
"data": {
"registryType": "Docker",
"registryUrl": "https://index.docker.io/",
"images": [
{
"image": "image:a1",
"digest": "sha256:22332233"
},
{
"image": "image:latest",
"digest": "sha256:22332233"
}
]
}
}
+38
View File
@@ -0,0 +1,38 @@
package artifact
import (
"io/ioutil"
"testing"
)
func TestWritePluginArtifactFile(t *testing.T) {
testFile := t.TempDir() + "got.json"
err := WritePluginArtifactFile(Docker, testFile, "https://index.docker.io/", "image", "sha256:22332233", []string{"a1", "latest"})
if err != nil {
t.Error(err)
t.FailNow()
}
gotBytes, err := ioutil.ReadFile(testFile)
if err != nil {
t.Error(err)
t.FailNow()
}
wantBytes, err := ioutil.ReadFile("./artifact.json")
if err != nil {
t.Error(err)
t.FailNow()
}
got := string(gotBytes)
want := string(wantBytes)
if got != want {
t.Logf("got:%s", got)
t.Logf("want:%s", want)
t.FailNow()
}
}
+34
View File
@@ -0,0 +1,34 @@
package docker
import (
"encoding/base64"
"fmt"
)
type (
Auth struct {
Auth string `json:"auth"`
}
Config struct {
Auths map[string]Auth `json:"auths"`
CredHelpers map[string]string `json:"credHelpers"`
}
)
func NewConfig() *Config {
return &Config{
Auths: map[string]Auth{},
CredHelpers: map[string]string{},
}
}
func (c *Config) SetAuth(registry, username, password string) {
authBytes := []byte(fmt.Sprintf("%s:%s", username, password))
encodedString := base64.StdEncoding.EncodeToString(authBytes)
c.Auths[registry] = Auth{Auth: encodedString}
}
func (c *Config) SetCredHelper(registry, helper string) {
c.CredHelpers[registry] = helper
}
+25
View File
@@ -0,0 +1,25 @@
package docker
import (
"encoding/json"
"testing"
)
func TestConfig(t *testing.T) {
c := NewConfig()
c.SetAuth(RegistryV1, "test", "password")
c.SetCredHelper(RegistryECRPublic, "ecr-login")
bytes, err := json.Marshal(c)
if err != nil {
t.Error("json marshal failed")
}
want := `{"auths":{"https://index.docker.io/v1/":{"auth":"dGVzdDpwYXNzd29yZA=="}},"credHelpers":{"public.ecr.aws":"ecr-login"}}`
got := string(bytes)
if want != got {
t.Errorf("unexpected json output:\n want: %s\n got: %s", want, got)
}
}
+7
View File
@@ -0,0 +1,7 @@
package docker
const (
RegistryV1 string = "https://index.docker.io/v1/"
RegistryV2 string = "https://index.docker.io/v2/"
RegistryECRPublic string = "public.ecr.aws"
)
+95
View File
@@ -0,0 +1,95 @@
// A fork of https://github.com/drone-plugins/drone-docker/blob/master/tags.go
package tagger
import (
"fmt"
"strings"
"github.com/coreos/go-semver/semver"
)
// AutoTagsSuffix returns a set of default suggested tags
// based on the commit ref with an attached suffix.
func AutoTagsSuffix(ref, suffix string) ([]string, error) {
tags, err := AutoTags(ref)
if err != nil {
return nil, err
}
if len(suffix) == 0 {
return tags, nil
}
for i, tag := range tags {
if tag == "latest" {
tags[i] = suffix
} else {
tags[i] = fmt.Sprintf("%s-%s", tag, suffix)
}
}
return tags, nil
}
func splitOff(input string, delim string) string {
parts := strings.SplitN(input, delim, 2)
if len(parts) == 2 {
return parts[0]
}
return input
}
// AutoTags returns a set of default suggested tags based on
// the commit ref.
func AutoTags(ref string) ([]string, error) {
if !strings.HasPrefix(ref, "refs/tags/") {
return []string{"latest"}, nil
}
v := stripTagPrefix(ref)
version, err := semver.NewVersion(v)
if err != nil {
return []string{"latest"}, err
}
if version.PreRelease != "" || version.Metadata != "" {
return []string{
version.String(),
}, nil
}
v = stripTagPrefix(ref)
v = splitOff(splitOff(v, "+"), "-")
dotParts := strings.SplitN(v, ".", 3)
if version.Major == 0 {
return []string{
fmt.Sprintf("%0*d.%0*d", len(dotParts[0]), version.Major, len(dotParts[1]), version.Minor),
fmt.Sprintf("%0*d.%0*d.%0*d", len(dotParts[0]), version.Major, len(dotParts[1]), version.Minor, len(dotParts[2]), version.Patch),
}, nil
}
return []string{
fmt.Sprintf("%0*d", len(dotParts[0]), version.Major),
fmt.Sprintf("%0*d.%0*d", len(dotParts[0]), version.Major, len(dotParts[1]), version.Minor),
fmt.Sprintf("%0*d.%0*d.%0*d", len(dotParts[0]), version.Major, len(dotParts[1]), version.Minor, len(dotParts[2]), version.Patch),
}, nil
}
// UseAutoTag for keep only default branch for latest tag.
func UseAutoTag(ref, defaultBranch string) bool {
if strings.HasPrefix(ref, "refs/tags/") {
return true
}
if stripHeadPrefix(ref) == defaultBranch {
return true
}
return false
}
func stripHeadPrefix(ref string) string {
return strings.TrimPrefix(ref, "refs/heads/")
}
func stripTagPrefix(ref string) string {
ref = strings.TrimPrefix(ref, "refs/tags/")
ref = strings.TrimPrefix(ref, "v")
return ref
}
+199
View File
@@ -0,0 +1,199 @@
// A fork of https://github.com/drone-plugins/drone-docker/blob/master/tags_test.go
package tagger
import (
"reflect"
"testing"
)
func Test_stripTagPrefix(t *testing.T) {
var tests = []struct {
Before string
After string
}{
{"refs/tags/1.0.0", "1.0.0"},
{"refs/tags/v1.0.0", "1.0.0"},
{"v1.0.0", "1.0.0"},
}
for _, test := range tests {
got, want := stripTagPrefix(test.Before), test.After
if got != want {
t.Errorf("Got tag %s, want %s", got, want)
}
}
}
func TestAutoTags(t *testing.T) {
var tests = []struct {
Before string
After []string
}{
{"", []string{"latest"}},
{"refs/heads/master", []string{"latest"}},
{"refs/tags/0.9.0", []string{"0.9", "0.9.0"}},
{"refs/tags/1.0.0", []string{"1", "1.0", "1.0.0"}},
{"refs/tags/v1.0.0", []string{"1", "1.0", "1.0.0"}},
{"refs/tags/v1.0.0-alpha.1", []string{"1.0.0-alpha.1"}},
}
for _, test := range tests {
tags, err := AutoTags(test.Before)
if err != nil {
t.Error(err)
continue
}
got, want := tags, test.After
if !reflect.DeepEqual(got, want) {
t.Errorf("Got tag %v, want %v", got, want)
}
}
}
func TestAutoTagsError(t *testing.T) {
var tests = []string{
"refs/tags/x1.0.0",
"refs/tags/20190203",
}
for _, test := range tests {
_, err := AutoTags(test)
if err == nil {
t.Errorf("Expect tag error for %s", test)
}
}
}
func TestAutoTagsSuffix(t *testing.T) {
var tests = []struct {
Before string
Suffix string
After []string
}{
// without suffix
{
After: []string{"latest"},
},
{
Before: "refs/tags/v1.0.0",
After: []string{
"1",
"1.0",
"1.0.0",
},
},
// with suffix
{
Suffix: "linux-amd64",
After: []string{"linux-amd64"},
},
{
Before: "refs/tags/v1.0.0",
Suffix: "linux-amd64",
After: []string{
"1-linux-amd64",
"1.0-linux-amd64",
"1.0.0-linux-amd64",
},
},
{
Suffix: "nanoserver",
After: []string{"nanoserver"},
},
{
Before: "refs/tags/v1.9.2",
Suffix: "nanoserver",
After: []string{
"1-nanoserver",
"1.9-nanoserver",
"1.9.2-nanoserver",
},
},
{
Before: "refs/tags/v18.06.0",
Suffix: "nanoserver",
After: []string{
"18-nanoserver",
"18.06-nanoserver",
"18.06.0-nanoserver",
},
},
}
for _, test := range tests {
tag, err := AutoTagsSuffix(test.Before, test.Suffix)
if err != nil {
t.Error(err)
continue
}
got, want := tag, test.After
if !reflect.DeepEqual(got, want) {
t.Errorf("Got tag %v, want %v", got, want)
}
}
}
func Test_stripHeadPrefix(t *testing.T) {
type args struct {
ref string
}
tests := []struct {
args args
want string
}{
{
args: args{
ref: "refs/heads/master",
},
want: "master",
},
}
for _, tt := range tests {
if got := stripHeadPrefix(tt.args.ref); got != tt.want {
t.Errorf("stripHeadPrefix() = %v, want %v", got, tt.want)
}
}
}
func TestUseAutoTag(t *testing.T) {
type args struct {
ref string
defaultBranch string
}
tests := []struct {
name string
args args
want bool
}{
{
name: "latest tag for default branch",
args: args{
ref: "refs/heads/master",
defaultBranch: "master",
},
want: true,
},
{
name: "build from tags",
args: args{
ref: "refs/tags/v1.0.0",
defaultBranch: "master",
},
want: true,
},
{
name: "skip build for not default branch",
args: args{
ref: "refs/heads/develop",
defaultBranch: "master",
},
want: false,
},
}
for _, tt := range tests {
if got := UseAutoTag(tt.args.ref, tt.args.defaultBranch); got != tt.want {
t.Errorf("%q. UseAutoTag() = %v, want %v", tt.name, got, tt.want)
}
}
}
+9 -9
View File
@@ -10,14 +10,14 @@ set -e
set -x
# linux
GOOS=linux GOARCH=amd64 go build -o release/linux/amd64/kaniko-gcr
GOOS=linux GOARCH=amd64 go build -o release/linux/amd64/kaniko-ecr
GOOS=linux GOARCH=amd64 go build -o release/linux/amd64/kaniko-docker
GOOS=linux GOARCH=amd64 go build -o release/linux/amd64/kaniko-gcr ./cmd/kaniko-gcr
GOOS=linux GOARCH=amd64 go build -o release/linux/amd64/kaniko-ecr ./cmd/kaniko-ecr
GOOS=linux GOARCH=amd64 go build -o release/linux/amd64/kaniko-docker ./cmd/kaniko-docker
GOOS=linux GOARCH=arm64 go build -o release/linux/arm64/kaniko-gcr
GOOS=linux GOARCH=arm64 go build -o release/linux/arm64/kaniko-ecr
GOOS=linux GOARCH=arm64 go build -o release/linux/arm64/kaniko-docker
GOOS=linux GOARCH=arm64 go build -o release/linux/arm64/kaniko-gcr ./cmd/kaniko-gcr
GOOS=linux GOARCH=arm64 go build -o release/linux/arm64/kaniko-ecr ./cmd/kaniko-ecr
GOOS=linux GOARCH=arm64 go build -o release/linux/arm64/kaniko-docker ./cmd/kaniko-docker
GOOS=linux GOARCH=arm go build -o release/linux/arm/kaniko-gcr
GOOS=linux GOARCH=arm go build -o release/linux/arm/kaniko-ecr
GOOS=linux GOARCH=arm go build -o release/linux/arm/kaniko-docker
GOOS=linux GOARCH=arm go build -o release/linux/arm/kaniko-gcr ./cmd/kaniko-gcr
GOOS=linux GOARCH=arm go build -o release/linux/arm/kaniko-ecr ./cmd/kaniko-ecr
GOOS=linux GOARCH=arm go build -o release/linux/arm/kaniko-docker ./cmd/kaniko-docker
Regular → Executable
+3 -3
View File
@@ -14,9 +14,9 @@ set -e
set -x
# build the binary
go build -o release/linux/amd64/kaniko-gcr
go build -o release/linux/amd64/kaniko-ecr
go build -o release/linux/amd64/kaniko-docker
go build -o release/linux/amd64/kaniko-gcr ./cmd/kaniko-gcr
go build -o release/linux/amd64/kaniko-ecr ./cmd/kaniko-ecr
go build -o release/linux/amd64/kaniko-docker ./cmd/kaniko-docker
# build the docker image
docker build -f docker/gcr/Dockerfile.linux.amd64 -t plugins/kaniko-gcr .