ipn/ipnlocal: reload prefs correctly on ReloadConfig

We were only updating the ProfileManager and not going down
the EditPrefs path which meant the prefs weren't applied
till either the process restarted or some other pref changed.

This makes it so that we reconfigure everything correctly when
ReloadConfig is called.

Updates #13032

Signed-off-by: Maisem Ali <maisem@tailscale.com>
maisem/fix-reloading
Maisem Ali 16 hours ago
parent 45354dab9b
commit 78e815584d

@ -479,7 +479,7 @@ func NewLocalBackend(logf logger.Logf, logID logid.PublicID, sys *tsd.System, lo
mConn.SetNetInfoCallback(b.setNetInfo) mConn.SetNetInfoCallback(b.setNetInfo)
if sys.InitialConfig != nil { if sys.InitialConfig != nil {
if err := b.setConfigLocked(sys.InitialConfig); err != nil { if err := b.initPrefsFromConfig(sys.InitialConfig); err != nil {
return nil, err return nil, err
} }
} }
@ -712,8 +712,8 @@ func (b *LocalBackend) SetDirectFileRoot(dir string) {
// It returns (false, nil) if not running in declarative mode, (true, nil) on // It returns (false, nil) if not running in declarative mode, (true, nil) on
// success, or (false, error) on failure. // success, or (false, error) on failure.
func (b *LocalBackend) ReloadConfig() (ok bool, err error) { func (b *LocalBackend) ReloadConfig() (ok bool, err error) {
b.mu.Lock() unlock := b.lockAndGetUnlock()
defer b.mu.Unlock() defer unlock()
if b.conf == nil { if b.conf == nil {
return false, nil return false, nil
} }
@ -721,18 +721,21 @@ func (b *LocalBackend) ReloadConfig() (ok bool, err error) {
if err != nil { if err != nil {
return false, err return false, err
} }
if err := b.setConfigLocked(conf); err != nil { if err := b.setConfigLockedOnEntry(conf, unlock); err != nil {
return false, fmt.Errorf("error setting config: %w", err) return false, fmt.Errorf("error setting config: %w", err)
} }
return true, nil return true, nil
} }
func (b *LocalBackend) setConfigLocked(conf *conffile.Config) error { // initPrefsFromConfig initializes the backend's prefs from the provided config.
// This should only be called once, at startup. For updates at runtime, use
// TODO(irbekrm): notify the relevant components to consume any prefs // [LocalBackend.setConfigLocked].
// updates. Currently only initial configfile settings are applied func (b *LocalBackend) initPrefsFromConfig(conf *conffile.Config) error {
// immediately. // TODO(maisem,bradfitz): combine this with setConfigLocked. This is called
// before anything is running, so there's no need to lock and we don't
// update any subsystems. At runtime, we both need to lock and update
// subsystems with the new prefs.
p := b.pm.CurrentPrefs().AsStruct() p := b.pm.CurrentPrefs().AsStruct()
mp, err := conf.Parsed.ToPrefs() mp, err := conf.Parsed.ToPrefs()
if err != nil { if err != nil {
@ -742,13 +745,14 @@ func (b *LocalBackend) setConfigLocked(conf *conffile.Config) error {
if err := b.pm.SetPrefs(p.View(), ipn.NetworkProfile{}); err != nil { if err := b.pm.SetPrefs(p.View(), ipn.NetworkProfile{}); err != nil {
return err return err
} }
b.setStaticEndpointsFromConfigLocked(conf)
defer func() {
b.conf = conf b.conf = conf
}() return nil
}
func (b *LocalBackend) setStaticEndpointsFromConfigLocked(conf *conffile.Config) {
if conf.Parsed.StaticEndpoints == nil && (b.conf == nil || b.conf.Parsed.StaticEndpoints == nil) { if conf.Parsed.StaticEndpoints == nil && (b.conf == nil || b.conf.Parsed.StaticEndpoints == nil) {
return nil return
} }
// Ensure that magicsock conn has the up to date static wireguard // Ensure that magicsock conn has the up to date static wireguard
@ -762,6 +766,22 @@ func (b *LocalBackend) setConfigLocked(conf *conffile.Config) error {
ms.SetStaticEndpoints(views.SliceOf(conf.Parsed.StaticEndpoints)) ms.SetStaticEndpoints(views.SliceOf(conf.Parsed.StaticEndpoints))
} }
} }
}
// setConfigLockedOnEntry uses the provided config to update the backend's prefs
// and other state.
func (b *LocalBackend) setConfigLockedOnEntry(conf *conffile.Config, unlock unlockOnce) error {
defer unlock()
p := b.pm.CurrentPrefs().AsStruct()
mp, err := conf.Parsed.ToPrefs()
if err != nil {
return fmt.Errorf("error parsing config to prefs: %w", err)
}
p.ApplyEdits(&mp)
b.setStaticEndpointsFromConfigLocked(conf)
b.setPrefsLockedOnEntry(p, unlock)
b.conf = conf
return nil return nil
} }

Loading…
Cancel
Save