Merge pull request #384 from ywk253100/update_and_create_policy_api_modify

Update and create policy api modify
This commit is contained in:
Wenkai Yin 2016-06-22 15:05:07 +08:00 committed by GitHub
commit 97ea1da965
5 changed files with 205 additions and 57 deletions

View File

@ -1,16 +1,16 @@
/* /*
Copyright (c) 2016 VMware, Inc. All Rights Reserved. Copyright (c) 2016 VMware, Inc. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
package api package api
@ -121,6 +121,16 @@ func (pa *RepPolicyAPI) Post() {
pa.CustomAbort(http.StatusBadRequest, fmt.Sprintf("target %d does not exist", policy.TargetID)) 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) pid, err := dao.AddRepPolicy(*policy)
if err != nil { if err != nil {
log.Errorf("Failed to add policy to DB, error: %v", err) log.Errorf("Failed to add policy to DB, error: %v", err)
@ -159,6 +169,7 @@ func (pa *RepPolicyAPI) Put() {
policy.ProjectID = originalPolicy.ProjectID policy.ProjectID = originalPolicy.ProjectID
pa.Validate(policy) pa.Validate(policy)
// check duplicate name
if policy.Name != originalPolicy.Name { if policy.Name != originalPolicy.Name {
po, err := dao.GetRepPolicyByName(policy.Name) po, err := dao.GetRepPolicyByName(policy.Name)
if err != nil { if err != nil {
@ -172,6 +183,12 @@ func (pa *RepPolicyAPI) Put() {
} }
if policy.TargetID != originalPolicy.TargetID { 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) target, err := dao.GetRepTarget(policy.TargetID)
if err != nil { if err != nil {
log.Errorf("failed to get target %d: %v", policy.TargetID, err) log.Errorf("failed to get target %d: %v", policy.TargetID, err)
@ -181,67 +198,90 @@ func (pa *RepPolicyAPI) Put() {
if target == nil { if target == nil {
pa.CustomAbort(http.StatusBadRequest, fmt.Sprintf("target %d does not exist", policy.TargetID)) 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 policy.ID = id
isTargetChanged := !(policy.TargetID == originalPolicy.TargetID) /*
isEnablementChanged := !(policy.Enabled == policy.Enabled) isTargetChanged := !(policy.TargetID == originalPolicy.TargetID)
isEnablementChanged := !(policy.Enabled == policy.Enabled)
var shouldStop, shouldTrigger bool var shouldStop, shouldTrigger bool
// if target and enablement are not changed, do nothing // if target and enablement are not changed, do nothing
if !isTargetChanged && !isEnablementChanged { if !isTargetChanged && !isEnablementChanged {
shouldStop = false
shouldTrigger = false
} else if !isTargetChanged && isEnablementChanged {
// target is not changed, but enablement is changed
if policy.Enabled == 0 {
shouldStop = true
shouldTrigger = false
} else {
shouldStop = false
shouldTrigger = true
}
} else if isTargetChanged && !isEnablementChanged {
// target is changed, but enablement is not changed
if policy.Enabled == 0 {
// enablement is 0, do nothing
shouldStop = false shouldStop = false
shouldTrigger = false shouldTrigger = false
} else if !isTargetChanged && isEnablementChanged {
// target is not changed, but enablement is changed
if policy.Enabled == 0 {
shouldStop = true
shouldTrigger = false
} else {
shouldStop = false
shouldTrigger = true
}
} else if isTargetChanged && !isEnablementChanged {
// target is changed, but enablement is not changed
if policy.Enabled == 0 {
// enablement is 0, do nothing
shouldStop = false
shouldTrigger = false
} else {
// enablement is 1, so stop original target's jobs
// and trigger new target's jobs
shouldStop = true
shouldTrigger = true
}
} else { } else {
// enablement is 1, so stop original target's jobs // both target and enablement are changed
// and trigger new target's jobs
shouldStop = true
shouldTrigger = true
}
} else {
// both target and enablement are changed
// enablement: 1 -> 0 // enablement: 1 -> 0
if policy.Enabled == 0 { if policy.Enabled == 0 {
shouldStop = true shouldStop = true
shouldTrigger = false shouldTrigger = false
} else { } else {
shouldStop = false shouldStop = false
shouldTrigger = true shouldTrigger = true
}
} }
}
if shouldStop { if shouldStop {
if err := postReplicationAction(id, "stop"); err != nil { if err := postReplicationAction(id, "stop"); err != nil {
log.Errorf("failed to stop replication of %d: %v", id, err) log.Errorf("failed to stop replication of %d: %v", id, err)
pa.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
}
log.Infof("replication of %d has been stopped", id)
}
if err = dao.UpdateRepPolicy(policy); err != nil {
log.Errorf("failed to update policy %d: %v", id, err)
pa.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) pa.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError))
} }
log.Infof("replication of %d has been stopped", id)
}
if err = dao.UpdateRepPolicy(policy); err != nil { if shouldTrigger {
log.Errorf("failed to update policy %d: %v", id, err) go func() {
pa.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) 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)
}
}()
}
*/
if shouldTrigger { if policy.Enabled != originalPolicy.Enabled && policy.Enabled == 1 {
go func() { go func() {
if err := TriggerReplication(id, "", nil, models.RepOpTransfer); err != nil { if err := TriggerReplication(id, "", nil, models.RepOpTransfer); err != nil {
log.Errorf("failed to trigger replication of %d: %v", id, err) log.Errorf("failed to trigger replication of %d: %v", id, err)

View File

@ -190,6 +190,16 @@ func (t *TargetAPI) Post() {
t.CustomAbort(http.StatusConflict, "name is already used") 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 { if len(target.Password) != 0 {
target.Password = utils.ReversibleEncrypt(target.Password) target.Password = utils.ReversibleEncrypt(target.Password)
} }
@ -217,6 +227,24 @@ func (t *TargetAPI) Put() {
t.CustomAbort(http.StatusNotFound, http.StatusText(http.StatusNotFound)) 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{} target := &models.RepTarget{}
t.DecodeJSONReqAndValidate(target) 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 target.ID = id
if len(target.Password) != 0 { if len(target.Password) != 0 {
@ -273,3 +313,27 @@ func (t *TargetAPI) Delete() {
t.CustomAbort(http.StatusInternalServerError, http.StatusText(http.StatusInternalServerError)) 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) { func TestGetRepPolicyByName(t *testing.T) {
policy, err := GetRepPolicy(policyID) policy, err := GetRepPolicy(policyID)
if err != nil { if err != nil {

View File

@ -52,6 +52,20 @@ func GetRepTargetByName(name string) (*models.RepTarget, error) {
return &t, err 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 ... // DeleteRepTarget ...
func DeleteRepTarget(id int64) error { func DeleteRepTarget(id int64) error {
o := GetOrmer() o := GetOrmer()
@ -206,6 +220,20 @@ func GetRepPolicyByTarget(targetID int64) ([]*models.RepPolicy, error) {
return policies, nil 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 ... // UpdateRepPolicy ...
func UpdateRepPolicy(policy *models.RepPolicy) error { func UpdateRepPolicy(policy *models.RepPolicy) error {
o := GetOrmer() o := GetOrmer()

View File

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