tsnet: reset serve config only once
Prior to this change, we were resetting the tsnet's serve config every time tsnet.Server.Up was run. This is important to do on startup, to prevent messy interactions with stale configuration when the code has changed. However, Up is frequently run as a just-in-case step (for example, by Server.ListenTLS/ListenFunnel and possibly by consumers of tsnet). When the serve config is reset on each of these calls to Up, this creates situations in which the serve config disappears unexpectedly. The solution is to reset the serve config only on the first call to Up. Fixes #8800 Updates tailscale/corp#27200 Signed-off-by: Harry Harpham <harry@tailscale.com>
This commit is contained in:
+12
-7
@@ -176,6 +176,7 @@ type Server struct {
|
|||||||
localAPIListener net.Listener // in-memory, used by localClient
|
localAPIListener net.Listener // in-memory, used by localClient
|
||||||
localClient *local.Client // in-memory
|
localClient *local.Client // in-memory
|
||||||
localAPIServer *http.Server
|
localAPIServer *http.Server
|
||||||
|
resetServeConfigOnce sync.Once
|
||||||
logbuffer *filch.Filch
|
logbuffer *filch.Filch
|
||||||
logtail *logtail.Logger
|
logtail *logtail.Logger
|
||||||
logid logid.PublicID
|
logid logid.PublicID
|
||||||
@@ -388,8 +389,8 @@ func (s *Server) Up(ctx context.Context) (*ipnstate.Status, error) {
|
|||||||
if n.ErrMessage != nil {
|
if n.ErrMessage != nil {
|
||||||
return nil, fmt.Errorf("tsnet.Up: backend: %s", *n.ErrMessage)
|
return nil, fmt.Errorf("tsnet.Up: backend: %s", *n.ErrMessage)
|
||||||
}
|
}
|
||||||
if s := n.State; s != nil {
|
if st := n.State; st != nil {
|
||||||
if *s == ipn.Running {
|
if *st == ipn.Running {
|
||||||
status, err := lc.Status(ctx)
|
status, err := lc.Status(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("tsnet.Up: %w", err)
|
return nil, fmt.Errorf("tsnet.Up: %w", err)
|
||||||
@@ -398,11 +399,15 @@ func (s *Server) Up(ctx context.Context) (*ipnstate.Status, error) {
|
|||||||
return nil, errors.New("tsnet.Up: running, but no ip")
|
return nil, errors.New("tsnet.Up: running, but no ip")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the persisted serve config state to prevent stale configuration
|
// The first time Up is run, clear the persisted serve config.
|
||||||
// from code changes. This is a temporary workaround until we have a better
|
// We do this to prevent messy interactions with stale config in
|
||||||
// way to handle this. (2023-03-11)
|
// the face of code changes.
|
||||||
if err := lc.SetServeConfig(ctx, new(ipn.ServeConfig)); err != nil {
|
var srvResetErr error
|
||||||
return nil, fmt.Errorf("tsnet.Up: %w", err)
|
s.resetServeConfigOnce.Do(func() {
|
||||||
|
srvResetErr = lc.SetServeConfig(ctx, new(ipn.ServeConfig))
|
||||||
|
})
|
||||||
|
if srvResetErr != nil {
|
||||||
|
return nil, fmt.Errorf("tsnet.Up: clearing serve config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return status, nil
|
return status, nil
|
||||||
|
|||||||
Reference in New Issue
Block a user