pkg

package
v0.0.7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 15, 2024 License: MIT Imports: 36 Imported by: 0

Documentation

Index

Constants

View Source
const (
	AppLongName  = "Tailscale IPs"
	AppShortName = "tips"
)
View Source
const (
	// These two buckets contain FULL data.
	DevicesBucket = "bucket:devices.full"
	StatsBucket   = "bucket:stats"

	StatsKey = "key:stats"
)

Variables

View Source
var (
	AppVersion = "0.0.1"
	UserAgent  = fmt.Sprintf("%s/%s", AppShortName, AppVersion)
)
View Source
var (
	// CtxKeyConfig holds all config settings that were resolved from the environment/config file/cli flags
	CtxKeyConfig    = contextKey("configuration")
	CtxKeyUserQuery = contextKey("user-query")
)
View Source
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 CtxAsBool

func CtxAsBool(ctx context.Context, key contextKey) bool

func CtxAsInt

func CtxAsInt(ctx context.Context, key contextKey) int

func CtxAsString

func CtxAsString(ctx context.Context, key contextKey) string

func ExecuteClusterRemoteCmd

func ExecuteClusterRemoteCmd(ctx context.Context, w io.Writer, hosts []RemoteCmdHost, remoteCmd string)

func NewClient

func NewClient(ctx context.Context) *tailscale.Client

func NewOauthClient

func NewOauthClient(ctx context.Context) *tailscale.Client

func ParseColumns

func ParseColumns(s string) (mapset.Set[string], mapset.Set[string])

func ParseFilter

func ParseFilter(filter string) (filtercomp.AST, error)

func RenderASCIITableView

func RenderASCIITableView(ctx context.Context, tableView *GeneralTableView, w io.Writer) error

func RenderIPs

func RenderIPs(ctx context.Context, tableView *GeneralTableView, w io.Writer) error

func RenderJson

func RenderJson(ctx context.Context, tableView *GeneralTableView, w io.Writer) error

func RenderLogLine

func RenderLogLine(ctx context.Context, w io.Writer, idx int, isStdErr bool, hostname, alias, line string)

func RenderRemoteSummary

func RenderRemoteSummary(ctx context.Context, w io.Writer, success, errors uint32, elapsed time.Duration) error

func RenderTableView

func RenderTableView(ctx context.Context, tableView *GeneralTableView, w io.Writer) error

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 CtxAsConfig(ctx context.Context, key contextKey) *ConfigCtx

func NewConfigCtx

func NewConfigCtx() *ConfigCtx

func (*ConfigCtx) IsRemoteCommand

func (c *ConfigCtx) IsRemoteCommand() bool

type ContextView

type ContextView struct {
	Query      string
	APIElapsed time.Duration
	CLIElapsed time.Duration
}

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 NewDB2

func NewDB2[T Indexer](tailnetScope string) *Db[T]

func (*Db[T]) Close added in v0.0.6

func (d *Db[T]) Close() error

func (*Db[T]) Erase added in v0.0.6

func (d *Db[T]) Erase() error

func (*Db[T]) Exists added in v0.0.6

func (d *Db[T]) Exists(ctx context.Context) (bool, error)

func (*Db[T]) File added in v0.0.6

func (d *Db[T]) File() string

func (*Db[T]) IndexOpaqueItems added in v0.0.6

func (d *Db[T]) IndexOpaqueItems(ctx context.Context, bucketName string, items []T) error

func (*Db[T]) LookupOpaqueItem added in v0.0.6

func (d *Db[T]) LookupOpaqueItem(ctx context.Context, bucketName, primaryKey string) (*T, error)

func (*Db[T]) Open added in v0.0.6

func (d *Db[T]) Open() error

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

func (d *Db[T]) TailnetScope() string

type DbStats added in v0.0.6

type DbStats struct {
	DevicesCount  int `json:"devices_count"`
	EnrichedCount int `json:"enriched_count"`
}

type DevicesTable

type DevicesTable struct {
	TailnetView
	Devices *DevicesView
}

type DevicesView

type DevicesView struct {
}

DevicesView has everything needed to be rendered.

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 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 Indexer

type Indexer interface {
	Key() string
}

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 RemoteCmdHost struct {
	Original string
	Alias    string
}

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 SelfView

type SelfView struct {
	Index   int
	DNSName string
}

type SortDirection

type SortDirection int
const (
	Ascending SortDirection = iota
	Descending
)

type SortSpec

type SortSpec struct {
	Field     string
	Direction SortDirection
}

func ParseSortString

func ParseSortString(sortString string) []SortSpec

Parse the sort string and return a slice of SortSpec

type TailnetView

type TailnetView struct {
	Tailnet       string
	TotalMachines int
}

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.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL