Пример #1
0
func cloneConfigsFromApp(from, to, aux_info, userKey string) (*models.App, []*models.Config, error) {
	memConfMux.RLock()
	fromApp := memConfAppsByName[from]
	memConfMux.RUnlock()

	fromConfigs, err := models.GetConfigsByAppKey(nil, fromApp.Key)
	if err != nil {
		return nil, nil, err
	}

	app := &models.App{
		Key:        utils.GenerateKey(),
		Name:       to,
		UserKey:    userKey,
		AuxInfo:    aux_info,
		CreatedUTC: utils.GetNowSecond(),
		Type:       fromApp.Type,
	}

	for _, config := range fromConfigs {
		config.Key = utils.GenerateKey()
		config.CreatorKey = app.UserKey
		config.AppKey = app.Key
		config.CreatedUTC = app.CreatedUTC
	}

	if err := cloneConfigs(app, fromConfigs, userKey); err != nil {
		return nil, nil, err
	}

	return app, fromConfigs, nil
}
Пример #2
0
func initOneConfig(userName, appName, appType, configK, configV, configVType string) (*models.User, *models.App, *models.Config, error) {
	user, err := updateUser(&models.User{
		Name: userName,
		Key:  utils.GenerateKey()}, nil)
	if err != nil {
		return nil, nil, nil, err
	}

	app, err := updateApp(&models.App{
		Key:     utils.GenerateKey(),
		UserKey: user.Key,
		Name:    appName,
		Type:    appType}, nil, nil)
	if err != nil {
		return nil, nil, nil, err
	}

	config, err := updateConfig(&models.Config{
		Key:    utils.GenerateKey(),
		AppKey: app.Key,
		K:      configK,
		V:      configV,
		VType:  configVType,
		Status: models.CONF_STATUS_ACTIVE}, "", nil, nil)

	return user, app, config, err
}
Пример #3
0
func TestUpdateApp(t *testing.T) {
	err := _clearModelData()
	assert.True(t, err == nil, "must correctly clear data")
	loadAllData()
	initNodeData()

	confWriteMux.Lock()
	defer confWriteMux.Unlock()

	user, err := updateUser(&models.User{
		Name: "rahuahua",
		Key:  utils.GenerateKey()}, nil)
	app, err := updateApp(&models.App{
		Key:     utils.GenerateKey(),
		UserKey: user.Key,
		Name:    "iconfreecn",
		Type:    models.APP_TYPE_REAL}, nil, nil)

	app, err = updateApp(&models.App{
		Key:     app.Key,
		UserKey: user.Key,
		Name:    "hdfreecn",
		Type:    models.APP_TYPE_REAL,
		AuxInfo: "guaji"}, nil, nil)
	assert.True(t, err == nil, "must correctly add new app")
	assert.True(t, len(memConfApps) == 1, "must only one app")
	assert.True(t, memConfAppsByName["iconfreecn"] == nil, "old-name app must not exist")
	assert.True(t, memConfAppsByName["hdfreecn"].AuxInfo == "guaji", "aux_info must be updated")

	_clearModelData()
}
Пример #4
0
func TestSearchApps(t *testing.T) {
	user, err := updateUser(&models.User{
		Name: "rahuahua",
		Key:  utils.GenerateKey()}, nil)

	_, err = updateApp(&models.App{
		Key:     utils.GenerateKey(),
		UserKey: user.Key,
		Name:    "iconfreecn",
		Type:    models.APP_TYPE_REAL}, nil, nil)
	assert.True(t, err == nil, "must correctly add new app")

	_, err = updateApp(&models.App{
		Key:     utils.GenerateKey(),
		UserKey: user.Key,
		Name:    "xianyouvideo",
		Type:    models.APP_TYPE_REAL}, nil, nil)
	assert.True(t, err == nil, "must correctly add new app")

	_, err = updateApp(&models.App{
		Key:     utils.GenerateKey(),
		UserKey: user.Key,
		Name:    "hdfreecn",
		Type:    models.APP_TYPE_REAL}, nil, nil)
	assert.True(t, err == nil, "must correctly add new app")

	_, err = updateApp(&models.App{
		Key:     utils.GenerateKey(),
		UserKey: user.Key,
		Name:    "phoneplay",
		Type:    models.APP_TYPE_REAL}, nil, nil)
	assert.True(t, err == nil, "must correctly add new app")

	apps, err := searchApps("free", 0)
	assert.True(t, err == nil)
	assert.True(t, len(apps) == 2)

	apps, err = searchApps("video", 0)
	assert.True(t, err == nil)
	assert.True(t, len(apps) == 1)

	apps, err = searchApps("phoneplay", 0)
	assert.True(t, err == nil)
	assert.True(t, len(apps) == 1)

	apps, err = searchApps("non-exist", 0)
	assert.True(t, err == nil)
	assert.True(t, len(apps) == 0)
}
Пример #5
0
func InitUser(c *gin.Context) {
	confWriteMux.Lock()
	defer confWriteMux.Unlock()

	if len(memConfUsers) > 0 {
		Error(c, BAD_REQUEST, "users already exists")
		return
	}

	data := &newUserData{}
	if err := c.BindJSON(data); err != nil {
		Error(c, BAD_POST_DATA, err.Error())
		return
	}

	if err := verifyNewUserData(data); err != nil {
		Error(c, BAD_REQUEST, err.Error())
		return
	}

	key := utils.GenerateKey()
	user, err := newUserWithNewUserData(data, key, key)
	if err != nil {
		Error(c, SERVER_ERROR, err.Error())
		return
	}

	failedNodes := syncData2SlaveIfNeed(user, key)
	setUserKeyCookie(c, user.Key, user.PassCode)
	if len(failedNodes) > 0 {
		Success(c, map[string]interface{}{"failed_nodes": failedNodes})
	} else {
		Success(c, nil)
	}
}
Пример #6
0
func genNewDataVersion(old *models.DataVersion) *models.DataVersion {
	return &models.DataVersion{
		Version: old.Version + 1,
		Sign:    utils.GenerateKey(),
		OldSign: old.Sign,
	}
}
Пример #7
0
func NewUser(c *gin.Context) {
	confWriteMux.Lock()
	defer confWriteMux.Unlock()

	data := &newUserData{}
	if err := c.BindJSON(data); err != nil {
		Error(c, BAD_POST_DATA, err.Error())
		return
	}

	if err := verifyNewUserData(data); err != nil {
		Error(c, BAD_REQUEST, err.Error())
		return
	}

	user, err := newUserWithNewUserData(data, utils.GenerateKey(), getOpUserKey(c))
	if err != nil {
		Error(c, SERVER_ERROR, err.Error())
		return
	}

	failedNodes := syncData2SlaveIfNeed(user, getOpUserKey(c))
	if len(failedNodes) > 0 {
		Success(c, map[string]interface{}{"failed_nodes": failedNodes})
	} else {
		Success(c, nil)
	}
}
Пример #8
0
func TestUpdateUser(t *testing.T) {
	err := _clearModelData()
	assert.True(t, err == nil, "must correctly clear data")
	loadAllData()
	initNodeData()

	confWriteMux.Lock()
	defer confWriteMux.Unlock()

	node1 := memConfNodes[conf.ClientAddr]
	userData := &newUserData{
		Name:     "rahuahua",
		PassCode: "huahua",
	}
	user, err := newUserWithNewUserData(userData, "1234567", "1234567")
	assert.True(t, err == nil, "must correctly add new user")

	node2 := memConfNodes[conf.ClientAddr]
	assert.True(t, node2.DataVersion.Sign != node1.DataVersion.Sign)
	assert.True(t, node2.DataVersion.OldSign == node1.DataVersion.Sign)
	assert.True(t, node2.DataVersion.Version == node1.DataVersion.Version+1)

	userData = &newUserData{
		Name:     "rahuahua2",
		PassCode: "huahua",
	}
	newUser, err := newUserWithNewUserData(userData, utils.GenerateKey(), user.Key)
	assert.True(t, err == nil, "must correctly add new user")
	assert.True(t, newUser.CreatorKey == user.Key && newUser.CreatedUTC >= user.CreatedUTC)

	node3 := memConfNodes[conf.ClientAddr]
	assert.True(t, node3.DataVersion.Sign != node2.DataVersion.Sign)
	assert.True(t, node3.DataVersion.OldSign == node2.DataVersion.Sign)
	assert.True(t, node3.DataVersion.Version == node2.DataVersion.Version+1)
	assert.True(t, node3.DataVersion.Version == node1.DataVersion.Version+2)

	updateData := &updateUserData{
		Name:    "rahuahua333",
		AuxInfo: "1234",
	}

	assert.True(t, verifyUpdateUserData(updateData, user.Key) == nil)

	oldUser := *user
	user, err = updateUserWithUpdateData(updateData, user.Key)
	assert.True(t, err == nil)
	assert.True(t, user.Key == oldUser.Key)
	assert.True(t, user.Name == "rahuahua333")

	badData := &updateUserData{
		Name: "rahuahua2",
	}
	assert.True(t, verifyUpdateUserData(badData, user.Key) != nil)
	badData.Name = "12"
	assert.True(t, verifyUpdateUserData(badData, user.Key) != nil)

	_clearModelData()
}
Пример #9
0
func TestNewApp(t *testing.T) {
	err := _clearModelData()
	assert.True(t, err == nil, "must correctly clear data")
	loadAllData()
	initNodeData()

	confWriteMux.Lock()
	defer confWriteMux.Unlock()

	user, err := updateUser(&models.User{
		Name: "rahuahua",
		Key:  utils.GenerateKey()}, nil)

	node1 := memConfNodes[conf.ClientAddr]

	app, err := updateApp(&models.App{
		Key:     utils.GenerateKey(),
		UserKey: user.Key,
		Name:    "iconfreecn",
		Type:    models.APP_TYPE_REAL}, nil, nil)
	assert.True(t, err == nil, "must correctly add new app")
	assert.True(t, len(memConfApps) == 1, "must only one app")
	assert.True(t, app.Key == memConfAppsByName["iconfreecn"].Key, "must the same app")

	node2 := memConfNodes[conf.ClientAddr]
	assert.True(t, node2.DataVersion.Sign != node1.DataVersion.Sign)
	assert.True(t, node2.DataVersion.OldSign == node1.DataVersion.Sign)
	assert.True(t, node2.DataVersion.Version == node1.DataVersion.Version+1)

	_, err = updateApp(&models.App{
		Key:     utils.GenerateKey(),
		UserKey: user.Key,
		Name:    "hdfreecn",
		Type:    models.APP_TYPE_REAL}, nil, nil)
	assert.True(t, err == nil, "must correctly add new app")
	assert.True(t, len(memConfApps) == 2, "must two apps")

	node3 := memConfNodes[conf.ClientAddr]
	assert.True(t, node3.DataVersion.Sign != node2.DataVersion.Sign)
	assert.True(t, node3.DataVersion.OldSign == node2.DataVersion.Sign)
	assert.True(t, node3.DataVersion.Version == node2.DataVersion.Version+1)
	assert.True(t, node3.DataVersion.Version == node1.DataVersion.Version+2)

	_clearModelData()
}
Пример #10
0
func TestDataVersion(t *testing.T) {
	err := _clearModelData()
	assert.True(t, err == nil, "must correctly clear data")
	loadAllData()
	initNodeData()

	assert.True(t, memConfDataVersion.Version == 0, "init data version must be 0")

	oldVersion := *memConfDataVersion
	user, err := updateUser(&models.User{
		Name: "rahuahua",
		Key:  utils.GenerateKey()}, nil)
	assert.True(t, memConfDataVersion.Version == 1, "data version must be 1")
	assert.True(t, memConfDataVersion.OldSign == oldVersion.Sign)
	assert.True(t, memConfDataVersion.Sign != oldVersion.Sign)

	oldVersion = *memConfDataVersion
	app, _ := updateApp(&models.App{
		Key:     utils.GenerateKey(),
		UserKey: user.Key,
		Name:    "iconfreecn",
		Type:    models.APP_TYPE_REAL}, nil, nil)
	assert.True(t, memConfDataVersion.Version == 2, "data version must be 2")
	assert.True(t, memConfDataVersion.OldSign == oldVersion.Sign)
	assert.True(t, memConfDataVersion.Sign != oldVersion.Sign)

	oldVersion = *memConfDataVersion
	updateConfig(&models.Config{
		Key:    utils.GenerateKey(),
		AppKey: app.Key,
		K:      "int_conf",
		V:      "1",
		VType:  models.CONF_V_TYPE_INT,
		Status: models.CONF_STATUS_ACTIVE}, "", nil, nil)
	assert.True(t, memConfDataVersion.Version == 3, "data version must be 3")
	assert.True(t, memConfDataVersion.OldSign == oldVersion.Sign)
	assert.True(t, memConfDataVersion.Sign != oldVersion.Sign)

	_clearModelData()
}
Пример #11
0
func NewWebHook(c *gin.Context) {
	confWriteMux.Lock()
	defer confWriteMux.Unlock()

	var data struct {
		AppKey string `json:"app_key"`
		Scope  int    `json:"scope"`
		Target string `json:"target" binding:"required"`
		URL    string `json:"url" binding:"required"`
		Status int    `json:"status"`
	}
	if err := c.BindJSON(&data); err != nil {
		Error(c, BAD_POST_DATA, err.Error())
		return
	}

	if data.Scope != models.WEBHOOK_SCOPE_GLOBAL && data.Scope != models.WEBHOOK_SCOPE_APP {
		Error(c, BAD_REQUEST, "unknown webHook scope: "+string(data.Scope))
		return
	}

	if data.Target != models.WEBHOOK_TARGET_PUBU && data.Target != models.WEBHOOK_TARGET_SLACK {
		Error(c, BAD_REQUEST, "unsupported webHook target: "+data.Target)
		return
	}

	if data.Scope == models.WEBHOOK_SCOPE_APP && memConfApps[data.AppKey] == nil {
		Error(c, BAD_REQUEST, "app key not exists: "+data.AppKey)
		return
	}

	webHook := &models.WebHook{
		Key:    utils.GenerateKey(),
		AppKey: data.AppKey,
		Scope:  data.Scope,
		Target: data.Target,
		URL:    data.URL,
		Status: data.Status,
	}
	if _, err := updateWebHook(webHook, nil); err != nil {
		Error(c, SERVER_ERROR, err.Error())
		return
	}

	failedNodes := syncData2SlaveIfNeed(webHook, getOpUserKey(c))
	if len(failedNodes) > 0 {
		Success(c, map[string]interface{}{"failed_nodes": failedNodes})
	} else {
		Success(c, nil)
	}
}
Пример #12
0
func newConfigWithNewConfigData(data *newConfigData, userKey string) (*models.Config, error) {
	config := &models.Config{
		Key:        utils.GenerateKey(),
		AppKey:     data.AppKey,
		K:          data.K,
		V:          data.V,
		VType:      data.VType,
		CreatedUTC: utils.GetNowSecond(),
		CreatorKey: userKey,
		Des:        data.Des,
		Status:     models.CONF_STATUS_ACTIVE,
	}

	return updateConfig(config, userKey, nil, nil)
}
Пример #13
0
func TestTemplateApp(t *testing.T) {
	err := _clearModelData()
	assert.True(t, err == nil, "must correctly clear data")
	loadAllData()
	initNodeData()

	user, _ := updateUser(&models.User{
		Name: "rahuahua",
		Key:  utils.GenerateKey()}, nil)

	templateApp, _ := updateApp(&models.App{
		Key:     utils.GenerateKey(),
		UserKey: user.Key,
		Name:    "template_app",
		Type:    models.APP_TYPE_TEMPLATE}, nil, nil)
	templateConfig, _ := updateConfig(&models.Config{
		Key:    utils.GenerateKey(),
		AppKey: templateApp.Key,
		K:      "template_int_conf",
		V:      "233",
		VType:  models.CONF_V_TYPE_INT,
		Status: models.CONF_STATUS_ACTIVE}, "", nil, nil)

	app, _ := updateApp(&models.App{
		Key:     utils.GenerateKey(),
		UserKey: user.Key,
		Name:    "iconfreecn",
		Type:    models.APP_TYPE_REAL}, nil, nil)

	updateConfig(&models.Config{
		Key:    utils.GenerateKey(),
		AppKey: app.Key,
		K:      "int_conf",
		V:      "1",
		VType:  models.CONF_V_TYPE_INT,
		Status: models.CONF_STATUS_ACTIVE}, "", nil, nil)

	_, err = updateConfig(&models.Config{
		Key:    utils.GenerateKey(),
		AppKey: app.Key,
		K:      "template_conf",
		V:      templateApp.Key,
		VType:  models.CONF_V_TYPE_TEMPLATE,
		Status: models.CONF_STATUS_ACTIVE}, "", nil, nil)
	assert.True(t, err == nil, "must correctly add template conf")
	appConfig := getAppMatchConf(app.Key, &ClientData{AppKey: app.Key})
	assert.True(t, reflect.TypeOf(appConfig["template_conf"]).Kind() == reflect.Map)

	appOldDataSign := memConfApps[app.Key].DataSign
	oldTemplateDataSign := memConfApps[templateApp.Key].DataSign
	updateConfig(templateConfig, "", nil, nil)
	assert.True(t, appOldDataSign != memConfApps[app.Key].DataSign, "app's data_sign must update after update config")
	assert.True(t, oldTemplateDataSign != memConfApps[templateApp.Key].DataSign, "app's data_sign must update after update config")

	_clearModelData()
}
Пример #14
0
func NewApp(c *gin.Context) {
	confWriteMux.Lock()
	defer confWriteMux.Unlock()

	var data struct {
		Name    string `json:"name" binding:"required"`
		Type    string `json:"type" binding:"required"`
		AuxInfo string `json:"aux_info"`
	}
	if err := c.BindJSON(&data); err != nil {
		Error(c, BAD_POST_DATA, err.Error())
		return
	}

	if !models.IsValidAppType(data.Type) {
		Error(c, BAD_REQUEST, "unknown app type: "+data.Type)
		return
	}

	if memConfAppsByName[data.Name] != nil {
		Error(c, BAD_REQUEST, "appname already exists: "+data.Name)
		return
	}

	app := &models.App{
		Key:        utils.GenerateKey(),
		Name:       data.Name,
		UserKey:    getOpUserKey(c),
		Type:       data.Type,
		AuxInfo:    data.AuxInfo,
		CreatedUTC: utils.GetNowSecond(),
	}
	if _, err := updateApp(app, nil, nil); err != nil {
		Error(c, SERVER_ERROR, err.Error())
		return
	}

	failedNodes := syncData2SlaveIfNeed(app, getOpUserKey(c))
	if len(failedNodes) > 0 {
		Success(c, map[string]interface{}{"failed_nodes": failedNodes})
	} else {
		Success(c, nil)
	}
}
Пример #15
0
func updateConfig(config *models.Config, userKey string, newDataVersion *models.DataVersion, ms *models.Session) (*models.Config, error) {
	var s *models.Session

	if ms != nil {
		s = ms
	} else {
		s = models.NewSession()
		defer s.Close()
		if err := s.Begin(); err != nil {
			s.Rollback()
			return nil, err
		}
	}

	isSysConf := isSysConfType(config.AppKey)

	node := *memConfNodes[conf.ClientAddr]
	oldConfig := memConfRawConfigs[config.Key]

	app, err := models.GetAppByKey(s, config.AppKey)
	if err != nil {
		return nil, err
	}

	if newDataVersion == nil {
		newDataVersion = genNewDataVersion(memConfDataVersion)
	}

	if err := updateNodeDataVersion(s, &node, newDataVersion); err != nil {
		if ms == nil {
			s.Rollback()
		}
		return nil, err
	}

	var configHistory *models.ConfigUpdateHistory

	if oldConfig == nil {
		configHistory = &models.ConfigUpdateHistory{
			Id:         utils.GenerateKey(),
			ConfigKey:  config.Key,
			K:          config.K,
			OldV:       "",
			OldVType:   "",
			NewV:       config.V,
			NewVType:   config.VType,
			Kind:       models.CONFIG_UPDATE_KIND_NEW,
			UserKey:    userKey,
			CreatedUTC: utils.GetNowSecond(),
		}
		if err := models.InsertRow(s, configHistory); err != nil {
			if ms == nil {
				s.Rollback()
			}
			return nil, err
		}

		config.LastUpdateId = configHistory.Id
		if err := models.InsertRow(s, config); err != nil {
			if ms == nil {
				s.Rollback()
			}
			return nil, err
		}

		if !isSysConf {
			app.KeyCount++
			app.LastUpdateUTC = configHistory.CreatedUTC
			app.LastUpdateId = configHistory.Id
			app.UpdateTimes++
		}

	} else {
		kind := models.CONFIG_UPDATE_KIND_UPDATE
		if config.Status != oldConfig.Status {
			if config.Status == models.CONF_STATUS_ACTIVE {
				kind = models.CONFIG_UPDATE_KIND_RECOVER
			} else {
				kind = models.CONFIG_UPDATE_KIND_HIDE
			}
		}

		configHistory = &models.ConfigUpdateHistory{
			Id:         utils.GenerateKey(),
			ConfigKey:  config.Key,
			K:          config.K,
			OldV:       oldConfig.V,
			OldVType:   oldConfig.VType,
			NewV:       config.V,
			NewVType:   config.VType,
			Kind:       kind,
			UserKey:    userKey,
			CreatedUTC: utils.GetNowSecond(),
		}
		if err := models.InsertRow(s, configHistory); err != nil {
			if ms == nil {
				s.Rollback()
			}
			return nil, err
		}

		config.UpdateTimes++
		config.LastUpdateId = configHistory.Id
		if err := models.UpdateDBModel(s, config); err != nil {
			if ms == nil {
				s.Rollback()
			}
			return nil, err
		}
		if !isSysConf {
			app.LastUpdateUTC = configHistory.CreatedUTC
			app.LastUpdateId = configHistory.Id
			app.UpdateTimes++
		}
	}

	var toUpdateApps []*models.App
	if !isSysConf {
		newDataSign := utils.GenerateKey()
		app.DataSign = newDataSign
		if err := models.UpdateDBModel(s, app); err != nil {
			if ms == nil {
				s.Rollback()
			}
			return nil, err
		}

		if app.Type == models.APP_TYPE_TEMPLATE {
			for _, _app := range memConfApps {
				if _app.Key == config.AppKey {
					continue
				}
				for _, _config := range memConfAppConfigs[_app.Key] {
					if _config.VType == models.CONF_V_TYPE_TEMPLATE && _config.V == config.AppKey {
						// this app has a config refer to this template app
						toUpdateApps = append(toUpdateApps, _app)
						break
					}
				}
			}
		}

		for _, app := range toUpdateApps {
			_app := *app
			_app.DataSign = newDataSign
			if err := models.UpdateDBModel(s, &_app); err != nil {
				if ms == nil {
					s.Rollback()
				}
				return nil, err
			}
		}
	}

	if ms == nil {
		if err := s.Commit(); err != nil {
			s.Rollback()
			return nil, err
		}

		if !isSysConf {
			go TriggerWebHooks(configHistory, app)
		} else {
			go TriggerWebHooks(configHistory, &models.App{Key: config.Key, Name: config.Key})
		}

		updateMemConf(config, newDataVersion, &node, toUpdateApps)
	}

	return config, nil
}