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  })