github.com/buildpacks/pack@v0.33.3-0.20240516162812-884dd1837311/internal/commands/package_buildpack_test.go (about)

     1  package commands_test
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"testing"
     7  
     8  	"github.com/heroku/color"
     9  	"github.com/pkg/errors"
    10  	"github.com/sclevine/spec"
    11  	"github.com/sclevine/spec/report"
    12  	"github.com/spf13/cobra"
    13  
    14  	pubbldpkg "github.com/buildpacks/pack/buildpackage"
    15  	"github.com/buildpacks/pack/internal/commands"
    16  	"github.com/buildpacks/pack/internal/commands/fakes"
    17  	"github.com/buildpacks/pack/internal/config"
    18  	"github.com/buildpacks/pack/pkg/dist"
    19  	"github.com/buildpacks/pack/pkg/image"
    20  	"github.com/buildpacks/pack/pkg/logging"
    21  	h "github.com/buildpacks/pack/testhelpers"
    22  )
    23  
    24  func TestPackageBuildpackCommand(t *testing.T) {
    25  	color.Disable(true)
    26  	defer color.Disable(false)
    27  	spec.Run(t, "PackageBuildpackCommand", testPackageBuildpackCommand, spec.Parallel(), spec.Report(report.Terminal{}))
    28  }
    29  
    30  func testPackageBuildpackCommand(t *testing.T, when spec.G, it spec.S) {
    31  	when("PackageBuildpack#Execute", func() {
    32  		when("valid package config", func() {
    33  			it("prints deprecation warning", func() {
    34  				var outBuf bytes.Buffer
    35  				logger := logging.NewLogWithWriters(&outBuf, &outBuf)
    36  				cmd := packageBuildpackCommand(withLogger(logger))
    37  				h.AssertNil(t, cmd.Execute())
    38  				h.AssertContains(t, outBuf.String(), "Warning: Command 'pack package-buildpack' has been deprecated, please use 'pack buildpack package' instead")
    39  			})
    40  
    41  			it("reads package config from the configured path", func() {
    42  				fakePackageConfigReader := fakes.NewFakePackageConfigReader()
    43  				expectedPackageConfigPath := "/path/to/some/file"
    44  
    45  				packageBuildpackCommand := packageBuildpackCommand(
    46  					withPackageConfigReader(fakePackageConfigReader),
    47  					withPackageConfigPath(expectedPackageConfigPath),
    48  				)
    49  
    50  				err := packageBuildpackCommand.Execute()
    51  				h.AssertNil(t, err)
    52  
    53  				h.AssertEq(t, fakePackageConfigReader.ReadCalledWithArg, expectedPackageConfigPath)
    54  			})
    55  
    56  			it("creates package with correct image name", func() {
    57  				fakeBuildpackPackager := &fakes.FakeBuildpackPackager{}
    58  
    59  				packageBuildpackCommand := packageBuildpackCommand(
    60  					withImageName("my-specific-image"),
    61  					withBuildpackPackager(fakeBuildpackPackager),
    62  				)
    63  
    64  				err := packageBuildpackCommand.Execute()
    65  				h.AssertNil(t, err)
    66  
    67  				receivedOptions := fakeBuildpackPackager.CreateCalledWithOptions
    68  
    69  				h.AssertEq(t, receivedOptions.Name, "my-specific-image")
    70  			})
    71  
    72  			it("creates package with config returned by the reader", func() {
    73  				fakeBuildpackPackager := &fakes.FakeBuildpackPackager{}
    74  
    75  				myConfig := pubbldpkg.Config{
    76  					Buildpack: dist.BuildpackURI{URI: "test"},
    77  				}
    78  
    79  				packageBuildpackCommand := packageBuildpackCommand(
    80  					withBuildpackPackager(fakeBuildpackPackager),
    81  					withPackageConfigReader(fakes.NewFakePackageConfigReader(whereReadReturns(myConfig, nil))),
    82  				)
    83  
    84  				err := packageBuildpackCommand.Execute()
    85  				h.AssertNil(t, err)
    86  
    87  				receivedOptions := fakeBuildpackPackager.CreateCalledWithOptions
    88  
    89  				h.AssertEq(t, receivedOptions.Config, myConfig)
    90  			})
    91  
    92  			when("pull-policy", func() {
    93  				var (
    94  					outBuf                bytes.Buffer
    95  					cmd                   *cobra.Command
    96  					args                  []string
    97  					fakeBuildpackPackager *fakes.FakeBuildpackPackager
    98  				)
    99  
   100  				it.Before(func() {
   101  					logger := logging.NewLogWithWriters(&outBuf, &outBuf)
   102  					fakeBuildpackPackager = &fakes.FakeBuildpackPackager{}
   103  
   104  					cmd = packageBuildpackCommand(withLogger(logger), withBuildpackPackager(fakeBuildpackPackager))
   105  					args = []string{
   106  						"some-image-name",
   107  						"--config", "/path/to/some/file",
   108  					}
   109  				})
   110  
   111  				it("pull-policy=never sets policy", func() {
   112  					args = append(args, "--pull-policy", "never")
   113  					cmd.SetArgs(args)
   114  
   115  					err := cmd.Execute()
   116  					h.AssertNil(t, err)
   117  
   118  					receivedOptions := fakeBuildpackPackager.CreateCalledWithOptions
   119  					h.AssertEq(t, receivedOptions.PullPolicy, image.PullNever)
   120  				})
   121  
   122  				it("pull-policy=always sets policy", func() {
   123  					args = append(args, "--pull-policy", "always")
   124  					cmd.SetArgs(args)
   125  
   126  					err := cmd.Execute()
   127  					h.AssertNil(t, err)
   128  
   129  					receivedOptions := fakeBuildpackPackager.CreateCalledWithOptions
   130  					h.AssertEq(t, receivedOptions.PullPolicy, image.PullAlways)
   131  				})
   132  				it("takes precedence over a configured pull policy", func() {
   133  					logger := logging.NewLogWithWriters(&bytes.Buffer{}, &bytes.Buffer{})
   134  					configReader := fakes.NewFakePackageConfigReader()
   135  					buildpackPackager := &fakes.FakeBuildpackPackager{}
   136  					clientConfig := config.Config{PullPolicy: "if-not-present"}
   137  
   138  					command := commands.PackageBuildpack(logger, clientConfig, buildpackPackager, configReader)
   139  					command.SetArgs([]string{
   140  						"some-image-name",
   141  						"--config", "/path/to/some/file",
   142  						"--pull-policy",
   143  						"never",
   144  					})
   145  
   146  					err := command.Execute()
   147  					h.AssertNil(t, err)
   148  
   149  					receivedOptions := buildpackPackager.CreateCalledWithOptions
   150  					h.AssertEq(t, receivedOptions.PullPolicy, image.PullNever)
   151  				})
   152  			})
   153  			when("configured pull policy", func() {
   154  				it("uses the configured pull policy", func() {
   155  					logger := logging.NewLogWithWriters(&bytes.Buffer{}, &bytes.Buffer{})
   156  					configReader := fakes.NewFakePackageConfigReader()
   157  					buildpackPackager := &fakes.FakeBuildpackPackager{}
   158  					clientConfig := config.Config{PullPolicy: "never"}
   159  
   160  					command := commands.PackageBuildpack(logger, clientConfig, buildpackPackager, configReader)
   161  					command.SetArgs([]string{
   162  						"some-image-name",
   163  						"--config", "/path/to/some/file",
   164  					})
   165  
   166  					err := command.Execute()
   167  					h.AssertNil(t, err)
   168  
   169  					receivedOptions := buildpackPackager.CreateCalledWithOptions
   170  					h.AssertEq(t, receivedOptions.PullPolicy, image.PullNever)
   171  				})
   172  			})
   173  		})
   174  	})
   175  
   176  	when("invalid flags", func() {
   177  		when("both --publish and --pull-policy never flags are specified", func() {
   178  			it("errors with a descriptive message", func() {
   179  				logger := logging.NewLogWithWriters(&bytes.Buffer{}, &bytes.Buffer{})
   180  				configReader := fakes.NewFakePackageConfigReader()
   181  				buildpackPackager := &fakes.FakeBuildpackPackager{}
   182  				clientConfig := config.Config{}
   183  
   184  				command := commands.PackageBuildpack(logger, clientConfig, buildpackPackager, configReader)
   185  				command.SetArgs([]string{
   186  					"some-image-name",
   187  					"--config", "/path/to/some/file",
   188  					"--publish",
   189  					"--pull-policy",
   190  					"never",
   191  				})
   192  
   193  				err := command.Execute()
   194  				h.AssertNotNil(t, err)
   195  				h.AssertError(t, err, "--publish and --pull-policy never cannot be used together. The --publish flag requires the use of remote images.")
   196  			})
   197  		})
   198  
   199  		it("logs an error and exits when package toml is invalid", func() {
   200  			outBuf := &bytes.Buffer{}
   201  			expectedErr := errors.New("it went wrong")
   202  
   203  			packageBuildpackCommand := packageBuildpackCommand(
   204  				withLogger(logging.NewLogWithWriters(outBuf, outBuf)),
   205  				withPackageConfigReader(
   206  					fakes.NewFakePackageConfigReader(whereReadReturns(pubbldpkg.Config{}, expectedErr)),
   207  				),
   208  			)
   209  
   210  			err := packageBuildpackCommand.Execute()
   211  			h.AssertNotNil(t, err)
   212  
   213  			h.AssertContains(t, outBuf.String(), fmt.Sprintf("ERROR: reading config: %s", expectedErr))
   214  		})
   215  
   216  		when("package-config is specified", func() {
   217  			it("errors with a descriptive message", func() {
   218  				outBuf := &bytes.Buffer{}
   219  
   220  				config := &packageCommandConfig{
   221  					logger:              logging.NewLogWithWriters(outBuf, outBuf),
   222  					packageConfigReader: fakes.NewFakePackageConfigReader(),
   223  					buildpackPackager:   &fakes.FakeBuildpackPackager{},
   224  
   225  					imageName:  "some-image-name",
   226  					configPath: "/path/to/some/file",
   227  				}
   228  
   229  				cmd := commands.PackageBuildpack(config.logger, config.clientConfig, config.buildpackPackager, config.packageConfigReader)
   230  				cmd.SetArgs([]string{config.imageName, "--package-config", config.configPath})
   231  
   232  				err := cmd.Execute()
   233  				h.AssertError(t, err, "unknown flag: --package-config")
   234  			})
   235  		})
   236  
   237  		when("no config path is specified", func() {
   238  			it("creates a default config", func() {
   239  				config := &packageCommandConfig{
   240  					logger:              logging.NewLogWithWriters(&bytes.Buffer{}, &bytes.Buffer{}),
   241  					packageConfigReader: fakes.NewFakePackageConfigReader(),
   242  					buildpackPackager:   &fakes.FakeBuildpackPackager{},
   243  
   244  					imageName: "some-image-name",
   245  				}
   246  
   247  				cmd := commands.PackageBuildpack(config.logger, config.clientConfig, config.buildpackPackager, config.packageConfigReader)
   248  				cmd.SetArgs([]string{config.imageName})
   249  
   250  				err := cmd.Execute()
   251  				h.AssertNil(t, err)
   252  
   253  				receivedOptions := config.buildpackPackager.CreateCalledWithOptions
   254  				h.AssertEq(t, receivedOptions.Config.Buildpack.URI, ".")
   255  			})
   256  		})
   257  
   258  		when("--pull-policy unknown-policy", func() {
   259  			it("fails to run", func() {
   260  				logger := logging.NewLogWithWriters(&bytes.Buffer{}, &bytes.Buffer{})
   261  				configReader := fakes.NewFakePackageConfigReader()
   262  				buildpackPackager := &fakes.FakeBuildpackPackager{}
   263  				clientConfig := config.Config{}
   264  
   265  				command := commands.PackageBuildpack(logger, clientConfig, buildpackPackager, configReader)
   266  				command.SetArgs([]string{
   267  					"some-image-name",
   268  					"--config", "/path/to/some/file",
   269  					"--pull-policy",
   270  					"unknown-policy",
   271  				})
   272  
   273  				h.AssertError(t, command.Execute(), "parsing pull policy")
   274  			})
   275  		})
   276  	})
   277  }
   278  
   279  func packageBuildpackCommand(ops ...packageCommandOption) *cobra.Command {
   280  	config := &packageCommandConfig{
   281  		logger:              logging.NewLogWithWriters(&bytes.Buffer{}, &bytes.Buffer{}),
   282  		packageConfigReader: fakes.NewFakePackageConfigReader(),
   283  		buildpackPackager:   &fakes.FakeBuildpackPackager{},
   284  		clientConfig:        config.Config{},
   285  
   286  		imageName:  "some-image-name",
   287  		configPath: "/path/to/some/file",
   288  	}
   289  
   290  	for _, op := range ops {
   291  		op(config)
   292  	}
   293  
   294  	cmd := commands.PackageBuildpack(config.logger, config.clientConfig, config.buildpackPackager, config.packageConfigReader)
   295  	cmd.SetArgs([]string{config.imageName, "--config", config.configPath})
   296  
   297  	return cmd
   298  }