Documentation
¶
Overview ¶
Package dbfwd connects a program to a database that is reachable only through a forward, such as a database that runs on Kubernetes.
Resolve reads a URL that github.com/xo/dburl parsed, such as k+cnpg://pg.prod/app, finds the database and its credentials, starts the forward, and returns a Forward with an ordinary URL for a local port. The URL holds no password. The backend finds it.
A backend registers itself from init. A program imports the backends it uses:
import _ "github.com/xo/dbfwd/k8s"
Index ¶
- func Handles(u *dburl.URL) bool
- func ListURL(backend, scope string, where ...Field) (*dburl.URL, error)
- func Register(name string, b Backend)
- type Backend
- type Config
- type Entry
- type Error
- type Field
- type Forward
- type Lister
- type Listing
- type LookupError
- type Match
- type Opened
- type Option
- type Skip
- type Step
- type Target
- type Tunnel
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Handles ¶
Handles reports whether a backend is registered for the scheme of u. A caller, such as usql, uses it in place of a list of schemes of its own.
func ListURL ¶ added in v0.3.0
ListURL builds the URL of a listing for the backend, such as "k8s", from a scope that a person typed and the fields that edit it, so that every caller reads a scope in the same way. The backend owns the rules, and docs/LIST.md holds them. A field that disagrees with the scope is an error that wraps ErrBadURL.
Types ¶
type Backend ¶
type Backend interface {
// Lookup runs the lookup for u.
Lookup(ctx context.Context, u *dburl.URL, cfg Config) (*Match, error)
// Open starts a forward to the database that u names, and returns once it
// is ready.
Open(ctx context.Context, u *dburl.URL, cfg Config) (*Opened, error)
}
Backend finds a database and starts a forward to it. A backend registers itself from init with Register.
type Config ¶
type Config struct {
// Tools maps the name of a tool, such as kubectl, to its path.
Tools map[string]string
// Env holds the variables that WithEnv set, as KEY=value, in order.
Env []string
// Interactive runs a child process with the terminal, or is nil.
Interactive func(run func(tty *os.File) error) error
}
Config is the configuration of one call, built from its options. A caller never builds one. A backend reads it.
type Entry ¶ added in v0.2.0
type Entry struct {
// Target is the object that the row stands for, as Lookup reports it.
Target Target
// Operator is the name of the operator that manages the database, such
// as "CloudNativePG", or empty when none does.
Operator string
// URL is the shortest URL that Resolve maps to the same database, such
// as "k://pg.prod/". It holds no password.
URL string
// Roles holds the roles that the database serves, such as "rw" and "ro".
Roles []string
// Ready is the number of pods that are ready, and Pods the number of
// pods.
Ready, Pods int
// Databases holds the databases that the rules name, or none.
Databases []string
// Credential says where Resolve reads the password, such as
// "Secret pg-app key password". It never holds a secret value.
Credential string
}
Entry is one database that List found.
type Error ¶
type Error string
Error is an error.
const ( // ErrNoBackend is the error for a URL whose scheme has no backend. ErrNoBackend Error = "no backend for the scheme" // ErrNoTool is the error when a tool that the backend runs, such as // kubectl, is missing or cannot run. The error that wraps it names the // tool. ErrNoTool Error = "tool is missing or cannot run" // refused, because they expired or a login failed. The fix is to log in // again. ErrUnauthorized Error = "not logged in" // ErrForbidden is the error when a step was not allowed, by RBAC or by // IAM. The fix is to ask for access. ErrForbidden Error = "not allowed" // ErrNotFound is the error when no step of the lookup matched. ErrNotFound Error = "not found" // ErrAmbiguous is the error when a step matched more than one object, or // the signals for the type disagree. ErrAmbiguous Error = "more than one match" // ErrUnsupported is the error for a database that no database/sql driver // can reach, such as MongoDB, or for a target that a forward cannot reach, // such as an ExternalName Service. ErrUnsupported Error = "not supported" // ErrRoleConflict is the error when role disagrees with the target, such // as role=ro with the Service pg-rw. ErrRoleConflict Error = "role conflicts with the target" // ErrQueryKey is the error when a driver key has the name of a key of the // backend. ErrQueryKey Error = "query key clashes with a key of the backend" // ErrBadURL is the error when a URL cannot be read. It names no part of // the URL, because a local URL holds a password. ErrBadURL Error = "the URL is not valid" // ErrForwardLost is the error when a running forward stops on its own. ErrForwardLost Error = "forward lost" // ErrClosed is the error when a forward is used after Close. ErrClosed Error = "forward closed" )
Error values.
type Forward ¶
type Forward struct {
// User is the user the URL logs in as.
User string
// Database is the database the URL opens. It is empty when the database
// has none.
Database string
// Target is the object that the lookup matched.
Target Target
// contains filtered or unexported fields
}
Forward is a running forward to a database. Its methods are safe to call from more than one goroutine.
func Resolve ¶
Resolve finds the database that u names, starts a forward to it, and returns the Forward. It returns when the forward is ready.
The backend is chosen by u.SchemeName. Canceling ctx before Resolve returns stops it and releases everything it started. After Resolve returns, ctx no longer controls the forward, and Forward.Close does.
func (*Forward) Close ¶
Close stops the forward and releases the local port. It is safe to call more than once.
func (*Forward) Done ¶
func (f *Forward) Done() <-chan struct{}
Done returns a channel that is closed when the forward stops, by Close or because it was lost.
func (*Forward) Err ¶
Err returns nil while the forward runs and after Close. It returns why the forward was lost, as an error that wraps ErrForwardLost.
func (*Forward) String ¶
String returns the target, such as "Service pg-rw in context kind-prod, namespace prod, owned by CloudNativePG Cluster pg". It never holds the password.
func (*Forward) URL ¶
URL returns the URL of the local end, such as postgres://app:...@127.0.0.1:41234/app. It holds the password, so it must never be printed or logged. When the credential of the backend expires, URL makes a new one first. After the forward is lost, it returns an error that wraps ErrForwardLost.
Call URL for each new connection, and do not keep its result. It is cheap when nothing expired, and safe to call from many goroutines at once.
type Lister ¶ added in v0.2.0
type Lister interface {
// List lists the databases that u names.
List(ctx context.Context, u *dburl.URL, cfg Config) (*Listing, error)
// ListURL builds the URL of a listing from a scope and the fields that
// edit it. It returns the URL as a string for dburl.Parse.
ListURL(scope string, where []Field) (string, error)
}
Lister is a Backend that can list the databases it reaches (D18).
type Listing ¶ added in v0.2.0
type Listing struct {
// Scope is where List looked, as Target.Scope holds it, with the context
// and the namespace resolved. With every namespace, the namespace is "*".
Scope []Field
// Entries holds one entry for each database, sorted by scope, then by
// name.
Entries []Entry
// Skipped holds each part of the scope that List did not read, such as a
// kind that RBAC does not allow.
Skipped []Skip
}
Listing is what List found.
func List ¶ added in v0.2.0
List lists the databases that u names. The name and the namespace in u can be "*", and the name can hold "*" as a wildcard, such as k://*, k://*.prod or k://pg*.prod. List reads no credential and starts no forward.
List fails only when it read nothing, or when RBAC forbids the scope that u asks for. When it read some of the scope, it lists the rest in Skipped.
type LookupError ¶
type LookupError struct {
// Name is the name in the URL.
Name string
// Scope is where the lookup looked.
Scope []Field
// Steps is each step that was tried.
Steps []Step
// Err is the error value, such as ErrNotFound.
Err error
}
LookupError is the error of a lookup that failed. It names what was tried, and wraps one of the error values.
func (*LookupError) Error ¶
func (err *LookupError) Error() string
Error satisfies the error interface.
type Match ¶
type Match struct {
// Target is the object that matched.
Target Target
// Steps is each step that Lookup tried, in order.
Steps []Step
}
Match is what Lookup found.
type Opened ¶
type Opened struct {
// URL is the URL of the local end, as a string for dburl.Parse. It holds
// the password.
URL string
// Expires is when the credential in URL expires. It is zero when the
// credential does not expire.
Expires time.Time
// Renew makes a new URL when the credential expires, and returns when the
// new one expires. It is nil when the credential does not expire.
Renew func(ctx context.Context) (string, time.Time, error)
// User is the user the URL logs in as.
User string
// Database is the database the URL opens, or empty.
Database string
// Target is the object that the lookup matched.
Target Target
// Tunnel is the running forward.
Tunnel Tunnel
}
Opened is what a backend returns from Open.
type Option ¶
type Option func(*Config)
Option sets one value of the Config of a call of Resolve or Lookup.
func WithEnv ¶
WithEnv sets the environment variable key to value for every child process of the call, such as WithEnv("KUBECONFIG", path). With no such option, a child process gets the environment of the caller.
func WithInteractive ¶
WithInteractive runs each child process that can prompt inside fn, so that a credential plugin or a login can use the terminal. With no such option, no child process gets a terminal.
type Skip ¶ added in v0.2.0
type Skip struct {
// Scope is where, such as the namespace "prod".
Scope []Field
// Kind is what List tried to read there, such as "services".
Kind string
// Reason says why, such as "not allowed".
Reason string
}
Skip is a part of the scope that List did not read.
type Step ¶
type Step struct {
// Kind is the kind that the step looked for, such as "Helm release".
Kind string
// Result says what the step found, such as "no match", "not installed",
// "not allowed" or "match".
Result string
}
Step is one step of a lookup.
type Target ¶
type Target struct {
// Backend is the name of the backend, such as "k8s".
Backend string
// Scope is where the object lives, from the outside in, such as the
// context and the namespace for Kubernetes.
Scope []Field
// Kind is the kind of the object that matched, such as "Service".
Kind string
// Name is the name of the object that matched, such as "pg-rw".
Name string
// Owner is what manages the object, such as "CloudNativePG Cluster pg".
// It is empty when nothing manages it.
Owner string
// Type is the database type, such as "postgres".
Type string
}
Target is the object that a lookup matched.
type Tunnel ¶
type Tunnel interface {
// Done returns a channel that is closed when the tunnel stops.
Done() <-chan struct{}
// Err returns why the tunnel stopped, after Done is closed.
Err() error
// Close stops the tunnel. It is safe to call more than once.
Close() error
}
Tunnel is the running forward of a backend.
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
dbfwd
command
Command dbfwd connects the native client of a database, or usql, to a database that is reachable only through a forward, such as a database that runs on Kubernetes.
|
Command dbfwd connects the native client of a database, or usql, to a database that is reachable only through a forward, such as a database that runs on Kubernetes. |
|
Package k8s is the Kubernetes backend of dbfwd.
|
Package k8s is the Kubernetes backend of dbfwd. |