コード例 #1
0
ファイル: resource_management.go プロジェクト: cloudwan/gohan
//CreateResourceInTransaction craete db resource model in transaction
func CreateResourceInTransaction(context middleware.Context, resource *schema.Resource) error {
	resourceSchema := resource.Schema()
	mainTransaction := context["transaction"].(transaction.Transaction)
	environmentManager := extension.GetManager()
	environment, ok := environmentManager.GetEnvironment(resourceSchema.ID)
	if !ok {
		return fmt.Errorf("No environment for schema")
	}
	if err := extension.HandleEvent(context, environment, "pre_create_in_transaction"); err != nil {
		return err
	}
	if err := mainTransaction.Create(resource); err != nil {
		log.Debug("%s transaction error", err)
		return ResourceError{
			err,
			fmt.Sprintf("Failed to store data in database: %v", err),
			CreateFailed}
	}

	response := map[string]interface{}{}
	response[resourceSchema.Singular] = resource.Data()
	context["response"] = response

	if err := extension.HandleEvent(context, environment, "post_create_in_transaction"); err != nil {
		return err
	}

	return nil
}
コード例 #2
0
ファイル: sql.go プロジェクト: vozhyk-/gohan
//Create create resource in the db
func (tx *Transaction) Create(resource *schema.Resource) error {
	var cols []string
	var values []interface{}
	db := tx.db
	s := resource.Schema()
	data := resource.Data()
	q := sq.Insert(quote(s.GetDbTableName()))
	for _, attr := range s.Properties {
		//TODO(nati) support optional value
		if _, ok := data[attr.ID]; ok {
			handler := db.handler(&attr)
			cols = append(cols, quote(attr.ID))
			encoded, err := handler.encode(&attr, data[attr.ID])
			if err != nil {
				return fmt.Errorf("SQL Create encoding error: %s", err)
			}
			values = append(values, encoded)
		}
	}
	q = q.Columns(cols...).Values(values...)
	sql, args, err := q.ToSql()
	if err != nil {
		return err
	}
	return tx.Exec(sql, args...)
}
コード例 #3
0
ファイル: file.go プロジェクト: masaki-saeki/gohan
//Create create resource in the db
func (tx *Transaction) Create(resource *schema.Resource) error {
	db := tx.db
	db.load()
	s := resource.Schema()
	data := resource.Data()
	table := db.getTable(s)
	db.data[s.GetDbTableName()] = append(table, data)
	db.write()
	return nil
}
コード例 #4
0
ファイル: sql.go プロジェクト: gitter-badger/gohan
//Update update resource in the db
func (tx *Transaction) Update(resource *schema.Resource) error {
	s := resource.Schema()
	data := resource.Data()
	db := tx.db
	q := sq.Update(quote(s.GetDbTableName()))
	for _, attr := range s.Properties {
		//TODO(nati) support optional value
		if _, ok := data[attr.ID]; ok {
			handler := db.handler(&attr)
			encoded, err := handler.encode(&attr, data[attr.ID])
			if err != nil {
				return fmt.Errorf("SQL Update encoding error: %s", err)
			}
			q = q.Set(quote(attr.ID), encoded)
		}
	}
	if s.Parent != "" {
		q.Set(s.ParentSchemaPropertyID(), resource.ParentID())
	}
	q = q.Where(sq.Eq{"id": resource.ID()})
	sql, args, err := q.ToSql()
	if err != nil {
		return err
	}
	return tx.Exec(sql, args...)
}
コード例 #5
0
ファイル: sync.go プロジェクト: vozhyk-/gohan
func (tl *transactionEventLogger) logEvent(eventType string, resource *schema.Resource, version int64) error {
	schemaManager := schema.GetManager()
	eventSchema, ok := schemaManager.Schema("event")
	if !ok {
		return fmt.Errorf("event schema not found")
	}

	if resource.Schema().Metadata["nosync"] == true {
		log.Debug("skipping event logging for schema: %s", resource.Schema().ID)
		return nil
	}
	body, err := resource.JSONString()
	if err != nil {
		return fmt.Errorf("Error during event resource deserialisation: %s", err.Error())
	}
	eventResource, err := schema.NewResource(eventSchema, map[string]interface{}{
		"type":      eventType,
		"path":      resource.Path(),
		"version":   version,
		"body":      body,
		"timestamp": int64(time.Now().Unix()),
	})
	tl.eventLogged = true
	return tl.Transaction.Create(eventResource)
}
コード例 #6
0
ファイル: sql.go プロジェクト: vozhyk-/gohan
//Update update resource in the db
func (tx *Transaction) Update(resource *schema.Resource) error {
	q, err := tx.updateQuery(resource)
	if err != nil {
		return err
	}
	sql, args, err := q.ToSql()
	if err != nil {
		return err
	}
	if resource.Schema().StateVersioning() {
		sql += ", `" + configVersionColumnName + "` = `" + configVersionColumnName + "` + 1"
	}
	sql += " WHERE id = ?"
	args = append(args, resource.ID())
	return tx.Exec(sql, args...)
}
コード例 #7
0
ファイル: sql.go プロジェクト: vozhyk-/gohan
//StateUpdate update resource state
func (tx *Transaction) StateUpdate(resource *schema.Resource, state *transaction.ResourceState) error {
	q, err := tx.updateQuery(resource)
	if err != nil {
		return err
	}
	if resource.Schema().StateVersioning() && state != nil {
		q = q.Set(quote(stateVersionColumnName), state.StateVersion)
		q = q.Set(quote(stateErrorColumnName), state.Error)
		q = q.Set(quote(stateColumnName), state.State)
		q = q.Set(quote(stateMonitoringColumnName), state.Monitoring)
	}
	q = q.Where(sq.Eq{"id": resource.ID()})
	sql, args, err := q.ToSql()
	if err != nil {
		return err
	}
	return tx.Exec(sql, args...)
}
コード例 #8
0
//GetSingleResourceInTransaction get resource in single transaction
func GetSingleResourceInTransaction(context middleware.Context, resourceSchema *schema.Schema, resourceID string, tenantIDs []string) (err error) {
	mainTransaction := context["transaction"].(transaction.Transaction)
	auth := context["auth"].(schema.Authorization)
	environmentManager := extension.GetManager()
	environment, ok := environmentManager.GetEnvironment(resourceSchema.ID)
	if !ok {
		return fmt.Errorf("no environment for schema")
	}

	if err := handleEvent(context, environment, "pre_show_in_transaction"); err != nil {
		return err
	}
	if rawResponse, ok := context["response"]; ok {
		if _, ok := rawResponse.(map[string]interface{}); ok {
			return nil
		}
		return fmt.Errorf("extension returned invalid JSON: %v", rawResponse)
	}
	var object *schema.Resource
	if resourceSchema.ID == "schema" {
		manager := schema.GetManager()
		requestedSchema, _ := manager.Schema(resourceID)
		object, err = GetSchema(requestedSchema, auth)
	} else {
		object, err = mainTransaction.Fetch(resourceSchema, resourceID, tenantIDs)
	}

	if err != nil || object == nil {
		return ResourceError{err, "", NotFound}
	}

	response := map[string]interface{}{}
	response[resourceSchema.Singular] = object.Data()
	context["response"] = response

	if err := handleEvent(context, environment, "post_show_in_transaction"); err != nil {
		return err
	}
	return
}
コード例 #9
0
ファイル: sync.go プロジェクト: gitter-badger/gohan
func (server *Server) syncEvent(resource *schema.Resource) error {
	schemaManager := schema.GetManager()
	eventSchema, _ := schemaManager.Schema("event")
	tx, err := server.db.Begin()
	if err != nil {
		return err
	}
	defer tx.Close()
	eventType := resource.Get("type").(string)
	path := resource.Get("path").(string)
	body := resource.Get("body").(string)
	log.Debug("event %s", eventType)

	if eventType == "create" || eventType == "update" {
		log.Debug("set %s on sync", path)
		err = server.sync.Update(path, body)
		if err != nil {
			log.Error(fmt.Sprintf("%s on sync", err))
			return err
		}
	} else if eventType == "delete" {
		log.Debug("delete %s", path)
		err = server.sync.Delete(path)
		if err != nil {
			log.Error(fmt.Sprintf("Delete from sync failed %s", err))
			return err
		}
	}
	log.Debug("delete event %d", resource.Get("id"))
	id := resource.Get("id")
	err = tx.Delete(eventSchema, id)
	if err != nil {
		log.Error(fmt.Sprintf("delete failed: %s", err))
		return err
	}

	err = tx.Commit()
	if err != nil {
		log.Error(fmt.Sprintf("commit failed: %s", err))
		return err
	}
	return nil
}
コード例 #10
0
func (tl *transactionEventLogger) Update(resource *schema.Resource) error {
	err := tl.Transaction.Update(resource)
	if err != nil {
		return err
	}
	if !resource.Schema().StateVersioning() {
		return tl.logEvent("update", resource, 0)
	}
	state, err := tl.StateFetch(resource.Schema(), transaction.IDFilter(resource.ID()))
	if err != nil {
		return err
	}
	return tl.logEvent("update", resource, state.ConfigVersion)
}
コード例 #11
0
ファイル: file.go プロジェクト: masaki-saeki/gohan
//Update update resource in the db
func (tx *Transaction) Update(resource *schema.Resource) error {
	db := tx.db
	db.load()
	s := resource.Schema()
	data := resource.Data()
	table := db.getTable(s)
	for _, rawDataInDB := range table {
		dataInDB := rawDataInDB.(map[string]interface{})
		if dataInDB["id"] == resource.ID() {
			for key, value := range data {
				dataInDB[key] = value
			}
		}
	}
	db.write()
	return nil
}
コード例 #12
0
ファイル: sql.go プロジェクト: vozhyk-/gohan
func (tx *Transaction) updateQuery(resource *schema.Resource) (sq.UpdateBuilder, error) {
	s := resource.Schema()
	db := tx.db
	data := resource.Data()
	q := sq.Update(quote(s.GetDbTableName()))
	for _, attr := range s.Properties {
		//TODO(nati) support optional value
		if _, ok := data[attr.ID]; ok {
			handler := db.handler(&attr)
			encoded, err := handler.encode(&attr, data[attr.ID])
			if err != nil {
				return q, fmt.Errorf("SQL Update encoding error: %s", err)
			}
			q = q.Set(quote(attr.ID), encoded)
		}
	}
	if s.Parent != "" {
		q = q.Set(s.ParentSchemaPropertyID(), resource.ParentID())
	}
	return q, nil
}
コード例 #13
0
ファイル: server_test.go プロジェクト: masaki-saeki/gohan
			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()
コード例 #14
0
ファイル: sync.go プロジェクト: saeki-masaki/gohan
func (server *Server) syncEvent(resource *schema.Resource) error {
	schemaManager := schema.GetManager()
	eventSchema, _ := schemaManager.Schema("event")
	tx, err := server.db.Begin()
	if err != nil {
		return err
	}
	defer tx.Close()
	eventType := resource.Get("type").(string)
	path := resource.Get("path").(string)
	path = configPrefix + path
	body := resource.Get("body").(string)
	version, _ := resource.Get("version").(uint64)
	log.Debug("event %s", eventType)

	if eventType == "create" || eventType == "update" {
		log.Debug("set %s on sync", path)
		content, err := json.Marshal(map[string]interface{}{
			"body":    body,
			"version": version,
		})
		if err != nil {
			log.Error(fmt.Sprintf("When marshalling sync object: %s", err))
			return err
		}
		err = server.sync.Update(path, string(content))
		if err != nil {
			log.Error(fmt.Sprintf("%s on sync", err))
			return err
		}
	} else if eventType == "delete" {
		log.Debug("delete %s", path)
		err = server.sync.Delete(path)
		if err != nil {
			log.Error(fmt.Sprintf("Delete from sync failed %s", err))
			return err
		}
	}
	log.Debug("delete event %d", resource.Get("id"))
	id := resource.Get("id")
	err = tx.Delete(eventSchema, id)
	if err != nil {
		log.Error(fmt.Sprintf("delete failed: %s", err))
		return err
	}

	err = tx.Commit()
	if err != nil {
		log.Error(fmt.Sprintf("commit failed: %s", err))
		return err
	}
	return nil
}
コード例 #15
0
ファイル: db_test.go プロジェクト: vozhyk-/gohan
	"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() {
コード例 #16
0
ファイル: sync.go プロジェクト: vozhyk-/gohan
func (server *Server) syncEvent(resource *schema.Resource) error {
	schemaManager := schema.GetManager()
	eventSchema, _ := schemaManager.Schema("event")
	tx, err := server.db.Begin()
	if err != nil {
		return err
	}
	defer tx.Close()
	eventType := resource.Get("type").(string)
	resourcePath := resource.Get("path").(string)
	body := resource.Get("body").(string)

	path := generatePath(resourcePath, body)

	version, ok := resource.Get("version").(int)
	if !ok {
		log.Debug("cannot cast version value in int for %s", path)
	}
	log.Debug("event %s", eventType)

	if eventType == "create" || eventType == "update" {
		log.Debug("set %s on sync", path)
		content, err := json.Marshal(map[string]interface{}{
			"body":    body,
			"version": version,
		})
		if err != nil {
			log.Error(fmt.Sprintf("When marshalling sync object: %s", err))
			return err
		}
		err = server.sync.Update(path, string(content))
		if err != nil {
			log.Error(fmt.Sprintf("%s on sync", err))
			return err
		}
	} else if eventType == "delete" {
		log.Debug("delete %s", resourcePath)
		deletePath := resourcePath
		resourceSchema := schema.GetSchemaByURLPath(resourcePath)
		if _, ok := resourceSchema.SyncKeyTemplate(); ok {
			var data map[string]interface{}
			err := json.Unmarshal(([]byte)(body), &data)
			deletePath, err = resourceSchema.GenerateCustomPath(data)
			if err != nil {
				log.Error(fmt.Sprintf("Delete from sync failed %s - generating of custom path failed", err))
				return err
			}
		}
		log.Debug("deleting %s", statePrefix+deletePath)
		err = server.sync.Delete(statePrefix + deletePath)
		if err != nil {
			log.Error(fmt.Sprintf("Delete from sync failed %s", err))
		}
		log.Debug("deleting %s", monitoringPrefix+deletePath)
		err = server.sync.Delete(monitoringPrefix + deletePath)
		if err != nil {
			log.Error(fmt.Sprintf("Delete from sync failed %s", err))
		}
		log.Debug("deleting %s", resourcePath)
		err = server.sync.Delete(path)
		if err != nil {
			log.Error(fmt.Sprintf("Delete from sync failed %s", err))
			return err
		}
	}
	log.Debug("delete event %d", resource.Get("id"))
	id := resource.Get("id")
	err = tx.Delete(eventSchema, id)
	if err != nil {
		log.Error(fmt.Sprintf("delete failed: %s", err))
		return err
	}

	err = tx.Commit()
	if err != nil {
		log.Error(fmt.Sprintf("commit failed: %s", err))
		return err
	}
	return nil
}
コード例 #17
0
ファイル: db_test.go プロジェクト: gitter-badger/gohan
func makePluralKey(resource *schema.Resource) string {
	s := resource.Schema()
	key := s.Prefix + "/" + s.Plural
	return key
}
コード例 #18
0
ファイル: sync.go プロジェクト: cloudwan/gohan
func (server *Server) syncEvent(resource *schema.Resource) error {
	schemaManager := schema.GetManager()
	eventSchema, _ := schemaManager.Schema("event")
	tx, err := server.db.Begin()
	if err != nil {
		return err
	}
	defer tx.Close()
	eventType := resource.Get("type").(string)
	resourcePath := resource.Get("path").(string)
	body := resource.Get("body").(string)
	syncPlain := resource.Get("sync_plain").(bool)
	syncProperty := resource.Get("sync_property").(string)

	path := generatePath(resourcePath, body)

	version, ok := resource.Get("version").(int)
	if !ok {
		log.Debug("cannot cast version value in int for %s", path)
	}
	log.Debug("event %s", eventType)

	if eventType == "create" || eventType == "update" {
		log.Debug("set %s on sync", path)

		content := body

		var data map[string]interface{}
		if syncProperty != "" {
			err = json.Unmarshal(([]byte)(body), &data)
			if err != nil {
				log.Error(fmt.Sprintf("failed to unmarshal body on sync: %s", err))
				return err
			}
			target, ok := data[syncProperty]
			if !ok {
				return fmt.Errorf("could not find property `%s`", syncProperty)
			}
			jsonData, err := json.Marshal(target)
			if err != nil {
				return err
			}
			content = string(jsonData)
		}

		if syncPlain {
			var target interface{}
			json.Unmarshal([]byte(content), &target)
			switch target.(type) {
			case string:
				content = fmt.Sprintf("%v", target)
			}
		} else {
			data, err := json.Marshal(map[string]interface{}{
				"body":    content,
				"version": version,
			})
			if err != nil {
				log.Error(fmt.Sprintf("When marshalling sync object: %s", err))
				return err
			}
			content = string(data)
		}

		err = server.sync.Update(path, content)
		if err != nil {
			log.Error(fmt.Sprintf("%s on sync", err))
			return err
		}
	} else if eventType == "delete" {
		log.Debug("delete %s", resourcePath)
		deletePath := resourcePath
		resourceSchema := schema.GetSchemaByURLPath(resourcePath)
		if _, ok := resourceSchema.SyncKeyTemplate(); ok {
			var data map[string]interface{}
			json.Unmarshal(([]byte)(body), &data)
			deletePath, err = resourceSchema.GenerateCustomPath(data)
			if err != nil {
				log.Error(fmt.Sprintf("Delete from sync failed %s - generating of custom path failed", err))
				return err
			}
		}
		log.Debug("deleting %s", statePrefix+deletePath)
		err = server.sync.Delete(statePrefix + deletePath)
		if err != nil {
			log.Error(fmt.Sprintf("Delete from sync failed %s", err))
		}
		log.Debug("deleting %s", monitoringPrefix+deletePath)
		err = server.sync.Delete(monitoringPrefix + deletePath)
		if err != nil {
			log.Error(fmt.Sprintf("Delete from sync failed %s", err))
		}
		log.Debug("deleting %s", resourcePath)
		err = server.sync.Delete(path)
		if err != nil {
			log.Error(fmt.Sprintf("Delete from sync failed %s", err))
			return err
		}
	}
	log.Debug("delete event %d", resource.Get("id"))
	id := resource.Get("id")
	err = tx.Delete(eventSchema, id)
	if err != nil {
		log.Error(fmt.Sprintf("delete failed: %s", err))
		return err
	}

	err = tx.Commit()
	if err != nil {
		log.Error(fmt.Sprintf("commit failed: %s", err))
		return err
	}
	return nil
}