github.com/buildpacks/pack@v0.33.3-0.20240516162812-884dd1837311/buildpackage/config_reader_test.go (about)

     1  package buildpackage_test
     2  
     3  import (
     4  	"os"
     5  	"path/filepath"
     6  	"testing"
     7  
     8  	"github.com/heroku/color"
     9  	"github.com/sclevine/spec"
    10  	"github.com/sclevine/spec/report"
    11  
    12  	"github.com/buildpacks/pack/buildpackage"
    13  	"github.com/buildpacks/pack/pkg/dist"
    14  	h "github.com/buildpacks/pack/testhelpers"
    15  )
    16  
    17  func TestBuildpackageConfigReader(t *testing.T) {
    18  	color.Disable(true)
    19  	defer color.Disable(false)
    20  	spec.Run(t, "Buildpackage Config Reader", testBuildpackageConfigReader, spec.Parallel(), spec.Report(report.Terminal{}))
    21  }
    22  
    23  func testBuildpackageConfigReader(t *testing.T, when spec.G, it spec.S) {
    24  	when("#Read", func() {
    25  		var tmpDir string
    26  
    27  		it.Before(func() {
    28  			var err error
    29  			tmpDir, err = os.MkdirTemp("", "buildpackage-config-test")
    30  			h.AssertNil(t, err)
    31  		})
    32  
    33  		it.After(func() {
    34  			os.RemoveAll(tmpDir)
    35  		})
    36  
    37  		it("returns default buildpack config", func() {
    38  			expected := buildpackage.Config{
    39  				Buildpack: dist.BuildpackURI{
    40  					URI: ".",
    41  				},
    42  				Platform: dist.Platform{
    43  					OS: "linux",
    44  				},
    45  			}
    46  			actual := buildpackage.DefaultConfig()
    47  
    48  			h.AssertEq(t, actual, expected)
    49  		})
    50  
    51  		it("returns default extension config", func() {
    52  			expected := buildpackage.Config{
    53  				Extension: dist.BuildpackURI{
    54  					URI: ".",
    55  				},
    56  				Platform: dist.Platform{
    57  					OS: "linux",
    58  				},
    59  			}
    60  			actual := buildpackage.DefaultExtensionConfig()
    61  
    62  			h.AssertEq(t, actual, expected)
    63  		})
    64  
    65  		it("returns correct config when provided toml file is valid", func() {
    66  			configFile := filepath.Join(tmpDir, "package.toml")
    67  
    68  			err := os.WriteFile(configFile, []byte(validPackageToml), os.ModePerm)
    69  			h.AssertNil(t, err)
    70  
    71  			packageConfigReader := buildpackage.NewConfigReader()
    72  
    73  			config, err := packageConfigReader.Read(configFile)
    74  			h.AssertNil(t, err)
    75  
    76  			h.AssertEq(t, config.Platform.OS, "windows")
    77  			h.AssertEq(t, config.Buildpack.URI, "https://example.com/bp/a.tgz")
    78  			h.AssertEq(t, len(config.Dependencies), 1)
    79  			h.AssertEq(t, config.Dependencies[0].URI, "https://example.com/bp/b.tgz")
    80  		})
    81  
    82  		it("returns a config with 'linux' as default when platform is missing", func() {
    83  			configFile := filepath.Join(tmpDir, "package.toml")
    84  
    85  			err := os.WriteFile(configFile, []byte(validPackageWithoutPlatformToml), os.ModePerm)
    86  			h.AssertNil(t, err)
    87  
    88  			packageConfigReader := buildpackage.NewConfigReader()
    89  
    90  			config, err := packageConfigReader.Read(configFile)
    91  			h.AssertNil(t, err)
    92  
    93  			h.AssertEq(t, config.Platform.OS, "linux")
    94  		})
    95  
    96  		it("returns an error when toml decode fails", func() {
    97  			configFile := filepath.Join(tmpDir, "package.toml")
    98  
    99  			err := os.WriteFile(configFile, []byte(brokenPackageToml), os.ModePerm)
   100  			h.AssertNil(t, err)
   101  
   102  			packageConfigReader := buildpackage.NewConfigReader()
   103  
   104  			_, err = packageConfigReader.Read(configFile)
   105  			h.AssertNotNil(t, err)
   106  
   107  			h.AssertError(t, err, "decoding toml")
   108  		})
   109  
   110  		it("returns an error when buildpack uri is invalid", func() {
   111  			configFile := filepath.Join(tmpDir, "package.toml")
   112  
   113  			err := os.WriteFile(configFile, []byte(invalidBPURIPackageToml), os.ModePerm)
   114  			h.AssertNil(t, err)
   115  
   116  			packageConfigReader := buildpackage.NewConfigReader()
   117  
   118  			_, err = packageConfigReader.Read(configFile)
   119  			h.AssertNotNil(t, err)
   120  			h.AssertError(t, err, "invalid locator")
   121  			h.AssertError(t, err, "invalid/uri@version-is-invalid")
   122  		})
   123  
   124  		it("returns an error when platform os is invalid", func() {
   125  			configFile := filepath.Join(tmpDir, "package.toml")
   126  
   127  			err := os.WriteFile(configFile, []byte(invalidPlatformOSPackageToml), os.ModePerm)
   128  			h.AssertNil(t, err)
   129  
   130  			packageConfigReader := buildpackage.NewConfigReader()
   131  
   132  			_, err = packageConfigReader.Read(configFile)
   133  			h.AssertNotNil(t, err)
   134  			h.AssertError(t, err, "invalid 'platform.os' configuration")
   135  			h.AssertError(t, err, "only ['linux', 'windows'] is permitted")
   136  		})
   137  
   138  		it("returns an error when dependency uri is invalid", func() {
   139  			configFile := filepath.Join(tmpDir, "package.toml")
   140  
   141  			err := os.WriteFile(configFile, []byte(invalidDepURIPackageToml), os.ModePerm)
   142  			h.AssertNil(t, err)
   143  
   144  			packageConfigReader := buildpackage.NewConfigReader()
   145  
   146  			_, err = packageConfigReader.Read(configFile)
   147  			h.AssertNotNil(t, err)
   148  			h.AssertError(t, err, "invalid locator")
   149  			h.AssertError(t, err, "invalid/uri@version-is-invalid")
   150  		})
   151  
   152  		it("returns an error when unknown array table is present", func() {
   153  			configFile := filepath.Join(tmpDir, "package.toml")
   154  
   155  			err := os.WriteFile(configFile, []byte(invalidDepTablePackageToml), os.ModePerm)
   156  			h.AssertNil(t, err)
   157  
   158  			packageConfigReader := buildpackage.NewConfigReader()
   159  
   160  			_, err = packageConfigReader.Read(configFile)
   161  			h.AssertNotNil(t, err)
   162  			h.AssertError(t, err, "unknown configuration element")
   163  			h.AssertError(t, err, "dependenceis")
   164  			h.AssertNotContains(t, err.Error(), ".image")
   165  			h.AssertError(t, err, configFile)
   166  		})
   167  
   168  		it("returns an error when unknown buildpack key is present", func() {
   169  			configFile := filepath.Join(tmpDir, "package.toml")
   170  
   171  			err := os.WriteFile(configFile, []byte(unknownBPKeyPackageToml), os.ModePerm)
   172  			h.AssertNil(t, err)
   173  
   174  			packageConfigReader := buildpackage.NewConfigReader()
   175  
   176  			_, err = packageConfigReader.Read(configFile)
   177  			h.AssertNotNil(t, err)
   178  			h.AssertError(t, err, "unknown configuration element ")
   179  			h.AssertError(t, err, "buildpack.url")
   180  			h.AssertError(t, err, configFile)
   181  		})
   182  
   183  		it("returns an error when multiple unknown keys are present", func() {
   184  			configFile := filepath.Join(tmpDir, "package.toml")
   185  
   186  			err := os.WriteFile(configFile, []byte(multipleUnknownKeysPackageToml), os.ModePerm)
   187  			h.AssertNil(t, err)
   188  
   189  			packageConfigReader := buildpackage.NewConfigReader()
   190  
   191  			_, err = packageConfigReader.Read(configFile)
   192  			h.AssertNotNil(t, err)
   193  			h.AssertError(t, err, "unknown configuration elements")
   194  			h.AssertError(t, err, "'buildpack.url'")
   195  			h.AssertError(t, err, "', '")
   196  			h.AssertError(t, err, "'dependenceis'")
   197  		})
   198  
   199  		it("returns an error when both dependency options are configured", func() {
   200  			configFile := filepath.Join(tmpDir, "package.toml")
   201  
   202  			err := os.WriteFile(configFile, []byte(conflictingDependencyKeysPackageToml), os.ModePerm)
   203  			h.AssertNil(t, err)
   204  
   205  			packageConfigReader := buildpackage.NewConfigReader()
   206  
   207  			_, err = packageConfigReader.Read(configFile)
   208  			h.AssertNotNil(t, err)
   209  			h.AssertError(t, err, "dependency configured with both 'uri' and 'image'")
   210  		})
   211  
   212  		it("returns an error no buildpack is configured", func() {
   213  			configFile := filepath.Join(tmpDir, "package.toml")
   214  
   215  			err := os.WriteFile(configFile, []byte(missingBuildpackPackageToml), os.ModePerm)
   216  			h.AssertNil(t, err)
   217  
   218  			packageConfigReader := buildpackage.NewConfigReader()
   219  
   220  			_, err = packageConfigReader.Read(configFile)
   221  			h.AssertNotNil(t, err)
   222  			h.AssertError(t, err, "missing 'buildpack.uri' configuration")
   223  		})
   224  	})
   225  }
   226  
   227  const validPackageToml = `
   228  [buildpack]
   229  uri = "https://example.com/bp/a.tgz"
   230  
   231  [[dependencies]]
   232  uri = "https://example.com/bp/b.tgz"
   233  
   234  [platform]
   235  os = "windows"
   236  `
   237  
   238  const validPackageWithoutPlatformToml = `
   239  [buildpack]
   240  uri = "https://example.com/bp/a.tgz"
   241  
   242  [[dependencies]]
   243  uri = "https://example.com/bp/b.tgz"
   244  `
   245  
   246  const brokenPackageToml = `
   247  [buildpack # missing closing bracket
   248  uri = "https://example.com/bp/a.tgz"
   249  
   250  [dependencies]] # missing opening bracket
   251  uri = "https://example.com/bp/b.tgz"
   252  `
   253  
   254  const invalidBPURIPackageToml = `
   255  [buildpack]
   256  uri = "invalid/uri@version-is-invalid"
   257  `
   258  
   259  const invalidDepURIPackageToml = `
   260  [buildpack]
   261  uri = "noop-buildpack.tgz"
   262  
   263  [[dependencies]]
   264  uri = "invalid/uri@version-is-invalid"
   265  `
   266  
   267  const invalidDepTablePackageToml = `
   268  [buildpack]
   269  uri = "noop-buildpack.tgz"
   270  
   271  [[dependenceis]] # Notice: this is misspelled
   272  image = "some/package-dep"
   273  `
   274  
   275  const invalidPlatformOSPackageToml = `
   276  [buildpack]
   277  uri = "https://example.com/bp/a.tgz"
   278  
   279  [platform]
   280  os = "some-incorrect-platform"
   281  `
   282  
   283  const unknownBPKeyPackageToml = `
   284  [buildpack]
   285  url = "noop-buildpack.tgz"
   286  `
   287  
   288  const multipleUnknownKeysPackageToml = `
   289  [buildpack]
   290  url = "noop-buildpack.tgz"
   291  
   292  [[dependenceis]] # Notice: this is misspelled
   293  image = "some/package-dep"
   294  `
   295  
   296  const conflictingDependencyKeysPackageToml = `
   297  [buildpack]
   298  uri = "noop-buildpack.tgz"
   299  
   300  [[dependencies]]
   301  uri = "bp/b"
   302  image = "some/package-dep"
   303  `
   304  
   305  const missingBuildpackPackageToml = `
   306  [[dependencies]]
   307  uri = "bp/b"
   308  `