Skip to content
This repository has been archived by the owner on Oct 2, 2023. It is now read-only.

Add a flag to control pushing new tags on unchanged images #1112

Merged
merged 19 commits into from
Aug 29, 2019

Conversation

zbarahal
Copy link
Contributor

My team ran into a use case where due to Bazel pushing a new tag to ECR for each service every time the monorepo changes we ran into the 100 tag per image cap on ECR for services that don't change often. This is because ECR groups tags onto images by digest so if your image isn't changing but you keep pushing new tags you end up with a bunch of tags on one image.

Per #1106 I added a new flag to the new_push functionality and updated the pusher. I may explore adding this to the old fast pusher as well.

Closes #1106

@googlebot
Copy link

Thanks for your pull request. It looks like this may be your first contribution to a Google open source project (if not, look below for help). Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA).

📝 Please visit https://cla.developers.google.com/ to sign.

Once you've signed (or fixed any issues), please reply here with @googlebot I signed it!) and we'll verify it.


What to do if you already signed the CLA

Individual signers
Corporate signers

ℹ️ Googlers: Go here for more info.

@zbarahal
Copy link
Contributor Author

@smukherj1 and I are working through some testing questions on the linked issue. I opened the PR so they could view my WIP. Barring any issues with testing I believe this PR is done but there may be changes.

@smukherj1
Copy link
Collaborator

@zbarahal Thanks for the PR. Could you please sign the CLA? Also, we would also like to include a test for the changed behavior in this PR as well. See my comment here for instructions on how to fix the issue you were seeing with new_container_push.

@zbarahal
Copy link
Contributor Author

@smukherj1 thanks for the help. I'm working on getting our organization CLA signed (should be done today) so that's the holdup. I'll add the tests in the meantime.

I voiced this on the issue but do you have a timeline for the release of this rewrite? Depending on that timeline I may try to add this to the Python pusher as well.

@zbarahal
Copy link
Contributor Author

@smukherj1 is there somewhere I should add integration tests for all of this? From reading the codebase I don't understand how the tests are currently working. I cam definitely write a Go test for the new pusher functionality I added but I'm not sure if there's a spot that tests the Bazel code.

@zbarahal
Copy link
Contributor Author

Okay I think I understand it now actually. Looks like a composite of shell scripts + bazel targets in e2e.sh. I'll write something up

@smukherj1
Copy link
Collaborator

@zbarahal suggest following #580 for status of the python -> Go migration. Don't have a timeline yet because it can change based on issues/incompatibilities discovered during the migration. I'm actively working on the migration right now.

@zbarahal
Copy link
Contributor Author

@smukherj1 Integration tests are added and CI is passing. The PR suggests adding @alex1545 as a reviewer but since we have been discussing it should you be the reviewer? Either way is fine by me but this is ready for review now.

Still working on the CLA but we'll have that done soon.

@zbarahal
Copy link
Contributor Author

There are also a lot of CI builds attached to this PR and I'm not sure which are required. Travis is passing and I've cleaned up the formatting for buildifier. Let me know if other CIs are failing that are required.

Copy link
Collaborator

@smukherj1 smukherj1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot ! The change mostly looks good! Just a few minor comments.

@@ -37,6 +38,7 @@ var (
clientConfigDir = flag.String("client-config-dir", "", "The path to the directory where the client configuration files are located. Overiddes the value from DOCKER_CONFIG.")
legacyBaseImage = flag.String("legacyBaseImage", "", "Path to a legacy base image in tarball form. Should be specified only when format is legacy.")
configPath = flag.String("configPath", "", "Path to the image config. Should be specified only when format is legacy.")
onlyPushChanged = flag.Bool("only-push-changed", false, "If set to true, will only push images where the digest has changed.")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest naming this skip-on-unchanged-digest to make it more explicit what defines the "change".

@@ -126,6 +130,27 @@ func main() {
log.Printf("Successfully pushed %s image from %s to %s", *format, imgSrc, stamped)
}

// Checks whether an images digest exists in a repository
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

// digestExists checks whether an ...

Also change images to image's

Also, our coding style is to have Go comments end with a period, i.e., be complete sentences.

if err != nil {
return false, errors.Wrapf(err, "unable to get local image digest")
}
digestRef, err := name.NewDigest(strings.Join([]string{dst, digest.String()}, "@"))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel name.NewDigest(fmt.Sprintf("%s@%s", dst, digest)) is more readable.

}
digestRef, err := name.NewDigest(strings.Join([]string{dst, digest.String()}, "@"))
if err != nil {
return false, errors.Wrapf(err, "Couldn't create ref from digest")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Couldn't -> couldn't

Our convention for error messages added to an error object is to begin with small letters and not end in a period or any other punctuation

}
remoteImg, err := remote.Image(digestRef, remote.WithAuthFromKeychain(authn.DefaultKeychain))
if err != nil {
if strings.HasPrefix(err.Error(), ManifestUnknownError) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest using the this here.

container/go/cmd/pusher/pusher.go Show resolved Hide resolved
@@ -179,6 +182,11 @@ new_container_push = rule(
mandatory = True,
doc = "The label of the image to push.",
),
"only_push_changed": attr.bool(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest naming this skip-on-unchanged-digest as well.

@@ -179,6 +182,11 @@ new_container_push = rule(
mandatory = True,
doc = "The label of the image to push.",
),
"only_push_changed": attr.bool(
default = False,
mandatory = False,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mandatory = False is the default so this is not necessary

@@ -46,6 +48,8 @@ const (
manifestFile = "manifest.json"
// indexManifestFile is the filename of image manifest config in OCI format.
indexManifestFile = "index.json"
// ManifestUnknownError is the error returned when a digest is not found
ManifestUnknownError = "MANIFEST_UNKNOWN"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be removed after addressing another comment below.

testing/e2e.sh Outdated
cd "${ROOT}"
clear_docker_full
cid=$(docker run --rm -d -p 5000:5000 --name registry registry:2)
EXPECT_CONTAINS "$(bazel run @io_bazel_rules_docker//tests/container:new_push_test_only_push_changed_unchanged_tag_1 2>&1)" "Successfully pushed docker image"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggest looking for the message that indicates the image push is being skipped here and the next line. Note that this log message doesn't currently exist and I suggested to add one in a separate comment.

@smukherj1
Copy link
Collaborator

/gcbrun

@zbarahal
Copy link
Contributor Author

@googlebot I signed it!

@zbarahal
Copy link
Contributor Author

/gcbrun

1 similar comment
@smukherj1
Copy link
Collaborator

/gcbrun

@smukherj1
Copy link
Collaborator

@googlebot rescan

@googlebot
Copy link

CLAs look good, thanks!

ℹ️ Googlers: Go here for more info.

@k8s-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: smukherj1, zbarahal

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@smukherj1 smukherj1 merged commit 5aedb19 into bazelbuild:master Aug 29, 2019
@zbarahal
Copy link
Contributor Author

Thanks @smukherj1!

zbarahal added a commit to zbarahal/rules_docker that referenced this pull request Aug 29, 2019
…d#1112)

* Add flag to check if digest already exists before pushing a new tag

* Clean up formatting

* Add comment for const

* Use more generic form of error

* Add integration tests for only_push_changed flag

* Run buildifier

* Fix dict ordering

* More buildifier changes

* Remove unnecessary mandatory field

* Rename flag to be more clear as to purpose

* Use existing error and clean up join

* Use correct coding style for comments/errors

* Add log message for not pushing

* Update bazel deps for transport package

* Fix import sort order

* Remove bin that got checked in

* Buildifier
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

container_push skip tag if sha256 exists
4 participants