diff --git a/CHANGELOG.md b/CHANGELOG.md index 63c2721077..9ae14c922e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,13 @@ the `%test` section of the build with a ephemeral tmpfs overlay, permitting tests that write to the container filesystem. +### Changed defaults / behaviours + + - LABELs from Docker/OCI images are now inherited. This fixes a longstanding + regression from Singularity 2.x. Note that you will now need to use + `--force` in a build to override a label that already exists in the source + Docker/OCI container. + ## v3.8.2 - [2021-08-31] ### Bug fixes diff --git a/e2e/docker/docker.go b/e2e/docker/docker.go index 7d1167e9de..c3a7833a1b 100644 --- a/e2e/docker/docker.go +++ b/e2e/docker/docker.go @@ -9,6 +9,7 @@ import ( "fmt" "os" "path/filepath" + "strings" "testing" "github.com/hpcng/singularity/e2e/internal/e2e" @@ -410,6 +411,45 @@ func (c ctx) testDockerCMDQuotes(t *testing.T) { ) } +func (c ctx) testDockerLabels(t *testing.T) { + imageDir, cleanup := e2e.MakeTempDir(t, c.env.TestDir, "labels-", "") + defer cleanup(t) + imagePath := filepath.Join(imageDir, "container") + + // Test container & set labels + // See: https://github.com/sylabs/singularity-test-containers/pull/1 + imgSrc := "docker://sylabsio/labels" + label1 := "LABEL1: 1" + label2 := "LABEL2: TWO" + + c.env.RunSingularity( + t, + e2e.AsSubtest("build"), + e2e.WithProfile(e2e.RootProfile), + e2e.WithCommand("build"), + e2e.WithArgs(imagePath, imgSrc), + e2e.ExpectExit(0), + ) + + verifyOutput := func(t *testing.T, r *e2e.SingularityCmdResult) { + output := string(r.Stdout) + for _, l := range []string{label1, label2} { + if !strings.Contains(output, l) { + t.Errorf("Did not find expected label %s in inspect output", l) + } + } + } + + c.env.RunSingularity( + t, + e2e.AsSubtest("inspect"), + e2e.WithProfile(e2e.UserProfile), + e2e.WithCommand("inspect"), + e2e.WithArgs([]string{"--labels", imagePath}...), + e2e.ExpectExit(0, verifyOutput), + ) +} + // E2ETests is the main func to trigger the test suite func E2ETests(env e2e.TestEnv) testhelper.Tests { c := ctx{ @@ -424,5 +464,6 @@ func E2ETests(env e2e.TestEnv) testhelper.Tests { "registry": c.testDockerRegistry, "whiteout symlink": c.testDockerWhiteoutSymlink, "cmd quotes": c.testDockerCMDQuotes, + "labels": c.testDockerLabels, } } diff --git a/internal/pkg/build/sources/conveyorPacker_oci.go b/internal/pkg/build/sources/conveyorPacker_oci.go index 690bc5fc15..4d06c4bea2 100644 --- a/internal/pkg/build/sources/conveyorPacker_oci.go +++ b/internal/pkg/build/sources/conveyorPacker_oci.go @@ -185,6 +185,11 @@ func (cp *OCIConveyorPacker) Pack(ctx context.Context) (*sytypes.Bundle, error) return nil, fmt.Errorf("while inserting oci config: %v", err) } + err = cp.insertOCILabels() + if err != nil { + return nil, fmt.Errorf("while inserting oci labels: %v", err) + } + return cp.b, nil } @@ -208,7 +213,6 @@ func (cp *OCIConveyorPacker) getConfig(ctx context.Context) (imgspecv1.ImageConf if err != nil { return imgspecv1.ImageConfig{}, err } - return imgSpec.Config, nil } @@ -444,6 +448,20 @@ func (cp *OCIConveyorPacker) insertEnv() (err error) { return nil } +func (cp *OCIConveyorPacker) insertOCILabels() (err error) { + labels := cp.imgConfig.Labels + var text []byte + + // make new map into json + text, err = json.MarshalIndent(labels, "", "\t") + if err != nil { + return err + } + + err = ioutil.WriteFile(filepath.Join(cp.b.RootfsPath, "/.singularity.d/labels.json"), []byte(text), 0644) + return err +} + // CleanUp removes any tmpfs owned by the conveyorPacker on the filesystem func (cp *OCIConveyorPacker) CleanUp() { cp.b.Remove()