-
Notifications
You must be signed in to change notification settings - Fork 66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Skip docker push
if image exists remotely
#36
Merged
Merged
Changes from all commits
Commits
Show all changes
14 commits
Select commit
Hold shift + click to select a range
fbbb4e9
serious restructure
8170450
another pass
309d380
get tests restructured
a07ef6b
more conversion
76fe3e0
rename push
bd2e414
getting closer
88f675e
getting closer
f613c11
all works
3329f46
refactor auth
12492b2
skip push of image exists
8601972
add to changelog
0ea1d2e
remove accidental line
b6e0b77
Merge branch 'master' into sritchie/skip_push
d49dddb
pass project id
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,10 +18,15 @@ | |
""" | ||
|
||
import json | ||
import subprocess | ||
|
||
from absl import logging | ||
|
||
def _image_tag_for_project(project_id: str, image_id: str) -> str: | ||
|
||
def _image_tag_for_project(project_id: str, | ||
image_id: str, | ||
include_tag: bool = True) -> str: | ||
"""Generate the GCR Docker image tag for the supplied pair of project_id and | ||
image_id. | ||
|
@@ -31,21 +36,48 @@ def _image_tag_for_project(project_id: str, image_id: str) -> str: | |
""" | ||
project_s = project_id.replace(":", "/") | ||
return "gcr.io/{}/{}:latest".format(project_s, image_id) | ||
base = f"gcr.io/{project_s}/{image_id}" | ||
return f"{base}:latest" if include_tag else base | ||
|
||
|
||
def _gcr_list_tags(project_id: str, image_id: str): | ||
"""Returns a sequence of metadata for all tags of the supplied image_id in the | ||
supplied project. | ||
""" | ||
image_tag = _image_tag_for_project(project_id, image_id, include_tag=False) | ||
cmd = [ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we pass the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. NIce! |
||
"gcloud", "container", "images", "list-tags", f"--project={project_id}", | ||
"--format=json", image_tag | ||
] | ||
return json.loads(subprocess.check_output(cmd)) | ||
|
||
|
||
def gcr_image_pushed(project_id: str, image_id: str) -> bool: | ||
"""Returns true if the supplied image has been pushed to the container registry | ||
for the supplied project, false otherwise. | ||
""" | ||
return len(_gcr_list_tags(project_id, image_id)) > 0 | ||
|
||
|
||
def push_uuid_tag(project_id: str, image_id: str) -> str: | ||
def push_uuid_tag(project_id: str, image_id: str, force: bool = False) -> str: | ||
"""Takes a base image and tags it for upload, then pushes it to a remote Google | ||
Container Registry. | ||
Returns the tag on a successful push. | ||
TODO should this just check first before attempting to push if the image | ||
exists? Immutable names means that if the tag is up there, we're done. | ||
Potentially use docker-py for this. | ||
""" | ||
image_tag = _image_tag_for_project(project_id, image_id) | ||
subprocess.run(["docker", "tag", image_id, image_tag], check=True) | ||
subprocess.run(["docker", "push", image_tag], check=True) | ||
|
||
def missing_remotely(): | ||
missing = not gcr_image_pushed(project_id, image_id) | ||
if not missing: | ||
logging.info( | ||
f"Skipping docker push, as {image_tag} already exists remotely.") | ||
return missing | ||
|
||
if force or missing_remotely(): | ||
subprocess.run(["docker", "tag", image_id, image_tag], check=True) | ||
subprocess.run(["docker", "push", image_tag], check=True) | ||
|
||
return image_tag |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,5 @@ ipython | |
pre-commit | ||
pytest==5.4.3 | ||
pytest-cov==2.10.0 | ||
pytest-subprocess==0.1.5 | ||
twine |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
#!/usr/bin/python | ||
# | ||
# Copyright 2020 Google LLC | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from subprocess import CalledProcessError | ||
|
||
from google.oauth2.credentials import Credentials | ||
|
||
import caliban.util.auth as a | ||
|
||
|
||
def register_auth(process, **kwargs): | ||
process.register_subprocess(["gcloud", "auth", "print-access-token"], | ||
**kwargs) | ||
|
||
|
||
def fail_process(process): | ||
process.returncode = 1 | ||
raise CalledProcessError("cmd", "exception! Not logged in!") | ||
|
||
|
||
def test_auth_access_token(fake_process): | ||
"""Check that if the user has logged in with `gcloud auth login`, | ||
`auth_access_token` returns the correct token. | ||
""" | ||
token = "token" | ||
register_auth(fake_process, stdout=token) | ||
assert a.auth_access_token() == token | ||
|
||
|
||
def test_missing_auth_access_token(fake_process): | ||
"""Check that if the user has NOT logged in with `gcloud auth login`, | ||
`auth_access_token` returns None. | ||
""" | ||
register_auth(fake_process, callback=fail_process) | ||
assert a.auth_access_token() is None | ||
|
||
|
||
def test_gcloud_auth_credentials(fake_process): | ||
"""Check that if the user has logged in with `gcloud auth login`, | ||
a proper instance of Credentials is returned. | ||
""" | ||
token = "token" | ||
register_auth(fake_process, stdout=token) | ||
assert isinstance(a.gcloud_auth_credentials(), Credentials) | ||
|
||
|
||
def test_missing_gcloud_auth_credentials(fake_process): | ||
"""Check that if the user has logged in with `gcloud auth login`, | ||
`auth_access_token` returns the correct token. | ||
""" | ||
register_auth(fake_process, callback=fail_process) | ||
assert a.gcloud_auth_credentials() is None |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would having a
tag
parameter here that defaults tolatest
be more flexible than justinclude_tag
? We don't really tag things differently now, but perhaps in the future.