Skip to content

Commit aec3d45

Browse files
GT-49 | Show error when user tries to change value of "persistent" option (#366)
* Show error when user tries to change value of "persistent" option * Add same test for docker, refactoring * Fix after merge
1 parent 467f3be commit aec3d45

17 files changed

+548
-109
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
- Add sanity check for pass-through args usage
55
- Fix printing --starter.instance-up-timeout instead of hardcoded value
66
- Fix context handling in WaitUntilStarterReady for tests
7+
- Show error when user tries to change value of "persistent" option
78

89
## [0.15.8](https://github.com/arangodb-helper/arangodb/tree/0.15.8) (2023-06-02)
910
- Add passing ARANGODB_SERVER_DIR env variable when starting arangod instances

config.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2017-2022 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2017-2023 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -28,6 +28,8 @@ import (
2828
"github.com/pkg/errors"
2929
"github.com/spf13/pflag"
3030
"gopkg.in/ini.v1"
31+
32+
"github.com/arangodb-helper/arangodb/service/options"
3133
)
3234

3335
// loadCfgFromFile returns config loaded from file if file exists, nil otherwise
@@ -72,17 +74,20 @@ func trySetFlagFromConfig(flagName string, k *ini.Key, flagSets ...*pflag.FlagSe
7274
return nil
7375
}
7476

75-
prefix, targ, err := passthroughPrefixes.Lookup(flagName)
77+
prefix, confPrefix, targ, err := passthroughPrefixes.Lookup(flagName)
7678
if err != nil {
7779
return errors.Wrapf(err, "invalid key %s", flagName)
7880
}
79-
if prefix != nil {
80-
valuePtr := prefix.FieldSelector(passthroughOpts, targ)
81+
if confPrefix != nil {
82+
valuePtr := confPrefix.FieldSelector(passthroughOpts, targ)
8183
if *valuePtr == nil {
8284
*valuePtr = k.ValueWithShadows()
8385
} else {
8486
*valuePtr = append(*valuePtr, k.ValueWithShadows()...)
8587
}
88+
if options.IsPersistentOption(targ) {
89+
passthroughOpts.PersistentOptions.Add(prefix, targ, valuePtr)
90+
}
8691
return nil
8792
}
8893
return fmt.Errorf("unknown key %s", flagName)
@@ -124,7 +129,7 @@ func loadFlagValuesFromConfig(cfgFilePath string, fs, persistentFs *pflag.FlagSe
124129
// example: --args.all.log.line-number --args.all.log.performance=true
125130
func sanityCheckPassThroughArgs(fs, persistentFs *pflag.FlagSet) {
126131
sanityCheck := func(flag *pflag.Flag) {
127-
if found, _, _ := passthroughPrefixes.Lookup(flag.Name); found != nil {
132+
if _, found, _, _ := passthroughPrefixes.Lookup(flag.Name); found != nil {
128133
if flag.Value == nil {
129134
return
130135
}

main.go

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -477,10 +477,19 @@ func cmdMainRun(cmd *cobra.Command, args []string) {
477477
}
478478

479479
// Read setup.json (if exists)
480-
bsCfg, clusterConfig, relaunch, _ := service.ReadSetupConfig(log, opts.starter.dataDir, bsCfg)
480+
setupConfig, relaunch, _ := service.ReadSetupConfig(log, opts.starter.dataDir)
481+
if relaunch {
482+
oldOpts := setupConfig.Peers.PersistentOptions
483+
newOpts := passthroughOpts.PersistentOptions
484+
if err := oldOpts.ValidateCompatibility(&newOpts); err != nil {
485+
log.Error().Err(err).Msg("Please check pass-through options")
486+
}
487+
488+
bsCfg.LoadFromSetupConfig(setupConfig)
489+
}
481490

482491
// Run the service
483-
if err := svc.Run(rootCtx, bsCfg, clusterConfig, relaunch); err != nil {
492+
if err := svc.Run(rootCtx, bsCfg, setupConfig.Peers, relaunch); err != nil {
484493
log.Fatal().Err(err).Msg("Failed to run service")
485494
}
486495
}

service/bootstrap_config.go

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2017-2023 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -17,8 +17,6 @@
1717
//
1818
// Copyright holder is ArangoDB GmbH, Cologne, Germany
1919
//
20-
// Author Ewout Prangsma
21-
//
2220

2321
package service
2422

@@ -54,11 +52,11 @@ type BootstrapConfig struct {
5452
RecoveryAgentID string `json:"-"` // ID of the agent. Only set during recovery
5553
}
5654

57-
func (bsCfg BootstrapConfig) JWTFolderDir() string {
55+
func (bsCfg *BootstrapConfig) JWTFolderDir() string {
5856
return path.Join(bsCfg.DataDir, definitions.ArangodJWTSecretFolderName)
5957
}
6058

61-
func (bsCfg BootstrapConfig) JWTFolderDirFile(f string) string {
59+
func (bsCfg *BootstrapConfig) JWTFolderDirFile(f string) string {
6260
return path.Join(bsCfg.DataDir, definitions.ArangodJWTSecretFolderName, f)
6361
}
6462

@@ -76,7 +74,7 @@ func (bsCfg *BootstrapConfig) Initialize() error {
7674
}
7775

7876
// CreateTLSConfig creates a TLS config based on given bootstrap config
79-
func (bsCfg BootstrapConfig) CreateTLSConfig() (*tls.Config, error) {
77+
func (bsCfg *BootstrapConfig) CreateTLSConfig() (*tls.Config, error) {
8078
if bsCfg.SslKeyFile == "" {
8179
return nil, nil
8280
}
@@ -90,7 +88,7 @@ func (bsCfg BootstrapConfig) CreateTLSConfig() (*tls.Config, error) {
9088
}
9189

9290
// PeersNeeded returns the minimum number of peers needed for the given config.
93-
func (bsCfg BootstrapConfig) PeersNeeded() int {
91+
func (bsCfg *BootstrapConfig) PeersNeeded() int {
9492
minServers := 1
9593
switch {
9694
case bsCfg.Mode.IsClusterMode():
@@ -105,3 +103,20 @@ func (bsCfg BootstrapConfig) PeersNeeded() int {
105103
}
106104
return minServers
107105
}
106+
107+
// LoadFromSetupConfig loads important values from setup config file
108+
func (bsCfg *BootstrapConfig) LoadFromSetupConfig(cfg SetupConfigFile) {
109+
// Reload data from config
110+
bsCfg.ID = cfg.ID
111+
if cfg.Mode != "" {
112+
bsCfg.Mode = cfg.Mode
113+
}
114+
bsCfg.StartLocalSlaves = cfg.StartLocalSlaves
115+
if cfg.SslKeyFile != "" {
116+
bsCfg.SslKeyFile = cfg.SslKeyFile
117+
}
118+
if cfg.JwtSecret != "" {
119+
bsCfg.JwtSecret = cfg.JwtSecret
120+
}
121+
bsCfg.AgencySize = cfg.Peers.AgencySize
122+
}

service/bootstrap_master.go

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2017-2023 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -17,8 +17,6 @@
1717
//
1818
// Copyright holder is ArangoDB GmbH, Cologne, Germany
1919
//
20-
// Author Ewout Prangsma
21-
//
2220

2321
package service
2422

@@ -58,12 +56,10 @@ func (s *Service) bootstrapMaster(ctx context.Context, runner Runner, config Con
5856
hasResilientSingle := boolFromRef(bsCfg.StartResilientSingle, s.mode.IsActiveFailoverMode())
5957
hasSyncMaster := boolFromRef(bsCfg.StartSyncMaster, true) && config.SyncEnabled
6058
hasSyncWorker := boolFromRef(bsCfg.StartSyncWorker, true) && config.SyncEnabled
61-
s.myPeers.Initialize(
62-
NewPeer(s.id, config.OwnAddress, s.announcePort, 0, config.DataDir,
63-
hasAgent, hasDBServer, hasCoordinator, hasResilientSingle,
64-
hasSyncMaster, hasSyncWorker,
65-
s.IsSecure()),
66-
bsCfg.AgencySize, storageEngine)
59+
me := NewPeer(s.id, config.OwnAddress, s.announcePort, 0, config.DataDir,
60+
hasAgent, hasDBServer, hasCoordinator, hasResilientSingle,
61+
hasSyncMaster, hasSyncWorker, s.IsSecure())
62+
s.myPeers.Initialize(me, bsCfg.AgencySize, storageEngine, s.cfg.Configuration.PersistentOptions)
6763
s.learnOwnAddress = config.OwnAddress == ""
6864

6965
// Start HTTP listener

service/cluster_config.go

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2017-2021 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2017-2023 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -17,9 +17,6 @@
1717
//
1818
// Copyright holder is ArangoDB GmbH, Cologne, Germany
1919
//
20-
// Author Ewout Prangsma
21-
// Author Tomasz Mielech
22-
//
2320

2421
package service
2522

@@ -38,16 +35,18 @@ import (
3835
"github.com/arangodb/go-driver/jwt"
3936

4037
"github.com/arangodb-helper/arangodb/pkg/definitions"
38+
"github.com/arangodb-helper/arangodb/service/options"
4139
)
4240

43-
// ClusterConfig contains all the informtion of a cluster from a starter's point of view.
41+
// ClusterConfig contains all the information of a cluster from a starter's point of view.
4442
// When this type (or any of the types used in here) is changed, increase `SetupConfigVersion`.
4543
type ClusterConfig struct {
46-
AllPeers []Peer `json:"Peers"` // All peers
47-
AgencySize int // Number of agents
48-
LastModified *time.Time `json:"LastModified,omitempty"` // Time of last modification
49-
PortOffsetIncrement int `json:"PortOffsetIncrement,omitempty"` // Increment of port offsets for peers on same address
50-
ServerStorageEngine string `json:ServerStorageEngine,omitempty"` // Storage engine being used
44+
AllPeers []Peer `json:"Peers"` // All peers
45+
AgencySize int // Number of agents
46+
LastModified *time.Time `json:"LastModified,omitempty"` // Time of last modification
47+
PortOffsetIncrement int `json:"PortOffsetIncrement,omitempty"` // Increment of port offsets for peers on same address
48+
ServerStorageEngine string `json:"ServerStorageEngine,omitempty"` // Storage engine being used
49+
PersistentOptions options.PersistentOptions `json:"PersistentOptions,omitempty"` // Options which were used during first start of DB and can't be changed anymore
5150
}
5251

5352
// PeerByID returns a peer with given id & true, or false if not found.
@@ -83,11 +82,12 @@ func (p ClusterConfig) AllAgents() []Peer {
8382
}
8483

8584
// Initialize a new cluster configuration
86-
func (p *ClusterConfig) Initialize(initialPeer Peer, agencySize int, storageEngine string) {
85+
func (p *ClusterConfig) Initialize(initialPeer Peer, agencySize int, storageEngine string, persistentOptions options.PersistentOptions) {
8786
p.AllPeers = []Peer{initialPeer}
8887
p.AgencySize = agencySize
8988
p.PortOffsetIncrement = definitions.PortOffsetIncrementNew
9089
p.ServerStorageEngine = storageEngine
90+
p.PersistentOptions = persistentOptions
9191
p.updateLastModified()
9292
}
9393

service/local_slaves.go

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2017 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2017-2023 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -17,8 +17,6 @@
1717
//
1818
// Copyright holder is ArangoDB GmbH, Cologne, Germany
1919
//
20-
// Author Ewout Prangsma
21-
//
2220

2321
package service
2422

@@ -69,15 +67,25 @@ func (s *Service) startLocalSlaves(wg *sync.WaitGroup, config Config, bsCfg Boot
6967
os.MkdirAll(p.DataDir, 0755)
7068

7169
// Read existing setup.json (if any)
72-
slaveBsCfg, clusterConfig, relaunch, _ := ReadSetupConfig(slaveLog, p.DataDir, slaveBsCfg)
70+
setupConfig, relaunch, _ := ReadSetupConfig(slaveLog, p.DataDir)
71+
if relaunch {
72+
oldOpts := setupConfig.Peers.PersistentOptions
73+
newOpts := config.Configuration.PersistentOptions
74+
if err := oldOpts.ValidateCompatibility(&newOpts); err != nil {
75+
s.log.Error().Err(err).Msg("Please check pass-through options")
76+
}
77+
78+
slaveBsCfg.LoadFromSetupConfig(setupConfig)
79+
}
80+
7381
slaveConfig := config // Create copy
7482
slaveConfig.DataDir = p.DataDir
7583
slaveConfig.MasterAddresses = []string{masterAddr}
7684
slaveService := NewService(s.stopPeer.ctx, slaveLog, s.logService, slaveConfig, bsCfg, true)
7785
wg.Add(1)
7886
go func() {
7987
defer wg.Done()
80-
if err := slaveService.Run(s.stopPeer.ctx, slaveBsCfg, clusterConfig, relaunch); err != nil {
88+
if err := slaveService.Run(s.stopPeer.ctx, slaveBsCfg, setupConfig.Peers, relaunch); err != nil {
8189
s.log.Error().Str("peer", p.ID).Err(err).Msg("Unable to start one of peers")
8290
}
8391
}()

service/options/options.go

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// DISCLAIMER
33
//
4-
// Copyright 2021 ArangoDB GmbH, Cologne, Germany
4+
// Copyright 2021-2023 ArangoDB GmbH, Cologne, Germany
55
//
66
// Licensed under the Apache License, Version 2.0 (the "License");
77
// you may not use this file except in compliance with the License.
@@ -17,8 +17,6 @@
1717
//
1818
// Copyright holder is ArangoDB GmbH, Cologne, Germany
1919
//
20-
// Author Adam Janikowski
21-
//
2220

2321
package options
2422

@@ -41,6 +39,8 @@ type Configuration struct {
4139
AllSync ConfigurationType
4240
SyncMasters ConfigurationType
4341
SyncWorkers ConfigurationType
42+
43+
PersistentOptions PersistentOptions
4444
}
4545

4646
func NewConfiguration() Configuration {
@@ -212,19 +212,19 @@ type ConfigurationFlag struct {
212212

213213
type ConfigurationPrefixes map[string]ConfigurationPrefix
214214

215-
func (c ConfigurationPrefixes) Lookup(key string) (*ConfigurationPrefix, string, error) {
215+
func (c ConfigurationPrefixes) Lookup(key string) (string, *ConfigurationPrefix, string, error) {
216216
for n, prefix := range c {
217217
p := fmt.Sprintf("%s.", n)
218218
if strings.HasPrefix(key, p) {
219219
targ := strings.TrimPrefix(key, p)
220220
if forbiddenOptions.IsForbidden(targ) {
221-
return nil, "", fmt.Errorf("option --%s is essential to the starters behavior and cannot be overwritten", targ)
221+
return n, nil, "", fmt.Errorf("option --%s is essential to the starters behavior and cannot be overwritten", targ)
222222
}
223223
prefix := prefix
224-
return &prefix, targ, nil
224+
return n, &prefix, targ, nil
225225
}
226226
}
227-
return nil, "", nil
227+
return "", nil, "", nil
228228
}
229229

230230
func (c ConfigurationPrefixes) Parse(args ...string) (*Configuration, []ConfigurationFlag, error) {
@@ -239,12 +239,12 @@ func (c ConfigurationPrefixes) Parse(args ...string) (*Configuration, []Configur
239239
continue
240240
}
241241

242-
ckey := strings.TrimPrefix(arg, "--")
243-
prefix, targ, err := c.Lookup(ckey)
242+
cleanKey := strings.TrimPrefix(arg, "--")
243+
prefix, confPrefix, targ, err := c.Lookup(cleanKey)
244244
if err != nil {
245245
return nil, nil, err
246246
}
247-
if prefix == nil {
247+
if confPrefix == nil {
248248
continue
249249
}
250250

@@ -254,14 +254,19 @@ func (c ConfigurationPrefixes) Parse(args ...string) (*Configuration, []Configur
254254
flags[arg] = true
255255
}
256256

257+
val := confPrefix.FieldSelector(&config, targ)
257258
f = append(f, ConfigurationFlag{
258259
Key: arg,
259-
CleanKey: ckey,
260+
CleanKey: cleanKey,
260261
Extension: targ,
261-
Usage: prefix.Usage(targ),
262-
Value: prefix.FieldSelector(&config, targ),
263-
DeprecatedHint: prefix.GetDeprecatedHint(targ),
262+
Usage: confPrefix.Usage(targ),
263+
Value: val,
264+
DeprecatedHint: confPrefix.GetDeprecatedHint(targ),
264265
})
266+
267+
if IsPersistentOption(targ) {
268+
config.PersistentOptions.Add(prefix, targ, val)
269+
}
265270
}
266271

267272
return &config, f, nil

0 commit comments

Comments
 (0)