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