chore(code): reduce divergence with EE EE-4344 (#7748)

pull/7752/head
andres-portainer 2022-09-28 14:56:32 -03:00 committed by GitHub
parent e9384a6987
commit cb79dc18f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
102 changed files with 259 additions and 180 deletions

View File

@ -25,7 +25,7 @@ type Monitor struct {
adminInitDisabled bool
}
// New creates a monitor that when started will wait for the timeout duration and then sends the timeout signal to disable the application
// New creates a monitor that when started will wait for the timeout duration and then shutdown the application unless it has been initialized.
func New(timeout time.Duration, datastore dataservices.DataStore, shutdownCtx context.Context) *Monitor {
return &Monitor{
timeout: timeout,
@ -105,12 +105,10 @@ func (m *Monitor) WasInstanceDisabled() bool {
// Otherwise, it will pass through the request to next
func (m *Monitor) WithRedirect(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if m.WasInstanceDisabled() {
if strings.HasPrefix(r.RequestURI, "/api") && r.RequestURI != "/api/status" && r.RequestURI != "/api/settings/public" {
w.Header().Set("redirect-reason", RedirectReasonAdminInitTimeout)
httperror.WriteError(w, http.StatusSeeOther, "Administrator initialization timeout", nil)
return
}
if m.WasInstanceDisabled() && strings.HasPrefix(r.RequestURI, "/api") && r.RequestURI != "/api/status" && r.RequestURI != "/api/settings/public" {
w.Header().Set("redirect-reason", RedirectReasonAdminInitTimeout)
httperror.WriteError(w, http.StatusSeeOther, "Administrator initialization timeout", nil)
return
}
next.ServeHTTP(w, r)

View File

@ -6,10 +6,10 @@ import (
"fmt"
"time"
"github.com/pkg/errors"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/dataservices"
"github.com/pkg/errors"
)
const portainerAPIKeyPrefix = "ptr_"

View File

@ -2,6 +2,7 @@ package apikey
import (
"crypto/sha256"
"fmt"
"strings"
"testing"
"time"
@ -170,11 +171,9 @@ func Test_UpdateAPIKey(t *testing.T) {
_, apiKeyGot, err := service.GetDigestUserAndKey(apiKey.Digest)
is.NoError(err)
log.Debug().Msgf("%+v", apiKey)
log.Debug().Msgf("%+v", apiKeyGot)
log.Debug().Str("wanted", fmt.Sprintf("%+v", apiKey)).Str("got", fmt.Sprintf("%+v", apiKeyGot)).Msg("")
is.Equal(apiKey.LastUsed, apiKeyGot.LastUsed)
})
t.Run("Successfully updates api-key in cache upon api-key update", func(t *testing.T) {

View File

@ -246,9 +246,8 @@ func (service *Service) checkTunnels() {
err := service.snapshotEnvironment(endpointID, tunnel.Port)
if err != nil {
log.Error().
Int("endpoint_id", int(endpointID)).Err(
err).
Int("endpoint_id", int(endpointID)).
Err(err).
Msg("unable to snapshot Edge environment")
}
}

View File

@ -1,10 +1,10 @@
package cli
import (
portainer "github.com/portainer/portainer/api"
"strings"
portainer "github.com/portainer/portainer/api"
"gopkg.in/alecthomas/kingpin.v2"
)

View File

@ -186,6 +186,10 @@ func initAPIKeyService(datastore dataservices.DataStore) apikey.APIKeyService {
}
func initJWTService(userSessionTimeout string, dataStore dataservices.DataStore) (dataservices.JWTService, error) {
if userSessionTimeout == "" {
userSessionTimeout = portainer.DefaultUserSessionTimeout
}
jwtService, err := jwt.NewService(userSessionTimeout, dataStore)
if err != nil {
return nil, err
@ -239,7 +243,13 @@ func initKubernetesClientFactory(signatureService portainer.DigitalSignatureServ
return kubecli.NewClientFactory(signatureService, reverseTunnelService, instanceID, dataStore)
}
func initSnapshotService(snapshotIntervalFromFlag string, dataStore dataservices.DataStore, dockerClientFactory *docker.ClientFactory, kubernetesClientFactory *kubecli.ClientFactory, shutdownCtx context.Context) (portainer.SnapshotService, error) {
func initSnapshotService(
snapshotIntervalFromFlag string,
dataStore dataservices.DataStore,
dockerClientFactory *docker.ClientFactory,
kubernetesClientFactory *kubecli.ClientFactory,
shutdownCtx context.Context,
) (portainer.SnapshotService, error) {
dockerSnapshotter := docker.NewSnapshotter(dockerClientFactory)
kubernetesSnapshotter := kubernetes.NewSnapshotter(kubernetesClientFactory)
@ -580,6 +590,7 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
ldapService := initLDAPService()
oauthService := initOAuthService()
gitService := initGitService(shutdownCtx)
openAMTService := openamt.NewService()
@ -704,15 +715,15 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
log.Fatal().Err(err).Msg("failed starting tunnel server")
}
scheduler := scheduler.NewScheduler(shutdownCtx)
stackDeployer := stacks.NewStackDeployer(swarmStackManager, composeStackManager, kubernetesDeployer)
stacks.StartStackSchedules(scheduler, stackDeployer, dataStore, gitService)
sslDBSettings, err := dataStore.SSLSettings().Settings()
if err != nil {
log.Fatal().Msg("failed to fetch SSL settings from DB")
}
scheduler := scheduler.NewScheduler(shutdownCtx)
stackDeployer := stacks.NewStackDeployer(swarmStackManager, composeStackManager, kubernetesDeployer)
stacks.StartStackSchedules(scheduler, stackDeployer, dataStore, gitService)
return &http.Server{
AuthorizationService: authorizationService,
ReverseTunnelService: reverseTunnelService,
@ -726,8 +737,8 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
ComposeStackManager: composeStackManager,
KubernetesDeployer: kubernetesDeployer,
HelmPackageManager: helmPackageManager,
CryptoService: cryptoService,
APIKeyService: apiKeyService,
CryptoService: cryptoService,
JWTService: jwtService,
FileService: fileService,
LDAPService: ldapService,

View File

@ -8,6 +8,7 @@ import (
"github.com/portainer/portainer/api/cli"
"github.com/portainer/portainer/api/dataservices"
"github.com/portainer/portainer/api/datastore"
"github.com/stretchr/testify/assert"
"gopkg.in/alecthomas/kingpin.v2"
)

View File

@ -1,6 +1,7 @@
package boltdb
import (
"bytes"
"encoding/binary"
"errors"
"fmt"
@ -162,7 +163,7 @@ func (connection *DbConnection) ExportRaw(filename string) error {
return fmt.Errorf("stat on %s failed: %s", databasePath, err)
}
b, err := connection.ExportJson(databasePath, true)
b, err := connection.ExportJSON(databasePath, true)
if err != nil {
return err
}
@ -369,6 +370,27 @@ func (connection *DbConnection) GetAllWithJsoniter(bucketName string, obj interf
return err
}
func (connection *DbConnection) GetAllWithKeyPrefix(bucketName string, keyPrefix []byte, obj interface{}, append func(o interface{}) (interface{}, error)) error {
return connection.View(func(tx *bolt.Tx) error {
cursor := tx.Bucket([]byte(bucketName)).Cursor()
for k, v := cursor.Seek(keyPrefix); k != nil && bytes.HasPrefix(k, keyPrefix); k, v = cursor.Next() {
err := connection.UnmarshalObjectWithJsoniter(v, obj)
if err != nil {
return err
}
obj, err = append(obj)
if err != nil {
return err
}
}
return nil
})
}
// BackupMetadata will return a copy of the boltdb sequence numbers for all buckets.
func (connection *DbConnection) BackupMetadata() (map[string]interface{}, error) {
buckets := map[string]interface{}{}
@ -387,6 +409,7 @@ func (connection *DbConnection) BackupMetadata() (map[string]interface{}, error)
return buckets, err
}
// RestoreMetadata will restore the boltdb sequence numbers for all buckets.
func (connection *DbConnection) RestoreMetadata(s map[string]interface{}) error {
var err error

View File

@ -31,7 +31,7 @@ func backupMetadata(connection *bolt.DB) (map[string]interface{}, error) {
// using this function.
// inspired by github.com/konoui/boltdb-exporter (which has no license)
// but very much simplified, based on how we use boltdb
func (c *DbConnection) ExportJson(databasePath string, metadata bool) ([]byte, error) {
func (c *DbConnection) ExportJSON(databasePath string, metadata bool) ([]byte, error) {
log.Debug().Str("databasePath", databasePath).Msg("exportJson")
connection, err := bolt.Open(databasePath, 0600, &bolt.Options{Timeout: 1 * time.Second, ReadOnly: true})

View File

@ -16,5 +16,6 @@ func NewDatabase(storeType, storePath string, encryptionKey []byte) (connection
EncryptionKey: encryptionKey,
}, nil
}
return nil, fmt.Errorf("unknown storage database: %s", storeType)
return nil, fmt.Errorf("Unknown storage database: %s", storeType)
}

View File

@ -85,7 +85,7 @@ func (service *Service) List() ([]edgetypes.UpdateSchedule, error) {
item, ok := obj.(*edgetypes.UpdateSchedule)
if !ok {
logrus.WithField("obj", obj).Errorf("Failed to convert to EdgeUpdateSchedule object")
return nil, fmt.Errorf("failed to convert to EdgeUpdateSchedule object: %s", obj)
return nil, fmt.Errorf("Failed to convert to EdgeUpdateSchedule object: %s", obj)
}
list = append(list, *item)
return &edgetypes.UpdateSchedule{}, nil

View File

@ -24,7 +24,6 @@ type (
BackupTo(w io.Writer) error
Export(filename string) (err error)
IsErrObjectNotFound(err error) bool
CustomTemplate() CustomTemplateService
EdgeGroup() EdgeGroupService
EdgeJob() EdgeJobService

View File

@ -156,6 +156,7 @@ func (store *Store) encryptDB() error {
if err != nil {
// Remove the new encrypted file that we failed to import
os.Remove(store.connection.GetDatabaseFilePath())
log.Fatal().Err(portainerErrors.ErrDBImportFailed).Msg("")
}

View File

@ -36,6 +36,7 @@ func (store *Store) checkOrCreateInstanceID() error {
instanceID := uid.String()
return store.VersionService.StoreInstanceID(instanceID)
}
return err
}
@ -88,7 +89,6 @@ func (store *Store) checkOrCreateDefaultSettings() error {
func (store *Store) checkOrCreateDefaultSSLSettings() error {
_, err := store.SSLSettings().Settings()
if store.IsErrObjectNotFound(err) {
defaultSSLSettings := &portainer.SSLSettings{
HTTPEnabled: true,
@ -96,6 +96,7 @@ func (store *Store) checkOrCreateDefaultSSLSettings() error {
return store.SSLSettings().UpdateSettings(defaultSSLSettings)
}
return err
}

View File

@ -259,7 +259,7 @@ func migrateDBTestHelper(t *testing.T, srcPath, wantPath string) error {
return fmt.Errorf("stat on %s failed: %s", databasePath, err)
}
gotJSON, err := con.ExportJson(databasePath, false)
gotJSON, err := con.ExportJSON(databasePath, false)
if err != nil {
t.Logf(
"failed re-exporting database %s to JSON: %v",

View File

@ -1,13 +1,12 @@
package migrator
import (
"errors"
"reflect"
"runtime"
portainer "github.com/portainer/portainer/api"
werrors "github.com/pkg/errors"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
)
@ -17,7 +16,7 @@ type migration struct {
}
func migrationError(err error, context string) error {
return werrors.Wrap(err, "failed in "+context)
return errors.Wrap(err, "failed in "+context)
}
func newMigration(dbversion int, migrate func() error) migration {

View File

@ -15,6 +15,7 @@ func (m *Migrator) updateUsersToDBVersion20() error {
}
func (m *Migrator) updateSettingsToDBVersion20() error {
log.Info().Msg("updating settings")
legacySettings, err := m.settingsService.Settings()
if err != nil {
return err

View File

@ -22,6 +22,7 @@ func (m *Migrator) updateTagsToDBVersion23() error {
return err
}
}
return nil
}

View File

@ -19,5 +19,6 @@ func (m *Migrator) MigrateSettingsToDB30() error {
legacySettings.OAuthSettings.SSO = false
legacySettings.OAuthSettings.LogoutURI = ""
return m.settingsService.UpdateSettings(legacySettings)
}

View File

@ -13,6 +13,7 @@ func (m *Migrator) migrateDBVersionToDB33() error {
}
func (m *Migrator) migrateSettingsToDB33() error {
log.Info().Msg("setting default kubctl shell")
settings, err := m.settingsService.Settings()
if err != nil {
return err

View File

@ -14,6 +14,8 @@ func (m *Migrator) migrateDBVersionToDB36() error {
}
func (m *Migrator) migrateUsersToDB36() error {
log.Info().Msg("updating user authorizations")
users, err := m.userService.Users()
if err != nil {
return err

View File

@ -2,6 +2,7 @@ package migrator
import (
portainer "github.com/portainer/portainer/api"
"github.com/rs/zerolog/log"
)

View File

@ -518,7 +518,7 @@ func (store *Store) Export(filename string) (err error) {
if snapshot, err := store.Snapshot().Snapshots(); err != nil {
if !store.IsErrObjectNotFound(err) {
log.Err(err).Msg("Exporting Snapshots")
log.Error().Err(err).Msg("exporting Snapshots")
}
} else {
backup.Snapshot = snapshot
@ -707,7 +707,7 @@ func (store *Store) Import(filename string) (err error) {
for _, user := range backup.User {
if err := store.User().UpdateUser(user.ID, &user); err != nil {
log.Debug().Str("user", fmt.Sprintf("%+v", user)).Err(err).Msg("user: failed to Update Database")
log.Debug().Str("user", fmt.Sprintf("%+v", user)).Err(err).Msg("failed to update the user in the database")
}
}

6
api/docker/labels.go Normal file
View File

@ -0,0 +1,6 @@
package docker
const (
ComposeStackNameLabel = "com.docker.compose.project"
SwarmStackNameLabel = "com.docker.stack.namespace"
)

View File

@ -194,7 +194,7 @@ func snapshotContainers(snapshot *portainer.DockerSnapshot, cli *client.Client)
}
for k, v := range container.Labels {
if k == "com.docker.compose.project" {
if k == ComposeStackNameLabel {
stacks[v] = struct{}{}
}
}

View File

@ -8,15 +8,14 @@ import (
"path"
"strings"
"github.com/pkg/errors"
libstack "github.com/portainer/docker-compose-wrapper"
"github.com/portainer/docker-compose-wrapper/compose"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/http/proxy"
"github.com/portainer/portainer/api/http/proxy/factory"
"github.com/portainer/portainer/api/internal/stackutils"
"github.com/pkg/errors"
)
// ComposeStackManager is a wrapper for docker-compose binary

View File

@ -6,6 +6,7 @@ import (
type kubernetesMockDeployer struct{}
// NewKubernetesDeployer creates a mock kubernetes deployer
func NewKubernetesDeployer() portainer.KubernetesDeployer {
return &kubernetesMockDeployer{}
}

View File

@ -9,14 +9,14 @@ import (
"runtime"
"strings"
"github.com/pkg/errors"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/dataservices"
"github.com/portainer/portainer/api/http/proxy"
"github.com/portainer/portainer/api/http/proxy/factory"
"github.com/portainer/portainer/api/http/proxy/factory/kubernetes"
"github.com/portainer/portainer/api/kubernetes/cli"
portainer "github.com/portainer/portainer/api"
"github.com/pkg/errors"
)
// KubernetesDeployer represents a service to deploy resources inside a Kubernetes environment(endpoint).
@ -73,6 +73,7 @@ func (deployer *KubernetesDeployer) getToken(userID portainer.UserID, endpoint *
if token == "" {
return "", fmt.Errorf("can not get a valid user service account token")
}
return token, nil
}

View File

@ -1,7 +1,6 @@
package auth
import (
"errors"
"net/http"
"strings"
@ -13,6 +12,7 @@ import (
"github.com/portainer/portainer/api/internal/authorization"
"github.com/asaskevich/govalidator"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
)

View File

@ -22,6 +22,7 @@ func (payload *oauthPayload) Validate(r *http.Request) error {
if govalidator.IsNull(payload.Code) {
return errors.New("Invalid OAuth authorization code")
}
return nil
}

View File

@ -3,13 +3,14 @@ package auth
import (
"net/http"
"github.com/gorilla/mux"
httperror "github.com/portainer/libhttp/error"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/dataservices"
"github.com/portainer/portainer/api/http/proxy"
"github.com/portainer/portainer/api/http/proxy/factory/kubernetes"
"github.com/portainer/portainer/api/http/security"
"github.com/gorilla/mux"
)
// Handler is the HTTP handler used to handle authentication operations.

View File

@ -56,6 +56,7 @@ func Test_backupHandlerWithoutPassword_shouldCreateATarballArchive(t *testing.T)
body, _ := io.ReadAll(response.Body)
tmpdir := t.TempDir()
archivePath := filepath.Join(tmpdir, "archive.tar.gz")
err := ioutil.WriteFile(archivePath, body, 0600)
if err != nil {
@ -91,6 +92,7 @@ func Test_backupHandlerWithPassword_shouldCreateEncryptedATarballArchive(t *test
body, _ := io.ReadAll(response.Body)
tmpdir := t.TempDir()
dr, err := crypto.AesDecrypt(bytes.NewReader(body), []byte("secret"))
if err != nil {
t.Fatal("Failed to decrypt archive")

View File

@ -3,6 +3,7 @@ package customtemplates
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"os"
"regexp"
@ -13,6 +14,7 @@ import (
"github.com/portainer/libhttp/response"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/filesystem"
"github.com/portainer/portainer/api/git"
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/internal/authorization"
@ -290,6 +292,9 @@ func (handler *Handler) createCustomTemplateFromGitRepository(r *http.Request) (
err = handler.GitService.CloneRepository(projectPath, payload.RepositoryURL, payload.RepositoryReferenceName, repositoryUsername, repositoryPassword)
if err != nil {
if err == git.ErrAuthenticationFailure {
return nil, fmt.Errorf("invalid git credential")
}
return nil, err
}

View File

@ -4,11 +4,13 @@ import (
"errors"
"net/http"
"github.com/asaskevich/govalidator"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
"github.com/portainer/libhttp/response"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/internal/endpointutils"
"github.com/asaskevich/govalidator"
)
type edgeGroupCreatePayload struct {
@ -81,7 +83,7 @@ func (handler *Handler) edgeGroupCreate(w http.ResponseWriter, r *http.Request)
return httperror.InternalServerError("Unable to retrieve environment from the database", err)
}
if endpoint.Type == portainer.EdgeAgentOnDockerEnvironment || endpoint.Type == portainer.EdgeAgentOnKubernetesEnvironment {
if endpointutils.IsEdgeEndpoint(endpoint) {
endpointIDs = append(endpointIDs, endpoint.ID)
}
}

View File

@ -53,5 +53,4 @@ func (handler *Handler) edgeGroupDelete(w http.ResponseWriter, r *http.Request)
}
return response.Empty(w)
}

View File

@ -81,7 +81,7 @@ func getEndpointTypes(endpointService dataservices.EndpointService, endpointIds
for _, endpointID := range endpointIds {
endpoint, err := endpointService.Endpoint(endpointID)
if err != nil {
return nil, fmt.Errorf("failed fetching endpoint: %w", err)
return nil, fmt.Errorf("failed fetching environment: %w", err)
}
typeSet[endpoint.Type] = true

View File

@ -4,12 +4,14 @@ import (
"errors"
"net/http"
"github.com/asaskevich/govalidator"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
"github.com/portainer/libhttp/response"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/internal/edge"
"github.com/portainer/portainer/api/internal/endpointutils"
"github.com/asaskevich/govalidator"
)
type edgeGroupUpdatePayload struct {
@ -102,7 +104,7 @@ func (handler *Handler) edgeGroupUpdate(w http.ResponseWriter, r *http.Request)
return httperror.InternalServerError("Unable to retrieve environment from the database", err)
}
if endpoint.Type == portainer.EdgeAgentOnDockerEnvironment || endpoint.Type == portainer.EdgeAgentOnKubernetesEnvironment {
if endpointutils.IsEdgeEndpoint(endpoint) {
endpointIDs = append(endpointIDs, endpoint.ID)
}
}

View File

@ -12,6 +12,7 @@ import (
"github.com/portainer/libhttp/request"
"github.com/portainer/libhttp/response"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/internal/endpointutils"
)
// @id EdgeJobCreate
@ -200,7 +201,7 @@ func (handler *Handler) addAndPersistEdgeJob(edgeJob *portainer.EdgeJob, file []
return err
}
if endpoint.Type != portainer.EdgeAgentOnDockerEnvironment && endpoint.Type != portainer.EdgeAgentOnKubernetesEnvironment {
if !endpointutils.IsEdgeEndpoint(endpoint) {
delete(edgeJob.Endpoints, ID)
}
}

View File

@ -5,11 +5,12 @@ import (
"net/http"
"strconv"
"github.com/asaskevich/govalidator"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
"github.com/portainer/libhttp/response"
portainer "github.com/portainer/portainer/api"
"github.com/asaskevich/govalidator"
)
type edgeJobUpdatePayload struct {

View File

@ -1,14 +1,12 @@
package edgestacks
import (
"errors"
"fmt"
"net/http"
"strconv"
"strings"
"time"
"github.com/asaskevich/govalidator"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
"github.com/portainer/libhttp/response"
@ -16,6 +14,9 @@ import (
"github.com/portainer/portainer/api/dataservices"
"github.com/portainer/portainer/api/filesystem"
"github.com/portainer/portainer/api/internal/edge"
"github.com/asaskevich/govalidator"
"github.com/pkg/errors"
)
// @id EdgeStackCreate
@ -271,7 +272,7 @@ func (handler *Handler) createSwarmStackFromGitRepository(r *http.Request) (*por
err = updateEndpointRelations(handler.DataStore.EndpointRelation(), stack.ID, relatedEndpointIds)
if err != nil {
return nil, fmt.Errorf("Unable to update endpoint relations: %w", err)
return nil, fmt.Errorf("Unable to update environment relations: %w", err)
}
err = handler.DataStore.EdgeStack().Create(stack.ID, stack)
@ -378,7 +379,7 @@ func (handler *Handler) createSwarmStackFromFileUpload(r *http.Request) (*portai
err = updateEndpointRelations(handler.DataStore.EndpointRelation(), stack.ID, relatedEndpointIds)
if err != nil {
return nil, fmt.Errorf("Unable to update endpoint relations: %w", err)
return nil, fmt.Errorf("Unable to update environment relations: %w", err)
}
err = handler.DataStore.EdgeStack().Create(stack.ID, stack)
@ -408,14 +409,14 @@ func updateEndpointRelations(endpointRelationService dataservices.EndpointRelati
for _, endpointID := range relatedEndpointIds {
relation, err := endpointRelationService.EndpointRelation(endpointID)
if err != nil {
return fmt.Errorf("unable to find endpoint relation in database: %w", err)
return fmt.Errorf("unable to find environment relation in database: %w", err)
}
relation.EdgeStacks[edgeStackID] = true
err = endpointRelationService.UpdateEndpointRelation(endpointID, relation)
if err != nil {
return fmt.Errorf("unable to persist endpoint relation in database: %w", err)
return fmt.Errorf("unable to persist environment relation in database: %w", err)
}
}

View File

@ -5,6 +5,7 @@ import (
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/internal/testhelpers"
"github.com/stretchr/testify/assert"
)

View File

@ -42,7 +42,7 @@ func (handler *Handler) edgeStackDelete(w http.ResponseWriter, r *http.Request)
relationConfig, err := fetchEndpointRelationsConfig(handler.DataStore)
if err != nil {
return httperror.InternalServerError("Unable to retrieve environments relations config from database", err)
return httperror.InternalServerError("Unable to find environment relations in database", err)
}
relatedEndpointIds, err := edge.EdgeStackRelatedEndpoints(edgeStack.EdgeGroups, relationConfig.endpoints, relationConfig.endpointGroups, relationConfig.edgeGroups)

View File

@ -46,7 +46,7 @@ func (handler *Handler) edgeStackFile(w http.ResponseWriter, r *http.Request) *h
stackFileContent, err := handler.FileService.GetFileContent(stack.ProjectPath, fileName)
if err != nil {
return httperror.InternalServerError("Unable to retrieve Compose file from disk", err)
return httperror.InternalServerError("Unable to retrieve stack file from disk", err)
}
return response.JSON(w, &stackFileResponse{StackFileContent: string(stackFileContent)})

View File

@ -3,7 +3,6 @@ package edgestacks
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"net/http/httptest"
@ -19,6 +18,8 @@ import (
"github.com/portainer/portainer/api/filesystem"
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/jwt"
"github.com/pkg/errors"
)
type gitService struct {

View File

@ -2,7 +2,6 @@ package edgestacks
import (
"errors"
"github.com/portainer/portainer/api/internal/endpointutils"
"net/http"
"strconv"
@ -12,6 +11,7 @@ import (
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/filesystem"
"github.com/portainer/portainer/api/internal/edge"
"github.com/portainer/portainer/api/internal/endpointutils"
)
type updateEdgeStackPayload struct {

View File

@ -31,14 +31,14 @@ func (payload *createPayload) Validate(r *http.Request) error {
return errors.New("Required to choose at least one group")
}
if payload.Type != edgetypes.UpdateScheduleRollback && payload.Type != edgetypes.UpdateScheduleUpdate {
return errors.New("Invalid schedule type")
}
if len(payload.Environments) == 0 {
return errors.New("No Environment is scheduled for update")
}
if payload.Type != edgetypes.UpdateScheduleRollback && payload.Type != edgetypes.UpdateScheduleUpdate {
return errors.New("Invalid schedule type")
}
if payload.Time < time.Now().Unix() {
return errors.New("Invalid time")
}

View File

@ -3,14 +3,13 @@ package endpointedge
import (
"net/http"
"github.com/portainer/portainer/api/http/middlewares"
httperror "github.com/portainer/libhttp/error"
"github.com/gorilla/mux"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/dataservices"
"github.com/portainer/portainer/api/http/middlewares"
"github.com/portainer/portainer/api/http/security"
"github.com/gorilla/mux"
)
// Handler is the HTTP handler used to handle edge environment(endpoint) operations.

View File

@ -2,13 +2,13 @@ package endpointproxy
import (
"errors"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
portainer "github.com/portainer/portainer/api"
"net/http"
"strconv"
"strings"
"net/http"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
portainer "github.com/portainer/portainer/api"
)
func (handler *Handler) proxyRequestsToDockerAPI(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {

View File

@ -3,12 +3,12 @@ package endpointproxy
import (
"errors"
"fmt"
"net/http"
"strings"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
portainer "github.com/portainer/portainer/api"
"strings"
"net/http"
)
func (handler *Handler) proxyRequestsToKubernetesAPI(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {

View File

@ -102,7 +102,6 @@ func Test_EndpointList_AgentVersion(t *testing.T) {
is.ElementsMatch(test.expected, respIds)
})
}
}
func Test_endpointList_edgeDeviceFilter(t *testing.T) {

View File

@ -32,6 +32,10 @@ func (handler *Handler) endpointSnapshots(w http.ResponseWriter, r *http.Request
continue
}
if endpoint.URL == "" {
continue
}
snapshotError := handler.SnapshotService.SnapshotEndpoint(&endpoint)
latestEndpointReference, err := handler.DataStore.Endpoint().Endpoint(endpoint.ID)

View File

@ -38,8 +38,6 @@ func (handler *Handler) helmList(w http.ResponseWriter, r *http.Request) *httper
KubernetesClusterAccess: clusterAccess,
}
params := r.URL.Query()
// optional namespace. The library defaults to "default"
namespace, _ := request.RetrieveQueryParameter(r, "namespace", true)
if namespace != "" {
@ -47,12 +45,12 @@ func (handler *Handler) helmList(w http.ResponseWriter, r *http.Request) *httper
}
// optional filter
if filter := params.Get("filter"); filter != "" {
if filter, _ := request.RetrieveQueryParameter(r, "filter", true); filter != "" {
listOpts.Filter = filter
}
// optional selector
if selector := params.Get("selector"); selector != "" {
if selector, _ := request.RetrieveQueryParameter(r, "selector", true); selector != "" {
listOpts.Selector = selector
}

View File

@ -9,7 +9,6 @@ import (
"testing"
"github.com/portainer/libhelm/binary/test"
helper "github.com/portainer/portainer/api/internal/testhelpers"
"github.com/stretchr/testify/assert"
)
@ -32,6 +31,7 @@ func Test_helmRepoSearch(t *testing.T) {
h.ServeHTTP(rr, req)
is.Equal(http.StatusOK, rr.Code, "Status should be 200 OK")
body, err := io.ReadAll(rr.Body)
is.NoError(err, "ReadAll should not return error")
is.NotEmpty(body, "Body should not be empty")

View File

@ -5,11 +5,11 @@ import (
"net/http"
"net/url"
"github.com/pkg/errors"
"github.com/portainer/libhelm/options"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
)

View File

@ -56,6 +56,7 @@ func (handler *Handler) userCreateHelmRepo(w http.ResponseWriter, r *http.Reques
if err != nil {
return httperror.BadRequest("Invalid Helm repository URL", err)
}
// lowercase, remove trailing slash
p.URL = strings.TrimSuffix(strings.ToLower(p.URL), "/")

View File

@ -89,7 +89,7 @@ func (handler *Handler) fdoConfigure(w http.ResponseWriter, r *http.Request) *ht
err := request.DecodeAndValidateJSONPayload(r, &payload)
if err != nil {
log.Error().Err(err).Msg("Invalid request payload")
log.Error().Err(err).Msg("invalid request payload")
return httperror.BadRequest("Invalid request payload", err)
}

View File

@ -3,13 +3,14 @@ package fdo
import (
"errors"
"fmt"
"net/http"
"strconv"
"time"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
"github.com/portainer/libhttp/response"
portainer "github.com/portainer/portainer/api"
"net/http"
"strconv"
"time"
)
// @id duplicate

View File

@ -38,7 +38,7 @@ func (handler *Handler) getKubernetesConfig(w http.ResponseWriter, r *http.Reque
if err != nil {
return httperror.Forbidden("Permission denied to access environment", err)
}
bearerToken, err := handler.jwtService.GenerateTokenForKubeconfig(tokenData)
bearerToken, err := handler.JwtService.GenerateTokenForKubeconfig(tokenData)
if err != nil {
return httperror.InternalServerError("Unable to generate JWT token", err)
}
@ -75,7 +75,7 @@ func (handler *Handler) filterUserKubeEndpoints(r *http.Request) ([]portainer.En
return nil, httperror.InternalServerError("Unable to retrieve info from request context", err)
}
endpointGroups, err := handler.dataStore.EndpointGroup().EndpointGroups()
endpointGroups, err := handler.DataStore.EndpointGroup().EndpointGroups()
if err != nil {
return nil, httperror.InternalServerError("Unable to retrieve environment groups from the database", err)
}
@ -83,7 +83,7 @@ func (handler *Handler) filterUserKubeEndpoints(r *http.Request) ([]portainer.En
if len(endpointIDs) > 0 {
var endpoints []portainer.Endpoint
for _, endpointID := range endpointIDs {
endpoint, err := handler.dataStore.Endpoint().Endpoint(endpointID)
endpoint, err := handler.DataStore.Endpoint().Endpoint(endpointID)
if err != nil {
return nil, httperror.InternalServerError("Unable to retrieve environment from the database", err)
}
@ -97,7 +97,7 @@ func (handler *Handler) filterUserKubeEndpoints(r *http.Request) ([]portainer.En
}
var kubeEndpoints []portainer.Endpoint
endpoints, err := handler.dataStore.Endpoint().Endpoints()
endpoints, err := handler.DataStore.Endpoint().Endpoints()
if err != nil {
return nil, httperror.InternalServerError("Unable to retrieve environments from the database", err)
}
@ -122,7 +122,7 @@ func (handler *Handler) buildConfig(r *http.Request, tokenData *portainer.TokenD
authInfosSet := make(map[string]bool)
for idx, endpoint := range endpoints {
instanceID := handler.kubernetesClientFactory.GetInstanceID()
instanceID := handler.KubernetesClientFactory.GetInstanceID()
serviceAccountName := kcli.UserServiceAccountName(int(tokenData.ID), instanceID)
configClusters[idx] = handler.buildCluster(r, endpoint)
@ -145,6 +145,7 @@ func (handler *Handler) buildConfig(r *http.Request, tokenData *portainer.TokenD
func (handler *Handler) buildCluster(r *http.Request, endpoint portainer.Endpoint) clientV1.NamedCluster {
kubeConfigInternal := handler.kubeClusterAccessService.GetData(r.Host, endpoint.ID)
return clientV1.NamedCluster{
Name: buildClusterName(endpoint.Name),
Cluster: clientV1.Cluster{

View File

@ -23,10 +23,10 @@ import (
type Handler struct {
*mux.Router
authorizationService *authorization.Service
dataStore dataservices.DataStore
DataStore dataservices.DataStore
KubernetesClient portainer.KubeClient
kubernetesClientFactory *cli.ClientFactory
jwtService dataservices.JWTService
KubernetesClientFactory *cli.ClientFactory
JwtService dataservices.JWTService
kubeClusterAccessService kubernetes.KubeClusterAccessService
}
@ -35,10 +35,10 @@ func NewHandler(bouncer *security.RequestBouncer, authorizationService *authoriz
h := &Handler{
Router: mux.NewRouter(),
authorizationService: authorizationService,
dataStore: dataStore,
jwtService: jwtService,
DataStore: dataStore,
JwtService: jwtService,
kubeClusterAccessService: kubeClusterAccessService,
kubernetesClientFactory: kubernetesClientFactory,
KubernetesClientFactory: kubernetesClientFactory,
KubernetesClient: kubernetesClient,
}
@ -90,7 +90,7 @@ func kubeOnlyMiddleware(next http.Handler) http.Handler {
}
if !endpointutils.IsKubernetesEndpoint(endpoint) {
errMessage := "Environment is not a kubernetes environment"
errMessage := "environment is not a Kubernetes environment"
httperror.WriteError(rw, http.StatusBadRequest, errMessage, errors.New(errMessage))
return
}
@ -111,7 +111,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 {
httperror.WriteError(
w,
@ -128,11 +128,11 @@ func (handler *Handler) kubeClient(next http.Handler) http.Handler {
)
}
if handler.kubernetesClientFactory == nil {
if handler.KubernetesClientFactory == nil {
next.ServeHTTP(w, r)
return
}
kubeCli, err := handler.kubernetesClientFactory.GetKubeClient(endpoint)
kubeCli, err := handler.KubernetesClientFactory.GetKubeClient(endpoint)
if err != nil {
httperror.WriteError(
w,

View File

@ -20,7 +20,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 {
return httperror.NotFound(
"Unable to find an environment with the specified identifier inside the database",
@ -41,7 +41,7 @@ func (handler *Handler) getKubernetesIngressControllers(w http.ResponseWriter, r
)
}
cli, err := handler.kubernetesClientFactory.GetKubeClient(endpoint)
cli, err := handler.KubernetesClientFactory.GetKubeClient(endpoint)
if err != nil {
return httperror.InternalServerError(
"Unable to create Kubernetes client",
@ -86,7 +86,7 @@ func (handler *Handler) getKubernetesIngressControllers(w http.ResponseWriter, r
newClasses = append(newClasses, class)
}
endpoint.Kubernetes.Configuration.IngressClasses = newClasses
err = handler.dataStore.Endpoint().UpdateEndpoint(
err = handler.DataStore.Endpoint().UpdateEndpoint(
portainer.EndpointID(endpointID),
endpoint,
)
@ -120,8 +120,8 @@ func (handler *Handler) getKubernetesIngressControllersByNamespace(w http.Respon
)
}
endpoint, err := handler.dataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
if err == portainerDsErrors.ErrObjectNotFound {
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
if handler.DataStore.IsErrObjectNotFound(err) {
return httperror.NotFound(
"Unable to find an environment with the specified identifier inside the database",
err,
@ -183,7 +183,7 @@ func (handler *Handler) getKubernetesIngressControllersByNamespace(w http.Respon
// Update the database to match the list of found controllers.
// This includes pruning out controllers which no longer exist.
endpoint.Kubernetes.Configuration.IngressClasses = updatedClasses
err = handler.dataStore.Endpoint().UpdateEndpoint(
err = handler.DataStore.Endpoint().UpdateEndpoint(
portainer.EndpointID(endpointID),
endpoint,
)
@ -205,8 +205,8 @@ func (handler *Handler) updateKubernetesIngressControllers(w http.ResponseWriter
)
}
endpoint, err := handler.dataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
if err == portainerDsErrors.ErrObjectNotFound {
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
if handler.DataStore.IsErrObjectNotFound(err) {
return httperror.NotFound(
"Unable to find an environment with the specified identifier inside the database",
err,
@ -227,7 +227,7 @@ func (handler *Handler) updateKubernetesIngressControllers(w http.ResponseWriter
)
}
cli, err := handler.kubernetesClientFactory.GetKubeClient(endpoint)
cli, err := handler.KubernetesClientFactory.GetKubeClient(endpoint)
if err != nil {
return httperror.InternalServerError(
"Unable to create Kubernetes client",
@ -269,7 +269,7 @@ func (handler *Handler) updateKubernetesIngressControllers(w http.ResponseWriter
}
endpoint.Kubernetes.Configuration.IngressClasses = newClasses
err = handler.dataStore.Endpoint().UpdateEndpoint(
err = handler.DataStore.Endpoint().UpdateEndpoint(
portainer.EndpointID(endpointID),
endpoint,
)
@ -291,8 +291,8 @@ func (handler *Handler) updateKubernetesIngressControllersByNamespace(w http.Res
)
}
endpoint, err := handler.dataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
if err == portainerDsErrors.ErrObjectNotFound {
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
if handler.DataStore.IsErrObjectNotFound(err) {
return httperror.NotFound(
"Unable to find an environment with the specified identifier inside the database",
err,
@ -369,7 +369,7 @@ PayloadLoop:
}
endpoint.Kubernetes.Configuration.IngressClasses = updatedClasses
err = handler.dataStore.Endpoint().UpdateEndpoint(
err = handler.DataStore.Endpoint().UpdateEndpoint(
portainer.EndpointID(endpointID),
endpoint,
)

View File

@ -73,20 +73,12 @@ func (handler *Handler) updateKubernetesNamespace(w http.ResponseWriter, r *http
var payload models.K8sNamespaceDetails
err := request.DecodeAndValidateJSONPayload(r, &payload)
if err != nil {
return &httperror.HandlerError{
StatusCode: http.StatusBadRequest,
Message: "Invalid request payload",
Err: err,
}
return httperror.BadRequest("Invalid request payload", err)
}
err = cli.UpdateNamespace(payload)
if err != nil {
return &httperror.HandlerError{
StatusCode: http.StatusInternalServerError,
Message: "Unable to retrieve nodes limits",
Err: err,
}
return httperror.InternalServerError("Unable to retrieve nodes limits", err)
}
return nil
}

View File

@ -32,14 +32,14 @@ func (handler *Handler) getKubernetesNodesLimits(w http.ResponseWriter, r *http.
return httperror.BadRequest("Invalid environment identifier route variable", err)
}
endpoint, err := handler.dataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
if handler.dataStore.IsErrObjectNotFound(err) {
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
if handler.DataStore.IsErrObjectNotFound(err) {
return httperror.NotFound("Unable to find an environment with the specified identifier inside the database", err)
} else if err != nil {
return httperror.InternalServerError("Unable to find an environment with the specified identifier inside the database", err)
}
cli, err := handler.kubernetesClientFactory.GetKubeClient(endpoint)
cli, err := handler.KubernetesClientFactory.GetKubeClient(endpoint)
if err != nil {
return httperror.InternalServerError("Unable to create Kubernetes client", err)
}

View File

@ -51,7 +51,7 @@ func (handler *Handler) namespacesToggleSystem(rw http.ResponseWriter, r *http.R
return httperror.BadRequest("Invalid request payload", err)
}
kubeClient, err := handler.kubernetesClientFactory.GetKubeClient(endpoint)
kubeClient, err := handler.KubernetesClientFactory.GetKubeClient(endpoint)
if err != nil {
return httperror.InternalServerError("Unable to create kubernetes client", err)
}

View File

@ -119,9 +119,7 @@ func (handler *Handler) registryCreate(w http.ResponseWriter, r *http.Request) *
Ecr: payload.Ecr,
}
rs := handler.DataStore.Registry()
registries, err := rs.Registries()
registries, err := handler.DataStore.Registry().Registries()
if err != nil {
return httperror.InternalServerError("Unable to retrieve registries from the database", err)
}
@ -134,7 +132,7 @@ func (handler *Handler) registryCreate(w http.ResponseWriter, r *http.Request) *
}
}
err = rs.Create(registry)
err = handler.DataStore.Registry().Create(registry)
if err != nil {
return httperror.InternalServerError("Unable to persist the registry inside the database", err)
}

View File

@ -74,7 +74,7 @@ func delete_TestHandler_registryUpdate(t *testing.T) {
},
}
handler.Router.ServeHTTP(w, r)
handler.ServeHTTP(w, r)
assert.Equal(t, http.StatusOK, w.Code)
// Registry type should remain intact
assert.Equal(t, registry.Type, updatedRegistry.Type)
@ -85,5 +85,4 @@ func delete_TestHandler_registryUpdate(t *testing.T) {
assert.Equal(t, *payload.Authentication, updatedRegistry.Authentication)
assert.Equal(t, *payload.Username, updatedRegistry.Username)
assert.Equal(t, *payload.Password, updatedRegistry.Password)
}

View File

@ -141,7 +141,6 @@ func (handler *Handler) settingsUpdate(w http.ResponseWriter, r *http.Request) *
if err != nil {
return httperror.BadRequest("Invalid Helm repository URL. Must correspond to a valid URL format", err)
}
}
settings.HelmRepositoryURL = newHelmRepo
@ -161,12 +160,15 @@ func (handler *Handler) settingsUpdate(w http.ResponseWriter, r *http.Request) *
if payload.LDAPSettings != nil {
ldapReaderDN := settings.LDAPSettings.ReaderDN
ldapPassword := settings.LDAPSettings.Password
if payload.LDAPSettings.ReaderDN != "" {
ldapReaderDN = payload.LDAPSettings.ReaderDN
}
if payload.LDAPSettings.Password != "" {
ldapPassword = payload.LDAPSettings.Password
}
settings.LDAPSettings = *payload.LDAPSettings
settings.LDAPSettings.ReaderDN = ldapReaderDN
settings.LDAPSettings.Password = ldapPassword

View File

@ -6,8 +6,6 @@ import (
"strconv"
"time"
"github.com/asaskevich/govalidator"
"github.com/pkg/errors"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
portainer "github.com/portainer/portainer/api"
@ -16,6 +14,8 @@ import (
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/internal/stackutils"
"github.com/asaskevich/govalidator"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
)
@ -438,6 +438,7 @@ func (handler *Handler) createComposeDeployConfig(r *http.Request, stack *portai
if err != nil {
return nil, httperror.InternalServerError("Unable to retrieve registries from the database", err)
}
filteredRegistries := security.FilterRegistries(registries, user, securityContext.UserMemberships, endpoint.ID)
config := &composeStackDeploymentConfig{

View File

@ -8,9 +8,8 @@ import (
"strconv"
"time"
"github.com/pkg/errors"
"github.com/asaskevich/govalidator"
"github.com/pkg/errors"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
@ -133,6 +132,7 @@ func (handler *Handler) createKubernetesStackFromFileContent(w http.ResponseWrit
}
stackFolder := strconv.Itoa(int(stack.ID))
projectPath, err := handler.FileService.StoreStackFileFromBytes(stackFolder, stack.EntryPoint, []byte(payload.StackFileContent))
if err != nil {
fileType := "Manifest"
@ -274,7 +274,7 @@ func (handler *Handler) createKubernetesStackFromGitRepository(w http.ResponseWr
err = handler.DataStore.Stack().Create(stack)
if err != nil {
return httperror.InternalServerError("Unable to persist the stack inside the database", err)
return httperror.InternalServerError("Unable to persist the Kubernetes stack inside the database", err)
}
resp := &createKubernetesStackResponse{

View File

@ -6,9 +6,9 @@ import (
"strconv"
"time"
"github.com/asaskevich/govalidator"
"github.com/pkg/errors"
"github.com/asaskevich/govalidator"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
portainer "github.com/portainer/portainer/api"
@ -378,6 +378,7 @@ func (handler *Handler) createSwarmDeployConfig(r *http.Request, stack *portaine
if err != nil {
return nil, httperror.InternalServerError("Unable to retrieve registries from the database", err)
}
filteredRegistries := security.FilterRegistries(registries, user, securityContext.UserMemberships, endpoint.ID)
config := &swarmStackDeploymentConfig{

View File

@ -199,7 +199,7 @@ func (handler *Handler) deleteStack(userID portainer.UserID, stack *portainer.St
//then process the remove operation
if stack.IsComposeFormat {
fileNames := append([]string{stack.EntryPoint}, stack.AdditionalFiles...)
tmpDir, err := ioutil.TempDir("", "kub_delete")
tmpDir, err := ioutil.TempDir("", "kube_delete")
if err != nil {
return errors.Wrap(err, "failed to create temp directory for deleting kub stack")
}

View File

@ -1,12 +1,12 @@
package teammemberships
import (
"net/http"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/portainer/api/dataservices"
"github.com/portainer/portainer/api/http/security"
"net/http"
"github.com/gorilla/mux"
)

View File

@ -5,13 +5,14 @@ import (
"net/http"
"time"
"github.com/asaskevich/govalidator"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
"github.com/portainer/libhttp/response"
portainer "github.com/portainer/portainer/api"
httperrors "github.com/portainer/portainer/api/http/errors"
"github.com/portainer/portainer/api/http/security"
"github.com/asaskevich/govalidator"
)
type userUpdatePayload struct {
@ -122,5 +123,6 @@ func (handler *Handler) userUpdate(w http.ResponseWriter, r *http.Request) *http
// remove all of the users persisted API keys
handler.apiKeyService.InvalidateUserKeyCache(user.ID)
return response.JSON(w, user)
}

View File

@ -5,13 +5,14 @@ import (
"net/http"
"time"
"github.com/asaskevich/govalidator"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
"github.com/portainer/libhttp/response"
portainer "github.com/portainer/portainer/api"
httperrors "github.com/portainer/portainer/api/http/errors"
"github.com/portainer/portainer/api/http/security"
"github.com/asaskevich/govalidator"
)
type userUpdatePasswordPayload struct {

View File

@ -5,11 +5,12 @@ import (
"github.com/portainer/portainer/api/internal/authorization"
"net/http"
"github.com/gorilla/mux"
httperror "github.com/portainer/libhttp/error"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/docker"
"github.com/portainer/portainer/api/http/security"
"github.com/gorilla/mux"
)
// Handler is the HTTP handler used to handle webhook operations.

View File

@ -7,12 +7,13 @@ import (
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/internal/registryutils/access"
"github.com/asaskevich/govalidator"
"github.com/gofrs/uuid"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
"github.com/portainer/libhttp/response"
portainer "github.com/portainer/portainer/api"
"github.com/asaskevich/govalidator"
"github.com/gofrs/uuid"
)
type webhookCreatePayload struct {

View File

@ -6,11 +6,12 @@ import (
"net/http/httputil"
"time"
"github.com/asaskevich/govalidator"
"github.com/gorilla/websocket"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
portainer "github.com/portainer/portainer/api"
"github.com/asaskevich/govalidator"
"github.com/gorilla/websocket"
)
// @summary Attach a websocket

View File

@ -8,11 +8,12 @@ import (
"net/http/httputil"
"time"
"github.com/asaskevich/govalidator"
"github.com/gorilla/websocket"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
portainer "github.com/portainer/portainer/api"
"github.com/asaskevich/govalidator"
"github.com/gorilla/websocket"
)
type execStartOperationPayload struct {

View File

@ -2,10 +2,11 @@ package websocket
import (
"crypto/tls"
"github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/crypto"
"net"
"net/url"
"github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/crypto"
)
func initDial(endpoint *portainer.Endpoint) (net.Conn, error) {

View File

@ -91,12 +91,14 @@ func (handler *Handler) websocketPodExec(w http.ResponseWriter, r *http.Request)
if err != nil {
return httperror.InternalServerError("Unable to proxy websocket request to agent", err)
}
return nil
} else if endpoint.Type == portainer.EdgeAgentOnKubernetesEnvironment {
err := handler.proxyEdgeAgentWebsocketRequest(w, r, params)
if err != nil {
return httperror.InternalServerError("Unable to proxy websocket request to Edge agent", err)
}
return nil
}

View File

@ -1,8 +1,6 @@
package websocket
import (
"github.com/portainer/portainer/api"
)
import "github.com/portainer/portainer/api"
type webSocketRequestParams struct {
ID string

View File

@ -23,7 +23,7 @@ func (transport *Transport) proxyContainerGroupRequest(request *http.Request) (*
}
func (transport *Transport) proxyContainerGroupPutRequest(request *http.Request) (*http.Response, error) {
//add a lock before processing existense check
//add a lock before processing existence check
transport.mutex.Lock()
defer transport.mutex.Unlock()

View File

@ -24,7 +24,6 @@ func (transport *Transport) applyPortainerContainers(resources []interface{}) ([
continue
}
responseObject, _ = transport.applyPortainerContainer(responseObject)
decoratedResourceData = append(decoratedResourceData, responseObject)
}
return decoratedResourceData, nil

View File

@ -18,6 +18,8 @@ type edgeTransport struct {
// NewAgentTransport returns a new transport that can be used to send signed requests to a Portainer Edge agent
func NewEdgeTransport(dataStore dataservices.DataStore, signatureService portainer.DigitalSignatureService, reverseTunnelService portainer.ReverseTunnelService, endpoint *portainer.Endpoint, tokenManager *tokenManager, k8sClientFactory *cli.ClientFactory) *edgeTransport {
transport := &edgeTransport{
reverseTunnelService: reverseTunnelService,
signatureService: signatureService,
baseTransport: newBaseTransport(
&http.Transport{},
tokenManager,
@ -25,8 +27,6 @@ func NewEdgeTransport(dataStore dataservices.DataStore, signatureService portain
k8sClientFactory,
dataStore,
),
reverseTunnelService: reverseTunnelService,
signatureService: signatureService,
}
return transport

View File

@ -1,8 +1,9 @@
package kubernetes
import (
"github.com/portainer/portainer/api/internal/registryutils"
"net/http"
"github.com/portainer/portainer/api/internal/registryutils"
)
func (transport *baseTransport) refreshRegistry(request *http.Request, namespace string) (err error) {

View File

@ -4,7 +4,7 @@ import (
"strconv"
"sync"
"github.com/orcaman/concurrent-map"
cmap "github.com/orcaman/concurrent-map"
)
type (

View File

@ -3,7 +3,6 @@ package kubernetes
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
@ -17,6 +16,7 @@ import (
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/kubernetes/cli"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
)

View File

@ -87,7 +87,7 @@ func marshal(contentType string, data interface{}) ([]byte, error) {
}
func unmarshal(contentType string, body []byte, returnBody interface{}) error {
// Note: contentType can look look like: "application/json" or "application/json; charset=utf-8"
// Note: contentType can look like: "application/json" or "application/json; charset=utf-8"
mediaType, _, err := mime.ParseMediaType(contentType)
if err != nil {
return err

View File

@ -2,12 +2,12 @@ package utils
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"net/http"
"strconv"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
)
@ -18,7 +18,10 @@ func GetResponseAsJSONObject(response *http.Response) (map[string]interface{}, e
return nil, err
}
responseObject := responseData.(map[string]interface{})
responseObject, ok := responseData.(map[string]interface{})
if !ok {
return nil, nil
}
return responseObject, nil
}
@ -28,6 +31,9 @@ func GetResponseAsJSONArray(response *http.Response) ([]interface{}, error) {
if err != nil {
return nil, err
}
if responseData == nil {
return nil, nil
}
switch responseObject := responseData.(type) {
case []interface{}:

View File

@ -16,7 +16,7 @@ import (
)
type (
// Manager represents a service used to manage proxies to environments (endpoints).
// Manager represents a service used to manage proxies to environments (endpoints) and extensions.
Manager struct {
proxyFactory *factory.ProxyFactory
endpointProxies cmap.ConcurrentMap

View File

@ -42,7 +42,7 @@ func AuthorizedResourceControlAccess(resourceControl *portainer.ResourceControl,
// AuthorizedResourceControlUpdate ensure that the user can update a resource control object.
// A non-administrator user cannot create a resource control where:
// * the Public flag is set false
// * the AdministatorsOnly flag is set to true
// * the AdministratorsOnly flag is set to true
// * he wants to create a resource control without any user/team accesses
// * he wants to add more than one user in the user accesses
// * he wants to add a user in the user accesses that is not corresponding to its id

View File

@ -409,7 +409,7 @@ func (bouncer *RequestBouncer) newRestrictedContextRequest(userID portainer.User
}, nil
}
// EdgeComputeOperation defines a restriced edge compute operation.
// EdgeComputeOperation defines a restricted edge compute operation.
// Use of this operation will only be authorized if edgeCompute is enabled in settings
func (bouncer *RequestBouncer) EdgeComputeOperation(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

View File

@ -12,6 +12,7 @@ import (
"github.com/portainer/portainer/api/datastore"
httperrors "github.com/portainer/portainer/api/http/errors"
"github.com/portainer/portainer/api/jwt"
"github.com/stretchr/testify/assert"
)

View File

@ -74,7 +74,6 @@ func FilterRegistries(registries []portainer.Registry, user *portainer.User, tea
}
filteredRegistries := []portainer.Registry{}
for _, registry := range registries {
if AuthorizedRegistryAccess(&registry, user, teamMemberships, endpointID) {
filteredRegistries = append(filteredRegistries, registry)

View File

@ -1,7 +1,8 @@
package edge
import (
"github.com/portainer/portainer/api"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/internal/endpointutils"
"github.com/portainer/portainer/api/internal/tag"
)
@ -13,7 +14,7 @@ func EdgeGroupRelatedEndpoints(edgeGroup *portainer.EdgeGroup, endpoints []porta
endpointIDs := []portainer.EndpointID{}
for _, endpoint := range endpoints {
if endpoint.Type != portainer.EdgeAgentOnDockerEnvironment && endpoint.Type != portainer.EdgeAgentOnKubernetesEnvironment {
if !endpointutils.IsEdgeEndpoint(&endpoint) {
continue
}

View File

@ -2,6 +2,7 @@ package edge
import (
"errors"
"github.com/portainer/portainer/api"
)

View File

@ -23,5 +23,4 @@ func EndpointRelatedEdgeStacks(endpoint *portainer.Endpoint, endpointGroup *port
}
return relatedEdgeStacks
}

View File

@ -3,6 +3,7 @@ package registryutils
import (
"encoding/base64"
"encoding/json"
portainer "github.com/portainer/portainer/api"
)

View File

@ -213,6 +213,10 @@ func (service *Service) snapshotEndpoints() error {
continue
}
if endpoint.URL == "" {
continue
}
snapshotError := service.SnapshotEndpoint(&endpoint)
latestEndpointReference, err := service.dataStore.Endpoint().Endpoint(endpoint.ID)

View File

@ -11,7 +11,6 @@ import (
// to prevent an error when url has port but no protocol prefix
// we add `//` prefix if needed
func ParseURL(endpointURL string) (*url.URL, error) {
if !strings.HasPrefix(endpointURL, "http") &&
!strings.HasPrefix(endpointURL, "tcp") &&
!strings.HasPrefix(endpointURL, "//") &&

View File

@ -1,8 +1,9 @@
package jwt
import (
portainer "github.com/portainer/portainer/api"
"time"
portainer "github.com/portainer/portainer/api"
)
// GenerateTokenForKubeconfig generates a new JWT token for Kubeconfig

Some files were not shown because too many files have changed in this diff Show More