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