diff --git a/internal/dbmodel/model_test.go b/internal/dbmodel/model_test.go index 923a010a5..195c1fda1 100644 --- a/internal/dbmodel/model_test.go +++ b/internal/dbmodel/model_test.go @@ -57,7 +57,7 @@ func TestRecreateDeletedModel(t *testing.T) { CloudRegion: cl.Regions[0], CloudCredential: cred, } - c.Check(db.Create(&m2).Error, qt.ErrorMatches, `.*violates unique constraint "models_controller_id_owner_identity_name_name_key".*`) + c.Check(db.Create(&m2).Error, qt.ErrorMatches, `.*violates unique constraint "unique_model_names".*`) c.Assert(db.Delete(&m1).Error, qt.IsNil) c.Check(db.First(&m1).Error, qt.Equals, gorm.ErrRecordNotFound) @@ -187,7 +187,7 @@ func TestModelUniqueConstraint(t *testing.T) { Level: "unsupported", }, } - c.Assert(db.Create(&m2).Error, qt.IsNil) + c.Assert(db.Create(&m2).Error, qt.ErrorMatches, `ERROR: duplicate key value violates unique constraint .*`) m3 := dbmodel.Model{ UUID: sql.NullString{ diff --git a/internal/dbmodel/sql/postgres/1_10.sql b/internal/dbmodel/sql/postgres/1_10.sql new file mode 100644 index 000000000..453fb7460 --- /dev/null +++ b/internal/dbmodel/sql/postgres/1_10.sql @@ -0,0 +1,6 @@ +-- 1_10.sql is a migration that enforces a stricter uniqueness +-- constraint on model names. +ALTER TABLE models DROP CONSTRAINT models_controller_id_owner_identity_name_name_key; +ALTER TABLE models ADD CONSTRAINT unique_model_names UNIQUE(owner_identity_name, name); + +UPDATE versions SET major=1, minor=10 WHERE component='jimmdb'; diff --git a/internal/dbmodel/version.go b/internal/dbmodel/version.go index 1649904f4..f5229fc18 100644 --- a/internal/dbmodel/version.go +++ b/internal/dbmodel/version.go @@ -20,7 +20,7 @@ const ( // Minor is the minor version of the model described in the dbmodel // package. It should be incremented for any change made to the // database model from database model in a released JIMM. - Minor = 9 + Minor = 10 ) type Version struct { diff --git a/internal/jujuapi/modelmanager_test.go b/internal/jujuapi/modelmanager_test.go index 3a5bfb87c..e937d829e 100644 --- a/internal/jujuapi/modelmanager_test.go +++ b/internal/jujuapi/modelmanager_test.go @@ -917,6 +917,24 @@ func (s *modelManagerSuite) TestCreateModel(c *gc.C) { } } +func (s *modelManagerSuite) TestCreateDuplicateModelsFails(c *gc.C) { + conn := s.open(c, nil, "bob") + defer conn.Close() + createModel := func(mi jujuparams.ModelInfo) error { + return conn.APICall("ModelManager", 9, "", "CreateModel", jujuparams.ModelCreateArgs{ + Name: "my-model", + OwnerTag: names.NewUserTag("bob@canonical.com").String(), + CloudTag: names.NewCloudTag(jimmtest.TestCloudName).String(), + CloudCredentialTag: "cloudcred-" + jimmtest.TestCloudName + "_bob@canonical.com_cred", + }, &mi) + } + var mi jujuparams.ModelInfo + err := createModel(mi) + c.Assert(err, gc.IsNil) + err = createModel(mi) + c.Assert(err, gc.ErrorMatches, `model bob@canonical\.com/my-model already exists \(already exists\)`) +} + func (s *modelManagerSuite) TestGrantAndRevokeModel(c *gc.C) { conn := s.open(c, nil, "bob") defer conn.Close()