github.com/liamawhite/cli-with-i18n@v6.32.1-0.20171122084555-dede0a5c3448+incompatible/command/v3/v3_stage_command_test.go (about) 1 package v3_test 2 3 import ( 4 "errors" 5 "time" 6 7 "github.com/liamawhite/cli-with-i18n/actor/sharedaction" 8 "github.com/liamawhite/cli-with-i18n/actor/v3action" 9 "github.com/liamawhite/cli-with-i18n/actor/v3action/v3actionfakes" 10 "github.com/liamawhite/cli-with-i18n/api/cloudcontroller/ccversion" 11 "github.com/liamawhite/cli-with-i18n/command/commandfakes" 12 "github.com/liamawhite/cli-with-i18n/command/flag" 13 "github.com/liamawhite/cli-with-i18n/command/translatableerror" 14 "github.com/liamawhite/cli-with-i18n/command/v3" 15 "github.com/liamawhite/cli-with-i18n/command/v3/v3fakes" 16 "github.com/liamawhite/cli-with-i18n/util/configv3" 17 "github.com/liamawhite/cli-with-i18n/util/ui" 18 . "github.com/onsi/ginkgo" 19 . "github.com/onsi/gomega" 20 . "github.com/onsi/gomega/gbytes" 21 ) 22 23 var _ = Describe("v3-stage Command", func() { 24 var ( 25 cmd v3.V3StageCommand 26 testUI *ui.UI 27 fakeConfig *commandfakes.FakeConfig 28 fakeSharedActor *commandfakes.FakeSharedActor 29 fakeActor *v3fakes.FakeV3StageActor 30 fakeNOAAClient *v3actionfakes.FakeNOAAClient 31 32 binaryName string 33 executeErr error 34 app string 35 packageGUID 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(v3fakes.FakeV3StageActor) 43 fakeNOAAClient = new(v3actionfakes.FakeNOAAClient) 44 45 fakeConfig.StagingTimeoutReturns(10 * time.Minute) 46 47 binaryName = "faceman" 48 fakeConfig.BinaryNameReturns(binaryName) 49 app = "some-app" 50 packageGUID = "some-package-guid" 51 52 cmd = v3.V3StageCommand{ 53 RequiredArgs: flag.AppName{AppName: app}, 54 PackageGUID: packageGUID, 55 56 UI: testUI, 57 Config: fakeConfig, 58 SharedActor: fakeSharedActor, 59 Actor: fakeActor, 60 NOAAClient: fakeNOAAClient, 61 } 62 63 fakeActor.CloudControllerAPIVersionReturns(ccversion.MinVersionV3) 64 }) 65 66 JustBeforeEach(func() { 67 executeErr = cmd.Execute(nil) 68 }) 69 70 Context("when the API version is below the minimum", func() { 71 BeforeEach(func() { 72 fakeActor.CloudControllerAPIVersionReturns("0.0.0") 73 }) 74 75 It("returns a MinimumAPIVersionNotMetError", func() { 76 Expect(executeErr).To(MatchError(translatableerror.MinimumAPIVersionNotMetError{ 77 CurrentVersion: "0.0.0", 78 MinimumVersion: ccversion.MinVersionV3, 79 })) 80 }) 81 }) 82 83 Context("when checking target fails", func() { 84 BeforeEach(func() { 85 fakeSharedActor.CheckTargetReturns(sharedaction.NotLoggedInError{BinaryName: binaryName}) 86 }) 87 88 It("returns an error", func() { 89 Expect(executeErr).To(MatchError(translatableerror.NotLoggedInError{BinaryName: binaryName})) 90 91 Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1)) 92 _, checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0) 93 Expect(checkTargetedOrg).To(BeTrue()) 94 Expect(checkTargetedSpace).To(BeTrue()) 95 }) 96 }) 97 98 Context("when the user is logged in", func() { 99 BeforeEach(func() { 100 fakeConfig.HasTargetedOrganizationReturns(true) 101 fakeConfig.TargetedOrganizationReturns(configv3.Organization{ 102 GUID: "some-org-guid", 103 Name: "some-org", 104 }) 105 fakeConfig.HasTargetedSpaceReturns(true) 106 fakeConfig.TargetedSpaceReturns(configv3.Space{ 107 GUID: "some-space-guid", 108 Name: "some-space", 109 }) 110 fakeConfig.CurrentUserReturns(configv3.User{Name: "steve"}, nil) 111 }) 112 113 Context("when the logging does not error", func() { 114 var allLogsWritten chan bool 115 116 BeforeEach(func() { 117 allLogsWritten = make(chan bool) 118 fakeActor.GetStreamingLogsForApplicationByNameAndSpaceStub = func(appName string, spaceGUID string, client v3action.NOAAClient) (<-chan *v3action.LogMessage, <-chan error, v3action.Warnings, error) { 119 logStream := make(chan *v3action.LogMessage) 120 errorStream := make(chan error) 121 122 go func() { 123 logStream <- v3action.NewLogMessage("Here are some staging logs!", 1, time.Now(), v3action.StagingLog, "sourceInstance") 124 logStream <- v3action.NewLogMessage("Here are some other staging logs!", 1, time.Now(), v3action.StagingLog, "sourceInstance") 125 allLogsWritten <- true 126 }() 127 128 return logStream, errorStream, v3action.Warnings{"steve for all I care"}, nil 129 } 130 }) 131 132 Context("when the staging is successful", func() { 133 const dropletCreateTime = "2017-08-14T21:16:42Z" 134 135 BeforeEach(func() { 136 fakeActor.StagePackageStub = func(packageGUID string, _ string) (<-chan v3action.Droplet, <-chan v3action.Warnings, <-chan error) { 137 dropletStream := make(chan v3action.Droplet) 138 warningsStream := make(chan v3action.Warnings) 139 errorStream := make(chan error) 140 141 go func() { 142 <-allLogsWritten 143 defer close(dropletStream) 144 defer close(warningsStream) 145 defer close(errorStream) 146 warningsStream <- v3action.Warnings{"some-warning", "some-other-warning"} 147 dropletStream <- v3action.Droplet{ 148 GUID: "some-droplet-guid", 149 CreatedAt: dropletCreateTime, 150 State: v3action.DropletStateStaged, 151 } 152 }() 153 154 return dropletStream, warningsStream, errorStream 155 } 156 }) 157 158 It("outputs the droplet GUID", func() { 159 Expect(executeErr).ToNot(HaveOccurred()) 160 161 createdAtTimeParsed, err := time.Parse(time.RFC3339, dropletCreateTime) 162 Expect(err).ToNot(HaveOccurred()) 163 164 Expect(testUI.Out).To(Say("Staging package for %s in org some-org / space some-space as steve...", app)) 165 Expect(testUI.Out).To(Say("\n\n")) 166 Expect(testUI.Out).To(Say("Package staged")) 167 Expect(testUI.Out).To(Say("droplet guid:\\s+some-droplet-guid")) 168 Expect(testUI.Out).To(Say("state:\\s+staged")) 169 Expect(testUI.Out).To(Say("created:\\s+%s", testUI.UserFriendlyDate(createdAtTimeParsed))) 170 171 Expect(testUI.Err).To(Say("some-warning")) 172 Expect(testUI.Err).To(Say("some-other-warning")) 173 }) 174 175 It("stages the package", func() { 176 Expect(executeErr).ToNot(HaveOccurred()) 177 Expect(fakeActor.StagePackageCallCount()).To(Equal(1)) 178 guidArg, _ := fakeActor.StagePackageArgsForCall(0) 179 Expect(guidArg).To(Equal(packageGUID)) 180 }) 181 182 It("displays staging logs and their warnings", func() { 183 Expect(testUI.Out).To(Say("Here are some staging logs!")) 184 Expect(testUI.Out).To(Say("Here are some other staging logs!")) 185 186 Expect(testUI.Err).To(Say("steve for all I care")) 187 188 Expect(fakeActor.GetStreamingLogsForApplicationByNameAndSpaceCallCount()).To(Equal(1)) 189 appName, spaceGUID, noaaClient := fakeActor.GetStreamingLogsForApplicationByNameAndSpaceArgsForCall(0) 190 Expect(appName).To(Equal(app)) 191 Expect(spaceGUID).To(Equal("some-space-guid")) 192 Expect(noaaClient).To(Equal(fakeNOAAClient)) 193 194 Expect(fakeActor.StagePackageCallCount()).To(Equal(1)) 195 guidArg, _ := fakeActor.StagePackageArgsForCall(0) 196 Expect(guidArg).To(Equal(packageGUID)) 197 }) 198 }) 199 200 Context("when the staging returns an error", func() { 201 var expectedErr error 202 203 BeforeEach(func() { 204 expectedErr = errors.New("any gibberish") 205 fakeActor.StagePackageStub = func(packageGUID string, _ string) (<-chan v3action.Droplet, <-chan v3action.Warnings, <-chan error) { 206 dropletStream := make(chan v3action.Droplet) 207 warningsStream := make(chan v3action.Warnings) 208 errorStream := make(chan error) 209 210 go func() { 211 <-allLogsWritten 212 defer close(dropletStream) 213 defer close(warningsStream) 214 defer close(errorStream) 215 warningsStream <- v3action.Warnings{"some-warning", "some-other-warning"} 216 errorStream <- expectedErr 217 }() 218 219 return dropletStream, warningsStream, errorStream 220 } 221 }) 222 223 It("returns the error and displays warnings", func() { 224 Expect(executeErr).To(Equal(expectedErr)) 225 226 Expect(testUI.Err).To(Say("some-warning")) 227 Expect(testUI.Err).To(Say("some-other-warning")) 228 }) 229 }) 230 }) 231 232 Context("when the logging stream has errors", func() { 233 var ( 234 expectedErr error 235 allLogsWritten chan bool 236 ) 237 238 BeforeEach(func() { 239 allLogsWritten = make(chan bool) 240 expectedErr = errors.New("banana") 241 242 fakeActor.GetStreamingLogsForApplicationByNameAndSpaceStub = func(appName string, spaceGUID string, client v3action.NOAAClient) (<-chan *v3action.LogMessage, <-chan error, v3action.Warnings, error) { 243 logStream := make(chan *v3action.LogMessage) 244 errorStream := make(chan error) 245 246 go func() { 247 defer close(logStream) 248 defer close(errorStream) 249 logStream <- v3action.NewLogMessage("Here are some staging logs!", 1, time.Now(), v3action.StagingLog, "sourceInstance") 250 errorStream <- expectedErr 251 allLogsWritten <- true 252 }() 253 254 return logStream, errorStream, v3action.Warnings{"steve for all I care"}, nil 255 } 256 257 fakeActor.StagePackageStub = func(packageGUID string, _ string) (<-chan v3action.Droplet, <-chan v3action.Warnings, <-chan error) { 258 dropletStream := make(chan v3action.Droplet) 259 warningsStream := make(chan v3action.Warnings) 260 errorStream := make(chan error) 261 262 go func() { 263 <-allLogsWritten 264 defer close(dropletStream) 265 defer close(warningsStream) 266 defer close(errorStream) 267 warningsStream <- v3action.Warnings{"some-warning", "some-other-warning"} 268 dropletStream <- v3action.Droplet{ 269 GUID: "some-droplet-guid", 270 CreatedAt: "2017-08-14T21:16:42Z", 271 State: v3action.DropletStateStaged, 272 } 273 }() 274 275 return dropletStream, warningsStream, errorStream 276 } 277 }) 278 279 It("displays the errors and continues staging", func() { 280 Expect(executeErr).ToNot(HaveOccurred()) 281 282 Expect(testUI.Err).To(Say("banana")) 283 Expect(testUI.Err).To(Say("some-warning")) 284 Expect(testUI.Err).To(Say("some-other-warning")) 285 }) 286 }) 287 288 Context("when the logging returns an error due to an API error", func() { 289 var expectedErr error 290 291 BeforeEach(func() { 292 expectedErr = errors.New("something is wrong!") 293 logStream := make(chan *v3action.LogMessage) 294 errorStream := make(chan error) 295 fakeActor.GetStreamingLogsForApplicationByNameAndSpaceReturns(logStream, errorStream, v3action.Warnings{"some-warning", "some-other-warning"}, expectedErr) 296 }) 297 298 It("returns the error and displays warnings", func() { 299 Expect(executeErr).To(Equal(expectedErr)) 300 301 Expect(testUI.Err).To(Say("some-warning")) 302 Expect(testUI.Err).To(Say("some-other-warning")) 303 }) 304 }) 305 }) 306 })