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 }