diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index 70e4f67822..04ff293e95 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -2253,6 +2253,208 @@ include = [ "*.jar", "media/mountain.jpg", "/media/person.png", ] }) }) + when("creating asset cache", func() { + var tmpDir string + it.Before(func() { + var err error + tmpDir, err = ioutil.TempDir("", "asset-cache-testing") + assert.Nil(err) + }) + it.After(func() { + os.RemoveAll(tmpDir) + }) + + it("creates reproducable asset image", func() { + buildpackManager = buildpacks.NewBuildpackManager( + t, + assert, + buildpacks.WithBuildpackSource(tmpDir), + ) + + templateMapping := map[string]interface{}{} + // resolve local assets to absolute paths + assetAPath, err := filepath.Abs(filepath.Join("testdata", "mock_assets", "assetA.txt")) + assert.Nil(err) + assetBPath, err := filepath.Abs(filepath.Join("testdata", "mock_assets", "assetB.txt")) + assert.Nil(err) + assetCPath, err := filepath.Abs(filepath.Join("testdata", "mock_assets", "assetC.txt")) + assert.Nil(err) + + templateMapping["assetAURI"] = assetAPath + templateMapping["assetBURI"] = assetBPath + templateMapping["assetCURI"] = assetCPath + + simpleBuildpackRoot := filepath.Join(tmpDir, "simple-buildpack") + assert.Succeeds(os.Mkdir(simpleBuildpackRoot, os.ModePerm)) + + secondSimpleBuildpackRoot := filepath.Join(tmpDir, "second-simple-buildpack") + assert.Succeeds(os.Mkdir(secondSimpleBuildpackRoot, os.ModePerm)) + + nestedBuildpackRoot := filepath.Join(tmpDir, "nested-assets-buildpack") + assert.Succeeds(os.Mkdir(nestedBuildpackRoot, os.ModePerm)) + + h.RecursiveCopy(t, filepath.Join("testdata", "mock_buildpacks", "with_assets", "simple-buildpack"), simpleBuildpackRoot) + h.RecursiveCopy(t, filepath.Join("testdata", "mock_buildpacks", "with_assets", "second-simple-buildpack"), secondSimpleBuildpackRoot) + h.RecursiveCopy(t, filepath.Join("testdata", "mock_buildpacks", "with_assets", "nested-assets-buildpack"), nestedBuildpackRoot) + + simpleBuildpackTOML := filepath.Join(simpleBuildpackRoot, "buildpack.toml") + simpleBuildpackTOMLFile, err := os.OpenFile(simpleBuildpackTOML, os.O_CREATE|os.O_RDWR, os.ModePerm) + assert.Nil(err) + + secondSimpleBuildpackTOML := filepath.Join(secondSimpleBuildpackRoot, "buildpack.toml") + secondSimpleBuildpackTOMLFile, err := os.OpenFile(secondSimpleBuildpackTOML, os.O_CREATE|os.O_RDWR, os.ModePerm) + assert.Nil(err) + + // create asset buildpacks + simpleArchiveBuildpack := buildpacks.NewArchiveBuildpack("simple-buildpack") + secondSimpleArchiveBuildpack := buildpacks.NewArchiveBuildpack("second-simple-buildpack") + nestedArchiveBuildpack := buildpacks.NewArchiveBuildpack("nested-assets-buildpack") + + // template buildpack assets + fixtureManager := pack.FixtureManager() + fixtureManager.TemplateFile(simpleBuildpackTOMLFile, templateMapping) + assert.Succeeds(simpleBuildpackTOMLFile.Close()) + + fixtureManager.TemplateFile(secondSimpleBuildpackTOMLFile, templateMapping) + assert.Succeeds(secondSimpleBuildpackTOMLFile.Close()) + + // template asset buildpacks using buildpack images + + simpleBuildpackConfigFile, err := ioutil.TempFile(tmpDir, "simple_package.toml") + assert.Nil(err) + fixtureManager.TemplateFixtureToFile( + "generic_package.toml", + simpleBuildpackConfigFile, + map[string]interface{}{ + "buildpack_uri": "simple-buildpack.tgz", + "OS": dockerHostOS(), + }, + ) + err = simpleBuildpackConfigFile.Close() + assert.Nil(err) + + secondBuildpackConfigFile, err := ioutil.TempFile(tmpDir, "second_package.toml") + assert.Nil(err) + fixtureManager.TemplateFixtureToFile( + "generic_package.toml", + secondBuildpackConfigFile, + map[string]interface{}{ + "buildpack_uri": "second-simple-buildpack.tgz", + "OS": dockerHostOS(), + }, + ) + err = secondBuildpackConfigFile.Close() + assert.Nil(err) + + // buildpack image names + simpleBuildpackImageName := registryConfig.RepoName("simple-assets-buildpack-" + h.RandString(8)) + secondSimpleBuildpackImageName := registryConfig.RepoName("second-simple-assets-buildpack-" + h.RandString(8)) + nestedBuildpackImageName := registryConfig.RepoName("nested-assets-buildpack-" + h.RandString(8)) + + templateMapping["simple_buildpack"] = simpleBuildpackImageName + templateMapping["second_simple_buildpack"] = secondSimpleBuildpackImageName + + nestedConfigFile, err := ioutil.TempFile(tmpDir, "nested_assets_buildpack_package.toml") + fixtureManager.TemplateFixtureToFile( + "nested_assets_buildpack_package.toml", + nestedConfigFile, + templateMapping, + ) + + assert.Succeeds(nestedConfigFile.Close()) + + packageImageBuildpack := buildpacks.NewPackageImage( + t, + pack, + nestedBuildpackImageName, + nestedConfigFile.Name(), + buildpacks.WithRequiredBuildpacks( + nestedArchiveBuildpack, + buildpacks.NewPackageImage( + t, + pack, + simpleBuildpackImageName, + simpleBuildpackConfigFile.Name(), + buildpacks.WithRequiredBuildpacks(simpleArchiveBuildpack), + ), + buildpacks.NewPackageImage( + t, + pack, + secondSimpleBuildpackImageName, + secondBuildpackConfigFile.Name(), + buildpacks.WithRequiredBuildpacks(secondSimpleArchiveBuildpack), + ), + ), + ) + + buildpackManager.PrepareBuildpacks(tmpDir, packageImageBuildpack) + defer h.DockerRmi(dockerCli, simpleBuildpackImageName, secondSimpleBuildpackImageName, nestedBuildpackImageName) + + assetCacheName := registryConfig.RepoName("some-asset-org/" + h.RandString(10)) + pack.RunSuccessfully( + "asset-cache", "create", + assetCacheName, + "--buildpack", nestedBuildpackImageName, + ) + defer h.DockerRmi(dockerCli, assetCacheName) + + allAssetsBuildpackRoot := filepath.Join(tmpDir, "all-assets-buildpack") + assert.Succeeds(os.Mkdir(allAssetsBuildpackRoot, os.ModePerm)) + + h.RecursiveCopy(t, filepath.Join("testdata", "mock_buildpacks", "with_assets", "all-assets-buildpack"), allAssetsBuildpackRoot) + + allAssetsBuildpackTOML := filepath.Join(allAssetsBuildpackRoot, "buildpack.toml") + allAssetsBuildpackTOMLFile, err := os.OpenFile(allAssetsBuildpackTOML, os.O_CREATE|os.O_RDWR, os.ModePerm) + assert.Nil(err) + + fixtureManager.TemplateFile(allAssetsBuildpackTOMLFile, templateMapping) + assert.Succeeds(allAssetsBuildpackTOMLFile.Close()) + + allAssetsBuildpackConfigFile, err := ioutil.TempFile(tmpDir, "all_assets_package.toml") + assert.Nil(err) + fixtureManager.TemplateFixtureToFile( + "generic_package.toml", + allAssetsBuildpackConfigFile, + map[string]interface{}{ + "buildpack_uri": "all-assets-buildpack.tgz", + "OS": dockerHostOS(), + }, + ) + err = allAssetsBuildpackConfigFile.Close() + assert.Nil(err) + + allAssetsBuildpackImageName := registryConfig.RepoName("all-assets-buildpack-" + h.RandString(8)) + allAssetsArchiveBuildpack := buildpacks.NewArchiveBuildpack("all-assets-buildpack") + + allAssetsImageBuildpack := buildpacks.NewPackageImage( + t, + pack, + allAssetsBuildpackImageName, + allAssetsBuildpackConfigFile.Name(), + buildpacks.WithRequiredBuildpacks( + allAssetsArchiveBuildpack, + ), + ) + + buildpackManager.PrepareBuildpacks(tmpDir, allAssetsImageBuildpack) + defer h.DockerRmi(dockerCli, allAssetsBuildpackImageName) + + identicalAssetCacheName := registryConfig.RepoName("some-identical-asset-org/" + h.RandString(10)) + pack.RunSuccessfully( + "asset-cache", "create", + identicalAssetCacheName, + "--buildpack", allAssetsBuildpackImageName, + ) + defer h.DockerRmi(dockerCli, identicalAssetCacheName) + + firstSha := imageSha(t, assert, dockerCli, assetCacheName) + secondSha := imageSha(t, assert, dockerCli, identicalAssetCacheName) + assert.Equal(firstSha, secondSha) + + // now lets check the sha256 values of these two assets are the same + }) + }) + when("rebase", func() { var repoName, runBefore, origID string var buildRunImage func(string, string, string) @@ -2877,6 +3079,13 @@ func imageLabel(t *testing.T, assert h.AssertionManager, dockerCli client.Common return label } +func imageSha(t *testing.T, assert h.AssertionManager, dockerCli client.CommonAPIClient, repoName string) string { + t.Helper() + inspect, _, err := dockerCli.ImageInspectWithRaw(context.Background(), repoName) + assert.Nil(err) + return inspect.ID +} + func dockerHostOS() string { daemonInfo, err := dockerCli.Info(context.TODO()) if err != nil { diff --git a/acceptance/buildpacks/archive_buildpack.go b/acceptance/buildpacks/archive_buildpack.go index fc188928fd..d756d42f75 100644 --- a/acceptance/buildpacks/archive_buildpack.go +++ b/acceptance/buildpacks/archive_buildpack.go @@ -22,6 +22,12 @@ const ( defaultMode = 0755 ) +func NewArchiveBuildpack(name string) archiveBuildpack { + return archiveBuildpack{ + name: name, + } +} + type archiveBuildpack struct { name string } diff --git a/acceptance/buildpacks/manager.go b/acceptance/buildpacks/manager.go index 5987155c93..0387c06c81 100644 --- a/acceptance/buildpacks/manager.go +++ b/acceptance/buildpacks/manager.go @@ -25,6 +25,12 @@ func WithBuildpackAPIVersion(apiVersion string) func(b *BuildpackManager) { } } +func WithBuildpackSource(source string) func(b *BuildpackManager) { + return func(b *BuildpackManager) { + b.sourceDir = source + } +} + func NewBuildpackManager(t *testing.T, assert testhelpers.AssertionManager, modifiers ...BuildpackManagerModifier) BuildpackManager { m := BuildpackManager{ testObject: t, diff --git a/acceptance/buildpacks/package_image_buildpack.go b/acceptance/buildpacks/package_image_buildpack.go index 26dbb1e0a5..d0e9724cb6 100644 --- a/acceptance/buildpacks/package_image_buildpack.go +++ b/acceptance/buildpacks/package_image_buildpack.go @@ -5,7 +5,6 @@ package buildpacks import ( "fmt" "io/ioutil" - "os" "path/filepath" "testing" diff --git a/acceptance/invoke/pack_fixtures.go b/acceptance/invoke/pack_fixtures.go index 65d7ea44d4..470640c8d9 100644 --- a/acceptance/invoke/pack_fixtures.go +++ b/acceptance/invoke/pack_fixtures.go @@ -80,6 +80,22 @@ func (m PackFixtureManager) TemplateFixtureToFile(name string, destination *os.F m.assert.Nil(err) } +func (m PackFixtureManager) TemplateFile(file *os.File, data map[string]interface{}) { + m.testObject.Helper() + + outputTemplate, err := ioutil.ReadAll(file) + m.assert.Nil(err) + + _, err = file.Seek(0, 0) + m.assert.Nil(err) + + err = file.Truncate(0) + m.assert.Nil(err) + + _, err = io.WriteString(file, m.fillTemplate(outputTemplate, data)) + m.assert.Nil(err) +} + func (m PackFixtureManager) fillTemplate(templateContents []byte, data map[string]interface{}) string { tpl, err := template.New(""). Funcs(template.FuncMap{ diff --git a/acceptance/testdata/mock_assets/assetA.txt b/acceptance/testdata/mock_assets/assetA.txt new file mode 100644 index 0000000000..187782c743 --- /dev/null +++ b/acceptance/testdata/mock_assets/assetA.txt @@ -0,0 +1 @@ +A pretty cool asset Ayyyy. \ No newline at end of file diff --git a/acceptance/testdata/mock_assets/assetB.txt b/acceptance/testdata/mock_assets/assetB.txt new file mode 100644 index 0000000000..e6652ab82c --- /dev/null +++ b/acceptance/testdata/mock_assets/assetB.txt @@ -0,0 +1 @@ +Just another asset. \ No newline at end of file diff --git a/acceptance/testdata/mock_assets/assetC.txt b/acceptance/testdata/mock_assets/assetC.txt new file mode 100644 index 0000000000..e3ea992bce --- /dev/null +++ b/acceptance/testdata/mock_assets/assetC.txt @@ -0,0 +1 @@ +Just another-nother asset. \ No newline at end of file diff --git a/acceptance/testdata/mock_buildpacks/with_assets/all-assets-buildpack/buildpack.toml b/acceptance/testdata/mock_buildpacks/with_assets/all-assets-buildpack/buildpack.toml new file mode 100644 index 0000000000..bb7408f8fd --- /dev/null +++ b/acceptance/testdata/mock_buildpacks/with_assets/all-assets-buildpack/buildpack.toml @@ -0,0 +1,33 @@ +api = "0.2" + +[buildpack] + id = "all-assets/asset-buildpack" + version = "all-assets-builapck-version" + name = "All Assets Buildpack Buildpack" + +[[stacks]] + id = "pack.test.stack" + +[[assets]] + id = "asset A" + sha256 = "797b3f6bf2b2c10a8299d51dfdbcfed329d3c133fdc7e695beddbe8f70b49da9" + name = "A Asset" + stacks = ["pack.test.stack"] + uri = "{{ .assetAURI }}" + version = "1.2.3" + +[[assets]] + id = "asset C" + sha256 = "339b5181dac7c2d01cbbd6fff90f541f0350864f03a02f05faf852baa2826064" + name = "C Asset" + stacks = ["pack.test.stack"] + uri = "{{ .assetCURI }}" + version = "1.3.5" + +[[assets]] + id = "asset B" + name = "B Asset" + sha256 = "61eea2ec4053ca25b9bd5d7bebaba48ee5398569aa1da5bc3541cbab1d09b86b" + stacks = ["pack.test.stack"] + uri = "{{ .assetBURI }}" + version = "4.5.6" \ No newline at end of file diff --git a/acceptance/testdata/mock_buildpacks/with_assets/nested-assets-buildpack/buildpack.toml b/acceptance/testdata/mock_buildpacks/with_assets/nested-assets-buildpack/buildpack.toml new file mode 100644 index 0000000000..0a96b435ca --- /dev/null +++ b/acceptance/testdata/mock_buildpacks/with_assets/nested-assets-buildpack/buildpack.toml @@ -0,0 +1,14 @@ +api = "0.2" + +[buildpack] + id = "simple/nested" + version = "nested-version" + name = "Nested Asset Buildpack" + +[[order]] + [[order.group]] + id = "simple/asset-buildpack" + version = "simple-asset-buildpack-version" + [[order.group]] + id = "second-simple/asset-buildpack" + version = "second-simple-asset-buildpack-version" \ No newline at end of file diff --git a/acceptance/testdata/mock_buildpacks/with_assets/second-simple-buildpack/buildpack.toml b/acceptance/testdata/mock_buildpacks/with_assets/second-simple-buildpack/buildpack.toml new file mode 100644 index 0000000000..18881aa29f --- /dev/null +++ b/acceptance/testdata/mock_buildpacks/with_assets/second-simple-buildpack/buildpack.toml @@ -0,0 +1,26 @@ +api = "0.2" + +[buildpack] + id = "second-simple/asset-buildpack" + version = "second-simple-asset-buildpack-version" + name = "Second Simple Asset Buildpack Buildpack" + +[[stacks]] + id = "pack.test.stack" + + +[[assets]] + id = "asset C" + sha256 = "339b5181dac7c2d01cbbd6fff90f541f0350864f03a02f05faf852baa2826064" + name = "C Asset" + stacks = ["pack.test.stack"] + uri = "{{ .assetCURI }}" + version = "1.3.5" + +[[assets]] + id = "asset B repeat" + name = "B Asset Repeat" + sha256 = "61eea2ec4053ca25b9bd5d7bebaba48ee5398569aa1da5bc3541cbab1d09b86b" + stacks = ["pack.test.stack"] + uri = "{{ .assetBURI }}" + version = "4.5.6" \ No newline at end of file diff --git a/acceptance/testdata/mock_buildpacks/with_assets/simple-buildpack/buildpack.toml b/acceptance/testdata/mock_buildpacks/with_assets/simple-buildpack/buildpack.toml new file mode 100644 index 0000000000..b0b45e3ad9 --- /dev/null +++ b/acceptance/testdata/mock_buildpacks/with_assets/simple-buildpack/buildpack.toml @@ -0,0 +1,25 @@ +api = "0.2" + +[buildpack] + id = "simple/asset-buildpack" + version = "simple-asset-buildpack-version" + name = "Simple Asset Buildpack Buildpack" + +[[stacks]] + id = "pack.test.stack" + +[[assets]] + id = "asset A" + sha256 = "797b3f6bf2b2c10a8299d51dfdbcfed329d3c133fdc7e695beddbe8f70b49da9" + name = "A Asset" + stacks = ["pack.test.stack"] + uri = "{{ .assetAURI }}" + version = "1.2.3" + +[[assets]] + id = "asset B" + name = "B Asset" + sha256 = "61eea2ec4053ca25b9bd5d7bebaba48ee5398569aa1da5bc3541cbab1d09b86b" + stacks = ["pack.test.stack"] + uri = "{{ .assetBURI }}" + version = "4.5.6" \ No newline at end of file diff --git a/acceptance/testdata/pack_fixtures/generic_package.toml b/acceptance/testdata/pack_fixtures/generic_package.toml new file mode 100644 index 0000000000..278fa4727a --- /dev/null +++ b/acceptance/testdata/pack_fixtures/generic_package.toml @@ -0,0 +1,5 @@ +[buildpack] +uri = "{{ .buildpack_uri }}" + +[platform] +os = "{{ .OS }}" \ No newline at end of file diff --git a/acceptance/testdata/pack_fixtures/nested_assets_buildpack_package.toml b/acceptance/testdata/pack_fixtures/nested_assets_buildpack_package.toml new file mode 100644 index 0000000000..f1b0de2b15 --- /dev/null +++ b/acceptance/testdata/pack_fixtures/nested_assets_buildpack_package.toml @@ -0,0 +1,8 @@ +[buildpack] +uri = "nested-assets-buildpack.tgz" + +[[dependencies]] +image = "{{.simple_buildpack}}" + +[[dependencies]] +image = "{{.second_simple_buildpack}}" \ No newline at end of file