diff --git a/modules/mesh-build-image/cmd/mesh-build-image/module.go b/modules/mesh-build-image/cmd/mesh-build-image/module.go index 9af9cfbc..c6d869c6 100644 --- a/modules/mesh-build-image/cmd/mesh-build-image/module.go +++ b/modules/mesh-build-image/cmd/mesh-build-image/module.go @@ -4,8 +4,6 @@ import ( "context" "fmt" "net/http" - "os" - "path/filepath" "time" "git.novox.be/novox/mesh-sdk/go/buildstep" @@ -60,6 +58,11 @@ type Look struct { // missing is a *buildstep.Refusal naming it, so a step ends refused and the health says the same. func (m *Module) look(ctx context.Context) (Look, error) { l := Look{Account: m.Account} + // The runtime directory comes first: buildah refuses before anything else when its XDG_RUNTIME_DIR is not there + // (issue 1884), so a look that made it only after `buildah --version` never made it at all. + if err := m.ensureRuntimeDir(); err != nil { + return l, &buildstep.Refusal{Text: err.Error()} + } var err error if l.Buildah, err = m.buildahVersion(ctx); err != nil { return l, &buildstep.Refusal{Text: err.Error()} @@ -67,11 +70,6 @@ func (m *Module) look(ctx context.Context) (Look, error) { if l.UIDs, l.GIDs, err = m.ranges(); err != nil { return l, &buildstep.Refusal{Text: err.Error(), Have: l.Buildah} } - for _, d := range []string{m.Store, filepath.Join(m.Store, "xdg")} { - if err := os.MkdirAll(d, 0o700); err != nil { - return l, err - } - } if err := m.userNamespace(ctx); err != nil { return l, &buildstep.Refusal{Text: err.Error(), Have: l.Buildah} } diff --git a/modules/mesh-build-image/cmd/mesh-build-image/probe.go b/modules/mesh-build-image/cmd/mesh-build-image/probe.go index 3b2a587d..e96c2212 100644 --- a/modules/mesh-build-image/cmd/mesh-build-image/probe.go +++ b/modules/mesh-build-image/cmd/mesh-build-image/probe.go @@ -111,6 +111,25 @@ func (m *Module) storeFlags() []string { // env is what buildah is given beyond the base environment: a runtime directory of its own inside the store, so // nothing is read from the account's runtime directory, and no registry credential file anywhere (the module has none // and REGISTRY_AUTH_FILE is never set). +// +// Every call makes the runtime directory first if it is not there (issue 1884): a directory removed after the last look +// is made again before buildah runs. A failure to make it is not lost: buildah then names the directory in its own +// error, and the next look refuses with it. func (m *Module) env() []string { - return []string{"XDG_RUNTIME_DIR=" + filepath.Join(m.Store, "xdg")} + _ = m.ensureRuntimeDir() + return []string{"XDG_RUNTIME_DIR=" + m.runtimeDir()} +} + +// runtimeDir is buildah's runtime directory, inside the store. +func (m *Module) runtimeDir() string { return filepath.Join(m.Store, "xdg") } + +// ensureRuntimeDir makes the store and the runtime directory inside it, 0700 and under the module's own account (the +// process runs as it), when they are not there; it changes nothing that is. +func (m *Module) ensureRuntimeDir() error { + for _, d := range []string{m.Store, m.runtimeDir()} { + if err := os.MkdirAll(d, 0o700); err != nil { + return fmt.Errorf("buildah's runtime directory %s cannot be made: %w", m.runtimeDir(), err) + } + } + return nil } diff --git a/modules/mesh-build-image/cmd/mesh-build-image/runtimedir_test.go b/modules/mesh-build-image/cmd/mesh-build-image/runtimedir_test.go new file mode 100644 index 00000000..d2445774 --- /dev/null +++ b/modules/mesh-build-image/cmd/mesh-build-image/runtimedir_test.go @@ -0,0 +1,83 @@ +package main + +import ( + "context" + "os" + "path/filepath" + "strings" + "testing" + + "git.novox.be/novox/mesh-sdk/go/forgekey" + "git.novox.be/novox/mesh-sdk/go/health" +) + +// buildahLike refuses as buildah does when the XDG_RUNTIME_DIR it is given is not there (seen on ace, issue 1884): +// "lstat