cmd/tailscale/cli,ipn/conffile: add declarative config mode for Services (#17435)

This commit adds the subcommands `get-config` and `set-config` to Serve,
which can be used to read the current Tailscale Services configuration
in a standard syntax and provide a configuration to declaratively apply
with that same syntax.

Both commands must be provided with either `--service=svc:service` for
one service, or `--all` for all services. When writing a config,
`--set-config --all` will overwrite all existing Services configuration,
and `--set-config --service=svc:service` will overwrite all
configuration for that particular Service. Incremental changes are not
supported.

Fixes tailscale/corp#30983.

cmd/tailscale/cli: hide serve "get-config"/"set-config" commands for now

tailscale/corp#33152 tracks unhiding them when docs exist.

Signed-off-by: Naman Sood <mail@nsood.in>
This commit is contained in:
Naman Sood
2025-10-10 11:02:35 -04:00
committed by GitHub
parent 08eae9affd
commit f157f3288d
6 changed files with 556 additions and 13 deletions

View File

@@ -5,7 +5,6 @@ package tailcfg
import (
"errors"
"fmt"
"strconv"
"strings"
@@ -70,14 +69,7 @@ func (ppr ProtoPortRange) String() string {
buf.Write(text)
buf.Write([]byte(":"))
}
pr := ppr.Ports
if pr.First == pr.Last {
fmt.Fprintf(&buf, "%d", pr.First)
} else if pr == PortRangeAny {
buf.WriteByte('*')
} else {
fmt.Fprintf(&buf, "%d-%d", pr.First, pr.Last)
}
buf.WriteString(ppr.Ports.String())
return buf.String()
}
@@ -104,7 +96,7 @@ func parseProtoPortRange(ipProtoPort string) (*ProtoPortRange, error) {
if !strings.Contains(ipProtoPort, ":") {
ipProtoPort = "*:" + ipProtoPort
}
protoStr, portRange, err := parseHostPortRange(ipProtoPort)
protoStr, portRange, err := ParseHostPortRange(ipProtoPort)
if err != nil {
return nil, err
}
@@ -126,9 +118,9 @@ func parseProtoPortRange(ipProtoPort string) (*ProtoPortRange, error) {
return ppr, nil
}
// parseHostPortRange parses hostport as HOST:PORTS where HOST is
// ParseHostPortRange parses hostport as HOST:PORTS where HOST is
// returned unchanged and PORTS is is either "*" or PORTLOW-PORTHIGH ranges.
func parseHostPortRange(hostport string) (host string, ports PortRange, err error) {
func ParseHostPortRange(hostport string) (host string, ports PortRange, err error) {
hostport = strings.ToLower(hostport)
colon := strings.LastIndexByte(hostport, ':')
if colon < 0 {