fix(all): avoid using pointers to zero sized structs BE-12129 (#986)

pull/12074/merge
andres-portainer 2025-08-07 09:47:42 -03:00 committed by GitHub
parent e39dcc458b
commit 9325cb2872
20 changed files with 145 additions and 68 deletions

View File

@ -67,7 +67,7 @@ func CLIFlags() *portainer.CLIFlags {
} }
// ParseFlags parse the CLI flags and return a portainer.Flags struct // ParseFlags parse the CLI flags and return a portainer.Flags struct
func (*Service) ParseFlags(version string) (*portainer.CLIFlags, error) { func (Service) ParseFlags(version string) (*portainer.CLIFlags, error) {
kingpin.Version(version) kingpin.Version(version)
flags := CLIFlags() flags := CLIFlags()
@ -87,7 +87,7 @@ func (*Service) ParseFlags(version string) (*portainer.CLIFlags, error) {
} }
// ValidateFlags validates the values of the flags. // ValidateFlags validates the values of the flags.
func (*Service) ValidateFlags(flags *portainer.CLIFlags) error { func (Service) ValidateFlags(flags *portainer.CLIFlags) error {
displayDeprecationWarnings(flags) displayDeprecationWarnings(flags)
if err := validateEndpointURL(*flags.EndpointURL); err != nil { if err := validateEndpointURL(*flags.EndpointURL); err != nil {

24
api/cli/cli_test.go Normal file
View File

@ -0,0 +1,24 @@
package cli
import (
"os"
"testing"
"github.com/stretchr/testify/require"
)
func TestOptionParser(t *testing.T) {
p := Service{}
require.NotNil(t, p)
a := os.Args
defer func() { os.Args = a }()
os.Args = []string{"portainer", "--edge-compute"}
opts, err := p.ParseFlags("2.34.5")
require.NoError(t, err)
require.False(t, *opts.HTTPDisabled)
require.True(t, *opts.EnableEdgeComputeFeatures)
}

View File

@ -60,7 +60,7 @@ import (
) )
func initCLI() *portainer.CLIFlags { func initCLI() *portainer.CLIFlags {
cliService := &cli.Service{} cliService := cli.Service{}
flags, err := cliService.ParseFlags(portainer.APIVersion) flags, err := cliService.ParseFlags(portainer.APIVersion)
if err != nil { if err != nil {
@ -381,7 +381,7 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
log.Fatal().Err(err).Msg("failed initializing JWT service") log.Fatal().Err(err).Msg("failed initializing JWT service")
} }
ldapService := &ldap.Service{} ldapService := ldap.Service{}
oauthService := oauth.NewService() oauthService := oauth.NewService()
@ -390,7 +390,7 @@ func buildServer(flags *portainer.CLIFlags) portainer.Server {
// Setting insecureSkipVerify to true to preserve the old behaviour. // Setting insecureSkipVerify to true to preserve the old behaviour.
openAMTService := openamt.NewService(true) openAMTService := openamt.NewService(true)
cryptoService := &crypto.Service{} cryptoService := crypto.Service{}
signatureService := initDigitalSignatureService() signatureService := initDigitalSignatureService()

View File

@ -8,15 +8,16 @@ import (
type Service struct{} type Service struct{}
// Hash hashes a string using the bcrypt algorithm // Hash hashes a string using the bcrypt algorithm
func (*Service) Hash(data string) (string, error) { func (Service) Hash(data string) (string, error) {
bytes, err := bcrypt.GenerateFromPassword([]byte(data), bcrypt.DefaultCost) bytes, err := bcrypt.GenerateFromPassword([]byte(data), bcrypt.DefaultCost)
if err != nil { if err != nil {
return "", err return "", err
} }
return string(bytes), err return string(bytes), err
} }
// CompareHashAndData compares a hash to clear data and returns an error if the comparison fails. // CompareHashAndData compares a hash to clear data and returns an error if the comparison fails.
func (*Service) CompareHashAndData(hash string, data string) error { func (Service) CompareHashAndData(hash string, data string) error {
return bcrypt.CompareHashAndPassword([]byte(hash), []byte(data)) return bcrypt.CompareHashAndPassword([]byte(hash), []byte(data))
} }

View File

@ -2,10 +2,12 @@ package crypto
import ( import (
"testing" "testing"
"github.com/stretchr/testify/require"
) )
func TestService_Hash(t *testing.T) { func TestService_Hash(t *testing.T) {
var s = &Service{} var s = Service{}
type args struct { type args struct {
hash string hash string
@ -51,3 +53,11 @@ func TestService_Hash(t *testing.T) {
}) })
} }
} }
func TestHash(t *testing.T) {
s := Service{}
hash, err := s.Hash("Passw0rd!")
require.NoError(t, err)
require.NotEmpty(t, hash)
}

View File

@ -232,7 +232,7 @@ func (store *Store) createAccount(username, password string, role portainer.User
user := &portainer.User{Username: username, Role: role} user := &portainer.User{Username: username, Role: role}
// encrypt the password // encrypt the password
cs := &crypto.Service{} cs := crypto.Service{}
user.Password, err = cs.Hash(password) user.Password, err = cs.Hash(password)
if err != nil { if err != nil {
return err return err
@ -259,7 +259,7 @@ func (store *Store) checkAccount(username, expectPassword string, expectRole por
} }
// Check the password // Check the password
cs := &crypto.Service{} cs := crypto.Service{}
expectPasswordHash, err := cs.Hash(expectPassword) expectPasswordHash, err := cs.Hash(expectPassword)
if err != nil { if err != nil {
return errors.Wrap(err, "hash failed") return errors.Wrap(err, "hash failed")

View File

@ -17,7 +17,7 @@ import (
type mockPasswordStrengthChecker struct{} type mockPasswordStrengthChecker struct{}
func (m *mockPasswordStrengthChecker) Check(string) bool { func (m mockPasswordStrengthChecker) Check(string) bool {
return true return true
} }
@ -25,8 +25,8 @@ func TestConcurrentUserCreation(t *testing.T) {
_, store := datastore.MustNewTestStore(t, true, false) _, store := datastore.MustNewTestStore(t, true, false)
h := &Handler{ h := &Handler{
passwordStrengthChecker: &mockPasswordStrengthChecker{}, passwordStrengthChecker: mockPasswordStrengthChecker{},
CryptoService: &crypto.Service{}, CryptoService: crypto.Service{},
DataStore: store, DataStore: store,
} }

View File

@ -9,10 +9,10 @@ import (
type httpLogger struct{} type httpLogger struct{}
func NewHTTPLogger() *log.Logger { func NewHTTPLogger() *log.Logger {
return log.New(&httpLogger{}, "", 0) return log.New(httpLogger{}, "", 0)
} }
func (l *httpLogger) Write(data []byte) (int, error) { func (l httpLogger) Write(data []byte) (int, error) {
zlog.Debug().CallerSkipFrame(3).Msg(string(data)) zlog.Debug().CallerSkipFrame(3).Msg(string(data))
return len(data), nil return len(data), nil

21
api/http/logger_test.go Normal file
View File

@ -0,0 +1,21 @@
package http
import (
"bytes"
"testing"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/stretchr/testify/require"
)
func TestLogger(t *testing.T) {
msg := "Testing HTTP logger"
buf := &bytes.Buffer{}
log.Logger = zerolog.New(buf)
NewHTTPLogger().Print(msg)
require.Contains(t, buf.String(), msg)
}

View File

@ -6,33 +6,33 @@ import (
portainer "github.com/portainer/portainer/api" portainer "github.com/portainer/portainer/api"
) )
var _ portainer.ComposeStackManager = &composeStackManager{} var _ portainer.ComposeStackManager = composeStackManager{}
type composeStackManager struct{} type composeStackManager struct{}
func NewComposeStackManager() *composeStackManager { func NewComposeStackManager() composeStackManager {
return &composeStackManager{} return composeStackManager{}
} }
func (manager *composeStackManager) ComposeSyntaxMaxVersion() string { func (manager composeStackManager) ComposeSyntaxMaxVersion() string {
return "" return ""
} }
func (manager *composeStackManager) NormalizeStackName(name string) string { func (manager composeStackManager) NormalizeStackName(name string) string {
return name return name
} }
func (manager *composeStackManager) Run(ctx context.Context, stack *portainer.Stack, endpoint *portainer.Endpoint, serviceName string, options portainer.ComposeRunOptions) error { func (manager composeStackManager) Run(ctx context.Context, stack *portainer.Stack, endpoint *portainer.Endpoint, serviceName string, options portainer.ComposeRunOptions) error {
return nil return nil
} }
func (manager *composeStackManager) Up(ctx context.Context, stack *portainer.Stack, endpoint *portainer.Endpoint, options portainer.ComposeUpOptions) error { func (manager composeStackManager) Up(ctx context.Context, stack *portainer.Stack, endpoint *portainer.Endpoint, options portainer.ComposeUpOptions) error {
return nil return nil
} }
func (manager *composeStackManager) Down(ctx context.Context, stack *portainer.Stack, endpoint *portainer.Endpoint) error { func (manager composeStackManager) Down(ctx context.Context, stack *portainer.Stack, endpoint *portainer.Endpoint) error {
return nil return nil
} }
func (manager *composeStackManager) Pull(ctx context.Context, stack *portainer.Stack, endpoint *portainer.Endpoint, options portainer.ComposeOptions) error { func (manager composeStackManager) Pull(ctx context.Context, stack *portainer.Stack, endpoint *portainer.Endpoint, options portainer.ComposeOptions) error {
return nil return nil
} }

View File

@ -3,14 +3,14 @@ package testhelpers
// Service represents a service for encrypting/hashing data. // Service represents a service for encrypting/hashing data.
type cryptoService struct{} type cryptoService struct{}
func NewCryptoService() *cryptoService { func NewCryptoService() cryptoService {
return &cryptoService{} return cryptoService{}
} }
func (*cryptoService) Hash(data string) (string, error) { func (cryptoService) Hash(data string) (string, error) {
return "", nil return "", nil
} }
func (*cryptoService) CompareHashAndData(hash string, data string) error { func (cryptoService) CompareHashAndData(hash string, data string) error {
return nil return nil
} }

View File

@ -10,8 +10,8 @@ import (
type testRequestBouncer struct{} type testRequestBouncer struct{}
// NewTestRequestBouncer creates new mock for requestBouncer // NewTestRequestBouncer creates new mock for requestBouncer
func NewTestRequestBouncer() *testRequestBouncer { func NewTestRequestBouncer() testRequestBouncer {
return &testRequestBouncer{} return testRequestBouncer{}
} }
func (testRequestBouncer) AuthenticatedAccess(h http.Handler) http.Handler { func (testRequestBouncer) AuthenticatedAccess(h http.Handler) http.Handler {

View File

@ -68,7 +68,7 @@ func createConnectionForURL(url string, settings *portainer.LDAPSettings) (*ldap
} }
// AuthenticateUser is used to authenticate a user against a LDAP/AD. // AuthenticateUser is used to authenticate a user against a LDAP/AD.
func (*Service) AuthenticateUser(username, password string, settings *portainer.LDAPSettings) error { func (Service) AuthenticateUser(username, password string, settings *portainer.LDAPSettings) error {
connection, err := createConnection(settings) connection, err := createConnection(settings)
if err != nil { if err != nil {
return err return err
@ -103,7 +103,7 @@ func (*Service) AuthenticateUser(username, password string, settings *portainer.
} }
// GetUserGroups is used to retrieve user groups from LDAP/AD. // GetUserGroups is used to retrieve user groups from LDAP/AD.
func (*Service) GetUserGroups(username string, settings *portainer.LDAPSettings) ([]string, error) { func (Service) GetUserGroups(username string, settings *portainer.LDAPSettings) ([]string, error) {
connection, err := createConnection(settings) connection, err := createConnection(settings)
if err != nil { if err != nil {
return nil, err return nil, err
@ -128,7 +128,7 @@ func (*Service) GetUserGroups(username string, settings *portainer.LDAPSettings)
} }
// SearchUsers searches for users with the specified settings // SearchUsers searches for users with the specified settings
func (*Service) SearchUsers(settings *portainer.LDAPSettings) ([]string, error) { func (Service) SearchUsers(settings *portainer.LDAPSettings) ([]string, error) {
connection, err := createConnection(settings) connection, err := createConnection(settings)
if err != nil { if err != nil {
return nil, err return nil, err
@ -175,7 +175,7 @@ func (*Service) SearchUsers(settings *portainer.LDAPSettings) ([]string, error)
} }
// SearchGroups searches for groups with the specified settings // SearchGroups searches for groups with the specified settings
func (*Service) SearchGroups(settings *portainer.LDAPSettings) ([]portainer.LDAPUser, error) { func (Service) SearchGroups(settings *portainer.LDAPSettings) ([]portainer.LDAPUser, error) {
type groupSet map[string]bool type groupSet map[string]bool
connection, err := createConnection(settings) connection, err := createConnection(settings)
@ -304,8 +304,7 @@ func getGroupsByUser(userDN string, conn *ldap.Conn, settings []portainer.LDAPGr
// TestConnectivity is used to test a connection against the LDAP server using the credentials // TestConnectivity is used to test a connection against the LDAP server using the credentials
// specified in the LDAPSettings. // specified in the LDAPSettings.
func (*Service) TestConnectivity(settings *portainer.LDAPSettings) error { func (Service) TestConnectivity(settings *portainer.LDAPSettings) error {
connection, err := createConnection(settings) connection, err := createConnection(settings)
if err != nil { if err != nil {
return err return err

View File

@ -70,3 +70,25 @@ func TestCreateConnectionForURL(t *testing.T) {
require.Error(t, err) require.Error(t, err)
require.Nil(t, conn) require.Nil(t, conn)
} }
func TestFailures(t *testing.T) {
s := Service{}
err := s.AuthenticateUser("username", "password", &portainer.LDAPSettings{})
require.Error(t, err)
uGroups, err := s.GetUserGroups("username", &portainer.LDAPSettings{})
require.Error(t, err)
require.Empty(t, uGroups)
users, err := s.SearchUsers(&portainer.LDAPSettings{})
require.Error(t, err)
require.Empty(t, users)
groups, err := s.SearchGroups(&portainer.LDAPSettings{})
require.Error(t, err)
require.Empty(t, groups)
err = s.TestConnectivity(&portainer.LDAPSettings{})
require.Error(t, err)
}

View File

@ -23,14 +23,14 @@ import (
type Service struct{} type Service struct{}
// NewService returns a pointer to a new instance of this service // NewService returns a pointer to a new instance of this service
func NewService() *Service { func NewService() Service {
return &Service{} return Service{}
} }
// Authenticate takes an access code and exchanges it for an access token from portainer OAuthSettings token environment(endpoint). // Authenticate takes an access code and exchanges it for an access token from portainer OAuthSettings token environment(endpoint).
// On success, it will then return the username and token expiry time associated to authenticated user by fetching this information // On success, it will then return the username and token expiry time associated to authenticated user by fetching this information
// from the resource server and matching it with the user identifier setting. // from the resource server and matching it with the user identifier setting.
func (*Service) Authenticate(code string, configuration *portainer.OAuthSettings) (string, error) { func (Service) Authenticate(code string, configuration *portainer.OAuthSettings) (string, error) {
token, err := GetOAuthToken(code, configuration) token, err := GetOAuthToken(code, configuration)
if err != nil { if err != nil {
log.Error().Err(err).Msg("failed retrieving oauth token") log.Error().Err(err).Msg("failed retrieving oauth token")

View File

@ -77,41 +77,41 @@ vJUUCFYm8+9p6gTVOcoMit+eGSwa81PCPEs1TnU1PV/PaDFeUhn/mg==
type noopDeployer struct{} type noopDeployer struct{}
// without unpacker // without unpacker
func (s *noopDeployer) DeploySwarmStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, prune, pullImage bool) error { func (s noopDeployer) DeploySwarmStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, prune, pullImage bool) error {
return nil return nil
} }
func (s *noopDeployer) DeployComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, forcePullImage, forceRecreate bool) error { func (s noopDeployer) DeployComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, forcePullImage, forceRecreate bool) error {
return nil return nil
} }
func (s *noopDeployer) DeployKubernetesStack(stack *portainer.Stack, endpoint *portainer.Endpoint, user *portainer.User) error { func (s noopDeployer) DeployKubernetesStack(stack *portainer.Stack, endpoint *portainer.Endpoint, user *portainer.User) error {
return nil return nil
} }
// with unpacker // with unpacker
func (s *noopDeployer) DeployRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, forcePullImage, forceRecreate bool) error { func (s noopDeployer) DeployRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, forcePullImage, forceRecreate bool) error {
return nil return nil
} }
func (s *noopDeployer) UndeployRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint) error { func (s noopDeployer) UndeployRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint) error {
return nil return nil
} }
func (s *noopDeployer) StartRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry) error { func (s noopDeployer) StartRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry) error {
return nil return nil
} }
func (s *noopDeployer) StopRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint) error { func (s noopDeployer) StopRemoteComposeStack(stack *portainer.Stack, endpoint *portainer.Endpoint) error {
return nil return nil
} }
func (s *noopDeployer) DeployRemoteSwarmStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, prune, pullImage bool) error { func (s noopDeployer) DeployRemoteSwarmStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry, prune, pullImage bool) error {
return nil return nil
} }
func (s *noopDeployer) UndeployRemoteSwarmStack(stack *portainer.Stack, endpoint *portainer.Endpoint) error { func (s noopDeployer) UndeployRemoteSwarmStack(stack *portainer.Stack, endpoint *portainer.Endpoint) error {
return nil return nil
} }
func (s *noopDeployer) StartRemoteSwarmStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry) error { func (s noopDeployer) StartRemoteSwarmStack(stack *portainer.Stack, endpoint *portainer.Endpoint, registries []portainer.Registry) error {
return nil return nil
} }
func (s *noopDeployer) StopRemoteSwarmStack(stack *portainer.Stack, endpoint *portainer.Endpoint) error { func (s noopDeployer) StopRemoteSwarmStack(stack *portainer.Stack, endpoint *portainer.Endpoint) error {
return nil return nil
} }
@ -266,7 +266,7 @@ func Test_redeployWhenChanged(t *testing.T) {
stack.Type = portainer.DockerComposeStack stack.Type = portainer.DockerComposeStack
store.Stack().Update(stack.ID, &stack) store.Stack().Update(stack.ID, &stack)
err = RedeployWhenChanged(1, &noopDeployer{}, store, testhelpers.NewGitService(nil, "newHash")) err = RedeployWhenChanged(1, noopDeployer{}, store, testhelpers.NewGitService(nil, "newHash"))
assert.NoError(t, err) assert.NoError(t, err)
}) })
@ -274,7 +274,7 @@ func Test_redeployWhenChanged(t *testing.T) {
stack.Type = portainer.DockerSwarmStack stack.Type = portainer.DockerSwarmStack
store.Stack().Update(stack.ID, &stack) store.Stack().Update(stack.ID, &stack)
err = RedeployWhenChanged(1, &noopDeployer{}, store, testhelpers.NewGitService(nil, "newHash")) err = RedeployWhenChanged(1, noopDeployer{}, store, testhelpers.NewGitService(nil, "newHash"))
assert.NoError(t, err) assert.NoError(t, err)
}) })
@ -282,7 +282,7 @@ func Test_redeployWhenChanged(t *testing.T) {
stack.Type = portainer.KubernetesStack stack.Type = portainer.KubernetesStack
store.Stack().Update(stack.ID, &stack) store.Stack().Update(stack.ID, &stack)
err = RedeployWhenChanged(1, &noopDeployer{}, store, testhelpers.NewGitService(nil, "newHash")) err = RedeployWhenChanged(1, noopDeployer{}, store, testhelpers.NewGitService(nil, "newHash"))
assert.NoError(t, err) assert.NoError(t, err)
}) })
} }

View File

@ -34,7 +34,7 @@ type helmMockPackageManager struct{}
// NewMockHelmPackageManager initializes a new HelmPackageManager service (a mock instance) // NewMockHelmPackageManager initializes a new HelmPackageManager service (a mock instance)
func NewMockHelmPackageManager() types.HelmPackageManager { func NewMockHelmPackageManager() types.HelmPackageManager {
return &helmMockPackageManager{} return helmMockPackageManager{}
} }
var mockCharts = []release.ReleaseElement{} var mockCharts = []release.ReleaseElement{}
@ -58,7 +58,7 @@ func newMockRelease(re *release.ReleaseElement) *release.Release {
} }
// Install a helm chart (not thread safe) // Install a helm chart (not thread safe)
func (hpm *helmMockPackageManager) Install(installOpts options.InstallOptions) (*release.Release, error) { func (hpm helmMockPackageManager) Install(installOpts options.InstallOptions) (*release.Release, error) {
releaseElement := newMockReleaseElement(installOpts) releaseElement := newMockReleaseElement(installOpts)
@ -75,17 +75,17 @@ func (hpm *helmMockPackageManager) Install(installOpts options.InstallOptions) (
} }
// Upgrade a helm chart (not thread safe) // Upgrade a helm chart (not thread safe)
func (hpm *helmMockPackageManager) Upgrade(upgradeOpts options.InstallOptions) (*release.Release, error) { func (hpm helmMockPackageManager) Upgrade(upgradeOpts options.InstallOptions) (*release.Release, error) {
return hpm.Install(upgradeOpts) return hpm.Install(upgradeOpts)
} }
// Rollback a helm chart (not thread safe) // Rollback a helm chart (not thread safe)
func (hpm *helmMockPackageManager) Rollback(rollbackOpts options.RollbackOptions) (*release.Release, error) { func (hpm helmMockPackageManager) Rollback(rollbackOpts options.RollbackOptions) (*release.Release, error) {
return hpm.Rollback(rollbackOpts) return hpm.Rollback(rollbackOpts)
} }
// Show values/readme/chart etc // Show values/readme/chart etc
func (hpm *helmMockPackageManager) Show(showOpts options.ShowOptions) ([]byte, error) { func (hpm helmMockPackageManager) Show(showOpts options.ShowOptions) ([]byte, error) {
switch showOpts.OutputFormat { switch showOpts.OutputFormat {
case options.ShowChart: case options.ShowChart:
return []byte(MockDataChart), nil return []byte(MockDataChart), nil
@ -98,7 +98,7 @@ func (hpm *helmMockPackageManager) Show(showOpts options.ShowOptions) ([]byte, e
} }
// Uninstall a helm chart (not thread safe) // Uninstall a helm chart (not thread safe)
func (hpm *helmMockPackageManager) Uninstall(uninstallOpts options.UninstallOptions) error { func (hpm helmMockPackageManager) Uninstall(uninstallOpts options.UninstallOptions) error {
for i, rel := range mockCharts { for i, rel := range mockCharts {
if rel.Name == uninstallOpts.Name && rel.Namespace == uninstallOpts.Namespace { if rel.Name == uninstallOpts.Name && rel.Namespace == uninstallOpts.Namespace {
mockCharts = slices.Delete(mockCharts, i, i+1) mockCharts = slices.Delete(mockCharts, i, i+1)
@ -108,19 +108,19 @@ func (hpm *helmMockPackageManager) Uninstall(uninstallOpts options.UninstallOpti
} }
// List a helm chart (not thread safe) // List a helm chart (not thread safe)
func (hpm *helmMockPackageManager) List(listOpts options.ListOptions) ([]release.ReleaseElement, error) { func (hpm helmMockPackageManager) List(listOpts options.ListOptions) ([]release.ReleaseElement, error) {
return mockCharts, nil return mockCharts, nil
} }
// Get a helm release (not thread safe) // Get a helm release (not thread safe)
func (hpm *helmMockPackageManager) Get(getOpts options.GetOptions) (*release.Release, error) { func (hpm helmMockPackageManager) Get(getOpts options.GetOptions) (*release.Release, error) {
index := slices.IndexFunc(mockCharts, func(re release.ReleaseElement) bool { index := slices.IndexFunc(mockCharts, func(re release.ReleaseElement) bool {
return re.Name == getOpts.Name && re.Namespace == getOpts.Namespace return re.Name == getOpts.Name && re.Namespace == getOpts.Namespace
}) })
return newMockRelease(&mockCharts[index]), nil return newMockRelease(&mockCharts[index]), nil
} }
func (hpm *helmMockPackageManager) GetHistory(historyOpts options.HistoryOptions) ([]*release.Release, error) { func (hpm helmMockPackageManager) GetHistory(historyOpts options.HistoryOptions) ([]*release.Release, error) {
var result []*release.Release var result []*release.Release
for i, v := range mockCharts { for i, v := range mockCharts {
if v.Name == historyOpts.Name && v.Namespace == historyOpts.Namespace { if v.Name == historyOpts.Name && v.Namespace == historyOpts.Namespace {
@ -154,7 +154,7 @@ entries:
version: 1.0.6 version: 1.0.6
generated: "2020-08-19T00:00:46.754739363Z"` generated: "2020-08-19T00:00:46.754739363Z"`
func (hbpm *helmMockPackageManager) SearchRepo(searchRepoOpts options.SearchRepoOptions) ([]byte, error) { func (hbpm helmMockPackageManager) SearchRepo(searchRepoOpts options.SearchRepoOptions) ([]byte, error) {
// Always return the same repo data no matter what // Always return the same repo data no matter what
reader := strings.NewReader(mockPortainerIndex) reader := strings.NewReader(mockPortainerIndex)

View File

@ -19,13 +19,13 @@ type RepositoryListClient interface {
type RepositoryListClientFactory struct{} type RepositoryListClientFactory struct{}
// NewRepositoryListClientFactory creates a new factory instance // NewRepositoryListClientFactory creates a new factory instance
func NewRepositoryListClientFactory() *RepositoryListClientFactory { func NewRepositoryListClientFactory() RepositoryListClientFactory {
return &RepositoryListClientFactory{} return RepositoryListClientFactory{}
} }
// CreateListClientWithRegistry creates a repository listing client based on the registry type // CreateListClientWithRegistry creates a repository listing client based on the registry type
// and automatically configures it with the provided ORAS registry client for generic registries // and automatically configures it with the provided ORAS registry client for generic registries
func (f *RepositoryListClientFactory) CreateListClientWithRegistry(registry *portainer.Registry, registryClient *remote.Registry) (RepositoryListClient, error) { func (f RepositoryListClientFactory) CreateListClientWithRegistry(registry *portainer.Registry, registryClient *remote.Registry) (RepositoryListClient, error) {
switch registry.Type { switch registry.Type {
case portainer.GitlabRegistry: case portainer.GitlabRegistry:
return NewGitlabListRepoClient(registry), nil return NewGitlabListRepoClient(registry), nil

View File

@ -35,7 +35,7 @@ const portainerEnvVarsPrefix = "PORTAINER_"
var mu sync.Mutex var mu sync.Mutex
func init() { func init() {
logrus.SetOutput(&LogrusToZerologWriter{}) logrus.SetOutput(LogrusToZerologWriter{})
logrus.SetFormatter(&logrus.TextFormatter{ logrus.SetFormatter(&logrus.TextFormatter{
DisableTimestamp: true, DisableTimestamp: true,
}) })

View File

@ -11,7 +11,7 @@ import (
// logrus is the logging library used by Docker Compose. // logrus is the logging library used by Docker Compose.
type LogrusToZerologWriter struct{} type LogrusToZerologWriter struct{}
func (ltzw *LogrusToZerologWriter) Write(p []byte) (n int, err error) { func (ltzw LogrusToZerologWriter) Write(p []byte) (n int, err error) {
logMessage := string(p) logMessage := string(p)
logMessage = strings.TrimSuffix(logMessage, "\n") logMessage = strings.TrimSuffix(logMessage, "\n")