Skip to content

Commit

Permalink
add test
Browse files Browse the repository at this point in the history
Signed-off-by: myan <[email protected]>
  • Loading branch information
yanmxa committed Jul 4, 2024
1 parent b0fa117 commit b1c649f
Show file tree
Hide file tree
Showing 8 changed files with 159 additions and 13 deletions.
1 change: 1 addition & 0 deletions cmd/maestro/environments/service_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func NewConsumerServiceLocator(env *Env) ConsumerServiceLocator {
return services.NewConsumerService(
db.NewAdvisoryLockFactory(env.Database.SessionFactory),
dao.NewConsumerDao(&env.Database.SessionFactory),
dao.NewResourceDao(&env.Database.SessionFactory),
env.Services.Events(),
)
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/maestro/server/routes.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func (s *apiServer) routes() *mux.Router {
}

resourceHandler := handlers.NewResourceHandler(services.Resources(), services.Generic())
consumerHandler := handlers.NewConsumerHandler(services.Consumers(), services.Generic())
consumerHandler := handlers.NewConsumerHandler(services.Consumers(), services.Resources(), services.Generic())
errorsHandler := handlers.NewErrorsHandler()

var authMiddleware auth.JWTMiddleware
Expand Down
4 changes: 4 additions & 0 deletions pkg/dao/mocks/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,7 @@ func (d *resourceDaoMock) FindBySource(ctx context.Context, source string) (api.
func (d *resourceDaoMock) All(ctx context.Context) (api.ResourceList, error) {
return d.resources, nil
}

func (d *resourceDaoMock) FirstByConsumerName(ctx context.Context, consumerName string) (api.Resource, error) {
return *d.resources[0], errors.NotImplemented("Resource").AsError()
}
8 changes: 8 additions & 0 deletions pkg/dao/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ type ResourceDao interface {
FindBySource(ctx context.Context, source string) (api.ResourceList, error)
FindByConsumerName(ctx context.Context, consumerName string) (api.ResourceList, error)
All(ctx context.Context) (api.ResourceList, error)
FirstByConsumerName(ctx context.Context, name string) (api.Resource, error)
}

var _ ResourceDao = &sqlResourceDao{}
Expand Down Expand Up @@ -115,3 +116,10 @@ func (d *sqlResourceDao) All(ctx context.Context) (api.ResourceList, error) {
}
return resources, nil
}

func (d *sqlResourceDao) FirstByConsumerName(ctx context.Context, consumerName string) (api.Resource, error) {
g2 := (*d.sessionFactory).New(ctx)
resource := api.Resource{}
err := g2.Where("consumer_name = ?", consumerName).First(&resource).Error
return resource, err
}
4 changes: 3 additions & 1 deletion pkg/handlers/consumer.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,14 @@ var _ RestHandler = consumerHandler{}

type consumerHandler struct {
consumer services.ConsumerService
resource services.ResourceService
generic services.GenericService
}

func NewConsumerHandler(consumer services.ConsumerService, generic services.GenericService) *consumerHandler {
func NewConsumerHandler(consumer services.ConsumerService, resource services.ResourceService, generic services.GenericService) *consumerHandler {
return &consumerHandler{
consumer: consumer,
resource: resource,
generic: generic,
}
}
Expand Down
19 changes: 18 additions & 1 deletion pkg/services/consumer.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/openshift-online/maestro/pkg/dao"
"github.com/openshift-online/maestro/pkg/db"
"gorm.io/gorm"

"github.com/openshift-online/maestro/pkg/api"
"github.com/openshift-online/maestro/pkg/errors"
Expand All @@ -20,16 +21,18 @@ type ConsumerService interface {
FindByIDs(ctx context.Context, ids []string) (api.ConsumerList, *errors.ServiceError)
}

func NewConsumerService(lockFactory db.LockFactory, consumerDao dao.ConsumerDao, events EventService) ConsumerService {
func NewConsumerService(lockFactory db.LockFactory, consumerDao dao.ConsumerDao, resourceDao dao.ResourceDao, events EventService) ConsumerService {
return &sqlConsumerService{
consumerDao: consumerDao,
resourceDao: resourceDao,
}
}

var _ ConsumerService = &sqlConsumerService{}

type sqlConsumerService struct {
consumerDao dao.ConsumerDao
resourceDao dao.ResourceDao
}

func (s *sqlConsumerService) Get(ctx context.Context, id string) (*api.Consumer, *errors.ServiceError) {
Expand Down Expand Up @@ -63,6 +66,20 @@ func (s *sqlConsumerService) Replace(ctx context.Context, consumer *api.Consumer
}

func (s *sqlConsumerService) Delete(ctx context.Context, id string) *errors.ServiceError {
consumer, err := s.Get(ctx, id)
if err != nil {
return err
}
_, e := s.resourceDao.FirstByConsumerName(ctx, consumer.Name)
if e == nil {
return errors.Forbidden("Resources associated with the consumer: %s", consumer.Name)
}

if e != gorm.ErrRecordNotFound {
return handleGetError("Resource", "consumer_name", consumer.Name, e)
}

// e is record not found
if err := s.consumerDao.Delete(ctx, id); err != nil {
return handleDeleteError("Consumer", errors.GeneralError("Unable to delete consumer: %s", err))
}
Expand Down
62 changes: 52 additions & 10 deletions test/e2e/pkg/consumer_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package e2e_test

import (
"fmt"
"net/http"
"reflect"

Expand All @@ -11,25 +12,42 @@ import (

// go test -v ./test/e2e/pkg -args -api-server=$api_server -consumer-name=$consumer_name -consumer-kubeconfig=$consumer_kubeconfig -ginkgo.focus "Consumer"
var _ = Describe("Consumer", Ordered, func() {
var testConsumerName string
var testConsumerID string
var consumer openapi.Consumer
var resourceConsumer openapi.Consumer
var resource openapi.Resource
BeforeAll(func() {
testConsumerName = "test-consumer"
consumer = openapi.Consumer{Name: openapi.PtrString("linda")}
resourceConsumer = openapi.Consumer{Name: openapi.PtrString("susan")}
resource = helper.NewAPIResource(*resourceConsumer.Name, 1)
})

Context("Consumer CRUD Tests", func() {
It("create consumer", func() {
consumer := openapi.Consumer{Name: &testConsumerName}
// create a consumser without resource
created, resp, err := apiClient.DefaultApi.ApiMaestroV1ConsumersPost(ctx).Consumer(consumer).Execute()
Expect(err).To(Succeed())
Expect(resp.StatusCode).To(Equal(http.StatusCreated))
Expect(*created.Id).NotTo(BeEmpty())
testConsumerID = *created.Id
consumer = *created

got, resp, err := apiClient.DefaultApi.ApiMaestroV1ConsumersIdGet(ctx, testConsumerID).Execute()
got, resp, err := apiClient.DefaultApi.ApiMaestroV1ConsumersIdGet(ctx, *consumer.Id).Execute()
Expect(err).To(Succeed())
Expect(resp.StatusCode).To(Equal(http.StatusOK))
Expect(got).NotTo(BeNil())

// create a consumser associates with resource
created, resp, err = apiClient.DefaultApi.ApiMaestroV1ConsumersPost(ctx).Consumer(resourceConsumer).Execute()
Expect(err).To(Succeed())
Expect(resp.StatusCode).To(Equal(http.StatusCreated))
Expect(*created.Id).NotTo(BeEmpty())
resourceConsumer = *created

res, resp, err := apiClient.DefaultApi.ApiMaestroV1ResourcesPost(ctx).Resource(resource).Execute()
Expect(err).ShouldNot(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusCreated))
Expect(*res.Id).ShouldNot(BeEmpty())
Expect(*res.Version).To(Equal(int32(1)))
resource = *res
})

It("list consumer", func() {
Expand All @@ -41,7 +59,8 @@ var _ = Describe("Consumer", Ordered, func() {

got := false
for _, c := range consumerList.Items {
if *c.Name == testConsumerName {
fmt.Println("got the consumer:", c.Name)
if *c.Name == *consumer.Name {
got = true
}
}
Expand All @@ -50,14 +69,14 @@ var _ = Describe("Consumer", Ordered, func() {

It("patch consumer", func() {
labels := &map[string]string{"hello": "world"}
patched, resp, err := apiClient.DefaultApi.ApiMaestroV1ConsumersIdPatch(ctx, testConsumerID).
patched, resp, err := apiClient.DefaultApi.ApiMaestroV1ConsumersIdPatch(ctx, *consumer.Id).
ConsumerPatchRequest(openapi.ConsumerPatchRequest{Labels: labels}).Execute()
Expect(err).To(Succeed())
Expect(resp.StatusCode).To(Equal(http.StatusOK))
_, ok := patched.GetLabelsOk()
Expect(ok).To(BeTrue())

got, resp, err := apiClient.DefaultApi.ApiMaestroV1ConsumersIdGet(ctx, testConsumerID).Execute()
got, resp, err := apiClient.DefaultApi.ApiMaestroV1ConsumersIdGet(ctx, *consumer.Id).Execute()
Expect(err).To(Succeed())
Expect(resp.StatusCode).To(Equal(http.StatusOK))
Expect(got).NotTo(BeNil())
Expand All @@ -66,7 +85,30 @@ var _ = Describe("Consumer", Ordered, func() {
})

AfterAll(func() {
// TODO: add the consumer deletion
// delete the consumer
resp, err := apiClient.DefaultApi.ApiMaestroV1ConsumersIdDelete(ctx, *consumer.Id).Execute()
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusNoContent))

_, resp, err = apiClient.DefaultApi.ApiMaestroV1ConsumersIdGet(ctx, *consumer.Id).Execute()
Expect(err.Error()).To(ContainSubstring("Not Found"))
Expect(resp.StatusCode).To(Equal(http.StatusNotFound))

// delete the consumer associated with resource
// 403 forbid deletion
resp, err = apiClient.DefaultApi.ApiMaestroV1ConsumersIdDelete(ctx, *resourceConsumer.Id).Execute()
Expect(err).To(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusForbidden))

// delete the resource
resp, err = apiClient.DefaultApi.ApiMaestroV1ResourcesIdDelete(ctx, *resource.Id).Execute()
Expect(err).To(Succeed())
Expect(resp.StatusCode).To(Equal(http.StatusNoContent))

// delete the consumer
resp, err = apiClient.DefaultApi.ApiMaestroV1ConsumersIdDelete(ctx, *consumer.Id).Execute()
Expect(err).To(Succeed())
Expect(resp.StatusCode).To(Equal(http.StatusNoContent))
})
})
})
72 changes: 72 additions & 0 deletions test/integration/consumers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,78 @@ func TestConsumerPatch(t *testing.T) {
Expect(restyResp.StatusCode()).To(Equal(http.StatusBadRequest))
}

func TestConsumerDelete(t *testing.T) {
h, client := test.RegisterIntegration(t)
account := h.NewRandAccount()
ctx := h.NewAuthenticatedContext(account)

// POST responses per openapi spec: 201, 409, 500
c := openapi.Consumer{
Name: openapi.PtrString("bazqux"),
}

// 201 Created
consumer, resp, err := client.DefaultApi.ApiMaestroV1ConsumersPost(ctx).Consumer(c).Execute()
Expect(err).NotTo(HaveOccurred(), "Error posting object: %v", err)
Expect(resp.StatusCode).To(Equal(http.StatusCreated))
Expect(*consumer.Id).NotTo(BeEmpty(), "Expected ID assigned on creation")

// 200 Got
got, resp, err := client.DefaultApi.ApiMaestroV1ConsumersIdGet(ctx, *consumer.Id).Execute()
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusOK))
Expect(*got.Id).To(Equal(*consumer.Id))
Expect(*got.Name).To(Equal(*consumer.Name))

// 204 Deleted
resp, err = client.DefaultApi.ApiMaestroV1ConsumersIdDelete(ctx, *consumer.Id).Execute()
Expect(err).NotTo(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusNoContent))

// 404 Not Found
_, resp, err = client.DefaultApi.ApiMaestroV1ConsumersIdGet(ctx, *consumer.Id).Execute()
Expect(err.Error()).To(ContainSubstring("Not Found"))
Expect(resp.StatusCode).To(Equal(http.StatusNotFound))
}

func TestConsumerDeleteForbidden(t *testing.T) {
h, client := test.RegisterIntegration(t)
account := h.NewRandAccount()
ctx := h.NewAuthenticatedContext(account)

// create a consumser
c := openapi.Consumer{
Name: openapi.PtrString("jamie"),
}
consumer, resp, err := client.DefaultApi.ApiMaestroV1ConsumersPost(ctx).Consumer(c).Execute()
Expect(err).To(Succeed())
Expect(resp.StatusCode).To(Equal(http.StatusCreated))
Expect(*consumer.Id).NotTo(BeEmpty())

// attach resource to the consumer
res := h.NewAPIResource(*consumer.Name, 1)
resource, resp, err := client.DefaultApi.ApiMaestroV1ResourcesPost(ctx).Resource(res).Execute()
Expect(err).To(Succeed())
Expect(resp.StatusCode).To(Equal(http.StatusCreated))
Expect(*resource.Id).ShouldNot(BeEmpty())
Expect(*resource.Version).To(Equal(int32(1)))

// 403 forbid deletion
resp, err = client.DefaultApi.ApiMaestroV1ConsumersIdDelete(ctx, *consumer.Id).Execute()
Expect(err).To(HaveOccurred())
Expect(resp.StatusCode).To(Equal(http.StatusForbidden))

// delete the resource
resp, err = client.DefaultApi.ApiMaestroV1ResourcesIdDelete(ctx, *resource.Id).Execute()
Expect(err).To(Succeed())
Expect(resp.StatusCode).To(Equal(http.StatusNoContent))

// delete the consumer
resp, err = client.DefaultApi.ApiMaestroV1ConsumersIdDelete(ctx, *consumer.Id).Execute()
Expect(err).To(Succeed())
Expect(resp.StatusCode).To(Equal(http.StatusNoContent))
}

func TestConsumerPaging(t *testing.T) {
h, client := test.RegisterIntegration(t)

Expand Down

0 comments on commit b1c649f

Please sign in to comment.