Documentation
¶
Overview ¶
Package core is pogi's shared plumbing: the gateway that routes every request to a service, the wire-protocol codecs, the request log, chaos rules, persistence and the admin API.
Index ¶
- Constants
- func APIVersionPath(path string) bool
- func ARN(service, region, account, resource string) string
- func AWSEnv(endpoint, region string) []string
- func Body(r *http.Request) []byte
- func Caution(size, limit int64) string
- func CheckZipPaths(data []byte) error
- func CheckZipReader(zr *zip.Reader) error
- func CodeCaution(what string, zipSize, zipLimit int64) string
- func DecodeCBOR(b []byte, v any) error
- func DecodeQuery(form url.Values, v any) error
- func DeliverTarget(target string) (service string, ok bool)
- func EncodeCBOR(v any) []byte
- func Env(endpoint, region string, storage ...string) []string
- func Every(d time.Duration, f func(now time.Time)) (stop func())
- func GRPCError(code codes.Code, format string, a ...any) error
- func GcloudEnv(endpoint string) []string
- func GlobalARN(service, region, account, resource string) string
- func Go(name string, f func())
- func GoogleStatus(httpStatus int) string
- func Hostport(endpoint string) string
- func InterruptGroup(cmd *exec.Cmd) error
- func JournalTest[S interface{ ... }](tb TB, svc, fresh S) func()
- func KillGroup(cmd *exec.Cmd)
- func Label(name string) string
- func Listen(tb TB, h http.Handler) string
- func ListenTLS(tb TB, hub *Hub, h http.Handler) (string, *x509.CertPool)
- func Loopback(host string) bool
- func NewID() string
- func NewTrace() string
- func OwnGroup(cmd *exec.Cmd)
- func ParseARN(arn string) (service, region, account, resource string, ok bool)
- func Partition(region string) string
- func PlainJSON(err error) string
- func PlainJSONOf(what string, err error) string
- func Protocols() *http.Protocols
- func QueryResponse(op, xmlns, requestID string, out any) []byte
- func RESTJSON(w http.ResponseWriter, c *Ctx, status int, out any)
- func RESTJSONError(w http.ResponseWriter, c *Ctx, err error)
- func RandHex(n int) string
- func RandString(n int, alphabet string) string
- func Recover(name string)
- func RegisterGoogleAPI(service, label string)
- func Replay[V any](m map[string]V, key string, value []byte) error
- func Sentence(name string) string
- func SniffTLS(ln net.Listener, cfg *tls.Config) net.Listener
- func SortedKeys[V any](m map[string]V) []string
- func SplitHost(host, hostname string) (label, base string)
- func TargetOp(target string) string
- func TraceFrom(h http.Header) string
- func TraceFromTraceparent(v string) string
- func TraceHeader(trace string) string
- func TraceRoot(v string) string
- func Traceparent(trace string) string
- func URLSuffix(region string) string
- func UUID() string
- func Unix(t time.Time) float64
- func WriteGoogleError(w http.ResponseWriter, c *Ctx, code int, name, msg string)
- func WriteJSON(w http.ResponseWriter, c *Ctx, version string, status int, out any)
- func WriteJSONError(w http.ResponseWriter, c *Ctx, version string, e *Error)
- func WriteQueryError(w http.ResponseWriter, c *Ctx, xmlns string, status int, code, msg string)
- func WriteXMLFields(b *strings.Builder, v reflect.Value)
- type BodyLimiter
- type Browsable
- type Chaos
- type Config
- type Ctx
- type DeliverFunc
- type Entry
- type Error
- type Field
- type Form
- type FunctionError
- type GRPCService
- type Handler
- type Hub
- func (h *Hub) AMQP() *amqp.Server
- func (h *Hub) AddIdentity(akid string, id Identity)
- func (h *Hub) BeginShutdown()
- func (h *Hub) CORS(w http.ResponseWriter, r *http.Request) (preflight bool)
- func (h *Hub) Call(account, region, target, op string, in, out any) error
- func (h *Hub) CallTrace(trace, account, region, target, op string, in, out any) error
- func (h *Hub) CertPaths() (ca, cert, key string)
- func (h *Hub) Check(c *Ctx) *Error
- func (h *Hub) Close()
- func (h *Hub) Closed(service, noun, verb, name string)
- func (h *Hub) ClosedPort(service, name string, port int)
- func (h *Hub) CodeLimit(base64 bool) int64
- func (h *Hub) ConsoleCall(account, region, target, op string, in, out any) error
- func (h *Hub) Credentials(akid string) (account, secret string, ok bool)
- func (h *Hub) DeleteSnapshot(path string) error
- func (h *Hub) Deliver(arn string, m *Message) error
- func (h *Hub) Do(account, region, signing, method, path string, header http.Header, body []byte) (int, http.Header, []byte)
- func (h *Hub) DoService(name string, req *http.Request) (int, []byte)
- func (h *Hub) DoServiceAs(name, account, region string, req *http.Request) (int, []byte)
- func (h *Hub) Docker() *docker.Client
- func (h *Hub) Emulator(match func(*http.Request) bool, handler http.Handler)
- func (h *Hub) Endpoint(key string) (string, bool)
- func (h *Hub) Flush(ctx context.Context)
- func (h *Hub) Handler(svc Service) http.Handler
- func (h *Hub) IAMMode() string
- func (h *Hub) Identity(akid string) (Identity, bool)
- func (h *Hub) ImportSnapshot(path string, r io.Reader) error
- func (h *Hub) Invoke(arn string, payload []byte) ([]byte, error)
- func (h *Hub) InvokeFrom(trace, from, arn string, payload []byte) ([]byte, error)
- func (h *Hub) LoadFile(path string) error
- func (h *Hub) LogConsole(service, op, target string, took time.Duration, err error)
- func (h *Hub) MarkDirty()
- func (h *Hub) MaxUpload() int64
- func (h *Hub) Mount(prefix string, handler http.Handler)
- func (h *Hub) OnDeliver(service string, f DeliverFunc)
- func (h *Hub) OnInvoke(f InvokeFunc)
- func (h *Hub) OnInvokeFrom(f InvokeFromFunc)
- func (h *Hub) OnReset(f func(services []string))
- func (h *Hub) OpenStorage() error
- func (h *Hub) PortProblem(service, text string)
- func (h *Hub) Problems() []Problem
- func (h *Hub) Register(s Service)
- func (h *Hub) RemoveIdentity(akid string)
- func (h *Hub) Reset(names ...string)
- func (h *Hub) Resources(service string) map[string][]Table
- func (h *Hub) Restore(b []byte) error
- func (h *Hub) SaveFile(path string) error
- func (h *Hub) ServeHTTP(w http.ResponseWriter, r *http.Request)
- func (h *Hub) Service(name string) Service
- func (h *Hub) Services() []Service
- func (h *Hub) SetEndpoint(key, addr string)
- func (h *Hub) SetIAMMode(mode string)
- func (h *Hub) ShutdownList() string
- func (h *Hub) Snapshot() ([]byte, error)
- func (h *Hub) SnapshotPath(name string) (string, error)
- func (h *Hub) Snapshots() []SnapshotInfo
- func (h *Hub) Sniff(ln net.Listener, cfg *tls.Config) net.Listener
- func (h *Hub) Span(kind, service, op, from, to, trace string, start time.Time, err error)
- func (h *Hub) Status() Status
- func (h *Hub) TLS() (*tls.Config, error)
- func (h *Hub) TooBig(service, resource string, size, limit int64) string
- func (h *Hub) TooBigCode(service, resource, what string, zipSize, zipLimit int64) string
- func (h *Hub) VerifyPolicy(credential, policy, signature string) *Error
- func (h *Hub) VerifyPresigned(service, rawURL string) error
- type Identity
- type ImageRegistry
- type Info
- type InitHooks
- type InitScript
- type Inspectable
- type InvokeFromFunc
- type InvokeFunc
- type Journal
- type Journaled
- type Link
- type Linker
- type Message
- type MessageAttribute
- type ObjectInfo
- type Porter
- type Problem
- type RPC
- type RegistryImage
- type RequestLog
- func (l *RequestLog) Add(e Entry) Entry
- func (l *RequestLog) Get(id int64) (Entry, bool)
- func (l *RequestLog) Query(after int64, limit int, service, q string, errorsOnly bool) []Entry
- func (l *RequestLog) Totals() map[string]int
- func (l *RequestLog) Wait(ctx context.Context, after int64, d time.Duration)
- type Rule
- type Service
- type ServiceStatus
- type SnapshotInfo
- type Span
- type SpanLog
- type Stateful
- type Status
- type TB
- type Table
- type Time
Constants ¶
const ( AWS = "aws" GCP = "gcp" Azure = "azure" )
Clouds.
const ( DefaultAccount = "000000000000" DefaultRegion = "us-east-1" // Azure resource IDs need a subscription and a resource group; pogi's resources live in these. AzureSubscription = "00000000-0000-0000-0000-000000000000" AzureResourceGroup = "pogi" )
Defaults used when a request does not say otherwise.
const ( Upper = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" UpperNum = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" AlphaNum = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" )
Alphabets for RandString.
const ( AzuriteKey = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==" CosmosKey = "C2y6yDjf5/R+ob0N8A7Cgv30VRDJIWEHLM+4QDU5DE2nQ9nDuVTqobD4b8mGGyPMbIZnqyMsEcaGQy67XIw/Jw==" )
Well-known emulator keys (Azurite and the Cosmos DB emulator); pogi accepts any key.
const ( SpanDeliver = "deliver" // a message handed from one resource to another SpanInvoke = "invoke" // pogi ran a function SpanRedrive = "redrive" // a message moved to a dead-letter queue SpanNotify = "notify" // a notification to a subscriber or endpoint )
Span kinds.
const ConsoleHeader = "X-Pogi-Console"
ConsoleHeader marks an in-process call as a write the console made for the user. Such calls are logged (marked "console"); other internal calls are not. Like internalHeader, it only counts for in-process calls.
const DefaultProject = "pogi"
DefaultProject is the Google Cloud project `pogi env` names for gcloud; pogi serves any project, and seeds without one use it too.
const ISO = "2006-01-02T15:04:05.000Z"
ISO is the timestamp layout used by XML protocols.
const TestLambdaInit = time.Minute
TestLambdaInit is the Lambda start limit in pogi's own tests. AWS's 10 seconds is too tight for a cold start while a full test run loads the machine (TestExternalExtension failed so, 3 runs in about 22); a start that is truly stuck still fails.
Variables ¶
This section is empty.
Functions ¶
func APIVersionPath ¶
APIVersionPath says whether a request path starts with a Google API version ("/v1/projects/..."). No S3 bucket has such a name: two characters are too short.
func ARN ¶
ARN builds "arn:partition:service:region:account:resource"; the partition follows the region.
func CheckZipPaths ¶ added in v0.2.0
CheckZipPaths refuses a zip with an entry that is absolute or leaves its folder ("../x"). Every code-zip reader (Lambda, Azure Functions, Google Cloud Functions) uses it, so the same rule holds at upload and at unpack. Data that is not a zip is not its job: the caller reports that.
func CheckZipReader ¶ added in v0.2.0
CheckZipReader is CheckZipPaths for a zip that is already open.
func CodeCaution ¶
CodeCaution is Caution for function code, which is limited by the size of its zip: what names the code ("Lambda code", "Function code").
func DecodeCBOR ¶
DecodeCBOR decodes a CBOR request into v by way of its JSON shape.
func DecodeQuery ¶
DecodeQuery fills v (a pointer to a struct) from AWS Query form values: lists as Name.member.N or flattened Name.N, maps as Name.entry.N.key/value (also Key/Name and Value), nested structs as Name.Field.
func DeliverTarget ¶
DeliverTarget names the service Deliver hands a target to.
func EncodeCBOR ¶
EncodeCBOR encodes an output value the way JSON would see it, with byte slices as byte strings and Time/time.Time as tag-1 epoch timestamps.
func Env ¶
Env is AWSEnv plus the variables Google Cloud and Azure clients read. storage overrides the blob, queue and table base URLs (default: the Azurite ports 10000-10002 on the endpoint's host).
func Every ¶
Every calls f on a ticker in its own goroutine until the returned stop is called; services use it for clocks (schedules, TTLs, buffers) and stop it in Close.
func GcloudEnv ¶
GcloudEnv points the gcloud CLI at pogi: one CLOUDSDK_API_ENDPOINT_OVERRIDES_<API> per served API, the default project and a dummy access token. The override is the bare endpoint with a "/" path, so that gcloud keeps each API's own version path (/v1, /v2). ponytail: gcloud itself reads its token from a file (CLOUDSDK_AUTH_ACCESS_TOKEN_FILE, which `pogi env` adds); CLOUDSDK_AUTH_ACCESS_TOKEN is for other tooling and ignored by gcloud.
func GlobalARN ¶
GlobalARN builds the ARN of a resource without a region (IAM, STS, S3 buckets, Route 53), in the partition of region: "arn:partition:service::account:resource".
func Go ¶
func Go(name string, f func())
Go runs f in a new goroutine. If f panics, the panic is logged once with the name and the stack, and only that goroutine ends. pogi keeps running.
func GoogleStatus ¶
GoogleStatus is the error.status that goes with an HTTP status in a Google API error: 404 is "NOT_FOUND", 501 is "UNIMPLEMENTED".
func InterruptGroup ¶
InterruptGroup asks the whole group of cmd to stop (SIGINT).
func JournalTest ¶
JournalTest gives svc a journal for a test and returns a check that replays it into fresh, which must then save the same state as svc.
func Label ¶
Label turns a member name into a label: DBInstanceIdentifier is "DB Instance Identifier".
func Listen ¶
Listen serves h on a random loopback port until the test ends and returns the base URL.
func ListenTLS ¶
ListenTLS serves h over HTTPS (pogi's local CA) for tests of SDKs that insist on TLS (Key Vault, Cosmos DB); it returns https://localhost:port and a pool that trusts the CA.
func NewTrace ¶
func NewTrace() string
NewTrace returns a fresh AWS-style trace id, 1-<8 hex>-<24 hex>.
func OwnGroup ¶
OwnGroup makes cmd start in its own process group, so StopGroup reaches the children it starts too (a Functions host's workers, for one). Call it before cmd.Start.
func Partition ¶
Partition is the AWS partition of a region: aws-cn for China, aws-us-gov for GovCloud, otherwise aws.
func PlainJSON ¶ added in v0.2.0
PlainJSON says in a plain sentence what is wrong with a JSON request body that failed to decode. Go's own text follows after " — " for anyone who needs the detail. Any other error comes back unchanged.
func PlainJSONOf ¶ added in v0.2.0
PlainJSONOf is PlainJSON for a document that is not a request body, such as "the plan file".
func QueryResponse ¶
QueryResponse renders <OpResponse><OpResult>…</OpResult><ResponseMetadata/></OpResponse>.
func RESTJSON ¶
func RESTJSON(w http.ResponseWriter, c *Ctx, status int, out any)
RESTJSON writes a REST-JSON success response.
func RESTJSONError ¶
func RESTJSONError(w http.ResponseWriter, c *Ctx, err error)
RESTJSONError writes the error format of REST-JSON services (Lambda, API Gateway…).
func RandString ¶
RandString returns n random characters from alphabet.
func Recover ¶
func Recover(name string)
Recover is for "defer core.Recover(name)" at the top of a goroutine. It logs a panic with the stack and swallows it.
func RegisterGoogleAPI ¶ added in v0.2.0
func RegisterGoogleAPI(service, label string)
RegisterGoogleAPI adds a Google API that a generic engine serves (internal/gcp/generic): the service's host label goes into googleHosts, and /<label>/v1/... reaches it on any host, like the APIs in googlePrefixed. Call it from an init function, before the server starts.
func Replay ¶
Replay is the usual body of Apply: it sets m[key] from a record's value, or deletes the key when the value is nil.
func Sentence ¶ added in v0.2.0
Sentence is Label in sentence case, for titles: CreateNodePool is "Create node pool". Acronyms (DB, IAM) keep their capitals.
func SniffTLS ¶
SniffTLS lets one port speak both HTTP and HTTPS: connections that open with a TLS handshake get TLS, everything else stays plain (incl. h2c).
func SortedKeys ¶
SortedKeys returns the keys of a string-keyed map in order.
func SplitHost ¶
SplitHost splits a request host into the label in front of a base and that base, without the port: "my-bucket.aws.localhost:7644" is ("my-bucket", "aws.localhost") and "abc.execute-api.localhost" is ("abc", "execute-api.localhost"). hostname (Config.Hostname, or "" for none) is a base of its own, and an SDK host prefix glued to it ("sync-aws.localhost", from Step Functions' StartSyncExecution) is dropped. IPs and single names have no label.
func TargetOp ¶
TargetOp is the operation of an X-Amz-Target header. It is what follows the last dot, so it also reads the long target some SDKs send to CloudTrail (com.amazonaws.cloudtrail.v20131101.CloudTrail_20131101.Op).
func TraceFrom ¶
TraceFrom reads the trace a request carries: the Root of X-Amzn-Trace-Id, else the id of traceparent or X-Cloud-Trace-Context. Without one it makes a new trace.
func TraceFromTraceparent ¶
TraceFromTraceparent reads the trace of a W3C traceparent value ("00-<32 hex>-<16 hex>-01"), or "".
func TraceHeader ¶
TraceHeader is the X-Amzn-Trace-Id value that carries a trace to the next hop.
func TraceRoot ¶
TraceRoot returns the Root of an X-Amzn-Trace-Id style value ("Root=1-...;Parent=...;Sampled=1"), or "".
func Traceparent ¶
Traceparent is the W3C traceparent that carries a trace to the next hop, or "" for a trace that has no such form.
func WriteGoogleError ¶
func WriteGoogleError(w http.ResponseWriter, c *Ctx, code int, name, msg string)
WriteGoogleError writes the error body of a Google JSON API: {"error": {"code", "message", "status"}}.
func WriteJSONError ¶
func WriteJSONError(w http.ResponseWriter, c *Ctx, version string, e *Error)
WriteJSONError writes an AWS JSON protocol error.
func WriteQueryError ¶
WriteQueryError writes an AWS Query protocol error.
func WriteXMLFields ¶
WriteXMLFields writes the fields of a struct (or the entries of a map) as query-protocol XML elements. Empty strings, nil pointers and empty lists/maps are omitted, as AWS mostly does; a list tagged query:",empty" is written empty, for the outputs where AWS sends one.
Types ¶
type BodyLimiter ¶
BodyLimiter is for a service that needs another body limit for some requests: a bigger one (function code) or none at all (a negative number: image pushes). 0 means the default, MaxUpload.
type Browsable ¶
type Browsable interface {
Resources() []Table
}
Browsable services list their resources for the console, TUI and CLI.
type Chaos ¶
type Chaos struct {
// contains filtered or unexported fields
}
Chaos holds fault-injection rules.
type Config ¶
type Config struct {
Host string // listen host
Port int // main port
ECRPort int // ECR registry port, localhost:<ECRPort> (pogi.New: 4510, Start: none); <0: main port only
SMTPPort int // SES SMTP port, localhost:<SMTPPort> (pogi.New: 2525, Start: none); <0: off
AMQPPort int // AMQP 1.0 port for Service Bus and Event Hubs, plain TCP (pogi.New: 5672, Start: a random port); <=0: off
MQTTPort int // IoT MQTT broker port, plain TCP (pogi.New: 1883, Start: none); <0: WebSocket at /mqtt only
TransferPort int // Transfer Family SFTP port, opened with the first server (pogi.New: 2222, Start: a free port)
Region string // default AWS region
DataDir string // ~/.pogi
Persist bool // --persist: hybrid storage when Storage is empty
Services []string // enabled services or clouds; empty means all
Lambda string // auto | native | docker
IAM string // off | soft | strict
Version string
NoTLS bool // plain HTTP only on the main port
NoPorts bool // do not open the Azurite-style extra ports
Hostname string // "localhost"; e.g. "aws.localhost" for virtual-host style URLs
TLSCert string // custom certificate and key files; empty: pogi's local CA
TLSKey string //
CORSOrigins []string // extra browser origins allowed on every API
CORSHeaders []string // extra request headers allowed from those origins
AllowExternal bool // permit a non-loopback Host
MaxUploadMB int // largest upload in MiB; 0 means 10
Storage string // memory | hybrid | persistent | wal; Persist means hybrid
FlushInterval time.Duration // hybrid flush period
StorageModes map[string]string // per-service storage mode
ValidateSigs bool // check SigV4 signatures
WarmPool int // Lambda environments kept warm per function
LambdaInit time.Duration // longest a new Lambda environment may take to start; 0 means 10s, AWS's init limit
DockerHost string // container engine socket or URL; empty: auto-detect
DockerNetwork string // network for managed containers
DockerImages map[string]string // image overrides, e.g. "rds.postgres"
AIEndpoint string // OpenAI-compatible endpoint for Bedrock and friends
AIKey string //
AIModels map[string]string // model id glob → local model
AITimeout time.Duration // longest one model call; 0 means 5 minutes
SMTPRelay string // smtp://[user:pass@]host:port that SES also delivers every message to (Mailpit, MailHog)
File *config.File // pogi.yaml, for seeding, identities, chaos and stacks
}
Config is the runtime configuration shared by all services.
type Ctx ¶
type Ctx struct {
Hub *Hub
Cloud string
Service string
Op string
Account string
Region string
AccessKey string
Principal string
Bearer string // the Authorization bearer token (HTTP) or authorization metadata (gRPC), for the cloud's IAM authorizer
Resource string // the resource name a gRPC request names, for IAM (HTTP requests carry theirs in Path)
RequestID string
Host string
Path string
RawQuery string // the URL query as received (HTTP), for IAM
Header http.Header // the request headers (HTTP), for IAM
Denied map[string]bool // S3 DeleteObjects: keys IAM refused; the handler answers each as AccessDenied
ErrCode string // set by error writers, shown in the request log
IAM string // the IAM decision when enforcement is on, shown in the request log
Trace string // the flow this request belongs to, shown in the request log
Chaos bool // the response was injected by a chaos rule
Internal bool // an in-process call from another service (Hub.Call)
// contains filtered or unexported fields
}
Ctx carries what the gateway learned about a request.
func (*Ctx) BodyErr ¶ added in v0.2.0
BodyErr is the answer for a request body that was too large or stalled, or nil. A service that looks up the operation before Intercept must answer it first, so the caller sees 413 and not "not implemented".
func (*Ctx) Context ¶ added in v0.2.0
Context is the request's context; it ends when the client leaves. Calls made in-process have none, so it is then Background.
func (*Ctx) GlobalARN ¶
GlobalARN builds a region-less ARN (IAM, STS) for this request's account, in the partition of its region.
type DeliverFunc ¶
DeliverFunc receives a message for a resource ARN of one service.
type Entry ¶
type Entry struct {
ID int64 `json:"id"`
Time time.Time `json:"time"`
Cloud string `json:"cloud"`
Service string `json:"service"`
Op string `json:"op"`
Method string `json:"method"`
Path string `json:"path"`
Status int `json:"status"`
Ms float64 `json:"ms"`
Account string `json:"account,omitempty"`
Region string `json:"region,omitempty"`
RequestID string `json:"requestId,omitempty"`
AccessKey string `json:"accessKey,omitempty"`
Principal string `json:"principal,omitempty"`
Error string `json:"error,omitempty"`
Console bool `json:"console,omitempty"` // a write made from the console, not an SDK call
Chaos bool `json:"chaos,omitempty"`
IAM string `json:"iam,omitempty"` // "allow" or "deny: why" when enforcement is on
Trace string `json:"trace,omitempty"` // the flow (Ctx.Trace) this request belongs to
ReqHeaders map[string]string `json:"reqHeaders,omitempty"`
ReqBody string `json:"reqBody,omitempty"`
RespBody string `json:"respBody,omitempty"`
}
Entry is one recorded API call.
func (Entry) Alarming ¶ added in v0.2.0
Alarming says whether the entry is an error worth a red count: status 400 or more, except a 404 from a read (a GET, a HEAD, or an operation named Get, Describe, Head or List: AWS JSON protocols POST their reads). Looking for something that is not there is normal.
type Error ¶
Error is an API error, rendered in the caller's wire protocol.
type Field ¶
type Field struct {
Name string // member name, as the API spells it
Label string // "DB Instance Identifier": shown instead of the name
Kind string // string, integer, number, bool, enum, json, struct, list, map
Required bool
Enum []string
Fields []Field // the members of a struct
Elem *Field // the element of a list, the value of a map
Default string // prefilled value
Help string // a hint under the input, for rules the API only reports after the call
Pattern string // a regular expression the browser checks a string input against
}
Field is one input of a console form, built from an API model (botocore, protobuf) or written by hand. Values are read back into JSON by member name.
type FunctionError ¶
type FunctionError struct{ Payload []byte }
FunctionError is returned by Hub.Invoke when the function itself failed; Payload holds its error JSON.
func (*FunctionError) Error ¶
func (e *FunctionError) Error() string
type GRPCService ¶
GRPCService is a service that also speaks gRPC (Google Cloud APIs). Its Info.Targets list the gRPC service names, e.g. "google.pubsub.v1.Publisher".
type Hub ¶
type Hub struct {
Cfg Config
Log *slog.Logger
Requests *RequestLog
Spans *SpanLog // steps of flows that are not requests: deliveries, invocations, redrives
Chaos *Chaos
Started time.Time
Init *InitHooks
URL string // base URL once listening, e.g. http://localhost:7644
GRPC *grpc.Server
// PG serves a connection that opens like a PostgreSQL client's (Aurora DSQL); a service sets it once at start.
// Nil: such a connection is closed.
PG func(net.Conn)
// Ready is set once serving, just before "Ready." is printed (pogi wait).
Ready atomic.Bool
// Authorize evaluates IAM for a request, by cloud: each cloud's IAM service sets its own.
// It records its decision in Ctx.IAM and returns an error to deny; it runs in every mode
// and only strict mode denies (see Hub.Check).
Authorize map[string]func(c *Ctx) *Error
// CheckInput checks the input limits of a request to an AWS service before the service sees it
// (set by pogi.New). It answers a bad request itself and reports true; false lets the service run.
CheckInput func(svc Service, c *Ctx, w http.ResponseWriter, r *http.Request) bool
// Seed applies a pogi.yaml `resources:` fragment (set by pogi.New; used by MCP).
Seed func(fragment []byte) error
// contains filtered or unexported fields
}
Hub owns the services of one pogi instance and routes requests to them. There are no globals: several hubs can live in one process (tests).
func (*Hub) AMQP ¶
AMQP is the AMQP 1.0 broker that Service Bus and Event Hubs add their resolvers to.
func (*Hub) AddIdentity ¶
AddIdentity maps an access key (e.g. from STS AssumeRole) to an identity.
func (*Hub) BeginShutdown ¶
func (h *Hub) BeginShutdown()
BeginShutdown starts the clock and the record; Run calls it once the stop signal came.
func (*Hub) CORS ¶
CORS lets browser apps call pogi's APIs. Like LocalStack, it allows loopback origins (any scheme and port on localhost, *.localhost, 127.0.0.1 and ::1), plus Cfg.CORSOrigins ("*" allows any), with the headers AWS SDKs send plus Cfg.CORSHeaders. It reports whether r was a preflight, which it has answered: 204, or 403 for any other origin. S3 buckets with a CORS configuration, API Gateway and Lambda URLs apply their own rules instead, and the admin API keeps its cross-origin protection.
func (*Hub) Call ¶
Call invokes a JSON-protocol operation in-process as account/region, the way Lambda pollers, Step Functions and CloudFormation reach other services. Internal calls skip the request log and chaos rules.
func (*Hub) CallTrace ¶
CallTrace is Call inside a flow: the called service sees the trace on X-Amzn-Trace-Id, so what it sends on stays in the same flow.
func (*Hub) Check ¶
Check runs the request's cloud's IAM authorizer. It also runs in off mode, where it only records for the console's IAM page; only strict mode denies. Paths that bypass the HTTP gateway (gRPC, AMQP) call it themselves.
func (*Hub) Close ¶
func (h *Hub) Close()
Close stops background work of services that have any (Lambda processes, containers), then writes on-disk state one last time; called on shutdown. A second call does nothing, so a test may stop a server early and still leave its cleanup in place (a service closing twice used to panic).
func (*Hub) Closed ¶
Closed records that a service stopped a local process, or removed a container (noun "process" or "container", verb "stopped" or "removed").
func (*Hub) ClosedPort ¶
ClosedPort records a TCP port that pogi opened for a service and closed; name says what it served.
func (*Hub) CodeLimit ¶
CodeLimit is the body limit for function code uploads: AWS's 50 MB direct-upload limit for a zip, or more when the owner raised the upload limit. base64 says the zip travels as base64 in JSON (Lambda), which needs a third more room.
func (*Hub) ConsoleCall ¶ added in v0.2.0
ConsoleCall is Call for a write the console makes: it shows in Activity, marked "console".
func (*Hub) Credentials ¶
Credentials returns the account an access key acts in and its secret (ok is false for an unknown key), for logins outside SigV4 such as SES SMTP.
func (*Hub) DeleteSnapshot ¶
DeleteSnapshot removes a saved snapshot.
func (*Hub) Deliver ¶
Deliver routes a message to the service that owns the target:
- an AWS ARN, to its service;
- a Google full resource name ("//pubsub.googleapis.com/projects/p/topics/t"), to the API ("pubsub") with the name after the host ("projects/p/topics/t");
- an Azure resource ID ("/subscriptions/s/resourceGroups/g/providers/Microsoft.ServiceBus/namespaces/n/queues/q"), to the lower-cased provider ("microsoft.servicebus") with the ID unchanged.
func (*Hub) Do ¶
func (h *Hub) Do(account, region, signing, method, path string, header http.Header, body []byte) (int, http.Header, []byte)
Do sends an HTTP request through the gateway in-process as account/region (signing name chooses the service), for REST services such as S3, Lambda and API Gateway. It returns the status, headers and body.
func (*Hub) DoService ¶
DoService serves req straight to the named service as an internal call (no routing, request log, chaos or IAM), the way seeding reaches the Google Cloud and Azure APIs. It returns the status and body.
func (*Hub) DoServiceAs ¶
DoServiceAs is DoService as the given account and region.
func (*Hub) Docker ¶
Docker is the container engine client of this instance, made on first use; Available says whether an engine runs.
func (*Hub) Emulator ¶
Emulator registers a handler for the vendor emulators' admin paths under /emulator/v1/ (Firestore's DELETE .../documents, Firebase Auth's accounts, oobCodes and config). The first handler whose match accepts the request serves it, so each emulator claims its own sub-paths and none swallows another's.
func (*Hub) Flush ¶
Flush keeps the files of on-disk services current until ctx ends: hybrid services every FlushInterval (default 5s), the others every second, which catches what services change in each other outside requests (SNS to SQS, CloudFormation). Journals past 8 MiB are compacted. Close writes once more. ponytail: each tick re-marshals every service to hash it; add per-service dirty bits if big states make the idle CPU matter.
func (*Hub) Handler ¶
Handler serves one service on its own port (Azurite-style), with the same context, logging and chaos as the gateway. The account is the first path segment (devstoreaccount1).
func (*Hub) IAMMode ¶
IAMMode is the IAM enforcement mode, off | soft | strict. It starts as Cfg.IAM and the console can change it while pogi runs.
func (*Hub) ImportSnapshot ¶
ImportSnapshot validates an uploaded snapshot and stores it at path.
func (*Hub) InvokeFrom ¶
InvokeFrom is Invoke inside a flow: trace reaches the function, and the invocation shows in the flow as a step from from (a resource id).
func (*Hub) LogConsole ¶ added in v0.2.0
LogConsole records a write the console made straight on a service (not through the hub), marked "console". err is the write's result. Every such write goes through it: web's UI.write.
func (*Hub) MarkDirty ¶
func (h *Hub) MarkDirty()
MarkDirty does nothing: the storage loop finds changes made outside requests by hashing each service's state. Kept for the services calling it.
func (*Hub) MaxUpload ¶
MaxUpload is the upload limit in bytes: Cfg.MaxUploadMB, or 10 MiB. It caps every request body and every assembled file (multipart, blocks, resumable chunks).
func (*Hub) Mount ¶
Mount serves an internal handler under prefix, outside the request log. The longest matching prefix wins.
func (*Hub) OnDeliver ¶
func (h *Hub) OnDeliver(service string, f DeliverFunc)
OnDeliver registers the deliverer for one service's targets: an AWS service ("sqs", "sns"), a Google API ("pubsub", "run", "cloudfunctions") or an Azure resource provider ("microsoft.servicebus", "microsoft.eventhub").
func (*Hub) OnInvoke ¶
func (h *Hub) OnInvoke(f InvokeFunc)
OnInvoke registers the synchronous function invoker.
func (*Hub) OnInvokeFrom ¶
func (h *Hub) OnInvokeFrom(f InvokeFromFunc)
OnInvokeFrom registers the invoker that takes a trace (Lambda).
func (*Hub) OnReset ¶
OnReset registers f to run after every Reset; services is empty for a full reset.
func (*Hub) OpenStorage ¶
OpenStorage loads every service kept on disk from DataDir/state, after migrating the single DataDir/state.json of older versions, and replays the journals of wal-mode services. Call it once, before serving.
func (*Hub) PortProblem ¶ added in v0.2.0
PortProblem records that a service's own port could not be opened, so that part of pogi is off. It stays for as long as pogi runs: the port is not tried again.
func (*Hub) RemoveIdentity ¶
RemoveIdentity forgets an access key (deleted or deactivated IAM keys).
func (*Hub) Reset ¶
Reset clears the named services (all when none given), then runs the OnReset hooks (seeding from pogi.yaml).
func (*Hub) ServeHTTP ¶
func (h *Hub) ServeHTTP(w http.ResponseWriter, r *http.Request)
ServeHTTP is the gateway: it finds the service, builds the Ctx and logs the call.
func (*Hub) SetEndpoint ¶
SetEndpoint records where pogi reaches a container-backed resource, for load balancers and proxies: "ip:10.0.1.5:80" or "instance:i-0abc:80" → "127.0.0.1:49153". An empty addr removes it.
func (*Hub) SetIAMMode ¶
SetIAMMode switches IAM enforcement for the requests that follow.
func (*Hub) ShutdownList ¶
ShutdownList is the text for the end of a run: what was stopped, where the state was saved and how long it took. It is empty if shutdown never began.
func (*Hub) SnapshotPath ¶
SnapshotPath validates a snapshot name and returns its file path.
func (*Hub) Snapshots ¶
func (h *Hub) Snapshots() []SnapshotInfo
Snapshots lists saved snapshots, newest first.
func (*Hub) Sniff ¶ added in v0.2.0
Sniff is SniffTLS for pogi's own port: a connection whose first byte is 0x00 is a PostgreSQL client (an SSLRequest or a StartupMessage; HTTP and TLS never open so) and goes to h.PG. A nil cfg keeps TLS off.
func (*Hub) Span ¶
Span records a step that began at start. With neither a trace nor a sender it records nothing: such traffic is part of no flow and no edge.
func (*Hub) TLS ¶
TLS returns a server config: Cfg.TLSCert and TLSKey when set, otherwise a certificate for localhost signed by a local CA, both created on first use (trust ca.pem once, see `pogi cert`).
func (*Hub) TooBig ¶
TooBig is the message for an upload that is over the limit. It logs the refusal (service and resource name what was refused) and returns the Caution sentence.
func (*Hub) TooBigCode ¶
TooBigCode is TooBig for function code: sizes are of the zip.
func (*Hub) VerifyPolicy ¶
VerifyPolicy checks an S3 browser POST upload when Config.ValidateSigs is on: the x-amz-signature form field over the base64 policy, then the policy's expiration. Uploads without a SigV4 signature pass. ponytail: policy conditions are not enforced.
func (*Hub) VerifyPresigned ¶
VerifyPresigned checks a presigned URL that never arrives as an HTTP request, like an RDS IAM auth token, the way verify checks requests; service is a registered one, whose error codes apply.
type Identity ¶
type Identity struct {
Account string `json:"account"`
ARN string `json:"arn"`
UserID string `json:"userId"`
Secret string `json:"-"` // secret access key, for signature checking
Expires time.Time `json:"-"` // temporary (STS) credentials stop working at this time; zero means never
}
Identity is who an access key belongs to.
type ImageRegistry ¶
type ImageRegistry interface {
// Claim serves the names under prefix/; it is idempotent and survives ECR's Reset.
Claim(prefix string)
// Release stops serving prefix/ and deletes everything pushed under it.
Release(prefix string)
// Images lists what was pushed under prefix/, by repository name and digest.
Images(prefix string) []RegistryImage
}
ImageRegistry is what the ECR service offers the other clouds' container registries (Azure Container Registry, Artifact Registry): its OCI endpoint for docker push and pull, under a name prefix of their own such as "myregistry" or "project/repository". A push under a claimed prefix makes its repository, and ECR's own API never lists them.
func Registry ¶
func Registry(h *Hub) ImageRegistry
Registry is the shared OCI registry, or nil when ECR is not enabled.
type Info ¶
type Info struct {
Name string // unique id, e.g. "s3", "sqs", "gcs"
Cloud string // AWS, GCP or Azure
Title string // human name
Targets []string // X-Amz-Target prefixes and smithy rpcv2 service names
Signing []string // SigV4 signing names
Match func(*http.Request) bool // routing on path or host, checked before Signing
Protocol string // error format for gateway-made errors: json, query, rest-xml, rest-json
}
Info describes a service and how the gateway finds it.
type InitHooks ¶
type InitHooks struct {
Completed map[string]bool `json:"completed"`
Scripts []InitScript `json:"scripts"`
// contains filtered or unexported fields
}
InitHooks runs LocalStack-style init scripts and remembers their status.
type InitScript ¶
type InitScript struct {
Stage string `json:"stage"`
Name string `json:"name"`
State string `json:"state"`
Output string `json:"output,omitempty"`
}
InitScript is one executed hook.
type Inspectable ¶
Inspectable services return the full view of one resource (first column of a row).
type InvokeFromFunc ¶
InvokeFromFunc runs a function for a caller that is part of a flow: trace is passed on to the function runtime and from names the caller.
type InvokeFunc ¶
InvokeFunc runs a function synchronously (Lambda).
type Journal ¶
type Journal struct {
// contains filtered or unexported fields
}
Journal is an append-only file of newline-delimited JSON records, one per change: {"op":"put"|"del","key":…,"value":…}. A nil *Journal (memory, hybrid and persistent modes) ignores everything, so services just call it.
func OpenJournal ¶
OpenJournal replays path.old (left by an interrupted compaction), then path, through apply, and opens path for appending. A torn last line from a crash is dropped; other bad records are skipped and reported in err, and the journal is still returned.
func (*Journal) Compact ¶
Compact folds the journal into a snapshot: it moves path to path.old under the journal lock, then, without it (services call Put under their own lock), runs snapshot, which saves the service and writes its file, and finally deletes path.old. If a failed compaction left a path.old, that one is kept and path is not rotated; replaying both stays correct.
type Journaled ¶
Journaled services log each change of their high-write records to a Journal in wal mode. The hub calls SetJournal after Load, and Apply to replay a record at startup; a nil value means delete.
type Link ¶
type Link struct {
From, To string
Kind string // "configured", or "dlq" for a dead-letter redrive
Label string // what the wire is: subscription, notification, event source, target, redrive
}
Link is a wire between two resources, for the console's map: From and To are resource ids (ARNs or full resource names).
type Linker ¶
type Linker interface{ Links() []Link }
Linker services list the wires their resources are configured with.
type Message ¶
type Message struct {
Body string
Attributes map[string]MessageAttribute
Subject string
GroupID string
DedupID string
Trace string // the flow this message belongs to (Ctx.Trace of the request that caused it)
From string // resource that sent it (ARN or full resource name), for the span log and the map
Source string // EventBridge source
DetailType string // EventBridge detail-type
Resources []string // EventBridge resources
}
Message is an event handed from one service to another through the hub.
type MessageAttribute ¶
type MessageAttribute struct {
DataType string
StringValue string `json:",omitempty"`
BinaryValue []byte `json:",omitempty"`
}
MessageAttribute is an SQS/SNS-style typed attribute.
type ObjectInfo ¶
ObjectInfo is one row of the console's object browser (S3, GCS, Blob).
type Porter ¶
type Porter interface {
Port() int
}
Porter services also listen on their own port (Azure Storage on Azurite's ports).
type Problem ¶ added in v0.2.0
type Problem struct {
Time time.Time `json:"time"`
Kind string `json:"kind"` // state: saved state can't be read or written; port: a port pogi could not open
Text string `json:"text"`
}
Problem is something wrong with pogi as a whole, shown in status, the console banner and the bell.
type RPC ¶
type RPC struct {
JSONVersion string // "1.0" or "1.1"
XMLNS string // namespace for Query responses
Ops map[string]Handler // operation name → handler
// QueryCodes maps a JSON error code to its legacy Query code
// (awsQueryCompatible services such as SQS).
QueryCodes map[string]string
}
RPC serves an AWS RPC-style service over JSON 1.0/1.1 and Query, with one set of typed operations.
type RegistryImage ¶
type RegistryImage struct {
Name string // the repository below the prefix, "app/web"
Digest string
MediaType string
Tags []string
Size int64
Pushed time.Time
}
RegistryImage is one pushed image of a claimed prefix.
type RequestLog ¶
type RequestLog struct {
// contains filtered or unexported fields
}
RequestLog is a bounded, waitable log of recent calls.
func NewRequestLog ¶
func NewRequestLog(max int) *RequestLog
NewRequestLog keeps the last max entries.
func (*RequestLog) Add ¶
func (l *RequestLog) Add(e Entry) Entry
Add appends an entry and wakes waiters.
func (*RequestLog) Get ¶
func (l *RequestLog) Get(id int64) (Entry, bool)
Get returns one full entry.
func (*RequestLog) Query ¶
Query returns summaries newer than after (newest last), filtered. q matches service, op, path or error code; errorsOnly keeps status >= 400.
func (*RequestLog) Totals ¶
func (l *RequestLog) Totals() map[string]int
Totals returns request counts per service since start.
type Rule ¶
type Rule struct {
ID string `json:"id"`
Cloud string `json:"cloud,omitempty"`
Service string `json:"service,omitempty"` // glob, empty = any
Op string `json:"op,omitempty"` // glob
Region string `json:"region,omitempty"` // glob
Principal string `json:"principal,omitempty"` // glob on Ctx.Principal
Path string `json:"path,omitempty"` // glob on Ctx.Path
Probability float64 `json:"probability"` // 0..1, 0 means always
LatencyMs int `json:"latencyMs,omitempty"`
Status int `json:"status,omitempty"` // >0 injects an error
Code string `json:"code,omitempty"`
Message string `json:"message,omitempty"`
Hits int `json:"hits"`
}
Rule is a chaos rule: matching calls get latency and/or an injected error.
type Service ¶
type Service interface {
Info() Info
ServeHTTP(http.ResponseWriter, *http.Request)
}
Service is one emulated cloud service.
type ServiceStatus ¶
type ServiceStatus struct {
Name string `json:"name"`
Cloud string `json:"cloud"`
Title string `json:"title"`
Resources int `json:"resources"`
Requests int `json:"requests"`
}
ServiceStatus is one row of /_pogi/api/info.
type SnapshotInfo ¶
type SnapshotInfo struct {
Name string `json:"name"`
Size int64 `json:"size"`
Saved time.Time `json:"saved"`
}
SnapshotInfo describes a saved snapshot.
type Span ¶
type Span struct {
Trace string `json:"trace"`
Time time.Time `json:"time"`
Ms float64 `json:"ms"`
Service string `json:"service"` // the service that did the work (the target's)
Op string `json:"op"`
From string `json:"from,omitempty"` // resource ids: ARNs or full resource names
To string `json:"to,omitempty"`
Kind string `json:"kind"`
Err string `json:"err,omitempty"`
}
Span is one step of a flow that is not an HTTP request to pogi.
type SpanLog ¶
type SpanLog struct {
// contains filtered or unexported fields
}
SpanLog is a bounded log of recent spans.
type Status ¶
type Status struct {
Version string `json:"version"`
Started time.Time `json:"started"`
Uptime int64 `json:"uptime"`
Region string `json:"region"`
Persist bool `json:"persist"`
DataDir string `json:"dataDir"`
IAM string `json:"iam"`
Lambda string `json:"lambda"`
Ready bool `json:"ready"`
Services []ServiceStatus `json:"services"`
Problems []Problem `json:"problems,omitempty"` // saved state that could not be read or written, ports that could not be opened
}
Status is the payload of /_pogi/api/info.
type Table ¶
type Table struct {
Name string `json:"name"`
Columns []string `json:"columns"`
Rows [][]string `json:"rows"`
// Log marks a record of activity, such as CloudTrail events or log entries, not resources the user made.
// Status does not count its rows, so a service is not "in use" just because other calls were logged.
Log bool `json:"log,omitempty"`
// Global marks a list that spans every region, like S3's bucket list. The console's region switcher
// does not hide its rows (the account still does).
Global bool `json:"global,omitempty"`
}
Table is a generic resource listing; the first column identifies a row.