Skip to content

Two rule-two refusals have no counterfactual the Refusal row shape can hold #116

Closed

Description

@lesnik512

Found by #109 phase 2. Two of the sites in its backfill list do not fit the row shape, for two different reasons. Both need a ruling before phase 3's completeness gate can demand a row for every site.

deploy.resources.reservations.cpus and .devices — no spelling exists

resources.py:64 refuses both with (no podman equivalent). A Refusal row asserts that podman run <podman_argv> exits nonzero, but there is no argv to write: the claim is that podman has no flag at all, not that a flag fails. Measured on 4.9.3, podman run --help offers --memory-reservation and nothing else matching reserv, and an invented --cpu-reservation gives unknown flag, which proves only that I guessed a name podman does not have.

The mechanizable form is an absence assertion: a row naming candidate flags that must stay absent from podman run --help, so that if podman ever grows one, the row goes red and the refusal gets re-examined. That is weaker evidence than the other rows but it is real, and it is the only thing that keeps the claim from going stale.

.devices is the messier half: --device exists, but Docker's reservations.devices is a scheduling reservation carrying capabilities (gpu), driver and count, which is not what --device does. Whether that counts as "no equivalent" or "a different thing" wants a written answer either way.

volume nocopy — measured, but the measurement is not clean

parsing.py:318 refuses it with (podman cannot express it). Measured on 4.9.3:

--mount type=volume,source=ncvol1,dst=/data,nocopy        exit=125 Error: nocopy: invalid mount option
--mount type=volume,source=ncvol2,dst=/data,nocopy=true   exit=125 Error: nocopy: invalid mount option
-v ncvol3:/data:nocopy                                    exit=0

So the long form podman2pod actually emits (--mount) cannot express it, but the short -v form accepts the option. A follow-up probe of the semantics was inconclusive rather than confirming: seeding a fresh volume from the image's /etc gave 10 entries without nocopy and 3 with it. Different, so podman is not simply ignoring the option, but not 0 either, which is what a working nocopy should produce.

I am not ruling on this from a probe that does not make sense. The refusal stays as it is until someone runs a clean experiment: a volume whose contents are known exactly, mounted with and without nocopy, checked for an empty volume rather than a smaller one. If -v :nocopy does suppress the copy-up, this is a LIMITATION row and the refusal message needs the same correction the drive-qualified bind got in #110.

Activity

  1. lesnik512 commented on Sep 20, 2026

    @lesnik512
    MemberAuthor

    Measured, podman 4.9.3, CI (run 35509724204 and its follow-up)

    nocopy works. The refusal message is wrong.

    The inconclusive "10 entries vs 3" from the first probe is fully explained: I was counting, not looking. Listing names instead:

    mounted at /etc          -> volume contains: group hostname hosts localtime mtab network
                                                 nsswitch.conf passwd resolv.conf shadow
    mounted at /etc:nocopy   -> volume contains: hostname hosts resolv.conf
    

    The three survivors are podman's own runtime files — it writes /etc/hosts, /etc/hostname and /etc/resolv.conf into every container, and they land in the volume because the volume is mounted at /etc. Every one of the image's seven files (group, localtime, mtab, network, nsswitch.conf, passwd, shadow) is gone. nocopy suppresses the copy-up completely.

    It is also parsed rather than tolerated:

    -v vol:/etc:nocopy          exit=0
    -v vol:/etc:nosuchoption    exit=125  Error: invalid option type "nosuchoption"
    

    So (podman cannot express it) is false. podman expresses it in the short form and it does what Docker says it does; what cannot express it is --mount, which is the grammar compose2pod emits for a long-form volume (nocopy: invalid mount option, measured in the first probe).

    That makes it a LIMITATION, not a rule-two refusal — the same correction the drive-qualified bind got in #110, with the same escape available: -v <vol>:<target>:nocopy is a spelling compose2pod could emit for exactly this case. Whether to emit it is a separate decision from fixing the message.

    reservations.cpus: absence confirmed

    flags matching reserv:  --memory-reservation   (and --preserve-fds, which only matched the regex)
    --cpu-reservation 1     exit=125  unknown flag
    --cpus-reservation 1    exit=125  unknown flag
    

    --memory-reservation is the one that exists, and compose2pod already emits it for reservations.memory. An absence-assertion row over the candidate names is the right shape here.

    reservations.devices: not absence — something worse

    --gpus exists on podman 4.9.3, hidden:

    grep -i gpu over the whole help text:  (absent from --help)
    --gpus 'all'        exit=0
    --gpus '1'          exit=0
    --gpus 'nonsense'   exit=0
    --gpus ''           exit=0
    

    It accepts nonsense, so it validates nothing. On a runner with no GPU --gpus all adds no device, which proves little by itself — but an unvalidated flag means emitting it would compile, run, exit 0, and reserve nothing. That is the #104 / #114 failure mode exactly: a false green.

    So the refusal stands, and the reason is sharper than "no equivalent": podman has a stub that accepts anything and does nothing. The mechanizable row is not absence but non-validation — assert --gpus nonsense exits 0, and when a later podman starts rejecting it, the row goes red and the refusal gets re-examined.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions