github.com/randomtask1155/cli@v6.41.1-0.20181227003417-a98eed78cbde+incompatible/command/translatableerror/convert_to_translatable_error_test.go (about) 1 package translatableerror_test 2 3 import ( 4 "encoding/json" 5 "errors" 6 "time" 7 8 "code.cloudfoundry.org/cli/actor/actionerror" 9 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 10 "code.cloudfoundry.org/cli/api/plugin/pluginerror" 11 "code.cloudfoundry.org/cli/api/uaa" 12 . "code.cloudfoundry.org/cli/command/translatableerror" 13 "code.cloudfoundry.org/cli/util/clissh/ssherror" 14 "code.cloudfoundry.org/cli/util/download" 15 "code.cloudfoundry.org/cli/util/manifest" 16 . "github.com/onsi/ginkgo" 17 . "github.com/onsi/ginkgo/extensions/table" 18 . "github.com/onsi/gomega" 19 ) 20 21 var _ = Describe("ConvertToTranslatableError", func() { 22 err := errors.New("some-error") 23 genericErr := errors.New("some-generic-error") 24 jsonErr := new(json.SyntaxError) 25 unprocessableEntityError := ccerror.UnprocessableEntityError{Message: "another message"} 26 27 DescribeTable("error translations", 28 func(passedInErr error, expectedErr error) { 29 actualErr := ConvertToTranslatableError(passedInErr) 30 Expect(actualErr).To(MatchError(expectedErr)) 31 }, 32 33 // Action Errors 34 Entry("actionerror.AddPluginRepositoryError -> AddPluginRepositoryError", 35 actionerror.AddPluginRepositoryError{Name: "some-repo", URL: "some-URL", Message: "404"}, 36 AddPluginRepositoryError{Name: "some-repo", URL: "some-URL", Message: "404"}), 37 38 Entry("actionerror.ApplicationNotFoundError -> ApplicationNotFoundError", 39 actionerror.ApplicationNotFoundError{Name: "some-app"}, 40 ApplicationNotFoundError{Name: "some-app"}), 41 42 Entry("actionerror.ApplicationNotStartedError -> ApplicationNotStartedError", 43 actionerror.ApplicationNotStartedError{Name: "some-app"}, 44 ApplicationNotStartedError{Name: "some-app"}), 45 46 Entry("actionerror.AppNotFoundInManifestError -> AppNotFoundInManifestError", 47 actionerror.AppNotFoundInManifestError{Name: "some-app"}, 48 AppNotFoundInManifestError{Name: "some-app"}), 49 50 Entry("actionerror.AssignDropletError -> AssignDropletError", 51 actionerror.AssignDropletError{Message: "some-message"}, 52 AssignDropletError{Message: "some-message"}), 53 54 Entry("actionerror.ServicePlanNotFoundError -> ServicePlanNotFoundError", 55 actionerror.ServicePlanNotFoundError{PlanName: "some-plan", ServiceName: "some-service"}, 56 ServicePlanNotFoundError{PlanName: "some-plan", ServiceName: "some-service"}), 57 58 Entry("actionerror.BuildpackNotFoundError -> BuildpackNotFoundError", 59 actionerror.BuildpackNotFoundError{}, 60 BuildpackNotFoundError{}), 61 62 Entry("actionerror.BuildpackStackChangeError-> BuildpackStackChangeError", 63 actionerror.BuildpackStackChangeError{}, 64 BuildpackStackChangeError{}), 65 66 Entry("actionerror.CommandLineOptionsWithMultipleAppsError -> CommandLineArgsWithMultipleAppsError", 67 actionerror.CommandLineOptionsWithMultipleAppsError{}, 68 CommandLineArgsWithMultipleAppsError{}), 69 70 Entry("actionerror.DockerPasswordNotSetError -> DockerPasswordNotSetError", 71 actionerror.DockerPasswordNotSetError{}, 72 DockerPasswordNotSetError{}), 73 74 Entry("actionerror.DomainNotFoundError -> DomainNotFoundError", 75 actionerror.DomainNotFoundError{Name: "some-domain-name", GUID: "some-domain-guid"}, 76 DomainNotFoundError{Name: "some-domain-name", GUID: "some-domain-guid"}), 77 78 Entry("actionerror.EmptyBuildpacksError -> EmptyBuildpacksError", 79 manifest.EmptyBuildpacksError{}, 80 EmptyBuildpacksError{}, 81 ), 82 83 Entry("actionerror.EmptyDirectoryError -> EmptyDirectoryError", 84 actionerror.EmptyDirectoryError{Path: "some-filename"}, 85 EmptyDirectoryError{Path: "some-filename"}), 86 87 Entry("actionerror.EmptyBuildpackDirectoryError -> EmptyBuildpackDirectoryError", 88 actionerror.EmptyBuildpackDirectoryError{Path: "some-path"}, 89 EmptyBuildpackDirectoryError{Path: "some-path"}), 90 91 Entry("actionerror.FileChangedError -> FileChangedError", 92 actionerror.FileChangedError{Filename: "some-filename"}, 93 FileChangedError{Filename: "some-filename"}), 94 95 Entry("actionerror.GettingPluginRepositoryError -> GettingPluginRepositoryError", 96 actionerror.GettingPluginRepositoryError{Name: "some-repo", Message: "404"}, 97 GettingPluginRepositoryError{Name: "some-repo", Message: "404"}), 98 99 Entry("actionerror.HostnameWithTCPDomainError -> HostnameWithTCPDomainError", 100 actionerror.HostnameWithTCPDomainError{}, 101 HostnameWithTCPDomainError{}), 102 103 Entry("actionerror.HTTPHealthCheckInvalidError -> HTTPHealthCheckInvalidError", 104 actionerror.HTTPHealthCheckInvalidError{}, 105 HTTPHealthCheckInvalidError{}), 106 107 Entry("actionerror.InvalidBuildpacksError -> InvalidBuildpacksError", 108 actionerror.InvalidBuildpacksError{}, 109 InvalidBuildpacksError{}), 110 111 Entry("actionerror.InvalidHTTPRouteSettings -> PortNotAllowedWithHTTPDomainError", 112 actionerror.InvalidHTTPRouteSettings{Domain: "some-domain"}, 113 PortNotAllowedWithHTTPDomainError{Domain: "some-domain"}), 114 115 Entry("actionerror.InvalidRouteError -> InvalidRouteError", 116 actionerror.InvalidRouteError{Route: "some-invalid-route"}, 117 InvalidRouteError{Route: "some-invalid-route"}), 118 119 Entry("actionerror.InvalidTCPRouteSettings -> HostAndPathNotAllowedWithTCPDomainError", 120 actionerror.InvalidTCPRouteSettings{Domain: "some-domain"}, 121 HostAndPathNotAllowedWithTCPDomainError{Domain: "some-domain"}), 122 123 Entry("actionerror.MissingNameError -> RequiredNameForPushError", 124 actionerror.MissingNameError{}, 125 RequiredNameForPushError{}), 126 127 Entry("actionerror.MultipleBuildpacksFoundError -> MultipleBuildpacksFoundError", 128 actionerror.MultipleBuildpacksFoundError{BuildpackName: "some-bp-name"}, 129 MultipleBuildpacksFoundError{BuildpackName: "some-bp-name"}), 130 131 Entry("actionerror.NoCompatibleBinaryError -> NoCompatibleBinaryError", 132 actionerror.NoCompatibleBinaryError{}, 133 NoCompatibleBinaryError{}), 134 135 Entry("actionerror.NoDomainsFoundError -> NoDomainsFoundError", 136 actionerror.NoDomainsFoundError{OrganizationGUID: "some-guid"}, 137 NoDomainsFoundError{}), 138 139 Entry("actionerror.NoHostnameAndSharedDomainError -> NoHostnameAndSharedDomainError", 140 actionerror.NoHostnameAndSharedDomainError{}, 141 NoHostnameAndSharedDomainError{}), 142 143 Entry("actionerror.NoMatchingDomainError -> NoMatchingDomainError", 144 actionerror.NoMatchingDomainError{Route: "some-route.com"}, 145 NoMatchingDomainError{Route: "some-route.com"}), 146 147 Entry("actionerror.NonexistentAppPathError -> FileNotFoundError", 148 actionerror.NonexistentAppPathError{Path: "some-path"}, 149 FileNotFoundError{Path: "some-path"}), 150 151 Entry("actionerror.NoOrganizationTargetedError -> NoOrganizationTargetedError", 152 actionerror.NoOrganizationTargetedError{BinaryName: "faceman"}, 153 NoOrganizationTargetedError{BinaryName: "faceman"}), 154 155 Entry("actionerror.NoSpaceTargetedError -> NoSpaceTargetedError", 156 actionerror.NoSpaceTargetedError{BinaryName: "faceman"}, 157 NoSpaceTargetedError{BinaryName: "faceman"}), 158 159 Entry("actionerror.NotLoggedInError -> NotLoggedInError", 160 actionerror.NotLoggedInError{BinaryName: "faceman"}, 161 NotLoggedInError{BinaryName: "faceman"}), 162 163 Entry("actionerror.OrganizationNotFoundError -> OrgNotFoundError", 164 actionerror.OrganizationNotFoundError{Name: "some-org"}, 165 OrganizationNotFoundError{Name: "some-org"}), 166 167 Entry("actionerror.OrganizationQuotaNotFoundForNameError -> OrganizationQuotaNotFoundForNameError", 168 actionerror.OrganizationQuotaNotFoundForNameError{Name: "some-quota"}, 169 OrganizationQuotaNotFoundForNameError{Name: "some-quota"}), 170 171 Entry("actionerror.PasswordGrantTypeLogoutRequiredError -> PasswordGrantTypeLogoutRequiredError", 172 actionerror.PasswordGrantTypeLogoutRequiredError{}, 173 PasswordGrantTypeLogoutRequiredError{}), 174 175 Entry("actionerror.PluginCommandConflictError -> PluginCommandConflictError", 176 actionerror.PluginCommandsConflictError{ 177 PluginName: "some-plugin", 178 PluginVersion: "1.1.1", 179 CommandNames: []string{"some-command", "some-other-command"}, 180 CommandAliases: []string{"sc", "soc"}, 181 }, 182 PluginCommandsConflictError{ 183 PluginName: "some-plugin", 184 PluginVersion: "1.1.1", 185 CommandNames: []string{"some-command", "some-other-command"}, 186 CommandAliases: []string{"sc", "soc"}, 187 }), 188 189 Entry("actionerror.PluginInvalidError -> PluginInvalidError", 190 actionerror.PluginInvalidError{}, 191 PluginInvalidError{}), 192 193 Entry("actionerror.PluginInvalidError -> PluginInvalidError", 194 actionerror.PluginInvalidError{Err: genericErr}, 195 PluginInvalidError{Err: genericErr}), 196 197 Entry("actionerror.PluginNotFoundError -> PluginNotFoundError", 198 actionerror.PluginNotFoundError{PluginName: "some-plugin"}, 199 PluginNotFoundError{PluginName: "some-plugin"}), 200 201 Entry("actionerror.ProcessInstanceNotFoundError -> ProcessInstanceNotFoundError", 202 actionerror.ProcessInstanceNotFoundError{ProcessType: "some-process-type", InstanceIndex: 42}, 203 ProcessInstanceNotFoundError{ProcessType: "some-process-type", InstanceIndex: 42}), 204 205 Entry("actionerror.ProcessInstanceNotRunningError -> ProcessInstanceNotRunningError", 206 actionerror.ProcessInstanceNotRunningError{ProcessType: "some-process-type", InstanceIndex: 42}, 207 ProcessInstanceNotRunningError{ProcessType: "some-process-type", InstanceIndex: 42}), 208 209 Entry("actionerror.ProcessNotFoundError -> ProcessNotFoundError", 210 actionerror.ProcessNotFoundError{ProcessType: "some-process-type"}, 211 ProcessNotFoundError{ProcessType: "some-process-type"}), 212 213 Entry("actionerror.PropertyCombinationError -> PropertyCombinationError", 214 actionerror.PropertyCombinationError{Properties: []string{"property-1", "property-2"}}, 215 PropertyCombinationError{Properties: []string{"property-1", "property-2"}}), 216 217 Entry("actionerror.RepositoryNameTakenError -> RepositoryNameTakenError", 218 actionerror.RepositoryNameTakenError{Name: "some-repo"}, 219 RepositoryNameTakenError{Name: "some-repo"}), 220 221 Entry("actionerror.RepositoryNotRegisteredError -> RepositoryNotRegisteredError", 222 actionerror.RepositoryNotRegisteredError{Name: "some-repo"}, 223 RepositoryNotRegisteredError{Name: "some-repo"}), 224 225 Entry("actionerror.RouteInDifferentSpaceError -> RouteInDifferentSpaceError", 226 actionerror.RouteInDifferentSpaceError{Route: "some-route"}, 227 RouteInDifferentSpaceError{Route: "some-route"}), 228 229 Entry("actionerror.RoutePathWithTCPDomainError -> RoutePathWithTCPDomainError", 230 actionerror.RoutePathWithTCPDomainError{}, 231 RoutePathWithTCPDomainError{}), 232 233 Entry("actionerror.RouterGroupNotFoundError -> RouterGroupNotFoundError", 234 actionerror.RouterGroupNotFoundError{Name: "some-group"}, 235 RouterGroupNotFoundError{Name: "some-group"}, 236 ), 237 238 Entry("actionerror.SecurityGroupNotFoundError -> SecurityGroupNotFoundError", 239 actionerror.SecurityGroupNotFoundError{Name: "some-security-group"}, 240 SecurityGroupNotFoundError{Name: "some-security-group"}), 241 242 Entry("actionerror.ServiceInstanceNotFoundError -> ServiceInstanceNotFoundError", 243 actionerror.ServiceInstanceNotFoundError{Name: "some-service-instance"}, 244 ServiceInstanceNotFoundError{Name: "some-service-instance"}), 245 246 Entry("actionerror.ServiceInstanceNotShareableError -> ServiceInstanceNotShareableError", 247 actionerror.ServiceInstanceNotShareableError{ 248 FeatureFlagEnabled: true, 249 ServiceBrokerSharingEnabled: false}, 250 ServiceInstanceNotShareableError{ 251 FeatureFlagEnabled: true, 252 ServiceBrokerSharingEnabled: false}), 253 254 Entry("actionerror.SharedServiceInstanceNotFoundError -> SharedServiceInstanceNotFoundError", 255 actionerror.SharedServiceInstanceNotFoundError{}, 256 SharedServiceInstanceNotFoundError{}), 257 258 Entry("actionerror.SpaceNotFoundError -> SpaceNotFoundError", 259 actionerror.SpaceNotFoundError{Name: "some-space"}, 260 SpaceNotFoundError{Name: "some-space"}), 261 262 Entry("actionerror.SpaceQuotaNotFoundByNameError -> SpaceQuotaNotFoundByNameError", 263 actionerror.SpaceQuotaNotFoundByNameError{Name: "some-space"}, 264 SpaceQuotaNotFoundByNameError{Name: "some-space"}), 265 266 Entry("actionerror.StackNotFoundError -> StackNotFoundError", 267 actionerror.StackNotFoundError{Name: "some-stack-name", GUID: "some-stack-guid"}, 268 StackNotFoundError{Name: "some-stack-name", GUID: "some-stack-guid"}), 269 270 Entry("actionerror.TaskWorkersUnavailableError -> RunTaskError", 271 actionerror.TaskWorkersUnavailableError{Message: "fooo: Banana Pants"}, 272 RunTaskError{Message: "Task workers are unavailable."}), 273 274 Entry("actionerror.TCPRouteOptionsNotProvidedError-> TCPRouteOptionsNotProvidedError", 275 actionerror.TCPRouteOptionsNotProvidedError{}, 276 TCPRouteOptionsNotProvidedError{}), 277 278 Entry("actionerror.TriggerLegacyPushError -> TriggerLegacyPushError", 279 actionerror.TriggerLegacyPushError{DomainHostRelated: []string{"domain", "host"}}, 280 TriggerLegacyPushError{DomainHostRelated: []string{"domain", "host"}}), 281 282 Entry("actionerror.UploadFailedError -> UploadFailedError", 283 actionerror.UploadFailedError{Err: actionerror.NoDomainsFoundError{}}, 284 UploadFailedError{Err: NoDomainsFoundError{}}), 285 286 Entry("v3action.StagingTimeoutError -> StagingTimeoutError", 287 actionerror.StagingTimeoutError{AppName: "some-app", Timeout: time.Nanosecond}, 288 StagingTimeoutError{AppName: "some-app", Timeout: time.Nanosecond}), 289 290 Entry("actionerror.CommandLineOptionsAndManifestConflictError -> CommandLineOptionsAndManifestConflictError", 291 actionerror.CommandLineOptionsAndManifestConflictError{ 292 ManifestAttribute: "some-attribute", 293 CommandLineOptions: []string{"option-1", "option-2"}, 294 }, 295 CommandLineOptionsAndManifestConflictError{ 296 ManifestAttribute: "some-attribute", 297 CommandLineOptions: []string{"option-1", "option-2"}, 298 }), 299 300 Entry("actionerror.ServiceInstanceNotSharedToSpaceError -> ServiceInstanceNotSharedToSpaceError", 301 actionerror.ServiceInstanceNotSharedToSpaceError{ServiceInstanceName: "some-service-instance-name"}, 302 ServiceInstanceNotSharedToSpaceError{ServiceInstanceName: "some-service-instance-name"}), 303 304 // CC Errors 305 Entry("ccerror.APINotFoundError -> APINotFoundError", 306 ccerror.APINotFoundError{URL: "some-url"}, 307 APINotFoundError{URL: "some-url"}), 308 309 Entry("ccerror.JobFailedError -> JobFailedError", 310 ccerror.JobFailedError{JobGUID: "some-job-guid", Message: "some-message"}, 311 JobFailedError{JobGUID: "some-job-guid", Message: "some-message"}), 312 313 Entry("ccerror.JobTimeoutError -> JobTimeoutError", 314 ccerror.JobTimeoutError{JobGUID: "some-job-guid"}, 315 JobTimeoutError{JobGUID: "some-job-guid"}), 316 317 Entry("ccerror.MultiError -> MultiError", 318 ccerror.MultiError{ResponseCode: 418, Errors: []ccerror.V3Error{ 319 { 320 Code: 282010, 321 Detail: "detail 1", 322 Title: "title-1", 323 }, 324 { 325 Code: 10242013, 326 Detail: "detail 2", 327 Title: "title-2", 328 }, 329 }}, 330 MultiError{Messages: []string{"detail 1", "detail 2"}}, 331 ), 332 333 Entry("ccerror.RequestError -> APIRequestError", 334 ccerror.RequestError{Err: err}, 335 APIRequestError{Err: err}), 336 337 Entry("ccerror.SSLValidationHostnameError -> SSLCertErrorError", 338 ccerror.SSLValidationHostnameError{Message: "some-message"}, 339 SSLCertError{Message: "some-message"}), 340 341 Entry("ccerror.UnverifiedServerError -> InvalidSSLCertError", 342 ccerror.UnverifiedServerError{URL: "some-url"}, 343 InvalidSSLCertError{URL: "some-url"}), 344 345 Entry("ccerror.UnprocessableEntityError with droplet message -> RunTaskError", 346 ccerror.UnprocessableEntityError{Message: "The request is semantically invalid: Task must have a droplet. Specify droplet or assign current droplet to app."}, 347 RunTaskError{Message: "App is not staged."}), 348 349 // This changed in CF254 350 Entry("ccerror.UnprocessableEntityError with droplet message -> RunTaskError", 351 ccerror.UnprocessableEntityError{Message: "Task must have a droplet. Specify droplet or assign current droplet to app."}, 352 RunTaskError{Message: "App is not staged."}), 353 354 Entry("ccerror.UnprocessableEntityError without droplet message -> original error", 355 unprocessableEntityError, 356 unprocessableEntityError), 357 358 Entry("download.RawHTTPStatusError -> HTTPStatusError", 359 download.RawHTTPStatusError{Status: "some status"}, 360 HTTPStatusError{Status: "some status"}, 361 ), 362 363 Entry("json.SyntaxError -> JSONSyntaxError", 364 jsonErr, 365 JSONSyntaxError{Err: jsonErr}, 366 ), 367 368 // Manifest Errors 369 Entry("manifest.ManifestCreationError -> ManifestCreationError", 370 manifest.ManifestCreationError{Err: errors.New("some-error")}, 371 ManifestCreationError{Err: errors.New("some-error")}), 372 373 Entry("manifest.InheritanceFieldError -> TriggerLegacyPushError", 374 manifest.InheritanceFieldError{}, 375 TriggerLegacyPushError{InheritanceRelated: true}), 376 377 Entry("manifest.GlobalFieldError -> TriggerLegacyPushError", 378 manifest.GlobalFieldsError{Fields: []string{"some-field"}}, 379 TriggerLegacyPushError{GlobalRelated: []string{"some-field"}}), 380 381 Entry("manifest.InterpolationError -> InterpolationError", 382 manifest.InterpolationError{Err: errors.New("an-error")}, 383 InterpolationError{Err: errors.New("an-error")}), 384 385 // Plugin Errors 386 Entry("pluginerror.RawHTTPStatusError -> DownloadPluginHTTPError", 387 pluginerror.RawHTTPStatusError{Status: "some status"}, 388 DownloadPluginHTTPError{Message: "some status"}, 389 ), 390 Entry("pluginerror.SSLValidationHostnameError -> DownloadPluginHTTPError", 391 pluginerror.SSLValidationHostnameError{Message: "some message"}, 392 DownloadPluginHTTPError{Message: "some message"}, 393 ), 394 Entry("pluginerror.UnverifiedServerError -> DownloadPluginHTTPError", 395 pluginerror.UnverifiedServerError{URL: "some URL"}, 396 DownloadPluginHTTPError{Message: "x509: certificate signed by unknown authority"}, 397 ), 398 399 // SSH Error 400 Entry("ssherror.UnableToAuthenticateError -> UnableToAuthenticateError", 401 ssherror.UnableToAuthenticateError{}, 402 SSHUnableToAuthenticateError{}), 403 404 // UAA Errors 405 Entry("uaa.BadCredentialsError -> BadCredentialsError", 406 uaa.UnauthorizedError{}, 407 UnauthorizedError{}), 408 409 Entry("uaa.InsufficientScopeError -> UnauthorizedToPerformActionError", 410 uaa.InsufficientScopeError{}, 411 UnauthorizedToPerformActionError{}), 412 413 Entry("uaa.InvalidAuthTokenError -> InvalidRefreshTokenError", 414 uaa.InvalidAuthTokenError{}, 415 InvalidRefreshTokenError{}), 416 417 Entry("default case -> original error", 418 err, 419 err), 420 ) 421 422 It("returns nil for a nil error", func() { 423 nilErr := ConvertToTranslatableError(nil) 424 Expect(nilErr).To(BeNil()) 425 }) 426 })