diff --git a/api/bolt/datastore.go b/api/bolt/datastore.go index 18f025d73..c4b51ba31 100644 --- a/api/bolt/datastore.go +++ b/api/bolt/datastore.go @@ -5,16 +5,14 @@ import ( "path" "time" - "github.com/portainer/portainer/api/bolt/edgegroup" - "github.com/portainer/portainer/api/bolt/edgestack" - "github.com/portainer/portainer/api/bolt/endpointrelation" - "github.com/portainer/portainer/api/bolt/tunnelserver" - "github.com/boltdb/bolt" "github.com/portainer/portainer/api" "github.com/portainer/portainer/api/bolt/dockerhub" + "github.com/portainer/portainer/api/bolt/edgegroup" + "github.com/portainer/portainer/api/bolt/edgestack" "github.com/portainer/portainer/api/bolt/endpoint" "github.com/portainer/portainer/api/bolt/endpointgroup" + "github.com/portainer/portainer/api/bolt/endpointrelation" "github.com/portainer/portainer/api/bolt/extension" "github.com/portainer/portainer/api/bolt/migrator" "github.com/portainer/portainer/api/bolt/registry" @@ -26,6 +24,7 @@ import ( "github.com/portainer/portainer/api/bolt/tag" "github.com/portainer/portainer/api/bolt/team" "github.com/portainer/portainer/api/bolt/teammembership" + "github.com/portainer/portainer/api/bolt/tunnelserver" "github.com/portainer/portainer/api/bolt/user" "github.com/portainer/portainer/api/bolt/version" "github.com/portainer/portainer/api/bolt/webhook" @@ -40,7 +39,7 @@ const ( type Store struct { path string db *bolt.DB - checkForDataMigration bool + isNew bool fileService portainer.FileService RoleService *role.Service DockerHubService *dockerhub.Service @@ -69,6 +68,7 @@ func NewStore(storePath string, fileService portainer.FileService) (*Store, erro store := &Store{ path: storePath, fileService: fileService, + isNew: true, } databasePath := path.Join(storePath, databaseFileName) @@ -77,10 +77,8 @@ func NewStore(storePath string, fileService portainer.FileService) (*Store, erro return nil, err } - if !databaseFileExists { - store.checkForDataMigration = false - } else { - store.checkForDataMigration = true + if databaseFileExists { + store.isNew = false } return store, nil @@ -106,9 +104,16 @@ func (store *Store) Close() error { return nil } +// IsNew returns true if the database was just created and false if it is re-using +// existing data. +func (store *Store) IsNew() bool { + return store.isNew +} + // MigrateData automatically migrate the data based on the DBVersion. +// This process is only triggered on an existing database, not if the database was just created. func (store *Store) MigrateData() error { - if !store.checkForDataMigration { + if store.isNew { return store.VersionService.StoreDBVersion(portainer.DBVersion) } diff --git a/api/bolt/init.go b/api/bolt/init.go index 8e1a0661c..cc0a0f261 100644 --- a/api/bolt/init.go +++ b/api/bolt/init.go @@ -4,6 +4,55 @@ import portainer "github.com/portainer/portainer/api" // Init creates the default data set. func (store *Store) Init() error { + _, err := store.SettingsService.Settings() + if err == portainer.ErrObjectNotFound { + defaultSettings := &portainer.Settings{ + AuthenticationMethod: portainer.AuthenticationInternal, + BlackListedLabels: make([]portainer.Pair, 0), + LDAPSettings: portainer.LDAPSettings{ + AnonymousMode: true, + AutoCreateUsers: true, + TLSConfig: portainer.TLSConfiguration{}, + SearchSettings: []portainer.LDAPSearchSettings{ + portainer.LDAPSearchSettings{}, + }, + GroupSearchSettings: []portainer.LDAPGroupSearchSettings{ + portainer.LDAPGroupSearchSettings{}, + }, + }, + OAuthSettings: portainer.OAuthSettings{}, + AllowBindMountsForRegularUsers: true, + AllowPrivilegedModeForRegularUsers: true, + AllowVolumeBrowserForRegularUsers: false, + EnableHostManagementFeatures: false, + EdgeAgentCheckinInterval: portainer.DefaultEdgeAgentCheckinIntervalInSeconds, + TemplatesURL: portainer.DefaultTemplatesURL, + } + + err = store.SettingsService.UpdateSettings(defaultSettings) + if err != nil { + return err + } + } else if err != nil { + return err + } + + _, err = store.DockerHubService.DockerHub() + if err == portainer.ErrObjectNotFound { + defaultDockerHub := &portainer.DockerHub{ + Authentication: false, + Username: "", + Password: "", + } + + err := store.DockerHubService.UpdateDockerHub(defaultDockerHub) + if err != nil { + return err + } + } else if err != nil { + return err + } + groups, err := store.EndpointGroupService.EndpointGroups() if err != nil { return err diff --git a/api/cmd/portainer/main.go b/api/cmd/portainer/main.go index 39c9bac92..795c2b473 100644 --- a/api/cmd/portainer/main.go +++ b/api/cmd/portainer/main.go @@ -235,73 +235,24 @@ func initStatus(endpointManagement, snapshot bool, flags *portainer.CLIFlags) *p } } -func initDockerHub(dockerHubService portainer.DockerHubService) error { - _, err := dockerHubService.DockerHub() - if err == portainer.ErrObjectNotFound { - dockerhub := &portainer.DockerHub{ - Authentication: false, - Username: "", - Password: "", - } - return dockerHubService.UpdateDockerHub(dockerhub) - } else if err != nil { - return err - } - - return nil -} - -func initSettings(settingsService portainer.SettingsService, flags *portainer.CLIFlags) error { - _, err := settingsService.Settings() - if err == portainer.ErrObjectNotFound { - settings := &portainer.Settings{ - LogoURL: *flags.Logo, - AuthenticationMethod: portainer.AuthenticationInternal, - LDAPSettings: portainer.LDAPSettings{ - AnonymousMode: true, - AutoCreateUsers: true, - TLSConfig: portainer.TLSConfiguration{}, - SearchSettings: []portainer.LDAPSearchSettings{ - portainer.LDAPSearchSettings{}, - }, - GroupSearchSettings: []portainer.LDAPGroupSearchSettings{ - portainer.LDAPGroupSearchSettings{}, - }, - }, - OAuthSettings: portainer.OAuthSettings{}, - AllowBindMountsForRegularUsers: true, - AllowPrivilegedModeForRegularUsers: true, - AllowVolumeBrowserForRegularUsers: false, - EnableHostManagementFeatures: false, - SnapshotInterval: *flags.SnapshotInterval, - EdgeAgentCheckinInterval: portainer.DefaultEdgeAgentCheckinIntervalInSeconds, - TemplatesURL: portainer.DefaultTemplatesURL, - } - - if *flags.Templates != "" { - settings.TemplatesURL = *flags.Templates - } - - if *flags.Labels != nil { - settings.BlackListedLabels = *flags.Labels - } else { - settings.BlackListedLabels = make([]portainer.Pair, 0) - } - - return settingsService.UpdateSettings(settings) - } else if err != nil { - return err - } - - return nil -} - -func retrieveFirstEndpointFromDatabase(endpointService portainer.EndpointService) *portainer.Endpoint { - endpoints, err := endpointService.Endpoints() +func updateSettingsFromFlags(settingsService portainer.SettingsService, flags *portainer.CLIFlags) error { + settings, err := settingsService.Settings() if err != nil { - log.Fatal(err) + return err } - return &endpoints[0] + + settings.LogoURL = *flags.Logo + settings.SnapshotInterval = *flags.SnapshotInterval + + if *flags.Templates != "" { + settings.TemplatesURL = *flags.Templates + } + + if *flags.Labels != nil { + settings.BlackListedLabels = *flags.Labels + } + + return settingsService.UpdateSettings(settings) } func loadAndParseKeyPair(fileService portainer.FileService, signatureService portainer.DigitalSignatureService) error { @@ -522,9 +473,11 @@ func main() { composeStackManager := initComposeStackManager(*flags.Data, reverseTunnelService) - err = initSettings(store.SettingsService, flags) - if err != nil { - log.Fatal(err) + if store.IsNew() { + err = updateSettingsFromFlags(store.SettingsService, flags) + if err != nil { + log.Fatal(err) + } } jobScheduler := initJobScheduler() @@ -548,11 +501,6 @@ func main() { jobScheduler.Start() - err = initDockerHub(store.DockerHubService) - if err != nil { - log.Fatal(err) - } - applicationStatus := initStatus(endpointManagement, *flags.Snapshot, flags) err = initEndpoint(flags, store.EndpointService, snapshotter) diff --git a/api/portainer.go b/api/portainer.go index 3b51f86c6..d311acc5c 100644 --- a/api/portainer.go +++ b/api/portainer.go @@ -73,6 +73,7 @@ type ( Open() error Init() error Close() error + IsNew() bool MigrateData() error } diff --git a/app/portainer/views/settings/settings.html b/app/portainer/views/settings/settings.html index 3f3da4b74..0de6b5fea 100644 --- a/app/portainer/views/settings/settings.html +++ b/app/portainer/views/settings/settings.html @@ -46,16 +46,7 @@
App Templates
-
-
- - -
-
-
+
You can specify the URL to your own template definitions file here. See @@ -67,7 +58,7 @@ URL
- +
@@ -157,7 +148,7 @@ type="button" class="btn btn-primary btn-sm" ng-click="saveApplicationSettings()" - ng-disabled="state.actionInProgress" + ng-disabled="state.actionInProgress || !settings.TemplatesURL" button-spinner="state.actionInProgress" > Save settings diff --git a/app/portainer/views/settings/settingsController.js b/app/portainer/views/settings/settingsController.js index eba237506..f2c766c34 100644 --- a/app/portainer/views/settings/settingsController.js +++ b/app/portainer/views/settings/settingsController.js @@ -25,7 +25,6 @@ angular.module('portainer.app').controller('SettingsController', [ $scope.formValues = { customLogo: false, - externalTemplates: false, restrictBindMounts: false, restrictPrivilegedMode: false, labelName: '', @@ -60,10 +59,6 @@ angular.module('portainer.app').controller('SettingsController', [ settings.LogoURL = ''; } - if (!$scope.formValues.externalTemplates) { - settings.TemplatesURL = ''; - } - settings.AllowBindMountsForRegularUsers = !$scope.formValues.restrictBindMounts; settings.AllowPrivilegedModeForRegularUsers = !$scope.formValues.restrictPrivilegedMode; settings.AllowVolumeBrowserForRegularUsers = $scope.formValues.enableVolumeBrowser; @@ -98,12 +93,10 @@ angular.module('portainer.app').controller('SettingsController', [ .then(function success(data) { var settings = data; $scope.settings = settings; + if (settings.LogoURL !== '') { $scope.formValues.customLogo = true; } - if (settings.TemplatesURL !== '') { - $scope.formValues.externalTemplates = true; - } $scope.formValues.restrictBindMounts = !settings.AllowBindMountsForRegularUsers; $scope.formValues.restrictPrivilegedMode = !settings.AllowPrivilegedModeForRegularUsers; $scope.formValues.enableVolumeBrowser = settings.AllowVolumeBrowserForRegularUsers;