func TestQueryBindingIterationError(t *testing.T) { ctx := context.Background() store := storage.New(storage.InMemoryConfig()) mock := &queryBindingErrStore{} if err := store.Mount(mock, storage.MustParsePath("/foo/bar")); err != nil { panic(err) } server, err := New(ctx, store, ":8182", false) if err != nil { panic(err) } recorder := httptest.NewRecorder() f := &fixture{ server: server, recorder: recorder, t: t, } get := newReqV1("GET", `/query?q=a=data.foo.bar`, "") f.server.Handler.ServeHTTP(f.recorder, get) if f.recorder.Code != 500 { t.Fatalf("Expected 500 error due to unknown storage error but got: %v", f.recorder) } }
func setupNodes(ctx context.Context, store *storage.Storage, txn storage.Transaction, n int) { tmpl, err := template.New("node").Parse(nodeTemplate) if err != nil { panic(err) } if err := store.Write(ctx, txn, storage.AddOp, storage.MustParsePath("/nodes"), map[string]interface{}{}); err != nil { panic(err) } for i := 0; i < n; i++ { input := nodeTemplateInput{ Name: fmt.Sprintf("node%v", i), } v := runTemplate(tmpl, input) path := storage.MustParsePath(fmt.Sprintf("/nodes/%v", input.Name)) if err := store.Write(ctx, txn, storage.AddOp, path, v); err != nil { panic(err) } } }
func ExampleStorage_Write() { // 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 DataStore with the dummy data. store := storage.New(storage.InMemoryWithJSONConfig(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) if err != nil { // Handle error. } defer store.Close(ctx, txn) // 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. // Output: // err0: <nil> // v1: -62.338889 // err1: <nil> // err2: storage error (code: 1): bad path: /users/1/color, document does not exist }
func TestInit(t *testing.T) { ctx := context.Background() tmp1, err := ioutil.TempFile("", "docFile") if err != nil { panic(err) } defer os.Remove(tmp1.Name()) doc1 := `{"foo": "bar", "x": {"y": {"z": [1]}}}` if _, err := tmp1.Write([]byte(doc1)); err != nil { panic(err) } if err := tmp1.Close(); err != nil { panic(err) } tmp2, err := ioutil.TempFile("", "policyFile") if err != nil { panic(err) } defer os.Remove(tmp2.Name()) mod1 := ` package a.b.c import data.foo p = true :- foo = "bar" p = true :- 1 = 2 ` if _, err := tmp2.Write([]byte(mod1)); err != nil { panic(err) } if err := tmp2.Close(); err != nil { panic(err) } tmp3, err := ioutil.TempDir("", "policyDir") if err != nil { panic(err) } defer os.RemoveAll(tmp3) tmp4 := filepath.Join(tmp3, "existingPolicy") err = ioutil.WriteFile(tmp4, []byte(` package a.b.c q = true :- false `), 0644) if err != nil { panic(err) } rt := Runtime{} err = rt.init(ctx, &Params{ Paths: []string{tmp1.Name(), tmp2.Name()}, PolicyDir: tmp3, }) if err != nil { t.Errorf("Unexpected error: %v", err) return } txn := storage.NewTransactionOrDie(ctx, rt.Store) node, err := rt.Store.Read(ctx, txn, storage.MustParsePath("/foo")) if util.Compare(node, "bar") != 0 || err != nil { t.Errorf("Expected %v but got %v (err: %v)", "bar", node, err) return } modules := rt.Store.ListPolicies(txn) expected := ast.MustParseModule(mod1) if !expected.Equal(modules[tmp2.Name()]) { t.Fatalf("Expected %v but got: %v", expected, modules[tmp2.Name()]) } }
func ExampleStorage_Read() { // 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 := storage.New(storage.InMemoryWithJSONConfig(data)) txn, err := store.NewTransaction(ctx) if err != nil { // Handle error. } defer store.Close(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 error (code: 1): bad path: /users/0/age, document does not exist // err2 is not found: true }