diff --git a/api/.golangci.yaml b/api/.golangci.yaml
index 5675e6deb..5b885de19 100644
--- a/api/.golangci.yaml
+++ b/api/.golangci.yaml
@@ -13,6 +13,8 @@ linters-settings:
rules:
main:
deny:
+ - pkg: 'encoding/json'
+ desc: 'use github.com/segmentio/encoding/json'
- pkg: 'github.com/sirupsen/logrus'
desc: 'logging is allowed only by github.com/rs/zerolog'
- pkg: 'golang.org/x/exp'
diff --git a/api/database/boltdb/db.go b/api/database/boltdb/db.go
index 52b7cbea4..62aa8f3a6 100644
--- a/api/database/boltdb/db.go
+++ b/api/database/boltdb/db.go
@@ -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))
}
- err := connection.UnmarshalObjectWithJsoniter(data, object)
+ err := connection.UnmarshalObject(data, object)
if err != nil {
return err
}
diff --git a/api/database/boltdb/export.go b/api/database/boltdb/export.go
index 00712c734..a95eb7dfe 100644
--- a/api/database/boltdb/export.go
+++ b/api/database/boltdb/export.go
@@ -1,10 +1,10 @@
package boltdb
import (
- "encoding/json"
"time"
"github.com/rs/zerolog/log"
+ "github.com/segmentio/encoding/json"
bolt "go.etcd.io/bbolt"
)
diff --git a/api/database/boltdb/json.go b/api/database/boltdb/json.go
index 045eb2720..2c9192d4e 100644
--- a/api/database/boltdb/json.go
+++ b/api/database/boltdb/json.go
@@ -1,34 +1,41 @@
package boltdb
import (
+ "bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
- "encoding/json"
"fmt"
"io"
- jsoniter "github.com/json-iterator/go"
"github.com/pkg/errors"
+ "github.com/segmentio/encoding/json"
)
var errEncryptedStringTooShort = fmt.Errorf("encrypted string too short")
// 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
if v, ok := object.(string); ok {
- data = []byte(v)
+ buf.WriteString(v)
} else {
- data, err = json.Marshal(object)
- if err != nil {
- return data, err
+ enc := json.NewEncoder(buf)
+ enc.SetSortMapKeys(false)
+ enc.SetAppendNewline(false)
+
+ if err := enc.Encode(object); err != nil {
+ return nil, err
}
}
+
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
@@ -54,31 +61,6 @@ func (connection *DbConnection) UnmarshalObject(data []byte, object interface{})
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
// https://gist.github.com/atoponce/07d8d4c833873be2f68c34f9afc5a78a#symmetric-encryption
diff --git a/api/database/boltdb/tx.go b/api/database/boltdb/tx.go
index 7cc8bee7a..073b279bf 100644
--- a/api/database/boltdb/tx.go
+++ b/api/database/boltdb/tx.go
@@ -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 tx.conn.UnmarshalObjectWithJsoniter(value, object)
+ return tx.conn.UnmarshalObject(value, object)
}
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))
return bucket.ForEach(func(k []byte, v []byte) error {
- err := tx.conn.UnmarshalObjectWithJsoniter(v, obj)
+ err := tx.conn.UnmarshalObject(v, obj)
if err == nil {
obj, err = appendFn(obj)
}
@@ -147,7 +147,7 @@ func (tx *DbTransaction) GetAllWithKeyPrefix(bucketName string, keyPrefix []byte
cursor := tx.tx.Bucket([]byte(bucketName)).Cursor()
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 {
return err
}
diff --git a/api/datastore/migrate_data_test.go b/api/datastore/migrate_data_test.go
index 7917bcd83..389481b95 100644
--- a/api/datastore/migrate_data_test.go
+++ b/api/datastore/migrate_data_test.go
@@ -2,7 +2,6 @@ package datastore
import (
"bytes"
- "encoding/json"
"fmt"
"io"
"os"
@@ -11,10 +10,11 @@ import (
"testing"
"github.com/portainer/portainer/api/database/boltdb"
+ "github.com/portainer/portainer/api/database/models"
"github.com/google/go-cmp/cmp"
- "github.com/portainer/portainer/api/database/models"
"github.com/rs/zerolog/log"
+ "github.com/segmentio/encoding/json"
)
// testVersion is a helper which tests current store version against wanted version
diff --git a/api/datastore/services.go b/api/datastore/services.go
index b0e5c764e..802989d3d 100644
--- a/api/datastore/services.go
+++ b/api/datastore/services.go
@@ -1,7 +1,6 @@
package datastore
import (
- "encoding/json"
"fmt"
"os"
@@ -38,6 +37,7 @@ import (
"github.com/portainer/portainer/api/dataservices/webhook"
"github.com/rs/zerolog/log"
+ "github.com/segmentio/encoding/json"
)
// Store defines the implementation of portainer.DataStore using
diff --git a/api/datastore/test_data/output_24_to_latest.json b/api/datastore/test_data/output_24_to_latest.json
index d10397ad5..9cd35f833 100644
--- a/api/datastore/test_data/output_24_to_latest.json
+++ b/api/datastore/test_data/output_24_to_latest.json
@@ -27,9 +27,7 @@
],
"endpoints": [
{
- "Agent": {
- "Version": ""
- },
+ "Agent": {},
"AuthorizedTeams": null,
"AuthorizedUsers": null,
"AzureCredentials": {
@@ -38,71 +36,42 @@
"TenantID": ""
},
"ComposeSyntaxMaxVersion": "",
- "Edge": {
- "AsyncMode": false,
- "CommandInterval": 0,
- "PingInterval": 0,
- "SnapshotInterval": 0
- },
+ "Edge": {},
"EdgeCheckinInterval": 0,
- "EdgeKey": "",
- "EnableGPUManagement": false,
"Gpus": [],
"GroupId": 1,
- "Heartbeat": false,
"Id": 1,
- "IsEdgeDevice": false,
"Kubernetes": {
"Configuration": {
- "AllowNoneIngressClass": false,
- "EnableResourceOverCommit": false,
"IngressAvailabilityPerNamespace": true,
"IngressClasses": null,
- "ResourceOverCommitPercentage": 0,
- "RestrictDefaultNamespace": false,
- "StorageClasses": null,
- "UseLoadBalancer": false,
- "UseServerMetrics": false
- },
- "Flags": {
- "IsServerIngressClassDetected": false,
- "IsServerMetricsDetected": false,
- "IsServerStorageDetected": false
+ "StorageClasses": null
},
+ "Flags": {},
"Snapshots": []
},
- "LastCheckInDate": 0,
"Name": "local",
"PostInitMigrations": {
"MigrateGPUs": true,
"MigrateIngresses": true
},
- "PublicURL": "",
- "QueryDate": 0,
"SecuritySettings": {
"allowBindMountsForRegularUsers": true,
"allowContainerCapabilitiesForRegularUsers": true,
"allowDeviceMappingForRegularUsers": true,
"allowHostNamespaceForRegularUsers": true,
"allowPrivilegedModeForRegularUsers": true,
- "allowStackManagementForRegularUsers": true,
- "allowSysctlSettingForRegularUsers": false,
- "allowVolumeBrowserForRegularUsers": false,
- "enableHostManagementFeatures": false
+ "allowStackManagementForRegularUsers": true
},
"Snapshots": [],
"Status": 1,
- "TLSConfig": {
- "TLS": false,
- "TLSSkipVerify": false
- },
+ "TLSConfig": {},
"TagIds": [],
"Tags": null,
"TeamAccessPolicies": {},
"Type": 1,
"URL": "unix:///var/run/docker.sock",
- "UserAccessPolicies": {},
- "UserTrusted": false
+ "UserAccessPolicies": {}
}
],
"registries": [
@@ -110,7 +79,6 @@
"Authentication": true,
"AuthorizedTeams": null,
"AuthorizedUsers": null,
- "BaseURL": "",
"Ecr": {
"Region": ""
},
@@ -124,8 +92,7 @@
"Name": "canister.io",
"Password": "MjWbx8A6YK7cw7",
"Quay": {
- "OrganisationName": "",
- "UseOrganisation": false
+ "OrganisationName": ""
},
"RegistryAccesses": {
"1": {
@@ -154,34 +121,28 @@
"UserAccesses": []
},
{
- "AdministratorsOnly": false,
"Id": 3,
"Public": true,
"ResourceId": "1_alpine",
"SubResourceIds": [],
- "System": false,
"TeamAccesses": [],
"Type": 6,
"UserAccesses": []
},
{
- "AdministratorsOnly": false,
"Id": 4,
"Public": true,
"ResourceId": "1_redis",
"SubResourceIds": [],
- "System": false,
"TeamAccesses": [],
"Type": 6,
"UserAccesses": []
},
{
- "AdministratorsOnly": false,
"Id": 5,
"Public": false,
"ResourceId": "1_nginx",
"SubResourceIds": [],
- "System": false,
"TeamAccesses": [
{
"AccessLevel": 1,
@@ -577,18 +538,14 @@
}
],
"settings": {
- "AgentSecret": "",
"AllowBindMountsForRegularUsers": true,
"AllowContainerCapabilitiesForRegularUsers": true,
"AllowDeviceMappingForRegularUsers": true,
"AllowHostNamespaceForRegularUsers": true,
"AllowPrivilegedModeForRegularUsers": true,
"AllowStackManagementForRegularUsers": true,
- "AllowVolumeBrowserForRegularUsers": false,
"AuthenticationMethod": 1,
"BlackListedLabels": [],
- "DisplayDonationHeader": false,
- "DisplayExternalContributors": false,
"Edge": {
"AsyncMode": false,
"CommandInterval": 0,
@@ -596,20 +553,13 @@
"SnapshotInterval": 0
},
"EdgeAgentCheckinInterval": 5,
- "EdgePortainerUrl": "",
- "EnableEdgeComputeFeatures": false,
- "EnableHostManagementFeatures": false,
"EnableTelemetry": true,
- "EnforceEdgeID": false,
"FeatureFlagSettings": null,
- "GlobalDeploymentOptions": {
- "hideStacksFunctionality": false
- },
+ "GlobalDeploymentOptions": {},
"HelmRepositoryURL": "https://charts.bitnami.com/bitnami",
"InternalAuthSettings": {
"RequiredPasswordLength": 12
},
- "IsDockerDesktopExtension": false,
"KubeconfigExpiry": "0",
"KubectlShellImage": "portainer/kubectl-shell",
"LDAPSettings": {
@@ -618,8 +568,7 @@
"GroupSearchSettings": [
{
"GroupAttribute": "",
- "GroupBaseDN": "",
- "GroupFilter": ""
+ "GroupBaseDN": ""
}
],
"ReaderDN": "",
@@ -630,14 +579,9 @@
"UserNameAttribute": ""
}
],
- "StartTLS": false,
- "TLSConfig": {
- "TLS": false,
- "TLSSkipVerify": false
- },
+ "TLSConfig": {},
"URL": ""
},
- "LogoURL": "",
"OAuthSettings": {
"AccessTokenURI": "",
"AuthorizationURI": "",
@@ -652,10 +596,8 @@
"Scopes": "",
"UserIdentifier": ""
},
- "ShowKomposeBuildOption": false,
"SnapshotInterval": "5m",
"TemplatesURL": "https://raw.githubusercontent.com/portainer/templates/master/templates-2.0.json",
- "TrustOnFirstConnect": false,
"UserSessionTimeout": "8h",
"fdoConfiguration": {
"enabled": false,
@@ -794,34 +736,23 @@
"UnhealthyContainerCount": 0,
"VolumeCount": 10
},
- "EndpointId": 1,
- "Kubernetes": null
+ "EndpointId": 1
}
],
"ssl": {
- "certPath": "",
- "httpEnabled": true,
- "keyPath": "",
- "selfSigned": false
+ "httpEnabled": true
},
"stacks": [
{
"AdditionalFiles": null,
- "AutoUpdate": null,
"CreatedBy": "",
"CreationDate": 0,
"EndpointId": 1,
"EntryPoint": "docker/alpine37-compose.yml",
"Env": [],
- "FromAppTemplate": false,
- "GitConfig": null,
"Id": 2,
- "IsComposeFormat": false,
"Name": "alpine",
- "Namespace": "",
- "Option": null,
"ProjectPath": "/home/prabhat/portainer/data/ce1.25/compose/2",
- "ResourceControl": null,
"Status": 1,
"SwarmId": "s3fd604zdba7z13tbq2x6lyue",
"Type": 1,
@@ -830,46 +761,30 @@
},
{
"AdditionalFiles": null,
- "AutoUpdate": null,
"CreatedBy": "",
"CreationDate": 0,
"EndpointId": 1,
"EntryPoint": "docker-compose.yml",
"Env": [],
- "FromAppTemplate": false,
- "GitConfig": null,
"Id": 5,
- "IsComposeFormat": false,
"Name": "redis",
- "Namespace": "",
- "Option": null,
"ProjectPath": "/home/prabhat/portainer/data/ce1.25/compose/5",
- "ResourceControl": null,
"Status": 1,
- "SwarmId": "",
"Type": 2,
"UpdateDate": 0,
"UpdatedBy": ""
},
{
"AdditionalFiles": null,
- "AutoUpdate": null,
"CreatedBy": "",
"CreationDate": 0,
"EndpointId": 1,
"EntryPoint": "docker-compose.yml",
"Env": [],
- "FromAppTemplate": false,
- "GitConfig": null,
"Id": 6,
- "IsComposeFormat": false,
"Name": "nginx",
- "Namespace": "",
- "Option": null,
"ProjectPath": "/home/prabhat/portainer/data/ce1.25/compose/6",
- "ResourceControl": null,
"Status": 1,
- "SwarmId": "",
"Type": 2,
"UpdateDate": 0,
"UpdatedBy": ""
@@ -881,9 +796,7 @@
"Name": "hello"
}
],
- "tunnel_server": {
- "PrivateKeySeed": ""
- },
+ "tunnel_server": {},
"users": [
{
"EndpointAuthorizations": null,
@@ -908,11 +821,8 @@
"PortainerUserRevokeToken": true
},
"Role": 1,
- "ThemeSettings": {
- "color": ""
- },
+ "ThemeSettings": {},
"TokenIssueAt": 0,
- "UserTheme": "",
"Username": "admin"
},
{
@@ -938,11 +848,8 @@
"PortainerUserRevokeToken": true
},
"Role": 1,
- "ThemeSettings": {
- "color": ""
- },
+ "ThemeSettings": {},
"TokenIssueAt": 0,
- "UserTheme": "",
"Username": "prabhat"
}
],
diff --git a/api/exec/swarm_stack.go b/api/exec/swarm_stack.go
index f8b031976..5745098ee 100644
--- a/api/exec/swarm_stack.go
+++ b/api/exec/swarm_stack.go
@@ -2,7 +2,6 @@ package exec
import (
"bytes"
- "encoding/json"
"errors"
"fmt"
"os"
@@ -15,7 +14,9 @@ import (
"github.com/portainer/portainer/api/dataservices"
"github.com/portainer/portainer/api/internal/registryutils"
"github.com/portainer/portainer/api/stacks/stackutils"
+
"github.com/rs/zerolog/log"
+ "github.com/segmentio/encoding/json"
)
// SwarmStackManager represents a service for managing stacks.
diff --git a/api/filesystem/filesystem.go b/api/filesystem/filesystem.go
index 3042f7a8b..9eee3b97e 100644
--- a/api/filesystem/filesystem.go
+++ b/api/filesystem/filesystem.go
@@ -2,7 +2,6 @@ package filesystem
import (
"bytes"
- "encoding/json"
"encoding/pem"
"errors"
"fmt"
@@ -15,6 +14,7 @@ import (
"github.com/gofrs/uuid"
"github.com/rs/zerolog/log"
+ "github.com/segmentio/encoding/json"
)
const (
diff --git a/api/git/azure.go b/api/git/azure.go
index b85ffe7b4..9fabeb066 100644
--- a/api/git/azure.go
+++ b/api/git/azure.go
@@ -2,7 +2,6 @@ package git
import (
"context"
- "encoding/json"
"fmt"
"io"
"net/http"
@@ -11,12 +10,13 @@ import (
"strings"
"time"
- "github.com/go-git/go-git/v5/plumbing/filemode"
"github.com/portainer/portainer/api/archive"
"github.com/portainer/portainer/api/crypto"
gittypes "github.com/portainer/portainer/api/git/types"
+ "github.com/go-git/go-git/v5/plumbing/filemode"
"github.com/pkg/errors"
+ "github.com/segmentio/encoding/json"
)
const (
diff --git a/api/hostmanagement/openamt/authorization.go b/api/hostmanagement/openamt/authorization.go
index 463cb4dcf..1c8c2cfe4 100644
--- a/api/hostmanagement/openamt/authorization.go
+++ b/api/hostmanagement/openamt/authorization.go
@@ -2,12 +2,13 @@ package openamt
import (
"bytes"
- "encoding/json"
"fmt"
"io"
"net/http"
portainer "github.com/portainer/portainer/api"
+
+ "github.com/segmentio/encoding/json"
)
type authenticationResponse struct {
diff --git a/api/hostmanagement/openamt/configCIRA.go b/api/hostmanagement/openamt/configCIRA.go
index feac5821a..f76c8938a 100644
--- a/api/hostmanagement/openamt/configCIRA.go
+++ b/api/hostmanagement/openamt/configCIRA.go
@@ -2,7 +2,6 @@ package openamt
import (
"encoding/base64"
- "encoding/json"
"encoding/pem"
"fmt"
"io"
@@ -11,6 +10,8 @@ import (
"strings"
portainer "github.com/portainer/portainer/api"
+
+ "github.com/segmentio/encoding/json"
)
type CIRAConfig struct {
diff --git a/api/hostmanagement/openamt/configDevice.go b/api/hostmanagement/openamt/configDevice.go
index 202d5be3e..8afdfbd42 100644
--- a/api/hostmanagement/openamt/configDevice.go
+++ b/api/hostmanagement/openamt/configDevice.go
@@ -1,11 +1,12 @@
package openamt
import (
- "encoding/json"
"fmt"
"strings"
portainer "github.com/portainer/portainer/api"
+
+ "github.com/segmentio/encoding/json"
)
type Device struct {
diff --git a/api/hostmanagement/openamt/configDomain.go b/api/hostmanagement/openamt/configDomain.go
index 5117defdf..46eb3b753 100644
--- a/api/hostmanagement/openamt/configDomain.go
+++ b/api/hostmanagement/openamt/configDomain.go
@@ -1,11 +1,12 @@
package openamt
import (
- "encoding/json"
"fmt"
"net/http"
portainer "github.com/portainer/portainer/api"
+
+ "github.com/segmentio/encoding/json"
)
type (
diff --git a/api/hostmanagement/openamt/configProfile.go b/api/hostmanagement/openamt/configProfile.go
index 5e80205b4..d8a08ae50 100644
--- a/api/hostmanagement/openamt/configProfile.go
+++ b/api/hostmanagement/openamt/configProfile.go
@@ -1,11 +1,12 @@
package openamt
import (
- "encoding/json"
"fmt"
"net/http"
portainer "github.com/portainer/portainer/api"
+
+ "github.com/segmentio/encoding/json"
)
type (
diff --git a/api/hostmanagement/openamt/deviceActions.go b/api/hostmanagement/openamt/deviceActions.go
index 39960add1..76b5344b7 100644
--- a/api/hostmanagement/openamt/deviceActions.go
+++ b/api/hostmanagement/openamt/deviceActions.go
@@ -1,12 +1,13 @@
package openamt
import (
- "encoding/json"
"fmt"
"net/http"
"strings"
portainer "github.com/portainer/portainer/api"
+
+ "github.com/segmentio/encoding/json"
)
type ActionResponse struct {
diff --git a/api/hostmanagement/openamt/deviceFeatures.go b/api/hostmanagement/openamt/deviceFeatures.go
index cce18a8db..c74a1e029 100644
--- a/api/hostmanagement/openamt/deviceFeatures.go
+++ b/api/hostmanagement/openamt/deviceFeatures.go
@@ -1,11 +1,12 @@
package openamt
import (
- "encoding/json"
"fmt"
"net/http"
portainer "github.com/portainer/portainer/api"
+
+ "github.com/segmentio/encoding/json"
)
func (service *Service) enableDeviceFeatures(configuration portainer.OpenAMTConfiguration, deviceGUID string, features portainer.OpenAMTDeviceEnabledFeatures) error {
diff --git a/api/hostmanagement/openamt/openamt.go b/api/hostmanagement/openamt/openamt.go
index c7a738fc4..82fbeafbf 100644
--- a/api/hostmanagement/openamt/openamt.go
+++ b/api/hostmanagement/openamt/openamt.go
@@ -2,7 +2,6 @@ package openamt
import (
"bytes"
- "encoding/json"
"errors"
"fmt"
"io"
@@ -12,6 +11,7 @@ import (
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/crypto"
+ "github.com/segmentio/encoding/json"
"golang.org/x/sync/errgroup"
)
diff --git a/api/http/client/client.go b/api/http/client/client.go
index d28364e07..2a7d0bf9b 100644
--- a/api/http/client/client.go
+++ b/api/http/client/client.go
@@ -2,7 +2,6 @@ package client
import (
"crypto/tls"
- "encoding/json"
"errors"
"fmt"
"io"
@@ -14,6 +13,7 @@ import (
portainer "github.com/portainer/portainer/api"
"github.com/rs/zerolog/log"
+ "github.com/segmentio/encoding/json"
)
var errInvalidResponseStatus = errors.New("invalid response status (expecting 200)")
diff --git a/api/http/handler/customtemplates/customtemplate_create.go b/api/http/handler/customtemplates/customtemplate_create.go
index a93f1facf..024ca1189 100644
--- a/api/http/handler/customtemplates/customtemplate_create.go
+++ b/api/http/handler/customtemplates/customtemplate_create.go
@@ -1,7 +1,6 @@
package customtemplates
import (
- "encoding/json"
"errors"
"fmt"
"net/http"
@@ -21,6 +20,7 @@ import (
"github.com/asaskevich/govalidator"
"github.com/rs/zerolog/log"
+ "github.com/segmentio/encoding/json"
)
func (handler *Handler) customTemplateCreate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
diff --git a/api/http/handler/customtemplates/customtemplate_git_fetch_test.go b/api/http/handler/customtemplates/customtemplate_git_fetch_test.go
index 3765a30f6..1e645abd9 100644
--- a/api/http/handler/customtemplates/customtemplate_git_fetch_test.go
+++ b/api/http/handler/customtemplates/customtemplate_git_fetch_test.go
@@ -2,7 +2,6 @@ package customtemplates
import (
"bytes"
- "encoding/json"
"fmt"
"io"
"io/fs"
@@ -20,6 +19,8 @@ import (
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/internal/authorization"
"github.com/portainer/portainer/api/jwt"
+
+ "github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert"
)
diff --git a/api/http/handler/edgestacks/edgestack_create_test.go b/api/http/handler/edgestacks/edgestack_create_test.go
index cc62de94e..88ead7c99 100644
--- a/api/http/handler/edgestacks/edgestack_create_test.go
+++ b/api/http/handler/edgestacks/edgestack_create_test.go
@@ -2,13 +2,14 @@ package edgestacks
import (
"bytes"
- "encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"
portainer "github.com/portainer/portainer/api"
+
+ "github.com/segmentio/encoding/json"
)
// Create
diff --git a/api/http/handler/edgestacks/edgestack_delete_test.go b/api/http/handler/edgestacks/edgestack_delete_test.go
index a225ff468..212dccb7e 100644
--- a/api/http/handler/edgestacks/edgestack_delete_test.go
+++ b/api/http/handler/edgestacks/edgestack_delete_test.go
@@ -1,13 +1,14 @@
package edgestacks
import (
- "encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"
portainer "github.com/portainer/portainer/api"
+
+ "github.com/segmentio/encoding/json"
)
// Delete
diff --git a/api/http/handler/edgestacks/edgestack_status_update_test.go b/api/http/handler/edgestacks/edgestack_status_update_test.go
index 4ae63aa3f..27a6c1d39 100644
--- a/api/http/handler/edgestacks/edgestack_status_update_test.go
+++ b/api/http/handler/edgestacks/edgestack_status_update_test.go
@@ -2,13 +2,14 @@ package edgestacks
import (
"bytes"
- "encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"testing"
portainer "github.com/portainer/portainer/api"
+
+ "github.com/segmentio/encoding/json"
)
// Update Status
diff --git a/api/http/handler/edgestacks/edgestack_update_test.go b/api/http/handler/edgestacks/edgestack_update_test.go
index 90542178a..973cec42d 100644
--- a/api/http/handler/edgestacks/edgestack_update_test.go
+++ b/api/http/handler/edgestacks/edgestack_update_test.go
@@ -2,7 +2,6 @@ package edgestacks
import (
"bytes"
- "encoding/json"
"fmt"
"net/http"
"net/http/httptest"
@@ -10,6 +9,8 @@ import (
"testing"
portainer "github.com/portainer/portainer/api"
+
+ "github.com/segmentio/encoding/json"
)
// Update
diff --git a/api/http/handler/edgetemplates/edgetemplate_list.go b/api/http/handler/edgetemplates/edgetemplate_list.go
index 70f6b585c..91fa9cf6c 100644
--- a/api/http/handler/edgetemplates/edgetemplate_list.go
+++ b/api/http/handler/edgetemplates/edgetemplate_list.go
@@ -1,13 +1,14 @@
package edgetemplates
import (
- "encoding/json"
"net/http"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/http/client"
httperror "github.com/portainer/portainer/pkg/libhttp/error"
"github.com/portainer/portainer/pkg/libhttp/response"
+
+ "github.com/segmentio/encoding/json"
)
type templateFileFormat struct {
diff --git a/api/http/handler/endpointedge/endpointedge_status_inspect_test.go b/api/http/handler/endpointedge/endpointedge_status_inspect_test.go
index 936261783..41b8eb2de 100644
--- a/api/http/handler/endpointedge/endpointedge_status_inspect_test.go
+++ b/api/http/handler/endpointedge/endpointedge_status_inspect_test.go
@@ -2,7 +2,6 @@ package endpointedge
import (
"context"
- "encoding/json"
"fmt"
"net/http"
"net/http/httptest"
@@ -17,6 +16,7 @@ import (
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/jwt"
+ "github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert"
)
diff --git a/api/http/handler/endpoints/endpoint_dockerhub_status.go b/api/http/handler/endpoints/endpoint_dockerhub_status.go
index cb4f8a6aa..4207d7735 100644
--- a/api/http/handler/endpoints/endpoint_dockerhub_status.go
+++ b/api/http/handler/endpoints/endpoint_dockerhub_status.go
@@ -1,7 +1,6 @@
package endpoints
import (
- "encoding/json"
"errors"
"fmt"
"io"
@@ -15,6 +14,8 @@ import (
httperror "github.com/portainer/portainer/pkg/libhttp/error"
"github.com/portainer/portainer/pkg/libhttp/request"
"github.com/portainer/portainer/pkg/libhttp/response"
+
+ "github.com/segmentio/encoding/json"
)
type dockerhubStatusResponse struct {
diff --git a/api/http/handler/endpoints/endpoint_list_test.go b/api/http/handler/endpoints/endpoint_list_test.go
index 6806de38e..cd53091b4 100644
--- a/api/http/handler/endpoints/endpoint_list_test.go
+++ b/api/http/handler/endpoints/endpoint_list_test.go
@@ -1,7 +1,6 @@
package endpoints
import (
- "encoding/json"
"fmt"
"io"
"net/http"
@@ -13,6 +12,8 @@ import (
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/internal/snapshot"
"github.com/portainer/portainer/api/internal/testhelpers"
+
+ "github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert"
)
@@ -27,13 +28,13 @@ func Test_EndpointList_AgentVersion(t *testing.T) {
GroupID: 1,
Type: portainer.AgentOnDockerEnvironment,
Agent: struct {
- Version string "example:\"1.0.0\""
+ Version string `json:"Version,omitempty" example:"1.0.0"`
}{
Version: "1.0.0",
},
}
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"}}
noVersionEndpoint := portainer.Endpoint{ID: 3, Type: portainer.AgentOnDockerEnvironment, GroupID: 1}
notAgentEnvironments := portainer.Endpoint{ID: 4, Type: portainer.DockerEnvironment, GroupID: 1}
diff --git a/api/http/handler/endpoints/filter_test.go b/api/http/handler/endpoints/filter_test.go
index dc1b10184..27f4aa216 100644
--- a/api/http/handler/endpoints/filter_test.go
+++ b/api/http/handler/endpoints/filter_test.go
@@ -22,12 +22,12 @@ func Test_Filter_AgentVersion(t *testing.T) {
version1Endpoint := portainer.Endpoint{ID: 1, GroupID: 1,
Type: portainer.AgentOnDockerEnvironment,
Agent: struct {
- Version string "example:\"1.0.0\""
+ Version string `json:"Version,omitempty" example:"1.0.0"`
}{Version: "1.0.0"}}
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"}}
noVersionEndpoint := portainer.Endpoint{ID: 3, GroupID: 1,
Type: portainer.AgentOnDockerEnvironment,
diff --git a/api/http/handler/helm/helm_install_test.go b/api/http/handler/helm/helm_install_test.go
index 6b061a16c..5e3904550 100644
--- a/api/http/handler/helm/helm_install_test.go
+++ b/api/http/handler/helm/helm_install_test.go
@@ -2,15 +2,13 @@ package helm
import (
"bytes"
- "encoding/json"
"io"
"net/http"
"net/http/httptest"
"testing"
- "github.com/portainer/portainer/api/datastore"
-
portainer "github.com/portainer/portainer/api"
+ "github.com/portainer/portainer/api/datastore"
"github.com/portainer/portainer/api/exec/exectest"
"github.com/portainer/portainer/api/http/security"
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/options"
"github.com/portainer/portainer/pkg/libhelm/release"
+
+ "github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert"
)
diff --git a/api/http/handler/helm/helm_list_test.go b/api/http/handler/helm/helm_list_test.go
index d05ba7a73..4de16589f 100644
--- a/api/http/handler/helm/helm_list_test.go
+++ b/api/http/handler/helm/helm_list_test.go
@@ -1,7 +1,6 @@
package helm
import (
- "encoding/json"
"io"
"net/http"
"net/http/httptest"
@@ -11,14 +10,15 @@ import (
"github.com/portainer/portainer/api/datastore"
"github.com/portainer/portainer/api/exec/exectest"
"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/kubernetes"
"github.com/portainer/portainer/pkg/libhelm/binary/test"
"github.com/portainer/portainer/pkg/libhelm/options"
"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) {
diff --git a/api/http/handler/hostmanagement/openamt/amtrpc.go b/api/http/handler/hostmanagement/openamt/amtrpc.go
index 07aa71320..ec3c457aa 100644
--- a/api/http/handler/hostmanagement/openamt/amtrpc.go
+++ b/api/http/handler/hostmanagement/openamt/amtrpc.go
@@ -2,7 +2,6 @@ package openamt
import (
"context"
- "encoding/json"
"fmt"
"io"
"net/http"
@@ -20,6 +19,7 @@ import (
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/client"
"github.com/rs/zerolog/log"
+ "github.com/segmentio/encoding/json"
)
type HostInfo struct {
diff --git a/api/http/handler/motd/motd.go b/api/http/handler/motd/motd.go
index 669f6e7b2..dd2112c16 100644
--- a/api/http/handler/motd/motd.go
+++ b/api/http/handler/motd/motd.go
@@ -1,7 +1,6 @@
package motd
import (
- "encoding/json"
"net/http"
"strings"
@@ -9,6 +8,8 @@ import (
"github.com/portainer/portainer/api/http/client"
"github.com/portainer/portainer/pkg/libcrypto"
"github.com/portainer/portainer/pkg/libhttp/response"
+
+ "github.com/segmentio/encoding/json"
)
type motdResponse struct {
diff --git a/api/http/handler/system/version.go b/api/http/handler/system/version.go
index 374f4e0a8..8972627f7 100644
--- a/api/http/handler/system/version.go
+++ b/api/http/handler/system/version.go
@@ -1,7 +1,6 @@
package system
import (
- "encoding/json"
"net/http"
portainer "github.com/portainer/portainer/api"
@@ -11,6 +10,7 @@ import (
"github.com/coreos/go-semver/semver"
"github.com/rs/zerolog/log"
+ "github.com/segmentio/encoding/json"
)
type versionResponse struct {
diff --git a/api/http/handler/system/version_test.go b/api/http/handler/system/version_test.go
index 47a748bf3..f7628fc59 100644
--- a/api/http/handler/system/version_test.go
+++ b/api/http/handler/system/version_test.go
@@ -1,7 +1,6 @@
package system
import (
- "encoding/json"
"fmt"
"io"
"net/http"
@@ -15,6 +14,8 @@ import (
"github.com/portainer/portainer/api/demo"
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/jwt"
+
+ "github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert"
)
diff --git a/api/http/handler/teams/team_list_test.go b/api/http/handler/teams/team_list_test.go
index 063aca097..a94c966cb 100644
--- a/api/http/handler/teams/team_list_test.go
+++ b/api/http/handler/teams/team_list_test.go
@@ -1,7 +1,6 @@
package teams
import (
- "encoding/json"
"fmt"
"io"
"net/http"
@@ -15,6 +14,8 @@ import (
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/internal/authorization"
"github.com/portainer/portainer/api/jwt"
+
+ "github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert"
)
diff --git a/api/http/handler/templates/template_file.go b/api/http/handler/templates/template_file.go
index 043d0d0a1..e56ccc305 100644
--- a/api/http/handler/templates/template_file.go
+++ b/api/http/handler/templates/template_file.go
@@ -1,7 +1,6 @@
package templates
import (
- "encoding/json"
"errors"
"net/http"
@@ -12,6 +11,7 @@ import (
"github.com/asaskevich/govalidator"
"github.com/rs/zerolog/log"
+ "github.com/segmentio/encoding/json"
)
type filePayload struct {
diff --git a/api/http/handler/users/user_create_access_token_test.go b/api/http/handler/users/user_create_access_token_test.go
index 9d33f204c..2c4a54489 100644
--- a/api/http/handler/users/user_create_access_token_test.go
+++ b/api/http/handler/users/user_create_access_token_test.go
@@ -2,7 +2,6 @@ package users
import (
"bytes"
- "encoding/json"
"fmt"
"io"
"net/http"
@@ -15,6 +14,8 @@ import (
"github.com/portainer/portainer/api/datastore"
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/jwt"
+
+ "github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert"
)
@@ -105,7 +106,7 @@ func Test_userCreateAccessToken(t *testing.T) {
body, err := io.ReadAll(rr.Body)
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))
})
}
diff --git a/api/http/handler/users/user_get_access_tokens_test.go b/api/http/handler/users/user_get_access_tokens_test.go
index f07d98e6f..849dc2f11 100644
--- a/api/http/handler/users/user_get_access_tokens_test.go
+++ b/api/http/handler/users/user_get_access_tokens_test.go
@@ -1,7 +1,6 @@
package users
import (
- "encoding/json"
"fmt"
"io"
"net/http"
@@ -14,6 +13,8 @@ import (
"github.com/portainer/portainer/api/datastore"
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/jwt"
+
+ "github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert"
)
diff --git a/api/http/handler/users/user_list_test.go b/api/http/handler/users/user_list_test.go
index 261857c38..41c0a0e09 100644
--- a/api/http/handler/users/user_list_test.go
+++ b/api/http/handler/users/user_list_test.go
@@ -1,7 +1,6 @@
package users
import (
- "encoding/json"
"fmt"
"io"
"net/http"
@@ -17,6 +16,8 @@ import (
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/internal/authorization"
"github.com/portainer/portainer/api/jwt"
+
+ "github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert"
)
diff --git a/api/http/handler/websocket/exec.go b/api/http/handler/websocket/exec.go
index 6a1df05e2..be66e255b 100644
--- a/api/http/handler/websocket/exec.go
+++ b/api/http/handler/websocket/exec.go
@@ -2,20 +2,20 @@ package websocket
import (
"bytes"
- "encoding/json"
- "github.com/portainer/portainer/api/http/security"
- "github.com/rs/zerolog/log"
"net"
"net/http"
"net/http/httputil"
"time"
portainer "github.com/portainer/portainer/api"
+ "github.com/portainer/portainer/api/http/security"
httperror "github.com/portainer/portainer/pkg/libhttp/error"
"github.com/portainer/portainer/pkg/libhttp/request"
"github.com/asaskevich/govalidator"
"github.com/gorilla/websocket"
+ "github.com/rs/zerolog/log"
+ "github.com/segmentio/encoding/json"
)
type execStartOperationPayload struct {
diff --git a/api/http/middlewares/endpoint.go b/api/http/middlewares/endpoint.go
index b2a8a6552..ca9d3fbf8 100644
--- a/api/http/middlewares/endpoint.go
+++ b/api/http/middlewares/endpoint.go
@@ -13,9 +13,7 @@ import (
"github.com/gorilla/mux"
)
-const (
- contextEndpoint = "endpoint"
-)
+const contextEndpoint = "endpoint"
func WithEndpoint(endpointService dataservices.EndpointService, endpointIDParam string) mux.MiddlewareFunc {
return func(next http.Handler) http.Handler {
diff --git a/api/http/proxy/factory/docker/build.go b/api/http/proxy/factory/docker/build.go
index 27f3622d7..ea71ce312 100644
--- a/api/http/proxy/factory/docker/build.go
+++ b/api/http/proxy/factory/docker/build.go
@@ -2,7 +2,6 @@ package docker
import (
"bytes"
- "encoding/json"
"errors"
"io"
"mime"
@@ -11,6 +10,7 @@ import (
"github.com/portainer/portainer/api/archive"
"github.com/rs/zerolog/log"
+ "github.com/segmentio/encoding/json"
)
const OneMegabyte = 1024768
diff --git a/api/http/proxy/factory/docker/containers.go b/api/http/proxy/factory/docker/containers.go
index c137e2606..745359c7b 100644
--- a/api/http/proxy/factory/docker/containers.go
+++ b/api/http/proxy/factory/docker/containers.go
@@ -3,22 +3,21 @@ package docker
import (
"bytes"
"context"
- "encoding/json"
"errors"
"io"
"net/http"
"strings"
- "github.com/docker/docker/client"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/http/proxy/factory/utils"
"github.com/portainer/portainer/api/http/security"
"github.com/portainer/portainer/api/internal/authorization"
+
+ "github.com/docker/docker/client"
+ "github.com/segmentio/encoding/json"
)
-const (
- containerObjectIdentifier = "Id"
-)
+const containerObjectIdentifier = "Id"
func getInheritedResourceControlFromContainerLabels(dockerClient *client.Client, endpointID portainer.EndpointID, containerID string, resourceControls []portainer.ResourceControl) (*portainer.ResourceControl, error) {
container, err := dockerClient.ContainerInspect(context.Background(), containerID)
diff --git a/api/http/proxy/factory/docker/services.go b/api/http/proxy/factory/docker/services.go
index 4df1d316a..4a51311dc 100644
--- a/api/http/proxy/factory/docker/services.go
+++ b/api/http/proxy/factory/docker/services.go
@@ -3,22 +3,20 @@ package docker
import (
"bytes"
"context"
- "encoding/json"
"errors"
"io"
"net/http"
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/client"
-
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/http/proxy/factory/utils"
"github.com/portainer/portainer/api/internal/authorization"
+
+ "github.com/docker/docker/api/types"
+ "github.com/docker/docker/client"
+ "github.com/segmentio/encoding/json"
)
-const (
- serviceObjectIdentifier = "ID"
-)
+const serviceObjectIdentifier = "ID"
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{})
diff --git a/api/http/proxy/factory/docker/transport.go b/api/http/proxy/factory/docker/transport.go
index a7bc06f4c..61ab1c711 100644
--- a/api/http/proxy/factory/docker/transport.go
+++ b/api/http/proxy/factory/docker/transport.go
@@ -3,7 +3,6 @@ package docker
import (
"bytes"
"encoding/base64"
- "encoding/json"
"errors"
"fmt"
"io"
@@ -15,12 +14,13 @@ import (
portainer "github.com/portainer/portainer/api"
"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/security"
"github.com/portainer/portainer/api/internal/authorization"
+ dockerclient "github.com/portainer/portainer/api/docker/client"
"github.com/rs/zerolog/log"
+ "github.com/segmentio/encoding/json"
)
var apiVersionRe = regexp.MustCompile(`(/v[0-9]\.[0-9]*)?`)
diff --git a/api/http/proxy/factory/kubernetes/transport.go b/api/http/proxy/factory/kubernetes/transport.go
index 2de13c695..c77fb97b4 100644
--- a/api/http/proxy/factory/kubernetes/transport.go
+++ b/api/http/proxy/factory/kubernetes/transport.go
@@ -2,7 +2,6 @@ package kubernetes
import (
"bytes"
- "encoding/json"
"fmt"
"io"
"net/http"
@@ -18,6 +17,7 @@ import (
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
+ "github.com/segmentio/encoding/json"
)
type baseTransport struct {
diff --git a/api/http/proxy/factory/utils/json.go b/api/http/proxy/factory/utils/json.go
index 7f215a685..b29aa8550 100644
--- a/api/http/proxy/factory/utils/json.go
+++ b/api/http/proxy/factory/utils/json.go
@@ -2,12 +2,12 @@ package utils
import (
"compress/gzip"
- "encoding/json"
"errors"
"fmt"
"io"
"mime"
+ "github.com/segmentio/encoding/json"
"gopkg.in/yaml.v3"
)
diff --git a/api/internal/registryutils/auth_header.go b/api/internal/registryutils/auth_header.go
index 0676a367d..ce09f1e00 100644
--- a/api/internal/registryutils/auth_header.go
+++ b/api/internal/registryutils/auth_header.go
@@ -2,18 +2,17 @@ package registryutils
import (
"encoding/base64"
- "encoding/json"
portainer "github.com/portainer/portainer/api"
+
+ "github.com/segmentio/encoding/json"
)
-type (
- authHeader struct {
- Username string `json:"username"`
- Password string `json:"password"`
- ServerAddress string `json:"serveraddress"`
- }
-)
+type authHeader struct {
+ Username string `json:"username"`
+ Password string `json:"password"`
+ ServerAddress string `json:"serveraddress"`
+}
// GetRegistryAuthHeader generate the X-Registry-Auth header from registry
func GetRegistryAuthHeader(registry *portainer.Registry) (header string, err error) {
diff --git a/api/kubernetes/cli/access.go b/api/kubernetes/cli/access.go
index 20a8e070e..3d306447c 100644
--- a/api/kubernetes/cli/access.go
+++ b/api/kubernetes/cli/access.go
@@ -2,10 +2,11 @@ package cli
import (
"context"
- "encoding/json"
+
+ portainer "github.com/portainer/portainer/api"
"github.com/pkg/errors"
- portainer "github.com/portainer/portainer/api"
+ "github.com/segmentio/encoding/json"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
diff --git a/api/kubernetes/cli/metrics.go b/api/kubernetes/cli/metrics.go
index 669ce27b3..6b1b85049 100644
--- a/api/kubernetes/cli/metrics.go
+++ b/api/kubernetes/cli/metrics.go
@@ -2,9 +2,10 @@ package cli
import (
"context"
- "encoding/json"
models "github.com/portainer/portainer/api/http/models/kubernetes"
+
+ "github.com/segmentio/encoding/json"
)
func (kcl *KubeClient) GetMetrics() (models.K8sMetrics, error) {
diff --git a/api/kubernetes/cli/registries.go b/api/kubernetes/cli/registries.go
index f58c65eba..5fc261ce0 100644
--- a/api/kubernetes/cli/registries.go
+++ b/api/kubernetes/cli/registries.go
@@ -2,13 +2,14 @@ package cli
import (
"context"
- "encoding/json"
"fmt"
"strconv"
- "github.com/pkg/errors"
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/internal/registryutils"
+
+ "github.com/pkg/errors"
+ "github.com/segmentio/encoding/json"
v1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
diff --git a/api/oauth/oauth.go b/api/oauth/oauth.go
index 3f15f8f92..678c2fff8 100644
--- a/api/oauth/oauth.go
+++ b/api/oauth/oauth.go
@@ -2,7 +2,6 @@ package oauth
import (
"context"
- "encoding/json"
"io"
"mime"
"net/http"
@@ -14,6 +13,7 @@ import (
"github.com/golang-jwt/jwt/v4"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
+ "github.com/segmentio/encoding/json"
"golang.org/x/oauth2"
)
diff --git a/api/oauth/oauthtest/oauth_server.go b/api/oauth/oauthtest/oauth_server.go
index 62ae0823e..ab3d8b9f2 100644
--- a/api/oauth/oauthtest/oauth_server.go
+++ b/api/oauth/oauthtest/oauth_server.go
@@ -1,19 +1,18 @@
package oauthtest
import (
- "encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"strings"
- "github.com/gorilla/mux"
portainer "github.com/portainer/portainer/api"
+
+ "github.com/gorilla/mux"
+ "github.com/segmentio/encoding/json"
)
-const (
- AccessToken = "test-token"
-)
+const AccessToken = "test-token"
// OAuthRoutes is an OAuth 2.0 compliant handler
func OAuthRoutes(code string, config *portainer.OAuthSettings) http.Handler {
diff --git a/api/portainer.go b/api/portainer.go
index dfc7ac369..647623c11 100644
--- a/api/portainer.go
+++ b/api/portainer.go
@@ -171,7 +171,7 @@ type (
// User identifier who created this template
CreatedByUserID UserID `json:"CreatedByUserId" example:"3"`
// A note that will be displayed in the UI. Supports HTML content
- Note string `json:"Note" example:"This is my custom template"`
+ Note string `json:"Note,omitempty" example:"This is my custom template"`
// Platform associated to the template.
// Valid values are: 1 - 'linux', 2 - 'windows'
Platform CustomTemplatePlatform `json:"Platform" example:"1" enums:"1,2"`
@@ -182,11 +182,11 @@ type (
// * 2 - compose
// * 3 - kubernetes
Type StackType `json:"Type" example:"1" enums:"1,2,3"`
- ResourceControl *ResourceControl `json:"ResourceControl"`
+ ResourceControl *ResourceControl `json:"ResourceControl,omitempty"`
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 bool `example:"false"`
+ IsComposeFormat bool `json:"IsComposeFormat,omitempty" example:"false"`
}
// CustomTemplateID represents a custom template identifier
@@ -249,10 +249,10 @@ type (
// EdgeGroup Identifier
ID EdgeGroupID `json:"Id" example:"1"`
Name string `json:"Name"`
- Dynamic bool `json:"Dynamic"`
+ Dynamic bool `json:"Dynamic,omitempty"`
TagIDs []TagID `json:"TagIds"`
Endpoints []EndpointID `json:"Endpoints"`
- PartialMatch bool `json:"PartialMatch"`
+ PartialMatch bool `json:"PartialMatch,omitempty"`
}
// EdgeGroupID represents an Edge group identifier
@@ -268,7 +268,7 @@ type (
EdgeGroups []EdgeGroupID `json:"EdgeGroups"`
Name string `json:"Name"`
ScriptPath string `json:"ScriptPath"`
- Recurring bool `json:"Recurring"`
+ Recurring bool `json:"Recurring,omitempty"`
Version int `json:"Version"`
// 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 struct {
LogsStatus EdgeJobLogsStatus
- CollectLogs bool
+ CollectLogs bool `json:"CollectLogs,omitempty"`
}
// EdgeJobID represents an Edge job identifier
@@ -325,10 +325,10 @@ type (
ManifestPath string
DeploymentType EdgeStackDeploymentType
// Uses the manifest's namespaces instead of the default one
- UseManifestNamespaces bool
+ UseManifestNamespaces bool `json:"UseManifestNamespaces,omitempty"`
// Deprecated
- Prune bool `json:"Prune"`
+ Prune bool `json:"Prune,omitempty"`
}
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).
Type EndpointType `json:"Type" example:"1"`
// 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
GroupID EndpointGroupID `json:"GroupId" example:"1"`
// 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"`
TLSConfig TLSConfiguration `json:"TLSConfig"`
AzureCredentials AzureCredentials `json:"AzureCredentials,omitempty"`
@@ -413,7 +413,7 @@ type (
// The identifier of the edge agent associated with this environment(endpoint)
EdgeID string `json:"EdgeID,omitempty"`
// 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)
EdgeCheckinInterval int `json:"EdgeCheckinInterval" example:"5"`
// Associated Kubernetes data
@@ -425,14 +425,14 @@ type (
// The identifier of the AMT Device associated with this environment(endpoint)
AMTDeviceGUID string `json:"AMTDeviceGUID,omitempty" example:"4c4c4544-004b-3910-8037-b6c04f504633"`
// LastCheckInDate mark last check-in date on checkin
- LastCheckInDate int64
+ LastCheckInDate int64 `json:"LastCheckInDate,omitempty"`
// 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 bool `json:"Heartbeat" example:"true"`
+ Heartbeat bool `json:"Heartbeat,omitempty" example:"true"`
// 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".
PostInitMigrations EndpointPostInitMigrations `json:"PostInitMigrations"`
@@ -440,10 +440,10 @@ type (
Edge EnvironmentEdgeSettings
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 in DBVersion == 4
@@ -460,18 +460,18 @@ type (
Tags []string `json:"Tags"`
// Deprecated v2.18
- IsEdgeDevice bool
+ IsEdgeDevice bool `json:"IsEdgeDevice,omitempty"`
}
EnvironmentEdgeSettings struct {
// 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]
- 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]
- 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]
- CommandInterval int `json:"CommandInterval" example:"60"`
+ CommandInterval int `json:"CommandInterval,omitempty" example:"60"`
}
// EndpointAuthorizations represents the authorizations associated to a set of environments(endpoints)
@@ -486,7 +486,7 @@ type (
// Environment(Endpoint) group name
Name string `json:"Name" example:"my-environment-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"`
TeamAccessPolicies TeamAccessPolicies `json:"TeamAccessPolicies"`
// List of tags associated to this environment(endpoint) group
@@ -500,7 +500,7 @@ type (
AuthorizedTeams []TeamID `json:"AuthorizedTeams"`
// Deprecated in DBVersion == 22
- Tags []string `json:"Tags"`
+ Tags []string `json:"Tags,omitempty"`
}
// EndpointGroupID represents an environment(endpoint) group identifier
@@ -519,23 +519,23 @@ type (
// EndpointSecuritySettings represents settings for an environment(endpoint)
EndpointSecuritySettings struct {
// 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
- AllowPrivilegedModeForRegularUsers bool `json:"allowPrivilegedModeForRegularUsers" example:"false"`
+ AllowPrivilegedModeForRegularUsers bool `json:"allowPrivilegedModeForRegularUsers,omitempty" example:"false"`
// 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
- AllowHostNamespaceForRegularUsers bool `json:"allowHostNamespaceForRegularUsers" example:"true"`
+ AllowHostNamespaceForRegularUsers bool `json:"allowHostNamespaceForRegularUsers,omitempty" example:"true"`
// 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
- AllowStackManagementForRegularUsers bool `json:"allowStackManagementForRegularUsers" example:"true"`
+ AllowStackManagementForRegularUsers bool `json:"allowStackManagementForRegularUsers,omitempty" example:"true"`
// 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
- AllowSysctlSettingForRegularUsers bool `json:"allowSysctlSettingForRegularUsers" example:"true"`
+ AllowSysctlSettingForRegularUsers bool `json:"allowSysctlSettingForRegularUsers,omitempty" example:"true"`
// 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)
@@ -549,15 +549,15 @@ type (
// EndpointPostInitMigrations
EndpointPostInitMigrations struct {
- MigrateIngresses bool `json:"MigrateIngresses"`
- MigrateGPUs bool `json:"MigrateGPUs"`
+ MigrateIngresses bool `json:"MigrateIngresses,omitempty"`
+ MigrateGPUs bool `json:"MigrateGPUs,omitempty"`
}
// Extension represents a deprecated Portainer extension
Extension struct {
// Extension Identifier
ID ExtensionID `json:"Id" example:"1"`
- Enabled bool `json:"Enabled"`
+ Enabled bool `json:"Enabled,omitempty"`
Name string `json:"Name,omitempty"`
ShortDescription string `json:"ShortDescription,omitempty"`
Description string `json:"Description,omitempty"`
@@ -598,7 +598,7 @@ type (
// QuayRegistryData represents data required for Quay registry to work
QuayRegistryData struct {
- UseOrganisation bool `json:"UseOrganisation"`
+ UseOrganisation bool `json:"UseOrganisation,omitempty"`
OrganisationName string `json:"OrganisationName"`
}
@@ -611,13 +611,13 @@ type (
JobType int
K8sNamespaceInfo struct {
- IsSystem bool `json:"IsSystem"`
- IsDefault bool `json:"IsDefault"`
+ IsSystem bool `json:"IsSystem,omitempty"`
+ IsDefault bool `json:"IsDefault,omitempty"`
}
K8sNodeLimits struct {
- CPU int64 `json:"CPU"`
- Memory int64 `json:"Memory"`
+ CPU int64 `json:"CPU,omitempty"`
+ Memory int64 `json:"Memory,omitempty"`
}
K8sNodesLimits map[string]*K8sNodeLimits
@@ -637,9 +637,9 @@ type (
// KubernetesFlags are used to detect if we need to run initial cluster
// detection again.
KubernetesFlags struct {
- IsServerMetricsDetected bool `json:"IsServerMetricsDetected"`
- IsServerIngressClassDetected bool `json:"IsServerIngressClassDetected"`
- IsServerStorageDetected bool `json:"IsServerStorageDetected"`
+ IsServerMetricsDetected bool `json:"IsServerMetricsDetected,omitempty"`
+ IsServerIngressClassDetected bool `json:"IsServerIngressClassDetected,omitempty"`
+ IsServerStorageDetected bool `json:"IsServerStorageDetected,omitempty"`
}
// 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 struct {
- UseLoadBalancer bool `json:"UseLoadBalancer"`
- UseServerMetrics bool `json:"UseServerMetrics"`
- EnableResourceOverCommit bool `json:"EnableResourceOverCommit"`
- ResourceOverCommitPercentage int `json:"ResourceOverCommitPercentage"`
+ UseLoadBalancer bool `json:"UseLoadBalancer,omitempty"`
+ UseServerMetrics bool `json:"UseServerMetrics,omitempty"`
+ EnableResourceOverCommit bool `json:"EnableResourceOverCommit,omitempty"`
+ ResourceOverCommitPercentage int `json:"ResourceOverCommitPercentage,omitempty"`
StorageClasses []KubernetesStorageClassConfig `json:"StorageClasses"`
IngressClasses []KubernetesIngressClassConfig `json:"IngressClasses"`
- RestrictDefaultNamespace bool `json:"RestrictDefaultNamespace"`
- IngressAvailabilityPerNamespace bool `json:"IngressAvailabilityPerNamespace"`
- AllowNoneIngressClass bool `json:"AllowNoneIngressClass"`
+ RestrictDefaultNamespace bool `json:"RestrictDefaultNamespace,omitempty"`
+ IngressAvailabilityPerNamespace bool `json:"IngressAvailabilityPerNamespace,omitempty"`
+ AllowNoneIngressClass bool `json:"AllowNoneIngressClass,omitempty"`
}
// KubernetesStorageClassConfig represents a Kubernetes Storage Class configuration
@@ -669,14 +669,14 @@ type (
Name string `json:"Name"`
AccessModes []string `json:"AccessModes"`
Provisioner string `json:"Provisioner"`
- AllowVolumeExpansion bool `json:"AllowVolumeExpansion"`
+ AllowVolumeExpansion bool `json:"AllowVolumeExpansion,omitempty"`
}
// KubernetesIngressClassConfig represents a Kubernetes Ingress Class configuration
KubernetesIngressClassConfig struct {
Name string `json:"Name"`
Type string `json:"Type"`
- GloballyBlocked bool `json:"Blocked"`
+ GloballyBlocked bool `json:"Blocked,omitempty"`
BlockedNamespaces []string `json:"BlockedNamespaces"`
}
@@ -690,7 +690,7 @@ type (
// InternalAuthSettings represents settings used for the default 'internal' authentication
InternalAuthSettings struct {
- RequiredPasswordLength int
+ RequiredPasswordLength int `json:"RequiredPasswordLength,omitempty"`
}
// 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
GroupBaseDN string `json:"GroupBaseDN" example:"dc=ldap,dc=domain,dc=tld"`
// 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
GroupAttribute string `json:"GroupAttribute" example:"member"`
}
@@ -716,7 +716,7 @@ type (
// LDAPSettings represents the settings used to connect to a LDAP server
LDAPSettings struct {
// 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
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
@@ -725,11 +725,11 @@ type (
URL string `json:"URL" example:"myldap.domain.tld:389" validate:"hostname_port"`
TLSConfig TLSConfiguration `json:"TLSConfig"`
// Whether LDAP connection should use StartTLS
- StartTLS bool `json:"StartTLS" example:"true"`
+ StartTLS bool `json:"StartTLS,omitempty" example:"true"`
SearchSettings []LDAPSearchSettings `json:"SearchSettings"`
GroupSearchSettings []LDAPGroupSearchSettings `json:"GroupSearchSettings"`
// 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
@@ -769,7 +769,7 @@ type (
// Pair defines a key/value string pair
Pair struct {
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
@@ -782,13 +782,13 @@ type (
// Registry Name
Name string `json:"Name" example:"my-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
- 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
- Authentication bool `json:"Authentication" example:"true"`
+ Authentication bool `json:"Authentication,omitempty" example:"true"`
// 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 string `json:"Password,omitempty" example:"registry_password"`
ManagementConfiguration *RegistryManagementConfiguration `json:"ManagementConfiguration"`
@@ -828,9 +828,9 @@ type (
// the registry API via the registry management extension.
RegistryManagementConfiguration struct {
Type RegistryType `json:"Type"`
- Authentication bool `json:"Authentication"`
- Username string `json:"Username"`
- Password string `json:"Password"`
+ Authentication bool `json:"Authentication,omitempty"`
+ Username string `json:"Username,omitempty"`
+ Password string `json:"Password,omitempty"`
TLSConfig TLSConfiguration `json:"TLSConfig"`
Ecr EcrData `json:"Ecr"`
AccessToken string `json:"AccessToken,omitempty"`
@@ -860,8 +860,8 @@ type (
// Permit access to the associated resource to any user
Public bool `json:"Public" example:"true"`
// Permit access to resource only to admins
- AdministratorsOnly bool `json:"AdministratorsOnly" example:"true"`
- System bool `json:"System"`
+ AdministratorsOnly bool `json:"AdministratorsOnly,omitempty" example:"true"`
+ System bool `json:"System,omitempty"`
// Deprecated fields
// Deprecated in DBVersion == 2
@@ -883,10 +883,10 @@ type (
// Role name
Name string `json:"Name" example:"HelpDesk"`
// 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 Authorizations `json:"Authorizations"`
- Priority int `json:"Priority"`
+ Priority int `json:"Priority,omitempty"`
}
// RoleID represents a role identifier
@@ -899,7 +899,7 @@ type (
APIKey struct {
ID APIKeyID `json:"id" 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)
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
@@ -916,10 +916,10 @@ type (
ID ScheduleID `json:"Id" example:"1"`
Name string
CronExpression string
- Recurring bool
+ Recurring bool `json:"Recurring,omitempty"`
Created int64
JobType JobType
- EdgeSchedule *EdgeSchedule
+ EdgeSchedule *EdgeSchedule `json:"EdgeSchedule,omitempty"`
}
// ScheduleID represents a schedule identifier.
@@ -931,18 +931,18 @@ type (
Endpoints []EndpointID
Image string
ScriptPath string
- RetryCount int
- RetryInterval int
+ RetryCount int `json:"RetryCount,omitempty"`
+ RetryInterval int `json:"RetryInterval,omitempty"`
}
GlobalDeploymentOptions struct {
- HideStacksFunctionality bool `json:"hideStacksFunctionality" example:"false"`
+ HideStacksFunctionality bool `json:"hideStacksFunctionality,omitempty" example:"false"`
}
// Settings represents the application settings
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
- 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
BlackListedLabels []Pair `json:"BlackListedLabels"`
// 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)
EdgeAgentCheckinInterval int `json:"EdgeAgentCheckinInterval" example:"5"`
// 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
- EnableEdgeComputeFeatures bool `json:"EnableEdgeComputeFeatures"`
+ EnableEdgeComputeFeatures bool `json:"EnableEdgeComputeFeatures,omitempty"`
// The duration of a user session
UserSessionTimeout string `json:"UserSessionTimeout" example:"5m"`
// The expiry of a Kubeconfig
KubeconfigExpiry string `json:"KubeconfigExpiry" example:"24h"`
// 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"
HelmRepositoryURL string `json:"HelmRepositoryURL" example:"https://charts.bitnami.com/bitnami"`
// KubectlImage, defaults to portainer/kubectl-shell
KubectlShellImage string `json:"KubectlShellImage" example:"portainer/kubectl-shell"`
// 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 bool `json:"EnforceEdgeID" example:"false"`
+ EnforceEdgeID bool `json:"EnforceEdgeID,omitempty" example:"false"`
// 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 string `json:"EdgePortainerUrl"`
+ EdgePortainerURL string `json:"EdgePortainerUrl,omitempty"`
Edge struct {
// The command list interval for edge agent - used in edge async mode (in seconds)
@@ -997,20 +997,20 @@ type (
}
// Deprecated fields
- DisplayDonationHeader bool
- DisplayExternalContributors bool
+ DisplayDonationHeader bool `json:"DisplayDonationHeader,omitempty"`
+ DisplayExternalContributors bool `json:"DisplayExternalContributors,omitempty"`
// Deprecated fields v26
- EnableHostManagementFeatures bool `json:"EnableHostManagementFeatures"`
- AllowVolumeBrowserForRegularUsers bool `json:"AllowVolumeBrowserForRegularUsers"`
- AllowBindMountsForRegularUsers bool `json:"AllowBindMountsForRegularUsers"`
- AllowPrivilegedModeForRegularUsers bool `json:"AllowPrivilegedModeForRegularUsers"`
- AllowHostNamespaceForRegularUsers bool `json:"AllowHostNamespaceForRegularUsers"`
- AllowStackManagementForRegularUsers bool `json:"AllowStackManagementForRegularUsers"`
- AllowDeviceMappingForRegularUsers bool `json:"AllowDeviceMappingForRegularUsers"`
- AllowContainerCapabilitiesForRegularUsers bool `json:"AllowContainerCapabilitiesForRegularUsers"`
+ EnableHostManagementFeatures bool `json:"EnableHostManagementFeatures,omitempty"`
+ AllowVolumeBrowserForRegularUsers bool `json:"AllowVolumeBrowserForRegularUsers,omitempty"`
+ AllowBindMountsForRegularUsers bool `json:"AllowBindMountsForRegularUsers,omitempty"`
+ AllowPrivilegedModeForRegularUsers bool `json:"AllowPrivilegedModeForRegularUsers,omitempty"`
+ AllowHostNamespaceForRegularUsers bool `json:"AllowHostNamespaceForRegularUsers,omitempty"`
+ AllowStackManagementForRegularUsers bool `json:"AllowStackManagementForRegularUsers,omitempty"`
+ AllowDeviceMappingForRegularUsers bool `json:"AllowDeviceMappingForRegularUsers,omitempty"`
+ 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
@@ -1021,10 +1021,10 @@ type (
// SSLSettings represents a pair of SSL certificate and key
SSLSettings struct {
- CertPath string `json:"certPath"`
- KeyPath string `json:"keyPath"`
- SelfSigned bool `json:"selfSigned"`
- HTTPEnabled bool `json:"httpEnabled"`
+ CertPath string `json:"certPath,omitempty"`
+ KeyPath string `json:"keyPath,omitempty"`
+ SelfSigned bool `json:"selfSigned,omitempty"`
+ HTTPEnabled bool `json:"httpEnabled,omitempty"`
}
// 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
EndpointID EndpointID `json:"EndpointId" example:"1"`
// 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
EntryPoint string `json:"EntryPoint" example:"docker-compose.yml"`
// A list of environment(endpoint) variables used during stack deployment
Env []Pair `json:"Env"`
//
- ResourceControl *ResourceControl `json:"ResourceControl"`
+ ResourceControl *ResourceControl `json:"ResourceControl,omitempty"`
// Stack status (1 - active, 2 - inactive)
Status StackStatus `json:"Status" example:"1"`
// Path on disk to the repository hosting the Stack file
@@ -1060,23 +1060,23 @@ type (
// Only applies when deploying stack with multiple files
AdditionalFiles []string `json:"AdditionalFiles"`
// The GitOps update settings of a git stack
- AutoUpdate *AutoUpdateSettings `json:"AutoUpdate"`
+ AutoUpdate *AutoUpdateSettings `json:"AutoUpdate,omitempty"`
// The stack deployment option
- Option *StackOption `json:"Option"`
+ Option *StackOption `json:"Option,omitempty"`
// The git config of this stack
- GitConfig *gittypes.RepoConfig
+ GitConfig *gittypes.RepoConfig `json:"GitConfig,omitempty"`
// 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
- 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 bool `example:"false"`
+ IsComposeFormat bool `json:"IsComposeFormat,omitempty" example:"false"`
}
// StackOption represents the options for stack deployment
StackOption struct {
// 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)
@@ -1159,9 +1159,9 @@ type (
// Title of the template
Title string `json:"title" example:"Nginx"`
// 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
- AdministratorOnly bool `json:"administrator_only" example:"true"`
+ AdministratorOnly bool `json:"administrator_only,omitempty" example:"true"`
// Mandatory container fields
// 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
Value string `json:"value" example:"value"`
// 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
@@ -1267,9 +1267,9 @@ type (
// TLSConfiguration represents a TLS configuration
TLSConfiguration struct {
// Use TLS
- TLS bool `json:"TLS" example:"true"`
+ TLS bool `json:"TLS,omitempty" example:"true"`
// 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
TLSCACertPath string `json:"TLSCACert,omitempty" example:"/data/tls/ca.pem"`
// Path to the TLS client certificate file
@@ -1287,7 +1287,7 @@ type (
ID UserID
Username string
Role UserRole
- ForceChangePassword bool
+ ForceChangePassword bool `json:"ForceChangePassword,omitempty"`
Token string
}
@@ -1302,7 +1302,7 @@ type (
// TunnelServerInfo represents information associated to the tunnel server
TunnelServerInfo struct {
- PrivateKeySeed string `json:"PrivateKeySeed"`
+ PrivateKeySeed string `json:"PrivateKeySeed,omitempty"`
}
// User represents a user account
@@ -1319,7 +1319,7 @@ type (
// Deprecated fields
// Deprecated
- UserTheme string `example:"dark"`
+ UserTheme string `json:"UserTheme,omitempty" example:"dark"`
// Deprecated in DBVersion == 25
PortainerAuthorizations Authorizations
// Deprecated in DBVersion == 25
@@ -1345,7 +1345,7 @@ type (
// UserThemeSettings represents the theme settings for a user
UserThemeSettings struct {
// 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
@@ -1368,8 +1368,8 @@ type (
Snapshot struct {
EndpointID EndpointID `json:"EndpointId"`
- Docker *DockerSnapshot `json:"Docker"`
- Kubernetes *KubernetesSnapshot `json:"Kubernetes"`
+ Docker *DockerSnapshot `json:"Docker,omitempty"`
+ Kubernetes *KubernetesSnapshot `json:"Kubernetes,omitempty"`
}
// CLIService represents a service for managing CLI
diff --git a/api/stacks/deployments/deployer_remote.go b/api/stacks/deployments/deployer_remote.go
index 8b1ab4c5d..33bec796e 100644
--- a/api/stacks/deployments/deployer_remote.go
+++ b/api/stacks/deployments/deployer_remote.go
@@ -3,7 +3,6 @@ package deployments
import (
"bytes"
"context"
- "encoding/json"
"fmt"
"io"
"math/rand"
@@ -11,16 +10,17 @@ import (
"strings"
"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/container"
"github.com/docker/docker/api/types/swarm"
+ dockerclient "github.com/docker/docker/client"
"github.com/docker/docker/pkg/stdcopy"
"github.com/pkg/errors"
- portainer "github.com/portainer/portainer/api"
- "github.com/portainer/portainer/api/filesystem"
"github.com/rs/zerolog/log"
-
- dockerclient "github.com/docker/docker/client"
+ "github.com/segmentio/encoding/json"
)
const (
diff --git a/go.mod b/go.mod
index 160628b61..ea9f1cbf1 100644
--- a/go.mod
+++ b/go.mod
@@ -31,7 +31,6 @@ require (
github.com/hashicorp/golang-lru v0.5.4
github.com/joho/godotenv v1.4.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/opencontainers/go-digest 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/robfig/cron/v3 v3.0.1
github.com/rs/zerolog v1.29.0
+ github.com/segmentio/encoding v0.3.6
github.com/stretchr/testify v1.8.2
github.com/viney-shih/go-lock v1.1.1
go.etcd.io/bbolt v1.3.7
@@ -106,6 +106,7 @@ require (
github.com/jpillora/ansi v1.0.3 // indirect
github.com/jpillora/requestlog 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/klauspost/compress v1.16.3 // 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/runtime-spec v1.1.0-rc.1 // 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/sirupsen/logrus v1.9.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
diff --git a/go.sum b/go.sum
index c8e0cfa90..faf6527e5 100644
--- a/go.sum
+++ b/go.sum
@@ -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/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/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/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
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-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-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-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
diff --git a/pkg/libhelm/binary/install.go b/pkg/libhelm/binary/install.go
index dbd2e5dd0..937df1500 100644
--- a/pkg/libhelm/binary/install.go
+++ b/pkg/libhelm/binary/install.go
@@ -1,11 +1,11 @@
package binary
import (
- "encoding/json"
-
- "github.com/pkg/errors"
"github.com/portainer/portainer/pkg/libhelm/options"
"github.com/portainer/portainer/pkg/libhelm/release"
+
+ "github.com/pkg/errors"
+ "github.com/segmentio/encoding/json"
)
// Install runs `helm install` with specified install options.
diff --git a/pkg/libhelm/binary/list.go b/pkg/libhelm/binary/list.go
index 7859c77f4..886d4c5ea 100644
--- a/pkg/libhelm/binary/list.go
+++ b/pkg/libhelm/binary/list.go
@@ -1,11 +1,11 @@
package binary
import (
- "encoding/json"
-
- "github.com/pkg/errors"
"github.com/portainer/portainer/pkg/libhelm/options"
"github.com/portainer/portainer/pkg/libhelm/release"
+
+ "github.com/pkg/errors"
+ "github.com/segmentio/encoding/json"
)
// List runs `helm list --output json --filter --selector --namespace ` with specified list options.
diff --git a/pkg/libhelm/binary/search_repo.go b/pkg/libhelm/binary/search_repo.go
index cbe524c75..81ebd172e 100644
--- a/pkg/libhelm/binary/search_repo.go
+++ b/pkg/libhelm/binary/search_repo.go
@@ -4,15 +4,16 @@ package binary
// The functionality does not rely on the implementation of `HelmPackageManager`
import (
- "encoding/json"
"fmt"
"net/http"
"net/url"
"path"
"time"
- "github.com/pkg/errors"
"github.com/portainer/portainer/pkg/libhelm/options"
+
+ "github.com/pkg/errors"
+ "github.com/segmentio/encoding/json"
"gopkg.in/yaml.v3"
)
diff --git a/pkg/libhelm/binary/test/mock.go b/pkg/libhelm/binary/test/mock.go
index 06c9e9105..e019ee248 100644
--- a/pkg/libhelm/binary/test/mock.go
+++ b/pkg/libhelm/binary/test/mock.go
@@ -1,13 +1,14 @@
package test
import (
- "encoding/json"
"strings"
- "github.com/pkg/errors"
"github.com/portainer/portainer/pkg/libhelm"
"github.com/portainer/portainer/pkg/libhelm/options"
"github.com/portainer/portainer/pkg/libhelm/release"
+
+ "github.com/pkg/errors"
+ "github.com/segmentio/encoding/json"
"gopkg.in/yaml.v3"
)
diff --git a/pkg/libhelm/time/time_test.go b/pkg/libhelm/time/time_test.go
index 20f0f8e29..9de753f05 100644
--- a/pkg/libhelm/time/time_test.go
+++ b/pkg/libhelm/time/time_test.go
@@ -17,9 +17,10 @@ limitations under the License.
package time
import (
- "encoding/json"
"testing"
"time"
+
+ "github.com/segmentio/encoding/json"
)
var (
diff --git a/pkg/libhttp/error/error.go b/pkg/libhttp/error/error.go
index 929e4570e..a7b307198 100644
--- a/pkg/libhttp/error/error.go
+++ b/pkg/libhttp/error/error.go
@@ -2,11 +2,11 @@
package error
import (
- "encoding/json"
"errors"
"net/http"
"github.com/rs/zerolog/log"
+ "github.com/segmentio/encoding/json"
)
type (
@@ -36,7 +36,11 @@ func writeErrorResponse(rw http.ResponseWriter, err *HandlerError) {
rw.Header().Set("Content-Type", "application/json")
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.
diff --git a/pkg/libhttp/request/payload.go b/pkg/libhttp/request/payload.go
index 9e563ddd2..19192c3c5 100644
--- a/pkg/libhttp/request/payload.go
+++ b/pkg/libhttp/request/payload.go
@@ -1,10 +1,10 @@
package request
import (
- "encoding/json"
"net/http"
"github.com/pkg/errors"
+ "github.com/segmentio/encoding/json"
)
// PayloadValidation is an interface used to validate the payload of a request.
diff --git a/pkg/libhttp/request/payload_test.go b/pkg/libhttp/request/payload_test.go
index 4f107c2f9..66408f9a7 100644
--- a/pkg/libhttp/request/payload_test.go
+++ b/pkg/libhttp/request/payload_test.go
@@ -2,13 +2,13 @@ package request_test
import (
"bytes"
- "encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/portainer/portainer/pkg/libhttp/request"
+ "github.com/segmentio/encoding/json"
"github.com/stretchr/testify/assert"
)
diff --git a/pkg/libhttp/request/request.go b/pkg/libhttp/request/request.go
index e5c2ed5fc..83c4876fe 100644
--- a/pkg/libhttp/request/request.go
+++ b/pkg/libhttp/request/request.go
@@ -4,13 +4,13 @@
package request
import (
- "encoding/json"
"errors"
"io/ioutil"
"net/http"
"strconv"
"github.com/gorilla/mux"
+ "github.com/segmentio/encoding/json"
)
const (
diff --git a/pkg/libhttp/response/response.go b/pkg/libhttp/response/response.go
index 3a5bddfb7..250a9859d 100644
--- a/pkg/libhttp/response/response.go
+++ b/pkg/libhttp/response/response.go
@@ -2,12 +2,13 @@
package response
import (
- "encoding/json"
"errors"
"fmt"
"net/http"
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
@@ -15,7 +16,11 @@ import (
func JSON(rw http.ResponseWriter, data interface{}) *httperror.HandlerError {
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 {
return httperror.InternalServerError("Unable to write JSON response", err)
}
diff --git a/pkg/libstack/compose/internal/composeplugin/status.go b/pkg/libstack/compose/internal/composeplugin/status.go
index 4b6d9299d..ab06a8ac5 100644
--- a/pkg/libstack/compose/internal/composeplugin/status.go
+++ b/pkg/libstack/compose/internal/composeplugin/status.go
@@ -2,12 +2,13 @@ package composeplugin
import (
"context"
- "encoding/json"
"fmt"
"time"
"github.com/portainer/portainer/pkg/libstack"
+
"github.com/rs/zerolog/log"
+ "github.com/segmentio/encoding/json"
)
type publisher struct {