feat(templates): fix an issue with templates initialization and update settings view

2.0
Anthony Lapenna 2020-04-16 12:22:08 +12:00
parent 5563ff60fc
commit f371dc5402
6 changed files with 91 additions and 104 deletions

View File

@ -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)
}

View File

@ -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

View File

@ -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)

View File

@ -73,6 +73,7 @@ type (
Open() error
Init() error
Close() error
IsNew() bool
MigrateData() error
}

View File

@ -46,16 +46,7 @@
<div class="col-sm-12 form-section-title">
App Templates
</div>
<div class="form-group">
<div class="col-sm-12">
<label for="toggle_templates" class="control-label text-left">
Use external templates
<portainer-tooltip position="bottom" message="When using external templates, in-app template management will be disabled."></portainer-tooltip>
</label>
<label class="switch" style="margin-left: 20px;"> <input type="checkbox" name="toggle_templates" ng-model="formValues.externalTemplates" /><i></i> </label>
</div>
</div>
<div ng-if="formValues.externalTemplates">
<div>
<div class="form-group">
<span class="col-sm-12 text-muted small">
You can specify the URL to your own template definitions file here. See
@ -67,7 +58,7 @@
URL
</label>
<div class="col-sm-11">
<input type="text" class="form-control" ng-model="settings.TemplatesURL" id="templates_url" placeholder="https://myserver.mydomain/templates.json" />
<input type="text" class="form-control" ng-model="settings.TemplatesURL" id="templates_url" placeholder="https://myserver.mydomain/templates.json" required/>
</div>
</div>
</div>
@ -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"
>
<span ng-hide="state.actionInProgress">Save settings</span>

View File

@ -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;