Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
Signed-off-by: jason yang <jasonyangshadow@gmail.com>
  • Loading branch information
JasonYangShadow committed Jan 5, 2024
1 parent 3c5a579 commit f8ab155
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ For older changes see the [archived Singularity change log](https://github.com/a
via dependency update of mvdan.cc/sh.
- Fix regression introduced in v1.2.0 that led to an empty user's shell field
in the `/etc/passwd` file.
- Fix image build issue causing time discrepancy between host and container.

### Release change

Expand Down
59 changes: 59 additions & 0 deletions e2e/imgbuild/imgbuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -2232,6 +2232,64 @@ func (c imgBuildTests) testGocryptfsSIFBuild(t *testing.T) {
}
}

// Verify time discrepancy between host and container. This issue occurs when container's /etc/localtime is symlink and its
// value is different from host's /etc/localtime value.
// Current solution is: when building the image, will unlink the /etc/localtime inside rootfs if /etc/localtime is symlink
func (c imgBuildTests) issue1868(t *testing.T) {
tmpdir, cleanup := c.tempDir(t, "patch-localtime-test")
t.Cleanup(func() {
if !t.Failed() {
cleanup()
}
})

definition := `Bootstrap: docker
From: centos:7
%%post
ln -s /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
`

defFile := e2e.RawDefFile(t, tmpdir, strings.NewReader(definition))
imagePath := filepath.Join(tmpdir, "image-centos-7-broken")

// build issue image, simulating the issue case
c.env.RunApptainer(
t,
e2e.WithProfile(e2e.RootProfile),
e2e.WithCommand("build"),
e2e.WithArgs("-F", imagePath, defFile),
e2e.PostRun(func(t *testing.T) {
os.Remove(defFile)
}),
e2e.ExpectExit(0),
)

// this image will print wrong value `1577880000`, correct value should be `1577847600`
c.env.RunApptainer(
t,
e2e.WithProfile(e2e.UserProfile),
e2e.WithCommand("exec"),
e2e.WithEnv([]string{"TZ=Asia/Tokyo"}),
e2e.WithArgs(imagePath, "sh", "-c", `date --date "2020-01-01T12:00:00" +%s`),
e2e.ExpectExit(0,
e2e.ExpectOutput(e2e.ExactMatch, "1577880000"),
),
)

// correct one
c.env.RunApptainer(
t,
e2e.WithProfile(e2e.UserProfile),
e2e.WithCommand("exec"),
e2e.WithEnv([]string{"TZ=Asia/Tokyo"}),
e2e.WithArgs("--disable-cache", "docker://centos:7", "sh", "-c", `date --date "2020-01-01T12:00:00" +%s`),
e2e.ExpectExit(0,
e2e.ExpectOutput(e2e.ExactMatch, "1577847600"),
),
)
}

// E2ETests is the main func to trigger the test suite
func E2ETests(env e2e.TestEnv) testhelper.Tests {
c := imgBuildTests{
Expand Down Expand Up @@ -2273,5 +2331,6 @@ func E2ETests(env e2e.TestEnv) testhelper.Tests {
"build sif image using gocryptfs": c.testGocryptfsSIFBuild, // https://github.com/apptainer/apptainer/issues/484
"definition build with template support": c.buildDefinitionWithBuildArgs, // builds from definition with build args (build arg file) support
"issue 1812": c.issue1812, // https://github.com/sylabs/singularity/issues/1812
"issue 1868": c.issue1868, // https://github.com/apptainer/apptainer/issues/1868
}
}
3 changes: 3 additions & 0 deletions internal/pkg/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,9 @@ func (b *Build) Full(ctx context.Context) error {
defer os.Remove(sessionHosts)
}

// patch /etc/localtime if this file inside container is a symlink
patchLocaltime(stage.b)

if stage.b.Recipe.BuildData.Post.Script != "" {
if err := stage.runPostScript(sessionResolv, sessionHosts); err != nil {
return fmt.Errorf("while running engine: %v", err)
Expand Down
23 changes: 23 additions & 0 deletions internal/pkg/build/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,3 +131,26 @@ func currentEnvNoApptainer(permitted []string) []string {

return envs
}

func patchLocaltime(b *types.Bundle) {
const (
localtime = "/etc/localtime"
)
conFile := filepath.Join(b.RootfsPath, localtime)

// could not read container's /etc/localtime file, skip
if err := unix.Access(conFile, unix.R_OK); err != nil {
return
}

if st, err := os.Lstat(conFile); err == nil {
// container's /etc/localtime is a symlink file
if st.Mode()&os.ModeSymlink > 0 {
// unlink it
sylog.Verbosef("%s inside container is symlink, will unlink it", conFile)
if err := unix.Unlink(conFile); err != nil {
sylog.Warningf("while unlinking %s: %s", conFile, err)
}
}
}
}

0 comments on commit f8ab155

Please sign in to comment.