github.com/YousefHaggyHeroku/pack@v1.5.5/internal/builder/label_manager_test.go (about)

     1  package builder_test
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"github.com/heroku/color"
     9  	"github.com/sclevine/spec"
    10  	"github.com/sclevine/spec/report"
    11  
    12  	"github.com/buildpacks/lifecycle/api"
    13  
    14  	"github.com/YousefHaggyHeroku/pack/internal/builder"
    15  	"github.com/YousefHaggyHeroku/pack/internal/builder/fakes"
    16  	"github.com/YousefHaggyHeroku/pack/internal/dist"
    17  	h "github.com/YousefHaggyHeroku/pack/testhelpers"
    18  )
    19  
    20  func TestLabelManager(t *testing.T) {
    21  	color.Disable(true)
    22  	defer color.Disable(false)
    23  	spec.Run(t, "testLabelManager", testLabelManager, spec.Parallel(), spec.Report(report.Terminal{}))
    24  }
    25  
    26  func testLabelManager(t *testing.T, when spec.G, it spec.S) {
    27  	var assert = h.NewAssertionManager(t)
    28  
    29  	when("Metadata", func() {
    30  		const (
    31  			buildpackFormat = `{
    32        "id": "%s",
    33        "version": "%s",
    34        "homepage": "%s"
    35      }`
    36  			lifecycleFormat = `{
    37        "version": "%s",
    38        "api": {
    39          "buildpack": "%s",
    40          "platform": "%s"
    41        },
    42        "apis": {
    43          "buildpack": {"deprecated": ["%s"], "supported": ["%s", "%s"]},
    44          "platform": {"deprecated": ["%s"], "supported": ["%s", "%s"]}
    45        }
    46      }`
    47  			metadataFormat = `{
    48    "description": "%s",
    49    "stack": {
    50      "runImage": {
    51        "image": "%s",
    52        "mirrors": ["%s"]
    53      }
    54    },
    55    "buildpacks": [
    56      %s,
    57      %s
    58    ],
    59    "lifecycle": %s,
    60    "createdBy": {"name": "%s", "version": "%s"}
    61  }`
    62  		)
    63  
    64  		var (
    65  			expectedDescription    = "Test image description"
    66  			expectedRunImage       = "some/run-image"
    67  			expectedRunImageMirror = "gcr.io/some/default"
    68  			expectedBuildpacks     = []dist.BuildpackInfo{
    69  				{
    70  					ID:       "test.buildpack",
    71  					Version:  "test.buildpack.version",
    72  					Homepage: "http://geocities.com/test-bp",
    73  				},
    74  				{
    75  					ID:       "test.buildpack.two",
    76  					Version:  "test.buildpack.two.version",
    77  					Homepage: "http://geocities.com/test-bp-two",
    78  				},
    79  			}
    80  			expectedLifecycleVersion    = builder.VersionMustParse("1.2.3")
    81  			expectedBuildpackAPI        = api.MustParse("0.1")
    82  			expectedPlatformAPI         = api.MustParse("2.3")
    83  			expectedBuildpackDeprecated = "0.1"
    84  			expectedBuildpackSupported  = []string{"1.2", "1.3"}
    85  			expectedPlatformDeprecated  = "1.2"
    86  			expectedPlatformSupported   = []string{"2.3", "2.4"}
    87  			expectedCreatorName         = "pack"
    88  			expectedVersion             = "2.3.4"
    89  
    90  			rawMetadata = fmt.Sprintf(
    91  				metadataFormat,
    92  				expectedDescription,
    93  				expectedRunImage,
    94  				expectedRunImageMirror,
    95  				fmt.Sprintf(
    96  					buildpackFormat,
    97  					expectedBuildpacks[0].ID,
    98  					expectedBuildpacks[0].Version,
    99  					expectedBuildpacks[0].Homepage,
   100  				),
   101  				fmt.Sprintf(
   102  					buildpackFormat,
   103  					expectedBuildpacks[1].ID,
   104  					expectedBuildpacks[1].Version,
   105  					expectedBuildpacks[1].Homepage,
   106  				),
   107  				fmt.Sprintf(
   108  					lifecycleFormat,
   109  					expectedLifecycleVersion,
   110  					expectedBuildpackAPI,
   111  					expectedPlatformAPI,
   112  					expectedBuildpackDeprecated,
   113  					expectedBuildpackSupported[0],
   114  					expectedBuildpackSupported[1],
   115  					expectedPlatformDeprecated,
   116  					expectedPlatformSupported[0],
   117  					expectedPlatformSupported[1],
   118  				),
   119  				expectedCreatorName,
   120  				expectedVersion,
   121  			)
   122  		)
   123  
   124  		it("returns full metadata", func() {
   125  			inspectable := newInspectable(returnForLabel(rawMetadata))
   126  
   127  			labelManager := builder.NewLabelManager(inspectable)
   128  			metadata, err := labelManager.Metadata()
   129  			assert.Nil(err)
   130  			assert.Equal(metadata.Description, expectedDescription)
   131  			assert.Equal(metadata.Stack.RunImage.Image, expectedRunImage)
   132  			assert.Equal(metadata.Stack.RunImage.Mirrors, []string{expectedRunImageMirror})
   133  			assert.Equal(metadata.Buildpacks, expectedBuildpacks)
   134  			assert.Equal(metadata.Lifecycle.Version, expectedLifecycleVersion)
   135  			assert.Equal(metadata.Lifecycle.API.BuildpackVersion, expectedBuildpackAPI)
   136  			assert.Equal(metadata.Lifecycle.API.PlatformVersion, expectedPlatformAPI)
   137  			assert.Equal(metadata.Lifecycle.APIs.Buildpack.Deprecated.AsStrings(), []string{expectedBuildpackDeprecated})
   138  			assert.Equal(metadata.Lifecycle.APIs.Buildpack.Supported.AsStrings(), expectedBuildpackSupported)
   139  			assert.Equal(metadata.Lifecycle.APIs.Platform.Deprecated.AsStrings(), []string{expectedPlatformDeprecated})
   140  			assert.Equal(metadata.Lifecycle.APIs.Platform.Supported.AsStrings(), expectedPlatformSupported)
   141  			assert.Equal(metadata.CreatedBy.Name, expectedCreatorName)
   142  			assert.Equal(metadata.CreatedBy.Version, expectedVersion)
   143  		})
   144  
   145  		it("requests the expected label", func() {
   146  			inspectable := newInspectable(returnForLabel(rawMetadata))
   147  
   148  			labelManager := builder.NewLabelManager(inspectable)
   149  			_, err := labelManager.Metadata()
   150  			assert.Nil(err)
   151  
   152  			assert.Equal(inspectable.ReceivedName, "io.buildpacks.builder.metadata")
   153  		})
   154  
   155  		when("inspectable returns an error for `Label`", func() {
   156  			it("returns a wrapped error", func() {
   157  				expectedError := errors.New("couldn't find label")
   158  
   159  				inspectable := newInspectable(errorForLabel(expectedError))
   160  
   161  				labelManager := builder.NewLabelManager(inspectable)
   162  				_, err := labelManager.Metadata()
   163  
   164  				assert.ErrorWithMessage(
   165  					err,
   166  					"getting label io.buildpacks.builder.metadata: couldn't find label",
   167  				)
   168  			})
   169  		})
   170  
   171  		when("inspectable returns invalid json for `Label`", func() {
   172  			it("returns a wrapped error", func() {
   173  				inspectable := newInspectable(returnForLabel("{"))
   174  
   175  				labelManager := builder.NewLabelManager(inspectable)
   176  				_, err := labelManager.Metadata()
   177  
   178  				assert.ErrorWithMessage(
   179  					err,
   180  					"parsing label content for io.buildpacks.builder.metadata: unexpected end of JSON input",
   181  				)
   182  			})
   183  		})
   184  
   185  		when("inspectable returns empty content for `Label`", func() {
   186  			it("returns an error suggesting rebuilding the builder", func() {
   187  				inspectable := newInspectable(returnForLabel(""))
   188  
   189  				labelManager := builder.NewLabelManager(inspectable)
   190  				_, err := labelManager.Metadata()
   191  
   192  				assert.ErrorWithMessage(
   193  					err,
   194  					"builder missing label io.buildpacks.builder.metadata -- try recreating builder",
   195  				)
   196  			})
   197  		})
   198  	})
   199  
   200  	when("StackID", func() {
   201  		it("returns the stack ID", func() {
   202  			inspectable := newInspectable(returnForLabel("some.stack.id"))
   203  
   204  			labelManager := builder.NewLabelManager(inspectable)
   205  			stackID, err := labelManager.StackID()
   206  			assert.Nil(err)
   207  
   208  			assert.Equal(stackID, "some.stack.id")
   209  		})
   210  
   211  		it("requests the expected label", func() {
   212  			inspectable := newInspectable(returnForLabel("some.stack.id"))
   213  
   214  			labelManager := builder.NewLabelManager(inspectable)
   215  			_, err := labelManager.StackID()
   216  			assert.Nil(err)
   217  
   218  			assert.Equal(inspectable.ReceivedName, "io.buildpacks.stack.id")
   219  		})
   220  
   221  		when("inspectable return empty content for `Label`", func() {
   222  			it("returns an error suggesting rebuilding the builder", func() {
   223  				inspectable := newInspectable(returnForLabel(""))
   224  
   225  				labelManager := builder.NewLabelManager(inspectable)
   226  				_, err := labelManager.StackID()
   227  
   228  				assert.ErrorWithMessage(
   229  					err,
   230  					"builder missing label io.buildpacks.stack.id -- try recreating builder",
   231  				)
   232  			})
   233  		})
   234  
   235  		when("inspectable returns an error for `Label`", func() {
   236  			it("returns a wrapped error", func() {
   237  				expectedError := errors.New("couldn't find label")
   238  
   239  				inspectable := newInspectable(errorForLabel(expectedError))
   240  
   241  				labelManager := builder.NewLabelManager(inspectable)
   242  				_, err := labelManager.StackID()
   243  
   244  				assert.ErrorWithMessage(
   245  					err,
   246  					"getting label io.buildpacks.stack.id: couldn't find label",
   247  				)
   248  			})
   249  		})
   250  	})
   251  
   252  	when("Mixins", func() {
   253  		it("returns the mixins", func() {
   254  			inspectable := newInspectable(returnForLabel(`["mixinX", "mixinY", "build:mixinA"]`))
   255  
   256  			labelManager := builder.NewLabelManager(inspectable)
   257  			mixins, err := labelManager.Mixins()
   258  			assert.Nil(err)
   259  
   260  			assert.Equal(mixins, []string{"mixinX", "mixinY", "build:mixinA"})
   261  		})
   262  
   263  		it("requests the expected label", func() {
   264  			inspectable := newInspectable(returnForLabel(`["mixinX", "mixinY", "build:mixinA"]`))
   265  
   266  			labelManager := builder.NewLabelManager(inspectable)
   267  			_, err := labelManager.Mixins()
   268  			assert.Nil(err)
   269  
   270  			assert.Equal(inspectable.ReceivedName, "io.buildpacks.stack.mixins")
   271  		})
   272  
   273  		when("inspectable return empty content for `Label`", func() {
   274  			it("returns empty stack mixins", func() {
   275  				inspectable := newInspectable(returnForLabel(""))
   276  
   277  				labelManager := builder.NewLabelManager(inspectable)
   278  				mixins, err := labelManager.Mixins()
   279  				assert.Nil(err)
   280  
   281  				assert.Equal(mixins, []string{})
   282  			})
   283  		})
   284  
   285  		when("inspectable returns an error for `Label`", func() {
   286  			it("returns a wrapped error", func() {
   287  				expectedError := errors.New("couldn't find label")
   288  
   289  				inspectable := newInspectable(errorForLabel(expectedError))
   290  
   291  				labelManager := builder.NewLabelManager(inspectable)
   292  				_, err := labelManager.Mixins()
   293  
   294  				assert.ErrorWithMessage(
   295  					err,
   296  					"getting label io.buildpacks.stack.mixins: couldn't find label",
   297  				)
   298  			})
   299  		})
   300  
   301  		when("inspectable returns invalid json for `Label`", func() {
   302  			it("returns a wrapped error", func() {
   303  				inspectable := newInspectable(returnForLabel("{"))
   304  
   305  				labelManager := builder.NewLabelManager(inspectable)
   306  				_, err := labelManager.Mixins()
   307  
   308  				assert.ErrorWithMessage(
   309  					err,
   310  					"parsing label content for io.buildpacks.stack.mixins: unexpected end of JSON input",
   311  				)
   312  			})
   313  		})
   314  	})
   315  
   316  	when("Order", func() {
   317  		var rawOrder = `[{"group": [{"id": "buildpack-1-id", "optional": false}, {"id": "buildpack-2-id", "version": "buildpack-2-version-1", "optional": true}]}]`
   318  
   319  		it("returns the order", func() {
   320  			inspectable := newInspectable(returnForLabel(rawOrder))
   321  
   322  			labelManager := builder.NewLabelManager(inspectable)
   323  			mixins, err := labelManager.Order()
   324  			assert.Nil(err)
   325  
   326  			expectedOrder := dist.Order{
   327  				{
   328  					Group: []dist.BuildpackRef{
   329  						{
   330  							BuildpackInfo: dist.BuildpackInfo{
   331  								ID: "buildpack-1-id",
   332  							},
   333  						},
   334  						{
   335  							BuildpackInfo: dist.BuildpackInfo{
   336  								ID:      "buildpack-2-id",
   337  								Version: "buildpack-2-version-1",
   338  							},
   339  							Optional: true,
   340  						},
   341  					},
   342  				},
   343  			}
   344  
   345  			assert.Equal(mixins, expectedOrder)
   346  		})
   347  
   348  		it("requests the expected label", func() {
   349  			inspectable := newInspectable(returnForLabel(rawOrder))
   350  
   351  			labelManager := builder.NewLabelManager(inspectable)
   352  			_, err := labelManager.Order()
   353  			assert.Nil(err)
   354  
   355  			assert.Equal(inspectable.ReceivedName, "io.buildpacks.buildpack.order")
   356  		})
   357  
   358  		when("inspectable return empty content for `Label`", func() {
   359  			it("returns an empty order object", func() {
   360  				inspectable := newInspectable(returnForLabel(""))
   361  
   362  				labelManager := builder.NewLabelManager(inspectable)
   363  				order, err := labelManager.Order()
   364  				assert.Nil(err)
   365  
   366  				assert.Equal(order, dist.Order{})
   367  			})
   368  		})
   369  
   370  		when("inspectable returns an error for `Label`", func() {
   371  			it("returns a wrapped error", func() {
   372  				expectedError := errors.New("couldn't find label")
   373  
   374  				inspectable := newInspectable(errorForLabel(expectedError))
   375  
   376  				labelManager := builder.NewLabelManager(inspectable)
   377  				_, err := labelManager.Order()
   378  
   379  				assert.ErrorWithMessage(
   380  					err,
   381  					"getting label io.buildpacks.buildpack.order: couldn't find label",
   382  				)
   383  			})
   384  		})
   385  
   386  		when("inspectable returns invalid json for `Label`", func() {
   387  			it("returns a wrapped error", func() {
   388  				inspectable := newInspectable(returnForLabel("{"))
   389  
   390  				labelManager := builder.NewLabelManager(inspectable)
   391  				_, err := labelManager.Order()
   392  
   393  				assert.ErrorWithMessage(
   394  					err,
   395  					"parsing label content for io.buildpacks.buildpack.order: unexpected end of JSON input",
   396  				)
   397  			})
   398  		})
   399  	})
   400  
   401  	when("BuildpackLayers", func() {
   402  		var rawLayers = `
   403  {
   404    "buildpack-1-id": {
   405      "buildpack-1-version-1": {
   406        "api": "0.1",
   407        "layerDiffID": "sha256:buildpack-1-version-1-diff-id"
   408      },
   409      "buildpack-1-version-2": {
   410        "api": "0.2",
   411        "layerDiffID": "sha256:buildpack-1-version-2-diff-id"
   412      }
   413    }
   414  }
   415  `
   416  
   417  		it("returns the layers", func() {
   418  			inspectable := newInspectable(returnForLabel(rawLayers))
   419  
   420  			labelManager := builder.NewLabelManager(inspectable)
   421  			layers, err := labelManager.BuildpackLayers()
   422  			assert.Nil(err)
   423  
   424  			expectedLayers := dist.BuildpackLayers{
   425  				"buildpack-1-id": {
   426  					"buildpack-1-version-1": dist.BuildpackLayerInfo{
   427  						API:         api.MustParse("0.1"),
   428  						LayerDiffID: "sha256:buildpack-1-version-1-diff-id",
   429  					},
   430  					"buildpack-1-version-2": dist.BuildpackLayerInfo{
   431  						API:         api.MustParse("0.2"),
   432  						LayerDiffID: "sha256:buildpack-1-version-2-diff-id",
   433  					},
   434  				},
   435  			}
   436  
   437  			assert.Equal(layers, expectedLayers)
   438  		})
   439  
   440  		it("requests the expected label", func() {
   441  			inspectable := newInspectable(returnForLabel(rawLayers))
   442  
   443  			labelManager := builder.NewLabelManager(inspectable)
   444  			_, err := labelManager.BuildpackLayers()
   445  			assert.Nil(err)
   446  
   447  			assert.Equal(inspectable.ReceivedName, "io.buildpacks.buildpack.layers")
   448  		})
   449  
   450  		when("inspectable return empty content for `Label`", func() {
   451  			it("returns an empty buildpack layers object", func() {
   452  				inspectable := newInspectable(returnForLabel(""))
   453  
   454  				labelManager := builder.NewLabelManager(inspectable)
   455  				layers, err := labelManager.BuildpackLayers()
   456  				assert.Nil(err)
   457  
   458  				assert.Equal(layers, dist.BuildpackLayers{})
   459  			})
   460  		})
   461  
   462  		when("inspectable returns an error for `Label`", func() {
   463  			it("returns a wrapped error", func() {
   464  				expectedError := errors.New("couldn't find label")
   465  
   466  				inspectable := newInspectable(errorForLabel(expectedError))
   467  
   468  				labelManager := builder.NewLabelManager(inspectable)
   469  				_, err := labelManager.BuildpackLayers()
   470  
   471  				assert.ErrorWithMessage(
   472  					err,
   473  					"getting label io.buildpacks.buildpack.layers: couldn't find label",
   474  				)
   475  			})
   476  		})
   477  
   478  		when("inspectable returns invalid json for `Label`", func() {
   479  			it("returns a wrapped error", func() {
   480  				inspectable := newInspectable(returnForLabel("{"))
   481  
   482  				labelManager := builder.NewLabelManager(inspectable)
   483  				_, err := labelManager.BuildpackLayers()
   484  
   485  				assert.ErrorWithMessage(
   486  					err,
   487  					"parsing label content for io.buildpacks.buildpack.layers: unexpected end of JSON input",
   488  				)
   489  			})
   490  		})
   491  	})
   492  }
   493  
   494  type inspectableModifier func(i *fakes.FakeInspectable)
   495  
   496  func returnForLabel(response string) inspectableModifier {
   497  	return func(i *fakes.FakeInspectable) {
   498  		i.ReturnForLabel = response
   499  	}
   500  }
   501  
   502  func errorForLabel(err error) inspectableModifier {
   503  	return func(i *fakes.FakeInspectable) {
   504  		i.ErrorForLabel = err
   505  	}
   506  }
   507  
   508  func newInspectable(modifiers ...inspectableModifier) *fakes.FakeInspectable {
   509  	inspectable := &fakes.FakeInspectable{}
   510  
   511  	for _, mod := range modifiers {
   512  		mod(inspectable)
   513  	}
   514  
   515  	return inspectable
   516  }