mirror of
https://github.com/tailscale/tailscale.git
synced 2026-05-16 21:00:57 -04:00
clientupdate, cmd/tailscale/cli: support updating to release-candidates (#18632)
Adds a new track for release candidates. Supports querying by track in version and updating to RCs in update for supported platforms. updates #18193 Signed-off-by: Will Hannah <willh@tailscale.com>
This commit is contained in:
@@ -38,8 +38,9 @@
|
||||
)
|
||||
|
||||
const (
|
||||
StableTrack = "stable"
|
||||
UnstableTrack = "unstable"
|
||||
StableTrack = "stable"
|
||||
UnstableTrack = "unstable"
|
||||
ReleaseCandidateTrack = "release-candidate"
|
||||
)
|
||||
|
||||
var CurrentTrack = func() string {
|
||||
@@ -80,6 +81,8 @@ type Arguments struct {
|
||||
// running binary
|
||||
// - StableTrack and UnstableTrack will use the latest versions of the
|
||||
// corresponding tracks
|
||||
// - ReleaseCandidateTrack will use the newest version from StableTrack
|
||||
// and ReleaseCandidateTrack.
|
||||
//
|
||||
// Leaving this empty will use Version or fall back to CurrentTrack if both
|
||||
// Track and Version are empty.
|
||||
@@ -114,7 +117,7 @@ func (args Arguments) validate() error {
|
||||
return fmt.Errorf("only one of Version(%q) or Track(%q) can be set", args.Version, args.Track)
|
||||
}
|
||||
switch args.Track {
|
||||
case StableTrack, UnstableTrack, "":
|
||||
case StableTrack, UnstableTrack, ReleaseCandidateTrack, "":
|
||||
// All valid values.
|
||||
default:
|
||||
return fmt.Errorf("unsupported track %q", args.Track)
|
||||
@@ -496,10 +499,10 @@ func (up *Updater) updateDebLike() error {
|
||||
const aptSourcesFile = "/etc/apt/sources.list.d/tailscale.list"
|
||||
|
||||
// updateDebianAptSourcesList updates the /etc/apt/sources.list.d/tailscale.list
|
||||
// file to make sure it has the provided track (stable or unstable) in it.
|
||||
// file to make sure it has the provided track (stable, unstable, or release-candidate) in it.
|
||||
//
|
||||
// If it already has the right track (including containing both stable and
|
||||
// unstable), it does nothing.
|
||||
// If it already has the right track (including containing both stable,
|
||||
// unstable, and release-candidate), it does nothing.
|
||||
func updateDebianAptSourcesList(dstTrack string) (rewrote bool, err error) {
|
||||
was, err := os.ReadFile(aptSourcesFile)
|
||||
if err != nil {
|
||||
@@ -522,7 +525,7 @@ func updateDebianAptSourcesListBytes(was []byte, dstTrack string) (newContent []
|
||||
bs := bufio.NewScanner(bytes.NewReader(was))
|
||||
hadCorrect := false
|
||||
commentLine := regexp.MustCompile(`^\s*\#`)
|
||||
pkgsURL := regexp.MustCompile(`\bhttps://pkgs\.tailscale\.com/((un)?stable)/`)
|
||||
pkgsURL := regexp.MustCompile(`\bhttps://pkgs\.tailscale\.com/(stable|unstable|release-candidate)/`)
|
||||
for bs.Scan() {
|
||||
line := bs.Bytes()
|
||||
if !commentLine.Match(line) {
|
||||
@@ -616,15 +619,15 @@ func (up *Updater) updateFedoraLike(packageManager string) func() error {
|
||||
}
|
||||
|
||||
// updateYUMRepoTrack updates the repoFile file to make sure it has the
|
||||
// provided track (stable or unstable) in it.
|
||||
// provided track (stable, unstable, or release-candidate) in it.
|
||||
func updateYUMRepoTrack(repoFile, dstTrack string) (rewrote bool, err error) {
|
||||
was, err := os.ReadFile(repoFile)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
urlRe := regexp.MustCompile(`^(baseurl|gpgkey)=https://pkgs\.tailscale\.com/(un)?stable/`)
|
||||
urlReplacement := fmt.Sprintf("$1=https://pkgs.tailscale.com/%s/", dstTrack)
|
||||
urlRe := regexp.MustCompile(`^(baseurl|gpgkey)=https://pkgs\.tailscale\.com/(stable|unstable|release-candidate)`)
|
||||
urlReplacement := fmt.Sprintf("$1=https://pkgs.tailscale.com/%s", dstTrack)
|
||||
|
||||
s := bufio.NewScanner(bytes.NewReader(was))
|
||||
newContent := bytes.NewBuffer(make([]byte, 0, len(was)))
|
||||
|
||||
@@ -86,18 +86,8 @@ func TestUpdateDebianAptSourcesListBytes(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateYUMRepoTrack(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
before string
|
||||
track string
|
||||
after string
|
||||
rewrote bool
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
desc: "same track",
|
||||
before: `
|
||||
var YUMRepos = map[string]string{
|
||||
StableTrack: `
|
||||
[tailscale-stable]
|
||||
name=Tailscale stable
|
||||
baseurl=https://pkgs.tailscale.com/stable/fedora/$basearch
|
||||
@@ -107,32 +97,8 @@ func TestUpdateYUMRepoTrack(t *testing.T) {
|
||||
gpgcheck=0
|
||||
gpgkey=https://pkgs.tailscale.com/stable/fedora/repo.gpg
|
||||
`,
|
||||
track: StableTrack,
|
||||
after: `
|
||||
[tailscale-stable]
|
||||
name=Tailscale stable
|
||||
baseurl=https://pkgs.tailscale.com/stable/fedora/$basearch
|
||||
enabled=1
|
||||
type=rpm
|
||||
repo_gpgcheck=1
|
||||
gpgcheck=0
|
||||
gpgkey=https://pkgs.tailscale.com/stable/fedora/repo.gpg
|
||||
`,
|
||||
},
|
||||
{
|
||||
desc: "change track",
|
||||
before: `
|
||||
[tailscale-stable]
|
||||
name=Tailscale stable
|
||||
baseurl=https://pkgs.tailscale.com/stable/fedora/$basearch
|
||||
enabled=1
|
||||
type=rpm
|
||||
repo_gpgcheck=1
|
||||
gpgcheck=0
|
||||
gpgkey=https://pkgs.tailscale.com/stable/fedora/repo.gpg
|
||||
`,
|
||||
track: UnstableTrack,
|
||||
after: `
|
||||
|
||||
UnstableTrack: `
|
||||
[tailscale-unstable]
|
||||
name=Tailscale unstable
|
||||
baseurl=https://pkgs.tailscale.com/unstable/fedora/$basearch
|
||||
@@ -142,11 +108,19 @@ func TestUpdateYUMRepoTrack(t *testing.T) {
|
||||
gpgcheck=0
|
||||
gpgkey=https://pkgs.tailscale.com/unstable/fedora/repo.gpg
|
||||
`,
|
||||
rewrote: true,
|
||||
},
|
||||
{
|
||||
desc: "non-tailscale repo file",
|
||||
before: `
|
||||
|
||||
ReleaseCandidateTrack: `
|
||||
[tailscale-release-candidate]
|
||||
name=Tailscale release-candidate
|
||||
baseurl=https://pkgs.tailscale.com/release-candidate/fedora/$basearch
|
||||
enabled=1
|
||||
type=rpm
|
||||
repo_gpgcheck=1
|
||||
gpgcheck=0
|
||||
gpgkey=https://pkgs.tailscale.com/release-candidate/fedora/repo.gpg
|
||||
`,
|
||||
|
||||
"FakeRepo": `
|
||||
[fedora]
|
||||
name=Fedora $releasever - $basearch
|
||||
#baseurl=http://download.example/pub/fedora/linux/releases/$releasever/Everything/$basearch/os/
|
||||
@@ -158,8 +132,41 @@ func TestUpdateYUMRepoTrack(t *testing.T) {
|
||||
type=rpm
|
||||
gpgcheck=1
|
||||
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-$releasever-$basearch
|
||||
skip_if_unavailable=False
|
||||
`,
|
||||
skip_if_unavailable=False`,
|
||||
}
|
||||
|
||||
func TestUpdateYUMRepoTrack(t *testing.T) {
|
||||
tests := []struct {
|
||||
desc string
|
||||
before string
|
||||
track string
|
||||
after string
|
||||
rewrote bool
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
desc: "same track",
|
||||
before: YUMRepos[StableTrack],
|
||||
track: StableTrack,
|
||||
after: YUMRepos[StableTrack],
|
||||
},
|
||||
{
|
||||
desc: "change track",
|
||||
before: YUMRepos[StableTrack],
|
||||
track: UnstableTrack,
|
||||
after: YUMRepos[UnstableTrack],
|
||||
rewrote: true,
|
||||
},
|
||||
{
|
||||
desc: "change track RC",
|
||||
before: YUMRepos[StableTrack],
|
||||
track: ReleaseCandidateTrack,
|
||||
after: YUMRepos[ReleaseCandidateTrack],
|
||||
rewrote: true,
|
||||
},
|
||||
{
|
||||
desc: "non-tailscale repo file",
|
||||
before: YUMRepos["FakeRepo"],
|
||||
track: StableTrack,
|
||||
wantErr: true,
|
||||
},
|
||||
|
||||
@@ -22,8 +22,11 @@
|
||||
func init() {
|
||||
maybeUpdateCmd = func() *ffcli.Command { return updateCmd }
|
||||
|
||||
clientupdateLatestTailscaleVersion.Set(func() (string, error) {
|
||||
return clientupdate.LatestTailscaleVersion(clientupdate.CurrentTrack)
|
||||
clientupdateLatestTailscaleVersion.Set(func(track string) (string, error) {
|
||||
if track == "" {
|
||||
return clientupdate.LatestTailscaleVersion(clientupdate.CurrentTrack)
|
||||
}
|
||||
return clientupdate.LatestTailscaleVersion(track)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -50,7 +53,7 @@ func init() {
|
||||
distro.Get() != distro.Synology &&
|
||||
runtime.GOOS != "freebsd" &&
|
||||
runtime.GOOS != "darwin" {
|
||||
fs.StringVar(&updateArgs.track, "track", "", `which track to check for updates: "stable" or "unstable" (dev); empty means same as current`)
|
||||
fs.StringVar(&updateArgs.track, "track", "", `which track to check for updates: "stable", "release-candidate", or "unstable" (dev); empty means same as current`)
|
||||
fs.StringVar(&updateArgs.version, "version", "", `explicit version to update/downgrade to`)
|
||||
}
|
||||
return fs
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
fs.BoolVar(&versionArgs.daemon, "daemon", false, "also print local node's daemon version")
|
||||
fs.BoolVar(&versionArgs.json, "json", false, "output in JSON format")
|
||||
fs.BoolVar(&versionArgs.upstream, "upstream", false, "fetch and print the latest upstream release version from pkgs.tailscale.com")
|
||||
fs.StringVar(&versionArgs.track, "track", "", `which track to check for updates: "stable", "release-candidate", or "unstable" (dev); empty means same as current`)
|
||||
return fs
|
||||
})(),
|
||||
Exec: runVersion,
|
||||
@@ -33,9 +34,10 @@
|
||||
daemon bool // also check local node's daemon version
|
||||
json bool
|
||||
upstream bool
|
||||
track string
|
||||
}
|
||||
|
||||
var clientupdateLatestTailscaleVersion feature.Hook[func() (string, error)]
|
||||
var clientupdateLatestTailscaleVersion feature.Hook[func(string) (string, error)]
|
||||
|
||||
func runVersion(ctx context.Context, args []string) error {
|
||||
if len(args) > 0 {
|
||||
@@ -57,7 +59,7 @@ func runVersion(ctx context.Context, args []string) error {
|
||||
if !ok {
|
||||
return fmt.Errorf("fetching latest version not supported in this build")
|
||||
}
|
||||
upstreamVer, err = f()
|
||||
upstreamVer, err = f(versionArgs.track)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user