|
7 | 7 | from django.conf import settings |
8 | 8 | from rest_framework.exceptions import PermissionDenied |
9 | 9 | from simpleflock import SimpleFlock |
| 10 | +from retrying import retry |
10 | 11 |
|
11 | 12 | import docker |
12 | 13 | import docker.constants |
@@ -59,6 +60,28 @@ def login(self, repository, creds=None): |
59 | 60 |
|
60 | 61 | logger.info('Successfully logged into {} with {}'.format(repository, registry_auth['username'])) # noqa |
61 | 62 |
|
| 63 | + def get_port(self, target, deis_registry=False, creds=None): |
| 64 | + """ |
| 65 | + Get a port from a Docker image |
| 66 | + """ |
| 67 | + # get the target repository name and tag |
| 68 | + name, _ = docker.utils.parse_repository_tag(target) |
| 69 | + |
| 70 | + # strip any "http://host.domain:port" prefix from the target repository name, |
| 71 | + # since we always publish to the Deis registry |
| 72 | + repo, name = auth.split_repo_name(name) |
| 73 | + |
| 74 | + # log into pull repo |
| 75 | + if not deis_registry: |
| 76 | + self.login(repo, creds) |
| 77 | + |
| 78 | + info = self.inspect_image(target, deis_registry) |
| 79 | + if 'ExposedPorts' not in info['Config']: |
| 80 | + return None |
| 81 | + |
| 82 | + port = int(list(info['Config']['ExposedPorts'].keys())[0].split('/')[0]) |
| 83 | + return port |
| 84 | + |
62 | 85 | def publish_release(self, source, target, deis_registry=False, creds=None): |
63 | 86 | """Update a source Docker image with environment config and publish it to deis-registry.""" |
64 | 87 | # get the source repository name and tag |
@@ -121,6 +144,22 @@ def tag(self, image, repo, tag): |
121 | 144 | if not self.client.tag(image, repo, tag=tag, force=True): |
122 | 145 | raise RegistryException('Tagging {} as {}:{} failed'.format(image, repo, tag)) |
123 | 146 |
|
| 147 | + @retry(stop_max_attempt_number=3, wait_fixed=1000) |
| 148 | + def inspect_image(self, target, insecure_registry=True): |
| 149 | + """ |
| 150 | + Inspect docker image to gather information from it |
| 151 | +
|
| 152 | + try thrice to find the port before raising exception as docker-py is flaky |
| 153 | + """ |
| 154 | + # image already includes the tag, so we split it out here |
| 155 | + repo, tag = docker.utils.parse_repository_tag(target) |
| 156 | + |
| 157 | + # make sure image is pulled locally already |
| 158 | + self.pull(repo, tag=tag, insecure_registry=insecure_registry) |
| 159 | + |
| 160 | + # inspect the image |
| 161 | + return self.client.inspect_image(target) |
| 162 | + |
124 | 163 |
|
125 | 164 | def check_blacklist(repo): |
126 | 165 | """Check a Docker repository name for collision with deis/* components.""" |
@@ -156,3 +195,7 @@ def stream_error(chunk, operation, repo, tag): |
156 | 195 |
|
157 | 196 | def publish_release(source, target, deis_registry, creds=None): |
158 | 197 | return DockerClient().publish_release(source, target, deis_registry, creds) |
| 198 | + |
| 199 | + |
| 200 | +def get_port(target, deis_registry, creds=None): |
| 201 | + return DockerClient().get_port(target, deis_registry, creds) |
0 commit comments