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