diff --git a/src/ImageSearchModal.jsx b/src/ImageSearchModal.jsx index 749c938da..5a2ea236b 100644 --- a/src/ImageSearchModal.jsx +++ b/src/ImageSearchModal.jsx @@ -1,8 +1,8 @@ import React from 'react'; import { ListGroup, ListGroupItem, Modal } from 'patternfly-react'; -import { Button, InputGroup, InputGroupText } from '@patternfly/react-core'; -import { SearchIcon } from '@patternfly/react-icons'; +import { Button, InputGroup } from '@patternfly/react-core'; +import * as Select from '../lib/cockpit-components-select.jsx'; import { ErrorNotification } from './Notification.jsx'; import cockpit from 'cockpit'; import rest from './rest.js'; @@ -22,6 +22,7 @@ export class ImageSearchModal extends React.Component { searchInProgress: false, searchFinished: false, isSystem: props.systemServiceAvailable, + registry: "", }; this.onDownloadClicked = this.onDownloadClicked.bind(this); this.onItemSelected = this.onItemSelected.bind(this); @@ -77,7 +78,7 @@ export class ImageSearchModal extends React.Component { path: "/v1.12/libpod/images/search", body: "", params: { - term: this.state.imageIdentifier, + term: this.state.registry + this.state.imageIdentifier, }, }; this.activeConnection.call(options) @@ -136,17 +137,36 @@ export class ImageSearchModal extends React.Component { } - - - - this.onValueChanged('imageIdentifier', e.target.value)} /> +
+ + + this.setState({ registry: value }, () => this.onSearchTriggered(false)) + }> + + {_("All registries")} + + { (this.props.registries.search || []).map(r => { + const rx = r[r.length - 1] === "/" ? r : r + "/"; + return + {rx} + ; + }) + } + +
+
+ + this.onValueChanged('imageIdentifier', e.target.value)} /> +
{this.state.searchInProgress &&
} diff --git a/src/Images.jsx b/src/Images.jsx index d1ba391d6..e2b0c0a1f 100644 --- a/src/Images.jsx +++ b/src/Images.jsx @@ -261,6 +261,7 @@ class Images extends React.Component { close={() => this.setState({ showSearchImageModal: false })} downloadImage={this.downloadImage} user={this.props.user} + registries={this.props.registries} userServiceAvailable={this.props.userServiceAvailable} systemServiceAvailable={this.props.systemServiceAvailable} /> } {this.state.imageDownloadInProgress &&
{_("Pulling")} {this.state.imageDownloadInProgress}...
} diff --git a/src/app.jsx b/src/app.jsx index a92ccdfc8..bfaf1c121 100644 --- a/src/app.jsx +++ b/src/app.jsx @@ -324,7 +324,11 @@ class Application extends React.Component { init(system) { client.getInfo(system) .then(reply => { - this.setState({ [system ? "systemServiceAvailable" : "userServiceAvailable"]: true, version: reply.version.Version }); + this.setState({ + [system ? "systemServiceAvailable" : "userServiceAvailable"]: true, + version: reply.version.Version, + registries: reply.registries, + }); this.updateImagesAfterEvent(system); this.updateContainersAfterEvent(system, true); client.streamEvents(system, @@ -514,6 +518,7 @@ class Application extends React.Component { user={permission.user || _("user")} userServiceAvailable={this.state.userServiceAvailable} systemServiceAvailable={this.state.systemServiceAvailable} + registries={this.state.registries} />; const containerList = label, + > select, + > input { + display: block; + margin-right: var(--pf-global--spacer--md); + } +} + +.vertical-group.wide { + flex-grow: 1; +} + .modal-body .alert { margin-bottom: -20px; margin-top: 30px; @@ -236,3 +257,6 @@ font-weight: 400; } +#registry-select option:first-child { + font-style: italic; +} diff --git a/test/check-application b/test/check-application index be0ccf113..4a0ee79f4 100755 --- a/test/check-application +++ b/test/check-application @@ -18,10 +18,10 @@ from machine_core import ssh_connection REGISTRIES_CONF=""" [registries.search] -registries = ['localhost:5000'] +registries = ['localhost:5000', 'localhost:6000'] [registries.insecure] -registries = ['localhost:5000'] +registries = ['localhost:5000', 'localhost:6000'] """ def checkImage(browser, name, owner): @@ -406,12 +406,14 @@ class TestApplication(testlib.MachineCase): execute = self.execute def prepare(): - # Create and start registry container + # Create and start registry containers self.execute(True, "podman run -d -p 5000:5000 --name registry registry:2") + self.execute(True, "podman run -d -p 6000:5000 --name registry_alt registry:2") # Add local insecure registry into registries conf self.execute(True, "echo \"{0}\" > /etc/containers/registries.conf && systemctl stop podman.service".format(REGISTRIES_CONF)) - # Push busybox image to the local registry + # Push busybox image to the local registries self.execute(True, "podman tag busybox localhost:5000/my-busybox && podman push localhost:5000/my-busybox") + self.execute(True, "podman tag busybox localhost:6000/my-busybox && podman push localhost:6000/my-busybox") # Untag busybox image which duplicates the image we are about to download self.execute(True, "podman rmi -f busybox") @@ -504,6 +506,7 @@ class TestApplication(testlib.MachineCase): self.login_and_go("/podman", authorized=True, superuser=True) b.wait_present("#app") + testlib.sit() dialog0 = DownloadImageDialog('my-busybox', user="system") dialog0.openDialog() \ @@ -538,6 +541,10 @@ class TestApplication(testlib.MachineCase): .selectImageAndDownload() \ .expectDownloadErrorForNonExistingTag() + # Test registries + # TODO Check that the list contains both repos + # TODO Check that it filters only in one + def testLifecycleOperationsUser(self): self._testLifecycleOperations(False)