-
Notifications
You must be signed in to change notification settings - Fork 90
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add option to clone containers #1270
base: main
Are you sure you want to change the base?
Conversation
7563400
to
29f5562
Compare
: []; | ||
|
||
const volumes = containerDetail.Mounts.map((mount, index) => { | ||
// podman does not expose SELinux labels |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought it did not, but then I thought I was proven wrong. Is there an issue for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm right, there's MountLabel
. I just need to figure out what it means.
this.setState({ | ||
dialogWarning: _("This container was not created by cockpit"), | ||
dialogWarningDetail: _("Some options may not be copied to the new container."), | ||
}); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't this something we need to always show? We won't support all options podman has as we won't ever have a feature complete UI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's okay to not show it when the container is created through cockpit. On the other hand the "check" if it is made by cockpit isn't 100% robust as it only checks whether it was created through commandline or podman API.
/packit build |
9c2f8d3
to
371704c
Compare
const memoryConfigure = containerDetail.HostConfig.Memory > 0; | ||
const cpuSharesConfigure = containerDetail.HostConfig.CpuShares > 0; | ||
const healthcheck = !!containerDetail.Config.Healthcheck; | ||
const healthCheckOnFailureAction = (this.props.version.split(".")) >= [4, 3, 0] |
Check warning
Code scanning / CodeQL
Implicit operand conversion
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm
371704c
to
41f541e
Compare
ac2abc6
to
01fd85d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This just creates a new container by copying the configuration from another container. However podman offers the 'clone' API, which does this exact thing internally.
Did we consider using that instead?
I discussed this a while back (in 2021) @ #363 (comment): It basically comes down to this; there are basically three things people want to do:
All three items replicate an existing container's configuration. The differences are all around if it's in addition to and if the configuration changes. There's an additional 4th option when pods are concerned (now that we have pod support):
All of these should probably run the container if the container was running before performing the action. (That is: If the container is running, queue up what we're going to do, perform the action, and make sure it's running after. If it was stopped before, then don't start it.)
Yes, As for updating? podman container clone might actually make sense, if I understand it correctly. https://docs.podman.io/en/latest/markdown/podman-container-clone.1.html:
The last example is this one:
...but what if the new name is the same as the old name? And Or is there a better way in Podman to recreate a container with the exact same settings but with a new image? There is https://docs.podman.io/en/latest/markdown/podman-auto-update.1.html but it relies on systemd and is supposed to be automatic with a system service based on a timer, instead of a manual update. It does have a way to check if there's a new version with Anyway, back to this PR and @KKoukiou's question about cloning with editing versus |
3c713c3
to
dd89f1e
Compare
Adds 'Clone' button to container actions which opens prefilled create container modal.
dd89f1e
to
9c8e406
Compare
const container = this.props.container; | ||
const containerDetail = this.props.containerDetail; | ||
const image = this.props.localImages.find(img => img.Id === container.ImageID); | ||
const owner = container.isSystem ? 'system' : this.props.user; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This added line is not executed by any test. Details
const healthcheck = !!containerDetail.Config.Healthcheck; | ||
const healthCheckOnFailureAction = (this.props.version.split(".")) >= [4, 3, 0] | ||
? HealthCheckOnFailureActionOrder.find(item => item.apiName === containerDetail.Config.HealthcheckOnFailureAction).value | ||
: null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This added line is not executed by any test. Details
: null; | ||
|
||
this.setState({ | ||
command: container.Command ? container.Command.join(' ') : "", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This added line is not executed by any test. Details
hasTTY: containerDetail.Config.Tty, | ||
publish, | ||
// memory in MB | ||
memory: memoryConfigure ? (containerDetail.HostConfig.Memory / 1000000) : 512, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This added line is not executed by any test. Details
volumes, | ||
owner, | ||
// unless-stopped: Identical to always | ||
restartPolicy: containerDetail.HostConfig.RestartPolicy.Name === 'unless-stopped' ? 'always' : containerDetail.HostConfig.RestartPolicy.Name, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This added line is not executed by any test. Details
<Button variant='primary' id="create-image-create-run-btn" onClick={() => this.onCreateClicked(true)} isDisabled={(!image && selectedImage === "")}> | ||
{createRunText} | ||
</Button> | ||
<Button variant='secondary' id="create-image-create-btn" onClick={() => this.onCreateClicked(false)} isDisabled={(!image && selectedImage === "")}> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This added line is not executed by any test. Details
let titleText = _("Create container"); | ||
|
||
if (this.props.prefill && this.props.pod) | ||
titleText = _("Clone container in $0"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This added line is not executed by any test. Details
if (this.props.prefill && this.props.pod) | ||
titleText = _("Clone container in $0"); | ||
else if (this.props.prefill) | ||
titleText = _("Clone container"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This added line is not executed by any test. Details
else if (this.props.pod) | ||
titleText = _("Create container in $0"); | ||
|
||
return this.props.pod ? cockpit.format(titleText, this.props.pod.Name) : titleText; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This added line is not executed by any test. Details
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand the use case of this feature, but this is also somewhat of a maintenance burden to as every new feature needs to be supported in the cloning feature as well. I'm not sure if there is a good way to keep track of that.
|
||
const publish = container.Ports | ||
? container.Ports.map((port, index) => { | ||
return { key: index, IP: port.hostIP || port.host_ip, containerPort: port.containerPort || port.container_port, hostPort: port.hostPort || port.host_port, protocol: port.protocol }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be nice to split this off in multiple lines to make it a bit more readable.
export const WarningNotification = ({ warningMessage, warningDetail }) => { | ||
return ( | ||
<Alert isInline variant='warning' title={warningMessage}> | ||
{ warningDetail && <p> {_("Warning message")}: <samp>{warningDetail}</samp> </p> } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also not sure if we should use samp
, we don't use that anywhere. And actually, maybe we should use
pkg/lib/cockpit-components-inline-notification.jsx
instead so basically ModalError
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The warning isn't that it was not created by cockpit, the warning is that some options may not be able to be copied. But: Which options? Is it possible to find out?
<!> Some options might not be copied to the new container (View details)
...And then it'd expand to show which options exist but aren't copied.
We don't need to mention anything about Cockpit.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is possible, but that makes this even more complex problem. We have the full command line - and if we know that it was created though cmdline then we show this message. Parsing it is no easy job. We could maybe show the command line for reminder how the container was created?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the warning message needs to be better. This "check" works in a way that it only sees if container was created using the API or from a commandline. Showing which options are not copied would require parsing the original command...
Cockpit shouldn't be mentioned at all as it's supposed to stay unbranded.
We could maybe show the command line for reminder how the container was created?
maybe this is a good idea?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that we don't use the command line to create containers, nor can you find it out for an existing one. You'd have to create an "inspect json → command line" translator, and that's a big no-no for cockpit-podman.
But also, even if you ignore the container state, you cannot just duplicate the command line. There is no general way to treat volumes during a "clone". It's reasonable to kill the original container and then start a new one with the same volumes, but you can't have two of them at the same time.
if auth: | ||
# Add restart policy | ||
b.set_val("#run-image-dialog-restart-policy", "on-failure") | ||
b.set_input_text('#run-image-dialog-restart-retries input', '2') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Restart policy set to 2, below we seem to check for 5?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
b.wait_visible("div.pf-c-modal-box") | ||
|
||
# container was not created through cockpit, warning should be present | ||
b.wait_visible(".pf-c-form .pf-c-alert") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should also verify what's in the alert.
self.waitContainerRow("busybox_copy") | ||
|
||
ports = self.execute(auth, "podman inspect --format '{{.NetworkSettings.Ports}}' busybox_copy") | ||
self.assertEqual(ports, 'map[]\n') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of checking for \n. Please call .strip()
@tomasmatus are you still working on this, or should we close this due to being conceptually too difficult? |
Implemets: #363
Adds 'Clone' button to container actions which opens prefilled create container modal.