Merge ~pappacena/launchpad:public-ecr-aws-ui into launchpad:master
- Git
- lp:~pappacena/launchpad
- public-ecr-aws-ui
- Merge into master
Proposed by
Thiago F. Pappacena
Status: | Merged |
---|---|
Approved by: | Thiago F. Pappacena |
Approved revision: | e93eeded3d3483a954fe250a0a4431b17c5558f0 |
Merge reported by: | Otto Co-Pilot |
Merged at revision: | not available |
Proposed branch: | ~pappacena/launchpad:public-ecr-aws-ui |
Merge into: | launchpad:master |
Prerequisite: | ~pappacena/launchpad:public-ecr-aws |
Diff against target: |
465 lines (+110/-10) 7 files modified
lib/lp/oci/browser/ocirecipe.py (+33/-2) lib/lp/oci/browser/tests/test_ocirecipe.py (+13/-4) lib/lp/oci/javascript/ocirecipe.edit.js (+1/-0) lib/lp/oci/templates/ocirecipe-edit-push-rules.pt (+14/-0) lib/lp/registry/browser/person.py (+26/-2) lib/lp/registry/browser/tests/test_person.py (+9/-2) lib/lp/registry/templates/person-edit-ociregistrycredentials.pt (+14/-0) |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Tom Wardill (community) | Approve | ||
Review via email: mp+394599@code.launchpad.net |
Commit message
UI to allow adding region to OCI registry credentials
Description of the change
To post a comment you must log in.
Revision history for this message
Thiago F. Pappacena (pappacena) wrote : | # |
Revision history for this message
Tom Wardill (twom) wrote : | # |
I think the field marked 'Region' should say 'Optional' or something. It's not clear (as a new user) that pushing to ROCKs or Dockerhub shouldn't need a 'region' field.
Also, I think it should appear in the overall push rules (picture 1), as you may have an image being pushed to multiple regions, with otherwise identical fields.
review:
Needs Fixing
Revision history for this message
Tom Wardill (twom) : | # |
review:
Approve
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | diff --git a/lib/lp/oci/browser/ocirecipe.py b/lib/lp/oci/browser/ocirecipe.py |
2 | index 460b108..b3a43d7 100644 |
3 | --- a/lib/lp/oci/browser/ocirecipe.py |
4 | +++ b/lib/lp/oci/browser/ocirecipe.py |
5 | @@ -344,7 +344,9 @@ class OCIRecipeEditPushRulesView(LaunchpadFormView): |
6 | super(OCIRecipeEditPushRulesView, self).setUpFields() |
7 | image_name_fields = [] |
8 | url_fields = [] |
9 | + region_fields = [] |
10 | private_url_fields = [] |
11 | + private_region_fields = [] |
12 | username_fields = [] |
13 | private_username_fields = [] |
14 | password_fields = [] |
15 | @@ -361,6 +363,13 @@ class OCIRecipeEditPushRulesView(LaunchpadFormView): |
16 | __name__=self._getFieldName('url', elem.id), |
17 | default=elem.registry_credentials.url, |
18 | required=True, readonly=True)) |
19 | + region = elem.registry_credentials.getCredentialsValue( |
20 | + 'region') |
21 | + region_fields.append( |
22 | + TextLine( |
23 | + __name__=self._getFieldName('region', elem.id), |
24 | + default=region, |
25 | + required=False, readonly=True)) |
26 | username_fields.append( |
27 | TextLine( |
28 | __name__=self._getFieldName('username', elem.id), |
29 | @@ -380,6 +389,10 @@ class OCIRecipeEditPushRulesView(LaunchpadFormView): |
30 | TextLine( |
31 | __name__=self._getFieldName('url', elem.id), |
32 | default='', required=True, readonly=True)) |
33 | + private_region_fields.append( |
34 | + TextLine( |
35 | + __name__=self._getFieldName('region', elem.id), |
36 | + default='', required=False, readonly=True)) |
37 | private_username_fields.append( |
38 | TextLine( |
39 | __name__=self._getFieldName('username', elem.id), |
40 | @@ -405,6 +418,10 @@ class OCIRecipeEditPushRulesView(LaunchpadFormView): |
41 | TextLine( |
42 | __name__=u'add_url', |
43 | required=False, readonly=False)) |
44 | + region_fields.append( |
45 | + TextLine( |
46 | + __name__=u'add_region', |
47 | + required=False, readonly=False)) |
48 | username_fields.append( |
49 | TextLine( |
50 | __name__=u'add_username', |
51 | @@ -424,6 +441,10 @@ class OCIRecipeEditPushRulesView(LaunchpadFormView): |
52 | FormFields( |
53 | *private_url_fields, |
54 | custom_widget=InvisibleCredentialsWidget) + |
55 | + FormFields(*region_fields) + |
56 | + FormFields( |
57 | + *private_region_fields, |
58 | + custom_widget=InvisibleCredentialsWidget) + |
59 | FormFields(*username_fields) + |
60 | FormFields( |
61 | *private_username_fields, |
62 | @@ -453,6 +474,8 @@ class OCIRecipeEditPushRulesView(LaunchpadFormView): |
63 | widgets_by_name = {widget.name: widget for widget in self.widgets} |
64 | url_field_name = ( |
65 | "field." + self._getFieldName("url", rule.id)) |
66 | + region_field_name = ( |
67 | + "field." + self._getFieldName("region", rule.id)) |
68 | image_field_name = ( |
69 | "field." + self._getFieldName("image_name", rule.id)) |
70 | username_field_name = ( |
71 | @@ -461,6 +484,7 @@ class OCIRecipeEditPushRulesView(LaunchpadFormView): |
72 | "field." + self._getFieldName("delete", rule.id)) |
73 | return { |
74 | "url": widgets_by_name[url_field_name], |
75 | + "region": widgets_by_name[region_field_name], |
76 | "image_name": widgets_by_name[image_field_name], |
77 | "username": widgets_by_name[username_field_name], |
78 | "delete": widgets_by_name[delete_field_name], |
79 | @@ -473,6 +497,7 @@ class OCIRecipeEditPushRulesView(LaunchpadFormView): |
80 | "existing_credentials": |
81 | widgets_by_name["field.existing_credentials"], |
82 | "url": widgets_by_name["field.add_url"], |
83 | + "region": widgets_by_name["field.add_region"], |
84 | "username": widgets_by_name["field.add_username"], |
85 | "password": widgets_by_name["field.add_password"], |
86 | "confirm_password": widgets_by_name["field.add_confirm_password"], |
87 | @@ -483,18 +508,20 @@ class OCIRecipeEditPushRulesView(LaunchpadFormView): |
88 | parsed_data = {} |
89 | add_image_name = data.get("add_image_name") |
90 | add_url = data.get("add_url") |
91 | + add_region = data.get("add_region") |
92 | add_username = data.get("add_username") |
93 | add_password = data.get("add_password") |
94 | add_confirm_password = data.get("add_confirm_password") |
95 | add_existing_credentials = data.get("existing_credentials") |
96 | |
97 | # parse data from the Add new rule section of the form |
98 | - if (add_url or add_username or add_password or |
99 | + if (add_url or add_region or add_username or add_password or |
100 | add_confirm_password or add_image_name or |
101 | add_existing_credentials): |
102 | parsed_data.setdefault(None, { |
103 | "image_name": add_image_name, |
104 | "url": add_url, |
105 | + "region": add_region, |
106 | "username": add_username, |
107 | "password": add_password, |
108 | "confirm_password": add_confirm_password, |
109 | @@ -523,6 +550,7 @@ class OCIRecipeEditPushRulesView(LaunchpadFormView): |
110 | add_data = parsed_data[None] |
111 | image_name = add_data.get("image_name") |
112 | url = add_data.get("url") |
113 | + region = add_data.get("region") |
114 | password = add_data.get("password") |
115 | confirm_password = add_data.get("confirm_password") |
116 | username = add_data.get("username") |
117 | @@ -550,9 +578,12 @@ class OCIRecipeEditPushRulesView(LaunchpadFormView): |
118 | |
119 | credentials_set = getUtility(IOCIRegistryCredentialsSet) |
120 | try: |
121 | + credential_data = {'username': username, 'password': password} |
122 | + if region is not None: |
123 | + credential_data['region'] = region |
124 | credentials = credentials_set.getOrCreate( |
125 | registrant=self.user, owner=self.context.owner, url=url, |
126 | - credentials={'username': username, 'password': password}) |
127 | + credentials=credential_data) |
128 | except OCIRegistryCredentialsAlreadyExist: |
129 | self.setFieldError( |
130 | "add_url", |
131 | diff --git a/lib/lp/oci/browser/tests/test_ocirecipe.py b/lib/lp/oci/browser/tests/test_ocirecipe.py |
132 | index 038e602..0ab9a59 100644 |
133 | --- a/lib/lp/oci/browser/tests/test_ocirecipe.py |
134 | +++ b/lib/lp/oci/browser/tests/test_ocirecipe.py |
135 | @@ -1111,6 +1111,10 @@ class TestOCIRecipeEditPushRulesView(OCIConfigHelperMixin, |
136 | text=soupmatchers._not_passed)), |
137 | soupmatchers.Within( |
138 | row, |
139 | + soupmatchers.Tag("Region", "td", |
140 | + text=soupmatchers._not_passed)), |
141 | + soupmatchers.Within( |
142 | + row, |
143 | soupmatchers.Tag("Username", "td", |
144 | text=soupmatchers._not_passed)), |
145 | soupmatchers.Within( |
146 | @@ -1330,6 +1334,7 @@ class TestOCIRecipeEditPushRulesView(OCIConfigHelperMixin, |
147 | browser.getControl(name="field.add_credentials").value = "new" |
148 | browser.getControl(name="field.add_image_name").value = "imagename3" |
149 | browser.getControl(name="field.add_url").value = url |
150 | + browser.getControl(name="field.add_region").value = "somewhere-02" |
151 | browser.getControl(name="field.add_username").value = "username" |
152 | browser.getControl(name="field.add_password").value = "password" |
153 | browser.getControl( |
154 | @@ -1347,8 +1352,9 @@ class TestOCIRecipeEditPushRulesView(OCIConfigHelperMixin, |
155 | url=url, |
156 | username="username"))) |
157 | with person_logged_in(self.person): |
158 | - self.assertEqual( |
159 | - {"username": "username", "password": "password"}, |
160 | + self.assertEqual({ |
161 | + "username": "username", "password": "password", |
162 | + "region": "somewhere-02"}, |
163 | rule.registry_credentials.getCredentials()) |
164 | |
165 | def test_add_oci_push_rules_existing_credentials_duplicate(self): |
166 | @@ -1494,6 +1500,7 @@ class TestOCIRecipeEditPushRulesView(OCIConfigHelperMixin, |
167 | browser.getLink("Edit OCI registry credentials").click() |
168 | |
169 | browser.getControl(name="field.add_url").value = url |
170 | + browser.getControl(name="field.add_region").value = "new_region1" |
171 | browser.getControl(name="field.add_username").value = "new_username" |
172 | browser.getControl(name="field.add_password").value = "password" |
173 | browser.getControl(name="field.add_confirm_password" |
174 | @@ -1508,8 +1515,10 @@ class TestOCIRecipeEditPushRulesView(OCIConfigHelperMixin, |
175 | self.assertEqual(url, creds[1].url) |
176 | self.assertThat( |
177 | (creds[1]).getCredentials(), |
178 | - MatchesDict({"username": Equals("new_username"), |
179 | - "password": Equals("password")})) |
180 | + MatchesDict({ |
181 | + "username": Equals("new_username"), |
182 | + "password": Equals("password"), |
183 | + "region": Equals("new_region1")})) |
184 | |
185 | |
186 | class TestOCIProjectRecipesView(BaseTestOCIRecipeView): |
187 | diff --git a/lib/lp/oci/javascript/ocirecipe.edit.js b/lib/lp/oci/javascript/ocirecipe.edit.js |
188 | index 8b3d82d..c31f532 100644 |
189 | --- a/lib/lp/oci/javascript/ocirecipe.edit.js |
190 | +++ b/lib/lp/oci/javascript/ocirecipe.edit.js |
191 | @@ -23,6 +23,7 @@ YUI.add('lp.oci.ocirecipe.edit', function(Y) { |
192 | }); |
193 | module.set_enabled('field.existing_credentials', value === 'existing'); |
194 | module.set_enabled('field.add_url', value === 'new'); |
195 | + module.set_enabled('field.add_region', value === 'new'); |
196 | module.set_enabled('field.add_username', value === 'new'); |
197 | module.set_enabled('field.add_password', value === 'new'); |
198 | module.set_enabled('field.add_confirm_password', value === 'new'); |
199 | diff --git a/lib/lp/oci/templates/ocirecipe-edit-push-rules.pt b/lib/lp/oci/templates/ocirecipe-edit-push-rules.pt |
200 | index eee7db7..2cb3fec 100644 |
201 | --- a/lib/lp/oci/templates/ocirecipe-edit-push-rules.pt |
202 | +++ b/lib/lp/oci/templates/ocirecipe-edit-push-rules.pt |
203 | @@ -46,6 +46,12 @@ |
204 | <tr> |
205 | <th class="push-rule-image-name">Image name</th> |
206 | <th class="push-rule-url">Registry URL</th> |
207 | + <th class="push-rule-region"> |
208 | + Region (optional) |
209 | + <img height="14" width="14" alt="" |
210 | + title="For AWS ECR, insert the AWS region of the repository. Leave blank otherwise." |
211 | + src="/@@/question" /> |
212 | + </th> |
213 | <th class="push-rule-username">Username</th> |
214 | <th class="push-rule-password">Password</th> |
215 | <th class="push-rule-confirm-password">Confirm password</th> |
216 | @@ -66,6 +72,10 @@ |
217 | tal:define="widget nocall:rule_widgets/url"> |
218 | <metal:widget use-macro="context/@@launchpad_form/widget_div" /> |
219 | </td> |
220 | + <td class="push-rule-region" |
221 | + tal:define="widget nocall:rule_widgets/region"> |
222 | + <metal:widget use-macro="context/@@launchpad_form/widget_div" /> |
223 | + </td> |
224 | <td class="push-rule-username" |
225 | tal:define="widget nocall:rule_widgets/username"> |
226 | <metal:widget use-macro="context/@@launchpad_form/widget_div" /> |
227 | @@ -115,6 +125,10 @@ |
228 | tal:define="widget nocall:new_rule_widgets/url"> |
229 | <metal:widget use-macro="context/@@launchpad_form/widget_div" /> |
230 | </td> |
231 | + <td class="push-rule-region" |
232 | + tal:define="widget nocall:new_rule_widgets/region"> |
233 | + <metal:widget use-macro="context/@@launchpad_form/widget_div" /> |
234 | + </td> |
235 | <td class="push-rule-username" |
236 | tal:define="widget nocall:new_rule_widgets/username"> |
237 | <metal:widget use-macro="context/@@launchpad_form/widget_div" /> |
238 | diff --git a/lib/lp/registry/browser/person.py b/lib/lp/registry/browser/person.py |
239 | index aef4eb0..55596e9 100644 |
240 | --- a/lib/lp/registry/browser/person.py |
241 | +++ b/lib/lp/registry/browser/person.py |
242 | @@ -3738,17 +3738,25 @@ class PersonEditOCIRegistryCredentialsView(LaunchpadFormView): |
243 | default=credentials.url, |
244 | required=True, readonly=False) |
245 | |
246 | + region = TextLine( |
247 | + __name__=self._getFieldName('region', id), |
248 | + default=credentials.getCredentialsValue("region"), |
249 | + required=False, readonly=False) |
250 | + |
251 | delete = Bool( |
252 | __name__=self._getFieldName('delete', id), |
253 | default=False, |
254 | required=True, readonly=False) |
255 | |
256 | - return owner, username, password, confirm_password, url, delete |
257 | + return owner, username, password, confirm_password, url, region, delete |
258 | |
259 | def getAddFieldsRow(self): |
260 | add_url = TextLine( |
261 | __name__=u'add_url', |
262 | required=False, readonly=False) |
263 | + add_region = TextLine( |
264 | + __name__=u'add_region', |
265 | + required=False, readonly=False) |
266 | add_owner = Choice( |
267 | __name__=u'add_owner', |
268 | vocabulary=( |
269 | @@ -3766,7 +3774,7 @@ class PersonEditOCIRegistryCredentialsView(LaunchpadFormView): |
270 | required=False, readonly=False) |
271 | |
272 | return ( |
273 | - add_url, add_owner, add_username, |
274 | + add_url, add_region, add_owner, add_username, |
275 | add_password, add_confirm_password) |
276 | |
277 | def _parseFieldName(self, field_name): |
278 | @@ -3825,6 +3833,8 @@ class PersonEditOCIRegistryCredentialsView(LaunchpadFormView): |
279 | "field." + self._getFieldName("confirm_password", |
280 | credentials.id)) |
281 | url_field_name = "field." + self._getFieldName("url", credentials.id) |
282 | + region_field_name = "field." + self._getFieldName( |
283 | + "region", credentials.id) |
284 | delete_field_name = ( |
285 | "field." + self._getFieldName("delete", credentials.id)) |
286 | return { |
287 | @@ -3833,6 +3843,7 @@ class PersonEditOCIRegistryCredentialsView(LaunchpadFormView): |
288 | "password": widgets_by_name[password_field_name], |
289 | "confirm_password": widgets_by_name[confirm_password_field_name], |
290 | "url": widgets_by_name[url_field_name], |
291 | + "region": widgets_by_name[region_field_name], |
292 | "delete": widgets_by_name[delete_field_name] |
293 | } |
294 | |
295 | @@ -3840,6 +3851,7 @@ class PersonEditOCIRegistryCredentialsView(LaunchpadFormView): |
296 | """Rearrange form data to make it easier to process.""" |
297 | parsed_data = {} |
298 | add_url = data["add_url"] |
299 | + add_region = data["add_region"] |
300 | add_owner = data["add_owner"] |
301 | add_username = data["add_username"] |
302 | add_password = data["add_password"] |
303 | @@ -3850,6 +3862,7 @@ class PersonEditOCIRegistryCredentialsView(LaunchpadFormView): |
304 | "password": add_password, |
305 | "confirm_password": add_confirm_password, |
306 | "url": add_url, |
307 | + "region": add_region, |
308 | "owner": add_owner, |
309 | "action": "add", |
310 | }) |
311 | @@ -3865,6 +3878,7 @@ class PersonEditOCIRegistryCredentialsView(LaunchpadFormView): |
312 | confirm_password_field_name = self._getFieldName( |
313 | "confirm_password", credentials_id) |
314 | url_field_name = self._getFieldName("url", credentials_id) |
315 | + region_field_name = self._getFieldName("region", credentials_id) |
316 | delete_field_name = self._getFieldName("delete", credentials_id) |
317 | if data.get(delete_field_name): |
318 | action = "delete" |
319 | @@ -3875,6 +3889,7 @@ class PersonEditOCIRegistryCredentialsView(LaunchpadFormView): |
320 | "password": data.get(password_field_name), |
321 | "confirm_password": data.get(confirm_password_field_name), |
322 | "url": data.get(url_field_name), |
323 | + "region": data.get(region_field_name), |
324 | "owner": data.get(owner_field_name), |
325 | "action": action, |
326 | }) |
327 | @@ -3882,6 +3897,7 @@ class PersonEditOCIRegistryCredentialsView(LaunchpadFormView): |
328 | return parsed_data |
329 | |
330 | def changeCredentials(self, parsed_credentials, credentials): |
331 | + region = parsed_credentials["region"] |
332 | username = parsed_credentials["username"] |
333 | password = parsed_credentials["password"] |
334 | confirm_password = parsed_credentials["confirm_password"] |
335 | @@ -3902,6 +3918,11 @@ class PersonEditOCIRegistryCredentialsView(LaunchpadFormView): |
336 | credentials.url = parsed_credentials["url"] |
337 | elif parsed_credentials["url"] != credentials.url: |
338 | credentials.url = parsed_credentials["url"] |
339 | + if credentials.getCredentialsValue('region') != region: |
340 | + credentials_data = removeSecurityProxy( |
341 | + credentials.getCredentials()) |
342 | + credentials_data["region"] = region |
343 | + credentials.setCredentials(credentials_data) |
344 | if owner != credentials.owner: |
345 | credentials.owner = owner |
346 | |
347 | @@ -3919,6 +3940,7 @@ class PersonEditOCIRegistryCredentialsView(LaunchpadFormView): |
348 | |
349 | def addCredentials(self, parsed_add_credentials): |
350 | url = parsed_add_credentials["url"] |
351 | + region = parsed_add_credentials["region"] |
352 | owner = parsed_add_credentials["owner"] |
353 | password = parsed_add_credentials["password"] |
354 | confirm_password = parsed_add_credentials["confirm_password"] |
355 | @@ -3936,6 +3958,8 @@ class PersonEditOCIRegistryCredentialsView(LaunchpadFormView): |
356 | credentials = { |
357 | 'username': username, |
358 | 'password': password} |
359 | + if region: |
360 | + credentials["region"] = region |
361 | try: |
362 | getUtility(IOCIRegistryCredentialsSet).new( |
363 | registrant=self.user, owner=owner, url=url, |
364 | diff --git a/lib/lp/registry/browser/tests/test_person.py b/lib/lp/registry/browser/tests/test_person.py |
365 | index 07ef8d4..350afcb 100644 |
366 | --- a/lib/lp/registry/browser/tests/test_person.py |
367 | +++ b/lib/lp/registry/browser/tests/test_person.py |
368 | @@ -1455,13 +1455,16 @@ class TestPersonOCIRegistryCredentialsView( |
369 | "password": Equals("bar"), |
370 | }))) |
371 | |
372 | - # change only the registry url |
373 | + # change only the registry url and region |
374 | browser = self.getViewBrowser( |
375 | self.owner, view_name='+oci-registry-credentials', user=self.user) |
376 | browser.getLink("Edit OCI registry credentials").click() |
377 | url_control = browser.getControl( |
378 | name="field.url.%d" % registry_credentials_id) |
379 | url_control.value = newurl |
380 | + url_control = browser.getControl( |
381 | + name="field.region.%d" % registry_credentials_id) |
382 | + url_control.value = 'us-west-2' |
383 | browser.getControl("Save").click() |
384 | with person_logged_in(self.user): |
385 | self.assertThat( |
386 | @@ -1470,6 +1473,7 @@ class TestPersonOCIRegistryCredentialsView( |
387 | MatchesDict({ |
388 | "username": Equals("different_username"), |
389 | "password": Equals("bar"), |
390 | + "region": Equals("us-west-2"), |
391 | }))) |
392 | |
393 | # change only the password |
394 | @@ -1484,7 +1488,7 @@ class TestPersonOCIRegistryCredentialsView( |
395 | self.assertIn( |
396 | "Passwords do not match.", six.ensure_text(browser.contents)) |
397 | |
398 | - # change all fields with one edit action |
399 | + # change all fields (except region) with one edit action |
400 | username_control = browser.getControl( |
401 | name="field.username.%d" % registry_credentials_id) |
402 | username_control.value = 'third_different_username' |
403 | @@ -1506,6 +1510,7 @@ class TestPersonOCIRegistryCredentialsView( |
404 | MatchesDict({ |
405 | "username": Equals("third_different_username"), |
406 | "password": Equals("third_newpassword"), |
407 | + "region": Equals("us-west-2"), |
408 | }))) |
409 | |
410 | def test_add_oci_registry_credentials(self): |
411 | @@ -1530,6 +1535,7 @@ class TestPersonOCIRegistryCredentialsView( |
412 | [owner_name], browser.getControl(name="field.add_owner").value) |
413 | |
414 | browser.getControl(name="field.add_url").value = url |
415 | + browser.getControl(name="field.add_region").value = "sa-east-1" |
416 | browser.getControl(name="field.add_owner").value = [new_owner_name] |
417 | browser.getControl(name="field.add_username").value = "new_username" |
418 | browser.getControl(name="field.add_password").value = "password" |
419 | @@ -1555,6 +1561,7 @@ class TestPersonOCIRegistryCredentialsView( |
420 | MatchesDict({ |
421 | "username": Equals("new_username"), |
422 | "password": Equals("password"), |
423 | + "region": Equals("sa-east-1"), |
424 | })))) |
425 | |
426 | def test_delete_oci_registry_credentials(self): |
427 | diff --git a/lib/lp/registry/templates/person-edit-ociregistrycredentials.pt b/lib/lp/registry/templates/person-edit-ociregistrycredentials.pt |
428 | index 1b0fd0f..27aa9d3 100644 |
429 | --- a/lib/lp/registry/templates/person-edit-ociregistrycredentials.pt |
430 | +++ b/lib/lp/registry/templates/person-edit-ociregistrycredentials.pt |
431 | @@ -43,6 +43,12 @@ |
432 | <thead> |
433 | <tr> |
434 | <th class="credentials-url">Registry URL</th> |
435 | + <th class="credentials-region"> |
436 | + Region (optional) |
437 | + <img height="14" width="14" alt="" |
438 | + title="For AWS ECR, insert the AWS region of the repository. Leave blank otherwise." |
439 | + src="/@@/question" /> |
440 | + </th> |
441 | <th class="credentials-owner">Owner</th> |
442 | <th class="credentials-username">Username</th> |
443 | <th class="credentials-password">Password</th> |
444 | @@ -60,6 +66,10 @@ |
445 | tal:define="widget nocall:credentials_widgets/url"> |
446 | <metal:widget use-macro="context/@@launchpad_form/widget_div" /> |
447 | </td> |
448 | + <td class="credentials-region" |
449 | + tal:define="widget nocall:credentials_widgets/region"> |
450 | + <metal:widget use-macro="context/@@launchpad_form/widget_div" /> |
451 | + </td> |
452 | <td class="credentials-owner" |
453 | tal:define="widget nocall:credentials_widgets/owner"> |
454 | <metal:widget use-macro="context/@@launchpad_form/widget_div" /> |
455 | @@ -91,6 +101,10 @@ |
456 | tal:define="widget nocall:view/widgets/add_url"> |
457 | <metal:widget use-macro="context/@@launchpad_form/widget_div" /> |
458 | </td> |
459 | + <td class="credentials-region" |
460 | + tal:define="widget nocall:view/widgets/add_region"> |
461 | + <metal:widget use-macro="context/@@launchpad_form/widget_div" /> |
462 | + </td> |
463 | <td class="credentials-owner" |
464 | tal:define="widget nocall:view/widgets/add_owner"> |
465 | <metal:widget use-macro="context/@@launchpad_form/widget_div" /> |
Screenshots can be found here:
https:/ /private- fileshare. canonical. com/~pappacena/ screenshots/ oci/1.png /private- fileshare. canonical. com/~pappacena/ screenshots/ oci/2.png /private- fileshare. canonical. com/~pappacena/ screenshots/ oci/3.png
https:/
https:/