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