1.only target of disabled policy can be modified 2.duplicated policy can not be created

This commit is contained in:
Wenkai Yin 2016-06-22 14:19:19 +08:00
parent 0a0b206863
commit b985c5bed4
5 changed files with 205 additions and 57 deletions

View File

@ -121,6 +121,16 @@ func (pa *RepPolicyAPI) Post() {
pa.CustomAbort(http.StatusBadRequest, fmt.Sprintf("target %d does not exist", policy.TargetID))
}
policies, err := dao.GetRepPolicyByProjectAndTarget(policy.ProjectID, policy.TargetID)
if err != nil {
log.Errorf("failed to get policy [project ID: %d,targetID: %d]: %v", policy.ProjectID, policy.TargetID, err)
pa.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}
if len(policies) > 0 {
pa.CustomAbort(http.StatusConflict, "policy already exists with the same project and target")
}
pid, err := dao.AddRepPolicy(*policy)
if err != nil {
log.Errorf("Failed to add policy to DB, error: %v", err)
@ -159,6 +169,7 @@ func (pa *RepPolicyAPI) Put() {
policy.ProjectID = originalPolicy.ProjectID
pa.Validate(policy)
// check duplicate name
if policy.Name != originalPolicy.Name {
po, err := dao.GetRepPolicyByName(policy.Name)
if err != nil {
@ -172,6 +183,12 @@ func (pa *RepPolicyAPI) Put() {
}
if policy.TargetID != originalPolicy.TargetID {
//target of policy can not be modified when the policy is enabled
if originalPolicy.Enabled == 1 {
pa.CustomAbort(http.StatusBadRequest, "target of policy can not be modified when the policy is enabled")
}
// check the existance of target
target, err := dao.GetRepTarget(policy.TargetID)
if err != nil {
log.Errorf("failed to get target %d: %v", policy.TargetID, err)
@ -181,10 +198,22 @@ func (pa *RepPolicyAPI) Put() {
if target == nil {
pa.CustomAbort(http.StatusBadRequest, fmt.Sprintf("target %d does not exist", policy.TargetID))
}
// check duplicate policy with the same project and target
policies, err := dao.GetRepPolicyByProjectAndTarget(policy.ProjectID, policy.TargetID)
if err != nil {
log.Errorf("failed to get policy [project ID: %d,targetID: %d]: %v", policy.ProjectID, policy.TargetID, err)
pa.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}
if len(policies) > 0 {
pa.CustomAbort(http.StatusConflict, "policy already exists with the same project and target")
}
}
policy.ID = id
/*
isTargetChanged := !(policy.TargetID == originalPolicy.TargetID)
isEnablementChanged := !(policy.Enabled == policy.Enabled)
@ -250,6 +279,17 @@ func (pa *RepPolicyAPI) Put() {
}
}()
}
*/
if policy.Enabled != originalPolicy.Enabled && policy.Enabled == 1 {
go func() {
if err := TriggerReplication(id, "", nil, models.RepOpTransfer); err != nil {
log.Errorf("failed to trigger replication of %d: %v", id, err)
} else {
log.Infof("replication of %d triggered", id)
}
}()
}
}
type enablementReq struct {

View File

@ -190,6 +190,16 @@ func (t *TargetAPI) Post() {
t.CustomAbort(http.StatusConflict, "name is already used")
}
ta, err = dao.GetRepTargetByConnInfo(target.URL, target.Username)
if err != nil {
log.Errorf("failed to get target [ %s %s ]: %v", target.URL, target.Username, err)
t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}
if ta != nil {
t.CustomAbort(http.StatusConflict, "the connection information[ endpoint, username ] is conflict with other target")
}
if len(target.Password) != 0 {
target.Password = utils.ReversibleEncrypt(target.Password)
}
@ -217,6 +227,24 @@ func (t *TargetAPI) Put() {
t.CustomAbort(http.StatusNotFound, http.StatusText(http.StatusNotFound))
}
policies, err := dao.GetRepPolicyByTarget(id)
if err != nil {
log.Errorf("failed to get policies according target %d: %v", id, err)
t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}
hasEnabledPolicy := false
for _, policy := range policies {
if policy.Enabled == 1 {
hasEnabledPolicy = true
break
}
}
if hasEnabledPolicy {
t.CustomAbort(http.StatusBadRequest, "the target is associated with policy which is enabled")
}
target := &models.RepTarget{}
t.DecodeJSONReqAndValidate(target)
@ -232,6 +260,18 @@ func (t *TargetAPI) Put() {
}
}
if target.URL != originalTarget.URL || target.Username != originalTarget.Username {
ta, err := dao.GetRepTargetByConnInfo(target.URL, target.Username)
if err != nil {
log.Errorf("failed to get target [ %s %s ]: %v", target.URL, target.Username, err)
t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}
if ta != nil {
t.CustomAbort(http.StatusConflict, "the connection information[ endpoint, username ] is conflict with other target")
}
}
target.ID = id
if len(target.Password) != 0 {
@ -273,3 +313,27 @@ func (t *TargetAPI) Delete() {
t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}
}
// ListPolicies ...
func (t *TargetAPI) ListPolicies() {
id := t.GetIDFromURL()
target, err := dao.GetRepTarget(id)
if err != nil {
log.Errorf("failed to get target %d: %v", id, err)
t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}
if target == nil {
t.CustomAbort(http.StatusNotFound, http.StatusText(http.StatusNotFound))
}
policies, err := dao.GetRepPolicyByTarget(id)
if err != nil {
log.Errorf("failed to get policies according target %d: %v", id, err)
t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}
t.Data["json"] = policies
t.ServeJSON()
}

View File

@ -926,6 +926,21 @@ func TestGetRepPolicyByTarget(t *testing.T) {
}
}
func TestGetRepPolicyByProjectAndTarget(t *testing.T) {
policies, err := GetRepPolicyByProjectAndTarget(1, targetID)
if err != nil {
t.Fatalf("failed to get policy according project %d and target %d: %v", 1, targetID, err)
}
if len(policies) == 0 {
t.Fatal("unexpected length of policies 0, expected is >0")
}
if policies[0].ID != policyID {
t.Fatalf("unexpected policy: %d, expected: %d", policies[0].ID, policyID)
}
}
func TestGetRepPolicyByName(t *testing.T) {
policy, err := GetRepPolicy(policyID)
if err != nil {

View File

@ -52,6 +52,20 @@ func GetRepTargetByName(name string) (*models.RepTarget, error) {
return &t, err
}
// GetRepTargetByConnInfo ...
func GetRepTargetByConnInfo(endpoint, username string) (*models.RepTarget, error) {
o := GetOrmer()
t := models.RepTarget{
URL: endpoint,
Username: username,
}
err := o.Read(&t, "URL", "Username")
if err == orm.ErrNoRows {
return nil, nil
}
return &t, err
}
// DeleteRepTarget ...
func DeleteRepTarget(id int64) error {
o := GetOrmer()
@ -206,6 +220,20 @@ func GetRepPolicyByTarget(targetID int64) ([]*models.RepPolicy, error) {
return policies, nil
}
// GetRepPolicyByProjectAndTarget ...
func GetRepPolicyByProjectAndTarget(projectID, targetID int64) ([]*models.RepPolicy, error) {
o := GetOrmer()
sql := `select * from replication_policy where project_id = ? and target_id = ?`
var policies []*models.RepPolicy
if _, err := o.Raw(sql, projectID, targetID).QueryRows(&policies); err != nil {
return nil, err
}
return policies, nil
}
// UpdateRepPolicy ...
func UpdateRepPolicy(policy *models.RepPolicy) error {
o := GetOrmer()

View File

@ -76,6 +76,7 @@ func initRouters() {
beego.Router("/api/targets/", &api.TargetAPI{}, "get:List")
beego.Router("/api/targets/", &api.TargetAPI{}, "post:Post")
beego.Router("/api/targets/:id([0-9]+)", &api.TargetAPI{})
beego.Router("/api/targets/:id([0-9]+)/policies/", &api.TargetAPI{}, "get:ListPolicies")
beego.Router("/api/targets/ping", &api.TargetAPI{}, "post:Ping")
beego.Router("/api/users/:id/sysadmin", &api.UserAPI{}, "put:ToggleUserAdminRole")
beego.Router("/api/repositories/top", &api.RepositoryAPI{}, "get:GetTopRepos")