mirror of
https://github.com/goharbor/harbor.git
synced 2024-11-22 18:25:56 +01:00
1.only target of disabled policy can be modified 2.duplicated policy can not be created
This commit is contained in:
parent
0a0b206863
commit
b985c5bed4
@ -1,16 +1,16 @@
|
||||
/*
|
||||
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
Copyright (c) 2016 VMware, Inc. All Rights Reserved.
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package api
|
||||
@ -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,67 +198,90 @@ 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)
|
||||
/*
|
||||
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 !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
|
||||
// if target and enablement are not changed, do nothing
|
||||
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
|
||||
shouldTrigger = false
|
||||
} else {
|
||||
// enablement is 1, so stop original target's jobs
|
||||
// and trigger new target's jobs
|
||||
shouldStop = true
|
||||
shouldTrigger = true
|
||||
}
|
||||
} else {
|
||||
// enablement is 1, so stop original target's jobs
|
||||
// and trigger new target's jobs
|
||||
shouldStop = true
|
||||
shouldTrigger = true
|
||||
}
|
||||
} else {
|
||||
// both target and enablement are changed
|
||||
// both target and enablement are changed
|
||||
|
||||
// enablement: 1 -> 0
|
||||
if policy.Enabled == 0 {
|
||||
shouldStop = true
|
||||
shouldTrigger = false
|
||||
} else {
|
||||
shouldStop = false
|
||||
shouldTrigger = true
|
||||
// enablement: 1 -> 0
|
||||
if policy.Enabled == 0 {
|
||||
shouldStop = true
|
||||
shouldTrigger = false
|
||||
} else {
|
||||
shouldStop = false
|
||||
shouldTrigger = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if shouldStop {
|
||||
if err := postReplicationAction(id, "stop"); err != nil {
|
||||
log.Errorf("failed to stop replication of %d: %v", id, err)
|
||||
if shouldStop {
|
||||
if err := postReplicationAction(id, "stop"); err != nil {
|
||||
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))
|
||||
}
|
||||
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))
|
||||
}
|
||||
if shouldTrigger {
|
||||
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)
|
||||
}
|
||||
}()
|
||||
}
|
||||
*/
|
||||
|
||||
if shouldTrigger {
|
||||
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)
|
||||
|
@ -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()
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
||||
|
@ -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")
|
||||
|
Loading…
Reference in New Issue
Block a user