From ee0dbf2d22e29d22c48a2456e5250ec5c554c0d6 Mon Sep 17 00:00:00 2001 From: Oscar Zhou <100548325+oscarzhou-portainer@users.noreply.github.com> Date: Tue, 26 Nov 2024 10:17:46 +1300 Subject: [PATCH] feat(init): allow to customize kubectl-shell image by cli flag [BE-11419] (#162) --- api/cli/cli.go | 1 + api/cmd/portainer/main.go | 4 ++-- api/datastore/datastore.go | 3 ++- api/datastore/init.go | 2 +- api/datastore/migrate_data.go | 5 +++-- api/datastore/migrate_data_test.go | 2 +- api/datastore/migrate_dbversion29_test.go | 1 + api/datastore/migrator/migrate_dbversion32.go | 4 +--- api/datastore/migrator/migrator.go | 3 +++ api/datastore/services.go | 1 + api/datastore/teststore.go | 6 +++++- api/portainer.go | 3 +++ 12 files changed, 24 insertions(+), 11 deletions(-) diff --git a/api/cli/cli.go b/api/cli/cli.go index 5bd9d07f9..67005fddb 100644 --- a/api/cli/cli.go +++ b/api/cli/cli.go @@ -59,6 +59,7 @@ func CLIFlags() *portainer.CLIFlags { SecretKeyName: kingpin.Flag("secret-key-name", "Secret key name for encryption and will be used as /run/secrets/.").Default(defaultSecretKeyName).String(), LogLevel: kingpin.Flag("log-level", "Set the minimum logging level to show").Default("INFO").Enum("DEBUG", "INFO", "WARN", "ERROR"), LogMode: kingpin.Flag("log-mode", "Set the logging output mode").Default("PRETTY").Enum("NOCOLOR", "PRETTY", "JSON"), + KubectlShellImage: kingpin.Flag("kubectl-shell-image", "Kubectl shell image").Envar(portainer.KubectlShellImageEnvVar).Default(portainer.DefaultKubectlShellImage).String(), } } diff --git a/api/cmd/portainer/main.go b/api/cmd/portainer/main.go index ee5eeb3fd..5fbe54484 100644 --- a/api/cmd/portainer/main.go +++ b/api/cmd/portainer/main.go @@ -93,7 +93,7 @@ func initDataStore(flags *portainer.CLIFlags, secretKey []byte, fileService port log.Fatal().Msg("failed creating database connection: expecting a boltdb database type but a different one was received") } - store := datastore.NewStore(*flags.Data, fileService, connection) + store := datastore.NewStore(flags, fileService, connection) isNew, err := store.Open() if err != nil { @@ -120,7 +120,7 @@ func initDataStore(flags *portainer.CLIFlags, secretKey []byte, fileService port log.Fatal().Err(err).Msg("failed generating instance id") } - migratorInstance := migrator.NewMigrator(&migrator.MigratorParameters{}) + migratorInstance := migrator.NewMigrator(&migrator.MigratorParameters{Flags: flags}) migratorCount := migratorInstance.GetMigratorCountOfCurrentAPIVersion() // from MigrateData diff --git a/api/datastore/datastore.go b/api/datastore/datastore.go index 643a90108..b46007315 100644 --- a/api/datastore/datastore.go +++ b/api/datastore/datastore.go @@ -16,8 +16,9 @@ import ( ) // NewStore initializes a new Store and the associated services -func NewStore(storePath string, fileService portainer.FileService, connection portainer.Connection) *Store { +func NewStore(cliFlags *portainer.CLIFlags, fileService portainer.FileService, connection portainer.Connection) *Store { return &Store{ + flags: cliFlags, fileService: fileService, connection: connection, } diff --git a/api/datastore/init.go b/api/datastore/init.go index 963a3ebc3..f6f676a70 100644 --- a/api/datastore/init.go +++ b/api/datastore/init.go @@ -57,7 +57,7 @@ func (store *Store) checkOrCreateDefaultSettings() error { HelmRepositoryURL: portainer.DefaultHelmRepositoryURL, UserSessionTimeout: portainer.DefaultUserSessionTimeout, KubeconfigExpiry: portainer.DefaultKubeconfigExpiry, - KubectlShellImage: portainer.DefaultKubectlShellImage, + KubectlShellImage: *store.flags.KubectlShellImage, IsDockerDesktopExtension: isDDExtention, } diff --git a/api/datastore/migrate_data.go b/api/datastore/migrate_data.go index 2bbd0db95..8047274d1 100644 --- a/api/datastore/migrate_data.go +++ b/api/datastore/migrate_data.go @@ -32,7 +32,7 @@ func (store *Store) MigrateData() error { return errors.Wrap(err, "while migrating legacy version") } - migratorParams := store.newMigratorParameters(version) + migratorParams := store.newMigratorParameters(version, store.flags) migrator := migrator.NewMigrator(migratorParams) if !migrator.NeedsMigration() { @@ -62,8 +62,9 @@ func (store *Store) MigrateData() error { return nil } -func (store *Store) newMigratorParameters(version *models.Version) *migrator.MigratorParameters { +func (store *Store) newMigratorParameters(version *models.Version, flags *portainer.CLIFlags) *migrator.MigratorParameters { return &migrator.MigratorParameters{ + Flags: flags, CurrentDBVersion: version, EndpointGroupService: store.EndpointGroupService, EndpointService: store.EndpointService, diff --git a/api/datastore/migrate_data_test.go b/api/datastore/migrate_data_test.go index 58ff743f0..fbb8d24b9 100644 --- a/api/datastore/migrate_data_test.go +++ b/api/datastore/migrate_data_test.go @@ -109,7 +109,7 @@ func TestMigrateData(t *testing.T) { t.FailNow() } - migratorParams := store.newMigratorParameters(v) + migratorParams := store.newMigratorParameters(v, store.flags) m := migrator.NewMigrator(migratorParams) latestMigrations := m.LatestMigrations() diff --git a/api/datastore/migrate_dbversion29_test.go b/api/datastore/migrate_dbversion29_test.go index 130add913..5a0c12eb7 100644 --- a/api/datastore/migrate_dbversion29_test.go +++ b/api/datastore/migrate_dbversion29_test.go @@ -48,6 +48,7 @@ func TestMigrateSettings(t *testing.T) { } m := migrator.NewMigrator(&migrator.MigratorParameters{ + Flags: store.flags, EndpointGroupService: store.EndpointGroupService, EndpointService: store.EndpointService, EndpointRelationService: store.EndpointRelationService, diff --git a/api/datastore/migrator/migrate_dbversion32.go b/api/datastore/migrator/migrate_dbversion32.go index 26cd207de..391e01ba3 100644 --- a/api/datastore/migrator/migrate_dbversion32.go +++ b/api/datastore/migrator/migrate_dbversion32.go @@ -1,8 +1,6 @@ package migrator import ( - portainer "github.com/portainer/portainer/api" - "github.com/rs/zerolog/log" ) @@ -20,7 +18,7 @@ func (m *Migrator) migrateSettingsToDB33() error { } log.Info().Msg("setting default kubectl shell image") - settings.KubectlShellImage = portainer.DefaultKubectlShellImage + settings.KubectlShellImage = *m.flags.KubectlShellImage return m.settingsService.UpdateSettings(settings) } diff --git a/api/datastore/migrator/migrator.go b/api/datastore/migrator/migrator.go index f4cfd91bf..dc92006ad 100644 --- a/api/datastore/migrator/migrator.go +++ b/api/datastore/migrator/migrator.go @@ -33,6 +33,7 @@ import ( type ( // Migrator defines a service to migrate data after a Portainer version update. Migrator struct { + flags *portainer.CLIFlags currentDBVersion *models.Version migrations []Migrations @@ -62,6 +63,7 @@ type ( // MigratorParameters represents the required parameters to create a new Migrator instance. MigratorParameters struct { + Flags *portainer.CLIFlags CurrentDBVersion *models.Version EndpointGroupService *endpointgroup.Service EndpointService *endpoint.Service @@ -91,6 +93,7 @@ type ( // NewMigrator creates a new Migrator. func NewMigrator(parameters *MigratorParameters) *Migrator { migrator := &Migrator{ + flags: parameters.Flags, currentDBVersion: parameters.CurrentDBVersion, endpointGroupService: parameters.EndpointGroupService, endpointService: parameters.EndpointService, diff --git a/api/datastore/services.go b/api/datastore/services.go index fc6904bde..0e9208f5c 100644 --- a/api/datastore/services.go +++ b/api/datastore/services.go @@ -42,6 +42,7 @@ import ( // Store defines the implementation of portainer.DataStore using // BoltDB as the storage system. type Store struct { + flags *portainer.CLIFlags connection portainer.Connection fileService portainer.FileService diff --git a/api/datastore/teststore.go b/api/datastore/teststore.go index d581f25b3..0945195b0 100644 --- a/api/datastore/teststore.go +++ b/api/datastore/teststore.go @@ -29,6 +29,10 @@ func MustNewTestStore(t testing.TB, init, secure bool) (bool, *Store) { func NewTestStore(t testing.TB, init, secure bool) (bool, *Store, func(), error) { // Creates unique temp directory in a concurrency friendly manner. storePath := t.TempDir() + defaultKubectlShellImage := portainer.DefaultKubectlShellImage + flags := &portainer.CLIFlags{ + KubectlShellImage: &defaultKubectlShellImage, + } fileService, err := filesystem.NewService(storePath, "") if err != nil { @@ -45,7 +49,7 @@ func NewTestStore(t testing.TB, init, secure bool) (bool, *Store, func(), error) panic(err) } - store := NewStore(storePath, fileService, connection) + store := NewStore(flags, fileService, connection) newStore, err := store.Open() if err != nil { return newStore, nil, nil, err diff --git a/api/portainer.go b/api/portainer.go index 5b5748e9b..f7f4668b9 100644 --- a/api/portainer.go +++ b/api/portainer.go @@ -133,6 +133,7 @@ type ( SecretKeyName *string LogLevel *string LogMode *string + KubectlShellImage *string } // CustomTemplateVariableDefinition @@ -1665,6 +1666,8 @@ const ( AuthCookieKey = "portainer_api_key" // PortainerCacheHeader is used to enabled FE caching for Kubernetes resources PortainerCacheHeader = "X-Portainer-Cache" + // KubectlShellImageEnvVar is the environment variable used to override the default kubectl shell image + KubectlShellImageEnvVar = "KUBECTL_SHELL_IMAGE" ) // List of supported features