Bug: top level directories are removed if there is only one
Opened this issue · 5 comments
stacker version
v0.30.1-15-gdc0ada0
Describe the bug
If you attempt to build the stacker.yaml below it will fail.
The reason is that the /files
directory is stripped away in the 'mybuild' layer. The files 'subuid' and 'subgid' are directly in /.
$ stacker build --layer-type=squashfs --layer-type=tar
...
error: lstat /files/subuid: no such file or directory
error: execute failed: exit status 1
error: exit status 1
$ cat stacker.yaml
mybuild:
from:
type: scratch
import:
- path: /etc/subuid
dest: /files/
- path: /etc/subgid
dest: /files
mytest:
from:
type: docker
url: docker://ubuntu:latest
import:
- stacker://mybuild/files/subuid
- stacker://mybuild/files/subgid
run: |
ls -l /stacker
To reproduce
No response
Expected behavior
No response
Screenshots
No response
Additional context
No response
Part of the fix is this:
--- a/pkg/squashfs/squashfs.go
+++ b/pkg/squashfs/squashfs.go
@@ -135,7 +135,7 @@ func MakeSquashfs(tempdir string, rootfs string, eps *ExcludePaths, verity Verit
tmpSquashfs.Close()
os.Remove(tmpSquashfs.Name())
defer os.Remove(tmpSquashfs.Name())
- args := []string{rootfs, tmpSquashfs.Name()}
+ args := []string{rootfs, tmpSquashfs.Name(), "-keep-as-directory"}
compression := GzipCompression
if mksquashfsSupportsZstd() {
args = append(args, "-comp", "zstd")
but I think the problem is also happening with tar layers. (fails to build with '--layer-type=tar' also).
When I was poking around trying to fix this, I noticed that each 'import' gets creates its own layer in the created oci.
i think it might be better to have stacker start populating the same overlay that the 'run' would be handed before 'run' (if present) occurs.
Given this stcker.lyaml:
mybuild:
from:
type: docker
url: ubuntu:latest
import:
- my-file
- path: /etc/passwd
dest: /etc/passwd-host
- path: /static/some-binary-here
dest: /usr/bin/
run: |
ls -l /usr/bin/some-binary-here
ls -l /etc/passwd /etc/passwd-host
ls -l /stacker/my-file
When 'run' occurred:
- there would be read-only bind-mount on /stacker (current behavior, i think)
- / would be a single overlay as if imports[1] and imports[2] were not present.
- /usr/bin/some-binary-here would be present.
I know that @rchincha was interested in keeping the import logic as simple as possible, and for sure we have some corner cases to work out with the above. What I suggest to handle those edge cases (new file over existing directory, symlink following ...) is just to mimic what gnu 'tar' would do. And one path we could follow for implementation would be to have all the 'import' statements ultimately result in a tar archive, and then to just enter the filesystem view (including /overlay) and extract that tar archive .
overlay-dirs, possibly modified after import: [{/tmp/a/.stacker/imports-copy/mybuild/2106930494 "/files/"} {/tmp/a/.stacker/imports-copy/mybuild/918196220 "/files"}]
lxc rootfs overlay arg overlayfs:/tmp/a/roots/sha256_f4447d034d1e036e1d4c281f25e1a32aa7a252ac6216c50f59c9e4f6e70a4272/overlay:/tmp/a/roots/sha256_0d9b1e118cb2b6462cffe390ab4becc2313f5bd898c0caee8fb372526c98bbe1/overlay:/tmp/a/roots/mybuild/overlay
stacker version v1.0.0-rc1-c00511a
stacker subcommand: [/tmp/a/stacker --oci-dir /tmp/a/oci --roots-dir /tmp/a/roots --stacker-dir /tmp/a/.stacker --storage-type overlay --internal-userns --debug internal-go check-aa-profile lxc-container-default-cgns]
bind mounting /tmp/a/.stacker/imports/mybuild into container
Generating overlay_dirs layers
filesystem mybuild built successfully
quotes :\
rootfs/"/files/"
$ ls
subuid
quotes :\
rootfs/"/files/" $ ls subuid
The scourge of shell will never end.