diff --git a/build.yaml b/build.yaml index ad82e793b..dc2d9f8cc 100644 --- a/build.yaml +++ b/build.yaml @@ -3,7 +3,7 @@ build-env: from: type: docker url: ${{STACKER_BUILD_BASE_IMAGE}} - import: + imports: - https://github.com/json-c/json-c/archive/refs/tags/json-c-0.16-20220414.tar.gz - https://gitlab.com/cryptsetup/cryptsetup/-/archive/v2.6.0/cryptsetup-v2.6.0.tar.gz - https://github.com/lvmteam/lvm2/archive/refs/tags/v2_03_18.tar.gz diff --git a/cmd/stacker/bom.go b/cmd/stacker/bom.go index a138d1ab7..be8457d22 100644 --- a/cmd/stacker/bom.go +++ b/cmd/stacker/bom.go @@ -10,6 +10,7 @@ import ( "stackerbuild.io/stacker-bom/pkg/bom" "stackerbuild.io/stacker-bom/pkg/distro" "stackerbuild.io/stacker-bom/pkg/fs" + "stackerbuild.io/stacker/pkg/types" ) var bomCmd = cli.Command{ @@ -39,7 +40,7 @@ func doBomDiscover(ctx *cli.Context) error { author := "stacker-internal" org := "stacker-internal" - if err := fs.Discover(author, org, "/stacker/artifacts/installed-packages.json"); err != nil { + if err := fs.Discover(author, org, types.InternalStackerDir+"/artifacts/installed-packages.json"); err != nil { return nil } @@ -57,7 +58,8 @@ func doBomGenerate(ctx *cli.Context) error { org := "stacker-internal" lic := "unknown" - if err := distro.ParsePackage(input, author, org, lic, fmt.Sprintf("/stacker/artifacts/%s.json", filepath.Base(input))); err != nil { + if err := distro.ParsePackage(input, author, org, lic, fmt.Sprintf("%s/artifacts/%s.json", + types.InternalStackerDir, filepath.Base(input))); err != nil { return nil } @@ -98,16 +100,17 @@ func doBomVerify(ctx *cli.Context) error { org := ctx.Args().Get(3) // first merge all individual sbom artifacts that may have been generated - if err := bom.MergeDocuments("/stacker/artifacts", name, author, org, dest); err != nil { + iDir := types.InternalStackerDir + if err := bom.MergeDocuments(iDir+"/artifacts", name, author, org, dest); err != nil { return err } // check against inventory if err := fs.GenerateInventory("/", - []string{"/proc", "/sys", "/dev", "/etc/resolv.conf", "/stacker"}, - "/stacker/artifacts/inventory.json"); err != nil { + []string{"/proc", "/sys", "/dev", "/etc/resolv.conf", iDir}, + iDir+"/artifacts/inventory.json"); err != nil { return err } - return fs.Verify(dest, "/stacker/artifacts/inventory.json", "") + return fs.Verify(dest, iDir+"/artifacts/inventory.json", "") } diff --git a/cmd/stacker/chroot.go b/cmd/stacker/chroot.go index 497d76a62..3703a7696 100644 --- a/cmd/stacker/chroot.go +++ b/cmd/stacker/chroot.go @@ -98,11 +98,11 @@ func doChroot(ctx *cli.Context) error { } defer c.Close() - err = stacker.SetupBuildContainerConfig(config, s, c, name) + err = stacker.SetupBuildContainerConfig(config, s, c, types.InternalStackerDir, name) if err != nil { return err } - err = stacker.SetupLayerConfig(config, c, layer, name) + err = stacker.SetupLayerConfig(config, c, layer, types.InternalStackerDir, name) if err != nil { return err } diff --git a/doc/stacker_yaml.md b/doc/stacker_yaml.md index c4d72fb99..eed9b9c46 100644 --- a/doc/stacker_yaml.md +++ b/doc/stacker_yaml.md @@ -64,10 +64,10 @@ layer on a previously specified layer in the stacker file. of `import` to generate minimal images, e.g. for statically built binaries. -### `import` +### `imports` -The `import` directive describes what files should be made available in -`/stacker` during the `run` phase. There are three forms of importing supported +The `imports` directive describes what files should be made available in +`/stacker/imports` during the `run` phase. There are three forms of importing supported today: /path/to/file @@ -89,10 +89,10 @@ Will grab /path/to/file from the previously built layer `$name`. #### `import hash` -The `import` directive also supports specifying the hash(sha256sum) of import source, -for all the three forms presented above, for example: +Each entry in the `imports' directive also supports specifying the hash(sha256sum) of +import source, for all the three forms presented above, for example: ``` -import: +imports: - path: config.json hash: f55af805b012017bc.... - path: http://example.com/foo.tar.gz @@ -115,7 +115,7 @@ If `--require-hash` is not passed, this import mode can be combined with uncheck and only files which have the hash specified will be checked. ``` -import: +imports: - path: "config.json hash: "BEEFcafeaaaaAAAA...." - /path/to/file @@ -127,11 +127,17 @@ The `import` directive also supports specifying the destination path (specified by `dest`) in the resulting container image, where the source file (specified by `path`) will be copyied to, for example: ``` -import: +imports: - path: config.json dest: / ``` + +### (Deprecated) `import` +The deprecated `import` directive works like `imports` except that +the entries in the `import` array will be placed into `/stacker/` rather +than `/stacker/imports`. + ### `overlay_dirs` This directive works only with OverlayFS backend storage. diff --git a/doc/tutorial.md b/doc/tutorial.md index ad531adbb..3d1d0b71e 100644 --- a/doc/tutorial.md +++ b/doc/tutorial.md @@ -98,7 +98,7 @@ output will look something like: There are two new stacker file directives here: - import: + imports: - config.json - install.sh @@ -115,8 +115,8 @@ And then there is: run: | mkdir -p /etc/myapp - cp /stacker/config.json /etc/myapp/ - /stacker/install.sh + cp /stacker/imports/config.json /etc/myapp/ + /stacker/imports/install.sh Which is the set of commands to run in order to install and configure the image. @@ -152,8 +152,8 @@ emitted in the final OCI image. For example: from: type: docker url: docker://centos:latest - import: stacker://build/umoci.static - run: cp /stacker/umoci.static /usr/bin/umoci + imports: stacker://build/umoci.static + run: cp /stacker/imports/umoci.static /usr/bin/umoci Will build a static version of umoci in an ubuntu container, but the final image will only contain an `umoci` tag with a statically linked version of @@ -165,7 +165,7 @@ indicates that the container shouldn't be emitted in the final image, because we're going to import something from it and don't need the rest of it. The line: - import: stacker://build/umoci.static + imports: stacker://build/umoci.static is what actually does this import, and it says "from a previously built stacker image called 'build', import /umoci.static". diff --git a/pkg/stacker/bom.go b/pkg/stacker/bom.go index 0cfe3eaba..dc2b243c4 100644 --- a/pkg/stacker/bom.go +++ b/pkg/stacker/bom.go @@ -5,6 +5,7 @@ import ( "io" "os" "path" + "path/filepath" "stackerbuild.io/stacker/pkg/container" "stackerbuild.io/stacker/pkg/log" @@ -27,24 +28,25 @@ func BuildLayerArtifacts(sc types.StackerConfig, storage types.Storage, l types. } defer c.Close() - err = SetupBuildContainerConfig(sc, storage, c, tag) + inDir := types.InternalStackerDir + err = SetupBuildContainerConfig(sc, storage, c, inDir, tag) if err != nil { log.Errorf("build container %v", err) return err } - err = SetupLayerConfig(sc, c, l, tag) + err = SetupLayerConfig(sc, c, l, inDir, tag) if err != nil { return err } - cmd := []string{insideStaticStacker} + cmd := []string{filepath.Join(inDir, types.BinStacker)} if sc.Debug { cmd = append(cmd, "--debug") } - cmd = append(cmd, "bom", "build", "/stacker/artifacts", + cmd = append(cmd, "bom", "build", filepath.Join(inDir, "artifacts"), l.Annotations[types.AuthorAnnotation], l.Annotations[types.OrgAnnotation], l.Annotations[types.LicenseAnnotation], @@ -71,25 +73,26 @@ func VerifyLayerArtifacts(sc types.StackerConfig, storage types.Storage, l types } defer c.Close() - err = SetupBuildContainerConfig(sc, storage, c, tag) + inDir := types.InternalStackerDir + err = SetupBuildContainerConfig(sc, storage, c, inDir, tag) if err != nil { log.Errorf("build container %v", err) return err } - err = SetupLayerConfig(sc, c, l, tag) + err = SetupLayerConfig(sc, c, l, inDir, tag) if err != nil { return err } - cmd := []string{insideStaticStacker} + cmd := []string{filepath.Join(inDir, types.BinStacker)} if sc.Debug { cmd = append(cmd, "--debug") } cmd = append(cmd, "bom", "verify", - fmt.Sprintf("/stacker/artifacts/%s.json", tag), + fmt.Sprintf(types.InternalStackerDir+"/artifacts/%s.json", tag), tag, l.Annotations[types.AuthorAnnotation], l.Annotations[types.OrgAnnotation]) err = c.Execute(cmd, os.Stdin) diff --git a/pkg/stacker/build.go b/pkg/stacker/build.go index 88b11203b..75764a4bc 100644 --- a/pkg/stacker/build.go +++ b/pkg/stacker/build.go @@ -7,6 +7,7 @@ import ( "os/exec" "os/user" "path" + "path/filepath" "strings" "time" @@ -23,8 +24,7 @@ import ( ) const ( - DefaultShell = "/bin/sh" - insideStaticStacker = "/stacker/tools/static-stacker" + DefaultShell = "/bin/sh" ) type BuildArgs struct { @@ -115,6 +115,11 @@ func (b *Builder) updateOCIConfigForOutput(sf *types.Stackerfile, s types.Storag imageConfig.Labels = map[string]string{} } + inDir := types.InternalStackerDir + if l.WasLegacyImport() { + inDir = types.LegacyInternalStackerDir + } + if len(l.GenerateLabels) > 0 { writable, cleanup, err := s.TemporaryWritableSnapshot(name) if err != nil { @@ -134,24 +139,26 @@ func (b *Builder) updateOCIConfigForOutput(sf *types.Stackerfile, s types.Storag } defer c.Close() - err = SetupBuildContainerConfig(opts.Config, s, c, writable) + err = SetupBuildContainerConfig(opts.Config, s, c, inDir, writable) if err != nil { return err } - err = c.BindMount(dir, "/stacker/oci-labels", "") + // /stacker/oci-labels + labelInDir := filepath.Join(inDir, "oci-labels") + const script = ".stacker-run.sh" + err = c.BindMount(dir, labelInDir, "") if err != nil { return err } - rootfs := path.Join(opts.Config.RootFSDir, writable, "rootfs") - runPath := path.Join(dir, ".stacker-run.sh") - err = generateShellForRunning(rootfs, l.GenerateLabels, runPath) + rootfs := filepath.Join(opts.Config.RootFSDir, writable, "rootfs") + err = generateShellForRunning(rootfs, l.GenerateLabels, filepath.Join(dir, script)) if err != nil { return err } - err = c.Execute([]string{"/stacker/oci-labels/.stacker-run.sh"}, nil) + err = c.Execute([]string{filepath.Join(labelInDir, script)}, nil) if err != nil { return err } @@ -166,7 +173,7 @@ func (b *Builder) updateOCIConfigForOutput(sf *types.Stackerfile, s types.Storag continue } - content, err := os.ReadFile(path.Join(dir, ent.Name())) + content, err := os.ReadFile(filepath.Join(dir, ent.Name())) if err != nil { return errors.Wrapf(err, "couldn't read label %s", ent.Name()) } @@ -362,6 +369,10 @@ func (b *Builder) build(s types.Storage, file string) error { } log.Infof("preparing image %s...", name) + inDir := types.InternalStackerDir + if l.WasLegacyImport() { + inDir = types.LegacyInternalStackerDir + } // We need to run the imports first since we now compare // against imports for caching layers. Since we don't do @@ -451,18 +462,18 @@ func (b *Builder) build(s types.Storage, file string) error { } defer c.Close() - err = SetupBuildContainerConfig(opts.Config, s, c, name) + err = SetupBuildContainerConfig(opts.Config, s, c, inDir, name) if err != nil { return err } - err = SetupLayerConfig(opts.Config, c, l, name) + err = SetupLayerConfig(opts.Config, c, l, inDir, name) if err != nil { return err } if opts.SetupOnly { - err = c.SaveConfigFile(path.Join(opts.Config.RootFSDir, name, "lxc.conf")) + err = c.SaveConfigFile(filepath.Join(opts.Config.RootFSDir, name, "lxc.conf")) if err != nil { return errors.Wrapf(err, "error saving config file for %s", name) } @@ -472,15 +483,15 @@ func (b *Builder) build(s types.Storage, file string) error { } if len(l.Run) != 0 { - rootfs := path.Join(opts.Config.RootFSDir, name, "rootfs") - shellScript := path.Join(opts.Config.StackerDir, "imports", name, ".stacker-run.sh") + rootfs := filepath.Join(opts.Config.RootFSDir, name, "rootfs") + shellScript := filepath.Join(opts.Config.StackerDir, "imports", name, ".stacker-run.sh") err = generateShellForRunning(rootfs, l.Run, shellScript) if err != nil { return err } // These should all be non-interactive; let's ensure that. - err = c.Execute([]string{"/stacker/imports/.stacker-run.sh"}, nil) + err = c.Execute([]string{filepath.Join(inDir, "imports", ".stacker-run.sh")}, nil) if err != nil { if opts.OnRunFailure != "" { err2 := c.Execute([]string{opts.OnRunFailure}, os.Stdin) @@ -655,7 +666,7 @@ func runInternalGoSubcommand(config types.StackerConfig, args []string) error { return errors.WithStack(c.Run()) } -func SetupBuildContainerConfig(config types.StackerConfig, storage types.Storage, c *container.Container, name string) error { +func SetupBuildContainerConfig(config types.StackerConfig, storage types.Storage, c *container.Container, inDir string, name string) error { rootfsPivot := path.Join(config.StackerDir, "rootfsPivot") if err := os.MkdirAll(rootfsPivot, 0755); err != nil { return err @@ -696,7 +707,7 @@ func SetupBuildContainerConfig(config types.StackerConfig, storage types.Storage } // make stacker binary available inside container - if err := c.BindMount(binary, insideStaticStacker, ""); err != nil { + if err := c.BindMount(binary, filepath.Join(inDir, "bin/stacker"), ""); err != nil { return err } @@ -752,7 +763,7 @@ func SetupBuildContainerConfig(config types.StackerConfig, storage types.Storage return nil } -func SetupLayerConfig(config types.StackerConfig, c *container.Container, l types.Layer, name string) error { +func SetupLayerConfig(config types.StackerConfig, c *container.Container, l types.Layer, inDir, name string) error { env, err := l.BuildEnvironment(name) if err != nil { return err @@ -760,11 +771,19 @@ func SetupLayerConfig(config types.StackerConfig, c *container.Container, l type importsDir := path.Join(config.StackerDir, "imports", name) if _, err := os.Stat(importsDir); err == nil { - log.Debugf("bind mounting %s into container", importsDir) - err = c.BindMount(importsDir, "/stacker/imports", "ro") + d := filepath.Join(inDir, "imports") + log.Debugf("bind mounting %s into container at %s", importsDir, d) + err = c.BindMount(importsDir, d, "ro") if err != nil { return err } + // legacy expect imports in /stacker + if inDir == types.LegacyInternalStackerDir { + err = c.BindMount(importsDir, types.InternalStackerDir, "ro") + if err != nil { + return err + } + } } else { log.Debugf("not bind mounting %s into container", importsDir) } @@ -773,8 +792,9 @@ func SetupLayerConfig(config types.StackerConfig, c *container.Container, l type if l.Bom != nil { artifactsDir := path.Join(config.StackerDir, "artifacts", name) if _, err := os.Stat(artifactsDir); err == nil { - log.Debugf("bind mounting %s into container", artifactsDir) - err = c.BindMount(artifactsDir, "/stacker/artifacts", "rw") + d := filepath.Join(inDir, "artifacts") + log.Debugf("bind mounting %s dir into container at %s", artifactsDir, d) + err = c.BindMount(artifactsDir, d, "rw") if err != nil { return err } diff --git a/pkg/stacker/cache.go b/pkg/stacker/cache.go index f407483eb..e7030cdea 100644 --- a/pkg/stacker/cache.go +++ b/pkg/stacker/cache.go @@ -22,7 +22,7 @@ import ( "stackerbuild.io/stacker/pkg/types" ) -const currentCacheVersion = 12 +const currentCacheVersion = 13 type ImportType int diff --git a/pkg/stacker/cache_test.go b/pkg/stacker/cache_test.go index 477550c73..55bb15eb8 100644 --- a/pkg/stacker/cache_test.go +++ b/pkg/stacker/cache_test.go @@ -125,5 +125,5 @@ func TestCacheEntryChanged(t *testing.T) { // This test works because the type information is included in the // hashstructure hash above, so using a zero valued CacheEntry is // enough to capture changes in types. - assert.Equal(uint64(0x5b52c6b8e076304c), h) + assert.Equal(uint64(0x4ef432528243e356), h) } diff --git a/pkg/stacker/grab.go b/pkg/stacker/grab.go index fdb58c92a..9efca86dd 100644 --- a/pkg/stacker/grab.go +++ b/pkg/stacker/grab.go @@ -5,6 +5,7 @@ import ( "io/fs" "os" "path" + "path/filepath" "stackerbuild.io/stacker/pkg/container" "stackerbuild.io/stacker/pkg/types" @@ -19,30 +20,31 @@ func Grab(sc types.StackerConfig, storage types.Storage, name string, source str } defer c.Close() - err = c.BindMount(targetDir, "/stacker", "") + err = c.BindMount(targetDir, types.InternalStackerDir, "") if err != nil { return err } defer os.Remove(path.Join(sc.RootFSDir, name, "rootfs", "stacker")) - err = SetupBuildContainerConfig(sc, storage, c, name) + err = SetupBuildContainerConfig(sc, storage, c, types.InternalStackerDir, name) if err != nil { return err } - bcmd := []string{insideStaticStacker, "internal-go"} + bcmd := []string{filepath.Join(types.InternalStackerDir, types.BinStacker), "internal-go"} + iDestName := filepath.Join(types.InternalStackerDir, path.Base(source)) if idest == "" || source[len(source)-1:] != "/" { - err = c.Execute(append(bcmd, "cp", source, "/stacker/"+path.Base(source)), nil) + err = c.Execute(append(bcmd, "cp", source, iDestName), nil) } else { - err = c.Execute(append(bcmd, "cp", source, "/stacker/"), nil) + err = c.Execute(append(bcmd, "cp", source, types.InternalStackerDir+"/"), nil) } if err != nil { return err } if mode != nil { - err = c.Execute(append(bcmd, "chmod", fmt.Sprintf("%o", *mode), "/stacker/"+path.Base(source)), nil) + err = c.Execute(append(bcmd, "chmod", fmt.Sprintf("%o", *mode), iDestName), nil) if err != nil { return err } @@ -54,7 +56,7 @@ func Grab(sc types.StackerConfig, storage types.Storage, name string, source str owns += fmt.Sprintf(":%d", gid) } - err = c.Execute(append(bcmd, "chown", owns, "/stacker/"+path.Base(source)), nil) + err = c.Execute(append(bcmd, "chown", owns, iDestName), nil) if err != nil { return err } diff --git a/pkg/types/layer.go b/pkg/types/layer.go index 2390384fa..d45b4c05c 100644 --- a/pkg/types/layer.go +++ b/pkg/types/layer.go @@ -2,6 +2,7 @@ package types import ( "encoding/json" + "fmt" "io/fs" "os" "path/filepath" @@ -236,27 +237,29 @@ func (bs *Bind) UnmarshalYAML(unmarshal func(interface{}) error) error { } type Layer struct { - From ImageSource `yaml:"from" json:"from"` - Imports Imports `yaml:"import" json:"import,omitempty"` - OverlayDirs OverlayDirs `yaml:"overlay_dirs" json:"overlay_dirs,omitempty"` - Run StringList `yaml:"run" json:"run,omitempty"` - Cmd Command `yaml:"cmd" json:"cmd,omitempty"` - Entrypoint Command `yaml:"entrypoint" json:"entrypoint,omitempty"` - FullCommand Command `yaml:"full_command" json:"full_command,omitempty"` - BuildEnvPt []string `yaml:"build_env_passthrough" json:"build_env_passthrough,omitempty"` - BuildEnv map[string]string `yaml:"build_env" json:"build_env,omitempty"` - Environment map[string]string `yaml:"environment" json:"environment,omitempty"` - Volumes []string `yaml:"volumes" json:"volumes,omitempty"` - Labels map[string]string `yaml:"labels" json:"labels,omitempty"` - GenerateLabels StringList `yaml:"generate_labels" json:"generate_labels,omitempty"` - WorkingDir string `yaml:"working_dir" json:"working_dir,omitempty"` - BuildOnly bool `yaml:"build_only" json:"build_only,omitempty"` - Binds Binds `yaml:"binds" json:"binds,omitempty"` - RuntimeUser string `yaml:"runtime_user" json:"runtime_user,omitempty"` - Annotations map[string]string `yaml:"annotations" json:"annotations,omitempty"` - OS *string `yaml:"os" json:"os,omitempty"` - Arch *string `yaml:"arch" json:"arch,omitempty"` - Bom *Bom `yaml:"bom" json:"bom,omitempty"` + From ImageSource `yaml:"from" json:"from"` + Imports Imports `yaml:"imports" json:"imports,omitempty"` + LegacyImport Imports `yaml:"import" json:"import,omitempty"` + OverlayDirs OverlayDirs `yaml:"overlay_dirs" json:"overlay_dirs,omitempty"` + Run StringList `yaml:"run" json:"run,omitempty"` + Cmd Command `yaml:"cmd" json:"cmd,omitempty"` + Entrypoint Command `yaml:"entrypoint" json:"entrypoint,omitempty"` + FullCommand Command `yaml:"full_command" json:"full_command,omitempty"` + BuildEnvPt []string `yaml:"build_env_passthrough" json:"build_env_passthrough,omitempty"` + BuildEnv map[string]string `yaml:"build_env" json:"build_env,omitempty"` + Environment map[string]string `yaml:"environment" json:"environment,omitempty"` + Volumes []string `yaml:"volumes" json:"volumes,omitempty"` + Labels map[string]string `yaml:"labels" json:"labels,omitempty"` + GenerateLabels StringList `yaml:"generate_labels" json:"generate_labels,omitempty"` + WorkingDir string `yaml:"working_dir" json:"working_dir,omitempty"` + BuildOnly bool `yaml:"build_only" json:"build_only,omitempty"` + Binds Binds `yaml:"binds" json:"binds,omitempty"` + RuntimeUser string `yaml:"runtime_user" json:"runtime_user,omitempty"` + Annotations map[string]string `yaml:"annotations" json:"annotations,omitempty"` + OS *string `yaml:"os" json:"os,omitempty"` + Arch *string `yaml:"arch" json:"arch,omitempty"` + Bom *Bom `yaml:"bom" json:"bom,omitempty"` + wasLegacyImport bool } func parseLayers(referenceDirectory string, lms yaml.MapSlice, requireHash bool) (map[string]Layer, error) { @@ -355,6 +358,15 @@ func parseLayers(referenceDirectory string, lms yaml.MapSlice, requireHash bool) layer.Arch = &arch } + if len(layer.LegacyImport) != 0 && len(layer.Imports) != 0 { + return nil, errors.New(fmt.Sprintf("layer '%s' cannot have both 'import' and 'imports'", name)) + } + if len(layer.LegacyImport) != 0 { + layer.Imports = layer.LegacyImport + layer.LegacyImport = nil + layer.wasLegacyImport = true + } + ret[name], err = layer.absolutify(referenceDirectory) if err != nil { return nil, err @@ -425,6 +437,11 @@ func (l Layer) absolutify(referenceDirectory string) (Layer, error) { return ret, nil } +// WasLegacyImport - return true if this layer used legacy 'import' directive. +func (l Layer) WasLegacyImport() bool { + return l.wasLegacyImport +} + func requireImportHash(imports Imports) error { for _, imp := range imports { url, err := NewDockerishUrl(imp.Path) diff --git a/pkg/types/stackerfile.go b/pkg/types/stackerfile.go index 7f703fe27..b2ad8aeae 100644 --- a/pkg/types/stackerfile.go +++ b/pkg/types/stackerfile.go @@ -15,6 +15,12 @@ import ( "stackerbuild.io/stacker/pkg/log" ) +const ( + InternalStackerDir = "/stacker" + LegacyInternalStackerDir = "/.stacker" + BinStacker = "bin/stacker" +) + type BuildConfig struct { Prerequisites []string `yaml:"prerequisites"` } @@ -211,6 +217,14 @@ func NewStackerfile(stackerfile string, validateHash bool, substitutions []strin return nil, err } + for _, name := range sf.FileOrder { + layer := sf.internal[name] + if layer.WasLegacyImport() { + log.Warnf("Deprecated 'import' directive used in layer '%s' of file '%s'. "+ + "Change from 'import' to 'imports', and '/stacker/' to '/stacker/imports/'", name, stackerfile) + } + } + return &sf, err } diff --git a/test/basic.bats b/test/basic.bats index 70414df9d..63258c7d3 100644 --- a/test/basic.bats +++ b/test/basic.bats @@ -14,7 +14,7 @@ busybox: from: type: oci url: $BUSYBOX_OCI - import: import + imports: import EOF echo 1 > import stacker build @@ -32,7 +32,7 @@ busybox: from: type: tar url: .stacker/layer-bases/busybox.tar - import: + imports: - ./stacker.yaml - https://www.cisco.com/favicon.ico - ./executable @@ -199,6 +199,7 @@ busybox: type: tar url: .stacker/layer-bases/busybox.tar import: + imports: - ./stacker.yaml - https://www.cisco.com/favicon.ico - ./executable diff --git a/test/broken-link.bats b/test/broken-link.bats index a43391b7c..c26d400f7 100644 --- a/test/broken-link.bats +++ b/test/broken-link.bats @@ -15,7 +15,7 @@ broken_link: from: type: oci url: $BUSYBOX_OCI - import: + imports: - dir run: cp -a /stacker/imports/dir/testln /testln EOF diff --git a/test/build-only.bats b/test/build-only.bats index 3d251d048..5e2199313 100644 --- a/test/build-only.bats +++ b/test/build-only.bats @@ -83,7 +83,7 @@ busybox: from: type: oci url: $BUSYBOX_OCI - import: https://www.cisco.com/favicon.ico + imports: https://www.cisco.com/favicon.ico run: | cp /stacker/imports/favicon.ico /favicon.ico build_only: true @@ -91,7 +91,7 @@ layer1: from: type: built tag: busybox - import: + imports: - stacker://busybox/favicon.ico run: - cp /stacker/imports/favicon.ico /favicon2.ico @@ -108,7 +108,7 @@ busybox: from: type: oci url: $BUSYBOX_OCI - import: https://www.cisco.com/favicon.ico + imports: https://www.cisco.com/favicon.ico run: | cp /stacker/imports/favicon.ico /favicon.ico build_only: true @@ -116,7 +116,7 @@ layer1: from: type: built tag: busybox - import: + imports: - stacker://busybox/favicon.ico run: - cp /stacker/imports/favicon.ico /favicon2.ico diff --git a/test/caching.bats b/test/caching.bats index 8c5bd09f0..55e000067 100644 --- a/test/caching.bats +++ b/test/caching.bats @@ -52,7 +52,7 @@ base: from: type: built tag: build-base - import: + imports: - foo run: | cp /stacker/imports/foo /foo @@ -71,7 +71,7 @@ import-cache: from: type: oci url: $BUSYBOX_OCI - import: + imports: - link/foo run: cp /stacker/imports/foo/zomg /zomg EOF @@ -95,7 +95,7 @@ a: from: type: oci url: $BUSYBOX_OCI - import: + imports: - foo run: | [ -f /stacker/imports/foo/bar ] @@ -111,7 +111,7 @@ a: from: type: oci url: $BUSYBOX_OCI - import: + imports: - foo run: | [ ! -f /stacker/imports/foo/bar ] @@ -126,7 +126,7 @@ bind-test: from: type: oci url: ${{BUSYBOX_OCI}} - import: + imports: - tree1/foo/zomg binds: - ${{bind_path}} -> /root/tree2/foo @@ -169,7 +169,7 @@ mode-test: from: type: oci url: $BUSYBOX_OCI - import: + imports: - executable run: cp /stacker/imports/executable /executable EOF @@ -185,6 +185,7 @@ EOF } @test "can read previous version's cache" { + skip "old version does not support imports (plural) directive" # some additional testing that the cache can be read by older versions of # stacker (cache_test.go has the full test for the type, this just checks # the mechanics of filepaths and such) @@ -204,7 +205,7 @@ test: from: type: oci url: $BUSYBOX_OCI - import: + imports: - foo run: cp /stacker/imports/foo /foo EOF diff --git a/test/cp-not-required.bats b/test/cp-not-required.bats index 137f9689b..ad935dc57 100644 --- a/test/cp-not-required.bats +++ b/test/cp-not-required.bats @@ -27,7 +27,7 @@ contents2: from: type: built tag: build - import: + imports: - stacker://contents/first - stacker://contents/second run: | diff --git a/test/dependency-order.bats b/test/dependency-order.bats index 202f24ccc..b38df731b 100644 --- a/test/dependency-order.bats +++ b/test/dependency-order.bats @@ -27,7 +27,7 @@ test: from: type: oci tag: $BUSYBOX_OCI - import: + imports: - stacker://foo/bar - stacker://baz/foo EOF @@ -74,7 +74,7 @@ installer-iso-build: type: built tag: minbase1 build_only: true - import: + imports: - stacker://installer-initrd/output/installer-initrd-base.cpio - stacker://installer-initrd-modules/output/installer-initrd-modules.cpio run: | diff --git a/test/docker-base.bats b/test/docker-base.bats index b9191ce08..9d2ba0ee8 100644 --- a/test/docker-base.bats +++ b/test/docker-base.bats @@ -14,7 +14,7 @@ busybox: from: type: docker url: oci:${BUSYBOX_OCI} - import: + imports: - https://www.cisco.com/favicon.ico run: | cp /stacker/imports/favicon.ico /favicon.ico diff --git a/test/import-http.bats b/test/import-http.bats index f2bbeb7d1..09de7f650 100644 --- a/test/import-http.bats +++ b/test/import-http.bats @@ -23,7 +23,7 @@ img: from: type: oci url: $(pwd)/oci:busybox_base - import: + imports: - http://network-test.debian.org/nm run: | cp /stacker/imports/nm /root/nm @@ -79,7 +79,7 @@ busybox_base: from: type: oci url: $BUSYBOX_OCI - import: + imports: - path: https://www.cisco.com/favicon.ico dest: /dest/icon run: | diff --git a/test/import.bats b/test/import.bats index 629e1784e..132a8d9f0 100644 --- a/test/import.bats +++ b/test/import.bats @@ -15,7 +15,7 @@ thing: from: type: oci url: $BUSYBOX_OCI - import: + imports: - https://bing.com/favicon.ico EOF stacker build @@ -35,7 +35,7 @@ busybox: from: type: oci url: $BUSYBOX_OCI - import: + imports: - recursive run: | [ -d /stacker/imports/recursive ] @@ -53,7 +53,7 @@ first: from: type: oci url: $BUSYBOX_OCI - import: + imports: - recursive run: | [ -d /stacker/imports/recursive ] @@ -63,7 +63,7 @@ second: from: type: oci url: $BUSYBOX_OCI - import: + imports: - stacker://first/recursive run: | [ -d /stacker/imports/recursive ] @@ -82,7 +82,7 @@ first: from: type: oci url: $BUSYBOX_OCI - import: + imports: - path: test_file hash: $test_file_sha - test_file2 @@ -96,7 +96,7 @@ second: from: type: built tag: first - import: + imports: - path: stacker://first/test_file hash: $test_file_sha run: | @@ -113,7 +113,7 @@ busybox: from: type: oci url: $BUSYBOX_OCI - import: + imports: - path: test_file hash: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b856 EOF @@ -128,7 +128,7 @@ busybox: from: type: oci url: $BUSYBOX_OCI - import: + imports: - path: test_file hash: 1234abcdef EOF @@ -145,7 +145,7 @@ first: from: type: oci url: $BUSYBOX_OCI - import: + imports: - path: test_file hash: $test_file_sha run: | @@ -155,7 +155,7 @@ second: from: type: built tag: first - import: + imports: - path: stacker://first/test_file hash: $test_file_sha_upper run: | @@ -173,7 +173,7 @@ thing: from: type: oci url: $BUSYBOX_OCI - import: + imports: - path: https://www.google.com/favicon.ico hash: $google_sha run: | @@ -190,7 +190,7 @@ thing: from: type: oci url: $BUSYBOX_OCI - import: + imports: - path: https://www.google.com/favicon.ico hash: 0d4856785d1d3c3aad3e5311e654c70c19d335f927c24ebb89dfcd52b2d988cb EOF @@ -209,7 +209,7 @@ thing: from: type: oci url: $BUSYBOX_OCI - import: + imports: - path: https://www.google.com/favicon.ico hash: $google_sha - path: test_file @@ -232,7 +232,7 @@ thing: from: type: oci url: $BUSYBOX_OCI - import: + imports: - path: https://www.google.com/favicon.ico - path: test_file hash: $test_file_sha @@ -250,7 +250,7 @@ thing: from: type: oci url: $BUSYBOX_OCI - import: + imports: - path: https://www.google.com/favicon.ico hash: $google_sha - path: test_file @@ -265,7 +265,7 @@ busybox: from: type: oci url: $BUSYBOX_OCI - import: + imports: - "zomg" - - "one" - "two" @@ -279,7 +279,7 @@ busybox: from: type: oci url: $BUSYBOX_OCI - import: + imports: - dir run: | find /stacker @@ -307,7 +307,7 @@ first: from: type: oci url: $BUSYBOX_OCI - import: + imports: - path: test_file hash: $test_file_sha - test_file2 @@ -321,7 +321,7 @@ second: from: type: built tag: first - import: + imports: - path: stacker://first/test_file perms: 0777 hash: $test_file_sha @@ -330,7 +330,7 @@ second: third: from: type: scratch - import: + imports: - path: stacker://first/test_file mode: 0777 hash: $test_file_sha @@ -338,7 +338,7 @@ third: fourth: from: type: scratch - import: + imports: - path: test_file hash: $test_file_sha mode: 0777 @@ -348,7 +348,7 @@ fourth: fifth: from: type: scratch - import: + imports: - path: test_file dest: /files/ - path: test_file2 @@ -357,7 +357,7 @@ sixth: from: type: docker url: oci:${UBUNTU_OCI} - import: + imports: - stacker://fifth/files/test_file - stacker://fifth/file2 run: | @@ -365,7 +365,7 @@ sixth: seventh: from: type: scratch - import: + imports: - path: test_file dest: /files/ - path: test_file2 @@ -376,7 +376,7 @@ eigth: from: type: docker url: oci:${UBUNTU_OCI} - import: + imports: - path: test_file dest: /dir/files/ - path: test_file2 @@ -403,7 +403,7 @@ first: from: type: oci url: $BUSYBOX_OCI - import: + imports: - path: folder1/ dest: /folder1/ run: | @@ -422,7 +422,7 @@ third: from: type: oci url: $BUSYBOX_OCI - import: + imports: - path: stacker://second/folder1/ dest: /folder1/ run: | @@ -433,7 +433,7 @@ fourth: from: type: oci url: $BUSYBOX_OCI - import: + imports: - path: folder1/ dest: / run: | @@ -446,7 +446,7 @@ fifth: from: type: oci url: $BUSYBOX_OCI - import: + imports: - path: folder1/subfolder2/ dest: /folder3/ - path: folder1/subfolder2 @@ -477,7 +477,7 @@ src_folder_dest_non_existent_folder_case1: from: type: docker url: oci:${UBUNTU_OCI} - import: + imports: - path: folder1 dest: /folder2 run: | @@ -487,7 +487,7 @@ src_folder_dest_non_existent_folder_case2: from: type: docker url: oci:${UBUNTU_OCI} - import: + imports: - path: folder1/ dest: /folder2 run: | @@ -497,7 +497,7 @@ src_folder_dest_non_existent_folder_case3: from: type: docker url: oci:${UBUNTU_OCI} - import: + imports: - path: folder1 dest: /folder2/ run: | @@ -509,7 +509,7 @@ src_folder_dest_non_existent_folder_case4: from: type: docker url: oci:${UBUNTU_OCI} - import: + imports: - path: folder1/ dest: /folder2/ run: | @@ -517,3 +517,30 @@ src_folder_dest_non_existent_folder_case4: EOF stacker build } + +@test "legacy imports" { + echo "file1-content" > file1.txt + cat > stacker.yaml <