diff --git a/make/migrations/postgresql/0002_1.7.0_schema.up.sql b/make/migrations/postgresql/0002_1.7.0_schema.up.sql index d285fe27c..654d03b65 100644 --- a/make/migrations/postgresql/0002_1.7.0_schema.up.sql +++ b/make/migrations/postgresql/0002_1.7.0_schema.up.sql @@ -10,3 +10,6 @@ create table job_log ( ); CREATE UNIQUE INDEX job_log_uuid ON job_log (job_uuid); + +ALTER TABLE replication_policy ADD CONSTRAINT unique_policy_name UNIQUE (name); +ALTER TABLE replication_target ADD CONSTRAINT unique_target_name UNIQUE (name); diff --git a/src/common/dao/dao_test.go b/src/common/dao/dao_test.go index 1751897cf..c69e492a4 100644 --- a/src/common/dao/dao_test.go +++ b/src/common/dao/dao_test.go @@ -875,27 +875,6 @@ func TestGetRepPolicyByName(t *testing.T) { } -func TestAddRepPolicy2(t *testing.T) { - policy2 := models.RepPolicy{ - ProjectID: 3, - TargetID: 3, - Description: "whatever", - Name: "mypolicy", - } - policyID2, err := AddRepPolicy(policy2) - t.Logf("added policy, id: %d", policyID2) - if err != nil { - t.Errorf("Error occurred in AddRepPolicy: %v", err) - } - p, err := GetRepPolicy(policyID2) - if err != nil { - t.Errorf("Error occurred in GetPolicy: %v, id: %d", err, policyID2) - } - if p == nil { - t.Errorf("Unable to find a policy with id: %d", policyID2) - } -} - func TestAddRepJob(t *testing.T) { job := models.RepJob{ Repository: "library/ubuntu", diff --git a/src/core/api/replication_policy.go b/src/core/api/replication_policy.go index 662191aea..ceb550b41 100644 --- a/src/core/api/replication_policy.go +++ b/src/core/api/replication_policy.go @@ -128,6 +128,18 @@ func (pa *RepPolicyAPI) Post() { policy := &api_models.ReplicationPolicy{} pa.DecodeJSONReqAndValidate(policy) + // check the name + exist, err := exist(policy.Name) + if err != nil { + pa.HandleInternalServerError(fmt.Sprintf("failed to check the existence of policy %s: %v", policy.Name, err)) + return + } + + if exist { + pa.HandleConflict(fmt.Sprintf("name %s is already used", policy.Name)) + return + } + // check the existence of projects for _, project := range policy.Projects { pro, err := pa.ProjectMgr.Get(project.ProjectID) @@ -191,6 +203,22 @@ func (pa *RepPolicyAPI) Post() { pa.Redirect(http.StatusCreated, strconv.FormatInt(id, 10)) } +func exist(name string) (bool, error) { + result, err := core.GlobalController.GetPolicies(rep_models.QueryParameter{ + Name: name, + }) + if err != nil { + return false, err + } + + for _, policy := range result.Policies { + if policy.Name == name { + return true, nil + } + } + return false, nil +} + // Put updates the replication policy func (pa *RepPolicyAPI) Put() { id := pa.GetIDFromURL() @@ -211,6 +239,20 @@ func (pa *RepPolicyAPI) Put() { policy.ID = id + // check the name + if policy.Name != originalPolicy.Name { + exist, err := exist(policy.Name) + if err != nil { + pa.HandleInternalServerError(fmt.Sprintf("failed to check the existence of policy %s: %v", policy.Name, err)) + return + } + + if exist { + pa.HandleConflict(fmt.Sprintf("name %s is already used", policy.Name)) + return + } + } + // check the existence of projects for _, project := range policy.Projects { pro, err := pa.ProjectMgr.Get(project.ProjectID) diff --git a/src/core/api/replication_policy_test.go b/src/core/api/replication_policy_test.go index 1e6afac49..3d67970af 100644 --- a/src/core/api/replication_policy_test.go +++ b/src/core/api/replication_policy_test.go @@ -311,6 +311,41 @@ func TestRepPolicyAPIPost(t *testing.T) { code: http.StatusCreated, postFunc: postFunc, }, + // 409 + { + request: &testingRequest{ + method: http.MethodPost, + url: repPolicyAPIBasePath, + bodyJSON: &api_models.ReplicationPolicy{ + Name: policyName, + Projects: []*models.Project{ + { + ProjectID: projectID, + }, + }, + Targets: []*models.RepTarget{ + { + ID: targetID, + }, + }, + Filters: []rep_models.Filter{ + { + Kind: replication.FilterItemKindRepository, + Pattern: "*", + }, + { + Kind: replication.FilterItemKindLabel, + Value: labelID2, + }, + }, + Trigger: &rep_models.Trigger{ + Kind: replication.TriggerKindManual, + }, + }, + credential: sysAdmin, + }, + code: http.StatusConflict, + }, } runCodeCheckingCases(t, cases...) diff --git a/tests/apitests/python/library/label.py b/tests/apitests/python/library/label.py index c84b3e664..b90a405e9 100644 --- a/tests/apitests/python/library/label.py +++ b/tests/apitests/python/library/label.py @@ -5,8 +5,10 @@ import base import swagger_client class Label(base.Base): - def create_label(self, name=base._random_name("label"), desc="", + def create_label(self, name=None, desc="", color="", scope="g", project_id=0, **kwargs): + if name is None: + name = base._random_name("label") label = swagger_client.Label(name=name, description=desc, color=color, scope=scope, project_id=project_id) diff --git a/tests/apitests/python/library/registry.py b/tests/apitests/python/library/registry.py index 389d7417c..decabb19f 100644 --- a/tests/apitests/python/library/registry.py +++ b/tests/apitests/python/library/registry.py @@ -5,8 +5,10 @@ import base import swagger_client class Registry(base.Base): - def create_registry(self, endpoint, name = base._random_name("registry"), username="", + def create_registry(self, endpoint, name=None, username="", password="", insecure=True, **kwargs): + if name is None: + name = base._random_name("registry") client = self._get_client(**kwargs) registry = swagger_client.RepTargetPost(name=name, endpoint=endpoint, username=username, password=password, insecure=insecure) diff --git a/tests/apitests/python/library/replication.py b/tests/apitests/python/library/replication.py index ecbf98491..af32ae73d 100644 --- a/tests/apitests/python/library/replication.py +++ b/tests/apitests/python/library/replication.py @@ -7,12 +7,14 @@ import swagger_client class Replication(base.Base): def create_replication_rule(self, - projectIDList, targetIDList, name=base._random_name("rule"), desc="", + projectIDList, targetIDList, name=None, desc="", filters=[], trigger=swagger_client.RepTrigger(kind="Manual"), replicate_deletion=True, replicate_existing_image_now=False, expect_status_code = 201, **kwargs): + if name is None: + name = base._random_name("rule") projects = [] for projectID in projectIDList: projects.append(swagger_client.Project(project_id=int(projectID))) diff --git a/tests/apitests/python/test_add_replication_rule.py b/tests/apitests/python/test_add_replication_rule.py index 1a1545671..3b321224a 100644 --- a/tests/apitests/python/test_add_replication_rule.py +++ b/tests/apitests/python/test_add_replication_rule.py @@ -43,7 +43,7 @@ class TestProjects(unittest.TestCase): #4. Delete user(UA); self.user.delete_user(TestProjects.user_add_rule_id, **ADMIN_CLIENT) - def testAddSysLabelToRepo(self): + def testAddReplicationRule(self): """ Test case: Add Replication Rule