Documentation ¶
Overview ¶
Package inmem implements an in-memory version of the policy engine's storage layer.
The in-memory store is used as the default storage layer implementation. The in-memory store supports multi-reader/single-writer concurrency with rollback.
Callers should assume the in-memory store does not make copies of written data. Once data is written to the in-memory store, it should not be modified (outside of calling Store.Write). Furthermore, data read from the in-memory store should be treated as read-only.
Example (Read) ¶
package main import ( "bytes" "context" "encoding/json" "fmt" "github.com/open-policy-agent/opa/storage" "github.com/open-policy-agent/opa/storage/inmem" ) func main() { // Initialize context for the example. Normally the caller would obtain the // context from an input parameter or instantiate their own. ctx := context.Background() // Define some dummy data to initialize the built-in store with. exampleInput := ` { "users": [ { "name": "alice", "color": "red", "likes": ["clouds", "ships"] }, { "name": "burt", "likes": ["cheese", "wine"] } ] } ` var data map[string]interface{} // OPA uses Go's standard JSON library but assumes that numbers have been // decoded as json.Number instead of float64. You MUST decode with UseNumber // enabled. decoder := json.NewDecoder(bytes.NewBufferString(exampleInput)) decoder.UseNumber() if err := decoder.Decode(&data); err != nil { // Handle error. } // Instantiate the storage layer. store := inmem.NewFromObject(data) txn, err := store.NewTransaction(ctx) if err != nil { // Handle error. } // Cancel transaction because no writes are performed. defer store.Abort(ctx, txn) // Read values out of storage. v1, err1 := store.Read(ctx, txn, storage.MustParsePath("/users/1/likes/1")) v2, err2 := store.Read(ctx, txn, storage.MustParsePath("/users/0/age")) // Inspect the return values. fmt.Println("v1:", v1) fmt.Println("err1:", err1) fmt.Println("v2:", v2) fmt.Println("err2:", err2) fmt.Println("err2 is not found:", storage.IsNotFound(err2)) }
Output: v1: wine err1: <nil> v2: <nil> err2: storage_not_found_error: /users/0/age: document does not exist err2 is not found: true
Example (Write) ¶
package main import ( "bytes" "context" "encoding/json" "fmt" "github.com/open-policy-agent/opa/storage" "github.com/open-policy-agent/opa/storage/inmem" ) func main() { // Initialize context for the example. Normally the caller would obtain the // context from an input parameter or instantiate their own. ctx := context.Background() // Define some dummy data to initialize the DataStore with. exampleInput := ` { "users": [ { "name": "alice", "color": "red", "likes": ["clouds", "ships"] }, { "name": "burt", "likes": ["cheese", "wine"] } ] } ` var data map[string]interface{} // OPA uses Go's standard JSON library but assumes that numbers have been // decoded as json.Number instead of float64. You MUST decode with UseNumber // enabled. decoder := json.NewDecoder(bytes.NewBufferString(exampleInput)) decoder.UseNumber() if err := decoder.Decode(&data); err != nil { // Handle error. } // Create the new store with the dummy data. store := inmem.NewFromObject(data) // Define dummy data to add to the DataStore. examplePatch := `{ "longitude": 82.501389, "latitude": -62.338889 }` var patch interface{} // See comment above regarding decoder usage. decoder = json.NewDecoder(bytes.NewBufferString(examplePatch)) decoder.UseNumber() if err := decoder.Decode(&patch); err != nil { // Handle error. } txn, err := store.NewTransaction(ctx, storage.WriteParams) if err != nil { // Handle error. } // Write values into storage and read result. err0 := store.Write(ctx, txn, storage.AddOp, storage.MustParsePath("/users/0/location"), patch) v1, err1 := store.Read(ctx, txn, storage.MustParsePath("/users/0/location/latitude")) err2 := store.Write(ctx, txn, storage.ReplaceOp, storage.MustParsePath("/users/1/color"), "red") // Inspect the return values. fmt.Println("err0:", err0) fmt.Println("v1:", v1) fmt.Println("err1:", err1) fmt.Println("err2:", err2) // Rollback transaction because write failed. store.Abort(ctx, txn) }
Output: err0: <nil> v1: -62.338889 err1: <nil> err2: storage_not_found_error: /users/1/color: document does not exist
Index ¶
- func New() storage.Store
- func NewFromObject(data map[string]interface{}) storage.Store
- func NewFromObjectWithOpts(data map[string]interface{}, opts ...Opt) storage.Store
- func NewFromReader(r io.Reader) storage.Store
- func NewFromReaderWithOpts(r io.Reader, opts ...Opt) storage.Store
- func NewWithOpts(opts ...Opt) storage.Store
- type Opt
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func NewFromObject ¶
NewFromObject returns a new in-memory store from the supplied data object.
func NewFromObjectWithOpts ¶ added in v0.44.0
NewFromObject returns a new in-memory store from the supplied data object, with the options passed.
func NewFromReader ¶
NewFromReader returns a new in-memory store from a reader that produces a JSON serialized object. This function is for test purposes.
func NewFromReaderWithOpts ¶ added in v0.44.0
NewFromReader returns a new in-memory store from a reader that produces a JSON serialized object, with extra options. This function is for test purposes.
func NewWithOpts ¶ added in v0.44.0
NewWithOpts returns an empty in-memory store, with extra options passed.
Types ¶
type Opt ¶ added in v0.44.0
type Opt func(*store)
An Opt modifies store at instantiation.
func OptRoundTripOnWrite ¶ added in v0.44.0
OptRoundTripOnWrite sets whether incoming objects written to store are round-tripped through JSON to ensure they are serializable to JSON.
Callers should disable this if they can guarantee all objects passed to Write() are serializable to JSON. Failing to do so may result in undefined behavior, including panics.
Usually, when only storing objects in the inmem store that have been read via encoding/json, this is safe to disable, and comes with an improvement in performance and memory use.
If setting to false, callers should deep-copy any objects passed to Write() unless they can guarantee the objects will not be mutated after being written, and that mutations happening to the objects after they have been passed into Write() don't affect their logic.