envknob, health: support Synology, show parse errors in status

Updates #5114

Change-Id: I8ac7a22a511f5a7d0dcb8cac470d4a403aa8c817
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick 2022-09-16 20:24:28 -07:00 committed by Brad Fitzpatrick
parent 5c42990c2f
commit 3562b5bdfa
5 changed files with 66 additions and 39 deletions

View File

@ -131,11 +131,9 @@ var subCommands = map[string]*func([]string) error{
var beCLI func() // non-nil if CLI is linked in
var diskConfigErr error
func main() {
envknob.PanicIfAnyEnvCheckedInInit()
diskConfigErr = envknob.ApplyDiskConfig()
envknob.ApplyDiskConfig()
printVersion := false
flag.IntVar(&args.verbose, "verbose", 0, "log verbosity level; 0 is default, 1 or higher are increasingly verbose")
@ -313,8 +311,8 @@ func run() error {
pol.Shutdown(ctx)
}()
if diskConfigErr != nil {
log.Printf("Error reading environment config: %v", diskConfigErr)
if err := envknob.ApplyDiskConfigError(); err != nil {
log.Printf("Error reading environment config: %v", err)
}
if isWindowsService() {

View File

@ -197,8 +197,8 @@ func beWindowsSubprocess() bool {
log.Printf("Program starting: v%v: %#v", version.Long, os.Args)
log.Printf("subproc mode: logid=%v", logid)
if diskConfigErr != nil {
log.Printf("Error reading environment config: %v", diskConfigErr)
if err := envknob.ApplyDiskConfigError(); err != nil {
log.Printf("Error reading environment config: %v", err)
}
go func() {

View File

@ -22,6 +22,7 @@ import (
"io"
"log"
"os"
"path/filepath"
"runtime"
"sort"
"strconv"
@ -30,6 +31,7 @@ import (
"sync/atomic"
"tailscale.com/types/opt"
"tailscale.com/version/distro"
)
var (
@ -325,7 +327,10 @@ func PanicIfAnyEnvCheckedInInit() {
}
}
var platformApplyDiskConfig func() error
var applyDiskConfigErr error
// ApplyDiskConfigError returns the most recent result of ApplyDiskConfig.
func ApplyDiskConfigError() error { return applyDiskConfigErr }
// ApplyDiskConfig returns a platform-specific config file of environment keys/values and
// applies them. On Linux and Unix operating systems, it's a no-op and always returns nil.
@ -334,11 +339,59 @@ var platformApplyDiskConfig func() error
// It exists primarily for Windows to make it easy to apply environment variables to
// a running service in a way similar to modifying /etc/default/tailscaled on Linux.
// On Windows, you use %ProgramData%\Tailscale\tailscaled-env.txt instead.
func ApplyDiskConfig() error {
if f := platformApplyDiskConfig; f != nil {
return f()
func ApplyDiskConfig() (err error) {
var f *os.File
defer func() {
if err != nil {
// Stash away our return error for the healthcheck package to use.
applyDiskConfigErr = fmt.Errorf("error parsing %s: %w", f.Name(), err)
}
}()
// First try the explicitly-provided value for development testing. Not
// useful for users to use on their own. (if they can set this, they can set
// any environment variable anyway)
if name := os.Getenv("TS_DEBUG_ENV_FILE"); name != "" {
f, err = os.Open(name)
if err != nil {
return fmt.Errorf("error opening explicitly configured TS_DEBUG_ENV_FILE: %w", err)
}
defer f.Close()
return applyKeyValueEnv(f)
}
return nil
name := getPlatformEnvFile()
if name == "" {
return nil
}
f, err = os.Open(name)
if os.IsNotExist(err) {
return nil
}
if err != nil {
return err
}
defer f.Close()
return applyKeyValueEnv(f)
}
// getPlatformEnvFile returns the current platform's path to an optional
// tailscaled-env.txt file. It returns an empty string if none is defined
// for the platform.
func getPlatformEnvFile() string {
switch runtime.GOOS {
case "windows":
return filepath.Join(os.Getenv("ProgramData"), "Tailscale", "tailscaled-env.txt")
case "linux":
if distro.Get() == distro.Synology {
return "/etc/tailscale/tailscaled-env.txt"
}
case "darwin":
// TODO(bradfitz): figure this out. There are three ways to run
// Tailscale on macOS (tailscaled, GUI App Store, GUI System Extension)
// and we should deal with all three.
}
return ""
}
// applyKeyValueEnv reads key=value lines r and calls Setenv for each.

View File

@ -1,27 +0,0 @@
// Copyright (c) 2022 Tailscale Inc & AUTHORS All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package envknob
import (
"os"
"path/filepath"
)
func init() {
platformApplyDiskConfig = platformApplyDiskConfigWindows
}
func platformApplyDiskConfigWindows() error {
name := filepath.Join(os.Getenv("ProgramData"), "Tailscale", "tailscaled-env.txt")
f, err := os.Open(name)
if os.IsNotExist(err) {
return nil
}
if err != nil {
return err
}
defer f.Close()
return applyKeyValueEnv(f)
}

View File

@ -383,6 +383,9 @@ func overallErrorLocked() error {
for _, s := range controlHealth {
errs = append(errs, errors.New(s))
}
if err := envknob.ApplyDiskConfigError(); err != nil {
errs = append(errs, err)
}
if e := fakeErrForTesting(); len(errs) == 0 && e != "" {
return errors.New(e)
}