github.com/loafoe/cli@v7.1.0+incompatible/command/v7/create_buildpack_command_test.go (about) 1 package v7_test 2 3 import ( 4 "errors" 5 6 "code.cloudfoundry.org/cli/actor/actionerror" 7 "code.cloudfoundry.org/cli/actor/v7action" 8 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 9 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" 10 "code.cloudfoundry.org/cli/command/commandfakes" 11 "code.cloudfoundry.org/cli/command/flag" 12 "code.cloudfoundry.org/cli/command/translatableerror" 13 . "code.cloudfoundry.org/cli/command/v7" 14 "code.cloudfoundry.org/cli/command/v7/v7fakes" 15 "code.cloudfoundry.org/cli/types" 16 "code.cloudfoundry.org/cli/util/configv3" 17 "code.cloudfoundry.org/cli/util/ui" 18 19 . "github.com/onsi/ginkgo" 20 . "github.com/onsi/gomega" 21 . "github.com/onsi/gomega/gbytes" 22 ) 23 24 var _ = Describe("create buildpack Command", func() { 25 var ( 26 cmd CreateBuildpackCommand 27 testUI *ui.UI 28 fakeConfig *commandfakes.FakeConfig 29 fakeSharedActor *commandfakes.FakeSharedActor 30 fakeActor *v7fakes.FakeActor 31 executeErr error 32 args []string 33 binaryName string 34 buildpackName string 35 buildpackPath string 36 ) 37 38 BeforeEach(func() { 39 testUI = ui.NewTestUI(nil, NewBuffer(), NewBuffer()) 40 fakeConfig = new(commandfakes.FakeConfig) 41 fakeSharedActor = new(commandfakes.FakeSharedActor) 42 fakeActor = new(v7fakes.FakeActor) 43 args = nil 44 buildpackName = "some-buildpack" 45 buildpackPath = "/path/to/buildpack.zip" 46 47 cmd = CreateBuildpackCommand{ 48 RequiredArgs: flag.CreateBuildpackArgs{ 49 Buildpack: buildpackName, 50 Path: flag.PathWithExistenceCheckOrURL(buildpackPath), 51 Position: 7, 52 }, 53 BaseCommand: BaseCommand{ 54 UI: testUI, 55 Config: fakeConfig, 56 SharedActor: fakeSharedActor, 57 Actor: fakeActor, 58 }, 59 } 60 61 binaryName = "faceman" 62 fakeConfig.BinaryNameReturns(binaryName) 63 }) 64 65 JustBeforeEach(func() { 66 executeErr = cmd.Execute(args) 67 }) 68 69 When("the environment is not set up correctly", func() { 70 BeforeEach(func() { 71 fakeSharedActor.CheckTargetReturns(actionerror.NotLoggedInError{BinaryName: binaryName}) 72 }) 73 74 It("returns an error", func() { 75 Expect(executeErr).To(MatchError(actionerror.NotLoggedInError{BinaryName: binaryName})) 76 77 Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1)) 78 checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0) 79 Expect(checkTargetedOrg).To(BeFalse()) 80 Expect(checkTargetedSpace).To(BeFalse()) 81 }) 82 }) 83 84 When("the environment is setup correctly", func() { 85 BeforeEach(func() { 86 fakeConfig.CurrentUserReturns(configv3.User{Name: "the-user"}, nil) 87 }) 88 89 It("should print text indicating it is creating a buildpack", func() { 90 Expect(executeErr).NotTo(HaveOccurred()) 91 Expect(testUI.Out).To(Say(`Creating buildpack %s as the-user\.\.\.`, buildpackName)) 92 }) 93 94 When("preparing the buildpack bits fails", func() { 95 BeforeEach(func() { 96 fakeActor.PrepareBuildpackBitsReturns("some/invalid/path", errors.New("some-prepare-bp-error")) 97 }) 98 99 It("returns an error", func() { 100 Expect(executeErr).To(MatchError("some-prepare-bp-error")) 101 Expect(fakeActor.PrepareBuildpackBitsCallCount()).To(Equal(1)) 102 }) 103 }) 104 105 When("Preparing the buildpack bits succeeds", func() { 106 107 BeforeEach(func() { 108 fakeActor.PrepareBuildpackBitsReturns("buildpack.zip", nil) 109 }) 110 111 When("creating the buildpack fails", func() { 112 BeforeEach(func() { 113 fakeActor.CreateBuildpackReturns( 114 v7action.Buildpack{}, 115 v7action.Warnings{"warning-1"}, 116 actionerror.BuildpackNameTakenError{Name: "this-error-occurred"}, 117 ) 118 }) 119 It("errors and prints all warnings", func() { 120 Expect(executeErr).To(Equal(actionerror.BuildpackNameTakenError{Name: "this-error-occurred"})) 121 Expect(testUI.Err).To(Say("warning-1")) 122 }) 123 }) 124 125 When("The disabled flag is set", func() { 126 BeforeEach(func() { 127 cmd.Disable = true 128 buildpack := v7action.Buildpack{ 129 Name: buildpackName, 130 Enabled: types.NullBool{Value: false, IsSet: true}, 131 } 132 fakeActor.CreateBuildpackReturns(buildpack, v7action.Warnings{"some-create-warning-1"}, nil) 133 }) 134 135 It("correctly creates a disabled buildpack", func() { 136 buildpack := fakeActor.CreateBuildpackArgsForCall(0) 137 Expect(buildpack.Name).To(Equal(buildpackName)) 138 Expect(buildpack.Enabled.Value).To(BeFalse()) 139 }) 140 }) 141 142 When("creating buildpack succeeds", func() { 143 BeforeEach(func() { 144 buildpack := v7action.Buildpack{ 145 Name: buildpackName, 146 Position: types.NullInt{Value: 1, IsSet: true}, 147 Enabled: types.NullBool{Value: true, IsSet: true}, 148 Locked: types.NullBool{Value: false, IsSet: true}, 149 Filename: "buildpack-1.file", 150 Stack: "buildpack-1-stack", 151 GUID: "some-guid", 152 } 153 fakeActor.CreateBuildpackReturns(buildpack, v7action.Warnings{"some-create-warning-1"}, nil) 154 }) 155 156 It("correctly created the buildpack", func() { 157 buildpack := fakeActor.CreateBuildpackArgsForCall(0) 158 Expect(buildpack.Name).To(Equal(buildpackName)) 159 Expect(buildpack.Position.Value).To(Equal(7)) 160 }) 161 162 It("prints any warnings and uploads the bits", func() { 163 Expect(executeErr).NotTo(HaveOccurred()) 164 Expect(testUI.Out).To(Say("OK")) 165 Expect(testUI.Err).To(Say("some-create-warning-1")) 166 Expect(testUI.Out).To(Say(`Uploading buildpack %s as the-user\.\.\.`, buildpackName)) 167 }) 168 169 It("Displays it is starting the upload", func() { 170 Expect(executeErr).ToNot(HaveOccurred()) 171 Expect(testUI.Out).To(Say("Uploading buildpack %s as the-user", buildpackName)) 172 173 Expect(fakeActor.PrepareBuildpackBitsCallCount()).To(Equal(1)) 174 path, _, _ := fakeActor.PrepareBuildpackBitsArgsForCall(0) 175 Expect(path).To(Equal(buildpackPath)) 176 }) 177 178 When("uploading the buildpack fails due to an auth token expired error", func() { 179 BeforeEach(func() { 180 fakeActor.UploadBuildpackReturns( 181 ccv3.JobURL(""), 182 v7action.Warnings{"some-create-bp-with-auth-warning"}, 183 ccerror.InvalidAuthTokenError{Message: "token expired"}, 184 ) 185 }) 186 187 It("alerts the user and retries the upload", func() { 188 Expect(testUI.Err).To(Say("Failed to upload buildpack due to auth token expiration, retrying...")) 189 Expect(fakeActor.UploadBuildpackCallCount()).To(Equal(2)) 190 }) 191 }) 192 193 When("Uploading the buildpack fails due to a generic error", func() { 194 BeforeEach(func() { 195 fakeActor.UploadBuildpackReturns( 196 ccv3.JobURL(""), 197 v7action.Warnings{"warning-2"}, 198 errors.New("some-error"), 199 ) 200 }) 201 202 It("errors, prints a tip and all warnings", func() { 203 Expect(executeErr).To(MatchError(translatableerror.TipDecoratorError{ 204 BaseError: errors.New("some-error"), 205 Tip: "A buildpack with name '{{.BuildpackName}}' and nil stack has been created. Use '{{.CfDeleteBuildpackCommand}}' to delete it or '{{.CfUpdateBuildpackCommand}}' to try again.", 206 TipKeys: map[string]interface{}{ 207 "BuildpackName": cmd.RequiredArgs.Buildpack, 208 "CfDeleteBuildpackCommand": cmd.Config.BinaryName() + " delete-buildpack", 209 "CfUpdateBuildpackCommand": cmd.Config.BinaryName() + " update-buildpack", 210 }, 211 })) 212 Expect(testUI.Err).To(Say("warning-2")) 213 Expect(testUI.Out).To(Say("Uploading buildpack %s", buildpackName)) 214 Consistently(testUI.Out).ShouldNot(Say("OK")) 215 }) 216 217 }) 218 219 When("Uploading the buildpack succeeds", func() { 220 BeforeEach(func() { 221 fakeActor.UploadBuildpackReturns( 222 ccv3.JobURL("http://example.com/some-job-url"), 223 v7action.Warnings{"some-upload-warning-1"}, 224 nil, 225 ) 226 }) 227 228 It("prints all warnings", func() { 229 Expect(executeErr).NotTo(HaveOccurred()) 230 Expect(testUI.Out).To(Say("Uploading buildpack %s", buildpackName)) 231 Expect(testUI.Out).To(Say("OK")) 232 Expect(testUI.Err).To(Say("some-upload-warning-1")) 233 234 Expect(fakeActor.UploadBuildpackCallCount()).To(Equal(1)) 235 guid, path, _ := fakeActor.UploadBuildpackArgsForCall(0) 236 Expect(guid).To(Equal("some-guid")) 237 Expect(path).To(Equal("buildpack.zip")) 238 }) 239 240 Describe("polling the upload-to-blobstore job", func() { 241 It("polls for job completion/failure", func() { 242 Expect(executeErr).NotTo(HaveOccurred()) 243 Expect(testUI.Out).To(Say("Uploading buildpack %s", buildpackName)) 244 Expect(testUI.Out).To(Say("OK")) 245 246 Expect(fakeActor.PollUploadBuildpackJobCallCount()).To(Equal(1)) 247 url := fakeActor.PollUploadBuildpackJobArgsForCall(0) 248 249 Expect(url).To(Equal(ccv3.JobURL("http://example.com/some-job-url"))) 250 }) 251 252 When("the job completes successfully", func() { 253 BeforeEach(func() { 254 fakeActor.PollUploadBuildpackJobReturns(v7action.Warnings{"poll-warning"}, nil) 255 }) 256 257 It("prints all warnings and exits successfully", func() { 258 Expect(executeErr).NotTo(HaveOccurred()) 259 Expect(testUI.Out).To(Say(`Processing uploaded buildpack %s\.\.\.`, buildpackName)) 260 Expect(testUI.Out).To(Say("OK")) 261 Expect(testUI.Err).To(Say("poll-warning")) 262 }) 263 }) 264 265 When("the job fails with an error", func() { 266 BeforeEach(func() { 267 fakeActor.PollUploadBuildpackJobReturns( 268 v7action.Warnings{"poll-warning"}, 269 errors.New("some-error"), 270 ) 271 }) 272 273 It("prints all warnings and a tip, then returns the error", func() { 274 Expect(executeErr).To(MatchError(translatableerror.TipDecoratorError{ 275 BaseError: errors.New("some-error"), 276 Tip: "A buildpack with name '{{.BuildpackName}}' and nil stack has been created. Use '{{.CfDeleteBuildpackCommand}}' to delete it or '{{.CfUpdateBuildpackCommand}}' to try again.", 277 TipKeys: map[string]interface{}{ 278 "BuildpackName": cmd.RequiredArgs.Buildpack, 279 "CfDeleteBuildpackCommand": cmd.Config.BinaryName() + " delete-buildpack", 280 "CfUpdateBuildpackCommand": cmd.Config.BinaryName() + " update-buildpack", 281 }, 282 })) 283 Expect(testUI.Err).To(Say("poll-warning")) 284 Expect(testUI.Out).To(Say(`Processing uploaded buildpack %s\.\.\.`, buildpackName)) 285 Consistently(testUI.Out).ShouldNot(Say("OK")) 286 }) 287 }) 288 }) 289 }) 290 }) 291 }) 292 }) 293 })