//InTransaction executes function in the db transaction and set it to the context func InTransaction(context middleware.Context, dataStore db.DB, level transaction.Type, f func() error) error { if context["transaction"] != nil { return fmt.Errorf("cannot create nested transaction") } aTransaction, err := dataStore.Begin() if err != nil { return fmt.Errorf("cannot create transaction: %v", err) } defer aTransaction.Close() err = aTransaction.SetIsolationLevel(level) if err != nil { return fmt.Errorf("error when setting isolation level '%s': %s", level, err) } context["transaction"] = aTransaction err = f() if err != nil { return err } err = aTransaction.Commit() if err != nil { return fmt.Errorf("commit error : %s", err) } delete(context, "transaction") return nil }
// DeleteResource deletes the resource specified by the schema and ID func DeleteResource(context middleware.Context, dataStore db.DB, resourceSchema *schema.Schema, resourceID string, ) error { context["id"] = resourceID environmentManager := extension.GetManager() environment, ok := environmentManager.GetEnvironment(resourceSchema.ID) if !ok { return fmt.Errorf("No environment for schema") } auth := context["auth"].(schema.Authorization) policy, err := loadPolicy(context, "delete", strings.Replace(resourceSchema.GetSingleURL(), ":id", resourceID, 1), auth) if err != nil { return err } context["policy"] = policy preTransaction, err := dataStore.Begin() if err != nil { return fmt.Errorf("cannot create transaction: %v", err) } tenantIDs := policy.GetTenantIDFilter(schema.ActionDelete, auth.TenantID()) filter := transaction.IDFilter(resourceID) if tenantIDs != nil { filter["tenant_id"] = tenantIDs } resource, fetchErr := preTransaction.Fetch(resourceSchema, filter) preTransaction.Close() if resource != nil { context["resource"] = resource.Data() } if err := extension.HandleEvent(context, environment, "pre_delete"); err != nil { return err } if fetchErr != nil { return ResourceError{err, "", NotFound} } if err := InTransaction( context, dataStore, transaction.GetIsolationLevel(resourceSchema, schema.ActionDelete), func() error { return DeleteResourceInTransaction(context, resourceSchema, resourceID) }, ); err != nil { return err } if err := extension.HandleEvent(context, environment, "post_delete"); err != nil { return err } return nil }
//InTransaction executes function in the db transaction and set it to the context func InTransaction(context middleware.Context, dataStore db.DB, f func() error) error { if context["transaction"] != nil { return fmt.Errorf("cannot create nested transaction") } aTransaction, err := dataStore.Begin() if err != nil { return fmt.Errorf("cannot create transaction: %v", err) } defer aTransaction.Close() context["transaction"] = aTransaction err = f() if err != nil { return err } err = aTransaction.Commit() if err != nil { return fmt.Errorf("commit error : %s", err) } delete(context, "transaction") return nil }
// CreateOrUpdateResource updates resource if it existed and otherwise creates it and returns true. func CreateOrUpdateResource( context middleware.Context, dataStore db.DB, identityService middleware.IdentityService, resourceSchema *schema.Schema, resourceID string, dataMap map[string]interface{}, ) (bool, error) { auth := context["auth"].(schema.Authorization) //LoadPolicy policy, err := loadPolicy(context, "update", strings.Replace(resourceSchema.GetSingleURL(), ":id", resourceID, 1), auth) if err != nil { return false, err } preTransaction, err := dataStore.Begin() if err != nil { return false, fmt.Errorf("cannot create transaction: %v", err) } tenantIDs := policy.GetTenantIDFilter(schema.ActionUpdate, auth.TenantID()) filter := transaction.IDFilter(resourceID) if tenantIDs != nil { filter["tenant_id"] = tenantIDs } _, fetchErr := preTransaction.Fetch(resourceSchema, filter) preTransaction.Close() if fetchErr != nil { dataMap["id"] = resourceID if err := CreateResource(context, dataStore, identityService, resourceSchema, dataMap); err != nil { return false, err } return true, err } return false, UpdateResource(context, dataStore, identityService, resourceSchema, resourceID, dataMap) }
Expect(server.Sync()).To(Succeed()) _, err = sync.Fetch(networkResource.Path()) Expect(err).To(HaveOccurred(), "Failed to sync db resource deletion to sync backend") }) }) Describe("Updating the state", func() { const ( statePrefix = "/state" monitoringPrefix = "/monitoring" ) var ( networkSchema *schema.Schema networkResource *schema.Resource wrappedTestDB db.DB possibleEvent gohan_sync.Event ) BeforeEach(func() { manager := schema.GetManager() var ok bool networkSchema, ok = manager.Schema("network") Expect(ok).To(BeTrue()) network := getNetwork("Red", "red") var err error networkResource, err = manager.LoadResource("network", network) Expect(err).ToNot(HaveOccurred()) wrappedTestDB = &srv.DbSyncWrapper{DB: testDB} tx, err := wrappedTestDB.Begin() defer tx.Close()
"github.com/cloudwan/gohan/schema" "github.com/cloudwan/gohan/util" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) var _ = Describe("Database operation test", func() { var ( err error ok bool conn string dbType string manager *schema.Manager networkSchema *schema.Schema serverSchema *schema.Schema networkResource1 *schema.Resource networkResource2 *schema.Resource subnetResource *schema.Resource serverResource *schema.Resource dataStore db.DB ) BeforeEach(func() { manager = schema.GetManager() Expect(manager.LoadSchemaFromFile("../etc/schema/gohan.json")).To(Succeed()) }) AfterEach(func() {
//DBBegin starts transaction func DBBegin(connection db.DB) (transaction.Transaction, error) { return connection.Begin() }