Compare commits

..

1 Commits

Author SHA1 Message Date
Chaim Lev-Ari
8c90a15edb fix(ldap): enable user/group setting in custom ldap 2021-10-07 17:13:01 +03:00
193 changed files with 717 additions and 1962 deletions

View File

@@ -18,16 +18,13 @@ const beforePortainerVersionUpgradeBackup = "portainer.db.bak"
var migrateLog = plog.NewScopedLog("bolt, migrate")
// FailSafeMigrate backup and restore DB if migration fail
func (store *Store) FailSafeMigrate(migrator *migrator.Migrator) (err error) {
func (store *Store) FailSafeMigrate(migrator *migrator.Migrator) error {
defer func() {
if e := recover(); e != nil {
if err := recover(); err != nil {
migrateLog.Info(fmt.Sprintf("Error during migration, recovering [%v]", err))
store.Rollback(true)
err = fmt.Errorf("%v", e)
}
}()
// !Important: we must use a named return value in the function definition and not a local
// !variable referenced from the closure or else the return value will be incorrectly set
return migrator.Migrate()
}

View File

@@ -192,8 +192,8 @@ func (service *Service) RefreshableStacks() ([]portainer.Stack, error) {
bucket := tx.Bucket([]byte(BucketName))
cursor := bucket.Cursor()
var stack portainer.Stack
for k, v := cursor.First(); k != nil; k, v = cursor.Next() {
stack := portainer.Stack{}
err := internal.UnmarshalObject(v, &stack)
if err != nil {
return err

View File

@@ -3,7 +3,6 @@ package chisel
import (
"context"
"fmt"
"github.com/portainer/portainer/api/http/proxy"
"log"
"net/http"
"strconv"
@@ -33,7 +32,6 @@ type Service struct {
snapshotService portainer.SnapshotService
chiselServer *chserver.Server
shutdownCtx context.Context
ProxyManager *proxy.Manager
}
// NewService returns a pointer to a new instance of Service
@@ -217,13 +215,18 @@ func (service *Service) checkTunnels() {
}
}
endpointID, err := strconv.Atoi(item.Key)
if err != nil {
log.Printf("[ERROR] [chisel,conversion] Invalid environment identifier (id: %s): %s", item.Key, err)
continue
if len(tunnel.Jobs) > 0 {
endpointID, err := strconv.Atoi(item.Key)
if err != nil {
log.Printf("[ERROR] [chisel,conversion] Invalid environment identifier (id: %s): %s", item.Key, err)
continue
}
service.SetTunnelStatusToIdle(portainer.EndpointID(endpointID))
} else {
service.tunnelDetailsMap.Remove(item.Key)
}
service.SetTunnelStatusToIdle(portainer.EndpointID(endpointID))
}
}

View File

@@ -59,12 +59,6 @@ func (service *Service) GetTunnelDetails(endpointID portainer.EndpointID) *porta
// GetActiveTunnel retrieves an active tunnel which allows communicating with edge agent
func (service *Service) GetActiveTunnel(endpoint *portainer.Endpoint) (*portainer.TunnelDetails, error) {
tunnel := service.GetTunnelDetails(endpoint.ID)
if tunnel.Status == portainer.EdgeAgentActive {
// update the LastActivity
service.SetTunnelStatusToActive(endpoint.ID)
}
if tunnel.Status == portainer.EdgeAgentIdle || tunnel.Status == portainer.EdgeAgentManagementRequired {
err := service.SetTunnelStatusToRequired(endpoint.ID)
if err != nil {
@@ -80,18 +74,9 @@ func (service *Service) GetActiveTunnel(endpoint *portainer.Endpoint) (*portaine
endpoint.EdgeCheckinInterval = settings.EdgeAgentCheckinInterval
}
waitForAgentToConnect := 2 * time.Duration(endpoint.EdgeCheckinInterval)
for waitForAgentToConnect >= 0 {
waitForAgentToConnect--
time.Sleep(time.Second)
tunnel = service.GetTunnelDetails(endpoint.ID)
if tunnel.Status == portainer.EdgeAgentActive {
break
}
}
waitForAgentToConnect := time.Duration(endpoint.EdgeCheckinInterval) * time.Second
time.Sleep(waitForAgentToConnect * 2)
}
tunnel = service.GetTunnelDetails(endpoint.ID)
return tunnel, nil
@@ -127,8 +112,6 @@ func (service *Service) SetTunnelStatusToIdle(endpointID portainer.EndpointID) {
key := strconv.Itoa(int(endpointID))
service.tunnelDetailsMap.Set(key, tunnel)
service.ProxyManager.DeleteEndpointProxy(endpointID)
}
// SetTunnelStatusToRequired update the status of the tunnel associated to the specified environment(endpoint).

View File

@@ -467,8 +467,6 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
proxyManager := proxy.NewManager(dataStore, digitalSignatureService, reverseTunnelService, dockerClientFactory, kubernetesClientFactory, kubernetesTokenCacheManager)
reverseTunnelService.ProxyManager = proxyManager
dockerConfigPath := fileService.GetDockerConfigPath()
composeStackManager := initComposeStackManager(*flags.Assets, dockerConfigPath, reverseTunnelService, proxyManager)

View File

@@ -91,11 +91,7 @@ func createEdgeClient(endpoint *portainer.Endpoint, signatureService portainer.D
headers[portainer.PortainerAgentTargetHeader] = nodeName
}
tunnel, err := reverseTunnelService.GetActiveTunnel(endpoint)
if err != nil {
return nil, err
}
tunnel := reverseTunnelService.GetTunnelDetails(endpoint.ID)
endpointURL := fmt.Sprintf("http://127.0.0.1:%d", tunnel.Port)
return client.NewClientWithOpts(

View File

@@ -93,7 +93,7 @@ func (manager *ComposeStackManager) fetchEndpointProxy(endpoint *portainer.Endpo
return "", nil, err
}
return fmt.Sprintf("tcp://127.0.0.1:%d", proxy.Port), proxy, nil
return fmt.Sprintf("http://127.0.0.1:%d", proxy.Port), proxy, nil
}
func createEnvFile(stack *portainer.Stack) (string, error) {

View File

@@ -44,26 +44,19 @@ func NewSwarmStackManager(binaryPath, configPath string, signatureService portai
}
// Login executes the docker login command against a list of registries (including DockerHub).
func (manager *SwarmStackManager) Login(registries []portainer.Registry, endpoint *portainer.Endpoint) error {
command, args, err := manager.prepareDockerCommandAndArgs(manager.binaryPath, manager.configPath, endpoint)
if err != nil {
return err
}
func (manager *SwarmStackManager) Login(registries []portainer.Registry, endpoint *portainer.Endpoint) {
command, args := manager.prepareDockerCommandAndArgs(manager.binaryPath, manager.configPath, endpoint)
for _, registry := range registries {
if registry.Authentication {
registryArgs := append(args, "login", "--username", registry.Username, "--password", registry.Password, registry.URL)
runCommandAndCaptureStdErr(command, registryArgs, nil, "")
}
}
return nil
}
// Logout executes the docker logout command.
func (manager *SwarmStackManager) Logout(endpoint *portainer.Endpoint) error {
command, args, err := manager.prepareDockerCommandAndArgs(manager.binaryPath, manager.configPath, endpoint)
if err != nil {
return err
}
command, args := manager.prepareDockerCommandAndArgs(manager.binaryPath, manager.configPath, endpoint)
args = append(args, "logout")
return runCommandAndCaptureStdErr(command, args, nil, "")
}
@@ -71,10 +64,7 @@ func (manager *SwarmStackManager) Logout(endpoint *portainer.Endpoint) error {
// Deploy executes the docker stack deploy command.
func (manager *SwarmStackManager) Deploy(stack *portainer.Stack, prune bool, endpoint *portainer.Endpoint) error {
filePaths := stackutils.GetStackFilePaths(stack)
command, args, err := manager.prepareDockerCommandAndArgs(manager.binaryPath, manager.configPath, endpoint)
if err != nil {
return err
}
command, args := manager.prepareDockerCommandAndArgs(manager.binaryPath, manager.configPath, endpoint)
if prune {
args = append(args, "stack", "deploy", "--prune", "--with-registry-auth")
@@ -94,10 +84,7 @@ func (manager *SwarmStackManager) Deploy(stack *portainer.Stack, prune bool, end
// Remove executes the docker stack rm command.
func (manager *SwarmStackManager) Remove(stack *portainer.Stack, endpoint *portainer.Endpoint) error {
command, args, err := manager.prepareDockerCommandAndArgs(manager.binaryPath, manager.configPath, endpoint)
if err != nil {
return err
}
command, args := manager.prepareDockerCommandAndArgs(manager.binaryPath, manager.configPath, endpoint)
args = append(args, "stack", "rm", stack.Name)
return runCommandAndCaptureStdErr(command, args, nil, "")
}
@@ -121,7 +108,7 @@ func runCommandAndCaptureStdErr(command string, args []string, env []string, wor
return nil
}
func (manager *SwarmStackManager) prepareDockerCommandAndArgs(binaryPath, configPath string, endpoint *portainer.Endpoint) (string, []string, error) {
func (manager *SwarmStackManager) prepareDockerCommandAndArgs(binaryPath, configPath string, endpoint *portainer.Endpoint) (string, []string) {
// Assume Linux as a default
command := path.Join(binaryPath, "docker")
@@ -134,10 +121,7 @@ func (manager *SwarmStackManager) prepareDockerCommandAndArgs(binaryPath, config
endpointURL := endpoint.URL
if endpoint.Type == portainer.EdgeAgentOnDockerEnvironment {
tunnel, err := manager.reverseTunnelService.GetActiveTunnel(endpoint)
if err != nil {
return "", nil, err
}
tunnel := manager.reverseTunnelService.GetTunnelDetails(endpoint.ID)
endpointURL = fmt.Sprintf("tcp://127.0.0.1:%d", tunnel.Port)
}
@@ -157,7 +141,7 @@ func (manager *SwarmStackManager) prepareDockerCommandAndArgs(binaryPath, config
}
}
return command, args, nil
return command, args
}
func (manager *SwarmStackManager) updateDockerCLIConfiguration(configPath string) error {

View File

@@ -3,48 +3,58 @@ module github.com/portainer/portainer/api
go 1.16
require (
github.com/Microsoft/go-winio v0.4.17
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/Microsoft/go-winio v0.4.16
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 // indirect
github.com/alecthomas/units v0.0.0-20210208195552-ff826a37aa15 // indirect
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535
github.com/boltdb/bolt v1.3.1
github.com/containerd/containerd v1.5.7 // indirect
github.com/containerd/containerd v1.3.1 // indirect
github.com/coreos/go-semver v0.3.0
github.com/dchest/uniuri v0.0.0-20160212164326-8902c56451e9
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/docker/cli v20.10.9+incompatible
github.com/docker/docker v20.10.9+incompatible
github.com/docker/cli v0.0.0-20191126203649-54d085b857e9
github.com/docker/distribution v2.7.1+incompatible // indirect
github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/g07cha/defender v0.0.0-20180505193036-5665c627c814
github.com/go-git/go-git/v5 v5.3.0
github.com/go-ldap/ldap/v3 v3.1.8
github.com/gofrs/uuid v4.0.0+incompatible
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/gofrs/uuid v3.2.0+incompatible
github.com/gorilla/mux v1.7.3
github.com/gorilla/securecookie v1.1.1
github.com/gorilla/websocket v1.4.2
github.com/gorilla/websocket v1.4.1
github.com/joho/godotenv v1.3.0
github.com/jpillora/chisel v0.0.0-20190724232113-f3a8df20e389
github.com/json-iterator/go v1.1.11
github.com/json-iterator/go v1.1.10
github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
github.com/mattn/go-shellwords v1.0.6 // indirect
github.com/mitchellh/mapstructure v1.1.2 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.1 // indirect
github.com/orcaman/concurrent-map v0.0.0-20190826125027-8c72a8bb44f6
github.com/pkg/errors v0.9.1
github.com/portainer/docker-compose-wrapper v0.0.0-20211018221743-10a04c9d4f19
github.com/portainer/docker-compose-wrapper v0.0.0-20210909083948-8be0d98451a1
github.com/portainer/libcrypto v0.0.0-20210422035235-c652195c5c3a
github.com/portainer/libhelm v0.0.0-20210929000907-825e93d62108
github.com/portainer/libhttp v0.0.0-20190806161843-ba068f58be33
github.com/robfig/cron/v3 v3.0.1
github.com/sirupsen/logrus v1.8.1
github.com/stretchr/testify v1.7.0
github.com/swaggo/swag v1.7.3
github.com/xeipuuv/gojsonschema v1.2.0 // indirect
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
gopkg.in/alecthomas/kingpin.v2 v2.2.6
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
k8s.io/api v0.22.2
k8s.io/apimachinery v0.22.2
k8s.io/client-go v0.22.2
gotest.tools v2.2.0+incompatible // indirect
k8s.io/api v0.17.2
k8s.io/apimachinery v0.17.2
k8s.io/client-go v0.17.2
)
replace github.com/docker/docker => github.com/docker/engine v1.4.2-0.20200204220554-5f6d6f3f2203
replace golang.org/x/sys => golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456

File diff suppressed because it is too large Load Diff

View File

@@ -39,7 +39,6 @@ func (payload *authenticatePayload) Validate(r *http.Request) error {
// @id AuthenticateUser
// @summary Authenticate
// @description **Access policy**: public
// @description Use this environment(endpoint) to authenticate against Portainer using a username and password.
// @tags auth
// @accept json

View File

@@ -44,7 +44,6 @@ func (handler *Handler) authenticateOAuth(code string, settings *portainer.OAuth
// @id ValidateOAuth
// @summary Authenticate with OAuth
// @description **Access policy**: public
// @tags auth
// @accept json
// @produce json

View File

@@ -10,7 +10,6 @@ import (
// @id Logout
// @summary Logout
// @description **Access policy**: authenticated
// @security jwt
// @tags auth
// @success 204 "Success"

View File

@@ -27,9 +27,8 @@ func (p *backupPayload) Validate(r *http.Request) error {
// @description **Access policy**: admin
// @tags backup
// @security jwt
// @accept json
// @produce octet-stream
// @param body body backupPayload false "An object contains the password to encrypt the backup with"
// @param Password body string false "Password to encrypt the backup with"
// @success 200 "Success"
// @failure 400 "Invalid request"
// @failure 500 "Server error"

View File

@@ -22,9 +22,10 @@ type restorePayload struct {
// @description Triggers a system restore using provided backup file
// @description **Access policy**: public
// @tags backup
// @accept json
// @param restorePayload body restorePayload true "Restore request payload"
// @success 200 "Success"
// @param FileContent body []byte true "Content of the backup"
// @param FileName body string true "File name"
// @param Password body string false "Password to decrypt the backup with"
// @success 200 "Success"
// @failure 400 "Invalid request"
// @failure 500 "Server error"
// @router /restore [post]

View File

@@ -16,7 +16,7 @@ import (
// @id CustomTemplateDelete
// @summary Remove a template
// @description Remove a template.
// @description **Access policy**: authenticated
// @description **Access policy**: authorized
// @tags custom_templates
// @security jwt
// @param id path int true "Template identifier"

View File

@@ -18,7 +18,7 @@ type fileResponse struct {
// @id CustomTemplateFile
// @summary Get Template stack file content.
// @description Retrieve the content of the Stack file for the specified custom template
// @description **Access policy**: authenticated
// @description **Access policy**: authorized
// @tags custom_templates
// @security jwt
// @produce json

View File

@@ -19,6 +19,7 @@ import (
// @description **Access policy**: authenticated
// @tags custom_templates
// @security jwt
// @accept json
// @produce json
// @param id path int true "Template identifier"
// @success 200 {object} portainer.CustomTemplate "Success"

View File

@@ -34,7 +34,7 @@ func (payload *edgeGroupCreatePayload) Validate(r *http.Request) error {
// @id EdgeGroupCreate
// @summary Create an EdgeGroup
// @description **Access policy**: administrator
// @description
// @tags edge_groups
// @security jwt
// @accept json

View File

@@ -13,9 +13,11 @@ import (
// @id EdgeGroupDelete
// @summary Deletes an EdgeGroup
// @description **Access policy**: administrator
// @description
// @tags edge_groups
// @security jwt
// @accept json
// @produce json
// @param id path int true "EdgeGroup Id"
// @success 204
// @failure 503 "Edge compute features are disabled"

View File

@@ -12,9 +12,10 @@ import (
// @id EdgeGroupInspect
// @summary Inspects an EdgeGroup
// @description **Access policy**: administrator
// @description
// @tags edge_groups
// @security jwt
// @accept json
// @produce json
// @param id path int true "EdgeGroup Id"
// @success 200 {object} portainer.EdgeGroup

View File

@@ -17,9 +17,10 @@ type decoratedEdgeGroup struct {
// @id EdgeGroupList
// @summary list EdgeGroups
// @description **Access policy**: administrator
// @description
// @tags edge_groups
// @security jwt
// @accept json
// @produce json
// @success 200 {array} portainer.EdgeGroup{HasEdgeStack=bool} "EdgeGroups"
// @failure 500

View File

@@ -36,7 +36,7 @@ func (payload *edgeGroupUpdatePayload) Validate(r *http.Request) error {
// @id EgeGroupUpdate
// @summary Updates an EdgeGroup
// @description **Access policy**: administrator
// @description
// @tags edge_groups
// @security jwt
// @accept json

View File

@@ -16,9 +16,10 @@ import (
// @id EdgeJobCreate
// @summary Create an EdgeJob
// @description **Access policy**: administrator
// @description
// @tags edge_jobs
// @security jwt
// @accept json
// @produce json
// @param method query string true "Creation Method" Enums(file, string)
// @param body_string body edgeJobCreateFromFileContentPayload true "EdgeGroup data when method is string"

View File

@@ -13,9 +13,11 @@ import (
// @id EdgeJobDelete
// @summary Delete an EdgeJob
// @description **Access policy**: administrator
// @description
// @tags edge_jobs
// @security jwt
// @accept json
// @produce json
// @param id path string true "EdgeJob Id"
// @success 204
// @failure 500

View File

@@ -16,9 +16,10 @@ type edgeJobFileResponse struct {
// @id EdgeJobFile
// @summary Fetch a file of an EdgeJob
// @description **Access policy**: administrator
// @description
// @tags edge_jobs
// @security jwt
// @accept json
// @produce json
// @param id path string true "EdgeJob Id"
// @success 200 {object} edgeJobFileResponse

View File

@@ -17,9 +17,10 @@ type edgeJobInspectResponse struct {
// @id EdgeJobInspect
// @summary Inspect an EdgeJob
// @description **Access policy**: administrator
// @description
// @tags edge_jobs
// @security jwt
// @accept json
// @produce json
// @param id path string true "EdgeJob Id"
// @success 200 {object} portainer.EdgeJob

View File

@@ -9,9 +9,10 @@ import (
// @id EdgeJobList
// @summary Fetch EdgeJobs list
// @description **Access policy**: administrator
// @description
// @tags edge_jobs
// @security jwt
// @accept json
// @produce json
// @success 200 {array} portainer.EdgeJob
// @failure 500

View File

@@ -13,9 +13,10 @@ import (
// @id EdgeJobTasksClear
// @summary Clear the log for a specifc task on an EdgeJob
// @description **Access policy**: administrator
// @description
// @tags edge_jobs
// @security jwt
// @accept json
// @produce json
// @param id path string true "EdgeJob Id"
// @param taskID path string true "Task Id"

View File

@@ -12,9 +12,10 @@ import (
// @id EdgeJobTasksCollect
// @summary Collect the log for a specifc task on an EdgeJob
// @description **Access policy**: administrator
// @description
// @tags edge_jobs
// @security jwt
// @accept json
// @produce json
// @param id path string true "EdgeJob Id"
// @param taskID path string true "Task Id"

View File

@@ -15,9 +15,10 @@ type fileResponse struct {
// @id EdgeJobTaskLogsInspect
// @summary Fetch the log for a specifc task on an EdgeJob
// @description **Access policy**: administrator
// @description
// @tags edge_jobs
// @security jwt
// @accept json
// @produce json
// @param id path string true "EdgeJob Id"
// @param taskID path string true "Task Id"

View File

@@ -19,9 +19,10 @@ type taskContainer struct {
// @id EdgeJobTasksList
// @summary Fetch the list of tasks on an EdgeJob
// @description **Access policy**: administrator
// @description
// @tags edge_jobs
// @security jwt
// @accept json
// @produce json
// @param id path string true "EdgeJob Id"
// @success 200 {array} taskContainer

View File

@@ -30,7 +30,7 @@ func (payload *edgeJobUpdatePayload) Validate(r *http.Request) error {
// @id EdgeJobUpdate
// @summary Update an EdgeJob
// @description **Access policy**: administrator
// @description
// @tags edge_jobs
// @security jwt
// @accept json

View File

@@ -19,9 +19,10 @@ import (
// @id EdgeStackCreate
// @summary Create an EdgeStack
// @description **Access policy**: administrator
// @description
// @tags edge_stacks
// @security jwt
// @accept json
// @produce json
// @param method query string true "Creation Method" Enums(file,string,repository)
// @param body_string body swarmStackFromFileContentPayload true "Required when using method=string"

View File

@@ -13,9 +13,11 @@ import (
// @id EdgeStackDelete
// @summary Delete an EdgeStack
// @description **Access policy**: administrator
// @description
// @tags edge_stacks
// @security jwt
// @accept json
// @produce json
// @param id path string true "EdgeStack Id"
// @success 204
// @failure 500

View File

@@ -17,9 +17,10 @@ type stackFileResponse struct {
// @id EdgeStackFile
// @summary Fetches the stack file for an EdgeStack
// @description **Access policy**: administrator
// @description
// @tags edge_stacks
// @security jwt
// @accept json
// @produce json
// @param id path string true "EdgeStack Id"
// @success 200 {object} stackFileResponse

View File

@@ -12,9 +12,10 @@ import (
// @id EdgeStackInspect
// @summary Inspect an EdgeStack
// @description **Access policy**: administrator
// @description
// @tags edge_stacks
// @security jwt
// @accept json
// @produce json
// @param id path string true "EdgeStack Id"
// @success 200 {object} portainer.EdgeStack

View File

@@ -9,9 +9,10 @@ import (
// @id EdgeStackList
// @summary Fetches the list of EdgeStacks
// @description **Access policy**: administrator
// @description
// @tags edge_stacks
// @security jwt
// @accept json
// @produce json
// @success 200 {array} portainer.EdgeStack
// @failure 500

View File

@@ -33,7 +33,7 @@ func (payload *updateEdgeStackPayload) Validate(r *http.Request) error {
// @id EdgeStackUpdate
// @summary Update an EdgeStack
// @description **Access policy**: administrator
// @description
// @tags edge_stacks
// @security jwt
// @accept json

View File

@@ -17,7 +17,7 @@ type templateFileFormat struct {
// @id EdgeTemplateList
// @summary Fetches the list of Edge Templates
// @description **Access policy**: administrator
// @description
// @tags edge_templates
// @security jwt
// @accept json

View File

@@ -21,7 +21,7 @@ func (payload *logsPayload) Validate(r *http.Request) error {
// endpointEdgeJobsLogs
// @summary Inspect an EdgeJob Log
// @description **Access policy**: public
// @description
// @tags edge, endpoints
// @accept json
// @produce json

View File

@@ -19,7 +19,7 @@ type configResponse struct {
}
// @summary Inspect an Edge Stack for an Environment(Endpoint)
// @description **Access policy**: public
// @description
// @tags edge, endpoints, edge_stacks
// @accept json
// @produce json

View File

@@ -17,6 +17,8 @@ import (
// @description **Access policy**: administrator
// @tags endpoint_groups
// @security jwt
// @accept json
// @produce json
// @param id path int true "EndpointGroup identifier"
// @success 204 "Success"
// @failure 400 "Invalid request"

View File

@@ -2,12 +2,14 @@ package endpointproxy
import (
"errors"
"strconv"
"strings"
"time"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
"github.com/portainer/portainer/api"
bolterrors "github.com/portainer/portainer/api/bolt/errors"
"strconv"
"strings"
"net/http"
)
@@ -35,9 +37,22 @@ func (handler *Handler) proxyRequestsToDockerAPI(w http.ResponseWriter, r *http.
return &httperror.HandlerError{http.StatusInternalServerError, "No Edge agent registered with the environment", errors.New("No agent available")}
}
_, err := handler.ReverseTunnelService.GetActiveTunnel(endpoint)
if err != nil {
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to get the active tunnel", err}
tunnel := handler.ReverseTunnelService.GetTunnelDetails(endpoint.ID)
if tunnel.Status == portainer.EdgeAgentIdle {
handler.ProxyManager.DeleteEndpointProxy(endpoint)
err := handler.ReverseTunnelService.SetTunnelStatusToRequired(endpoint.ID)
if err != nil {
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to update tunnel status", err}
}
settings, err := handler.DataStore.Settings().Settings()
if err != nil {
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve settings from the database", err}
}
waitForAgentToConnect := time.Duration(settings.EdgeAgentCheckinInterval) * time.Second
time.Sleep(waitForAgentToConnect * 2)
}
}

View File

@@ -3,11 +3,13 @@ package endpointproxy
import (
"errors"
"fmt"
"strings"
"time"
httperror "github.com/portainer/libhttp/error"
"github.com/portainer/libhttp/request"
portainer "github.com/portainer/portainer/api"
bolterrors "github.com/portainer/portainer/api/bolt/errors"
"strings"
"net/http"
)
@@ -35,9 +37,22 @@ func (handler *Handler) proxyRequestsToKubernetesAPI(w http.ResponseWriter, r *h
return &httperror.HandlerError{http.StatusInternalServerError, "No Edge agent registered with the environment", errors.New("No agent available")}
}
_, err := handler.ReverseTunnelService.GetActiveTunnel(endpoint)
if err != nil {
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to get the active tunnel", err}
tunnel := handler.ReverseTunnelService.GetTunnelDetails(endpoint.ID)
if tunnel.Status == portainer.EdgeAgentIdle {
handler.ProxyManager.DeleteEndpointProxy(endpoint)
err := handler.ReverseTunnelService.SetTunnelStatusToRequired(endpoint.ID)
if err != nil {
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to update tunnel status", err}
}
settings, err := handler.DataStore.Settings().Settings()
if err != nil {
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve settings from the database", err}
}
waitForAgentToConnect := time.Duration(settings.EdgeAgentCheckinInterval) * time.Second
time.Sleep(waitForAgentToConnect * 2)
}
}

View File

@@ -27,7 +27,7 @@ import (
// @failure 400 "Invalid request"
// @failure 404 "Environment(Endpoint) not found"
// @failure 500 "Server error"
// @router /endpoints/{id}/association [put]
// @router /api/endpoints/{id}/association [put]
func (handler *Handler) endpointAssociationDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
if err != nil {

View File

@@ -49,7 +49,7 @@ func (handler *Handler) endpointDelete(w http.ResponseWriter, r *http.Request) *
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to remove environment from the database", err}
}
handler.ProxyManager.DeleteEndpointProxy(endpoint.ID)
handler.ProxyManager.DeleteEndpointProxy(endpoint)
err = handler.DataStore.EndpointRelation().DeleteEndpointRelation(endpoint.ID)
if err != nil {

View File

@@ -18,27 +18,11 @@ import (
)
type dockerhubStatusResponse struct {
// Remaiming images to pull
Remaining int `json:"remaining"`
// Daily limit
Limit int `json:"limit"`
Limit int `json:"limit"`
}
// @id endpointDockerhubStatus
// @summary fetch docker pull limits
// @description get docker pull limits for a docker hub registry in the environment
// @description **Access policy**:
// @tags endpoints
// @security jwt
// @produce json
// @param id path int true "endpoint ID"
// @param registryId path int true "registry ID"
// @success 200 {object} dockerhubStatusResponse "Success"
// @failure 400 "Invalid request"
// @failure 403 "Permission denied"
// @failure 404 "registry or endpoint not found"
// @failure 500 "Server error"
// @router /endpoints/{id}/dockerhub/{registryId} [get]
// GET request on /api/endpoints/{id}/dockerhub/{registryId}
func (handler *Handler) endpointDockerhubStatus(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
if err != nil {

View File

@@ -29,12 +29,6 @@ func (payload *endpointExtensionAddPayload) Validate(r *http.Request) error {
return nil
}
// @id endpointExtensionAdd
// @tags endpoints
// @deprecated
// @param id path int true "Environment(Endpoint) identifier"
// @success 204 "Success"
// @router /endpoints/{id}/extensions [post]
func (handler *Handler) endpointExtensionAdd(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
if err != nil {

View File

@@ -12,13 +12,6 @@ import (
"github.com/portainer/portainer/api/bolt/errors"
)
// @id endpointExtensionRemove
// @tags endpoints
// @deprecated
// @param id path int true "Environment(Endpoint) identifier"
// @param extensionType path string true "Extension Type"
// @success 204 "Success"
// @router /endpoints/{id}/extensions/{extensionType} [delete]
func (handler *Handler) endpointExtensionRemove(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
if err != nil {

View File

@@ -12,20 +12,7 @@ import (
"github.com/portainer/portainer/api/http/security"
)
// @id endpointRegistryInspect
// @summary get registry for environment
// @description **Access policy**: authenticated
// @tags endpoints
// @security jwt
// @produce json
// @param id path int true "identifier"
// @param registryId path int true "Registry identifier"
// @success 200 {object} portainer.Registry "Success"
// @failure 400 "Invalid request"
// @failure 403 "Permission denied"
// @failure 404 "Registry not found"
// @failure 500 "Server error"
// @router /endpoints/{id}/registries/{registryId} [get]
// GET request on /endpoints/{id}/registries/{registryId}
func (handler *Handler) endpointRegistryInspect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
if err != nil {

View File

@@ -13,18 +13,7 @@ import (
"github.com/portainer/portainer/api/internal/endpointutils"
)
// @id endpointRegistriesList
// @summary List Registries on environment
// @description List all registries based on the current user authorizations in current environment.
// @description **Access policy**: authenticated
// @tags endpoints
// @param namespace query string false "required if kubernetes environment, will show registries by namespace"
// @security jwt
// @produce json
// @param id path int true "Environment(Endpoint) identifier"
// @success 200 {array} portainer.Registry "Success"
// @failure 500 "Server error"
// @router /endpoints/{id}/registries [get]
// GET request on /endpoints/{id}/registries?namespace
func (handler *Handler) endpointRegistriesList(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
securityContext, err := security.RetrieveRestrictedRequestContext(r)
if err != nil {

View File

@@ -21,22 +21,7 @@ func (payload *registryAccessPayload) Validate(r *http.Request) error {
return nil
}
// @id endpointRegistryAccess
// @summary update registry access for environment
// @description **Access policy**: authenticated
// @tags endpoints
// @security jwt
// @accept json
// @produce json
// @param id path int true "Environment(Endpoint) identifier"
// @param registryId path int true "Registry identifier"
// @param body body registryAccessPayload true "details"
// @success 204 "Success"
// @failure 400 "Invalid request"
// @failure 403 "Permission denied"
// @failure 404 "Endpoint not found"
// @failure 500 "Server error"
// @router /endpoints/{id}/registries/{registryId} [put]
// PUT request on /endpoints/{id}/registries/{registryId}
func (handler *Handler) endpointRegistryAccess(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
if err != nil {

View File

@@ -36,9 +36,9 @@ func (payload *endpointSettingsUpdatePayload) Validate(r *http.Request) error {
}
// @id EndpointSettingsUpdate
// @summary Update settings for an environment(endpoint)
// @description Update settings for an environment(endpoint).
// @description **Access policy**: authenticated
// @summary Update settings for an environments(endpoints)
// @description Update settings for an environments(endpoints).
// @description **Access policy**: administrator
// @security jwt
// @tags endpoints
// @accept json
@@ -49,7 +49,7 @@ func (payload *endpointSettingsUpdatePayload) Validate(r *http.Request) error {
// @failure 400 "Invalid request"
// @failure 404 "Environment(Endpoint) not found"
// @failure 500 "Server error"
// @router /endpoints/{id}/settings [put]
// @router /api/endpoints/{id}/settings [put]
func (handler *Handler) endpointSettingsUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
if err != nil {

View File

@@ -12,9 +12,9 @@ import (
)
// @id EndpointSnapshot
// @summary Snapshots an environment(endpoint)
// @description Snapshots an environment(endpoint)
// @description **Access policy**: administrator
// @summary Snapshots an environments(endpoints)
// @description Snapshots an environments(endpoints)
// @description **Access policy**: restricted
// @tags endpoints
// @security jwt
// @param id path int true "Environment(Endpoint) identifier"

View File

@@ -56,7 +56,7 @@ func (payload *endpointUpdatePayload) Validate(r *http.Request) error {
// @id EndpointUpdate
// @summary Update an environment(endpoint)
// @description Update an environment(endpoint).
// @description **Access policy**: authenticated
// @description **Access policy**: administrator
// @security jwt
// @tags endpoints
// @accept json

View File

@@ -74,7 +74,7 @@ type Handler struct {
}
// @title PortainerCE API
// @version 2.9.2
// @version 2.9.1
// @description.markdown api-description.md
// @termsOfService

View File

@@ -12,9 +12,11 @@ import (
// @id HelmDelete
// @summary Delete Helm Release
// @description
// @description **Access policy**: authenticated
// @description **Access policy**: authorized
// @tags helm
// @security jwt
// @accept json
// @produce json
// @param id path int true "Environment(Endpoint) identifier"
// @param release path string true "The name of the release/application to uninstall"
// @param namespace query string true "An optional namespace"

View File

@@ -36,7 +36,7 @@ var errChartNameInvalid = errors.New("invalid chart name. " +
// @id HelmInstall
// @summary Install Helm Chart
// @description
// @description **Access policy**: authenticated
// @description **Access policy**: authorized
// @tags helm
// @security jwt
// @accept json

View File

@@ -12,7 +12,7 @@ import (
// @id HelmList
// @summary List Helm Releases
// @description
// @description **Access policy**: authenticated
// @description **Access policy**: authorized
// @tags helm
// @security jwt
// @accept json

View File

@@ -13,7 +13,7 @@ import (
// @id HelmRepoSearch
// @summary Search Helm Charts
// @description
// @description **Access policy**: authenticated
// @description **Access policy**: authorized
// @tags helm
// @param repo query string true "Helm repository URL"
// @security jwt

View File

@@ -15,8 +15,8 @@ import (
// @id HelmShow
// @summary Show Helm Chart Information
// @description
// @description **Access policy**: authenticated
// @tags helm
// @description **Access policy**: authorized
// @tags helm_chart
// @param repo query string true "Helm repository URL"
// @param chart query string true "Chart name"
// @param command path string true "chart/values/readme"

View File

@@ -17,7 +17,7 @@ import (
// @id GetKubernetesConfig
// @summary Generates kubeconfig file enabling client communication with k8s api server
// @description Generates kubeconfig file enabling client communication with k8s api server
// @description **Access policy**: authenticated
// @description **Access policy**: authorized
// @tags kubernetes
// @security jwt
// @accept json

View File

@@ -13,7 +13,7 @@ import (
// @id getKubernetesNodesLimits
// @summary Get CPU and memory limits of all nodes within k8s cluster
// @description Get CPU and memory limits of all nodes within k8s cluster
// @description **Access policy**: authenticated
// @description **Access policy**: authorized
// @tags kubernetes
// @security jwt
// @accept json

View File

@@ -26,9 +26,7 @@ type motdData struct {
Style string `json:"style"`
}
// @id MOTD
// @summary fetches the message of the day
// @description **Access policy**: restricted
// @tags motd
// @security jwt
// @produce json

View File

@@ -81,7 +81,7 @@ func (payload *registryConfigurePayload) Validate(r *http.Request) error {
// @id RegistryConfigure
// @summary Configures a registry
// @description Configures a registry.
// @description **Access policy**: restricted
// @description **Access policy**: admin
// @tags registries
// @security jwt
// @accept json

View File

@@ -62,7 +62,7 @@ func (payload *registryCreatePayload) Validate(_ *http.Request) error {
// @id RegistryCreate
// @summary Create a new registry
// @description Create a new registry.
// @description **Access policy**: restricted
// @description **Access policy**: administrator
// @tags registries
// @security jwt
// @accept json

View File

@@ -15,7 +15,7 @@ import (
// @id RegistryDelete
// @summary Remove a registry
// @description Remove a registry
// @description **Access policy**: restricted
// @description **Access policy**: administrator
// @tags registries
// @security jwt
// @param id path int true "Registry identifier"

View File

@@ -14,7 +14,7 @@ import (
// @id RegistryInspect
// @summary Inspect a registry
// @description Retrieve details about a registry.
// @description **Access policy**: restricted
// @description **Access policy**: administrator
// @tags registries
// @security jwt
// @produce json

View File

@@ -37,7 +37,7 @@ func (payload *registryUpdatePayload) Validate(r *http.Request) error {
// @id RegistryUpdate
// @summary Update a registry
// @description Update a registry
// @description **Access policy**: restricted
// @description **Access policy**: administrator
// @tags registries
// @security jwt
// @accept json

View File

@@ -38,7 +38,7 @@ func (payload *resourceControlUpdatePayload) Validate(r *http.Request) error {
// @id ResourceControlUpdate
// @summary Update a resource control
// @description Update a resource control
// @description **Access policy**: authenticated
// @description **Access policy**: restricted
// @tags resource_controls
// @security jwt
// @accept json

View File

@@ -54,8 +54,11 @@ func (payload *settingsUpdatePayload) Validate(r *http.Request) error {
if payload.TemplatesURL != nil && *payload.TemplatesURL != "" && !govalidator.IsURL(*payload.TemplatesURL) {
return errors.New("Invalid external templates URL. Must correspond to a valid URL format")
}
if payload.HelmRepositoryURL != nil && *payload.HelmRepositoryURL != "" && !govalidator.IsURL(*payload.HelmRepositoryURL) {
return errors.New("Invalid Helm repository URL. Must correspond to a valid URL format")
if payload.HelmRepositoryURL != nil && *payload.HelmRepositoryURL != "" {
err := libhelm.ValidateHelmRepositoryURL(*payload.HelmRepositoryURL)
if err != nil {
return errors.Wrap(err, "Invalid Helm repository URL. Must correspond to a valid URL format")
}
}
if payload.UserSessionTimeout != nil {
_, err := time.ParseDuration(*payload.UserSessionTimeout)
@@ -111,16 +114,7 @@ func (handler *Handler) settingsUpdate(w http.ResponseWriter, r *http.Request) *
}
if payload.HelmRepositoryURL != nil {
newHelmRepo := strings.TrimSuffix(strings.ToLower(*payload.HelmRepositoryURL), "/")
if newHelmRepo != settings.HelmRepositoryURL && newHelmRepo != portainer.DefaultHelmRepositoryURL {
err := libhelm.ValidateHelmRepositoryURL(*payload.HelmRepositoryURL)
if err != nil {
return &httperror.HandlerError{http.StatusBadRequest, "Invalid Helm repository URL. Must correspond to a valid URL format", err}
}
}
settings.HelmRepositoryURL = newHelmRepo
settings.HelmRepositoryURL = strings.TrimSuffix(strings.ToLower(*payload.HelmRepositoryURL), "/")
}
if payload.BlackListedLabels != nil {

View File

@@ -14,22 +14,7 @@ import (
"github.com/portainer/portainer/api/internal/stackutils"
)
// @id StackAssociate
// @summary Associate an orphaned stack to a new environment(endpoint)
// @description **Access policy**: administrator
// @tags stacks
// @security jwt
// @produce json
// @param id path int true "Stack identifier"
// @param endpointId query int true "Stacks created before version 1.18.0 might not have an associated environment(endpoint) identifier. Use this optional parameter to set the environment(endpoint) identifier used by the stack."
// @param swarmId query int true "Swarm identifier"
// @param orphanedRunning query boolean true "Indicates whether the stack is orphaned"
// @success 200 {object} portainer.Stack "Success"
// @failure 400 "Invalid request"
// @failure 403 "Permission denied"
// @failure 404 "Stack not found"
// @failure 500 "Server error"
// @router /stacks/{id}/associate [put]
// PUT request on /api/stacks/:id/associate?endpointId=<endpointId>&swarmId=<swarmId>&orphanedRunning=<orphanedRunning>
func (handler *Handler) stackAssociate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
if err != nil {

View File

@@ -33,7 +33,7 @@ func (handler *Handler) cleanUp(stack *portainer.Stack, doCleanUp *bool) error {
// @id StackCreate
// @summary Deploy a new stack
// @description Deploy a new stack into a Docker environment(endpoint) specified via the environment(endpoint) identifier.
// @description **Access policy**: authenticated
// @description **Access policy**: restricted
// @tags stacks
// @security jwt
// @accept json,multipart/form-data

View File

@@ -24,10 +24,10 @@ type stackListOperationFilters struct {
// @description List all stacks based on the current user authorizations.
// @description Will return all stacks if using an administrator account otherwise it
// @description will only return the list of stacks the user have access to.
// @description **Access policy**: authenticated
// @description **Access policy**: restricted
// @tags stacks
// @security jwt
// @param filters query string false "Filters to process on the stack list. Encoded as JSON (a map[string]string). For example, {'SwarmID': 'jpofkc0i9uo9wtx1zesuk649w'} will only return stacks that are part of the specified Swarm cluster. Available filters: EndpointID, SwarmID."
// @param filters query string false "Filters to process on the stack list. Encoded as JSON (a map[string]string). For example, {"SwarmID": "jpofkc0i9uo9wtx1zesuk649w"} will only return stacks that are part of the specified Swarm cluster. Available filters: EndpointID, SwarmID."
// @success 200 {array} portainer.Stack "Success"
// @success 204 "Success"
// @failure 400 "Invalid request"

View File

@@ -34,7 +34,7 @@ func (payload *stackMigratePayload) Validate(r *http.Request) error {
// @id StackMigrate
// @summary Migrate a stack to another environment(endpoint)
// @description Migrate a stack from an environment(endpoint) to another environment(endpoint). It will re-create the stack inside the target environment(endpoint) before removing the original stack.
// @description **Access policy**: authenticated
// @description **Access policy**: restricted
// @tags stacks
// @security jwt
// @produce json
@@ -143,14 +143,12 @@ func (handler *Handler) stackMigrate(w http.ResponseWriter, r *http.Request) *ht
return migrationError
}
newName := stack.Name
stack.Name = oldName
err = handler.deleteStack(securityContext.UserID, stack, endpoint)
if err != nil {
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: err.Error(), Err: err}
}
stack.Name = newName
err = handler.DataStore.Stack().UpdateStack(stack.ID, stack)
if err != nil {
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to persist the stack changes inside the database", Err: err}

View File

@@ -20,7 +20,7 @@ import (
// @id StackStart
// @summary Starts a stopped Stack
// @description Starts a stopped Stack.
// @description **Access policy**: authenticated
// @description **Access policy**: restricted
// @tags stacks
// @security jwt
// @param id path int true "Stack identifier"

View File

@@ -18,7 +18,7 @@ import (
// @id StackStop
// @summary Stops a stopped Stack
// @description Stops a stopped Stack.
// @description **Access policy**: authenticated
// @description **Access policy**: restricted
// @tags stacks
// @security jwt
// @param id path int true "Stack identifier"

View File

@@ -51,7 +51,7 @@ func (payload *updateSwarmStackPayload) Validate(r *http.Request) error {
// @id StackUpdate
// @summary Update a stack
// @description Update a stack.
// @description **Access policy**: authenticated
// @description **Access policy**: restricted
// @tags stacks
// @security jwt
// @accept json

View File

@@ -40,7 +40,7 @@ func (payload *stackGitUpdatePayload) Validate(r *http.Request) error {
// @id StackUpdateGit
// @summary Update a stack's Git configs
// @description Update the Git settings in a stack, e.g., RepositoryReferenceName and AutoUpdate
// @description **Access policy**: authenticated
// @description **Access policy**: restricted
// @tags stacks
// @security jwt
// @accept json
@@ -146,10 +146,6 @@ func (handler *Handler) stackUpdateGit(w http.ResponseWriter, r *http.Request) *
Username: payload.RepositoryUsername,
Password: password,
}
_, err = handler.GitService.LatestCommitID(stack.GitConfig.URL, stack.GitConfig.ReferenceName, stack.GitConfig.Authentication.Username, stack.GitConfig.Authentication.Password)
if err != nil {
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to fetch git repository", Err: err}
}
}
if payload.AutoUpdate != nil && payload.AutoUpdate.Interval != "" {

View File

@@ -38,7 +38,7 @@ func (payload *stackGitRedployPayload) Validate(r *http.Request) error {
// @id StackGitRedeploy
// @summary Redeploy a stack
// @description Pull and redeploy a stack via Git
// @description **Access policy**: authenticated
// @description **Access policy**: restricted
// @tags stacks
// @security jwt
// @accept json

View File

@@ -74,10 +74,6 @@ func (handler *Handler) updateKubernetesStack(r *http.Request, stack *portainer.
Username: payload.RepositoryUsername,
Password: password,
}
_, err := handler.GitService.LatestCommitID(stack.GitConfig.URL, stack.GitConfig.ReferenceName, stack.GitConfig.Authentication.Username, stack.GitConfig.Authentication.Password)
if err != nil {
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to fetch git repository", Err: err}
}
} else {
stack.GitConfig.Authentication = nil
}

View File

@@ -15,16 +15,6 @@ import (
"github.com/portainer/libhttp/request"
)
// @id WebhookInvoke
// @summary Webhook for triggering stack updates from git
// @description **Access policy**: public
// @tags stacks
// @param webhookID path string true "Stack identifier"
// @success 200 "Success"
// @failure 400 "Invalid request"
// @failure 409 "Conflict"
// @failure 500 "Server error"
// @router /stacks/webhooks/{webhookID} [post]
func (handler *Handler) webhookInvoke(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
webhookID, err := retrieveUUIDRouteVariableValue(r, "webhookID")
if err != nil {

View File

@@ -29,7 +29,6 @@ func (payload *tagCreatePayload) Validate(r *http.Request) error {
// @description **Access policy**: administrator
// @tags tags
// @security jwt
// @accept json
// @produce json
// @param body body tagCreatePayload true "Tag details"
// @success 200 {object} portainer.Tag "Success"

View File

@@ -17,6 +17,8 @@ import (
// @description **Access policy**: administrator
// @tags tags
// @security jwt
// @accept json
// @produce json
// @param id path int true "Tag identifier"
// @success 204 "Success"
// @failure 400 "Invalid request"

View File

@@ -10,7 +10,7 @@ import (
// @id TagList
// @summary List tags
// @description List tags.
// @description **Access policy**: authenticated
// @description **Access policy**: administrator
// @tags tags
// @security jwt
// @produce json

View File

@@ -37,7 +37,7 @@ func (payload *teamMembershipCreatePayload) Validate(r *http.Request) error {
// @id TeamMembershipCreate
// @summary Create a new team membership
// @description Create a new team memberships. Access is only available to administrators leaders of the associated team.
// @description **Access policy**: administrator
// @description **Access policy**: admin
// @tags team_memberships
// @security jwt
// @accept json

View File

@@ -15,7 +15,7 @@ import (
// @id TeamMembershipDelete
// @summary Remove a team membership
// @description Remove a team membership. Access is only available to administrators leaders of the associated team.
// @description **Access policy**: administrator
// @description **Access policy**: restricted
// @tags team_memberships
// @security jwt
// @param id path int true "TeamMembership identifier"

View File

@@ -12,7 +12,7 @@ import (
// @id TeamMembershipList
// @summary List team memberships
// @description List team memberships. Access is only available to administrators and team leaders.
// @description **Access policy**: administrator
// @description **Access policy**: admin
// @tags team_memberships
// @security jwt
// @produce json

View File

@@ -38,7 +38,7 @@ func (payload *teamMembershipUpdatePayload) Validate(r *http.Request) error {
// @id TeamMembershipUpdate
// @summary Update a team membership
// @description Update a team membership. Access is only available to administrators leaders of the associated team.
// @description **Access policy**: administrator
// @description **Access policy**: restricted
// @tags team_memberships
// @security jwt
// @accept json

View File

@@ -15,7 +15,7 @@ import (
// @id TeamInspect
// @summary Inspect a team
// @description Retrieve details about a team. Access is only available for administrator and leaders of that team.
// @description **Access policy**: administrator
// @description **Access policy**: restricted
// @tags teams
// @security jwt
// @produce json

View File

@@ -23,7 +23,7 @@ func (payload *teamUpdatePayload) Validate(r *http.Request) error {
// @summary Update a team
// @description Update a team.
// @description **Access policy**: administrator
// @tags teams
// @tags
// @security jwt
// @accept json
// @produce json

View File

@@ -39,7 +39,7 @@ func (payload *filePayload) Validate(r *http.Request) error {
// @id TemplateFile
// @summary Get a template's file
// @description Get a template's file
// @description **Access policy**: authenticated
// @description **Access policy**: restricted
// @tags templates
// @security jwt
// @accept json

View File

@@ -17,7 +17,7 @@ type listResponse struct {
// @id TemplateList
// @summary List available templates
// @description List available templates.
// @description **Access policy**: authenticated
// @description **Access policy**: restricted
// @tags templates
// @security jwt
// @produce json

View File

@@ -32,7 +32,7 @@ func (payload *adminInitPayload) Validate(r *http.Request) error {
// @summary Initialize administrator account
// @description Initialize the 'admin' user account.
// @description **Access policy**: public
// @tags users
// @tags
// @accept json
// @produce json
// @param body body adminInitPayload true "User details"

View File

@@ -18,6 +18,7 @@ import (
// @description **Access policy**: administrator
// @tags users
// @security jwt
// @accept json
// @produce json
// @param id path int true "User identifier"
// @success 204 "Success"

View File

@@ -16,7 +16,7 @@ import (
// @summary Inspect a user
// @description Retrieve details about a user.
// @description User passwords are filtered out, and should never be accessible.
// @description **Access policy**: authenticated
// @description **Access policy**: administrator
// @tags users
// @security jwt
// @produce json

View File

@@ -14,7 +14,7 @@ import (
// @id UserMembershipsInspect
// @summary Inspect a user memberships
// @description Inspect a user memberships.
// @description **Access policy**: restricted
// @description **Access policy**: authenticated
// @tags users
// @security jwt
// @produce json

View File

@@ -33,7 +33,7 @@ func (payload *webhookCreatePayload) Validate(r *http.Request) error {
}
// @summary Create a webhook
// @description **Access policy**: authenticated
// @description
// @security jwt
// @tags webhooks
// @accept json

View File

@@ -10,9 +10,11 @@ import (
)
// @summary Delete a webhook
// @description **Access policy**: authenticated
// @description
// @security jwt
// @tags webhooks
// @accept json
// @produce json
// @param id path int true "Webhook id"
// @success 202 "Webhook deleted"
// @failure 400

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