Skip to content

Commit

Permalink
feat: add errorz package to combine errors as enum in there (#47)
Browse files Browse the repository at this point in the history
* feat: add errorz package to combine errors as enum in there

* feat: missed duplicated error

* fix: not worked error checks

* fix: not worked error checks

* rename error package

* applied JRA's suggestions

* applied JRA's suggestions

* fix error in test suite

---------

Co-authored-by: Nedim Akar <[email protected]>
Co-authored-by: Nedim Akar <[email protected]>
Co-authored-by: Jan-Robin Aumann <[email protected]>
  • Loading branch information
4 people authored Nov 2, 2023
1 parent 83683da commit 61e3c00
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 36 deletions.
21 changes: 14 additions & 7 deletions src/jetstream/cnsi.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"crypto/x509"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
Expand All @@ -23,15 +24,21 @@ import (
const dbReferenceError = "unable to establish a database reference: '%v'"

func isSSLRelatedError(err error) (bool, string) {
if urlErr, ok := err.(*url.Error); ok {
if x509Err, ok := urlErr.Err.(x509.UnknownAuthorityError); ok {
return true, x509Err.Error()
var urlError *url.Error
if errors.As(err, &urlError) {
var (
certInvalidError *x509.CertificateInvalidError
unknownAuthorityError *x509.UnknownAuthorityError
hostnameError *x509.HostnameError
)
if errors.As(urlError.Err, unknownAuthorityError) {
return true, unknownAuthorityError.Error()
}
if x509Err, ok := urlErr.Err.(x509.HostnameError); ok {
return true, x509Err.Error()
if errors.As(urlError.Err, hostnameError) {
return true, hostnameError.Error()
}
if x509Err, ok := urlErr.Err.(x509.CertificateInvalidError); ok {
return true, x509Err.Error()
if errors.As(urlError.Err, certInvalidError) {
return true, certInvalidError.Error()
}
}
return false, ""
Expand Down
7 changes: 7 additions & 0 deletions src/jetstream/custom_errors/constants/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package constants

const (
ERR_GOOSE_DB_NO_DATABASE_VERSIONS_FOUND = "pgsql_goosedb: no database versions found"
ERR_GOOSE_DB_NO_SUCH_TABLE = "pgsql_goosedb: no such table"
ERR_GOOSE_DB_FAILED_GETTING_CURRENT_DATABASE_VERSION = "pgsql_goosedb: error trying to get current database version: %w"
)
26 changes: 26 additions & 0 deletions src/jetstream/custom_errors/custom_errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package custom_errors

import (
"fmt"

"github.com/cloudfoundry-incubator/stratos/src/jetstream/custom_errors/constants"
)

type GooseDBNoDatabaseVersionsFoundError struct{}

func (e GooseDBNoDatabaseVersionsFoundError) Error() string {
return constants.ERR_GOOSE_DB_NO_DATABASE_VERSIONS_FOUND
}

type GooseDBNoSuchTableError struct{}

func (e GooseDBNoSuchTableError) Error() string {
return constants.ERR_GOOSE_DB_NO_SUCH_TABLE
}

func ErrGettingCurrentVersion(err error) error {
return fmt.Errorf(constants.ERR_GOOSE_DB_FAILED_GETTING_CURRENT_DATABASE_VERSION, err)
}

var ErrNoDatabaseVersionsFound = GooseDBNoDatabaseVersionsFoundError{}
var ErrNoSuchTable = GooseDBNoSuchTableError{}
7 changes: 5 additions & 2 deletions src/jetstream/datastore/datastore.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package datastore

import (
"database/sql"
"errors"
"fmt"
"os"
"path"
"regexp"
"strings"
"time"

"github.com/cloudfoundry-incubator/stratos/src/jetstream/custom_errors"

goosedbversion "github.com/cloudfoundry-incubator/stratos/src/jetstream/repository/goose-db-version"
"github.com/govau/cf-common/env"
log "github.com/sirupsen/logrus"
Expand Down Expand Up @@ -301,9 +304,9 @@ func WaitForMigrations(db *sql.DB) error {
databaseVersionRec, err := dbVersionRepo.GetCurrentVersion()
if err != nil {
var errorMsg = err.Error()
if strings.Contains(err.Error(), "no such table") {
if errors.Is(err, custom_errors.ErrNoSuchTable) {
errorMsg = "Waiting for versions table to be created"
} else if strings.Contains(err.Error(), "No database versions found") {
} else if errors.Is(err, custom_errors.ErrNoDatabaseVersionsFound) {
errorMsg = "Versions table is empty - waiting for migrations"
}
log.Infof("Database schema check: %s", errorMsg)
Expand Down
16 changes: 10 additions & 6 deletions src/jetstream/middleware.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"database/sql"
"errors"
"fmt"
"net"
"net/http"
"os"
"strings"
Expand Down Expand Up @@ -39,12 +40,15 @@ const APIKeyAuthScheme = "Bearer"
func handleSessionError(config api.PortalConfig, c echo.Context, err error, doNotLog bool, msg string) error {
log.Debug("handleSessionError")

if strings.Contains(err.Error(), "dial tcp") {
return api.NewHTTPShadowError(
http.StatusServiceUnavailable,
"Service is currently unavailable",
"Service is currently unavailable: %v", err,
)
var netOpErr *net.OpError
if errors.As(err, &netOpErr) {
if netOpErr.Op == "dial" && netOpErr.Net == "tcp" {
return api.NewHTTPShadowError(
http.StatusServiceUnavailable,
"Service is currently unavailable",
"Service is currently unavailable: %v", err,
)
}
}

if doNotLog {
Expand Down
4 changes: 2 additions & 2 deletions src/jetstream/plugins/kubernetes/main.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package kubernetes

import (
"crypto/x509"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strconv"
"strings"

"errors"

Expand Down Expand Up @@ -288,7 +288,7 @@ func (c *KubernetesSpecification) RequiresCert(ec echo.Context) error {
Message string
}
if err != nil {
if strings.Contains(err.Error(), "x509: certificate") {
if errors.Is(err, new(x509.CertificateInvalidError)) {
response.Status = http.StatusOK
response.Required = true
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import (
"database/sql"
"errors"
"fmt"
"strings"

log "github.com/sirupsen/logrus"

"github.com/cloudfoundry-incubator/stratos/src/jetstream/api"
"github.com/cloudfoundry-incubator/stratos/src/jetstream/custom_errors"
)

const (
Expand Down Expand Up @@ -35,15 +37,15 @@ func (p *PostgresGooseDBVersionRepository) GetCurrentVersion() (api.GooseDBVersi

err := p.db.QueryRow(getCurrentVersion).Scan(&dbVersion.VersionID)

switch {
case err == sql.ErrNoRows:
return api.GooseDBVersionRecord{}, errors.New("No database versions found")
case err != nil:
return api.GooseDBVersionRecord{}, fmt.Errorf("Error trying to get current database version: %v", err)
default:
// do nothing
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return api.GooseDBVersionRecord{}, custom_errors.ErrNoDatabaseVersionsFound
} else if strings.Contains(err.Error(), "no such table") {
return api.GooseDBVersionRecord{}, custom_errors.ErrNoSuchTable
} else {
return api.GooseDBVersionRecord{}, custom_errors.ErrGettingCurrentVersion(err)
}
}

return *dbVersion, nil
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ package goosedbversion

import (
"errors"
"fmt"
"testing"

"gopkg.in/DATA-DOG/go-sqlmock.v1"

. "github.com/smartystreets/goconvey/convey"

"github.com/cloudfoundry-incubator/stratos/src/jetstream/api"
"github.com/cloudfoundry-incubator/stratos/src/jetstream/custom_errors"
)

func TestPgSQLGooseDB(t *testing.T) {
Expand Down Expand Up @@ -63,9 +63,6 @@ func TestPgSQLGooseDB(t *testing.T) {
})

Convey("if one doesn't exist", func() {

expectedErrorMessage := "No database versions found"

// Database setup
rs := sqlmock.NewRows(rowFieldsForVersionID)
mock.ExpectQuery(selectFromDBVersionWhere).
Expand All @@ -74,25 +71,22 @@ func TestPgSQLGooseDB(t *testing.T) {
Convey("there should be an error", func() {
repository, _ := NewPostgresGooseDBVersionRepository(db)
_, err := repository.GetCurrentVersion()
So(err, ShouldResemble, errors.New(expectedErrorMessage))
So(err, ShouldResemble, custom_errors.ErrNoDatabaseVersionsFound)

dberr := mock.ExpectationsWereMet()
So(dberr, ShouldBeNil)
})
})

Convey("if there is a problem talking to the database", func() {

expectedErrorMessage := fmt.Sprintf("Error trying to get current database version: %s", "error")

// Database setup
mock.ExpectQuery(selectFromDBVersionWhere).
WillReturnError(errors.New("error"))

Convey("there should be an error", func() {
repository, _ := NewPostgresGooseDBVersionRepository(db)
_, err := repository.GetCurrentVersion()
So(err, ShouldResemble, errors.New(expectedErrorMessage))
So(err, ShouldResemble, custom_errors.ErrGettingCurrentVersion(errors.New("error")))

dberr := mock.ExpectationsWereMet()
So(dberr, ShouldBeNil)
Expand Down
5 changes: 3 additions & 2 deletions src/jetstream/setup_console.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package main

import (
"crypto/x509"
"errors"
"fmt"
"net/http"
"net/url"
"regexp"
"strconv"
"strings"

"github.com/govau/cf-common/env"
"github.com/labstack/echo/v4"
Expand Down Expand Up @@ -93,7 +93,8 @@ func (p *portalProxy) setupGetAvailableScopes(c echo.Context) error {
errInfo, ok := err.(api.ErrHTTPRequest)
if ok {
if errInfo.Status == 0 {
if strings.Contains(errInfo.Error(), "x509: certificate") {
var certError *x509.CertificateInvalidError
if errors.As(err, certError) {
return api.NewHTTPShadowError(
http.StatusBadRequest,
"Could not connect to the UAA - Certificate error - check Skip SSL validation setting",
Expand Down

0 comments on commit 61e3c00

Please sign in to comment.