config

package
v0.1.33 Latest Latest
Warning

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

Go to latest
Published: Aug 4, 2026 License: MIT Imports: 9 Imported by: 0

Documentation

Overview

Package config loads and validates the g9s configuration file.

Index

Constants

View Source
const (
	DefaultBigQueryJobs             = 500
	DefaultDataflowJobs             = 500
	DefaultDataprocJobsPerRegion    = 200
	DefaultClusterJobs              = 200
	DefaultBigQueryTables           = 1000
	DefaultDNSRecordSets            = 1000
	DefaultBackendGroups            = 40
	DefaultServiceAccountKeyLookups = 200
	DefaultKMSKeyRings              = 100
	DefaultCloudBuilds              = 200
)

Default row caps. These are the numbers that used to be compiled into each lister, kept exactly as they were so upgrading changes nothing on its own.

Variables

View Source
var PlaceholderProjectIDs = []string{"my-sandbox-project", "my-prod-data-project"}

PlaceholderProjectIDs are the project IDs `g9s -init` writes.

They exist here rather than only in the template so the two cannot drift: the UI needs to recognise an unedited config, and recognising it by a string copied into another file is how that check quietly stops working.

Functions

func DefaultPath

func DefaultPath() string

DefaultPath resolves the config location: $G9S_CONFIG, then $XDG_CONFIG_HOME/g9s/config.yaml, then ~/.config/g9s/config.yaml.

func IsPlaceholder added in v0.1.25

func IsPlaceholder(p Project) bool

IsPlaceholder reports whether a project is one `g9s -init` wrote and nobody has edited yet.

Worth detecting because an unedited config looks exactly like a working one until the first login, which then fails against a project that does not exist — and the error comes back from Google talking about permissions, which sends people looking in entirely the wrong place.

Types

type Config

type Config struct {
	Defaults Defaults  `yaml:"defaults"`
	Projects []Project `yaml:"projects"`
	// contains filtered or unexported fields
}

Config is the top-level configuration document.

func Load

func Load(path string) (*Config, error)

Load reads and validates the config at path.

func (*Config) AllPlaceholders added in v0.1.25

func (c *Config) AllPlaceholders() bool

AllPlaceholders reports whether every configured project is still a placeholder, which means the config has not been edited at all.

func (*Config) BigQueryJobWindow added in v0.1.3

func (c *Config) BigQueryJobWindow() time.Duration

BigQueryJobWindow is how far back to list BigQuery jobs.

func (*Config) ComposerLocations

func (c *Config) ComposerLocations(p Project) []string

ComposerLocations returns the locations to sweep for Composer environments.

func (*Config) CredentialsFile added in v0.1.5

func (c *Config) CredentialsFile(p Project) string

CredentialsFile returns the existing credentials file to read for a project, or "" when g9s manages the credentials itself.

func (*Config) DataprocRegions

func (c *Config) DataprocRegions(p Project) []string

dataprocRegions returns the regions to sweep for Dataproc clusters, most specific setting first. "global" is always included because clusters can be created there and it is easy to forget.

func (*Config) HasDataprocRegions

func (c *Config) HasDataprocRegions(p Project) bool

HasDataprocRegions reports whether any region setting applies to Dataproc for this project. When false, DataprocRegions falls back to just "global", and the lister says so rather than letting the narrow sweep look complete.

func (*Config) KMSLocations added in v0.1.16

func (c *Config) KMSLocations(p Project) []string

KMSLocations returns the locations to sweep for KMS key rings.

Regions plus "global", always, and for a stronger reason than Dataproc's: a key ring in the global location is not an edge case, it is where most projects put their first one. Sweeping only the configured regions would show an empty KMS table to a project whose keys all exist.

func (*Config) LimitBackendGroups added in v0.1.17

func (c *Config) LimitBackendGroups() int

func (*Config) LimitBigQueryJobs added in v0.1.17

func (c *Config) LimitBigQueryJobs() int

func (*Config) LimitBigQueryTables added in v0.1.17

func (c *Config) LimitBigQueryTables() int

func (*Config) LimitCloudBuilds added in v0.1.29

func (c *Config) LimitCloudBuilds() int

func (*Config) LimitClusterJobs added in v0.1.17

func (c *Config) LimitClusterJobs() int

func (*Config) LimitDNSRecordSets added in v0.1.17

func (c *Config) LimitDNSRecordSets() int

func (*Config) LimitDataflowJobs added in v0.1.17

func (c *Config) LimitDataflowJobs() int

func (*Config) LimitDataprocJobsPerRegion added in v0.1.17

func (c *Config) LimitDataprocJobsPerRegion() int

func (*Config) LimitKMSKeyRings added in v0.1.17

func (c *Config) LimitKMSKeyRings() int

func (*Config) LimitServiceAccountKeyLookups added in v0.1.17

func (c *Config) LimitServiceAccountKeyLookups() int

func (*Config) Path added in v0.1.25

func (c *Config) Path() string

Path is the file this config was loaded from, empty if it was not loaded from one.

func (*Config) Project

func (c *Config) Project(name string) (Project, bool)

Project looks up a project by name.

func (*Config) Regions added in v0.1.6

func (c *Config) Regions(p Project) []string

Regions returns the regions to sweep for a kind with no override of its own, most specific setting first. Cloud Run uses this: its API refuses the "-" wildcard, so the sweep is only ever as wide as this list.

func (*Config) StorageObjectsPageSize added in v0.1.20

func (c *Config) StorageObjectsPageSize() int

StorageObjectsPageSize returns the human-sized page used by the object browser. A nil or hand-built Config gets the same default as one loaded from YAML; tests and embedded callers do not necessarily pass through applyDefaults.

type Defaults

type Defaults struct {
	// Regions is the fallback region list for every region-scoped resource.
	Regions []string `yaml:"regions"`
	// DataprocRegions narrows the Dataproc fan-out for all projects.
	DataprocRegions []string `yaml:"dataproc_regions"`
	// ComposerLocations narrows the Composer fan-out for all projects.
	ComposerLocations []string `yaml:"composer_locations"`
	// CredentialDir is where per-project gcloud config directories live.
	CredentialDir string `yaml:"credential_dir"`
	// GcloudPath is the gcloud binary to shell out to for login.
	GcloudPath string `yaml:"gcloud_path"`
	// CredentialsFile points every project at an existing credentials file
	// instead of a per-project directory g9s logs into. See Project.
	CredentialsFile string `yaml:"credentials_file"`
	// LoginNoBrowser makes `l` always use gcloud's --no-browser flow, the same
	// as pressing `L` every time.
	//
	// Worth setting on a machine behind a proxy. gcloud's ordinary login ends
	// with the browser fetching http://localhost:<port>/ to hand the
	// authorization code back, and a browser that sends localhost through a
	// proxy never delivers it — the sign-in succeeds and the terminal waits
	// forever. Whether the browser does that is a property of this machine, not
	// of any one project, which is why this lives in defaults.
	LoginNoBrowser bool `yaml:"login_no_browser"`
	// ListTimeout bounds a single refresh across all regions.
	ListTimeout Duration `yaml:"list_timeout"`
	// BigQueryJobWindow is how far back the BigQuery jobs table looks. Jobs are
	// kept for six months, which is far more than a "what is running now"
	// table can show, so the window is what makes the listing a complete
	// answer rather than a truncated one.
	BigQueryJobWindow Duration `yaml:"bigquery_job_window"`
	// StorageObjectsPageSize is the number of object and folder rows shown in
	// one UI page while browsing a bucket. It is not a total cap: the UI retains
	// the continuation token and can load the next page.
	StorageObjectsPageSize int `yaml:"storage_objects_page_size"`
	// ClipboardLimit is the largest OSC 52 escape sequence, in bytes, that this
	// terminal is believed to accept.
	//
	// It exists because the failure it prevents is silent. `y` writes the
	// clipboard as one escape sequence, and a terminal that considers it too
	// long drops the whole thing without reporting anything — so g9s would say
	// "copied" over a clipboard that never changed. A stock xterm cuts off
	// around 8 KB and tmux refuses entirely unless set-clipboard is on, while
	// modern terminals take far more, and nothing in the protocol lets g9s ask
	// which it is talking to. So the default is the conservative one and the
	// number is yours to raise once you know your terminal.
	//
	// Zero uses the default. Negative removes the check, which means trusting
	// the terminal to say something when it truncates — most do not.
	ClipboardLimit int `yaml:"clipboard_limit"`

	// Limits raises or removes the per-kind row caps.
	Limits Limits `yaml:"limits"`
}

Defaults supply values for any project that does not override them.

type Duration

type Duration time.Duration

Duration is a time.Duration that unmarshals from a YAML string like "90s".

func (Duration) Duration

func (d Duration) Duration() time.Duration

func (*Duration) UnmarshalYAML

func (d *Duration) UnmarshalYAML(node *yaml.Node) error

type Limits added in v0.1.17

type Limits struct {
	// BigQueryJobs caps the BigQuery jobs table. The window bounds it first;
	// this is the backstop for a busy hour inside that window.
	BigQueryJobs int `yaml:"bigquery_jobs"`
	// DataflowJobs caps the Dataflow jobs table.
	DataflowJobs int `yaml:"dataflow_jobs"`
	// DataprocJobsPerRegion caps each region's Dataproc job listing. It is per
	// region, so the table can hold this many times your region count.
	DataprocJobsPerRegion int `yaml:"dataproc_jobs_per_region"`
	// ClusterJobs caps the per-cluster Dataproc job drill-down.
	ClusterJobs int `yaml:"cluster_jobs"`
	// BigQueryTables caps one dataset's table listing.
	BigQueryTables int `yaml:"bigquery_tables"`
	// DNSRecordSets caps one zone's record listing.
	DNSRecordSets int `yaml:"dns_record_sets"`
	// BackendGroups caps the getHealth calls one backend-health drill-down
	// makes. Unlike the others this bounds *requests*, not rows: each group is
	// its own round trip, so raising it costs latency rather than memory.
	BackendGroups int `yaml:"backend_groups"`
	// ServiceAccountKeyLookups caps how many accounts get their key ages read.
	// Also a request bound: one keys.list per account.
	ServiceAccountKeyLookups int `yaml:"service_account_key_lookups"`
	// KMSKeyRings caps how many key rings per location get their keys read.
	// One cryptoKeys.list per ring, so this is a request bound too.
	KMSKeyRings int `yaml:"kms_key_rings"`
	// CloudBuilds caps the build history table. Build records are kept
	// indefinitely, so without a bound this is the one listing that grows
	// without limit for the life of the project.
	CloudBuilds int `yaml:"cloud_builds"`
}

Limits are the row caps each listing stops at.

Every one of these was a constant compiled into a lister, which made the bound the tool's opinion rather than the reader's. The defaults are unchanged and are sized for a table a person scrolls; the point of the block is that a project big enough to hit one is no longer stuck at a number it did not pick.

Zero means "use the default". A negative value means no cap at all, which is a real choice with real consequences — a zone with 90,000 record sets will fetch all 90,000 — so it has to be asked for explicitly rather than being what an empty field happens to mean.

type Project

type Project struct {
	// Name is the label shown in the picker. Also names the credential dir.
	Name string `yaml:"name"`
	// ProjectID is the real GCP project ID.
	ProjectID string `yaml:"project_id"`
	// Account is the support account email passed to `gcloud --account`.
	// Empty means "whatever gcloud picks", which is fine for a personal login.
	Account string `yaml:"account"`
	// Description is free text shown alongside the project in the picker.
	Description string `yaml:"description"`

	// CredentialsFile is an existing credentials file to read for this
	// project, instead of the per-project directory g9s logs into.
	//
	// This is the way in when the login handshake cannot complete at all —
	// behind a proxy that swallows the loopback redirect, gcloud's browser
	// flow and its --no-browser flow both end at a localhost the browser
	// cannot reach. Point this at credentials obtained any way that does
	// work, most often the ordinary ~/.config/gcloud ADC, and g9s reads them
	// rather than demanding a login it cannot finish.
	//
	// g9s only ever reads this file. Keeping it fresh is then yours, which is
	// the trade: no isolation between projects that share one file, and no
	// login for g9s to run.
	CredentialsFile string `yaml:"credentials_file"`

	// Production marks a project where a mistake is expensive.
	//
	// It only ever adds friction: a project marked production makes every
	// action confirmation louder and demands the resource's name be typed,
	// including for actions that are not otherwise destructive. It cannot
	// make anything easier, which is what makes it safe to guess at — see
	// IsProduction.
	//
	// A pointer so that "unset" and "explicitly false" are different answers.
	// Someone who writes `production: false` on a project called prod-data has
	// said something deliberate, and guessing over the top of it would make
	// the setting a lie.
	Production *bool `yaml:"production"`

	Regions           []string `yaml:"regions"`
	DataprocRegions   []string `yaml:"dataproc_regions"`
	ComposerLocations []string `yaml:"composer_locations"`
}

Project is one GCP project as the user works with it: the project ID plus the identity used to reach it and the regions worth scanning.

func (Project) IsProduction added in v0.1.30

func (p Project) IsProduction() bool

IsProduction reports whether a project should be treated as production.

An explicit setting always wins. Otherwise the name and project ID are checked for the usual markers, because the common case is that nobody set the flag and the project is called something like acme-dataeng-prod-4471 — and the first time anyone thinks about this setting should not be after stopping the wrong instance.

Jump to

Keyboard shortcuts

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