Skip to content

Commit c75935e

Browse files
committed
skaffold deploy -t flag
See GoogleContainerTools#4455
1 parent 2582151 commit c75935e

File tree

6 files changed

+109
-1
lines changed

6 files changed

+109
-1
lines changed

cmd/skaffold/app/cmd/deploy.go

+16
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/GoogleContainerTools/skaffold/cmd/skaffold/app/flags"
2828
"github.com/GoogleContainerTools/skaffold/cmd/skaffold/app/tips"
2929
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/build"
30+
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/build/tag"
3031
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/runner"
3132
"github.com/GoogleContainerTools/skaffold/pkg/skaffold/schema/latest"
3233
)
@@ -88,6 +89,21 @@ func getArtifactsToDeploy(out io.Writer, fromFile, fromCLI []build.Artifact, art
8889
deployed = build.MergeWithPreviousBuilds(fromCLI, deployed)
8990
deployed = build.MergeWithPreviousBuilds(fromFile, deployed)
9091

92+
if opts.CustomTag != "" {
93+
for i := range deployed {
94+
artifact := &deployed[i]
95+
if artifact.Tag == "" {
96+
artifact.Tag = artifact.ImageName + ":" + opts.CustomTag
97+
} else {
98+
newTag, err := tag.SetImageTag(artifact.Tag, opts.CustomTag)
99+
if err != nil {
100+
return nil, err
101+
}
102+
artifact.Tag = newTag
103+
}
104+
}
105+
}
106+
91107
// Check that every image has a non empty tag
92108
for _, d := range deployed {
93109
if d.Tag == "" {

cmd/skaffold/app/cmd/deploy_test.go

+21
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ func TestGetDeployedArtifacts(t *testing.T) {
3232
fromFile []build.Artifact
3333
fromCLI []build.Artifact
3434
expected []build.Artifact
35+
customTag string
3536
shouldErr bool
3637
}{
3738
{
@@ -82,9 +83,29 @@ func TestGetDeployedArtifacts(t *testing.T) {
8283
fromCLI: nil,
8384
shouldErr: true,
8485
},
86+
{
87+
description: "override tag",
88+
artifacts: []*latest.Artifact{{ImageName: "image1"}, {ImageName: "image2"}},
89+
fromFile: []build.Artifact{{ImageName: "image1", Tag: "image1:tag"}},
90+
fromCLI: []build.Artifact{{ImageName: "image2", Tag: "image2:tag"}},
91+
expected: []build.Artifact{{ImageName: "image1", Tag: "image1:test"}, {ImageName: "image2", Tag: "image2:test"}},
92+
customTag: "test",
93+
},
94+
{
95+
description: "override missing tag",
96+
artifacts: []*latest.Artifact{{ImageName: "image1"}, {ImageName: "image2"}},
97+
fromFile: nil,
98+
fromCLI: nil,
99+
expected: []build.Artifact{{ImageName: "image1", Tag: "image1:test"}, {ImageName: "image2", Tag: "image2:test"}},
100+
customTag: "test",
101+
},
85102
}
86103
for _, test := range tests {
87104
testutil.Run(t, test.description, func(t *testutil.T) {
105+
if test.customTag != "" {
106+
t.Override(&opts.CustomTag, test.customTag)
107+
}
108+
88109
deployed, err := getArtifactsToDeploy(ioutil.Discard, test.fromFile, test.fromCLI, test.artifacts)
89110

90111
t.CheckErrorAndDeepEqual(test.shouldErr, err, test.expected, deployed)

cmd/skaffold/app/cmd/flags.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ var flagRegistry = []Flag{
271271
Value: &opts.CustomTag,
272272
DefValue: "",
273273
FlagAddMethod: "StringVar",
274-
DefinedOn: []string{"build", "debug", "dev", "run"},
274+
DefinedOn: []string{"build", "debug", "dev", "run", "deploy"},
275275
},
276276
{
277277
Name: "minikube-profile",

docs/content/en/docs/references/cli/_index.md

+2
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,7 @@ Options:
493493
--rpc-port=50051: tcp port to expose event API
494494
--skip-render=false: Don't render the manifests, just deploy them
495495
--status-check=true: Wait for deployed resources to stabilize
496+
-t, --tag='': The optional custom tag to use for images which overrides the current Tagger configuration
496497
--tail=false: Stream logs from deployed objects (true by default for `skaffold dev` and `skaffold debug`)
497498
--toot=false: Emit a terminal beep after the deploy is complete
498499
--wait-for-deletions=true: Wait for pending deletions to complete before a deployment
@@ -528,6 +529,7 @@ Env vars:
528529
* `SKAFFOLD_RPC_PORT` (same as `--rpc-port`)
529530
* `SKAFFOLD_SKIP_RENDER` (same as `--skip-render`)
530531
* `SKAFFOLD_STATUS_CHECK` (same as `--status-check`)
532+
* `SKAFFOLD_TAG` (same as `--tag`)
531533
* `SKAFFOLD_TAIL` (same as `--tail`)
532534
* `SKAFFOLD_TOOT` (same as `--toot`)
533535
* `SKAFFOLD_WAIT_FOR_DELETIONS` (same as `--wait-for-deletions`)

pkg/skaffold/build/tag/util.go

+15
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,18 @@ func StripTags(taggedImages []string) []string {
4040
}
4141
return images
4242
}
43+
44+
func SetImageTag(image, tag string) (string, error) {
45+
parsed, err := docker.ParseReference(image)
46+
if err != nil {
47+
return "", err
48+
}
49+
image = parsed.BaseName
50+
if tag != "" {
51+
image = image + ":" + tag
52+
}
53+
if parsed.Digest != "" {
54+
image = image + "@" + parsed.Digest
55+
}
56+
return image, nil
57+
}

pkg/skaffold/build/tag/util_test.go

+54
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,57 @@ func TestStripTags(t *testing.T) {
5959
})
6060
}
6161
}
62+
63+
func TestSetImageTag(t *testing.T) {
64+
tests := []struct {
65+
description string
66+
image string
67+
tag string
68+
expectedImage string
69+
shouldErr bool
70+
}{
71+
{
72+
description: "image with tag",
73+
image: "gcr.io/foo/bar:latest",
74+
tag: "test-1",
75+
expectedImage: "gcr.io/foo/bar:test-1",
76+
},
77+
{
78+
description: "image with tag and digest",
79+
image: "gcr.io/foo/bar:latest@sha256:79e160161fd8190acae2d04d8f296a27a562c8a59732c64ac71c99009a6e89bc",
80+
tag: "test-2",
81+
expectedImage: "gcr.io/foo/bar:test-2@sha256:79e160161fd8190acae2d04d8f296a27a562c8a59732c64ac71c99009a6e89bc",
82+
},
83+
{
84+
description: "image without tag and digest",
85+
image: "gcr.io/foo/bar",
86+
tag: "test-3",
87+
expectedImage: "gcr.io/foo/bar:test-3",
88+
},
89+
{
90+
description: "empty tag",
91+
image: "gcr.io/foo/bar:test-4",
92+
expectedImage: "gcr.io/foo/bar",
93+
},
94+
{
95+
description: "image with digest",
96+
image: "gcr.io/foo/bar@sha256:79e160161fd8190acae2d04d8f296a27a562c8a59732c64ac71c99009a6e89bc",
97+
tag: "test-5",
98+
expectedImage: "gcr.io/foo/bar:test-5@sha256:79e160161fd8190acae2d04d8f296a27a562c8a59732c64ac71c99009a6e89bc",
99+
},
100+
{
101+
description: "invalid reference",
102+
image: "!!invalid!!",
103+
shouldErr: true,
104+
},
105+
}
106+
107+
for _, test := range tests {
108+
testutil.Run(t, test.description, func(t *testutil.T) {
109+
t.Parallel()
110+
111+
image, err := SetImageTag(test.image, test.tag)
112+
t.CheckErrorAndDeepEqual(test.shouldErr, err, test.expectedImage, image)
113+
})
114+
}
115+
}

0 commit comments

Comments
 (0)