feat(performance): performance optimizations EE-6042 (#10520)

pull/10545/head
andres-portainer 2023-10-24 13:55:11 -03:00 committed by GitHub
parent e4e66dac9c
commit ae1726cece
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
71 changed files with 311 additions and 382 deletions

View File

@ -13,6 +13,8 @@ linters-settings:
rules: rules:
main: main:
deny: deny:
- pkg: 'encoding/json'
desc: 'use github.com/segmentio/encoding/json'
- pkg: 'github.com/sirupsen/logrus' - pkg: 'github.com/sirupsen/logrus'
desc: 'logging is allowed only by github.com/rs/zerolog' desc: 'logging is allowed only by github.com/rs/zerolog'
- pkg: 'golang.org/x/exp' - pkg: 'golang.org/x/exp'

View File

@ -255,7 +255,7 @@ func (connection *DbConnection) UpdateObjectFunc(bucketName string, key []byte,
return fmt.Errorf("%w (bucket=%s, key=%s)", dserrors.ErrObjectNotFound, bucketName, keyToString(key)) return fmt.Errorf("%w (bucket=%s, key=%s)", dserrors.ErrObjectNotFound, bucketName, keyToString(key))
} }
err := connection.UnmarshalObjectWithJsoniter(data, object) err := connection.UnmarshalObject(data, object)
if err != nil { if err != nil {
return err return err
} }

View File

@ -1,10 +1,10 @@
package boltdb package boltdb
import ( import (
"encoding/json"
"time" "time"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/segmentio/encoding/json"
bolt "go.etcd.io/bbolt" bolt "go.etcd.io/bbolt"
) )

View File

@ -1,34 +1,41 @@
package boltdb package boltdb
import ( import (
"bytes"
"crypto/aes" "crypto/aes"
"crypto/cipher" "crypto/cipher"
"crypto/rand" "crypto/rand"
"encoding/json"
"fmt" "fmt"
"io" "io"
jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/segmentio/encoding/json"
) )
var errEncryptedStringTooShort = fmt.Errorf("encrypted string too short") var errEncryptedStringTooShort = fmt.Errorf("encrypted string too short")
// MarshalObject encodes an object to binary format // MarshalObject encodes an object to binary format
func (connection *DbConnection) MarshalObject(object interface{}) (data []byte, err error) { func (connection *DbConnection) MarshalObject(object interface{}) ([]byte, error) {
buf := &bytes.Buffer{}
// Special case for the VERSION bucket. Here we're not using json // Special case for the VERSION bucket. Here we're not using json
if v, ok := object.(string); ok { if v, ok := object.(string); ok {
data = []byte(v) buf.WriteString(v)
} else { } else {
data, err = json.Marshal(object) enc := json.NewEncoder(buf)
if err != nil { enc.SetSortMapKeys(false)
return data, err enc.SetAppendNewline(false)
if err := enc.Encode(object); err != nil {
return nil, err
} }
} }
if connection.getEncryptionKey() == nil { if connection.getEncryptionKey() == nil {
return data, nil return buf.Bytes(), nil
} }
return encrypt(data, connection.getEncryptionKey())
return encrypt(buf.Bytes(), connection.getEncryptionKey())
} }
// UnmarshalObject decodes an object from binary data // UnmarshalObject decodes an object from binary data
@ -54,31 +61,6 @@ func (connection *DbConnection) UnmarshalObject(data []byte, object interface{})
return err return err
} }
// UnmarshalObjectWithJsoniter decodes an object from binary data
// using the jsoniter library. It is mainly used to accelerate environment(endpoint)
// decoding at the moment.
func (connection *DbConnection) UnmarshalObjectWithJsoniter(data []byte, object interface{}) error {
if connection.getEncryptionKey() != nil {
var err error
data, err = decrypt(data, connection.getEncryptionKey())
if err != nil {
return err
}
}
var jsoni = jsoniter.ConfigCompatibleWithStandardLibrary
err := jsoni.Unmarshal(data, &object)
if err != nil {
if s, ok := object.(*string); ok {
*s = string(data)
return nil
}
return err
}
return nil
}
// mmm, don't have a KMS .... aes GCM seems the most likely from // mmm, don't have a KMS .... aes GCM seems the most likely from
// https://gist.github.com/atoponce/07d8d4c833873be2f68c34f9afc5a78a#symmetric-encryption // https://gist.github.com/atoponce/07d8d4c833873be2f68c34f9afc5a78a#symmetric-encryption

View File

@ -28,7 +28,7 @@ func (tx *DbTransaction) GetObject(bucketName string, key []byte, object interfa
return fmt.Errorf("%w (bucket=%s, key=%s)", dserrors.ErrObjectNotFound, bucketName, keyToString(key)) return fmt.Errorf("%w (bucket=%s, key=%s)", dserrors.ErrObjectNotFound, bucketName, keyToString(key))
} }
return tx.conn.UnmarshalObjectWithJsoniter(value, object) return tx.conn.UnmarshalObject(value, object)
} }
func (tx *DbTransaction) UpdateObject(bucketName string, key []byte, object interface{}) error { func (tx *DbTransaction) UpdateObject(bucketName string, key []byte, object interface{}) error {
@ -134,7 +134,7 @@ func (tx *DbTransaction) GetAllWithJsoniter(bucketName string, obj interface{},
bucket := tx.tx.Bucket([]byte(bucketName)) bucket := tx.tx.Bucket([]byte(bucketName))
return bucket.ForEach(func(k []byte, v []byte) error { return bucket.ForEach(func(k []byte, v []byte) error {
err := tx.conn.UnmarshalObjectWithJsoniter(v, obj) err := tx.conn.UnmarshalObject(v, obj)
if err == nil { if err == nil {
obj, err = appendFn(obj) obj, err = appendFn(obj)
} }
@ -147,7 +147,7 @@ func (tx *DbTransaction) GetAllWithKeyPrefix(bucketName string, keyPrefix []byte
cursor := tx.tx.Bucket([]byte(bucketName)).Cursor() cursor := tx.tx.Bucket([]byte(bucketName)).Cursor()
for k, v := cursor.Seek(keyPrefix); k != nil && bytes.HasPrefix(k, keyPrefix); k, v = cursor.Next() { for k, v := cursor.Seek(keyPrefix); k != nil && bytes.HasPrefix(k, keyPrefix); k, v = cursor.Next() {
err := tx.conn.UnmarshalObjectWithJsoniter(v, obj) err := tx.conn.UnmarshalObject(v, obj)
if err != nil { if err != nil {
return err return err
} }

View File

@ -2,7 +2,6 @@ package datastore
import ( import (
"bytes" "bytes"
"encoding/json"
"fmt" "fmt"
"io" "io"
"os" "os"
@ -11,10 +10,11 @@ import (
"testing" "testing"
"github.com/portainer/portainer/api/database/boltdb" "github.com/portainer/portainer/api/database/boltdb"
"github.com/portainer/portainer/api/database/models"
"github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp"
"github.com/portainer/portainer/api/database/models"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/segmentio/encoding/json"
) )
// testVersion is a helper which tests current store version against wanted version // testVersion is a helper which tests current store version against wanted version

View File

@ -1,7 +1,6 @@
package datastore package datastore
import ( import (
"encoding/json"
"fmt" "fmt"
"os" "os"
@ -38,6 +37,7 @@ import (
"github.com/portainer/portainer/api/dataservices/webhook" "github.com/portainer/portainer/api/dataservices/webhook"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/segmentio/encoding/json"
) )
// Store defines the implementation of portainer.DataStore using // Store defines the implementation of portainer.DataStore using

View File

@ -27,9 +27,7 @@
], ],
"endpoints": [ "endpoints": [
{ {
"Agent": { "Agent": {},
"Version": ""
},
"AuthorizedTeams": null, "AuthorizedTeams": null,
"AuthorizedUsers": null, "AuthorizedUsers": null,
"AzureCredentials": { "AzureCredentials": {
@ -38,71 +36,42 @@
"TenantID": "" "TenantID": ""
}, },
"ComposeSyntaxMaxVersion": "", "ComposeSyntaxMaxVersion": "",
"Edge": { "Edge": {},
"AsyncMode": false,
"CommandInterval": 0,
"PingInterval": 0,
"SnapshotInterval": 0
},
"EdgeCheckinInterval": 0, "EdgeCheckinInterval": 0,
"EdgeKey": "",
"EnableGPUManagement": false,
"Gpus": [], "Gpus": [],
"GroupId": 1, "GroupId": 1,
"Heartbeat": false,
"Id": 1, "Id": 1,
"IsEdgeDevice": false,
"Kubernetes": { "Kubernetes": {
"Configuration": { "Configuration": {
"AllowNoneIngressClass": false,
"EnableResourceOverCommit": false,
"IngressAvailabilityPerNamespace": true, "IngressAvailabilityPerNamespace": true,
"IngressClasses": null, "IngressClasses": null,
"ResourceOverCommitPercentage": 0, "StorageClasses": null
"RestrictDefaultNamespace": false,
"StorageClasses": null,
"UseLoadBalancer": false,
"UseServerMetrics": false
},
"Flags": {
"IsServerIngressClassDetected": false,
"IsServerMetricsDetected": false,
"IsServerStorageDetected": false
}, },
"Flags": {},
"Snapshots": [] "Snapshots": []
}, },
"LastCheckInDate": 0,
"Name": "local", "Name": "local",
"PostInitMigrations": { "PostInitMigrations": {
"MigrateGPUs": true, "MigrateGPUs": true,
"MigrateIngresses": true "MigrateIngresses": true
}, },
"PublicURL": "",
"QueryDate": 0,
"SecuritySettings": { "SecuritySettings": {
"allowBindMountsForRegularUsers": true, "allowBindMountsForRegularUsers": true,
"allowContainerCapabilitiesForRegularUsers": true, "allowContainerCapabilitiesForRegularUsers": true,
"allowDeviceMappingForRegularUsers": true, "allowDeviceMappingForRegularUsers": true,
"allowHostNamespaceForRegularUsers": true, "allowHostNamespaceForRegularUsers": true,
"allowPrivilegedModeForRegularUsers": true, "allowPrivilegedModeForRegularUsers": true,
"allowStackManagementForRegularUsers": true, "allowStackManagementForRegularUsers": true
"allowSysctlSettingForRegularUsers": false,
"allowVolumeBrowserForRegularUsers": false,
"enableHostManagementFeatures": false
}, },
"Snapshots": [], "Snapshots": [],
"Status": 1, "Status": 1,
"TLSConfig": { "TLSConfig": {},
"TLS": false,
"TLSSkipVerify": false
},
"TagIds": [], "TagIds": [],
"Tags": null, "Tags": null,
"TeamAccessPolicies": {}, "TeamAccessPolicies": {},
"Type": 1, "Type": 1,
"URL": "unix:///var/run/docker.sock", "URL": "unix:///var/run/docker.sock",
"UserAccessPolicies": {}, "UserAccessPolicies": {}
"UserTrusted": false
} }
], ],
"registries": [ "registries": [
@ -110,7 +79,6 @@
"Authentication": true, "Authentication": true,
"AuthorizedTeams": null, "AuthorizedTeams": null,
"AuthorizedUsers": null, "AuthorizedUsers": null,
"BaseURL": "",
"Ecr": { "Ecr": {
"Region": "" "Region": ""
}, },
@ -124,8 +92,7 @@
"Name": "canister.io", "Name": "canister.io",
"Password": "MjWbx8A6YK7cw7", "Password": "MjWbx8A6YK7cw7",
"Quay": { "Quay": {
"OrganisationName": "", "OrganisationName": ""
"UseOrganisation": false
}, },
"RegistryAccesses": { "RegistryAccesses": {
"1": { "1": {
@ -154,34 +121,28 @@
"UserAccesses": [] "UserAccesses": []
}, },
{ {
"AdministratorsOnly": false,
"Id": 3, "Id": 3,
"Public": true, "Public": true,
"ResourceId": "1_alpine", "ResourceId": "1_alpine",
"SubResourceIds": [], "SubResourceIds": [],
"System": false,
"TeamAccesses": [], "TeamAccesses": [],
"Type": 6, "Type": 6,
"UserAccesses": [] "UserAccesses": []
}, },
{ {
"AdministratorsOnly": false,
"Id": 4, "Id": 4,
"Public": true, "Public": true,
"ResourceId": "1_redis", "ResourceId": "1_redis",
"SubResourceIds": [], "SubResourceIds": [],
"System": false,
"TeamAccesses": [], "TeamAccesses": [],
"Type": 6, "Type": 6,
"UserAccesses": [] "UserAccesses": []
}, },
{ {
"AdministratorsOnly": false,
"Id": 5, "Id": 5,
"Public": false, "Public": false,
"ResourceId": "1_nginx", "ResourceId": "1_nginx",
"SubResourceIds": [], "SubResourceIds": [],
"System": false,
"TeamAccesses": [ "TeamAccesses": [
{ {
"AccessLevel": 1, "AccessLevel": 1,
@ -577,18 +538,14 @@
} }
], ],
"settings": { "settings": {
"AgentSecret": "",
"AllowBindMountsForRegularUsers": true, "AllowBindMountsForRegularUsers": true,
"AllowContainerCapabilitiesForRegularUsers": true, "AllowContainerCapabilitiesForRegularUsers": true,
"AllowDeviceMappingForRegularUsers": true, "AllowDeviceMappingForRegularUsers": true,
"AllowHostNamespaceForRegularUsers": true, "AllowHostNamespaceForRegularUsers": true,
"AllowPrivilegedModeForRegularUsers": true, "AllowPrivilegedModeForRegularUsers": true,
"AllowStackManagementForRegularUsers": true, "AllowStackManagementForRegularUsers": true,
"AllowVolumeBrowserForRegularUsers": false,
"AuthenticationMethod": 1, "AuthenticationMethod": 1,
"BlackListedLabels": [], "BlackListedLabels": [],
"DisplayDonationHeader": false,
"DisplayExternalContributors": false,
"Edge": { "Edge": {
"AsyncMode": false, "AsyncMode": false,
"CommandInterval": 0, "CommandInterval": 0,
@ -596,20 +553,13 @@
"SnapshotInterval": 0 "SnapshotInterval": 0
}, },
"EdgeAgentCheckinInterval": 5, "EdgeAgentCheckinInterval": 5,
"EdgePortainerUrl": "",
"EnableEdgeComputeFeatures": false,
"EnableHostManagementFeatures": false,
"EnableTelemetry": true, "EnableTelemetry": true,
"EnforceEdgeID": false,
"FeatureFlagSettings": null, "FeatureFlagSettings": null,
"GlobalDeploymentOptions": { "GlobalDeploymentOptions": {},
"hideStacksFunctionality": false
},
"HelmRepositoryURL": "https://charts.bitnami.com/bitnami", "HelmRepositoryURL": "https://charts.bitnami.com/bitnami",
"InternalAuthSettings": { "InternalAuthSettings": {
"RequiredPasswordLength": 12 "RequiredPasswordLength": 12
}, },
"IsDockerDesktopExtension": false,
"KubeconfigExpiry": "0", "KubeconfigExpiry": "0",
"KubectlShellImage": "portainer/kubectl-shell", "KubectlShellImage": "portainer/kubectl-shell",
"LDAPSettings": { "LDAPSettings": {
@ -618,8 +568,7 @@
"GroupSearchSettings": [ "GroupSearchSettings": [
{ {
"GroupAttribute": "", "GroupAttribute": "",
"GroupBaseDN": "", "GroupBaseDN": ""
"GroupFilter": ""
} }
], ],
"ReaderDN": "", "ReaderDN": "",
@ -630,14 +579,9 @@
"UserNameAttribute": "" "UserNameAttribute": ""
} }
], ],
"StartTLS": false, "TLSConfig": {},
"TLSConfig": {
"TLS": false,
"TLSSkipVerify": false
},
"URL": "" "URL": ""
}, },
"LogoURL": "",
"OAuthSettings": { "OAuthSettings": {
"AccessTokenURI": "", "AccessTokenURI": "",
"AuthorizationURI": "", "AuthorizationURI": "",
@ -652,10 +596,8 @@
"Scopes": "", "Scopes": "",
"UserIdentifier": "" "UserIdentifier": ""
}, },
"ShowKomposeBuildOption": false,
"SnapshotInterval": "5m", "SnapshotInterval": "5m",
"TemplatesURL": "https://raw.githubusercontent.com/portainer/templates/master/templates-2.0.json", "TemplatesURL": "https://raw.githubusercontent.com/portainer/templates/master/templates-2.0.json",
"TrustOnFirstConnect": false,
"UserSessionTimeout": "8h", "UserSessionTimeout": "8h",
"fdoConfiguration": { "fdoConfiguration": {
"enabled": false, "enabled": false,
@ -794,34 +736,23 @@
"UnhealthyContainerCount": 0, "UnhealthyContainerCount": 0,
"VolumeCount": 10 "VolumeCount": 10
}, },
"EndpointId": 1, "EndpointId": 1
"Kubernetes": null
} }
], ],
"ssl": { "ssl": {
"certPath": "", "httpEnabled": true
"httpEnabled": true,
"keyPath": "",
"selfSigned": false
}, },
"stacks": [ "stacks": [
{ {
"AdditionalFiles": null, "AdditionalFiles": null,
"AutoUpdate": null,
"CreatedBy": "", "CreatedBy": "",
"CreationDate": 0, "CreationDate": 0,
"EndpointId": 1, "EndpointId": 1,
"EntryPoint": "docker/alpine37-compose.yml", "EntryPoint": "docker/alpine37-compose.yml",
"Env": [], "Env": [],
"FromAppTemplate": false,
"GitConfig": null,
"Id": 2, "Id": 2,
"IsComposeFormat": false,
"Name": "alpine", "Name": "alpine",
"Namespace": "",
"Option": null,
"ProjectPath": "/home/prabhat/portainer/data/ce1.25/compose/2", "ProjectPath": "/home/prabhat/portainer/data/ce1.25/compose/2",
"ResourceControl": null,
"Status": 1, "Status": 1,
"SwarmId": "s3fd604zdba7z13tbq2x6lyue", "SwarmId": "s3fd604zdba7z13tbq2x6lyue",
"Type": 1, "Type": 1,
@ -830,46 +761,30 @@
}, },
{ {
"AdditionalFiles": null, "AdditionalFiles": null,
"AutoUpdate": null,
"CreatedBy": "", "CreatedBy": "",
"CreationDate": 0, "CreationDate": 0,
"EndpointId": 1, "EndpointId": 1,
"EntryPoint": "docker-compose.yml", "EntryPoint": "docker-compose.yml",
"Env": [], "Env": [],
"FromAppTemplate": false,
"GitConfig": null,
"Id": 5, "Id": 5,
"IsComposeFormat": false,
"Name": "redis", "Name": "redis",
"Namespace": "",
"Option": null,
"ProjectPath": "/home/prabhat/portainer/data/ce1.25/compose/5", "ProjectPath": "/home/prabhat/portainer/data/ce1.25/compose/5",
"ResourceControl": null,
"Status": 1, "Status": 1,
"SwarmId": "",
"Type": 2, "Type": 2,
"UpdateDate": 0, "UpdateDate": 0,
"UpdatedBy": "" "UpdatedBy": ""
}, },
{ {
"AdditionalFiles": null, "AdditionalFiles": null,
"AutoUpdate": null,
"CreatedBy": "", "CreatedBy": "",
"CreationDate": 0, "CreationDate": 0,
"EndpointId": 1, "EndpointId": 1,
"EntryPoint": "docker-compose.yml", "EntryPoint": "docker-compose.yml",
"Env": [], "Env": [],
"FromAppTemplate": false,
"GitConfig": null,
"Id": 6, "Id": 6,
"IsComposeFormat": false,
"Name": "nginx", "Name": "nginx",
"Namespace": "",
"Option": null,
"ProjectPath": "/home/prabhat/portainer/data/ce1.25/compose/6", "ProjectPath": "/home/prabhat/portainer/data/ce1.25/compose/6",
"ResourceControl": null,
"Status": 1, "Status": 1,
"SwarmId": "",
"Type": 2, "Type": 2,
"UpdateDate": 0, "UpdateDate": 0,
"UpdatedBy": "" "UpdatedBy": ""
@ -881,9 +796,7 @@
"Name": "hello" "Name": "hello"
} }
], ],
"tunnel_server": { "tunnel_server": {},
"PrivateKeySeed": ""
},
"users": [ "users": [
{ {
"EndpointAuthorizations": null, "EndpointAuthorizations": null,
@ -908,11 +821,8 @@
"PortainerUserRevokeToken": true "PortainerUserRevokeToken": true
}, },
"Role": 1, "Role": 1,
"ThemeSettings": { "ThemeSettings": {},
"color": ""
},
"TokenIssueAt": 0, "TokenIssueAt": 0,
"UserTheme": "",
"Username": "admin" "Username": "admin"
}, },
{ {
@ -938,11 +848,8 @@
"PortainerUserRevokeToken": true "PortainerUserRevokeToken": true
}, },
"Role": 1, "Role": 1,
"ThemeSettings": { "ThemeSettings": {},
"color": ""
},
"TokenIssueAt": 0, "TokenIssueAt": 0,
"UserTheme": "",
"Username": "prabhat" "Username": "prabhat"
} }
], ],

View File

@ -2,7 +2,6 @@ package exec
import ( import (
"bytes" "bytes"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"os" "os"
@ -15,7 +14,9 @@ import (
"github.com/portainer/portainer/api/dataservices" "github.com/portainer/portainer/api/dataservices"
"github.com/portainer/portainer/api/internal/registryutils" "github.com/portainer/portainer/api/internal/registryutils"
"github.com/portainer/portainer/api/stacks/stackutils" "github.com/portainer/portainer/api/stacks/stackutils"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/segmentio/encoding/json"
) )
// SwarmStackManager represents a service for managing stacks. // SwarmStackManager represents a service for managing stacks.

View File

@ -2,7 +2,6 @@ package filesystem
import ( import (
"bytes" "bytes"
"encoding/json"
"encoding/pem" "encoding/pem"
"errors" "errors"
"fmt" "fmt"
@ -15,6 +14,7 @@ import (
"github.com/gofrs/uuid" "github.com/gofrs/uuid"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/segmentio/encoding/json"
) )
const ( const (

View File

@ -2,7 +2,6 @@ package git
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -11,12 +10,13 @@ import (
"strings" "strings"
"time" "time"
"github.com/go-git/go-git/v5/plumbing/filemode"
"github.com/portainer/portainer/api/archive" "github.com/portainer/portainer/api/archive"
"github.com/portainer/portainer/api/crypto" "github.com/portainer/portainer/api/crypto"
gittypes "github.com/portainer/portainer/api/git/types" gittypes "github.com/portainer/portainer/api/git/types"
"github.com/go-git/go-git/v5/plumbing/filemode"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/segmentio/encoding/json"
) )
const ( const (

View File

@ -2,12 +2,13 @@ package openamt
import ( import (
"bytes" "bytes"
"encoding/json"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/segmentio/encoding/json"
) )
type authenticationResponse struct { type authenticationResponse struct {

View File

@ -2,7 +2,6 @@ package openamt
import ( import (
"encoding/base64" "encoding/base64"
"encoding/json"
"encoding/pem" "encoding/pem"
"fmt" "fmt"
"io" "io"
@ -11,6 +10,8 @@ import (
"strings" "strings"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/segmentio/encoding/json"
) )
type CIRAConfig struct { type CIRAConfig struct {

View File

@ -1,11 +1,12 @@
package openamt package openamt
import ( import (
"encoding/json"
"fmt" "fmt"
"strings" "strings"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/segmentio/encoding/json"
) )
type Device struct { type Device struct {

View File

@ -1,11 +1,12 @@
package openamt package openamt
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/segmentio/encoding/json"
) )
type ( type (

View File

@ -1,11 +1,12 @@
package openamt package openamt
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/segmentio/encoding/json"
) )
type ( type (

View File

@ -1,12 +1,13 @@
package openamt package openamt
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"strings" "strings"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/segmentio/encoding/json"
) )
type ActionResponse struct { type ActionResponse struct {

View File

@ -1,11 +1,12 @@
package openamt package openamt
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/segmentio/encoding/json"
) )
func (service *Service) enableDeviceFeatures(configuration portainer.OpenAMTConfiguration, deviceGUID string, features portainer.OpenAMTDeviceEnabledFeatures) error { func (service *Service) enableDeviceFeatures(configuration portainer.OpenAMTConfiguration, deviceGUID string, features portainer.OpenAMTDeviceEnabledFeatures) error {

View File

@ -2,7 +2,6 @@ package openamt
import ( import (
"bytes" "bytes"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io" "io"
@ -12,6 +11,7 @@ import (
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/crypto" "github.com/portainer/portainer/api/crypto"
"github.com/segmentio/encoding/json"
"golang.org/x/sync/errgroup" "golang.org/x/sync/errgroup"
) )

View File

@ -2,7 +2,6 @@ package client
import ( import (
"crypto/tls" "crypto/tls"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io" "io"
@ -14,6 +13,7 @@ import (
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/segmentio/encoding/json"
) )
var errInvalidResponseStatus = errors.New("invalid response status (expecting 200)") var errInvalidResponseStatus = errors.New("invalid response status (expecting 200)")

View File

@ -1,7 +1,6 @@
package customtemplates package customtemplates
import ( import (
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"net/http" "net/http"
@ -21,6 +20,7 @@ import (
"github.com/asaskevich/govalidator" "github.com/asaskevich/govalidator"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/segmentio/encoding/json"
) )
func (handler *Handler) customTemplateCreate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError { func (handler *Handler) customTemplateCreate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {

View File

@ -2,7 +2,6 @@ package customtemplates
import ( import (
"bytes" "bytes"
"encoding/json"
"fmt" "fmt"
"io" "io"
"io/fs" "io/fs"
@ -20,6 +19,8 @@ import (
"github.com/portainer/portainer/api/http/security" "github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/internal/authorization" "github.com/portainer/portainer/api/internal/authorization"
"github.com/portainer/portainer/api/jwt" "github.com/portainer/portainer/api/jwt"
"github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -2,13 +2,14 @@ package edgestacks
import ( import (
"bytes" "bytes"
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"testing" "testing"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/segmentio/encoding/json"
) )
// Create // Create

View File

@ -1,13 +1,14 @@
package edgestacks package edgestacks
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"testing" "testing"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/segmentio/encoding/json"
) )
// Delete // Delete

View File

@ -2,13 +2,14 @@ package edgestacks
import ( import (
"bytes" "bytes"
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"testing" "testing"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/segmentio/encoding/json"
) )
// Update Status // Update Status

View File

@ -2,7 +2,6 @@ package edgestacks
import ( import (
"bytes" "bytes"
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
@ -10,6 +9,8 @@ import (
"testing" "testing"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/segmentio/encoding/json"
) )
// Update // Update

View File

@ -1,13 +1,14 @@
package edgetemplates package edgetemplates
import ( import (
"encoding/json"
"net/http" "net/http"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/http/client" "github.com/portainer/portainer/api/http/client"
httperror "github.com/portainer/portainer/pkg/libhttp/error" httperror "github.com/portainer/portainer/pkg/libhttp/error"
"github.com/portainer/portainer/pkg/libhttp/response" "github.com/portainer/portainer/pkg/libhttp/response"
"github.com/segmentio/encoding/json"
) )
type templateFileFormat struct { type templateFileFormat struct {

View File

@ -2,7 +2,6 @@ package endpointedge
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
@ -17,6 +16,7 @@ import (
"github.com/portainer/portainer/api/http/security" "github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/jwt" "github.com/portainer/portainer/api/jwt"
"github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -1,7 +1,6 @@
package endpoints package endpoints
import ( import (
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io" "io"
@ -15,6 +14,8 @@ import (
httperror "github.com/portainer/portainer/pkg/libhttp/error" httperror "github.com/portainer/portainer/pkg/libhttp/error"
"github.com/portainer/portainer/pkg/libhttp/request" "github.com/portainer/portainer/pkg/libhttp/request"
"github.com/portainer/portainer/pkg/libhttp/response" "github.com/portainer/portainer/pkg/libhttp/response"
"github.com/segmentio/encoding/json"
) )
type dockerhubStatusResponse struct { type dockerhubStatusResponse struct {

View File

@ -1,7 +1,6 @@
package endpoints package endpoints
import ( import (
"encoding/json"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -13,6 +12,8 @@ import (
"github.com/portainer/portainer/api/http/security" "github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/internal/snapshot" "github.com/portainer/portainer/api/internal/snapshot"
"github.com/portainer/portainer/api/internal/testhelpers" "github.com/portainer/portainer/api/internal/testhelpers"
"github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -27,13 +28,13 @@ func Test_EndpointList_AgentVersion(t *testing.T) {
GroupID: 1, GroupID: 1,
Type: portainer.AgentOnDockerEnvironment, Type: portainer.AgentOnDockerEnvironment,
Agent: struct { Agent: struct {
Version string "example:\"1.0.0\"" Version string `json:"Version,omitempty" example:"1.0.0"`
}{ }{
Version: "1.0.0", Version: "1.0.0",
}, },
} }
version2Endpoint := portainer.Endpoint{ID: 2, GroupID: 1, Type: portainer.AgentOnDockerEnvironment, Agent: struct { version2Endpoint := portainer.Endpoint{ID: 2, GroupID: 1, Type: portainer.AgentOnDockerEnvironment, Agent: struct {
Version string "example:\"1.0.0\"" Version string `json:"Version,omitempty" example:"1.0.0"`
}{Version: "2.0.0"}} }{Version: "2.0.0"}}
noVersionEndpoint := portainer.Endpoint{ID: 3, Type: portainer.AgentOnDockerEnvironment, GroupID: 1} noVersionEndpoint := portainer.Endpoint{ID: 3, Type: portainer.AgentOnDockerEnvironment, GroupID: 1}
notAgentEnvironments := portainer.Endpoint{ID: 4, Type: portainer.DockerEnvironment, GroupID: 1} notAgentEnvironments := portainer.Endpoint{ID: 4, Type: portainer.DockerEnvironment, GroupID: 1}

View File

@ -22,12 +22,12 @@ func Test_Filter_AgentVersion(t *testing.T) {
version1Endpoint := portainer.Endpoint{ID: 1, GroupID: 1, version1Endpoint := portainer.Endpoint{ID: 1, GroupID: 1,
Type: portainer.AgentOnDockerEnvironment, Type: portainer.AgentOnDockerEnvironment,
Agent: struct { Agent: struct {
Version string "example:\"1.0.0\"" Version string `json:"Version,omitempty" example:"1.0.0"`
}{Version: "1.0.0"}} }{Version: "1.0.0"}}
version2Endpoint := portainer.Endpoint{ID: 2, GroupID: 1, version2Endpoint := portainer.Endpoint{ID: 2, GroupID: 1,
Type: portainer.AgentOnDockerEnvironment, Type: portainer.AgentOnDockerEnvironment,
Agent: struct { Agent: struct {
Version string "example:\"1.0.0\"" Version string `json:"Version,omitempty" example:"1.0.0"`
}{Version: "2.0.0"}} }{Version: "2.0.0"}}
noVersionEndpoint := portainer.Endpoint{ID: 3, GroupID: 1, noVersionEndpoint := portainer.Endpoint{ID: 3, GroupID: 1,
Type: portainer.AgentOnDockerEnvironment, Type: portainer.AgentOnDockerEnvironment,

View File

@ -2,15 +2,13 @@ package helm
import ( import (
"bytes" "bytes"
"encoding/json"
"io" "io"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"testing" "testing"
"github.com/portainer/portainer/api/datastore"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/datastore"
"github.com/portainer/portainer/api/exec/exectest" "github.com/portainer/portainer/api/exec/exectest"
"github.com/portainer/portainer/api/http/security" "github.com/portainer/portainer/api/http/security"
helper "github.com/portainer/portainer/api/internal/testhelpers" helper "github.com/portainer/portainer/api/internal/testhelpers"
@ -19,6 +17,8 @@ import (
"github.com/portainer/portainer/pkg/libhelm/binary/test" "github.com/portainer/portainer/pkg/libhelm/binary/test"
"github.com/portainer/portainer/pkg/libhelm/options" "github.com/portainer/portainer/pkg/libhelm/options"
"github.com/portainer/portainer/pkg/libhelm/release" "github.com/portainer/portainer/pkg/libhelm/release"
"github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -1,7 +1,6 @@
package helm package helm
import ( import (
"encoding/json"
"io" "io"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
@ -11,14 +10,15 @@ import (
"github.com/portainer/portainer/api/datastore" "github.com/portainer/portainer/api/datastore"
"github.com/portainer/portainer/api/exec/exectest" "github.com/portainer/portainer/api/exec/exectest"
"github.com/portainer/portainer/api/http/security" "github.com/portainer/portainer/api/http/security"
helper "github.com/portainer/portainer/api/internal/testhelpers"
"github.com/portainer/portainer/api/jwt" "github.com/portainer/portainer/api/jwt"
"github.com/portainer/portainer/api/kubernetes" "github.com/portainer/portainer/api/kubernetes"
"github.com/portainer/portainer/pkg/libhelm/binary/test" "github.com/portainer/portainer/pkg/libhelm/binary/test"
"github.com/portainer/portainer/pkg/libhelm/options" "github.com/portainer/portainer/pkg/libhelm/options"
"github.com/portainer/portainer/pkg/libhelm/release" "github.com/portainer/portainer/pkg/libhelm/release"
"github.com/stretchr/testify/assert"
helper "github.com/portainer/portainer/api/internal/testhelpers" "github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert"
) )
func Test_helmList(t *testing.T) { func Test_helmList(t *testing.T) {

View File

@ -2,7 +2,6 @@ package openamt
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -20,6 +19,7 @@ import (
"github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/network"
"github.com/docker/docker/client" "github.com/docker/docker/client"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/segmentio/encoding/json"
) )
type HostInfo struct { type HostInfo struct {

View File

@ -1,7 +1,6 @@
package motd package motd
import ( import (
"encoding/json"
"net/http" "net/http"
"strings" "strings"
@ -9,6 +8,8 @@ import (
"github.com/portainer/portainer/api/http/client" "github.com/portainer/portainer/api/http/client"
"github.com/portainer/portainer/pkg/libcrypto" "github.com/portainer/portainer/pkg/libcrypto"
"github.com/portainer/portainer/pkg/libhttp/response" "github.com/portainer/portainer/pkg/libhttp/response"
"github.com/segmentio/encoding/json"
) )
type motdResponse struct { type motdResponse struct {

View File

@ -1,7 +1,6 @@
package system package system
import ( import (
"encoding/json"
"net/http" "net/http"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
@ -11,6 +10,7 @@ import (
"github.com/coreos/go-semver/semver" "github.com/coreos/go-semver/semver"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/segmentio/encoding/json"
) )
type versionResponse struct { type versionResponse struct {

View File

@ -1,7 +1,6 @@
package system package system
import ( import (
"encoding/json"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -15,6 +14,8 @@ import (
"github.com/portainer/portainer/api/demo" "github.com/portainer/portainer/api/demo"
"github.com/portainer/portainer/api/http/security" "github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/jwt" "github.com/portainer/portainer/api/jwt"
"github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -1,7 +1,6 @@
package teams package teams
import ( import (
"encoding/json"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -15,6 +14,8 @@ import (
"github.com/portainer/portainer/api/http/security" "github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/internal/authorization" "github.com/portainer/portainer/api/internal/authorization"
"github.com/portainer/portainer/api/jwt" "github.com/portainer/portainer/api/jwt"
"github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -1,7 +1,6 @@
package templates package templates
import ( import (
"encoding/json"
"errors" "errors"
"net/http" "net/http"
@ -12,6 +11,7 @@ import (
"github.com/asaskevich/govalidator" "github.com/asaskevich/govalidator"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/segmentio/encoding/json"
) )
type filePayload struct { type filePayload struct {

View File

@ -2,7 +2,6 @@ package users
import ( import (
"bytes" "bytes"
"encoding/json"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -15,6 +14,8 @@ import (
"github.com/portainer/portainer/api/datastore" "github.com/portainer/portainer/api/datastore"
"github.com/portainer/portainer/api/http/security" "github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/jwt" "github.com/portainer/portainer/api/jwt"
"github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )
@ -105,7 +106,7 @@ func Test_userCreateAccessToken(t *testing.T) {
body, err := io.ReadAll(rr.Body) body, err := io.ReadAll(rr.Body)
is.NoError(err, "ReadAll should not return error") is.NoError(err, "ReadAll should not return error")
is.Equal("{\"message\":\"Auth not supported\",\"details\":\"JWT Authentication required\"}\n", string(body)) is.Equal(`{"message":"Auth not supported","details":"JWT Authentication required"}`, string(body))
}) })
} }

View File

@ -1,7 +1,6 @@
package users package users
import ( import (
"encoding/json"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -14,6 +13,8 @@ import (
"github.com/portainer/portainer/api/datastore" "github.com/portainer/portainer/api/datastore"
"github.com/portainer/portainer/api/http/security" "github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/jwt" "github.com/portainer/portainer/api/jwt"
"github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -1,7 +1,6 @@
package users package users
import ( import (
"encoding/json"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -17,6 +16,8 @@ import (
"github.com/portainer/portainer/api/http/security" "github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/internal/authorization" "github.com/portainer/portainer/api/internal/authorization"
"github.com/portainer/portainer/api/jwt" "github.com/portainer/portainer/api/jwt"
"github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -2,20 +2,20 @@ package websocket
import ( import (
"bytes" "bytes"
"encoding/json"
"github.com/portainer/portainer/api/http/security"
"github.com/rs/zerolog/log"
"net" "net"
"net/http" "net/http"
"net/http/httputil" "net/http/httputil"
"time" "time"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/http/security"
httperror "github.com/portainer/portainer/pkg/libhttp/error" httperror "github.com/portainer/portainer/pkg/libhttp/error"
"github.com/portainer/portainer/pkg/libhttp/request" "github.com/portainer/portainer/pkg/libhttp/request"
"github.com/asaskevich/govalidator" "github.com/asaskevich/govalidator"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/rs/zerolog/log"
"github.com/segmentio/encoding/json"
) )
type execStartOperationPayload struct { type execStartOperationPayload struct {

View File

@ -13,9 +13,7 @@ import (
"github.com/gorilla/mux" "github.com/gorilla/mux"
) )
const ( const contextEndpoint = "endpoint"
contextEndpoint = "endpoint"
)
func WithEndpoint(endpointService dataservices.EndpointService, endpointIDParam string) mux.MiddlewareFunc { func WithEndpoint(endpointService dataservices.EndpointService, endpointIDParam string) mux.MiddlewareFunc {
return func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler {

View File

@ -2,7 +2,6 @@ package docker
import ( import (
"bytes" "bytes"
"encoding/json"
"errors" "errors"
"io" "io"
"mime" "mime"
@ -11,6 +10,7 @@ import (
"github.com/portainer/portainer/api/archive" "github.com/portainer/portainer/api/archive"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/segmentio/encoding/json"
) )
const OneMegabyte = 1024768 const OneMegabyte = 1024768

View File

@ -3,22 +3,21 @@ package docker
import ( import (
"bytes" "bytes"
"context" "context"
"encoding/json"
"errors" "errors"
"io" "io"
"net/http" "net/http"
"strings" "strings"
"github.com/docker/docker/client"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/http/proxy/factory/utils" "github.com/portainer/portainer/api/http/proxy/factory/utils"
"github.com/portainer/portainer/api/http/security" "github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/internal/authorization" "github.com/portainer/portainer/api/internal/authorization"
"github.com/docker/docker/client"
"github.com/segmentio/encoding/json"
) )
const ( const containerObjectIdentifier = "Id"
containerObjectIdentifier = "Id"
)
func getInheritedResourceControlFromContainerLabels(dockerClient *client.Client, endpointID portainer.EndpointID, containerID string, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) { func getInheritedResourceControlFromContainerLabels(dockerClient *client.Client, endpointID portainer.EndpointID, containerID string, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) {
container, err := dockerClient.ContainerInspect(context.Background(), containerID) container, err := dockerClient.ContainerInspect(context.Background(), containerID)

View File

@ -3,22 +3,20 @@ package docker
import ( import (
"bytes" "bytes"
"context" "context"
"encoding/json"
"errors" "errors"
"io" "io"
"net/http" "net/http"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/http/proxy/factory/utils" "github.com/portainer/portainer/api/http/proxy/factory/utils"
"github.com/portainer/portainer/api/internal/authorization" "github.com/portainer/portainer/api/internal/authorization"
"github.com/docker/docker/api/types"
"github.com/docker/docker/client"
"github.com/segmentio/encoding/json"
) )
const ( const serviceObjectIdentifier = "ID"
serviceObjectIdentifier = "ID"
)
func getInheritedResourceControlFromServiceLabels(dockerClient *client.Client, endpointID portainer.EndpointID, serviceID string, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) { func getInheritedResourceControlFromServiceLabels(dockerClient *client.Client, endpointID portainer.EndpointID, serviceID string, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) {
service, _, err := dockerClient.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{}) service, _, err := dockerClient.ServiceInspectWithRaw(context.Background(), serviceID, types.ServiceInspectOptions{})

View File

@ -3,7 +3,6 @@ package docker
import ( import (
"bytes" "bytes"
"encoding/base64" "encoding/base64"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io" "io"
@ -15,12 +14,13 @@ import (
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/dataservices" "github.com/portainer/portainer/api/dataservices"
dockerclient "github.com/portainer/portainer/api/docker/client"
"github.com/portainer/portainer/api/http/proxy/factory/utils" "github.com/portainer/portainer/api/http/proxy/factory/utils"
"github.com/portainer/portainer/api/http/security" "github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/internal/authorization" "github.com/portainer/portainer/api/internal/authorization"
dockerclient "github.com/portainer/portainer/api/docker/client"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/segmentio/encoding/json"
) )
var apiVersionRe = regexp.MustCompile(`(/v[0-9]\.[0-9]*)?`) var apiVersionRe = regexp.MustCompile(`(/v[0-9]\.[0-9]*)?`)

View File

@ -2,7 +2,6 @@ package kubernetes
import ( import (
"bytes" "bytes"
"encoding/json"
"fmt" "fmt"
"io" "io"
"net/http" "net/http"
@ -18,6 +17,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/segmentio/encoding/json"
) )
type baseTransport struct { type baseTransport struct {

View File

@ -2,12 +2,12 @@ package utils
import ( import (
"compress/gzip" "compress/gzip"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io" "io"
"mime" "mime"
"github.com/segmentio/encoding/json"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )

View File

@ -2,18 +2,17 @@ package registryutils
import ( import (
"encoding/base64" "encoding/base64"
"encoding/json"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/segmentio/encoding/json"
) )
type ( type authHeader struct {
authHeader struct { Username string `json:"username"`
Username string `json:"username"` Password string `json:"password"`
Password string `json:"password"` ServerAddress string `json:"serveraddress"`
ServerAddress string `json:"serveraddress"` }
}
)
// GetRegistryAuthHeader generate the X-Registry-Auth header from registry // GetRegistryAuthHeader generate the X-Registry-Auth header from registry
func GetRegistryAuthHeader(registry *portainer.Registry) (header string, err error) { func GetRegistryAuthHeader(registry *portainer.Registry) (header string, err error) {

View File

@ -2,10 +2,11 @@ package cli
import ( import (
"context" "context"
"encoding/json"
portainer "github.com/portainer/portainer/api"
"github.com/pkg/errors" "github.com/pkg/errors"
portainer "github.com/portainer/portainer/api" "github.com/segmentio/encoding/json"
k8serrors "k8s.io/apimachinery/pkg/api/errors" k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
) )

View File

@ -2,9 +2,10 @@ package cli
import ( import (
"context" "context"
"encoding/json"
models "github.com/portainer/portainer/api/http/models/kubernetes" models "github.com/portainer/portainer/api/http/models/kubernetes"
"github.com/segmentio/encoding/json"
) )
func (kcl *KubeClient) GetMetrics() (models.K8sMetrics, error) { func (kcl *KubeClient) GetMetrics() (models.K8sMetrics, error) {

View File

@ -2,13 +2,14 @@ package cli
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"strconv" "strconv"
"github.com/pkg/errors"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/internal/registryutils" "github.com/portainer/portainer/api/internal/registryutils"
"github.com/pkg/errors"
"github.com/segmentio/encoding/json"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors" k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

View File

@ -2,7 +2,6 @@ package oauth
import ( import (
"context" "context"
"encoding/json"
"io" "io"
"mime" "mime"
"net/http" "net/http"
@ -14,6 +13,7 @@ import (
"github.com/golang-jwt/jwt/v4" "github.com/golang-jwt/jwt/v4"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/segmentio/encoding/json"
"golang.org/x/oauth2" "golang.org/x/oauth2"
) )

View File

@ -1,19 +1,18 @@
package oauthtest package oauthtest
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"strings" "strings"
"github.com/gorilla/mux"
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
"github.com/gorilla/mux"
"github.com/segmentio/encoding/json"
) )
const ( const AccessToken = "test-token"
AccessToken = "test-token"
)
// OAuthRoutes is an OAuth 2.0 compliant handler // OAuthRoutes is an OAuth 2.0 compliant handler
func OAuthRoutes(code string, config *portainer.OAuthSettings) http.Handler { func OAuthRoutes(code string, config *portainer.OAuthSettings) http.Handler {

View File

@ -171,7 +171,7 @@ type (
// User identifier who created this template // User identifier who created this template
CreatedByUserID UserID `json:"CreatedByUserId" example:"3"` CreatedByUserID UserID `json:"CreatedByUserId" example:"3"`
// A note that will be displayed in the UI. Supports HTML content // A note that will be displayed in the UI. Supports HTML content
Note string `json:"Note" example:"This is my <b>custom</b> template"` Note string `json:"Note,omitempty" example:"This is my <b>custom</b> template"`
// Platform associated to the template. // Platform associated to the template.
// Valid values are: 1 - 'linux', 2 - 'windows' // Valid values are: 1 - 'linux', 2 - 'windows'
Platform CustomTemplatePlatform `json:"Platform" example:"1" enums:"1,2"` Platform CustomTemplatePlatform `json:"Platform" example:"1" enums:"1,2"`
@ -182,11 +182,11 @@ type (
// * 2 - compose // * 2 - compose
// * 3 - kubernetes // * 3 - kubernetes
Type StackType `json:"Type" example:"1" enums:"1,2,3"` Type StackType `json:"Type" example:"1" enums:"1,2,3"`
ResourceControl *ResourceControl `json:"ResourceControl"` ResourceControl *ResourceControl `json:"ResourceControl,omitempty"`
Variables []CustomTemplateVariableDefinition Variables []CustomTemplateVariableDefinition
GitConfig *gittypes.RepoConfig `json:"GitConfig"` GitConfig *gittypes.RepoConfig `json:"GitConfig,omitempty"`
// IsComposeFormat indicates if the Kubernetes template is created from a Docker Compose file // IsComposeFormat indicates if the Kubernetes template is created from a Docker Compose file
IsComposeFormat bool `example:"false"` IsComposeFormat bool `json:"IsComposeFormat,omitempty" example:"false"`
} }
// CustomTemplateID represents a custom template identifier // CustomTemplateID represents a custom template identifier
@ -249,10 +249,10 @@ type (
// EdgeGroup Identifier // EdgeGroup Identifier
ID EdgeGroupID `json:"Id" example:"1"` ID EdgeGroupID `json:"Id" example:"1"`
Name string `json:"Name"` Name string `json:"Name"`
Dynamic bool `json:"Dynamic"` Dynamic bool `json:"Dynamic,omitempty"`
TagIDs []TagID `json:"TagIds"` TagIDs []TagID `json:"TagIds"`
Endpoints []EndpointID `json:"Endpoints"` Endpoints []EndpointID `json:"Endpoints"`
PartialMatch bool `json:"PartialMatch"` PartialMatch bool `json:"PartialMatch,omitempty"`
} }
// EdgeGroupID represents an Edge group identifier // EdgeGroupID represents an Edge group identifier
@ -268,7 +268,7 @@ type (
EdgeGroups []EdgeGroupID `json:"EdgeGroups"` EdgeGroups []EdgeGroupID `json:"EdgeGroups"`
Name string `json:"Name"` Name string `json:"Name"`
ScriptPath string `json:"ScriptPath"` ScriptPath string `json:"ScriptPath"`
Recurring bool `json:"Recurring"` Recurring bool `json:"Recurring,omitempty"`
Version int `json:"Version"` Version int `json:"Version"`
// Field used for log collection of Endpoints belonging to EdgeGroups // Field used for log collection of Endpoints belonging to EdgeGroups
@ -278,7 +278,7 @@ type (
// EdgeJobEndpointMeta represents a meta data object for an Edge job and Environment(Endpoint) relation // EdgeJobEndpointMeta represents a meta data object for an Edge job and Environment(Endpoint) relation
EdgeJobEndpointMeta struct { EdgeJobEndpointMeta struct {
LogsStatus EdgeJobLogsStatus LogsStatus EdgeJobLogsStatus
CollectLogs bool CollectLogs bool `json:"CollectLogs,omitempty"`
} }
// EdgeJobID represents an Edge job identifier // EdgeJobID represents an Edge job identifier
@ -325,10 +325,10 @@ type (
ManifestPath string ManifestPath string
DeploymentType EdgeStackDeploymentType DeploymentType EdgeStackDeploymentType
// Uses the manifest's namespaces instead of the default one // Uses the manifest's namespaces instead of the default one
UseManifestNamespaces bool UseManifestNamespaces bool `json:"UseManifestNamespaces,omitempty"`
// Deprecated // Deprecated
Prune bool `json:"Prune"` Prune bool `json:"Prune,omitempty"`
} }
EdgeStackDeploymentType int EdgeStackDeploymentType int
@ -392,11 +392,11 @@ type (
// Environment(Endpoint) environment(endpoint) type. 1 for a Docker environment(endpoint), 2 for an agent on Docker environment(endpoint) or 3 for an Azure environment(endpoint). // Environment(Endpoint) environment(endpoint) type. 1 for a Docker environment(endpoint), 2 for an agent on Docker environment(endpoint) or 3 for an Azure environment(endpoint).
Type EndpointType `json:"Type" example:"1"` Type EndpointType `json:"Type" example:"1"`
// URL or IP address of the Docker host associated to this environment(endpoint) // URL or IP address of the Docker host associated to this environment(endpoint)
URL string `json:"URL" example:"docker.mydomain.tld:2375"` URL string `json:"URL,omitempty" example:"docker.mydomain.tld:2375"`
// Environment(Endpoint) group identifier // Environment(Endpoint) group identifier
GroupID EndpointGroupID `json:"GroupId" example:"1"` GroupID EndpointGroupID `json:"GroupId" example:"1"`
// URL or IP address where exposed containers will be reachable // URL or IP address where exposed containers will be reachable
PublicURL string `json:"PublicURL" example:"docker.mydomain.tld:2375"` PublicURL string `json:"PublicURL,omitempty" example:"docker.mydomain.tld:2375"`
Gpus []Pair `json:"Gpus"` Gpus []Pair `json:"Gpus"`
TLSConfig TLSConfiguration `json:"TLSConfig"` TLSConfig TLSConfiguration `json:"TLSConfig"`
AzureCredentials AzureCredentials `json:"AzureCredentials,omitempty"` AzureCredentials AzureCredentials `json:"AzureCredentials,omitempty"`
@ -413,7 +413,7 @@ type (
// The identifier of the edge agent associated with this environment(endpoint) // The identifier of the edge agent associated with this environment(endpoint)
EdgeID string `json:"EdgeID,omitempty"` EdgeID string `json:"EdgeID,omitempty"`
// The key which is used to map the agent to Portainer // The key which is used to map the agent to Portainer
EdgeKey string `json:"EdgeKey"` EdgeKey string `json:"EdgeKey,omitempty"`
// The check in interval for edge agent (in seconds) // The check in interval for edge agent (in seconds)
EdgeCheckinInterval int `json:"EdgeCheckinInterval" example:"5"` EdgeCheckinInterval int `json:"EdgeCheckinInterval" example:"5"`
// Associated Kubernetes data // Associated Kubernetes data
@ -425,14 +425,14 @@ type (
// The identifier of the AMT Device associated with this environment(endpoint) // The identifier of the AMT Device associated with this environment(endpoint)
AMTDeviceGUID string `json:"AMTDeviceGUID,omitempty" example:"4c4c4544-004b-3910-8037-b6c04f504633"` AMTDeviceGUID string `json:"AMTDeviceGUID,omitempty" example:"4c4c4544-004b-3910-8037-b6c04f504633"`
// LastCheckInDate mark last check-in date on checkin // LastCheckInDate mark last check-in date on checkin
LastCheckInDate int64 LastCheckInDate int64 `json:"LastCheckInDate,omitempty"`
// QueryDate of each query with the endpoints list // QueryDate of each query with the endpoints list
QueryDate int64 QueryDate int64 `json:"QueryDate,omitempty"`
// Heartbeat indicates the heartbeat status of an edge environment // Heartbeat indicates the heartbeat status of an edge environment
Heartbeat bool `json:"Heartbeat" example:"true"` Heartbeat bool `json:"Heartbeat,omitempty" example:"true"`
// Whether the device has been trusted or not by the user // Whether the device has been trusted or not by the user
UserTrusted bool UserTrusted bool `json:"UserTrusted,omitempty"`
// Whether we need to run any "post init migrations". // Whether we need to run any "post init migrations".
PostInitMigrations EndpointPostInitMigrations `json:"PostInitMigrations"` PostInitMigrations EndpointPostInitMigrations `json:"PostInitMigrations"`
@ -440,10 +440,10 @@ type (
Edge EnvironmentEdgeSettings Edge EnvironmentEdgeSettings
Agent struct { Agent struct {
Version string `example:"1.0.0"` Version string `json:"Version,omitempty" example:"1.0.0"`
} }
EnableGPUManagement bool `json:"EnableGPUManagement"` EnableGPUManagement bool `json:"EnableGPUManagement,omitempty"`
// Deprecated fields // Deprecated fields
// Deprecated in DBVersion == 4 // Deprecated in DBVersion == 4
@ -460,18 +460,18 @@ type (
Tags []string `json:"Tags"` Tags []string `json:"Tags"`
// Deprecated v2.18 // Deprecated v2.18
IsEdgeDevice bool IsEdgeDevice bool `json:"IsEdgeDevice,omitempty"`
} }
EnvironmentEdgeSettings struct { EnvironmentEdgeSettings struct {
// Whether the device has been started in edge async mode // Whether the device has been started in edge async mode
AsyncMode bool AsyncMode bool `json:"AsyncMode,omitempty"`
// The ping interval for edge agent - used in edge async mode [seconds] // The ping interval for edge agent - used in edge async mode [seconds]
PingInterval int `json:"PingInterval" example:"60"` PingInterval int `json:"PingInterval,omitempty" example:"60"`
// The snapshot interval for edge agent - used in edge async mode [seconds] // The snapshot interval for edge agent - used in edge async mode [seconds]
SnapshotInterval int `json:"SnapshotInterval" example:"60"` SnapshotInterval int `json:"SnapshotInterval,omitempty" example:"60"`
// The command list interval for edge agent - used in edge async mode [seconds] // The command list interval for edge agent - used in edge async mode [seconds]
CommandInterval int `json:"CommandInterval" example:"60"` CommandInterval int `json:"CommandInterval,omitempty" example:"60"`
} }
// EndpointAuthorizations represents the authorizations associated to a set of environments(endpoints) // EndpointAuthorizations represents the authorizations associated to a set of environments(endpoints)
@ -486,7 +486,7 @@ type (
// Environment(Endpoint) group name // Environment(Endpoint) group name
Name string `json:"Name" example:"my-environment-group"` Name string `json:"Name" example:"my-environment-group"`
// Description associated to the environment(endpoint) group // Description associated to the environment(endpoint) group
Description string `json:"Description" example:"Environment(Endpoint) group description"` Description string `json:"Description,omitempty" example:"Environment(Endpoint) group description"`
UserAccessPolicies UserAccessPolicies `json:"UserAccessPolicies"` UserAccessPolicies UserAccessPolicies `json:"UserAccessPolicies"`
TeamAccessPolicies TeamAccessPolicies `json:"TeamAccessPolicies"` TeamAccessPolicies TeamAccessPolicies `json:"TeamAccessPolicies"`
// List of tags associated to this environment(endpoint) group // List of tags associated to this environment(endpoint) group
@ -500,7 +500,7 @@ type (
AuthorizedTeams []TeamID `json:"AuthorizedTeams"` AuthorizedTeams []TeamID `json:"AuthorizedTeams"`
// Deprecated in DBVersion == 22 // Deprecated in DBVersion == 22
Tags []string `json:"Tags"` Tags []string `json:"Tags,omitempty"`
} }
// EndpointGroupID represents an environment(endpoint) group identifier // EndpointGroupID represents an environment(endpoint) group identifier
@ -519,23 +519,23 @@ type (
// EndpointSecuritySettings represents settings for an environment(endpoint) // EndpointSecuritySettings represents settings for an environment(endpoint)
EndpointSecuritySettings struct { EndpointSecuritySettings struct {
// Whether non-administrator should be able to use bind mounts when creating containers // Whether non-administrator should be able to use bind mounts when creating containers
AllowBindMountsForRegularUsers bool `json:"allowBindMountsForRegularUsers" example:"false"` AllowBindMountsForRegularUsers bool `json:"allowBindMountsForRegularUsers,omitempty" example:"false"`
// Whether non-administrator should be able to use privileged mode when creating containers // Whether non-administrator should be able to use privileged mode when creating containers
AllowPrivilegedModeForRegularUsers bool `json:"allowPrivilegedModeForRegularUsers" example:"false"` AllowPrivilegedModeForRegularUsers bool `json:"allowPrivilegedModeForRegularUsers,omitempty" example:"false"`
// Whether non-administrator should be able to browse volumes // Whether non-administrator should be able to browse volumes
AllowVolumeBrowserForRegularUsers bool `json:"allowVolumeBrowserForRegularUsers" example:"true"` AllowVolumeBrowserForRegularUsers bool `json:"allowVolumeBrowserForRegularUsers,omitempty" example:"true"`
// Whether non-administrator should be able to use the host pid // Whether non-administrator should be able to use the host pid
AllowHostNamespaceForRegularUsers bool `json:"allowHostNamespaceForRegularUsers" example:"true"` AllowHostNamespaceForRegularUsers bool `json:"allowHostNamespaceForRegularUsers,omitempty" example:"true"`
// Whether non-administrator should be able to use device mapping // Whether non-administrator should be able to use device mapping
AllowDeviceMappingForRegularUsers bool `json:"allowDeviceMappingForRegularUsers" example:"true"` AllowDeviceMappingForRegularUsers bool `json:"allowDeviceMappingForRegularUsers,omitempty" example:"true"`
// Whether non-administrator should be able to manage stacks // Whether non-administrator should be able to manage stacks
AllowStackManagementForRegularUsers bool `json:"allowStackManagementForRegularUsers" example:"true"` AllowStackManagementForRegularUsers bool `json:"allowStackManagementForRegularUsers,omitempty" example:"true"`
// Whether non-administrator should be able to use container capabilities // Whether non-administrator should be able to use container capabilities
AllowContainerCapabilitiesForRegularUsers bool `json:"allowContainerCapabilitiesForRegularUsers" example:"true"` AllowContainerCapabilitiesForRegularUsers bool `json:"allowContainerCapabilitiesForRegularUsers,omitempty" example:"true"`
// Whether non-administrator should be able to use sysctl settings // Whether non-administrator should be able to use sysctl settings
AllowSysctlSettingForRegularUsers bool `json:"allowSysctlSettingForRegularUsers" example:"true"` AllowSysctlSettingForRegularUsers bool `json:"allowSysctlSettingForRegularUsers,omitempty" example:"true"`
// Whether host management features are enabled // Whether host management features are enabled
EnableHostManagementFeatures bool `json:"enableHostManagementFeatures" example:"true"` EnableHostManagementFeatures bool `json:"enableHostManagementFeatures,omitempty" example:"true"`
} }
// EndpointType represents the type of an environment(endpoint) // EndpointType represents the type of an environment(endpoint)
@ -549,15 +549,15 @@ type (
// EndpointPostInitMigrations // EndpointPostInitMigrations
EndpointPostInitMigrations struct { EndpointPostInitMigrations struct {
MigrateIngresses bool `json:"MigrateIngresses"` MigrateIngresses bool `json:"MigrateIngresses,omitempty"`
MigrateGPUs bool `json:"MigrateGPUs"` MigrateGPUs bool `json:"MigrateGPUs,omitempty"`
} }
// Extension represents a deprecated Portainer extension // Extension represents a deprecated Portainer extension
Extension struct { Extension struct {
// Extension Identifier // Extension Identifier
ID ExtensionID `json:"Id" example:"1"` ID ExtensionID `json:"Id" example:"1"`
Enabled bool `json:"Enabled"` Enabled bool `json:"Enabled,omitempty"`
Name string `json:"Name,omitempty"` Name string `json:"Name,omitempty"`
ShortDescription string `json:"ShortDescription,omitempty"` ShortDescription string `json:"ShortDescription,omitempty"`
Description string `json:"Description,omitempty"` Description string `json:"Description,omitempty"`
@ -598,7 +598,7 @@ type (
// QuayRegistryData represents data required for Quay registry to work // QuayRegistryData represents data required for Quay registry to work
QuayRegistryData struct { QuayRegistryData struct {
UseOrganisation bool `json:"UseOrganisation"` UseOrganisation bool `json:"UseOrganisation,omitempty"`
OrganisationName string `json:"OrganisationName"` OrganisationName string `json:"OrganisationName"`
} }
@ -611,13 +611,13 @@ type (
JobType int JobType int
K8sNamespaceInfo struct { K8sNamespaceInfo struct {
IsSystem bool `json:"IsSystem"` IsSystem bool `json:"IsSystem,omitempty"`
IsDefault bool `json:"IsDefault"` IsDefault bool `json:"IsDefault,omitempty"`
} }
K8sNodeLimits struct { K8sNodeLimits struct {
CPU int64 `json:"CPU"` CPU int64 `json:"CPU,omitempty"`
Memory int64 `json:"Memory"` Memory int64 `json:"Memory,omitempty"`
} }
K8sNodesLimits map[string]*K8sNodeLimits K8sNodesLimits map[string]*K8sNodeLimits
@ -637,9 +637,9 @@ type (
// KubernetesFlags are used to detect if we need to run initial cluster // KubernetesFlags are used to detect if we need to run initial cluster
// detection again. // detection again.
KubernetesFlags struct { KubernetesFlags struct {
IsServerMetricsDetected bool `json:"IsServerMetricsDetected"` IsServerMetricsDetected bool `json:"IsServerMetricsDetected,omitempty"`
IsServerIngressClassDetected bool `json:"IsServerIngressClassDetected"` IsServerIngressClassDetected bool `json:"IsServerIngressClassDetected,omitempty"`
IsServerStorageDetected bool `json:"IsServerStorageDetected"` IsServerStorageDetected bool `json:"IsServerStorageDetected,omitempty"`
} }
// KubernetesSnapshot represents a snapshot of a specific Kubernetes environment(endpoint) at a specific time // KubernetesSnapshot represents a snapshot of a specific Kubernetes environment(endpoint) at a specific time
@ -653,15 +653,15 @@ type (
// KubernetesConfiguration represents the configuration of a Kubernetes environment(endpoint) // KubernetesConfiguration represents the configuration of a Kubernetes environment(endpoint)
KubernetesConfiguration struct { KubernetesConfiguration struct {
UseLoadBalancer bool `json:"UseLoadBalancer"` UseLoadBalancer bool `json:"UseLoadBalancer,omitempty"`
UseServerMetrics bool `json:"UseServerMetrics"` UseServerMetrics bool `json:"UseServerMetrics,omitempty"`
EnableResourceOverCommit bool `json:"EnableResourceOverCommit"` EnableResourceOverCommit bool `json:"EnableResourceOverCommit,omitempty"`
ResourceOverCommitPercentage int `json:"ResourceOverCommitPercentage"` ResourceOverCommitPercentage int `json:"ResourceOverCommitPercentage,omitempty"`
StorageClasses []KubernetesStorageClassConfig `json:"StorageClasses"` StorageClasses []KubernetesStorageClassConfig `json:"StorageClasses"`
IngressClasses []KubernetesIngressClassConfig `json:"IngressClasses"` IngressClasses []KubernetesIngressClassConfig `json:"IngressClasses"`
RestrictDefaultNamespace bool `json:"RestrictDefaultNamespace"` RestrictDefaultNamespace bool `json:"RestrictDefaultNamespace,omitempty"`
IngressAvailabilityPerNamespace bool `json:"IngressAvailabilityPerNamespace"` IngressAvailabilityPerNamespace bool `json:"IngressAvailabilityPerNamespace,omitempty"`
AllowNoneIngressClass bool `json:"AllowNoneIngressClass"` AllowNoneIngressClass bool `json:"AllowNoneIngressClass,omitempty"`
} }
// KubernetesStorageClassConfig represents a Kubernetes Storage Class configuration // KubernetesStorageClassConfig represents a Kubernetes Storage Class configuration
@ -669,14 +669,14 @@ type (
Name string `json:"Name"` Name string `json:"Name"`
AccessModes []string `json:"AccessModes"` AccessModes []string `json:"AccessModes"`
Provisioner string `json:"Provisioner"` Provisioner string `json:"Provisioner"`
AllowVolumeExpansion bool `json:"AllowVolumeExpansion"` AllowVolumeExpansion bool `json:"AllowVolumeExpansion,omitempty"`
} }
// KubernetesIngressClassConfig represents a Kubernetes Ingress Class configuration // KubernetesIngressClassConfig represents a Kubernetes Ingress Class configuration
KubernetesIngressClassConfig struct { KubernetesIngressClassConfig struct {
Name string `json:"Name"` Name string `json:"Name"`
Type string `json:"Type"` Type string `json:"Type"`
GloballyBlocked bool `json:"Blocked"` GloballyBlocked bool `json:"Blocked,omitempty"`
BlockedNamespaces []string `json:"BlockedNamespaces"` BlockedNamespaces []string `json:"BlockedNamespaces"`
} }
@ -690,7 +690,7 @@ type (
// InternalAuthSettings represents settings used for the default 'internal' authentication // InternalAuthSettings represents settings used for the default 'internal' authentication
InternalAuthSettings struct { InternalAuthSettings struct {
RequiredPasswordLength int RequiredPasswordLength int `json:"RequiredPasswordLength,omitempty"`
} }
// LDAPGroupSearchSettings represents settings used to search for groups in a LDAP server // LDAPGroupSearchSettings represents settings used to search for groups in a LDAP server
@ -698,7 +698,7 @@ type (
// The distinguished name of the element from which the LDAP server will search for groups // The distinguished name of the element from which the LDAP server will search for groups
GroupBaseDN string `json:"GroupBaseDN" example:"dc=ldap,dc=domain,dc=tld"` GroupBaseDN string `json:"GroupBaseDN" example:"dc=ldap,dc=domain,dc=tld"`
// The LDAP search filter used to select group elements, optional // The LDAP search filter used to select group elements, optional
GroupFilter string `json:"GroupFilter" example:"(objectClass=account"` GroupFilter string `json:"GroupFilter,omitempty" example:"(objectClass=account"`
// LDAP attribute which denotes the group membership // LDAP attribute which denotes the group membership
GroupAttribute string `json:"GroupAttribute" example:"member"` GroupAttribute string `json:"GroupAttribute" example:"member"`
} }
@ -716,7 +716,7 @@ type (
// LDAPSettings represents the settings used to connect to a LDAP server // LDAPSettings represents the settings used to connect to a LDAP server
LDAPSettings struct { LDAPSettings struct {
// Enable this option if the server is configured for Anonymous access. When enabled, ReaderDN and Password will not be used // Enable this option if the server is configured for Anonymous access. When enabled, ReaderDN and Password will not be used
AnonymousMode bool `json:"AnonymousMode" example:"true" validate:"validate_bool"` AnonymousMode bool `json:"AnonymousMode,omitempty" example:"true" validate:"validate_bool"`
// Account that will be used to search for users // Account that will be used to search for users
ReaderDN string `json:"ReaderDN" example:"cn=readonly-account,dc=ldap,dc=domain,dc=tld" validate:"required_if=AnonymousMode false"` ReaderDN string `json:"ReaderDN" example:"cn=readonly-account,dc=ldap,dc=domain,dc=tld" validate:"required_if=AnonymousMode false"`
// Password of the account that will be used to search users // Password of the account that will be used to search users
@ -725,11 +725,11 @@ type (
URL string `json:"URL" example:"myldap.domain.tld:389" validate:"hostname_port"` URL string `json:"URL" example:"myldap.domain.tld:389" validate:"hostname_port"`
TLSConfig TLSConfiguration `json:"TLSConfig"` TLSConfig TLSConfiguration `json:"TLSConfig"`
// Whether LDAP connection should use StartTLS // Whether LDAP connection should use StartTLS
StartTLS bool `json:"StartTLS" example:"true"` StartTLS bool `json:"StartTLS,omitempty" example:"true"`
SearchSettings []LDAPSearchSettings `json:"SearchSettings"` SearchSettings []LDAPSearchSettings `json:"SearchSettings"`
GroupSearchSettings []LDAPGroupSearchSettings `json:"GroupSearchSettings"` GroupSearchSettings []LDAPGroupSearchSettings `json:"GroupSearchSettings"`
// Automatically provision users and assign them to matching LDAP group names // Automatically provision users and assign them to matching LDAP group names
AutoCreateUsers bool `json:"AutoCreateUsers" example:"true"` AutoCreateUsers bool `json:"AutoCreateUsers,omitempty" example:"true"`
} }
// LDAPUser represents a LDAP user // LDAPUser represents a LDAP user
@ -769,7 +769,7 @@ type (
// Pair defines a key/value string pair // Pair defines a key/value string pair
Pair struct { Pair struct {
Name string `json:"name" example:"name"` Name string `json:"name" example:"name"`
Value string `json:"value" example:"value"` Value string `json:"value,omitempty" example:"value"`
} }
// Registry represents a Docker registry with all the info required // Registry represents a Docker registry with all the info required
@ -782,13 +782,13 @@ type (
// Registry Name // Registry Name
Name string `json:"Name" example:"my-registry"` Name string `json:"Name" example:"my-registry"`
// URL or IP address of the Docker registry // URL or IP address of the Docker registry
URL string `json:"URL" example:"registry.mydomain.tld:2375"` URL string `json:"URL,omitempty" example:"registry.mydomain.tld:2375"`
// Base URL, introduced for ProGet registry // Base URL, introduced for ProGet registry
BaseURL string `json:"BaseURL" example:"registry.mydomain.tld:2375"` BaseURL string `json:"BaseURL,omitempty" example:"registry.mydomain.tld:2375"`
// Is authentication against this registry enabled // Is authentication against this registry enabled
Authentication bool `json:"Authentication" example:"true"` Authentication bool `json:"Authentication,omitempty" example:"true"`
// Username or AccessKeyID used to authenticate against this registry // Username or AccessKeyID used to authenticate against this registry
Username string `json:"Username" example:"registry user"` Username string `json:"Username,omitempty" example:"registry user"`
// Password or SecretAccessKey used to authenticate against this registry // Password or SecretAccessKey used to authenticate against this registry
Password string `json:"Password,omitempty" example:"registry_password"` Password string `json:"Password,omitempty" example:"registry_password"`
ManagementConfiguration *RegistryManagementConfiguration `json:"ManagementConfiguration"` ManagementConfiguration *RegistryManagementConfiguration `json:"ManagementConfiguration"`
@ -828,9 +828,9 @@ type (
// the registry API via the registry management extension. // the registry API via the registry management extension.
RegistryManagementConfiguration struct { RegistryManagementConfiguration struct {
Type RegistryType `json:"Type"` Type RegistryType `json:"Type"`
Authentication bool `json:"Authentication"` Authentication bool `json:"Authentication,omitempty"`
Username string `json:"Username"` Username string `json:"Username,omitempty"`
Password string `json:"Password"` Password string `json:"Password,omitempty"`
TLSConfig TLSConfiguration `json:"TLSConfig"` TLSConfig TLSConfiguration `json:"TLSConfig"`
Ecr EcrData `json:"Ecr"` Ecr EcrData `json:"Ecr"`
AccessToken string `json:"AccessToken,omitempty"` AccessToken string `json:"AccessToken,omitempty"`
@ -860,8 +860,8 @@ type (
// Permit access to the associated resource to any user // Permit access to the associated resource to any user
Public bool `json:"Public" example:"true"` Public bool `json:"Public" example:"true"`
// Permit access to resource only to admins // Permit access to resource only to admins
AdministratorsOnly bool `json:"AdministratorsOnly" example:"true"` AdministratorsOnly bool `json:"AdministratorsOnly,omitempty" example:"true"`
System bool `json:"System"` System bool `json:"System,omitempty"`
// Deprecated fields // Deprecated fields
// Deprecated in DBVersion == 2 // Deprecated in DBVersion == 2
@ -883,10 +883,10 @@ type (
// Role name // Role name
Name string `json:"Name" example:"HelpDesk"` Name string `json:"Name" example:"HelpDesk"`
// Role description // Role description
Description string `json:"Description" example:"Read-only access of all resources in an environment(endpoint)"` Description string `json:"Description,omitempty" example:"Read-only access of all resources in an environment(endpoint)"`
// Authorizations associated to a role // Authorizations associated to a role
Authorizations Authorizations `json:"Authorizations"` Authorizations Authorizations `json:"Authorizations"`
Priority int `json:"Priority"` Priority int `json:"Priority,omitempty"`
} }
// RoleID represents a role identifier // RoleID represents a role identifier
@ -899,7 +899,7 @@ type (
APIKey struct { APIKey struct {
ID APIKeyID `json:"id" example:"1"` ID APIKeyID `json:"id" example:"1"`
UserID UserID `json:"userId" example:"1"` UserID UserID `json:"userId" example:"1"`
Description string `json:"description" example:"portainer-api-key"` Description string `json:"description,omitempty" example:"portainer-api-key"`
Prefix string `json:"prefix"` // API key identifier (7 char prefix) Prefix string `json:"prefix"` // API key identifier (7 char prefix)
DateCreated int64 `json:"dateCreated"` // Unix timestamp (UTC) when the API key was created DateCreated int64 `json:"dateCreated"` // Unix timestamp (UTC) when the API key was created
LastUsed int64 `json:"lastUsed"` // Unix timestamp (UTC) when the API key was last used LastUsed int64 `json:"lastUsed"` // Unix timestamp (UTC) when the API key was last used
@ -916,10 +916,10 @@ type (
ID ScheduleID `json:"Id" example:"1"` ID ScheduleID `json:"Id" example:"1"`
Name string Name string
CronExpression string CronExpression string
Recurring bool Recurring bool `json:"Recurring,omitempty"`
Created int64 Created int64
JobType JobType JobType JobType
EdgeSchedule *EdgeSchedule EdgeSchedule *EdgeSchedule `json:"EdgeSchedule,omitempty"`
} }
// ScheduleID represents a schedule identifier. // ScheduleID represents a schedule identifier.
@ -931,18 +931,18 @@ type (
Endpoints []EndpointID Endpoints []EndpointID
Image string Image string
ScriptPath string ScriptPath string
RetryCount int RetryCount int `json:"RetryCount,omitempty"`
RetryInterval int RetryInterval int `json:"RetryInterval,omitempty"`
} }
GlobalDeploymentOptions struct { GlobalDeploymentOptions struct {
HideStacksFunctionality bool `json:"hideStacksFunctionality" example:"false"` HideStacksFunctionality bool `json:"hideStacksFunctionality,omitempty" example:"false"`
} }
// Settings represents the application settings // Settings represents the application settings
Settings struct { Settings struct {
// URL to a logo that will be displayed on the login page as well as on top of the sidebar. Will use default Portainer logo when value is empty string // URL to a logo that will be displayed on the login page as well as on top of the sidebar. Will use default Portainer logo when value is empty string
LogoURL string `json:"LogoURL" example:"https://mycompany.mydomain.tld/logo.png"` LogoURL string `json:"LogoURL,omitempty" example:"https://mycompany.mydomain.tld/logo.png"`
// A list of label name & value that will be used to hide containers when querying containers // A list of label name & value that will be used to hide containers when querying containers
BlackListedLabels []Pair `json:"BlackListedLabels"` BlackListedLabels []Pair `json:"BlackListedLabels"`
// Active authentication method for the Portainer instance. Valid values are: 1 for internal, 2 for LDAP, or 3 for oauth // Active authentication method for the Portainer instance. Valid values are: 1 for internal, 2 for LDAP, or 3 for oauth
@ -962,27 +962,27 @@ type (
// The default check in interval for edge agent (in seconds) // The default check in interval for edge agent (in seconds)
EdgeAgentCheckinInterval int `json:"EdgeAgentCheckinInterval" example:"5"` EdgeAgentCheckinInterval int `json:"EdgeAgentCheckinInterval" example:"5"`
// Show the Kompose build option (discontinued in 2.18) // Show the Kompose build option (discontinued in 2.18)
ShowKomposeBuildOption bool `json:"ShowKomposeBuildOption" example:"false"` ShowKomposeBuildOption bool `json:"ShowKomposeBuildOption,omitempty" example:"false"`
// Whether edge compute features are enabled // Whether edge compute features are enabled
EnableEdgeComputeFeatures bool `json:"EnableEdgeComputeFeatures"` EnableEdgeComputeFeatures bool `json:"EnableEdgeComputeFeatures,omitempty"`
// The duration of a user session // The duration of a user session
UserSessionTimeout string `json:"UserSessionTimeout" example:"5m"` UserSessionTimeout string `json:"UserSessionTimeout" example:"5m"`
// The expiry of a Kubeconfig // The expiry of a Kubeconfig
KubeconfigExpiry string `json:"KubeconfigExpiry" example:"24h"` KubeconfigExpiry string `json:"KubeconfigExpiry" example:"24h"`
// Whether telemetry is enabled // Whether telemetry is enabled
EnableTelemetry bool `json:"EnableTelemetry" example:"false"` EnableTelemetry bool `json:"EnableTelemetry,omitempty" example:"false"`
// Helm repository URL, defaults to "https://charts.bitnami.com/bitnami" // Helm repository URL, defaults to "https://charts.bitnami.com/bitnami"
HelmRepositoryURL string `json:"HelmRepositoryURL" example:"https://charts.bitnami.com/bitnami"` HelmRepositoryURL string `json:"HelmRepositoryURL" example:"https://charts.bitnami.com/bitnami"`
// KubectlImage, defaults to portainer/kubectl-shell // KubectlImage, defaults to portainer/kubectl-shell
KubectlShellImage string `json:"KubectlShellImage" example:"portainer/kubectl-shell"` KubectlShellImage string `json:"KubectlShellImage" example:"portainer/kubectl-shell"`
// TrustOnFirstConnect makes Portainer accepting edge agent connection by default // TrustOnFirstConnect makes Portainer accepting edge agent connection by default
TrustOnFirstConnect bool `json:"TrustOnFirstConnect" example:"false"` TrustOnFirstConnect bool `json:"TrustOnFirstConnect,omitempty" example:"false"`
// EnforceEdgeID makes Portainer store the Edge ID instead of accepting anyone // EnforceEdgeID makes Portainer store the Edge ID instead of accepting anyone
EnforceEdgeID bool `json:"EnforceEdgeID" example:"false"` EnforceEdgeID bool `json:"EnforceEdgeID,omitempty" example:"false"`
// Container environment parameter AGENT_SECRET // Container environment parameter AGENT_SECRET
AgentSecret string `json:"AgentSecret"` AgentSecret string `json:"AgentSecret,omitempty"`
// EdgePortainerURL is the URL that is exposed to edge agents // EdgePortainerURL is the URL that is exposed to edge agents
EdgePortainerURL string `json:"EdgePortainerUrl"` EdgePortainerURL string `json:"EdgePortainerUrl,omitempty"`
Edge struct { Edge struct {
// The command list interval for edge agent - used in edge async mode (in seconds) // The command list interval for edge agent - used in edge async mode (in seconds)
@ -997,20 +997,20 @@ type (
} }
// Deprecated fields // Deprecated fields
DisplayDonationHeader bool DisplayDonationHeader bool `json:"DisplayDonationHeader,omitempty"`
DisplayExternalContributors bool DisplayExternalContributors bool `json:"DisplayExternalContributors,omitempty"`
// Deprecated fields v26 // Deprecated fields v26
EnableHostManagementFeatures bool `json:"EnableHostManagementFeatures"` EnableHostManagementFeatures bool `json:"EnableHostManagementFeatures,omitempty"`
AllowVolumeBrowserForRegularUsers bool `json:"AllowVolumeBrowserForRegularUsers"` AllowVolumeBrowserForRegularUsers bool `json:"AllowVolumeBrowserForRegularUsers,omitempty"`
AllowBindMountsForRegularUsers bool `json:"AllowBindMountsForRegularUsers"` AllowBindMountsForRegularUsers bool `json:"AllowBindMountsForRegularUsers,omitempty"`
AllowPrivilegedModeForRegularUsers bool `json:"AllowPrivilegedModeForRegularUsers"` AllowPrivilegedModeForRegularUsers bool `json:"AllowPrivilegedModeForRegularUsers,omitempty"`
AllowHostNamespaceForRegularUsers bool `json:"AllowHostNamespaceForRegularUsers"` AllowHostNamespaceForRegularUsers bool `json:"AllowHostNamespaceForRegularUsers,omitempty"`
AllowStackManagementForRegularUsers bool `json:"AllowStackManagementForRegularUsers"` AllowStackManagementForRegularUsers bool `json:"AllowStackManagementForRegularUsers,omitempty"`
AllowDeviceMappingForRegularUsers bool `json:"AllowDeviceMappingForRegularUsers"` AllowDeviceMappingForRegularUsers bool `json:"AllowDeviceMappingForRegularUsers,omitempty"`
AllowContainerCapabilitiesForRegularUsers bool `json:"AllowContainerCapabilitiesForRegularUsers"` AllowContainerCapabilitiesForRegularUsers bool `json:"AllowContainerCapabilitiesForRegularUsers,omitempty"`
IsDockerDesktopExtension bool `json:"IsDockerDesktopExtension"` IsDockerDesktopExtension bool `json:"IsDockerDesktopExtension,omitempty"`
} }
// SnapshotJob represents a scheduled job that can create environment(endpoint) snapshots // SnapshotJob represents a scheduled job that can create environment(endpoint) snapshots
@ -1021,10 +1021,10 @@ type (
// SSLSettings represents a pair of SSL certificate and key // SSLSettings represents a pair of SSL certificate and key
SSLSettings struct { SSLSettings struct {
CertPath string `json:"certPath"` CertPath string `json:"certPath,omitempty"`
KeyPath string `json:"keyPath"` KeyPath string `json:"keyPath,omitempty"`
SelfSigned bool `json:"selfSigned"` SelfSigned bool `json:"selfSigned,omitempty"`
HTTPEnabled bool `json:"httpEnabled"` HTTPEnabled bool `json:"httpEnabled,omitempty"`
} }
// Stack represents a Docker stack created via docker stack deploy // Stack represents a Docker stack created via docker stack deploy
@ -1038,13 +1038,13 @@ type (
// Environment(Endpoint) identifier. Reference the environment(endpoint) that will be used for deployment // Environment(Endpoint) identifier. Reference the environment(endpoint) that will be used for deployment
EndpointID EndpointID `json:"EndpointId" example:"1"` EndpointID EndpointID `json:"EndpointId" example:"1"`
// Cluster identifier of the Swarm cluster where the stack is deployed // Cluster identifier of the Swarm cluster where the stack is deployed
SwarmID string `json:"SwarmId" example:"jpofkc0i9uo9wtx1zesuk649w"` SwarmID string `json:"SwarmId,omitempty" example:"jpofkc0i9uo9wtx1zesuk649w"`
// Path to the Stack file // Path to the Stack file
EntryPoint string `json:"EntryPoint" example:"docker-compose.yml"` EntryPoint string `json:"EntryPoint" example:"docker-compose.yml"`
// A list of environment(endpoint) variables used during stack deployment // A list of environment(endpoint) variables used during stack deployment
Env []Pair `json:"Env"` Env []Pair `json:"Env"`
// //
ResourceControl *ResourceControl `json:"ResourceControl"` ResourceControl *ResourceControl `json:"ResourceControl,omitempty"`
// Stack status (1 - active, 2 - inactive) // Stack status (1 - active, 2 - inactive)
Status StackStatus `json:"Status" example:"1"` Status StackStatus `json:"Status" example:"1"`
// Path on disk to the repository hosting the Stack file // Path on disk to the repository hosting the Stack file
@ -1060,23 +1060,23 @@ type (
// Only applies when deploying stack with multiple files // Only applies when deploying stack with multiple files
AdditionalFiles []string `json:"AdditionalFiles"` AdditionalFiles []string `json:"AdditionalFiles"`
// The GitOps update settings of a git stack // The GitOps update settings of a git stack
AutoUpdate *AutoUpdateSettings `json:"AutoUpdate"` AutoUpdate *AutoUpdateSettings `json:"AutoUpdate,omitempty"`
// The stack deployment option // The stack deployment option
Option *StackOption `json:"Option"` Option *StackOption `json:"Option,omitempty"`
// The git config of this stack // The git config of this stack
GitConfig *gittypes.RepoConfig GitConfig *gittypes.RepoConfig `json:"GitConfig,omitempty"`
// Whether the stack is from a app template // Whether the stack is from a app template
FromAppTemplate bool `example:"false"` FromAppTemplate bool `json:"FromAppTemplate,omitempty" example:"false"`
// Kubernetes namespace if stack is a kube application // Kubernetes namespace if stack is a kube application
Namespace string `example:"default"` Namespace string `json:"Namespace,omitempty" example:"default"`
// IsComposeFormat indicates if the Kubernetes stack is created from a Docker Compose file // IsComposeFormat indicates if the Kubernetes stack is created from a Docker Compose file
IsComposeFormat bool `example:"false"` IsComposeFormat bool `json:"IsComposeFormat,omitempty" example:"false"`
} }
// StackOption represents the options for stack deployment // StackOption represents the options for stack deployment
StackOption struct { StackOption struct {
// Prune services that are no longer referenced // Prune services that are no longer referenced
Prune bool `example:"false"` Prune bool `json:"Prune,omitempty" example:"false"`
} }
// StackID represents a stack identifier (it must be composed of Name + "_" + SwarmID to create a unique identifier) // StackID represents a stack identifier (it must be composed of Name + "_" + SwarmID to create a unique identifier)
@ -1159,9 +1159,9 @@ type (
// Title of the template // Title of the template
Title string `json:"title" example:"Nginx"` Title string `json:"title" example:"Nginx"`
// Description of the template // Description of the template
Description string `json:"description" example:"High performance web server"` Description string `json:"description,omitempty" example:"High performance web server"`
// Whether the template should be available to administrators only // Whether the template should be available to administrators only
AdministratorOnly bool `json:"administrator_only" example:"true"` AdministratorOnly bool `json:"administrator_only,omitempty" example:"true"`
// Mandatory container fields // Mandatory container fields
// Image associated to a container template. Mandatory for a container template // Image associated to a container template. Mandatory for a container template
@ -1237,7 +1237,7 @@ type (
// A value that will be associated to the choice // A value that will be associated to the choice
Value string `json:"value" example:"value"` Value string `json:"value" example:"value"`
// Will set this choice as the default choice // Will set this choice as the default choice
Default bool `json:"default" example:"false"` Default bool `json:"default,omitempty" example:"false"`
} }
// TemplateID represents a template identifier // TemplateID represents a template identifier
@ -1267,9 +1267,9 @@ type (
// TLSConfiguration represents a TLS configuration // TLSConfiguration represents a TLS configuration
TLSConfiguration struct { TLSConfiguration struct {
// Use TLS // Use TLS
TLS bool `json:"TLS" example:"true"` TLS bool `json:"TLS,omitempty" example:"true"`
// Skip the verification of the server TLS certificate // Skip the verification of the server TLS certificate
TLSSkipVerify bool `json:"TLSSkipVerify" example:"false"` TLSSkipVerify bool `json:"TLSSkipVerify,omitempty" example:"false"`
// Path to the TLS CA certificate file // Path to the TLS CA certificate file
TLSCACertPath string `json:"TLSCACert,omitempty" example:"/data/tls/ca.pem"` TLSCACertPath string `json:"TLSCACert,omitempty" example:"/data/tls/ca.pem"`
// Path to the TLS client certificate file // Path to the TLS client certificate file
@ -1287,7 +1287,7 @@ type (
ID UserID ID UserID
Username string Username string
Role UserRole Role UserRole
ForceChangePassword bool ForceChangePassword bool `json:"ForceChangePassword,omitempty"`
Token string Token string
} }
@ -1302,7 +1302,7 @@ type (
// TunnelServerInfo represents information associated to the tunnel server // TunnelServerInfo represents information associated to the tunnel server
TunnelServerInfo struct { TunnelServerInfo struct {
PrivateKeySeed string `json:"PrivateKeySeed"` PrivateKeySeed string `json:"PrivateKeySeed,omitempty"`
} }
// User represents a user account // User represents a user account
@ -1319,7 +1319,7 @@ type (
// Deprecated fields // Deprecated fields
// Deprecated // Deprecated
UserTheme string `example:"dark"` UserTheme string `json:"UserTheme,omitempty" example:"dark"`
// Deprecated in DBVersion == 25 // Deprecated in DBVersion == 25
PortainerAuthorizations Authorizations PortainerAuthorizations Authorizations
// Deprecated in DBVersion == 25 // Deprecated in DBVersion == 25
@ -1345,7 +1345,7 @@ type (
// UserThemeSettings represents the theme settings for a user // UserThemeSettings represents the theme settings for a user
UserThemeSettings struct { UserThemeSettings struct {
// Color represents the color theme of the UI // Color represents the color theme of the UI
Color string `json:"color" example:"dark" enums:"dark,light,highcontrast,auto"` Color string `json:"color,omitempty" example:"dark" enums:"dark,light,highcontrast,auto"`
} }
// Webhook represents a url webhook that can be used to update a service // Webhook represents a url webhook that can be used to update a service
@ -1368,8 +1368,8 @@ type (
Snapshot struct { Snapshot struct {
EndpointID EndpointID `json:"EndpointId"` EndpointID EndpointID `json:"EndpointId"`
Docker *DockerSnapshot `json:"Docker"` Docker *DockerSnapshot `json:"Docker,omitempty"`
Kubernetes *KubernetesSnapshot `json:"Kubernetes"` Kubernetes *KubernetesSnapshot `json:"Kubernetes,omitempty"`
} }
// CLIService represents a service for managing CLI // CLIService represents a service for managing CLI

View File

@ -3,7 +3,6 @@ package deployments
import ( import (
"bytes" "bytes"
"context" "context"
"encoding/json"
"fmt" "fmt"
"io" "io"
"math/rand" "math/rand"
@ -11,16 +10,17 @@ import (
"strings" "strings"
"time" "time"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/filesystem"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/swarm" "github.com/docker/docker/api/types/swarm"
dockerclient "github.com/docker/docker/client"
"github.com/docker/docker/pkg/stdcopy" "github.com/docker/docker/pkg/stdcopy"
"github.com/pkg/errors" "github.com/pkg/errors"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/filesystem"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/segmentio/encoding/json"
dockerclient "github.com/docker/docker/client"
) )
const ( const (

4
go.mod
View File

@ -31,7 +31,6 @@ require (
github.com/hashicorp/golang-lru v0.5.4 github.com/hashicorp/golang-lru v0.5.4
github.com/joho/godotenv v1.4.0 github.com/joho/godotenv v1.4.0
github.com/jpillora/chisel v1.9.0 github.com/jpillora/chisel v1.9.0
github.com/json-iterator/go v1.1.12
github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c github.com/koding/websocketproxy v0.0.0-20181220232114-7ed82d81a28c
github.com/opencontainers/go-digest v1.0.0 github.com/opencontainers/go-digest v1.0.0
github.com/orcaman/concurrent-map v1.0.0 github.com/orcaman/concurrent-map v1.0.0
@ -39,6 +38,7 @@ require (
github.com/pkg/errors v0.9.1 github.com/pkg/errors v0.9.1
github.com/robfig/cron/v3 v3.0.1 github.com/robfig/cron/v3 v3.0.1
github.com/rs/zerolog v1.29.0 github.com/rs/zerolog v1.29.0
github.com/segmentio/encoding v0.3.6
github.com/stretchr/testify v1.8.2 github.com/stretchr/testify v1.8.2
github.com/viney-shih/go-lock v1.1.1 github.com/viney-shih/go-lock v1.1.1
go.etcd.io/bbolt v1.3.7 go.etcd.io/bbolt v1.3.7
@ -106,6 +106,7 @@ require (
github.com/jpillora/ansi v1.0.3 // indirect github.com/jpillora/ansi v1.0.3 // indirect
github.com/jpillora/requestlog v1.0.0 // indirect github.com/jpillora/requestlog v1.0.0 // indirect
github.com/jpillora/sizestr v1.0.0 // indirect github.com/jpillora/sizestr v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
github.com/klauspost/compress v1.16.3 // indirect github.com/klauspost/compress v1.16.3 // indirect
github.com/klauspost/pgzip v1.2.6-0.20220930104621-17e8dac29df8 // indirect github.com/klauspost/pgzip v1.2.6-0.20220930104621-17e8dac29df8 // indirect
@ -125,6 +126,7 @@ require (
github.com/opencontainers/runc v1.1.5 // indirect github.com/opencontainers/runc v1.1.5 // indirect
github.com/opencontainers/runtime-spec v1.1.0-rc.1 // indirect github.com/opencontainers/runtime-spec v1.1.0-rc.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/segmentio/asm v1.1.3 // indirect
github.com/sergi/go-diff v1.1.0 // indirect github.com/sergi/go-diff v1.1.0 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect github.com/sirupsen/logrus v1.9.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/spf13/pflag v1.0.5 // indirect

5
go.sum
View File

@ -330,6 +330,10 @@ github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQD
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/rwtodd/Go.Sed v0.0.0-20210816025313-55464686f9ef/go.mod h1:8AEUvGVi2uQ5b24BIhcr0GCcpd/RNAFWaN2CJFrWIIQ= github.com/rwtodd/Go.Sed v0.0.0-20210816025313-55464686f9ef/go.mod h1:8AEUvGVi2uQ5b24BIhcr0GCcpd/RNAFWaN2CJFrWIIQ=
github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg=
github.com/segmentio/asm v1.1.3 h1:WM03sfUOENvvKexOLp+pCqgb/WDjsi7EK8gIsICtzhc=
github.com/segmentio/asm v1.1.3/go.mod h1:Ld3L4ZXGNcSLRg4JBsZ3//1+f/TjYl0Mzen/DQy1EJg=
github.com/segmentio/encoding v0.3.6 h1:E6lVLyDPseWEulBmCmAKPanDd3jiyGDo5gMcugCRwZQ=
github.com/segmentio/encoding v0.3.6/go.mod h1:n0JeuIqEQrQoPDGsjo8UNd1iA0U8d8+oHAA4E3G3OxM=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
@ -450,6 +454,7 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

View File

@ -1,11 +1,11 @@
package binary package binary
import ( import (
"encoding/json"
"github.com/pkg/errors"
"github.com/portainer/portainer/pkg/libhelm/options" "github.com/portainer/portainer/pkg/libhelm/options"
"github.com/portainer/portainer/pkg/libhelm/release" "github.com/portainer/portainer/pkg/libhelm/release"
"github.com/pkg/errors"
"github.com/segmentio/encoding/json"
) )
// Install runs `helm install` with specified install options. // Install runs `helm install` with specified install options.

View File

@ -1,11 +1,11 @@
package binary package binary
import ( import (
"encoding/json"
"github.com/pkg/errors"
"github.com/portainer/portainer/pkg/libhelm/options" "github.com/portainer/portainer/pkg/libhelm/options"
"github.com/portainer/portainer/pkg/libhelm/release" "github.com/portainer/portainer/pkg/libhelm/release"
"github.com/pkg/errors"
"github.com/segmentio/encoding/json"
) )
// List runs `helm list --output json --filter <filter> --selector <selector> --namespace <namespace>` with specified list options. // List runs `helm list --output json --filter <filter> --selector <selector> --namespace <namespace>` with specified list options.

View File

@ -4,15 +4,16 @@ package binary
// The functionality does not rely on the implementation of `HelmPackageManager` // The functionality does not rely on the implementation of `HelmPackageManager`
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"net/url" "net/url"
"path" "path"
"time" "time"
"github.com/pkg/errors"
"github.com/portainer/portainer/pkg/libhelm/options" "github.com/portainer/portainer/pkg/libhelm/options"
"github.com/pkg/errors"
"github.com/segmentio/encoding/json"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )

View File

@ -1,13 +1,14 @@
package test package test
import ( import (
"encoding/json"
"strings" "strings"
"github.com/pkg/errors"
"github.com/portainer/portainer/pkg/libhelm" "github.com/portainer/portainer/pkg/libhelm"
"github.com/portainer/portainer/pkg/libhelm/options" "github.com/portainer/portainer/pkg/libhelm/options"
"github.com/portainer/portainer/pkg/libhelm/release" "github.com/portainer/portainer/pkg/libhelm/release"
"github.com/pkg/errors"
"github.com/segmentio/encoding/json"
"gopkg.in/yaml.v3" "gopkg.in/yaml.v3"
) )

View File

@ -17,9 +17,10 @@ limitations under the License.
package time package time
import ( import (
"encoding/json"
"testing" "testing"
"time" "time"
"github.com/segmentio/encoding/json"
) )
var ( var (

View File

@ -2,11 +2,11 @@
package error package error
import ( import (
"encoding/json"
"errors" "errors"
"net/http" "net/http"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/segmentio/encoding/json"
) )
type ( type (
@ -36,7 +36,11 @@ func writeErrorResponse(rw http.ResponseWriter, err *HandlerError) {
rw.Header().Set("Content-Type", "application/json") rw.Header().Set("Content-Type", "application/json")
rw.WriteHeader(err.StatusCode) rw.WriteHeader(err.StatusCode)
json.NewEncoder(rw).Encode(&errorResponse{Message: err.Message, Details: err.Err.Error()}) enc := json.NewEncoder(rw)
enc.SetSortMapKeys(false)
enc.SetAppendNewline(false)
enc.Encode(&errorResponse{Message: err.Message, Details: err.Err.Error()})
} }
// WriteError is a convenience function that creates a new HandlerError before calling writeErrorResponse. // WriteError is a convenience function that creates a new HandlerError before calling writeErrorResponse.

View File

@ -1,10 +1,10 @@
package request package request
import ( import (
"encoding/json"
"net/http" "net/http"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/segmentio/encoding/json"
) )
// PayloadValidation is an interface used to validate the payload of a request. // PayloadValidation is an interface used to validate the payload of a request.

View File

@ -2,13 +2,13 @@ package request_test
import ( import (
"bytes" "bytes"
"encoding/json"
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"testing" "testing"
"github.com/portainer/portainer/pkg/libhttp/request" "github.com/portainer/portainer/pkg/libhttp/request"
"github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
) )

View File

@ -4,13 +4,13 @@
package request package request
import ( import (
"encoding/json"
"errors" "errors"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"strconv" "strconv"
"github.com/gorilla/mux" "github.com/gorilla/mux"
"github.com/segmentio/encoding/json"
) )
const ( const (

View File

@ -2,12 +2,13 @@
package response package response
import ( import (
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"net/http" "net/http"
httperror "github.com/portainer/portainer/pkg/libhttp/error" httperror "github.com/portainer/portainer/pkg/libhttp/error"
"github.com/segmentio/encoding/json"
) )
// JSON encodes data to rw in JSON format. Returns a pointer to a // JSON encodes data to rw in JSON format. Returns a pointer to a
@ -15,7 +16,11 @@ import (
func JSON(rw http.ResponseWriter, data interface{}) *httperror.HandlerError { func JSON(rw http.ResponseWriter, data interface{}) *httperror.HandlerError {
rw.Header().Set("Content-Type", "application/json") rw.Header().Set("Content-Type", "application/json")
err := json.NewEncoder(rw).Encode(data) enc := json.NewEncoder(rw)
enc.SetSortMapKeys(false)
enc.SetAppendNewline(false)
err := enc.Encode(data)
if err != nil { if err != nil {
return httperror.InternalServerError("Unable to write JSON response", err) return httperror.InternalServerError("Unable to write JSON response", err)
} }

View File

@ -2,12 +2,13 @@ package composeplugin
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"time" "time"
"github.com/portainer/portainer/pkg/libstack" "github.com/portainer/portainer/pkg/libstack"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
"github.com/segmentio/encoding/json"
) )
type publisher struct { type publisher struct {