|
3 | 3 | from django.conf import settings |
4 | 4 | from django.db import models |
5 | 5 |
|
6 | | -import docker |
7 | | -from docker import Client |
8 | | -from retrying import retry |
9 | | - |
10 | | -from registry import publish_release, RegistryException |
| 6 | +from registry import publish_release, get_port as docker_get_port, RegistryException |
11 | 7 | from api.utils import dict_diff |
12 | 8 | from api.models import UuidAuditedModel, log_event, DeisException |
13 | 9 | from scheduler import KubeHTTPException |
@@ -40,7 +36,19 @@ def __str__(self): |
40 | 36 |
|
41 | 37 | @property |
42 | 38 | def image(self): |
43 | | - # return image if it is already in the registry, test host and then host + port |
| 39 | + # Builder pushes to internal registry, exclude SHA based images from being returned |
| 40 | + registry = self.config.registry |
| 41 | + if ( |
| 42 | + registry.get('username', None) and |
| 43 | + registry.get('password', None) and |
| 44 | + # SHA means it came from a git push (builder) |
| 45 | + not self.build.sha and |
| 46 | + # hostname tells Builder where to push images |
| 47 | + not registry.get('hostname', None) |
| 48 | + ): |
| 49 | + return self.build.image |
| 50 | + |
| 51 | + # return image if it is already in a registry, test host and then host + port |
44 | 52 | if ( |
45 | 53 | self.build.image.startswith(settings.REGISTRY_HOST) or |
46 | 54 | self.build.image.startswith(settings.REGISTRY_URL) |
@@ -95,49 +103,80 @@ def publish(self): |
95 | 103 | if self.build.source_based: |
96 | 104 | return |
97 | 105 |
|
98 | | - source_image = self.build.image |
| 106 | + # Builder pushes to internal registry, exclude SHA based images from being returned early |
| 107 | + registry = self.config.registry |
| 108 | + if ( |
| 109 | + registry.get('username', None) and |
| 110 | + registry.get('password', None) and |
| 111 | + # SHA means it came from a git push (builder) |
| 112 | + not self.build.sha and |
| 113 | + # hostname tells Builder where to push images |
| 114 | + not registry.get('hostname', None) |
| 115 | + ): |
| 116 | + log_event(self.app, '{} exists in the target registry. Using image for release {} of app {}'.format(self.build.image, self.version, self.app)) # noqa |
| 117 | + return |
| 118 | + |
99 | 119 | # return image if it is already in the registry, test host and then host + port |
100 | 120 | if ( |
101 | | - source_image.startswith(settings.REGISTRY_HOST) or |
102 | | - source_image.startswith(settings.REGISTRY_URL) |
| 121 | + self.build.image.startswith(settings.REGISTRY_HOST) or |
| 122 | + self.build.image.startswith(settings.REGISTRY_URL) |
103 | 123 | ): |
104 | | - log_event(self.app, '{} already exists in the target registry. Using this image for release {} of app {}'.format(source_image, self.version, self.app)) # noqa |
| 124 | + log_event(self.app, '{} exists in the target registry. Using image for release {} of app {}'.format(self.build.image, self.version, self.app)) # noqa |
105 | 125 | return |
106 | 126 |
|
107 | 127 | # add tag if it was not provided |
| 128 | + source_image = self.build.image |
108 | 129 | if ':' not in source_image: |
109 | 130 | source_image = "{}:{}".format(source_image, self.build.version) |
110 | 131 |
|
111 | 132 | # if build is source based then it was pushed into the deis registry |
112 | 133 | deis_registry = bool(self.build.source_based) |
113 | 134 | publish_release(source_image, self.image, deis_registry, self.get_registry_auth()) |
114 | 135 |
|
115 | | - @retry(stop_max_attempt_number=3, wait_fixed=1000) |
116 | 136 | def get_port(self, routable=False): |
117 | 137 | """ |
118 | | - Get a port from a Docker image |
| 138 | + Get application port for a given release. If pulling from private registry |
| 139 | + then use default port or read from ENV var, otherwise attempt to pull from |
| 140 | + the docker image |
119 | 141 | """ |
120 | | - port = None |
121 | | - # Only care about port for routable application |
122 | | - if not routable: |
123 | | - return port |
124 | | - |
125 | | - if self.build.type == "buildpack": |
126 | | - msg = "Using default port 5000 for build pack image {}".format(self.image) |
127 | | - log_event(self.app, msg) |
128 | | - return 5000 |
129 | | - |
130 | | - # get the target repository name and tag |
131 | | - repo, tag = docker.utils.parse_repository_tag(self.image) |
132 | | - |
133 | | - docker_cli = Client(version="auto") |
134 | | - docker_cli.pull(repo, tag=tag, insecure_registry=True) |
135 | | - image_info = docker_cli.inspect_image(self.image) |
136 | | - if 'ExposedPorts' not in image_info['Config']: |
137 | | - return None |
| 142 | + try: |
| 143 | + deis_registry = bool(self.build.source_based) |
| 144 | + envs = self.config.values |
| 145 | + creds = self.get_registry_auth() |
| 146 | + |
| 147 | + port = None |
| 148 | + # Only care about port for routable application |
| 149 | + if not routable: |
| 150 | + return port |
| 151 | + |
| 152 | + if self.build.type == "buildpack": |
| 153 | + msg = "Using default port 5000 for build pack image {}".format(self.image) |
| 154 | + log_event(self.app, msg) |
| 155 | + return 5000 |
| 156 | + |
| 157 | + # application has registry auth - $PORT is required |
| 158 | + if creds is not None: |
| 159 | + if envs.get('PORT', None) is None: |
| 160 | + log_event(self.app, 'Private registry detected but no $PORT defined. Defaulting to $PORT 5000', logging.WARNING) # noqa |
| 161 | + return 5000 |
| 162 | + |
| 163 | + # User provided PORT |
| 164 | + return envs.get('PORT') |
| 165 | + |
| 166 | + # If the user provides PORT |
| 167 | + if envs.get('PORT', None): |
| 168 | + return envs.get('PORT') |
| 169 | + |
| 170 | + # discover port from docker image |
| 171 | + port = docker_get_port(self.image, deis_registry, creds) |
| 172 | + if port is None: |
| 173 | + msg = "Expose a port or make the app non routable by changing the process type" |
| 174 | + log_event(self.app, msg, logging.ERROR) |
| 175 | + raise DeisException(msg) |
138 | 176 |
|
139 | | - port = int(list(image_info['Config']['ExposedPorts'].keys())[0].split("/")[0]) |
140 | | - return port |
| 177 | + return port |
| 178 | + except Exception as e: |
| 179 | + raise DeisException(str(e)) from e |
141 | 180 |
|
142 | 181 | def get_registry_auth(self): |
143 | 182 | """ |
|
0 commit comments