Documentation
¶
Overview ¶
Package analysis answers "which flows and hooks break if this API changes?" (design §9). For each request version it finds the consumers (flow request nodes, post-hooks, and the version's own extract and assert), what each one reads from the response and which inputs it fills, and checks those reads against the best contract available: pinned examples, else the last saved response.
The package does no logging and reads files only through Contracts.
Index ¶
Constants ¶
const ( SourceSchema = "schema" // OpenAPI response schemas kept at import SourceExample = "example" // pinned examples SourceResponse = "response" // the last saved response )
Contract sources, best first (design §9).
const ( ReadBody = "body" // a body path from a template, e.g. nodes.login.body.data.token ReadJSONPath = "jsonpath" // an extraction's JSONPath ReadHeader = "header" ReadCookie = "cookie" ReadRegex = "regex" // an extraction's regex over the body text ReadExtract = "extract" // an extract name the version does not define ReadInput = "input" // an input the request needs and the node does not fill )
Read kinds: what part of the response (or which input) a read relies on.
const ( KindNode = "node" // a request node in a flow or an inline hook step KindHook = "hook" // a post-hook step of the request KindRequest = "request" // the version's own extract and assert )
Consumer kinds.
Variables ¶
var ( ErrUnknownRequest = errors.New("unknown request") ErrUnknownVersion = errors.New("unknown version") )
Errors for Impact's target.
Functions ¶
Types ¶
type Consumer ¶
type Consumer struct {
Kind string `json:"kind"`
Collection string `json:"collection"` // where the consumer is declared
CollectionID model.ID `json:"collection_id"` //
File string `json:"file"` // the flow, hook flow or request file
Flow string `json:"flow,omitempty"`
Node string `json:"node,omitempty"`
Hook string `json:"hook,omitempty"` // e.g. "post · request auth/login · inline #0"
Version string `json:"version"`
Fills []string `json:"fills,omitempty"` // the node's with keys
Reads []Read `json:"reads,omitempty"`
Status Status `json:"status"`
}
Consumer is one user of a request version and everything it relies on.
type Contract ¶
Contract is what a request version is known to return. Source is empty when nothing is known.
type ContractInfo ¶
type ContractInfo struct {
Source string `json:"source"` // SourceExample, SourceResponse, or empty when nothing is known
Files []string `json:"files,omitempty"`
}
ContractInfo says what a version's consumers were checked against.
type Contracts ¶
type Contracts interface {
Contract(c model.Collection, r model.Request, version string) (Contract, diag.List)
}
Contracts finds the contract of one request version.
type DataLink ¶
DataLink says that node To reads a value node From made: either its output (`{{nodes.login.token}}`, Via "login.token") or a variable From wrote (`{{vars.token}}`, Via "token"). Links are for drawing and explaining a flow; they do not change how it runs.
func DataLinks ¶
DataLinks lists the values the nodes of f pass to each other, in the order the readers appear. A variable counts as made by the last node before the reader that writes it, except a `generate` node: its values are fresh, not taken from another step. A node reading its own output is not a link.
type FileContracts ¶
FileContracts reads response schemas (<request>.schemas/<version>- <status>.json, written by OpenAPI import), pinned examples (<request>.examples/*.json, next to the request file) and saved responses (<data>/responses/<request-id>/ <version>/last.json). DataDir maps a collection id to its data dir.
type Read ¶
type Read struct {
Kind string `json:"kind"`
Expr string `json:"expr"` // as written: nodes.login.token, response.body.id, extract token, with.tenant
Target string `json:"target"` // what is checked: $.data.token, a header, cookie or input name
Via string `json:"via,omitempty"` // the extract name a node read goes through
Reader string `json:"reader,omitempty"` // the node whose template reads it; empty for flow-level templates
File string `json:"file"`
Path string `json:"path"` // YAML path of the reading template
Status Status `json:"status"`
Reason string `json:"reason,omitempty"`
// contains filtered or unexported fields
}
Read is one thing a consumer relies on.
type Report ¶
type Report struct {
Collection string `json:"collection"`
CollectionID model.ID `json:"collection_id"`
Request string `json:"request"` // path, e.g. auth/login
RequestID model.ID `json:"request_id"`
Versions []VersionUsage `json:"versions"`
Status Status `json:"status"` // the worst version's
}
Report is the impact of one request: its versions and their consumers.
func Analyze ¶
Analyze reports every request version that has consumers, for validate's contract warnings.
func Impact ¶
func Impact(cs []model.Collection, t Target, version string, src Contracts) (Report, diag.List, error)
Impact reports who uses request t, across every collection in cs, and whether they still fit its contract. version limits the report to one version; empty means all of them. diags are contract-source problems.
type Sample ¶
type Sample struct {
Source string // SourceExample or SourceResponse
File string // the example or saved-response file
Status int // HTTP status
Headers http.Header // response headers
HeadersKnown bool // false when an example lists no headers: header reads cannot be judged
Body any // the JSON body, or nil when the body is not JSON
Text string // the body text, when it is not JSON
Schema any // for SourceSchema: the response's JSON Schema
}
Sample is one response a contract is made of.
type Status ¶
type Status string
Status is how a consumer fares against a contract. Ranked Compatible < Unknown < Broken.
type VersionUsage ¶
type VersionUsage struct {
Version string `json:"version"`
Contract ContractInfo `json:"contract"`
Consumers []Consumer `json:"consumers"`
Status Status `json:"status"` // the worst consumer's
}
VersionUsage is every consumer of one request version.