mirror of
https://github.com/tailscale/tailscale.git
synced 2025-08-13 14:43:19 +00:00
ipn,cmd/tailscale/cli: support hierarchical MaskedPrefs (#10507)
Some fields if `ipn.Prefs` are structs. `ipn.MaskedPrefs` has a single level of boolean `*Set` flags, which doesn't map well to nested structs within `ipn.Prefs`. Change `MaskedPrefs` and `ApplyEdits` to support `FooSet` struct fields that map to a nested struct of `ipn.Prefs` like `AutoUpdates`. Each struct field in `MaskedPrefs` is just a bundle of more `Set` bool fields or other structs. This allows you to have a `Set` flag for any arbitrarily-nested field of `ipn.Prefs`. Also, make `ApplyEdits` match fields between `Prefs` and `MaskedPrefs` by name instead of order, to make it a bit less finicky. It's probably slower but `ipn.ApplyEdits` should not be in any hot path. As a result, `AutoUpdate.Check` and `AutoUpdate.Apply` fields don't clobber each other when set individually. Updates #16247 Signed-off-by: Andrew Lytvynov <awly@tailscale.com>
This commit is contained in:
@@ -786,7 +786,7 @@ func TestPrefFlagMapping(t *testing.T) {
|
||||
prefHasFlag := map[string]bool{}
|
||||
for _, pv := range prefsOfFlag {
|
||||
for _, pref := range pv {
|
||||
prefHasFlag[pref] = true
|
||||
prefHasFlag[strings.Split(pref, ".")[0]] = true
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -167,7 +167,7 @@ func runSet(ctx context.Context, args []string) (retErr error) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if maskedPrefs.AutoUpdateSet {
|
||||
if maskedPrefs.AutoUpdateSet.ApplySet {
|
||||
// On macsys, tailscaled will set the Sparkle auto-update setting. It
|
||||
// does not use clientupdate.
|
||||
if version.IsMacSysExt() {
|
||||
|
@@ -718,8 +718,8 @@ func init() {
|
||||
addPrefFlagMapping("ssh", "RunSSH")
|
||||
addPrefFlagMapping("webclient", "RunWebClient")
|
||||
addPrefFlagMapping("nickname", "ProfileName")
|
||||
addPrefFlagMapping("update-check", "AutoUpdate")
|
||||
addPrefFlagMapping("auto-update", "AutoUpdate")
|
||||
addPrefFlagMapping("update-check", "AutoUpdate.Check")
|
||||
addPrefFlagMapping("auto-update", "AutoUpdate.Apply")
|
||||
addPrefFlagMapping("advertise-connector", "AppConnector")
|
||||
addPrefFlagMapping("posture-checking", "PostureChecking")
|
||||
}
|
||||
@@ -728,9 +728,14 @@ func addPrefFlagMapping(flagName string, prefNames ...string) {
|
||||
prefsOfFlag[flagName] = prefNames
|
||||
prefType := reflect.TypeOf(ipn.Prefs{})
|
||||
for _, pref := range prefNames {
|
||||
// Crash at runtime if there's a typo in the prefName.
|
||||
if _, ok := prefType.FieldByName(pref); !ok {
|
||||
panic(fmt.Sprintf("invalid ipn.Prefs field %q", pref))
|
||||
t := prefType
|
||||
for _, name := range strings.Split(pref, ".") {
|
||||
// Crash at runtime if there's a typo in the prefName.
|
||||
f, ok := t.FieldByName(name)
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("invalid ipn.Prefs field %q", pref))
|
||||
}
|
||||
t = f.Type
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -751,7 +756,11 @@ func updateMaskedPrefsFromUpOrSetFlag(mp *ipn.MaskedPrefs, flagName string) {
|
||||
}
|
||||
if prefs, ok := prefsOfFlag[flagName]; ok {
|
||||
for _, pref := range prefs {
|
||||
reflect.ValueOf(mp).Elem().FieldByName(pref + "Set").SetBool(true)
|
||||
f := reflect.ValueOf(mp).Elem()
|
||||
for _, name := range strings.Split(pref, ".") {
|
||||
f = f.FieldByName(name + "Set")
|
||||
}
|
||||
f.SetBool(true)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
Reference in New Issue
Block a user