feature/featuretags: make QR codes modular (#18358)
QR codes are used by `tailscale up --qr` to provide an easy way to open a web-page without transcribing a difficult URI. However, there’s no need for this feature if the client will never be called interactively. So this PR adds the `ts_omit_qrcodes` build tag. Updates #18182 Signed-off-by: Simon Law <sfllaw@tailscale.com>
This commit is contained in:
+10
-6
@@ -94,8 +94,10 @@ func newUpFlagSet(goos string, upArgs *upArgsT, cmd string) *flag.FlagSet {
|
|||||||
|
|
||||||
// When adding new flags, prefer to put them under "tailscale set" instead
|
// When adding new flags, prefer to put them under "tailscale set" instead
|
||||||
// of here. Setting preferences via "tailscale up" is deprecated.
|
// of here. Setting preferences via "tailscale up" is deprecated.
|
||||||
upf.BoolVar(&upArgs.qr, "qr", false, "show QR code for login URLs")
|
if buildfeatures.HasQRCodes {
|
||||||
upf.StringVar(&upArgs.qrFormat, "qr-format", string(qrcodes.FormatAuto), fmt.Sprintf("QR code formatting (%s, %s, %s, %s)", qrcodes.FormatAuto, qrcodes.FormatASCII, qrcodes.FormatLarge, qrcodes.FormatSmall))
|
upf.BoolVar(&upArgs.qr, "qr", false, "show QR code for login URLs")
|
||||||
|
upf.StringVar(&upArgs.qrFormat, "qr-format", string(qrcodes.FormatAuto), fmt.Sprintf("QR code formatting (%s, %s, %s, %s)", qrcodes.FormatAuto, qrcodes.FormatASCII, qrcodes.FormatLarge, qrcodes.FormatSmall))
|
||||||
|
}
|
||||||
upf.StringVar(&upArgs.authKeyOrFile, "auth-key", "", `node authorization key; if it begins with "file:", then it's a path to a file containing the authkey`)
|
upf.StringVar(&upArgs.authKeyOrFile, "auth-key", "", `node authorization key; if it begins with "file:", then it's a path to a file containing the authkey`)
|
||||||
upf.StringVar(&upArgs.clientID, "client-id", "", "Client ID used to generate authkeys via workload identity federation")
|
upf.StringVar(&upArgs.clientID, "client-id", "", "Client ID used to generate authkeys via workload identity federation")
|
||||||
upf.StringVar(&upArgs.clientSecretOrFile, "client-secret", "", `Client Secret used to generate authkeys via OAuth; if it begins with "file:", then it's a path to a file containing the secret`)
|
upf.StringVar(&upArgs.clientSecretOrFile, "client-secret", "", `Client Secret used to generate authkeys via OAuth; if it begins with "file:", then it's a path to a file containing the secret`)
|
||||||
@@ -720,9 +722,11 @@ func runUp(ctx context.Context, cmd string, args []string, upArgs upArgsT) (retE
|
|||||||
if upArgs.json {
|
if upArgs.json {
|
||||||
js := &upOutputJSON{AuthURL: authURL, BackendState: st.BackendState}
|
js := &upOutputJSON{AuthURL: authURL, BackendState: st.BackendState}
|
||||||
|
|
||||||
png, err := qrcodes.EncodePNG(authURL, 128)
|
if buildfeatures.HasQRCodes {
|
||||||
if err == nil {
|
png, err := qrcodes.EncodePNG(authURL, 128)
|
||||||
js.QR = "data:image/png;base64," + base64.StdEncoding.EncodeToString(png)
|
if err == nil {
|
||||||
|
js.QR = "data:image/png;base64," + base64.StdEncoding.EncodeToString(png)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
data, err := json.MarshalIndent(js, "", "\t")
|
data, err := json.MarshalIndent(js, "", "\t")
|
||||||
@@ -733,7 +737,7 @@ func runUp(ctx context.Context, cmd string, args []string, upArgs upArgsT) (retE
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(Stderr, "\nTo authenticate, visit:\n\n\t%s\n\n", authURL)
|
fmt.Fprintf(Stderr, "\nTo authenticate, visit:\n\n\t%s\n\n", authURL)
|
||||||
if upArgs.qr {
|
if upArgs.qr && buildfeatures.HasQRCodes {
|
||||||
_, err := qrcodes.Fprintln(Stderr, qrcodes.Format(upArgs.qrFormat), authURL)
|
_, err := qrcodes.Fprintln(Stderr, qrcodes.Format(upArgs.qrFormat), authURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"tailscale.com/tstest/deptest"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestOmitQRCodes(t *testing.T) {
|
||||||
|
const msg = "unexpected with ts_omit_qrcodes"
|
||||||
|
deptest.DepChecker{
|
||||||
|
GOOS: "linux",
|
||||||
|
GOARCH: "amd64",
|
||||||
|
Tags: "ts_omit_qrcodes",
|
||||||
|
BadDeps: map[string]string{
|
||||||
|
"github.com/skip2/go-qrcode": msg,
|
||||||
|
},
|
||||||
|
}.Check(t)
|
||||||
|
}
|
||||||
@@ -33,9 +33,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
github.com/peterbourgon/ff/v3/ffcli from tailscale.com/cmd/tailscale/cli+
|
github.com/peterbourgon/ff/v3/ffcli from tailscale.com/cmd/tailscale/cli+
|
||||||
github.com/peterbourgon/ff/v3/internal from github.com/peterbourgon/ff/v3
|
github.com/peterbourgon/ff/v3/internal from github.com/peterbourgon/ff/v3
|
||||||
💣 github.com/safchain/ethtool from tailscale.com/net/netkernelconf
|
💣 github.com/safchain/ethtool from tailscale.com/net/netkernelconf
|
||||||
github.com/skip2/go-qrcode from tailscale.com/util/qrcodes
|
|
||||||
github.com/skip2/go-qrcode/bitset from github.com/skip2/go-qrcode+
|
|
||||||
github.com/skip2/go-qrcode/reedsolomon from github.com/skip2/go-qrcode
|
|
||||||
💣 github.com/tailscale/wireguard-go/conn from github.com/tailscale/wireguard-go/device+
|
💣 github.com/tailscale/wireguard-go/conn from github.com/tailscale/wireguard-go/device+
|
||||||
💣 github.com/tailscale/wireguard-go/device from tailscale.com/net/tstun+
|
💣 github.com/tailscale/wireguard-go/device from tailscale.com/net/tstun+
|
||||||
github.com/tailscale/wireguard-go/ipc from github.com/tailscale/wireguard-go/device
|
github.com/tailscale/wireguard-go/ipc from github.com/tailscale/wireguard-go/device
|
||||||
@@ -193,7 +190,7 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
tailscale.com/util/osshare from tailscale.com/cmd/tailscaled
|
tailscale.com/util/osshare from tailscale.com/cmd/tailscaled
|
||||||
tailscale.com/util/osuser from tailscale.com/ipn/ipnlocal+
|
tailscale.com/util/osuser from tailscale.com/ipn/ipnlocal+
|
||||||
tailscale.com/util/prompt from tailscale.com/cmd/tailscale/cli
|
tailscale.com/util/prompt from tailscale.com/cmd/tailscale/cli
|
||||||
💣 tailscale.com/util/qrcodes from tailscale.com/cmd/tailscale/cli
|
tailscale.com/util/qrcodes from tailscale.com/cmd/tailscale/cli
|
||||||
tailscale.com/util/race from tailscale.com/net/dns/resolver
|
tailscale.com/util/race from tailscale.com/net/dns/resolver
|
||||||
tailscale.com/util/racebuild from tailscale.com/logpolicy
|
tailscale.com/util/racebuild from tailscale.com/logpolicy
|
||||||
tailscale.com/util/rands from tailscale.com/ipn/ipnlocal+
|
tailscale.com/util/rands from tailscale.com/ipn/ipnlocal+
|
||||||
@@ -274,9 +271,8 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
bufio from compress/flate+
|
bufio from compress/flate+
|
||||||
bytes from bufio+
|
bytes from bufio+
|
||||||
cmp from encoding/json+
|
cmp from encoding/json+
|
||||||
compress/flate from compress/gzip+
|
compress/flate from compress/gzip
|
||||||
compress/gzip from net/http+
|
compress/gzip from net/http+
|
||||||
compress/zlib from image/png
|
|
||||||
container/list from crypto/tls+
|
container/list from crypto/tls+
|
||||||
context from crypto/tls+
|
context from crypto/tls+
|
||||||
crypto from crypto/ecdh+
|
crypto from crypto/ecdh+
|
||||||
@@ -355,13 +351,9 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
flag from tailscale.com/cmd/tailscaled+
|
flag from tailscale.com/cmd/tailscaled+
|
||||||
fmt from compress/flate+
|
fmt from compress/flate+
|
||||||
hash from crypto+
|
hash from crypto+
|
||||||
hash/adler32 from compress/zlib
|
|
||||||
hash/crc32 from compress/gzip+
|
hash/crc32 from compress/gzip+
|
||||||
hash/maphash from go4.org/mem
|
hash/maphash from go4.org/mem
|
||||||
html from tailscale.com/ipn/ipnlocal+
|
html from tailscale.com/ipn/ipnlocal+
|
||||||
image from github.com/skip2/go-qrcode+
|
|
||||||
image/color from github.com/skip2/go-qrcode+
|
|
||||||
image/png from github.com/skip2/go-qrcode
|
|
||||||
internal/abi from hash/maphash+
|
internal/abi from hash/maphash+
|
||||||
internal/asan from internal/runtime/maps+
|
internal/asan from internal/runtime/maps+
|
||||||
internal/bisect from internal/godebug
|
internal/bisect from internal/godebug
|
||||||
@@ -406,7 +398,6 @@ tailscale.com/cmd/tailscaled dependencies: (generated by github.com/tailscale/de
|
|||||||
internal/unsafeheader from internal/reflectlite+
|
internal/unsafeheader from internal/reflectlite+
|
||||||
io from bufio+
|
io from bufio+
|
||||||
io/fs from crypto/x509+
|
io/fs from crypto/x509+
|
||||||
io/ioutil from github.com/skip2/go-qrcode
|
|
||||||
iter from bytes+
|
iter from bytes+
|
||||||
log from github.com/klauspost/compress/zstd+
|
log from github.com/klauspost/compress/zstd+
|
||||||
log/internal from log
|
log/internal from log
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
// Code generated by gen.go; DO NOT EDIT.
|
||||||
|
|
||||||
|
//go:build ts_omit_qrcodes
|
||||||
|
|
||||||
|
package buildfeatures
|
||||||
|
|
||||||
|
// HasQRCodes is whether the binary was built with support for modular feature "QR codes in tailscale CLI".
|
||||||
|
// Specifically, it's whether the binary was NOT built with the "ts_omit_qrcodes" build tag.
|
||||||
|
// It's a const so it can be used for dead code elimination.
|
||||||
|
const HasQRCodes = false
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
// Code generated by gen.go; DO NOT EDIT.
|
||||||
|
|
||||||
|
//go:build !ts_omit_qrcodes
|
||||||
|
|
||||||
|
package buildfeatures
|
||||||
|
|
||||||
|
// HasQRCodes is whether the binary was built with support for modular feature "QR codes in tailscale CLI".
|
||||||
|
// Specifically, it's whether the binary was NOT built with the "ts_omit_qrcodes" build tag.
|
||||||
|
// It's a const so it can be used for dead code elimination.
|
||||||
|
const HasQRCodes = true
|
||||||
@@ -222,6 +222,7 @@ var Features = map[FeatureTag]FeatureMeta{
|
|||||||
Desc: "Linux NetworkManager integration",
|
Desc: "Linux NetworkManager integration",
|
||||||
Deps: []FeatureTag{"dbus"},
|
Deps: []FeatureTag{"dbus"},
|
||||||
},
|
},
|
||||||
|
"qrcodes": {Sym: "QRCodes", Desc: "QR codes in tailscale CLI"},
|
||||||
"relayserver": {Sym: "RelayServer", Desc: "Relay server"},
|
"relayserver": {Sym: "RelayServer", Desc: "Relay server"},
|
||||||
"resolved": {
|
"resolved": {
|
||||||
Sym: "Resolved",
|
Sym: "Resolved",
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
package qrcodes
|
||||||
|
|
||||||
|
// Format selects the text representation used to print QR codes.
|
||||||
|
type Format string
|
||||||
|
|
||||||
|
const (
|
||||||
|
// FormatAuto will format QR codes to best fit the capabilities of the
|
||||||
|
// [io.Writer].
|
||||||
|
FormatAuto Format = "auto"
|
||||||
|
|
||||||
|
// FormatASCII will format QR codes with only ASCII characters.
|
||||||
|
FormatASCII Format = "ascii"
|
||||||
|
|
||||||
|
// FormatLarge will format QR codes with full block characters.
|
||||||
|
FormatLarge Format = "large"
|
||||||
|
|
||||||
|
// FormatSmall will format QR codes with full and half block characters.
|
||||||
|
FormatSmall Format = "small"
|
||||||
|
)
|
||||||
+2
-18
@@ -1,6 +1,8 @@
|
|||||||
// Copyright (c) Tailscale Inc & AUTHORS
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
//go:build !ts_omit_qrcodes
|
||||||
|
|
||||||
// Package qrcodes provides functions to render or format QR codes.
|
// Package qrcodes provides functions to render or format QR codes.
|
||||||
package qrcodes
|
package qrcodes
|
||||||
|
|
||||||
@@ -12,24 +14,6 @@ import (
|
|||||||
qrcode "github.com/skip2/go-qrcode"
|
qrcode "github.com/skip2/go-qrcode"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Format selects the text representation used to print QR codes.
|
|
||||||
type Format string
|
|
||||||
|
|
||||||
const (
|
|
||||||
// FormatAuto will format QR codes to best fit the capabilities of the
|
|
||||||
// [io.Writer].
|
|
||||||
FormatAuto Format = "auto"
|
|
||||||
|
|
||||||
// FormatASCII will format QR codes with only ASCII characters.
|
|
||||||
FormatASCII Format = "ascii"
|
|
||||||
|
|
||||||
// FormatLarge will format QR codes with full block characters.
|
|
||||||
FormatLarge Format = "large"
|
|
||||||
|
|
||||||
// FormatSmall will format QR codes with full and half block characters.
|
|
||||||
FormatSmall Format = "small"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Fprintln formats s according to [Format] and writes a QR code to w, along
|
// Fprintln formats s according to [Format] and writes a QR code to w, along
|
||||||
// with a newline. It returns the number of bytes written and any write error
|
// with a newline. It returns the number of bytes written and any write error
|
||||||
// encountered.
|
// encountered.
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
//go:build ts_omit_qrcodes
|
||||||
|
|
||||||
|
package qrcodes
|
||||||
|
|
||||||
|
import "io"
|
||||||
|
|
||||||
|
func Fprintln(w io.Writer, format Format, s string) (n int, err error) {
|
||||||
|
panic("omitted")
|
||||||
|
}
|
||||||
|
|
||||||
|
func EncodePNG(s string, size int) ([]byte, error) {
|
||||||
|
panic("omitted")
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright (c) Tailscale Inc & AUTHORS
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
//go:build linux
|
//go:build linux && !ts_omit_qrcodes
|
||||||
|
|
||||||
package qrcodes
|
package qrcodes
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// Copyright (c) Tailscale Inc & AUTHORS
|
// Copyright (c) Tailscale Inc & AUTHORS
|
||||||
// SPDX-License-Identifier: BSD-3-Clause
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
//go:build !linux
|
//go:build !linux && !ts_omit_qrcodes
|
||||||
|
|
||||||
package qrcodes
|
package qrcodes
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user