diff --git a/controller/space.go b/controller/space.go index 9d908a3948..caefef2751 100644 --- a/controller/space.go +++ b/controller/space.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" "net/url" + "regexp" "github.com/fabric8-services/fabric8-wit/app" "github.com/fabric8-services/fabric8-wit/application" @@ -546,6 +547,18 @@ func (c *SpaceController) Update(ctx *app.UpdateSpaceContext) error { return ctx.OK(&response) } +const ( + // see https://github.com/kubernetes/community/blob/master/contributors/design-proposals/architecture/identifiers.md + spaceNameMaxLength int = 63 + spaceNamePattern string = `^([A-Za-z0-9][-A-Za-z0-9]*)?[A-Za-z0-9]$` +) + +var nameRegex *regexp.Regexp + +func init() { + nameRegex = regexp.MustCompile(spaceNamePattern) // will panic if the pattern is invalid +} + func validateCreateSpace(ctx *app.CreateSpaceContext) error { if ctx.Payload.Data == nil { return errors.NewBadParameterError("data", nil).Expected("not nil") @@ -556,6 +569,16 @@ func validateCreateSpace(ctx *app.CreateSpaceContext) error { if ctx.Payload.Data.Attributes.Name == nil { return errors.NewBadParameterError("data.attributes.name", nil).Expected("not nil") } + name := *ctx.Payload.Data.Attributes.Name + // now, verify the length and pattern for the space name + if len(name) > spaceNameMaxLength { + return errors.NewBadParameterError("data.attributes.name", name).Expected(fmt.Sprintf("max length: %d (was %d)", spaceNameMaxLength, len(name))) + } + matched := nameRegex.MatchString(name) + if !matched { + return errors.NewBadParameterError("data.attributes.name", name).Expected(fmt.Sprintf("matching '%s' pattern", spaceNamePattern)) + } + // // TODO(kwk): Comment back in once space template is official // if ctx.Payload.Data.Relationships == nil { // return errors.NewBadParameterError("data.relationships", nil).Expected("not nil") diff --git a/controller/space_blackbox_test.go b/controller/space_blackbox_test.go index d0bf72b340..6e3f7926e5 100644 --- a/controller/space_blackbox_test.go +++ b/controller/space_blackbox_test.go @@ -154,241 +154,233 @@ func (s *SpaceControllerTestSuite) SecuredSpaceIterationController(identity acco return svc, NewSpaceIterationsController(svc, s.db, s.Configuration) } -func (s *SpaceControllerTestSuite) TestValidateSpaceName() { +func (s *SpaceControllerTestSuite) TestCreateSpace() { s.T().Run("ok", func(t *testing.T) { - // given - p := newCreateSpacePayload(&testsupport.TestMaxsizedNameObj, nil) - // when - err := p.Validate() - // Validate payload function returns no error - assert.Nil(t, err) - }) - - s.T().Run("Fail - length", func(t *testing.T) { - // given - p := newCreateSpacePayload(&testsupport.TestOversizedNameObj, nil) - // when - err := p.Validate() - // Validate payload function returns an error - assert.NotNil(t, err) - assert.Contains(t, err.Error(), "length of type.name must be less than or equal to 63 but got") - }) - s.T().Run("Fail - prefix", func(t *testing.T) { - // given - invalidSpaceName := "_TestSpace" - p := newCreateSpacePayload(&invalidSpaceName, nil) - // when - err := p.Validate() - // Validate payload function returns an error - assert.NotNil(t, err) - assert.Contains(t, err.Error(), "type.name must match the regexp") - }) -} + t.Run("valid name", func(t *testing.T) { + // given + name := testsupport.CreateRandomValidTestName("TestSuccessCreateSpace-") + p := newCreateSpacePayload(&name, nil) + svc, ctrl := s.SecuredController(testsupport.TestIdentity) + // when + compareWithGoldenAgnostic(t, filepath.Join(s.testDir, "create", "ok.payload.req.golden.json"), p) + res, created := test.CreateSpaceCreated(t, svc.Context, svc, ctrl, p) + // then + require.NotNil(t, created.Data) + require.NotNil(t, created.Data.Attributes) + assert.NotNil(t, created.Data.Attributes.CreatedAt) + assert.NotNil(t, created.Data.Attributes.UpdatedAt) + require.NotNil(t, created.Data.Attributes.Name) + assert.Equal(t, name, *created.Data.Attributes.Name) + require.NotNil(t, created.Data.Links) + assert.NotNil(t, created.Data.Links.Self) + compareWithGoldenAgnostic(t, filepath.Join(s.testDir, "create", "ok.payload.res.golden.json"), created) + compareWithGoldenAgnostic(t, filepath.Join(s.testDir, "create", "ok.headers.res.golden.json"), res.Header()) + }) -func (s *SpaceControllerTestSuite) TestCreateSpace() { - s.T().Run("Fail - unsecure", func(t *testing.T) { - // given - p := newCreateSpacePayload(nil, nil) - svc, ctrl := s.UnSecuredController() - // when/then - test.CreateSpaceUnauthorized(t, svc.Context, svc, ctrl, p) - }) + t.Run("with explicit template", func(t *testing.T) { + // given + fxt := tf.NewTestFixture(t, s.DB, tf.SpaceTemplates(1)) + name := testsupport.CreateRandomValidTestName("TestSuccessCreateSpace-") + p := newCreateSpacePayload(&name, nil) - s.T().Run("Fail - auth returned 400", func(t *testing.T) { - // given - spaceName := uuid.NewV4().String() - p := newCreateSpacePayload(&spaceName, nil) - r := DummyResourceManager{ - httpResponseCode: 400, - } - svc, ctrl := s.SecuredControllerWithDummyResourceManager(testsupport.TestIdentity, r) - // when/then - test.CreateSpaceBadRequest(t, svc.Context, svc, ctrl, p) - }) - s.T().Run("Fail - auth returned 401", func(t *testing.T) { - // given - spaceName := uuid.NewV4().String() - p := newCreateSpacePayload(&spaceName, nil) - r := DummyResourceManager{ - httpResponseCode: 401, - } - svc, ctrl := s.SecuredControllerWithDummyResourceManager(testsupport.TestIdentity, r) - // when/then - test.CreateSpaceUnauthorized(t, svc.Context, svc, ctrl, p) - }) - s.T().Run("Fail - auth returned 500", func(t *testing.T) { - // given - spaceName := uuid.NewV4().String() - p := newCreateSpacePayload(&spaceName, nil) - r := DummyResourceManager{ - httpResponseCode: 500, - } - svc, ctrl := s.SecuredControllerWithDummyResourceManager(testsupport.TestIdentity, r) - // when/then - test.CreateSpaceInternalServerError(t, svc.Context, svc, ctrl, p) - }) + if p.Data.Relationships == nil { + p.Data.Relationships = &app.SpaceRelationships{} + } + p.Data.Relationships.SpaceTemplate = app.NewSpaceTemplateRelation( + fxt.SpaceTemplates[0].ID, + rest.AbsoluteURL( + &http.Request{Host: "api.service.domain.org"}, + app.SpaceTemplateHref(fxt.SpaceTemplates[0].ID.String()), + ), + ) + svc, ctrl := s.SecuredController(testsupport.TestIdentity) + // when + compareWithGoldenAgnostic(t, filepath.Join(s.testDir, "create", "ok_with_explicit_template.payload.req.golden.json"), p) + res, created := test.CreateSpaceCreated(t, svc.Context, svc, ctrl, p) + // then + require.NotNil(t, created.Data) + require.NotNil(t, created.Data.Attributes) + assert.NotNil(t, created.Data.Attributes.CreatedAt) + assert.NotNil(t, created.Data.Attributes.UpdatedAt) + require.NotNil(t, created.Data.Attributes.Name) + assert.Equal(t, name, *created.Data.Attributes.Name) + require.NotNil(t, created.Data.Links) + assert.NotNil(t, created.Data.Links.Self) + compareWithGoldenAgnostic(t, filepath.Join(s.testDir, "create", "ok_with_explicit_template.payload.res.golden.json"), created) + compareWithGoldenAgnostic(t, filepath.Join(s.testDir, "create", "ok_with_explicit_template.headers.res.golden.json"), res.Header()) + }) - s.T().Run("ok", func(t *testing.T) { - // given - name := testsupport.CreateRandomValidTestName("TestSuccessCreateSpace-") - p := newCreateSpacePayload(&name, nil) - svc, ctrl := s.SecuredController(testsupport.TestIdentity) - // when - compareWithGoldenAgnostic(t, filepath.Join(s.testDir, "create", "ok.payload.req.golden.json"), p) - res, created := test.CreateSpaceCreated(t, svc.Context, svc, ctrl, p) - // then - require.NotNil(t, created.Data) - require.NotNil(t, created.Data.Attributes) - assert.NotNil(t, created.Data.Attributes.CreatedAt) - assert.NotNil(t, created.Data.Attributes.UpdatedAt) - require.NotNil(t, created.Data.Attributes.Name) - assert.Equal(t, name, *created.Data.Attributes.Name) - require.NotNil(t, created.Data.Links) - assert.NotNil(t, created.Data.Links.Self) - compareWithGoldenAgnostic(t, filepath.Join(s.testDir, "create", "ok.payload.res.golden.json"), created) - compareWithGoldenAgnostic(t, filepath.Join(s.testDir, "create", "ok.headers.res.golden.json"), res.Header()) - }) + t.Run("with default area", func(t *testing.T) { + // given + name := testsupport.CreateRandomValidTestName("TestSuccessCreateSpaceAndDefaultArea-") + p := newCreateSpacePayload(&name, nil) + svc, ctrl := s.SecuredController(testsupport.TestIdentity) + // when + _, created := test.CreateSpaceCreated(t, svc.Context, svc, ctrl, p) + require.NotNil(t, created.Data) + spaceAreaSvc, spaceAreaCtrl := s.SecuredSpaceAreaController(testsupport.TestIdentity) + _, areaList := test.ListSpaceAreasOK(t, spaceAreaSvc.Context, spaceAreaSvc, spaceAreaCtrl, *created.Data.ID, nil, nil) + // then + // only 1 default gets created. + assert.Len(t, areaList.Data, 1) + assert.Equal(t, name, *areaList.Data[0].Attributes.Name) + + // verify if root iteration is created or not + spaceIterationSvc, spaceIterationCtrl := s.SecuredSpaceIterationController(testsupport.TestIdentity) + _, iterationList := test.ListSpaceIterationsOK(t, spaceIterationSvc.Context, spaceIterationSvc, spaceIterationCtrl, *created.Data.ID, nil, nil) + require.Len(t, iterationList.Data, 1) + assert.Equal(t, name, *iterationList.Data[0].Attributes.Name) + }) - s.T().Run("ok (with explicit template)", func(t *testing.T) { - // given - fxt := tf.NewTestFixture(t, s.DB, tf.SpaceTemplates(1)) - name := testsupport.CreateRandomValidTestName("TestSuccessCreateSpace-") - p := newCreateSpacePayload(&name, nil) + t.Run("with description", func(t *testing.T) { + // given + name := testsupport.CreateRandomValidTestName("TestSuccessCreateSpaceWithDescription-") + description := "Space for TestSuccessCreateSpaceWithDescription" + p := newCreateSpacePayload(&name, &description) + svc, ctrl := s.SecuredController(testsupport.TestIdentity) + // when + _, created := test.CreateSpaceCreated(t, svc.Context, svc, ctrl, p) + // then + assert.NotNil(t, created.Data) + assert.NotNil(t, created.Data.Attributes) + assert.NotNil(t, created.Data.Attributes.CreatedAt) + assert.NotNil(t, created.Data.Attributes.UpdatedAt) + assert.NotNil(t, created.Data.Attributes.Name) + assert.Equal(t, name, *created.Data.Attributes.Name) + assert.NotNil(t, created.Data.Attributes.Description) + assert.Equal(t, description, *created.Data.Attributes.Description) + assert.NotNil(t, created.Data.Links) + assert.NotNil(t, created.Data.Links.Self) + }) - if p.Data.Relationships == nil { - p.Data.Relationships = &app.SpaceRelationships{} - } - p.Data.Relationships.SpaceTemplate = app.NewSpaceTemplateRelation( - fxt.SpaceTemplates[0].ID, - rest.AbsoluteURL( - &http.Request{Host: "api.service.domain.org"}, - app.SpaceTemplateHref(fxt.SpaceTemplates[0].ID.String()), - ), - ) - svc, ctrl := s.SecuredController(testsupport.TestIdentity) - // when - compareWithGoldenAgnostic(t, filepath.Join(s.testDir, "create", "ok_with_explicit_template.payload.req.golden.json"), p) - res, created := test.CreateSpaceCreated(t, svc.Context, svc, ctrl, p) - // then - require.NotNil(t, created.Data) - require.NotNil(t, created.Data.Attributes) - assert.NotNil(t, created.Data.Attributes.CreatedAt) - assert.NotNil(t, created.Data.Attributes.UpdatedAt) - require.NotNil(t, created.Data.Attributes.Name) - assert.Equal(t, name, *created.Data.Attributes.Name) - require.NotNil(t, created.Data.Links) - assert.NotNil(t, created.Data.Links.Self) - compareWithGoldenAgnostic(t, filepath.Join(s.testDir, "create", "ok_with_explicit_template.payload.res.golden.json"), created) - compareWithGoldenAgnostic(t, filepath.Join(s.testDir, "create", "ok_with_explicit_template.headers.res.golden.json"), res.Header()) - }) + t.Run("same name but different owner", func(t *testing.T) { + // given + name := testsupport.CreateRandomValidTestName("SameName-") + description := "Space for TestSuccessCreateSameSpaceNameDifferentOwners" + newDescription := "Space for TestSuccessCreateSameSpaceNameDifferentOwners2" + a := newCreateSpacePayload(&name, &description) + svc, ctrl := s.SecuredController(testsupport.TestIdentity) + _, created := test.CreateSpaceCreated(t, svc.Context, svc, ctrl, a) + // when + b := newCreateSpacePayload(&name, &newDescription) + svc2, ctrl2 := s.SecuredController(testsupport.TestIdentity2) + _, created2 := test.CreateSpaceCreated(t, svc2.Context, svc2, ctrl2, b) + // then + assert.NotNil(t, created.Data) + assert.NotNil(t, created.Data.Attributes) + assert.NotNil(t, created.Data.Attributes.Name) + assert.Equal(t, name, *created.Data.Attributes.Name) + assert.NotNil(t, created2.Data) + assert.NotNil(t, created2.Data.Attributes) + assert.NotNil(t, created2.Data.Attributes.Name) + assert.Equal(t, name, *created2.Data.Attributes.Name) + assert.NotEqual(t, created.Data.Relationships.OwnedBy.Data.ID, created2.Data.Relationships.OwnedBy.Data.ID) + }) - s.T().Run("ok with default area", func(t *testing.T) { - // given - name := testsupport.CreateRandomValidTestName("TestSuccessCreateSpaceAndDefaultArea-") - p := newCreateSpacePayload(&name, nil) - svc, ctrl := s.SecuredController(testsupport.TestIdentity) - // when - _, created := test.CreateSpaceCreated(t, svc.Context, svc, ctrl, p) - require.NotNil(t, created.Data) - spaceAreaSvc, spaceAreaCtrl := s.SecuredSpaceAreaController(testsupport.TestIdentity) - _, areaList := test.ListSpaceAreasOK(t, spaceAreaSvc.Context, spaceAreaSvc, spaceAreaCtrl, *created.Data.ID, nil, nil) - // then - // only 1 default gets created. - assert.Len(t, areaList.Data, 1) - assert.Equal(t, name, *areaList.Data[0].Attributes.Name) - - // verify if root iteration is created or not - spaceIterationSvc, spaceIterationCtrl := s.SecuredSpaceIterationController(testsupport.TestIdentity) - _, iterationList := test.ListSpaceIterationsOK(t, spaceIterationSvc.Context, spaceIterationSvc, spaceIterationCtrl, *created.Data.ID, nil, nil) - require.Len(t, iterationList.Data, 1) - assert.Equal(t, name, *iterationList.Data[0].Attributes.Name) + t.Run("with max length name", func(t *testing.T) { + // given + name := testsupport.TestMaxsizedNameObj + p := newCreateSpacePayload(&name, nil) + svc, ctrl := s.SecuredController(testsupport.TestIdentity) + // when + _, created := test.CreateSpaceCreated(t, svc.Context, svc, ctrl, p) + // then + require.NotNil(t, created.Data) + require.NotNil(t, created.Data.Attributes) + assert.NotNil(t, created.Data.Attributes.CreatedAt) + assert.NotNil(t, created.Data.Attributes.UpdatedAt) + require.NotNil(t, created.Data.Attributes.Name) + assert.Equal(t, name, *created.Data.Attributes.Name) + require.NotNil(t, created.Data.Links) + assert.NotNil(t, created.Data.Links.Self) + }) }) - s.T().Run("ok with description", func(t *testing.T) { - // given - name := testsupport.CreateRandomValidTestName("TestSuccessCreateSpaceWithDescription-") - description := "Space for TestSuccessCreateSpaceWithDescription" - p := newCreateSpacePayload(&name, &description) - svc, ctrl := s.SecuredController(testsupport.TestIdentity) - // when - _, created := test.CreateSpaceCreated(t, svc.Context, svc, ctrl, p) - // then - assert.NotNil(t, created.Data) - assert.NotNil(t, created.Data.Attributes) - assert.NotNil(t, created.Data.Attributes.CreatedAt) - assert.NotNil(t, created.Data.Attributes.UpdatedAt) - assert.NotNil(t, created.Data.Attributes.Name) - assert.Equal(t, name, *created.Data.Attributes.Name) - assert.NotNil(t, created.Data.Attributes.Description) - assert.Equal(t, description, *created.Data.Attributes.Description) - assert.NotNil(t, created.Data.Links) - assert.NotNil(t, created.Data.Links.Self) - }) + s.T().Run("fail", func(t *testing.T) { - s.T().Run("ok same name but different owner", func(t *testing.T) { - // given - name := testsupport.CreateRandomValidTestName("SameName-") - description := "Space for TestSuccessCreateSameSpaceNameDifferentOwners" - newDescription := "Space for TestSuccessCreateSameSpaceNameDifferentOwners2" - a := newCreateSpacePayload(&name, &description) - svc, ctrl := s.SecuredController(testsupport.TestIdentity) - _, created := test.CreateSpaceCreated(t, svc.Context, svc, ctrl, a) - // when - b := newCreateSpacePayload(&name, &newDescription) - svc2, ctrl2 := s.SecuredController(testsupport.TestIdentity2) - _, created2 := test.CreateSpaceCreated(t, svc2.Context, svc2, ctrl2, b) - // then - assert.NotNil(t, created.Data) - assert.NotNil(t, created.Data.Attributes) - assert.NotNil(t, created.Data.Attributes.Name) - assert.Equal(t, name, *created.Data.Attributes.Name) - assert.NotNil(t, created2.Data) - assert.NotNil(t, created2.Data.Attributes) - assert.NotNil(t, created2.Data.Attributes.Name) - assert.Equal(t, name, *created2.Data.Attributes.Name) - assert.NotEqual(t, created.Data.Relationships.OwnedBy.Data.ID, created2.Data.Relationships.OwnedBy.Data.ID) - }) + t.Run("same name and same owner", func(t *testing.T) { + // given + name := testsupport.CreateRandomValidTestName("SameName-") + description := "Space for TestSuccessCreateSameSpaceNameDifferentOwners" + newDescription := "Space for TestSuccessCreateSameSpaceNameDifferentOwners2" + // when + a := newCreateSpacePayload(&name, &description) + svc, ctrl := s.SecuredController(testsupport.TestIdentity) + _, created := test.CreateSpaceCreated(t, svc.Context, svc, ctrl, a) + // then + assert.NotNil(t, created.Data) + assert.NotNil(t, created.Data.Attributes) + assert.NotNil(t, created.Data.Attributes.Name) + assert.Equal(t, name, *created.Data.Attributes.Name) - s.T().Run("ok with max length name", func(t *testing.T) { - // given - name := testsupport.TestMaxsizedNameObj - p := newCreateSpacePayload(&name, nil) - svc, ctrl := s.SecuredController(testsupport.TestIdentity) - // when - _, created := test.CreateSpaceCreated(t, svc.Context, svc, ctrl, p) - // then - require.NotNil(t, created.Data) - require.NotNil(t, created.Data.Attributes) - assert.NotNil(t, created.Data.Attributes.CreatedAt) - assert.NotNil(t, created.Data.Attributes.UpdatedAt) - require.NotNil(t, created.Data.Attributes.Name) - assert.Equal(t, name, *created.Data.Attributes.Name) - require.NotNil(t, created.Data.Links) - assert.NotNil(t, created.Data.Links.Self) - }) + // when + b := newCreateSpacePayload(&name, &newDescription) + b.Data.Attributes.Name = &name + b.Data.Attributes.Description = &newDescription + test.CreateSpaceConflict(t, svc.Context, svc, ctrl, b) + }) - s.T().Run("fail same name and same owner", func(t *testing.T) { - // given - name := testsupport.CreateRandomValidTestName("SameName-") - description := "Space for TestSuccessCreateSameSpaceNameDifferentOwners" - newDescription := "Space for TestSuccessCreateSameSpaceNameDifferentOwners2" - // when - a := newCreateSpacePayload(&name, &description) - svc, ctrl := s.SecuredController(testsupport.TestIdentity) - _, created := test.CreateSpaceCreated(t, svc.Context, svc, ctrl, a) - // then - assert.NotNil(t, created.Data) - assert.NotNil(t, created.Data.Attributes) - assert.NotNil(t, created.Data.Attributes.Name) - assert.Equal(t, name, *created.Data.Attributes.Name) + t.Run("invalid name", func(t *testing.T) { + t.Run("invalid character", func(t *testing.T) { + // given + name := "foo@bar.com" + description := "Space with invalid name" + // when/then + p := newCreateSpacePayload(&name, &description) + svc, ctrl := s.SecuredController(testsupport.TestIdentity) + test.CreateSpaceBadRequest(t, svc.Context, svc, ctrl, p) + }) + + t.Run("invalid length", func(t *testing.T) { + // given + name := testsupport.TestOversizedNameObj + description := "Space with invalid name" + // when/then + p := newCreateSpacePayload(&name, &description) + svc, ctrl := s.SecuredController(testsupport.TestIdentity) + test.CreateSpaceBadRequest(t, svc.Context, svc, ctrl, p) + }) + }) - // when - b := newCreateSpacePayload(&name, &newDescription) - b.Data.Attributes.Name = &name - b.Data.Attributes.Description = &newDescription - test.CreateSpaceConflict(t, svc.Context, svc, ctrl, b) + t.Run("auth", func(t *testing.T) { + t.Run("400", func(t *testing.T) { + // given + spaceName := uuid.NewV4().String() + p := newCreateSpacePayload(&spaceName, nil) + r := DummyResourceManager{ + httpResponseCode: 400, + } + svc, ctrl := s.SecuredControllerWithDummyResourceManager(testsupport.TestIdentity, r) + // when/then + test.CreateSpaceBadRequest(t, svc.Context, svc, ctrl, p) + }) + + t.Run("returned 401", func(t *testing.T) { + // given + spaceName := uuid.NewV4().String() + p := newCreateSpacePayload(&spaceName, nil) + r := DummyResourceManager{ + httpResponseCode: 401, + } + svc, ctrl := s.SecuredControllerWithDummyResourceManager(testsupport.TestIdentity, r) + // when/then + test.CreateSpaceUnauthorized(t, svc.Context, svc, ctrl, p) + }) + + s.T().Run("500", func(t *testing.T) { + // given + spaceName := uuid.NewV4().String() + p := newCreateSpacePayload(&spaceName, nil) + r := DummyResourceManager{ + httpResponseCode: 500, + } + svc, ctrl := s.SecuredControllerWithDummyResourceManager(testsupport.TestIdentity, r) + // when/then + test.CreateSpaceInternalServerError(t, svc.Context, svc, ctrl, p) + }) + }) }) } diff --git a/design/resources.go b/design/resources.go index 40a215cc08..e40a15f409 100644 --- a/design/resources.go +++ b/design/resources.go @@ -97,6 +97,10 @@ var _ = a.Resource("trackerquery", func() { }) }) +const ( + spaceNamePattern string = `^([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9]$` +) + var nameValidationFunction = func() { a.MaxLength(63) // maximum name length is 63 characters a.MinLength(1) // minimum name length is 1 characters diff --git a/design/spaces.go b/design/spaces.go index f992731e7d..f3f18afada 100644 --- a/design/spaces.go +++ b/design/spaces.go @@ -63,7 +63,7 @@ var spaceOwnedBy = a.Type("SpaceOwnedBy", func() { }) var spaceAttributes = a.Type("SpaceAttributes", func() { - a.Attribute("name", d.String, "Name for the space", nameValidationFunction) + a.Attribute("name", d.String, "Name for the space") // name validation is performed at the controller level, to return a proper JSON-API response a.Attribute("description", d.String, "Description for the space", func() { a.Example("This is the foobar collaboration space") }) diff --git a/errors/errors.go b/errors/errors.go index 7518667df4..b9a8fa299a 100644 --- a/errors/errors.go +++ b/errors/errors.go @@ -179,8 +179,8 @@ func (err BadParameterError) Error() string { } // Expected sets the optional expectedValue parameter on the BadParameterError -func (err BadParameterError) Expected(expexcted interface{}) BadParameterError { - err.expectedValue = expexcted +func (err BadParameterError) Expected(expected interface{}) BadParameterError { + err.expectedValue = expected err.hasExpectedValue = true return err }