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