diff --git a/src/ImageSearchModal.jsx b/src/ImageSearchModal.jsx
index 749c938da..b789151b1 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);
@@ -72,12 +73,16 @@ export class ImageSearchModal extends React.Component {
this.setState({ searchInProgress: true });
this.activeConnection = rest.connect(client.getAddress(this.state.isSystem), this.state.isSystem);
+
+ const rr = this.state.registry;
+ const registry = rr.length < 1 || rr[rr.length - 1] === "/" ? rr : rr + "/";
+
const options = {
method: "GET",
path: "/v1.12/libpod/images/search",
body: "",
params: {
- term: this.state.imageIdentifier,
+ term: registry + this.state.imageIdentifier,
},
};
this.activeConnection.call(options)
@@ -136,17 +141,37 @@ export class ImageSearchModal extends React.Component {
}
-
-
-
- this.onValueChanged('imageIdentifier', e.target.value)} />
+
+
+
this.onValueChanged('imageIdentifier', e.target.value)} />
+
+
+
+ this.setState({ registry: value }, () => this.onSearchTriggered(false))
+ }>
+
+ {_("All registries")}
+
+ {(this.props.registries.search || []).map(r => {
+ return
+ {r}
+ ;
+ })
+ }
+
+
+
{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 =
/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")
@@ -433,6 +435,7 @@ class TestApplication(testlib.MachineCase):
def fillDialog(self):
# Search for image specified with self.imageName and self.imageTag
b.click("#{0}".format(self.user))
+ b.set_val('#registry-select', "localhost:5000")
# HACK: Sometimes the value is not shown fully. FIXME
b.set_input_text("#search-image-dialog-name", self.imageName, value_check=False)
if self.imageTag:
@@ -468,7 +471,7 @@ class TestApplication(testlib.MachineCase):
checkImage(b, "localhost:5000/{0}:{1}".format(self.imageName, self.imageTag or "latest"), "system" if self.user == "system" else "admin")
# Find out this image ID
- self.imageSha = execute(self.user == "system", "podman inspect --format '{{{{.Id}}}}' {0}:{1}".format(self.imageName, self.imageTag or "latest")).strip()
+ self.imageSha = execute(self.user == "system", "podman inspect --format '{{{{.Id}}}}' localhost:5000/{0}:{1}".format(self.imageName, self.imageTag or "latest")).strip()
return self
@@ -505,6 +508,19 @@ class TestApplication(testlib.MachineCase):
self.login_and_go("/podman", authorized=True, superuser=True)
b.wait_present("#app")
+ # Test registries
+ b.click("header button:contains(Get new image)")
+ b.wait_present('div.modal-dialog div.modal-header h4.modal-title:contains("Search Image")')
+ # HACK: Sometimes the value is not shown fully. FIXME
+ b.set_input_text("#search-image-dialog-name", "my-busybox", value_check=False)
+
+ b.wait_present("div.list-group .image-list-item label:contains('localhost:5000/my-busybox')")
+ b.wait_present("div.list-group .image-list-item label:contains('localhost:6000/my-busybox')")
+
+ b.set_val('#registry-select', "localhost:6000")
+ b.wait_not_present("div.list-group .image-list-item label:contains('localhost:5000/my-busybox')")
+ b.wait_present("div.list-group .image-list-item label:contains('localhost:6000/my-busybox')")
+
dialog0 = DownloadImageDialog('my-busybox', user="system")
dialog0.openDialog() \
.fillDialog() \
@@ -518,7 +534,7 @@ class TestApplication(testlib.MachineCase):
.expectDownloadSuccess()
dialog1.deleteImage(True)
- dialog0.deleteImage()
+ dialog0.deleteImage(True)
dialog = DownloadImageDialog('my-busybox', 'latest', user="system")
dialog.openDialog() \