Documentation
¶
Index ¶
- Constants
- Variables
- func CtxAsBool(ctx context.Context, key contextKey) bool
- func CtxAsInt(ctx context.Context, key contextKey) int
- func CtxAsString(ctx context.Context, key contextKey) string
- func ExecuteClusterRemoteCmd(ctx context.Context, w io.Writer, hosts []RemoteCmdHost, remoteCmd string)
- func NewClient(ctx context.Context) *tailscale.Client
- func NewOauthClient(ctx context.Context) *tailscale.Client
- func ParseColumns(s string) (mapset.Set[string], mapset.Set[string])
- func ParseFilter(filter string) (filtercomp.AST, error)
- func RenderASCIITableView(ctx context.Context, tableView *GeneralTableView, w io.Writer) error
- func RenderIPs(ctx context.Context, tableView *GeneralTableView, w io.Writer) error
- func RenderJson(ctx context.Context, tableView *GeneralTableView, w io.Writer) error
- func RenderLogLine(ctx context.Context, w io.Writer, idx int, isStdErr bool, ...)
- func RenderRemoteSummary(ctx context.Context, w io.Writer, success, errors uint32, ...) error
- func RenderTableView(ctx context.Context, tableView *GeneralTableView, w io.Writer) error
- type CachedRepository
- type ConfigCtx
- type ContextView
- type DBQuery
- type Db
- func (d *Db[T]) Close() error
- func (d *Db[T]) Erase() error
- func (d *Db[T]) Exists(ctx context.Context) (bool, error)
- func (d *Db[T]) File() string
- func (d *Db[T]) IndexOpaqueItems(ctx context.Context, bucketName string, items []T) error
- func (d *Db[T]) LookupOpaqueItem(ctx context.Context, bucketName, primaryKey string) (*T, error)
- func (d *Db[T]) Open() error
- func (d *Db[T]) SearchOpaqueItems(ctx context.Context, bucketName string, query DBQuery) ([]T, error)
- func (d *Db[T]) TailnetScope() string
- type DbStats
- type DevicesTable
- type DevicesView
- type GeneralTableView
- type Header
- type HeaderMatchName
- type Indexer
- type InnerRepo
- type MockedDeviceRepo
- type RemoteCmdHost
- type RemoteDeviceRepo
- type SelfView
- type SortDirection
- type SortSpec
- type TailnetView
- type TailscaleAPICfgCtx
- type TailscaleCLICfgCtx
- type WrappedDevice
Constants ¶
const ( AppLongName = "Tailscale IPs" AppShortName = "tips" )
const ( // These two buckets contain FULL data. DevicesBucket = "bucket:devices.full" StatsBucket = "bucket:stats" StatsKey = "key:stats" )
Variables ¶
var ( AppVersion = "0.0.1" UserAgent = fmt.Sprintf("%s/%s", AppShortName, AppVersion) )
var ( // CtxKeyConfig holds all config settings that were resolved from the environment/config file/cli flags CtxKeyConfig = contextKey("configuration") CtxKeyUserQuery = contextKey("user-query") )
var ( HdrAddress = Header{Title: "Address", MatchName: MatchNameAddress} HdrExitStatus = Header{Title: "Exit Status", MatchName: MatchNameExitStatus} HdrIpv4 = Header{Title: "Ipv4", MatchName: MatchNameIpv4} HdrIpv6 = Header{Title: "Ipv6", MatchName: MatchNameIpv6} HdrLastSeenAgo = Header{Title: "Last Seen", MatchName: MatchNameLastSeenAgo, ReqEnriched: true} HdrMachine = Header{Title: "Machine", MatchName: MatchNameMachine} HdrNo = Header{Title: "No", MatchName: MatchNameNo} HdrTags = Header{Title: "Tags", MatchName: MatchNameTags} HdrUser = Header{Title: "User", MatchName: MatchNameUser} HdrVersion = Header{Title: "Version", MatchName: MatchNameVersion} // AllHeadersList must contain the complete list of headers. AllHeadersList = []Header{ HdrAddress, HdrExitStatus, HdrIpv4, HdrIpv6, HdrLastSeenAgo, HdrMachine, HdrNo, HdrTags, HdrUser, HdrVersion, } // AllHeadersMap initializes a map of HeaderMatchName to Header. AllHeadersMap = func() map[HeaderMatchName]Header { a := make(map[HeaderMatchName]Header) for _, hdr := range AllHeadersList { a[hdr.MatchName] = hdr } return a }() // DefaultColumnSet is the column set that ships out of the box. // Order matters which is why it's created as a slice. DefaultColumnSet = []Header{ HdrNo, HdrMachine, HdrIpv4, HdrTags, HdrUser, HdrVersion, HdrExitStatus, HdrLastSeenAgo, } )
Functions ¶
func CtxAsString ¶
func ExecuteClusterRemoteCmd ¶
func ParseFilter ¶
func ParseFilter(filter string) (filtercomp.AST, error)
func RenderASCIITableView ¶
func RenderJson ¶
func RenderLogLine ¶
func RenderRemoteSummary ¶
func RenderTableView ¶
Types ¶
type CachedRepository ¶
type CachedRepository struct {
// contains filtered or unexported fields
}
func NewCachedRepo ¶
func NewCachedRepo(innerRepo InnerRepo) *CachedRepository
func (*CachedRepository) DevicesResource ¶
func (c *CachedRepository) DevicesResource(ctx context.Context) ([]*WrappedDevice, error)
type ConfigCtx ¶
type ConfigCtx struct {
Basic bool
CacheTimeout time.Duration
Columns mapset.Set[string]
ColumnsExclude mapset.Set[string]
Concurrency int
Filters filtercomp.AST
IPsOutput bool
IPsDelimiter string
JsonOutput bool
NoCache bool
NoColor bool
PrefixFilter *prefixcomp.PrimaryFilterAST
RemoteCmd string
Slice *slicecomp.Slice
SortOrder []SortSpec
Tailnet string
CachedElapsed time.Duration
TailscaleAPI TailscaleAPICfgCtx
TailscaleCLI TailscaleCLICfgCtx
Page int
TestMode bool
}
func CtxAsConfig ¶
func NewConfigCtx ¶
func NewConfigCtx() *ConfigCtx
func (*ConfigCtx) IsRemoteCommand ¶
type ContextView ¶
type DBQuery ¶ added in v0.0.4
type DBQuery struct {
PrefixFilters *prefixcomp.PrimaryFilterAST
PrimaryKeys []string
}
type Db ¶ added in v0.0.6
type Db[T Indexer] struct { // contains filtered or unexported fields }
func (*Db[T]) IndexOpaqueItems ¶ added in v0.0.6
func (*Db[T]) LookupOpaqueItem ¶ added in v0.0.6
func (*Db[T]) SearchOpaqueItems ¶ added in v0.0.6
func (d *Db[T]) SearchOpaqueItems(ctx context.Context, bucketName string, query DBQuery) ([]T, error)
SearchOpaqueItems can generically search with 3 different ways. 1. Using one or more primary keys, in which case this is a direct lookup (not technically a search) 2. Using the * (all/everything) construct, this is just a full table scan really. 3. Using a prefix scan, this is a seek to a segment of the index and should be fast assuming good selectivity.
func (*Db[T]) TailnetScope ¶ added in v0.0.6
type DevicesTable ¶
type DevicesTable struct {
TailnetView
Devices *DevicesView
}
type GeneralTableView ¶
type GeneralTableView struct {
ContextView
TailnetView
SelfView
Headers []Header
Rows [][]string
}
func ProcessDevicesTable ¶
func ProcessDevicesTable(ctx context.Context, devList []*WrappedDevice) (*GeneralTableView, error)
ProcessDevicesTable will apply sorting (if required), slicing (if required) and the massage/transformation of data to produce a final `*DevicesTable` that has everything required to render.
func (*GeneralTableView) HeaderTitles ¶ added in v0.0.7
func (g *GeneralTableView) HeaderTitles() []string
type Header ¶ added in v0.0.7
type Header struct {
ReqEnriched bool
MatchName HeaderMatchName
Title string
}
type HeaderMatchName ¶ added in v0.0.7
type HeaderMatchName string
const ( MatchNameAddress HeaderMatchName = "address" MatchNameAuthorized HeaderMatchName = "authorized" MatchNameBlocksIncomingConnections HeaderMatchName = "blocksincomingconnections" MatchNameClientVersion HeaderMatchName = "clientversion" MatchNameExitStatus HeaderMatchName = "exitstatus" MatchNameFullname HeaderMatchName = "fullname" MatchNameIpv4 HeaderMatchName = "ipv4" MatchNameIpv6 HeaderMatchName = "ipv6" MatchNameHostname HeaderMatchName = "hostname" MatchNameLastSeen HeaderMatchName = "lastseen" MatchNameLastSeenAgo HeaderMatchName = "lastseen.ago" MatchNameMachine HeaderMatchName = "machine" MatchNameName HeaderMatchName = "name" MatchNameNo HeaderMatchName = "no" MatchNameOS HeaderMatchName = "os" MatchNameTags HeaderMatchName = "tags" MatchNameUser HeaderMatchName = "user" MatchNameVersion HeaderMatchName = "version" )
type InnerRepo ¶
type InnerRepo interface {
DevicesResource(ctx context.Context) ([]*WrappedDevice, error)
}
type MockedDeviceRepo ¶
type MockedDeviceRepo struct {
// contains filtered or unexported fields
}
func NewMockedDeviceRepo ¶
func NewMockedDeviceRepo() *MockedDeviceRepo
func NewMockedDeviceRepoWithPath ¶ added in v0.0.6
func NewMockedDeviceRepoWithPath(filePath string) *MockedDeviceRepo
func (*MockedDeviceRepo) DevicesResource ¶
func (r *MockedDeviceRepo) DevicesResource(ctx context.Context) ([]*WrappedDevice, error)
type RemoteCmdHost ¶
type RemoteDeviceRepo ¶
type RemoteDeviceRepo struct {
// contains filtered or unexported fields
}
func NewRemoteDeviceRepo ¶
func NewRemoteDeviceRepo(client *tailscale.Client) *RemoteDeviceRepo
func (*RemoteDeviceRepo) DevicesResource ¶
func (r *RemoteDeviceRepo) DevicesResource(ctx context.Context) ([]*WrappedDevice, error)
type SortSpec ¶
type SortSpec struct {
Field string
Direction SortDirection
}
func ParseSortString ¶
Parse the sort string and return a slice of SortSpec
type TailnetView ¶
TailnetView has everything known about a Tailnet
type TailscaleAPICfgCtx ¶
type TailscaleAPICfgCtx struct {
Timeout time.Duration
// ApiKey for regular authentication
ApiKey string
// OAuthClientID for OAuth based login.
OAuthClientID string
// OAuthClientSecret for Oauth based login.
OAuthClientSecret string
// ElapsedTime records the time this API call took. It's meant to be mutated during the API call and populated then.
ElapsedTime time.Duration
}
type TailscaleCLICfgCtx ¶
type TailscaleCLICfgCtx struct {
}
type WrappedDevice ¶
type WrappedDevice struct {
tailscale.Device
EnrichedInfo *tailscale_cli.DeviceInfo `json:"enrichedInfo"`
}
WrappedDevice is a type that wraps the core `tailscale.Device` type. It also holds the joined `tailscale_cli.DeviceInfo` that may or may not be present when fetched from within the tailnet. It also implements the `Indexer` interface, so it may be stored in the DB.
func (*WrappedDevice) EvalColumnField ¶ added in v0.0.7
func (w *WrappedDevice) EvalColumnField(ctx context.Context, idx int, headerMatchName HeaderMatchName) string
func (*WrappedDevice) Key ¶
func (w *WrappedDevice) Key() string
Key returns the device field of how this device gets indexed into the cached db. Currently, it just uses the name such: "blade.tail372c.ts.net" which implies devices are stored in alphabetical order as ascending via their `name` field.