mirror of https://github.com/portainer/portainer
fix(errors): wrap db errors, improve error handling (#8859)
* use error check func, wrap db object not found * add errorlint and fix all the linting errors * add exportloopref linter and fix errors * fix incorrect error details returned on an api * fix new errors * increase linter timeout * increase timeout to 10minutes * increase timeout to 10minutes * rebase and fix new lint errors * make CE match EE * fix govet issuepull/8906/head
parent
550e235d59
commit
334eee0c8c
|
@ -21,13 +21,12 @@ jobs:
|
|||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: '14'
|
||||
node-version: '18'
|
||||
cache: 'yarn'
|
||||
- uses: actions/setup-go@v3
|
||||
- uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: 1.19.4
|
||||
go-version: 1.19.5
|
||||
- run: yarn --frozen-lockfile
|
||||
|
||||
- name: Run linters
|
||||
uses: wearerequired/lint-action@v1
|
||||
with:
|
||||
|
@ -44,4 +43,4 @@ jobs:
|
|||
with:
|
||||
version: latest
|
||||
working-directory: api
|
||||
args: -c .golangci.yaml
|
||||
args: --timeout=10m -c .golangci.yaml
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
linters:
|
||||
# Disable all linters.
|
||||
# Disable all linters, the defaults don't pass on our code yet
|
||||
disable-all: true
|
||||
|
||||
# Enable these for now
|
||||
enable:
|
||||
- depguard
|
||||
- govet
|
||||
- errorlint
|
||||
- exportloopref
|
||||
linters-settings:
|
||||
depguard:
|
||||
list-type: denylist
|
||||
|
@ -13,14 +18,12 @@ linters-settings:
|
|||
packages-with-error-message:
|
||||
- github.com/sirupsen/logrus: 'logging is allowed only by github.com/rs/zerolog'
|
||||
ignore-file-rules:
|
||||
- "**/*_test.go"
|
||||
# Create additional guards that follow the same configuration pattern.
|
||||
# Results from all guards are aggregated together.
|
||||
# additional-guards:
|
||||
# - list-type: allowlist
|
||||
# include-go-root: false
|
||||
# packages:
|
||||
# - github.com/sirupsen/logrus
|
||||
# # Specify rules by which the linter ignores certain files for consideration.
|
||||
# ignore-file-rules:
|
||||
# - "!**/*_test.go"
|
||||
- '**/*_test.go'
|
||||
|
||||
# errorlint is causing a typecheck error for some reason. The go compiler will report these
|
||||
# anyway, so ignore them from the linter
|
||||
issues:
|
||||
exclude-rules:
|
||||
- path: ./
|
||||
linters:
|
||||
- typecheck
|
||||
|
|
|
@ -3,6 +3,7 @@ package archive
|
|||
import (
|
||||
"archive/tar"
|
||||
"compress/gzip"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
@ -84,7 +85,7 @@ func ExtractTarGz(r io.Reader, outputDirPath string) error {
|
|||
for {
|
||||
header, err := tarReader.Next()
|
||||
|
||||
if err == io.EOF {
|
||||
if errors.Is(err, io.EOF) {
|
||||
break
|
||||
}
|
||||
|
||||
|
@ -109,7 +110,7 @@ func ExtractTarGz(r io.Reader, outputDirPath string) error {
|
|||
}
|
||||
outFile.Close()
|
||||
default:
|
||||
return fmt.Errorf("Tar: uknown type: %v in %s",
|
||||
return fmt.Errorf("tar: unknown type: %v in %s",
|
||||
header.Typeflag,
|
||||
header.Name)
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
|
@ -182,7 +183,7 @@ func (connection *DbConnection) BackupTo(w io.Writer) error {
|
|||
func (connection *DbConnection) ExportRaw(filename string) error {
|
||||
databasePath := connection.GetDatabaseFilePath()
|
||||
if _, err := os.Stat(databasePath); err != nil {
|
||||
return fmt.Errorf("stat on %s failed: %s", databasePath, err)
|
||||
return fmt.Errorf("stat on %s failed, error: %w", databasePath, err)
|
||||
}
|
||||
|
||||
b, err := connection.ExportJSON(databasePath, true)
|
||||
|
@ -201,6 +202,20 @@ func (connection *DbConnection) ConvertToKey(v int) []byte {
|
|||
return b
|
||||
}
|
||||
|
||||
// keyToString Converts a key to a string value suitable for logging
|
||||
func keyToString(b []byte) string {
|
||||
if len(b) != 8 {
|
||||
return string(b)
|
||||
}
|
||||
|
||||
v := binary.BigEndian.Uint64(b)
|
||||
if v <= math.MaxInt32 {
|
||||
return fmt.Sprintf("%d", v)
|
||||
}
|
||||
|
||||
return string(b)
|
||||
}
|
||||
|
||||
// CreateBucket is a generic function used to create a bucket inside a database.
|
||||
func (connection *DbConnection) SetServiceName(bucketName string) error {
|
||||
return connection.UpdateTx(func(tx portainer.Transaction) error {
|
||||
|
@ -237,7 +252,7 @@ func (connection *DbConnection) UpdateObjectFunc(bucketName string, key []byte,
|
|||
|
||||
data := bucket.Get(key)
|
||||
if data == nil {
|
||||
return dserrors.ErrObjectNotFound
|
||||
return fmt.Errorf("%w (bucket=%s, key=%s)", dserrors.ErrObjectNotFound, bucketName, keyToString(key))
|
||||
}
|
||||
|
||||
err := connection.UnmarshalObjectWithJsoniter(data, object)
|
||||
|
|
|
@ -2,6 +2,7 @@ package boltdb
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
dserrors "github.com/portainer/portainer/api/dataservices/errors"
|
||||
|
||||
|
@ -24,7 +25,7 @@ func (tx *DbTransaction) GetObject(bucketName string, key []byte, object interfa
|
|||
|
||||
value := bucket.Get(key)
|
||||
if value == nil {
|
||||
return dserrors.ErrObjectNotFound
|
||||
return fmt.Errorf("%w (bucket=%s, key=%s)", dserrors.ErrObjectNotFound, bucketName, keyToString(key))
|
||||
}
|
||||
|
||||
data := make([]byte, len(value))
|
||||
|
@ -74,7 +75,6 @@ func (tx *DbTransaction) GetNextIdentifier(bucketName string) int {
|
|||
id, err := bucket.NextSequence()
|
||||
if err != nil {
|
||||
log.Error().Err(err).Str("bucket", bucketName).Msg("failed to get the next identifer")
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"testing"
|
||||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
dserrors "github.com/portainer/portainer/api/dataservices/errors"
|
||||
"github.com/portainer/portainer/api/dataservices"
|
||||
)
|
||||
|
||||
const testBucketName = "test-bucket"
|
||||
|
@ -97,7 +97,7 @@ func TestTxs(t *testing.T) {
|
|||
err = conn.ViewTx(func(tx portainer.Transaction) error {
|
||||
return tx.GetObject(testBucketName, conn.ConvertToKey(testId), &obj)
|
||||
})
|
||||
if err != dserrors.ErrObjectNotFound {
|
||||
if !dataservices.IsErrObjectNotFound(err) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
|
|
@ -2,10 +2,11 @@ package apikeyrepository
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/dataservices/errors"
|
||||
dserrors "github.com/portainer/portainer/api/dataservices/errors"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
@ -78,12 +79,12 @@ func (service *Service) GetAPIKeyByDigest(digest []byte) (*portainer.APIKey, err
|
|||
return &portainer.APIKey{}, nil
|
||||
})
|
||||
|
||||
if err == stop {
|
||||
if errors.Is(err, stop) {
|
||||
return k, nil
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
return nil, errors.ErrObjectNotFound
|
||||
return nil, dserrors.ErrObjectNotFound
|
||||
}
|
||||
|
||||
return nil, err
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package errors
|
||||
|
||||
import "errors"
|
||||
import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
var (
|
||||
// TODO: i'm pretty sure this needs wrapping at several levels
|
||||
ErrObjectNotFound = errors.New("object not found inside the database")
|
||||
ErrWrongDBEdition = errors.New("the Portainer database is set for Portainer Business Edition, please follow the instructions in our documentation to downgrade it: https://documentation.portainer.io/v2.0-be/downgrade/be-to-ce/")
|
||||
ErrDBImportFailed = errors.New("importing backup failed")
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
package dataservices
|
||||
|
||||
// "github.com/portainer/portainer/api/dataservices"
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/portainer/portainer/api/database/models"
|
||||
"github.com/portainer/portainer/api/dataservices/errors"
|
||||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/database/models"
|
||||
dserrors "github.com/portainer/portainer/api/dataservices/errors"
|
||||
)
|
||||
|
||||
type (
|
||||
|
@ -325,5 +323,5 @@ type (
|
|||
)
|
||||
|
||||
func IsErrObjectNotFound(e error) bool {
|
||||
return e == errors.ErrObjectNotFound
|
||||
return errors.Is(e, dserrors.ErrObjectNotFound)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package resourcecontrol
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
|
@ -82,7 +83,7 @@ func (service *Service) ResourceControlByResourceIDAndType(resourceID string, re
|
|||
|
||||
return &portainer.ResourceControl{}, nil
|
||||
})
|
||||
if err == stop {
|
||||
if errors.Is(err, stop) {
|
||||
return resourceControl, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package resourcecontrol
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
|
@ -60,7 +61,7 @@ func (service ServiceTx) ResourceControlByResourceIDAndType(resourceID string, r
|
|||
|
||||
return &portainer.ResourceControl{}, nil
|
||||
})
|
||||
if err == stop {
|
||||
if errors.Is(err, stop) {
|
||||
return resourceControl, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package stack
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/dataservices/errors"
|
||||
dserrors "github.com/portainer/portainer/api/dataservices/errors"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
@ -71,11 +72,11 @@ func (service *Service) StackByName(name string) (*portainer.Stack, error) {
|
|||
|
||||
return &portainer.Stack{}, nil
|
||||
})
|
||||
if err == stop {
|
||||
if errors.Is(err, stop) {
|
||||
return s, nil
|
||||
}
|
||||
if err == nil {
|
||||
return nil, errors.ErrObjectNotFound
|
||||
return nil, dserrors.ErrObjectNotFound
|
||||
}
|
||||
|
||||
return nil, err
|
||||
|
@ -92,7 +93,7 @@ func (service *Service) StacksByName(name string) ([]portainer.Stack, error) {
|
|||
stack, ok := obj.(portainer.Stack)
|
||||
if !ok {
|
||||
log.Debug().Str("obj", fmt.Sprintf("%#v", obj)).Msg("failed to convert to Stack object")
|
||||
return nil, fmt.Errorf("Failed to convert to Stack object: %s", obj)
|
||||
return nil, fmt.Errorf("failed to convert to Stack object: %s", obj)
|
||||
}
|
||||
|
||||
if stack.Name == name {
|
||||
|
@ -173,11 +174,11 @@ func (service *Service) StackByWebhookID(id string) (*portainer.Stack, error) {
|
|||
|
||||
return &portainer.Stack{}, nil
|
||||
})
|
||||
if err == stop {
|
||||
if errors.Is(err, stop) {
|
||||
return s, nil
|
||||
}
|
||||
if err == nil {
|
||||
return nil, errors.ErrObjectNotFound
|
||||
return nil, dserrors.ErrObjectNotFound
|
||||
}
|
||||
|
||||
return nil, err
|
||||
|
|
|
@ -59,7 +59,7 @@ func (b *stackBuilder) createNewStack(webhookID string) portainer.Stack {
|
|||
Type: portainer.DockerComposeStack,
|
||||
EndpointID: 2,
|
||||
EntryPoint: filesystem.ComposeFileDefaultName,
|
||||
Env: []portainer.Pair{{"Name1", "Value1"}},
|
||||
Env: []portainer.Pair{{Name: "Name1", Value: "Value1"}},
|
||||
Status: portainer.StackStatusActive,
|
||||
CreationDate: time.Now().Unix(),
|
||||
ProjectPath: "/tmp/project",
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package team
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/dataservices/errors"
|
||||
dserrors "github.com/portainer/portainer/api/dataservices/errors"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
@ -71,11 +72,11 @@ func (service *Service) TeamByName(name string) (*portainer.Team, error) {
|
|||
|
||||
return &portainer.Team{}, nil
|
||||
})
|
||||
if err == stop {
|
||||
if errors.Is(err, stop) {
|
||||
return t, nil
|
||||
}
|
||||
if err == nil {
|
||||
return nil, errors.ErrObjectNotFound
|
||||
return nil, dserrors.ErrObjectNotFound
|
||||
}
|
||||
|
||||
return nil, err
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
package user
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/dataservices/errors"
|
||||
dserrors "github.com/portainer/portainer/api/dataservices/errors"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
@ -72,12 +73,12 @@ func (service *Service) UserByUsername(username string) (*portainer.User, error)
|
|||
return &portainer.User{}, nil
|
||||
})
|
||||
|
||||
if err == stop {
|
||||
if errors.Is(err, stop) {
|
||||
return u, nil
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
return nil, errors.ErrObjectNotFound
|
||||
return nil, dserrors.ErrObjectNotFound
|
||||
}
|
||||
|
||||
return nil, err
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package webhook
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/dataservices/errors"
|
||||
dserrors "github.com/portainer/portainer/api/dataservices/errors"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
@ -93,12 +94,12 @@ func (service *Service) WebhookByResourceID(ID string) (*portainer.Webhook, erro
|
|||
return &portainer.Webhook{}, nil
|
||||
})
|
||||
|
||||
if err == stop {
|
||||
if errors.Is(err, stop) {
|
||||
return w, nil
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
return nil, errors.ErrObjectNotFound
|
||||
return nil, dserrors.ErrObjectNotFound
|
||||
}
|
||||
|
||||
return nil, err
|
||||
|
@ -127,12 +128,12 @@ func (service *Service) WebhookByToken(token string) (*portainer.Webhook, error)
|
|||
return &portainer.Webhook{}, nil
|
||||
})
|
||||
|
||||
if err == stop {
|
||||
if errors.Is(err, stop) {
|
||||
return w, nil
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
return nil, errors.ErrObjectNotFound
|
||||
return nil, dserrors.ErrObjectNotFound
|
||||
}
|
||||
|
||||
return nil, err
|
||||
|
|
|
@ -115,7 +115,7 @@ func (store *Store) backupWithOptions(options *BackupOptions) (string, error) {
|
|||
|
||||
if err := store.Close(); err != nil {
|
||||
return options.BackupPath, fmt.Errorf(
|
||||
"error closing datastore before creating backup: %v",
|
||||
"error closing datastore before creating backup: %w",
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func (store *Store) backupWithOptions(options *BackupOptions) (string, error) {
|
|||
|
||||
if _, err := store.Open(); err != nil {
|
||||
return options.BackupPath, fmt.Errorf(
|
||||
"error opening datastore after creating backup: %v",
|
||||
"error opening datastore after creating backup: %w",
|
||||
err,
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package datastore
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
|
@ -104,7 +105,7 @@ func (store *Store) edition() portainer.SoftwareEdition {
|
|||
|
||||
// TODO: move the use of this to dataservices.IsErrObjectNotFound()?
|
||||
func (store *Store) IsErrObjectNotFound(e error) bool {
|
||||
return e == portainerErrors.ErrObjectNotFound
|
||||
return errors.Is(e, portainerErrors.ErrObjectNotFound)
|
||||
}
|
||||
|
||||
func (store *Store) Connection() portainer.Connection {
|
||||
|
|
|
@ -288,7 +288,7 @@ func migrateDBTestHelper(t *testing.T, srcPath, wantPath string, overrideInstanc
|
|||
// Convert database back to json.
|
||||
databasePath := con.GetDatabaseFilePath()
|
||||
if _, err := os.Stat(databasePath); err != nil {
|
||||
return fmt.Errorf("stat on %s failed: %s", databasePath, err)
|
||||
return fmt.Errorf("stat on %s failed: %w", databasePath, err)
|
||||
}
|
||||
|
||||
gotJSON, err := con.ExportJSON(databasePath, false)
|
||||
|
|
|
@ -2,7 +2,7 @@ package migrator
|
|||
|
||||
import (
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/dataservices/errors"
|
||||
"github.com/portainer/portainer/api/dataservices"
|
||||
"github.com/portainer/portainer/api/stacks/stackutils"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
|
@ -25,7 +25,7 @@ func (m *Migrator) updateStackResourceControlToDB27() error {
|
|||
|
||||
stack, err := m.stackService.StackByName(stackName)
|
||||
if err != nil {
|
||||
if err == errors.ErrObjectNotFound {
|
||||
if dataservices.IsErrObjectNotFound(err) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/dataservices/errors"
|
||||
"github.com/portainer/portainer/api/dataservices"
|
||||
"github.com/portainer/portainer/api/internal/endpointutils"
|
||||
snapshotutils "github.com/portainer/portainer/api/internal/snapshot"
|
||||
|
||||
|
@ -86,7 +86,7 @@ func (m *Migrator) updateDockerhubToDB32() error {
|
|||
log.Info().Msg("updating dockerhub")
|
||||
|
||||
dockerhub, err := m.dockerhubService.DockerHub()
|
||||
if err == errors.ErrObjectNotFound {
|
||||
if dataservices.IsErrObjectNotFound(err) {
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return err
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package migrator
|
||||
|
||||
import (
|
||||
"github.com/portainer/portainer/api/dataservices/errors"
|
||||
"github.com/portainer/portainer/api/dataservices"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
@ -19,7 +19,7 @@ func (m *Migrator) migrateDBVersionToDB71() error {
|
|||
if err == nil {
|
||||
log.Debug().Int("endpoint_id", int(s.EndpointID)).Msg("keeping snapshot")
|
||||
continue
|
||||
} else if err != errors.ErrObjectNotFound {
|
||||
} else if !dataservices.IsErrObjectNotFound(err) {
|
||||
log.Debug().Int("endpoint_id", int(s.EndpointID)).Err(err).Msg("database error")
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"github.com/rs/zerolog/log"
|
||||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
portainerDsErrors "github.com/portainer/portainer/api/dataservices/errors"
|
||||
"github.com/portainer/portainer/api/dataservices"
|
||||
)
|
||||
|
||||
func (m *Migrator) migrateDBVersionToDB90() error {
|
||||
|
@ -30,7 +30,7 @@ func (m *Migrator) updateEdgeStackStatusForDB90() error {
|
|||
for _, edgeJob := range edgeJobs {
|
||||
for endpointId := range edgeJob.Endpoints {
|
||||
_, err := m.endpointService.Endpoint(endpointId)
|
||||
if err == portainerDsErrors.ErrObjectNotFound {
|
||||
if dataservices.IsErrObjectNotFound(err) {
|
||||
delete(edgeJob.Endpoints, endpointId)
|
||||
|
||||
err = m.edgeJobService.UpdateEdgeJob(edgeJob.ID, &edgeJob)
|
||||
|
|
|
@ -178,6 +178,7 @@ func snapshotContainers(snapshot *portainer.DockerSnapshot, cli *client.Client)
|
|||
} else {
|
||||
var gpuOptions *_container.DeviceRequest = nil
|
||||
for _, deviceRequest := range response.HostConfig.Resources.DeviceRequests {
|
||||
deviceRequest := deviceRequest
|
||||
if deviceRequest.Driver == "nvidia" || deviceRequest.Capabilities[0][0] == "gpu" {
|
||||
gpuOptions = &deviceRequest
|
||||
}
|
||||
|
|
|
@ -53,7 +53,7 @@ func CloneWithBackup(gitService portainer.GitService, fileService portainer.File
|
|||
log.Warn().Err(restoreError).Msg("failed restoring backup folder")
|
||||
}
|
||||
|
||||
if err == gittypes.ErrAuthenticationFailure {
|
||||
if errors.Is(err, gittypes.ErrAuthenticationFailure) {
|
||||
return cleanFn, errors.WithMessage(err, ErrInvalidGitCredential.Error())
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package edgegroups
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
|
@ -39,8 +40,9 @@ func NewHandler(bouncer *security.RequestBouncer) *Handler {
|
|||
|
||||
func txResponse(w http.ResponseWriter, r any, err error) *httperror.HandlerError {
|
||||
if err != nil {
|
||||
if httpErr, ok := err.(*httperror.HandlerError); ok {
|
||||
return httpErr
|
||||
var handlerError *httperror.HandlerError
|
||||
if errors.As(err, &handlerError) {
|
||||
return handlerError
|
||||
}
|
||||
|
||||
return httperror.InternalServerError("Unexpected error", err)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package edgejobs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
|
@ -42,8 +43,9 @@ func (handler *Handler) edgeJobDelete(w http.ResponseWriter, r *http.Request) *h
|
|||
}
|
||||
|
||||
if err != nil {
|
||||
if httpErr, ok := err.(*httperror.HandlerError); ok {
|
||||
return httpErr
|
||||
var handlerError *httperror.HandlerError
|
||||
if errors.As(err, &handlerError) {
|
||||
return handlerError
|
||||
}
|
||||
|
||||
return httperror.InternalServerError("Unexpected error", err)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package edgejobs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
|
@ -75,8 +76,9 @@ func (handler *Handler) edgeJobTasksClear(w http.ResponseWriter, r *http.Request
|
|||
}
|
||||
|
||||
if err != nil {
|
||||
if httpErr, ok := err.(*httperror.HandlerError); ok {
|
||||
return httpErr
|
||||
var handlerError *httperror.HandlerError
|
||||
if errors.As(err, &handlerError) {
|
||||
return handlerError
|
||||
}
|
||||
|
||||
return httperror.InternalServerError("Unexpected error", err)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package edgejobs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
|
@ -83,8 +84,9 @@ func (handler *Handler) edgeJobTasksCollect(w http.ResponseWriter, r *http.Reque
|
|||
})
|
||||
|
||||
if err != nil {
|
||||
if httpErr, ok := err.(*httperror.HandlerError); ok {
|
||||
return httpErr
|
||||
var handlerError *httperror.HandlerError
|
||||
if errors.As(err, &handlerError) {
|
||||
return handlerError
|
||||
}
|
||||
|
||||
return httperror.InternalServerError("Unexpected error", err)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package edgejobs
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
|
@ -62,8 +63,9 @@ func convertEndpointsToMetaObject(endpoints []portainer.EndpointID) map[portaine
|
|||
|
||||
func txResponse(w http.ResponseWriter, r any, err error) *httperror.HandlerError {
|
||||
if err != nil {
|
||||
if httpErr, ok := err.(*httperror.HandlerError); ok {
|
||||
return httpErr
|
||||
var handlerError *httperror.HandlerError
|
||||
if errors.As(err, &handlerError) {
|
||||
return handlerError
|
||||
}
|
||||
|
||||
return httperror.InternalServerError("Unexpected error", err)
|
||||
|
|
|
@ -153,8 +153,8 @@ func registryAccessPoliciesContainsNamespace(registryAccess portainer.RegistryAc
|
|||
|
||||
func (handler *Handler) filterKubernetesRegistriesByUserRole(r *http.Request, registries []portainer.Registry, endpoint *portainer.Endpoint, user *portainer.User) ([]portainer.Registry, *httperror.HandlerError) {
|
||||
err := handler.requestBouncer.AuthorizedEndpointOperation(r, endpoint)
|
||||
if err == security.ErrAuthorizationRequired {
|
||||
return nil, httperror.Forbidden("User is not authorized", errors.New("missing namespace query parameter"))
|
||||
if errors.Is(err, security.ErrAuthorizationRequired) {
|
||||
return nil, httperror.Forbidden("User is not authorized", err)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, httperror.InternalServerError("Unable to retrieve info from request context", err)
|
||||
|
|
|
@ -29,7 +29,7 @@ type repositoryFilePreviewPayload struct {
|
|||
|
||||
func (payload *repositoryFilePreviewPayload) Validate(r *http.Request) error {
|
||||
if govalidator.IsNull(payload.Repository) || !govalidator.IsURL(payload.Repository) {
|
||||
return errors.New("Invalid repository URL. Must correspond to a valid URL format")
|
||||
return errors.New("invalid repository URL. Must correspond to a valid URL format")
|
||||
}
|
||||
|
||||
if govalidator.IsNull(payload.Reference) {
|
||||
|
@ -37,7 +37,7 @@ func (payload *repositoryFilePreviewPayload) Validate(r *http.Request) error {
|
|||
}
|
||||
|
||||
if govalidator.IsNull(payload.TargetFile) {
|
||||
return errors.New("Invalid target filename.")
|
||||
return errors.New("invalid target filename")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -70,11 +70,11 @@ func (handler *Handler) gitOperationRepoFilePreview(w http.ResponseWriter, r *ht
|
|||
|
||||
err = handler.gitService.CloneRepository(projectPath, payload.Repository, payload.Reference, payload.Username, payload.Password, payload.TLSSkipVerify)
|
||||
if err != nil {
|
||||
if err == gittypes.ErrAuthenticationFailure {
|
||||
if errors.Is(err, gittypes.ErrAuthenticationFailure) {
|
||||
return httperror.BadRequest("Invalid git credential", err)
|
||||
}
|
||||
|
||||
newErr := fmt.Errorf("unable to clone git repository: %w", err)
|
||||
newErr := fmt.Errorf("unable to clone git repository, error: %w", err)
|
||||
return httperror.InternalServerError(newErr.Error(), newErr)
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/dataservices/errors"
|
||||
"github.com/portainer/portainer/api/internal/endpointutils"
|
||||
)
|
||||
|
||||
|
@ -33,7 +32,7 @@ func (handler *Handler) openAMTActivate(w http.ResponseWriter, r *http.Request)
|
|||
}
|
||||
|
||||
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
|
||||
if err == bolterrors.ErrObjectNotFound {
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return httperror.NotFound("Unable to find an endpoint with the specified identifier inside the database", err)
|
||||
} else if err != nil {
|
||||
return httperror.InternalServerError("Unable to find an endpoint with the specified identifier inside the database", err)
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/dataservices/errors"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
@ -33,7 +32,7 @@ func (handler *Handler) openAMTDevices(w http.ResponseWriter, r *http.Request) *
|
|||
}
|
||||
|
||||
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
|
||||
if err == bolterrors.ErrObjectNotFound {
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return httperror.NotFound("Unable to find an endpoint with the specified identifier inside the database", err)
|
||||
} else if err != nil {
|
||||
return httperror.InternalServerError("Unable to find an endpoint with the specified identifier inside the database", err)
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/dataservices/errors"
|
||||
"github.com/portainer/portainer/api/hostmanagement/openamt"
|
||||
|
||||
"github.com/docker/docker/api/types"
|
||||
|
@ -63,7 +62,7 @@ func (handler *Handler) openAMTHostInfo(w http.ResponseWriter, r *http.Request)
|
|||
log.Info().Int("endpointID", endpointID).Msg("OpenAMTHostInfo")
|
||||
|
||||
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
|
||||
if err == bolterrors.ErrObjectNotFound {
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return httperror.NotFound("Unable to find an endpoint with the specified identifier inside the database", err)
|
||||
} else if err != nil {
|
||||
return httperror.InternalServerError("Unable to find an endpoint with the specified identifier inside the database", err)
|
||||
|
|
|
@ -7,7 +7,6 @@ import (
|
|||
"strconv"
|
||||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
portainerDsErrors "github.com/portainer/portainer/api/dataservices/errors"
|
||||
"github.com/portainer/portainer/api/kubernetes"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
@ -121,7 +120,7 @@ func (handler *Handler) kubeClient(next http.Handler) http.Handler {
|
|||
}
|
||||
|
||||
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
|
||||
if err == portainerDsErrors.ErrObjectNotFound {
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
httperror.WriteError(
|
||||
w,
|
||||
http.StatusNotFound,
|
||||
|
|
|
@ -8,7 +8,6 @@ import (
|
|||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
portainerDsErrors "github.com/portainer/portainer/api/dataservices/errors"
|
||||
models "github.com/portainer/portainer/api/http/models/kubernetes"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
@ -23,7 +22,7 @@ func (handler *Handler) getKubernetesIngressControllers(w http.ResponseWriter, r
|
|||
}
|
||||
|
||||
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
|
||||
if err == portainerDsErrors.ErrObjectNotFound {
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return httperror.NotFound(
|
||||
"Unable to find an environment with the specified identifier inside the database",
|
||||
err,
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package stacks
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
|
@ -38,7 +39,8 @@ func (handler *Handler) webhookInvoke(w http.ResponseWriter, r *http.Request) *h
|
|||
}
|
||||
|
||||
if err = deployments.RedeployWhenChanged(stack.ID, handler.StackDeployer, handler.DataStore, handler.GitService); err != nil {
|
||||
if _, ok := err.(*deployments.StackAuthorMissingErr); ok {
|
||||
var StackAuthorMissingErr *deployments.StackAuthorMissingErr
|
||||
if errors.As(err, &StackAuthorMissingErr) {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusConflict, Message: "Autoupdate for the stack isn't available", Err: err}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package tags
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
|
@ -34,8 +35,9 @@ func NewHandler(bouncer *security.RequestBouncer) *Handler {
|
|||
|
||||
func txResponse(w http.ResponseWriter, r any, err error) *httperror.HandlerError {
|
||||
if err != nil {
|
||||
if httpErr, ok := err.(*httperror.HandlerError); ok {
|
||||
return httpErr
|
||||
var handlerError *httperror.HandlerError
|
||||
if errors.As(err, &handlerError) {
|
||||
return handlerError
|
||||
}
|
||||
|
||||
return httperror.InternalServerError("Unexpected error", err)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package tags
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
|
@ -41,8 +42,9 @@ func (handler *Handler) tagDelete(w http.ResponseWriter, r *http.Request) *httpe
|
|||
}
|
||||
|
||||
if err != nil {
|
||||
if httpErr, ok := err.(*httperror.HandlerError); ok {
|
||||
return httpErr
|
||||
var handlerError *httperror.HandlerError
|
||||
if errors.As(err, &handlerError) {
|
||||
return handlerError
|
||||
}
|
||||
|
||||
return httperror.InternalServerError("Unexpected error", err)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package users
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
|
@ -66,7 +67,7 @@ func (handler *Handler) userRemoveAccessToken(w http.ResponseWriter, r *http.Req
|
|||
|
||||
err = handler.apiKeyService.DeleteAPIKey(portainer.APIKeyID(apiKeyID))
|
||||
if err != nil {
|
||||
if err == apikey.ErrInvalidAPIKey {
|
||||
if errors.Is(err, apikey.ErrInvalidAPIKey) {
|
||||
return httperror.NotFound("Unable to find an api-key with the specified identifier inside the database", err)
|
||||
}
|
||||
return httperror.InternalServerError("Unable to remove the api-key from the user", err)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package websocket
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
|
@ -11,7 +12,7 @@ import (
|
|||
func hijackRequest(websocketConn *websocket.Conn, httpConn *httputil.ClientConn, request *http.Request) error {
|
||||
// Server hijacks the connection, error 'connection closed' expected
|
||||
resp, err := httpConn.Do(request)
|
||||
if err != httputil.ErrPersistEOF {
|
||||
if !errors.Is(err, httputil.ErrPersistEOF) {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"github.com/gorilla/mux"
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
bolterrors "github.com/portainer/portainer/api/dataservices/errors"
|
||||
"github.com/portainer/portainer/api/dataservices"
|
||||
)
|
||||
|
||||
type ItemContextKey string
|
||||
|
@ -31,7 +31,7 @@ func WithItem[TId ~int, TObject any](getter ItemGetter[TId, TObject], idParam st
|
|||
item, err := getter(TId(itemId))
|
||||
if err != nil {
|
||||
statusCode := http.StatusInternalServerError
|
||||
if err == bolterrors.ErrObjectNotFound {
|
||||
if dataservices.IsErrObjectNotFound(err) {
|
||||
statusCode = http.StatusNotFound
|
||||
}
|
||||
httperror.WriteError(rw, statusCode, "Unable to find a object with the specified identifier inside the database", err)
|
||||
|
|
|
@ -37,6 +37,7 @@ func createRegistryAuthenticationHeader(
|
|||
} else { // any "custom" registry
|
||||
var matchingRegistry *portainer.Registry
|
||||
for _, registry := range accessContext.registries {
|
||||
registry := registry
|
||||
if registry.ID == registryId &&
|
||||
(accessContext.isAdmin ||
|
||||
security.AuthorizedRegistryAccess(®istry, accessContext.user, accessContext.teamMemberships, accessContext.endpointID)) {
|
||||
|
|
|
@ -15,7 +15,6 @@ import (
|
|||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/dataservices"
|
||||
dataerrors "github.com/portainer/portainer/api/dataservices/errors"
|
||||
"github.com/portainer/portainer/api/docker"
|
||||
"github.com/portainer/portainer/api/http/proxy/factory/utils"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
|
@ -647,7 +646,7 @@ func (transport *Transport) executeGenericResourceDeletionOperation(request *htt
|
|||
if response.StatusCode == http.StatusNoContent || response.StatusCode == http.StatusOK {
|
||||
resourceControl, err := transport.dataStore.ResourceControl().ResourceControlByResourceIDAndType(resourceIdentifierAttribute, resourceType)
|
||||
if err != nil {
|
||||
if err == dataerrors.ErrObjectNotFound {
|
||||
if dataservices.IsErrObjectNotFound(err) {
|
||||
return response, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ func EdgeStackRelatedEndpoints(edgeGroupIDs []portainer.EdgeGroupID, endpoints [
|
|||
var edgeGroup *portainer.EdgeGroup
|
||||
|
||||
for _, group := range edgeGroups {
|
||||
group := group
|
||||
if group.ID == edgeGroupID {
|
||||
edgeGroup = &group
|
||||
break
|
||||
|
|
|
@ -81,7 +81,7 @@ func (service *Service) PersistEdgeStack(
|
|||
|
||||
relatedEndpointIds, err := edge.EdgeStackRelatedEndpoints(stack.EdgeGroups, relationConfig.Endpoints, relationConfig.EndpointGroups, relationConfig.EdgeGroups)
|
||||
if err != nil {
|
||||
if err == edge.ErrEdgeGroupNotFound {
|
||||
if errors.Is(err, edge.ErrEdgeGroupNotFound) {
|
||||
return nil, httperrors.NewInvalidPayloadError(err.Error())
|
||||
}
|
||||
return nil, fmt.Errorf("unable to persist environment relation in database: %w", err)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
|
@ -50,13 +51,14 @@ func (kcl *KubeClient) StartExecProcess(token string, useAdminToken bool, namesp
|
|||
return
|
||||
}
|
||||
|
||||
err = exec.Stream(remotecommand.StreamOptions{
|
||||
err = exec.StreamWithContext(context.TODO(), remotecommand.StreamOptions{
|
||||
Stdin: stdin,
|
||||
Stdout: stdout,
|
||||
Tty: true,
|
||||
})
|
||||
if err != nil {
|
||||
if _, ok := err.(utilexec.ExitError); !ok {
|
||||
var exitError utilexec.ExitError
|
||||
if !errors.As(err, &exitError) {
|
||||
errChan <- errors.New("unable to start exec process")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package cli
|
|||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -30,7 +31,7 @@ func Test_waitForPodStatus(t *testing.T) {
|
|||
ctx, cancel := context.WithCancel(context.TODO())
|
||||
cancel()
|
||||
err := k.waitForPodStatus(ctx, v1.PodRunning, podSpec)
|
||||
if err != context.Canceled {
|
||||
if !errors.Is(err, context.Canceled) {
|
||||
t.Errorf("waitForPodStatus should throw context cancellation error; err=%s", err)
|
||||
}
|
||||
})
|
||||
|
@ -59,7 +60,7 @@ func Test_waitForPodStatus(t *testing.T) {
|
|||
ctx, cancelFunc := context.WithTimeout(context.TODO(), 0*time.Second)
|
||||
defer cancelFunc()
|
||||
err = k.waitForPodStatus(ctx, v1.PodRunning, podSpec)
|
||||
if err != context.DeadlineExceeded {
|
||||
if !errors.Is(err, context.DeadlineExceeded) {
|
||||
t.Errorf("waitForPodStatus should throw deadline exceeded error; err=%s", err)
|
||||
}
|
||||
})
|
||||
|
|
|
@ -55,7 +55,7 @@ func (s *Scheduler) Shutdown() error {
|
|||
s.mu.Unlock()
|
||||
|
||||
err := ctx.Err()
|
||||
if err == context.Canceled {
|
||||
if errors.Is(err, context.Canceled) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
|
|
|
@ -27,7 +27,7 @@ func DownloadGitRepository(config gittypes.RepoConfig, gitService portainer.GitS
|
|||
projectPath := getProjectPath()
|
||||
err := gitService.CloneRepository(projectPath, config.URL, config.ReferenceName, username, password, config.TLSSkipVerify)
|
||||
if err != nil {
|
||||
if err == gittypes.ErrAuthenticationFailure {
|
||||
if errors.Is(err, gittypes.ErrAuthenticationFailure) {
|
||||
newErr := ErrInvalidGitCredential
|
||||
return "", newErr
|
||||
}
|
||||
|
|
|
@ -2,10 +2,10 @@
|
|||
#!/bin/bash
|
||||
|
||||
cd api
|
||||
if golangci-lint run -c .golangci.yaml
|
||||
if golangci-lint run --timeout=10m -c .golangci.yaml
|
||||
then
|
||||
echo "golangci-lint run successfully"
|
||||
else
|
||||
echo "golangci-lint run failed"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
|
Loading…
Reference in New Issue