Skip to content

Commit

Permalink
chore(code): clean up the code EE-7251 (#11948)
Browse files Browse the repository at this point in the history
  • Loading branch information
andres-portainer committed Jun 18, 2024
1 parent be9d328 commit bfa27d9
Show file tree
Hide file tree
Showing 49 changed files with 325 additions and 355 deletions.
26 changes: 14 additions & 12 deletions api/database/boltdb/db.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"math"
"os"
"path"
"strconv"
"time"

portainer "github.com/portainer/portainer/api"
Expand Down Expand Up @@ -73,7 +74,6 @@ func (connection *DbConnection) IsEncryptedStore() bool {
// NeedsEncryptionMigration returns true if database encryption is enabled and
// we have an un-encrypted DB that requires migration to an encrypted DB
func (connection *DbConnection) NeedsEncryptionMigration() (bool, error) {

// Cases: Note, we need to check both portainer.db and portainer.edb
// to determine if it's a new store. We only need to differentiate between cases 2,3 and 5

Expand Down Expand Up @@ -121,11 +121,11 @@ func (connection *DbConnection) NeedsEncryptionMigration() (bool, error) {

// Open opens and initializes the BoltDB database.
func (connection *DbConnection) Open() error {

log.Info().Str("filename", connection.GetDatabaseFileName()).Msg("loading PortainerDB")

// Now we open the db
databasePath := connection.GetDatabaseFilePath()

db, err := bolt.Open(databasePath, 0600, &bolt.Options{
Timeout: 1 * time.Second,
InitialMmapSize: connection.InitialMmapSize,
Expand Down Expand Up @@ -178,6 +178,7 @@ func (connection *DbConnection) ViewTx(fn func(portainer.Transaction) error) err
func (connection *DbConnection) BackupTo(w io.Writer) error {
return connection.View(func(tx *bolt.Tx) error {
_, err := tx.WriteTo(w)

return err
})
}
Expand All @@ -192,6 +193,7 @@ func (connection *DbConnection) ExportRaw(filename string) error {
if err != nil {
return err
}

return os.WriteFile(filename, b, 0600)
}

Expand All @@ -212,7 +214,7 @@ func keyToString(b []byte) string {

v := binary.BigEndian.Uint64(b)
if v <= math.MaxInt32 {
return fmt.Sprintf("%d", v)
return strconv.FormatUint(v, 10)
}

return string(b)
Expand Down Expand Up @@ -321,22 +323,22 @@ func (connection *DbConnection) CreateObjectWithStringId(bucketName string, id [
})
}

func (connection *DbConnection) GetAll(bucketName string, obj interface{}, append func(o interface{}) (interface{}, error)) error {
func (connection *DbConnection) GetAll(bucketName string, obj interface{}, appendFn func(o interface{}) (interface{}, error)) error {
return connection.ViewTx(func(tx portainer.Transaction) error {
return tx.GetAll(bucketName, obj, append)
return tx.GetAll(bucketName, obj, appendFn)
})
}

// TODO: decide which Unmarshal to use, and use one...
func (connection *DbConnection) GetAllWithJsoniter(bucketName string, obj interface{}, append func(o interface{}) (interface{}, error)) error {
func (connection *DbConnection) GetAllWithJsoniter(bucketName string, obj interface{}, appendFn func(o interface{}) (interface{}, error)) error {
return connection.ViewTx(func(tx portainer.Transaction) error {
return tx.GetAllWithJsoniter(bucketName, obj, append)
return tx.GetAllWithJsoniter(bucketName, obj, appendFn)
})
}

func (connection *DbConnection) GetAllWithKeyPrefix(bucketName string, keyPrefix []byte, obj interface{}, append func(o interface{}) (interface{}, error)) error {
func (connection *DbConnection) GetAllWithKeyPrefix(bucketName string, keyPrefix []byte, obj interface{}, appendFn func(o interface{}) (interface{}, error)) error {
return connection.ViewTx(func(tx portainer.Transaction) error {
return tx.GetAllWithKeyPrefix(bucketName, keyPrefix, obj, append)
return tx.GetAllWithKeyPrefix(bucketName, keyPrefix, obj, appendFn)
})
}

Expand All @@ -345,14 +347,13 @@ func (connection *DbConnection) BackupMetadata() (map[string]interface{}, error)
buckets := map[string]interface{}{}

err := connection.View(func(tx *bolt.Tx) error {
err := tx.ForEach(func(name []byte, bucket *bolt.Bucket) error {
return tx.ForEach(func(name []byte, bucket *bolt.Bucket) error {
bucketName := string(name)
seqId := bucket.Sequence()
buckets[bucketName] = int(seqId)

return nil
})

return err
})

return buckets, err
Expand All @@ -366,6 +367,7 @@ func (connection *DbConnection) RestoreMetadata(s map[string]interface{}) error
id, ok := v.(float64) // JSON ints are unmarshalled to interface as float64. See: https://pkg.go.dev/encoding/json#Decoder.Decode
if !ok {
log.Error().Str("bucket", bucketName).Msg("failed to restore metadata to bucket, skipped")

continue
}

Expand Down
20 changes: 7 additions & 13 deletions api/database/boltdb/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@ import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"fmt"
"io"

"github.com/pkg/errors"
"github.com/segmentio/encoding/json"
)

var errEncryptedStringTooShort = fmt.Errorf("encrypted string too short")
var errEncryptedStringTooShort = errors.New("encrypted string too short")

// MarshalObject encodes an object to binary format
func (connection *DbConnection) MarshalObject(object interface{}) ([]byte, error) {
Expand Down Expand Up @@ -70,22 +69,20 @@ func encrypt(plaintext []byte, passphrase []byte) (encrypted []byte, err error)
if err != nil {
return encrypted, err
}

nonce := make([]byte, gcm.NonceSize())
if _, err = io.ReadFull(rand.Reader, nonce); err != nil {
return encrypted, err
}
ciphertextByte := gcm.Seal(
nonce,
nonce,
plaintext,
nil)
return ciphertextByte, nil

return gcm.Seal(nonce, nonce, plaintext, nil), nil
}

func decrypt(encrypted []byte, passphrase []byte) (plaintextByte []byte, err error) {
if string(encrypted) == "false" {
return []byte("false"), nil
}

block, err := aes.NewCipher(passphrase)
if err != nil {
return encrypted, errors.Wrap(err, "Error creating cypher block")
Expand All @@ -102,11 +99,8 @@ func decrypt(encrypted []byte, passphrase []byte) (plaintextByte []byte, err err
}

nonce, ciphertextByteClean := encrypted[:nonceSize], encrypted[nonceSize:]
plaintextByte, err = gcm.Open(
nil,
nonce,
ciphertextByteClean,
nil)

plaintextByte, err = gcm.Open(nil, nonce, ciphertextByteClean, nil)
if err != nil {
return encrypted, errors.Wrap(err, "Error decrypting text")
}
Expand Down
3 changes: 2 additions & 1 deletion api/database/boltdb/tx.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,10 @@ func (tx *DbTransaction) DeleteAllObjects(bucketName string, obj interface{}, ma

func (tx *DbTransaction) GetNextIdentifier(bucketName string) int {
bucket := tx.tx.Bucket([]byte(bucketName))

id, err := bucket.NextSequence()
if err != nil {
log.Error().Err(err).Str("bucket", bucketName).Msg("failed to get the next identifer")
log.Error().Err(err).Str("bucket", bucketName).Msg("failed to get the next identifier")
return 0
}

Expand Down
4 changes: 2 additions & 2 deletions api/docker/consts/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package consts
const (
ComposeStackNameLabel = "com.docker.compose.project"
SwarmStackNameLabel = "com.docker.stack.namespace"
SwarmServiceIdLabel = "com.docker.swarm.service.id"
SwarmNodeIdLabel = "com.docker.swarm.node.id"
SwarmServiceIDLabel = "com.docker.swarm.service.id"
SwarmNodeIDLabel = "com.docker.swarm.node.id"
HideStackLabel = "io.portainer.hideStack"
)
8 changes: 3 additions & 5 deletions api/docker/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import (
"github.com/docker/docker/api/types"
dockercontainer "github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/network"
"github.com/docker/docker/client"
"github.com/pkg/errors"
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/docker/images"

"github.com/pkg/errors"
"github.com/rs/zerolog/log"
)

Expand All @@ -37,9 +37,7 @@ func (c *ContainerService) Recreate(ctx context.Context, endpoint *portainer.End
return nil, errors.Wrap(err, "create client error")
}

defer func(cli *client.Client) {
cli.Close()
}(cli)
defer cli.Close()

log.Debug().Str("container_id", containerId).Msg("starting to fetch container information")

Expand Down
6 changes: 3 additions & 3 deletions api/docker/images/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ func (c *DigestClient) ContainersImageStatus(ctx context.Context, containers []t
statuses := make([]Status, len(containers))
for i, ct := range containers {
var nodeName string
if swarmNodeId := ct.Labels[consts.SwarmNodeIdLabel]; swarmNodeId != "" {
if swarmNodeId := ct.Labels[consts.SwarmNodeIDLabel]; swarmNodeId != "" {
if swarmNodeName, ok := swarmID2NameCache.Get(swarmNodeId); ok {
nodeName, _ = swarmNodeName.(string)
} else {
node, _, err := cli.NodeInspectWithRaw(ctx, ct.Labels[consts.SwarmNodeIdLabel])
node, _, err := cli.NodeInspectWithRaw(ctx, ct.Labels[consts.SwarmNodeIDLabel])
if err != nil {
return Error
}
Expand Down Expand Up @@ -160,7 +160,7 @@ func (c *DigestClient) ServiceImageStatus(ctx context.Context, serviceID string,

containers, err := cli.ContainerList(ctx, container.ListOptions{
All: true,
Filters: filters.NewArgs(filters.Arg("label", consts.SwarmServiceIdLabel+"="+serviceID)),
Filters: filters.NewArgs(filters.Arg("label", consts.SwarmServiceIDLabel+"="+serviceID)),
})
if err != nil {
log.Warn().Err(err).Str("serviceID", serviceID).Msg("cannot list container for the service")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func singleAPIRequest(h *Handler, jwt string, is *assert.Assertions, expect stri
FileContent string
}

req := httptest.NewRequest(http.MethodPut, "/custom_templates/1/git_fetch", bytes.NewBuffer([]byte("{}")))
req := httptest.NewRequest(http.MethodPut, "/custom_templates/1/git_fetch", bytes.NewBufferString("{}"))
testhelpers.AddTestSecurityCookie(req, jwt)

rr := httptest.NewRecorder()
Expand Down Expand Up @@ -196,7 +196,7 @@ func Test_customTemplateGitFetch(t *testing.T) {
}
h := NewHandler(requestBouncer, store, fileService, invalidGitService)

req := httptest.NewRequest(http.MethodPut, "/custom_templates/1/git_fetch", bytes.NewBuffer([]byte("{}")))
req := httptest.NewRequest(http.MethodPut, "/custom_templates/1/git_fetch", bytes.NewBufferString("{}"))
testhelpers.AddTestSecurityCookie(req, jwt1)

rr := httptest.NewRecorder()
Expand Down
20 changes: 10 additions & 10 deletions api/http/handler/docker/containers/recreate.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ 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/rs/zerolog/log"
)

Expand All @@ -30,8 +31,7 @@ func (handler *Handler) recreate(w http.ResponseWriter, r *http.Request) *httper
}

var payload RecreatePayload
err = request.DecodeAndValidateJSONPayload(r, &payload)
if err != nil {
if err := request.DecodeAndValidateJSONPayload(r, &payload); err != nil {
return httperror.BadRequest("Invalid request payload", err)
}

Expand All @@ -40,8 +40,7 @@ func (handler *Handler) recreate(w http.ResponseWriter, r *http.Request) *httper
return httperror.NotFound("Unable to find an environment on request context", err)
}

err = handler.bouncer.AuthorizedEndpointOperation(r, endpoint)
if err != nil {
if err := handler.bouncer.AuthorizedEndpointOperation(r, endpoint); err != nil {
return httperror.Forbidden("Permission denied to force update service", err)
}

Expand All @@ -58,40 +57,41 @@ func (handler *Handler) recreate(w http.ResponseWriter, r *http.Request) *httper
go func() {
images.EvictImageStatus(containerID)
images.EvictImageStatus(newContainer.Config.Labels[consts.ComposeStackNameLabel])
images.EvictImageStatus(newContainer.Config.Labels[consts.SwarmServiceIdLabel])
images.EvictImageStatus(newContainer.Config.Labels[consts.SwarmServiceIDLabel])
}()

return response.JSON(w, newContainer)
}

func (handler *Handler) createResourceControl(oldContainerId string, newContainerId string) {
resourceControls, err := handler.dataStore.ResourceControl().ReadAll()
if err != nil {
log.Error().Err(err).Msg("Exporting Resource Controls")

return
}

resourceControl := authorization.GetResourceControlByResourceIDAndType(oldContainerId, portainer.ContainerResourceControl, resourceControls)
if resourceControl == nil {
return
}

resourceControl.ResourceID = newContainerId
err = handler.dataStore.ResourceControl().Create(resourceControl)
if err != nil {
if err := handler.dataStore.ResourceControl().Create(resourceControl); err != nil {
log.Error().Err(err).Str("containerId", newContainerId).Msg("Failed to create new resource control for container")
return
}
}

func (handler *Handler) updateWebhook(oldContainerId string, newContainerId string) {
webhook, err := handler.dataStore.Webhook().WebhookByResourceID(oldContainerId)
if err != nil {
log.Error().Err(err).Str("containerId", oldContainerId).Msg("cannot find webhook by containerId")

return
}

webhook.ResourceID = newContainerId
err = handler.dataStore.Webhook().Update(webhook.ID, webhook)
if err != nil {
if err := handler.dataStore.Webhook().Update(webhook.ID, webhook); err != nil {
log.Error().Err(err).Int("webhookId", int(webhook.ID)).Msg("cannot update webhook")
}
}
9 changes: 3 additions & 6 deletions api/http/handler/edgestacks/utils_update_stack_version.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,21 @@ import (
portainer "github.com/portainer/portainer/api"
"github.com/portainer/portainer/api/filesystem"
edgestackutils "github.com/portainer/portainer/api/internal/edge/edgestacks"

"github.com/rs/zerolog/log"
)

func (handler *Handler) updateStackVersion(stack *portainer.EdgeStack, deploymentType portainer.EdgeStackDeploymentType, config []byte, oldGitHash string, relatedEnvironmentsIDs []portainer.EndpointID) error {

stack.Version = stack.Version + 1
stack.Status = edgestackutils.NewStatus(stack.Status, relatedEnvironmentsIDs)

return handler.storeStackFile(stack, deploymentType, config)
}

func (handler *Handler) storeStackFile(stack *portainer.EdgeStack, deploymentType portainer.EdgeStackDeploymentType, config []byte) error {

if deploymentType != stack.DeploymentType {
// deployment type was changed - need to delete all old files
err := handler.FileService.RemoveDirectory(stack.ProjectPath)
if err != nil {
if err := handler.FileService.RemoveDirectory(stack.ProjectPath); err != nil {
log.Warn().Err(err).Msg("Unable to clear old files")
}

Expand All @@ -50,8 +48,7 @@ func (handler *Handler) storeStackFile(stack *portainer.EdgeStack, deploymentTyp
entryPoint = stack.ManifestPath
}

_, err := handler.FileService.StoreEdgeStackFileFromBytes(stackFolder, entryPoint, config)
if err != nil {
if _, err := handler.FileService.StoreEdgeStackFileFromBytes(stackFolder, entryPoint, config); err != nil {
return fmt.Errorf("unable to persist updated Compose file with version on disk: %w", err)
}

Expand Down
Loading

0 comments on commit bfa27d9

Please sign in to comment.