Remove duplicate code

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This commit is contained in:
Gabriel Adrian Samfira 2024-03-29 18:18:29 +00:00
parent 9384e37bb1
commit f9f545f060
18 changed files with 487 additions and 1245 deletions

View file

@ -5,7 +5,6 @@ import (
"github.com/google/uuid"
"github.com/pkg/errors"
"gorm.io/datatypes"
"gorm.io/gorm"
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
@ -134,137 +133,6 @@ func (s *sqlDatabase) UpdateEnterprise(ctx context.Context, enterpriseID string,
return newParams, nil
}
func (s *sqlDatabase) CreateEnterprisePool(ctx context.Context, enterpriseID string, param params.CreatePoolParams) (params.Pool, error) {
if len(param.Tags) == 0 {
return params.Pool{}, runnerErrors.NewBadRequestError("no tags specified")
}
enterprise, err := s.getEnterpriseByID(ctx, enterpriseID)
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching enterprise")
}
newPool := Pool{
ProviderName: param.ProviderName,
MaxRunners: param.MaxRunners,
MinIdleRunners: param.MinIdleRunners,
RunnerPrefix: param.GetRunnerPrefix(),
Image: param.Image,
Flavor: param.Flavor,
OSType: param.OSType,
OSArch: param.OSArch,
EnterpriseID: &enterprise.ID,
Enabled: param.Enabled,
RunnerBootstrapTimeout: param.RunnerBootstrapTimeout,
GitHubRunnerGroup: param.GitHubRunnerGroup,
Priority: param.Priority,
}
if len(param.ExtraSpecs) > 0 {
newPool.ExtraSpecs = datatypes.JSON(param.ExtraSpecs)
}
_, err = s.getEnterprisePoolByUniqueFields(ctx, enterpriseID, newPool.ProviderName, newPool.Image, newPool.Flavor)
if err != nil {
if !errors.Is(err, runnerErrors.ErrNotFound) {
return params.Pool{}, errors.Wrap(err, "creating pool")
}
} else {
return params.Pool{}, runnerErrors.NewConflictError("pool with the same image and flavor already exists on this provider")
}
tags := []Tag{}
for _, val := range param.Tags {
t, err := s.getOrCreateTag(s.conn, val)
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching tag")
}
tags = append(tags, t)
}
q := s.conn.Create(&newPool)
if q.Error != nil {
return params.Pool{}, errors.Wrap(q.Error, "adding pool")
}
for i := range tags {
if err := s.conn.Model(&newPool).Association("Tags").Append(&tags[i]); err != nil {
return params.Pool{}, errors.Wrap(err, "saving tag")
}
}
pool, err := s.getPoolByID(s.conn, newPool.ID.String(), "Tags", "Instances", "Enterprise", "Organization", "Repository")
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching pool")
}
return s.sqlToCommonPool(pool)
}
func (s *sqlDatabase) GetEnterprisePool(_ context.Context, enterpriseID, poolID string) (params.Pool, error) {
pool, err := s.getEntityPool(s.conn, params.GithubEntityTypeEnterprise, enterpriseID, poolID, "Tags", "Instances")
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching pool")
}
return s.sqlToCommonPool(pool)
}
func (s *sqlDatabase) DeleteEnterprisePool(_ context.Context, enterpriseID, poolID string) error {
pool, err := s.getEntityPool(s.conn, params.GithubEntityTypeEnterprise, enterpriseID, poolID)
if err != nil {
return errors.Wrap(err, "looking up enterprise pool")
}
q := s.conn.Unscoped().Delete(&pool)
if q.Error != nil && !errors.Is(q.Error, gorm.ErrRecordNotFound) {
return errors.Wrap(q.Error, "deleting pool")
}
return nil
}
func (s *sqlDatabase) UpdateEnterprisePool(_ context.Context, enterpriseID, poolID string, param params.UpdatePoolParams) (params.Pool, error) {
pool, err := s.getEntityPool(s.conn, params.GithubEntityTypeEnterprise, enterpriseID, poolID, "Tags", "Instances", "Enterprise", "Organization", "Repository")
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching pool")
}
return s.updatePool(s.conn, pool, param)
}
func (s *sqlDatabase) ListEnterprisePools(ctx context.Context, enterpriseID string) ([]params.Pool, error) {
pools, err := s.listEntityPools(ctx, params.GithubEntityTypeEnterprise, enterpriseID, "Tags", "Instances", "Enterprise")
if err != nil {
return nil, errors.Wrap(err, "fetching pools")
}
ret := make([]params.Pool, len(pools))
for idx, pool := range pools {
ret[idx], err = s.sqlToCommonPool(pool)
if err != nil {
return nil, errors.Wrap(err, "fetching pools")
}
}
return ret, nil
}
func (s *sqlDatabase) ListEnterpriseInstances(ctx context.Context, enterpriseID string) ([]params.Instance, error) {
pools, err := s.listEntityPools(ctx, params.GithubEntityTypeEnterprise, enterpriseID, "Instances", "Tags", "Instances.Job")
if err != nil {
return nil, errors.Wrap(err, "fetching enterprise")
}
ret := []params.Instance{}
for _, pool := range pools {
for _, instance := range pool.Instances {
paramsInstance, err := s.sqlToParamsInstance(instance)
if err != nil {
return nil, errors.Wrap(err, "fetching instance")
}
ret = append(ret, paramsInstance)
}
}
return ret, nil
}
func (s *sqlDatabase) getEnterprise(_ context.Context, name string) (Enterprise, error) {
var enterprise Enterprise
@ -302,22 +170,3 @@ func (s *sqlDatabase) getEnterpriseByID(_ context.Context, id string, preload ..
}
return enterprise, nil
}
func (s *sqlDatabase) getEnterprisePoolByUniqueFields(ctx context.Context, enterpriseID string, provider, image, flavor string) (Pool, error) {
enterprise, err := s.getEnterpriseByID(ctx, enterpriseID)
if err != nil {
return Pool{}, errors.Wrap(err, "fetching enterprise")
}
q := s.conn
var pool []Pool
err = q.Model(&enterprise).Association("Pools").Find(&pool, "provider_name = ? and image = ? and flavor = ?", provider, image, flavor)
if err != nil {
return Pool{}, errors.Wrap(err, "fetching pool")
}
if len(pool) == 0 {
return Pool{}, runnerErrors.ErrNotFound
}
return pool[0], nil
}

View file

@ -405,10 +405,8 @@ func (s *EnterpriseTestSuite) TestGetEnterpriseByIDDBDecryptingErr() {
}
func (s *EnterpriseTestSuite) TestCreateEnterprisePool() {
entity := params.GithubEntity{
ID: s.Fixtures.Enterprises[0].ID,
EntityType: params.GithubEntityTypeEnterprise,
}
entity, err := s.Fixtures.Enterprises[0].GetEntity()
s.Require().Nil(err)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.Require().Nil(err)
@ -426,11 +424,9 @@ func (s *EnterpriseTestSuite) TestCreateEnterprisePool() {
func (s *EnterpriseTestSuite) TestCreateEnterprisePoolMissingTags() {
s.Fixtures.CreatePoolParams.Tags = []string{}
entity := params.GithubEntity{
ID: s.Fixtures.Enterprises[0].ID,
EntityType: params.GithubEntityTypeEnterprise,
}
_, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Enterprises[0].GetEntity()
s.Require().Nil(err)
_, err = s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.Require().NotNil(err)
s.Require().Equal("no tags specified", err.Error())
@ -448,41 +444,37 @@ func (s *EnterpriseTestSuite) TestCreateEnterprisePoolInvalidEnterpriseID() {
}
func (s *EnterpriseTestSuite) TestCreateEnterprisePoolDBCreateErr() {
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `enterprises` WHERE id = ? AND `enterprises`.`deleted_at` IS NULL ORDER BY `enterprises`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Enterprises[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Enterprises[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `enterprises` WHERE id = ? AND `enterprises`.`deleted_at` IS NULL ORDER BY `enterprises`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Enterprises[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Enterprises[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE `pools`.`enterprise_id` = ? AND (provider_name = ? and image = ? and flavor = ?) AND `pools`.`deleted_at` IS NULL")).
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (provider_name = ? and image = ? and flavor = ? and enterprise_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WillReturnError(fmt.Errorf("mocked creating pool error"))
_, err := s.StoreSQLMocked.CreateEnterprisePool(context.Background(), s.Fixtures.Enterprises[0].ID, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Enterprises[0].GetEntity()
s.Require().Nil(err)
_, err = s.StoreSQLMocked.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.assertSQLMockExpectations()
s.Require().NotNil(err)
s.Require().Equal("creating pool: fetching pool: mocked creating pool error", err.Error())
s.Require().Equal("checking pool existence: mocked creating pool error", err.Error())
s.assertSQLMockExpectations()
}
func (s *EnterpriseTestSuite) TestCreateEnterpriseDBPoolAlreadyExistErr() {
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `enterprises` WHERE id = ? AND `enterprises`.`deleted_at` IS NULL ORDER BY `enterprises`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Enterprises[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Enterprises[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `enterprises` WHERE id = ? AND `enterprises`.`deleted_at` IS NULL ORDER BY `enterprises`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Enterprises[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Enterprises[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE `pools`.`enterprise_id` = ? AND (provider_name = ? and image = ? and flavor = ?) AND `pools`.`deleted_at` IS NULL")).
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (provider_name = ? and image = ? and flavor = ? and enterprise_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WithArgs(
s.Fixtures.Enterprises[0].ID,
s.Fixtures.CreatePoolParams.ProviderName,
s.Fixtures.CreatePoolParams.Image,
s.Fixtures.CreatePoolParams.Flavor).
s.Fixtures.CreatePoolParams.Flavor,
s.Fixtures.Enterprises[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"enterprise_id", "provider_name", "image", "flavor"}).
AddRow(
s.Fixtures.Enterprises[0].ID,
@ -490,159 +482,141 @@ func (s *EnterpriseTestSuite) TestCreateEnterpriseDBPoolAlreadyExistErr() {
s.Fixtures.CreatePoolParams.Image,
s.Fixtures.CreatePoolParams.Flavor))
_, err := s.StoreSQLMocked.CreateEnterprisePool(context.Background(), s.Fixtures.Enterprises[0].ID, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Enterprises[0].GetEntity()
s.Require().Nil(err)
_, err = s.StoreSQLMocked.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.assertSQLMockExpectations()
s.Require().NotNil(err)
s.Require().Equal(runnerErrors.NewConflictError("pool with the same image and flavor already exists on this provider"), err)
s.assertSQLMockExpectations()
}
func (s *EnterpriseTestSuite) TestCreateEnterprisePoolDBFetchTagErr() {
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `enterprises` WHERE id = ? AND `enterprises`.`deleted_at` IS NULL ORDER BY `enterprises`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Enterprises[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Enterprises[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `enterprises` WHERE id = ? AND `enterprises`.`deleted_at` IS NULL ORDER BY `enterprises`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Enterprises[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Enterprises[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE `pools`.`enterprise_id` = ? AND (provider_name = ? and image = ? and flavor = ?) AND `pools`.`deleted_at` IS NULL")).
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (provider_name = ? and image = ? and flavor = ? and enterprise_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WithArgs(
s.Fixtures.Enterprises[0].ID,
s.Fixtures.CreatePoolParams.ProviderName,
s.Fixtures.CreatePoolParams.Image,
s.Fixtures.CreatePoolParams.Flavor).
s.Fixtures.CreatePoolParams.Flavor,
s.Fixtures.Enterprises[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"enterprise_id"}))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `tags` WHERE name = ? AND `tags`.`deleted_at` IS NULL ORDER BY `tags`.`id` LIMIT 1")).
WillReturnError(fmt.Errorf("mocked fetching tag error"))
_, err := s.StoreSQLMocked.CreateEnterprisePool(context.Background(), s.Fixtures.Enterprises[0].ID, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Enterprises[0].GetEntity()
s.Require().Nil(err)
_, err = s.StoreSQLMocked.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.assertSQLMockExpectations()
s.Require().NotNil(err)
s.Require().Equal("fetching tag: fetching tag from database: mocked fetching tag error", err.Error())
s.Require().Equal("creating tag: fetching tag from database: mocked fetching tag error", err.Error())
s.assertSQLMockExpectations()
}
func (s *EnterpriseTestSuite) TestCreateEnterprisePoolDBAddingPoolErr() {
s.Fixtures.CreatePoolParams.Tags = []string{"linux"}
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `enterprises` WHERE id = ? AND `enterprises`.`deleted_at` IS NULL ORDER BY `enterprises`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Enterprises[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Enterprises[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `enterprises` WHERE id = ? AND `enterprises`.`deleted_at` IS NULL ORDER BY `enterprises`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Enterprises[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Enterprises[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE `pools`.`enterprise_id` = ? AND (provider_name = ? and image = ? and flavor = ?) AND `pools`.`deleted_at` IS NULL")).
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (provider_name = ? and image = ? and flavor = ? and enterprise_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WithArgs(
s.Fixtures.Enterprises[0].ID,
s.Fixtures.CreatePoolParams.ProviderName,
s.Fixtures.CreatePoolParams.Image,
s.Fixtures.CreatePoolParams.Flavor).
s.Fixtures.CreatePoolParams.Flavor,
s.Fixtures.Enterprises[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"enterprise_id"}))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `tags` WHERE name = ? AND `tags`.`deleted_at` IS NULL ORDER BY `tags`.`id` LIMIT 1")).
WillReturnRows(sqlmock.NewRows([]string{"linux"}))
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("INSERT INTO `tags`")).
WillReturnResult(sqlmock.NewResult(1, 1))
s.Fixtures.SQLMock.ExpectCommit()
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("INSERT INTO `pools`")).
WillReturnError(fmt.Errorf("mocked adding pool error"))
s.Fixtures.SQLMock.ExpectRollback()
_, err := s.StoreSQLMocked.CreateEnterprisePool(context.Background(), s.Fixtures.Enterprises[0].ID, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Enterprises[0].GetEntity()
s.Require().Nil(err)
_, err = s.StoreSQLMocked.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.assertSQLMockExpectations()
s.Require().NotNil(err)
s.Require().Equal("adding pool: mocked adding pool error", err.Error())
s.Require().Equal("creating pool: mocked adding pool error", err.Error())
s.assertSQLMockExpectations()
}
func (s *EnterpriseTestSuite) TestCreateEnterprisePoolDBSaveTagErr() {
s.Fixtures.CreatePoolParams.Tags = []string{"linux"}
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `enterprises` WHERE id = ? AND `enterprises`.`deleted_at` IS NULL ORDER BY `enterprises`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Enterprises[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Enterprises[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `enterprises` WHERE id = ? AND `enterprises`.`deleted_at` IS NULL ORDER BY `enterprises`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Enterprises[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Enterprises[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE `pools`.`enterprise_id` = ? AND (provider_name = ? and image = ? and flavor = ?) AND `pools`.`deleted_at` IS NULL")).
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (provider_name = ? and image = ? and flavor = ? and enterprise_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WithArgs(
s.Fixtures.Enterprises[0].ID,
s.Fixtures.CreatePoolParams.ProviderName,
s.Fixtures.CreatePoolParams.Image,
s.Fixtures.CreatePoolParams.Flavor).
s.Fixtures.CreatePoolParams.Flavor,
s.Fixtures.Enterprises[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"enterprise_id"}))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `tags` WHERE name = ? AND `tags`.`deleted_at` IS NULL ORDER BY `tags`.`id` LIMIT 1")).
WillReturnRows(sqlmock.NewRows([]string{"linux"}))
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("INSERT INTO `tags`")).
WillReturnResult(sqlmock.NewResult(1, 1))
s.Fixtures.SQLMock.ExpectCommit()
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("INSERT INTO `pools`")).
WillReturnResult(sqlmock.NewResult(1, 1))
s.Fixtures.SQLMock.ExpectCommit()
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("UPDATE `pools` SET")).
WillReturnError(fmt.Errorf("mocked saving tag error"))
s.Fixtures.SQLMock.ExpectRollback()
_, err := s.StoreSQLMocked.CreateEnterprisePool(context.Background(), s.Fixtures.Enterprises[0].ID, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Enterprises[0].GetEntity()
s.Require().Nil(err)
_, err = s.StoreSQLMocked.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.assertSQLMockExpectations()
s.Require().NotNil(err)
s.Require().Equal("saving tag: mocked saving tag error", err.Error())
s.Require().Equal("associating tags: mocked saving tag error", err.Error())
s.assertSQLMockExpectations()
}
func (s *EnterpriseTestSuite) TestCreateEnterprisePoolDBFetchPoolErr() {
s.Fixtures.CreatePoolParams.Tags = []string{"linux"}
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `enterprises` WHERE id = ? AND `enterprises`.`deleted_at` IS NULL ORDER BY `enterprises`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Enterprises[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Enterprises[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `enterprises` WHERE id = ? AND `enterprises`.`deleted_at` IS NULL ORDER BY `enterprises`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Enterprises[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Enterprises[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE `pools`.`enterprise_id` = ? AND (provider_name = ? and image = ? and flavor = ?) AND `pools`.`deleted_at` IS NULL")).
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (provider_name = ? and image = ? and flavor = ? and enterprise_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WithArgs(
s.Fixtures.Enterprises[0].ID,
s.Fixtures.CreatePoolParams.ProviderName,
s.Fixtures.CreatePoolParams.Image,
s.Fixtures.CreatePoolParams.Flavor).
s.Fixtures.CreatePoolParams.Flavor,
s.Fixtures.Enterprises[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"enterprise_id"}))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `tags` WHERE name = ? AND `tags`.`deleted_at` IS NULL ORDER BY `tags`.`id` LIMIT 1")).
WillReturnRows(sqlmock.NewRows([]string{"linux"}))
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("INSERT INTO `tags`")).
WillReturnResult(sqlmock.NewResult(1, 1))
s.Fixtures.SQLMock.ExpectCommit()
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("INSERT INTO `pools`")).
WillReturnResult(sqlmock.NewResult(1, 1))
s.Fixtures.SQLMock.ExpectCommit()
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("UPDATE `pools` SET")).
WillReturnResult(sqlmock.NewResult(1, 1))
@ -657,19 +631,19 @@ func (s *EnterpriseTestSuite) TestCreateEnterprisePoolDBFetchPoolErr() {
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE id = ? AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WillReturnRows(sqlmock.NewRows([]string{"id"}))
_, err := s.StoreSQLMocked.CreateEnterprisePool(context.Background(), s.Fixtures.Enterprises[0].ID, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Enterprises[0].GetEntity()
s.Require().Nil(err)
_, err = s.StoreSQLMocked.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.assertSQLMockExpectations()
s.Require().NotNil(err)
s.Require().Equal("fetching pool: not found", err.Error())
s.assertSQLMockExpectations()
}
func (s *EnterpriseTestSuite) TestListEnterprisePools() {
enterprisePools := []params.Pool{}
entity := params.GithubEntity{
ID: s.Fixtures.Enterprises[0].ID,
EntityType: params.GithubEntityTypeEnterprise,
}
entity, err := s.Fixtures.Enterprises[0].GetEntity()
s.Require().Nil(err)
for i := 1; i <= 2; i++ {
s.Fixtures.CreatePoolParams.Flavor = fmt.Sprintf("test-flavor-%v", i)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
@ -679,24 +653,26 @@ func (s *EnterpriseTestSuite) TestListEnterprisePools() {
enterprisePools = append(enterprisePools, pool)
}
pools, err := s.Store.ListEnterprisePools(context.Background(), s.Fixtures.Enterprises[0].ID)
pools, err := s.Store.ListEntityPools(context.Background(), entity)
s.Require().Nil(err)
garmTesting.EqualDBEntityID(s.T(), enterprisePools, pools)
}
func (s *EnterpriseTestSuite) TestListEnterprisePoolsInvalidEnterpriseID() {
_, err := s.Store.ListEnterprisePools(context.Background(), "dummy-enterprise-id")
entity := params.GithubEntity{
ID: "dummy-enterprise-id",
EntityType: params.GithubEntityTypeEnterprise,
}
_, err := s.Store.ListEntityPools(context.Background(), entity)
s.Require().NotNil(err)
s.Require().Equal("fetching pools: parsing id: invalid request", err.Error())
}
func (s *EnterpriseTestSuite) TestGetEnterprisePool() {
entity := params.GithubEntity{
ID: s.Fixtures.Enterprises[0].ID,
EntityType: params.GithubEntityTypeEnterprise,
}
entity, err := s.Fixtures.Enterprises[0].GetEntity()
s.Require().Nil(err)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
if err != nil {
s.FailNow(fmt.Sprintf("cannot create enterprise pool: %v", err))
@ -720,10 +696,8 @@ func (s *EnterpriseTestSuite) TestGetEnterprisePoolInvalidEnterpriseID() {
}
func (s *EnterpriseTestSuite) TestDeleteEnterprisePool() {
entity := params.GithubEntity{
ID: s.Fixtures.Enterprises[0].ID,
EntityType: params.GithubEntityTypeEnterprise,
}
entity, err := s.Fixtures.Enterprises[0].GetEntity()
s.Require().Nil(err)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
if err != nil {
s.FailNow(fmt.Sprintf("cannot create enterprise pool: %v", err))
@ -748,38 +722,29 @@ func (s *EnterpriseTestSuite) TestDeleteEnterprisePoolInvalidEnterpriseID() {
}
func (s *EnterpriseTestSuite) TestDeleteEnterprisePoolDBDeleteErr() {
entity := params.GithubEntity{
ID: s.Fixtures.Enterprises[0].ID,
EntityType: params.GithubEntityTypeEnterprise,
}
entity, err := s.Fixtures.Enterprises[0].GetEntity()
s.Require().Nil(err)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
if err != nil {
s.FailNow(fmt.Sprintf("cannot create enterprise pool: %v", err))
}
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (id = ? and enterprise_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WithArgs(pool.ID, s.Fixtures.Enterprises[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"enterprise_id", "id"}).AddRow(s.Fixtures.Enterprises[0].ID, pool.ID))
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("DELETE FROM `pools` WHERE `pools`.`id` = ?")).
WithArgs(pool.ID).
ExpectExec(regexp.QuoteMeta("DELETE FROM `pools` WHERE id = ? and enterprise_id = ?")).
WithArgs(pool.ID, s.Fixtures.Enterprises[0].ID).
WillReturnError(fmt.Errorf("mocked deleting pool error"))
s.Fixtures.SQLMock.ExpectRollback()
err = s.StoreSQLMocked.DeleteEnterprisePool(context.Background(), s.Fixtures.Enterprises[0].ID, pool.ID)
s.assertSQLMockExpectations()
err = s.StoreSQLMocked.DeleteEntityPool(context.Background(), entity, pool.ID)
s.Require().NotNil(err)
s.Require().Equal("deleting pool: mocked deleting pool error", err.Error())
s.Require().Equal("removing pool: mocked deleting pool error", err.Error())
s.assertSQLMockExpectations()
}
func (s *EnterpriseTestSuite) TestListEnterpriseInstances() {
entity := params.GithubEntity{
ID: s.Fixtures.Enterprises[0].ID,
EntityType: params.GithubEntityTypeEnterprise,
}
entity, err := s.Fixtures.Enterprises[0].GetEntity()
s.Require().Nil(err)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
if err != nil {
s.FailNow(fmt.Sprintf("cannot create enterprise pool: %v", err))
@ -794,30 +759,32 @@ func (s *EnterpriseTestSuite) TestListEnterpriseInstances() {
poolInstances = append(poolInstances, instance)
}
instances, err := s.Store.ListEnterpriseInstances(context.Background(), s.Fixtures.Enterprises[0].ID)
instances, err := s.Store.ListEntityInstances(context.Background(), entity)
s.Require().Nil(err)
s.equalInstancesByName(poolInstances, instances)
}
func (s *EnterpriseTestSuite) TestListEnterpriseInstancesInvalidEnterpriseID() {
_, err := s.Store.ListEnterpriseInstances(context.Background(), "dummy-enterprise-id")
entity := params.GithubEntity{
ID: "dummy-enterprise-id",
EntityType: params.GithubEntityTypeEnterprise,
}
_, err := s.Store.ListEntityInstances(context.Background(), entity)
s.Require().NotNil(err)
s.Require().Equal("fetching enterprise: parsing id: invalid request", err.Error())
s.Require().Equal("fetching entity: parsing id: invalid request", err.Error())
}
func (s *EnterpriseTestSuite) TestUpdateEnterprisePool() {
entity := params.GithubEntity{
ID: s.Fixtures.Enterprises[0].ID,
EntityType: params.GithubEntityTypeEnterprise,
}
entity, err := s.Fixtures.Enterprises[0].GetEntity()
s.Require().Nil(err)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
if err != nil {
s.FailNow(fmt.Sprintf("cannot create enterprise pool: %v", err))
}
pool, err = s.Store.UpdateEnterprisePool(context.Background(), s.Fixtures.Enterprises[0].ID, pool.ID, s.Fixtures.UpdatePoolParams)
pool, err = s.Store.UpdateEntityPool(context.Background(), entity, pool.ID, s.Fixtures.UpdatePoolParams)
s.Require().Nil(err)
s.Require().Equal(*s.Fixtures.UpdatePoolParams.MaxRunners, pool.MaxRunners)
@ -827,7 +794,11 @@ func (s *EnterpriseTestSuite) TestUpdateEnterprisePool() {
}
func (s *EnterpriseTestSuite) TestUpdateEnterprisePoolInvalidEnterpriseID() {
_, err := s.Store.UpdateEnterprisePool(context.Background(), "dummy-enterprise-id", "dummy-pool-id", s.Fixtures.UpdatePoolParams)
entity := params.GithubEntity{
ID: "dummy-enterprise-id",
EntityType: params.GithubEntityTypeEnterprise,
}
_, err := s.Store.UpdateEntityPool(context.Background(), entity, "dummy-pool-id", s.Fixtures.UpdatePoolParams)
s.Require().NotNil(err)
s.Require().Equal("fetching pool: parsing id: invalid request", err.Error())

View file

@ -92,10 +92,8 @@ func (s *InstancesTestSuite) SetupTest() {
OSType: "linux",
Tags: []string{"self-hosted", "amd64", "linux"},
}
entity := params.GithubEntity{
ID: org.ID,
EntityType: params.GithubEntityTypeOrganization,
}
entity, err := org.GetEntity()
s.Require().Nil(err)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, createPoolParams)
if err != nil {
s.FailNow(fmt.Sprintf("failed to create org pool: %s", err))

View file

@ -20,7 +20,6 @@ import (
"github.com/google/uuid"
"github.com/pkg/errors"
"gorm.io/datatypes"
"gorm.io/gorm"
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
@ -151,137 +150,6 @@ func (s *sqlDatabase) GetOrganizationByID(ctx context.Context, orgID string) (pa
return param, nil
}
func (s *sqlDatabase) CreateOrganizationPool(ctx context.Context, orgID string, param params.CreatePoolParams) (params.Pool, error) {
if len(param.Tags) == 0 {
return params.Pool{}, runnerErrors.NewBadRequestError("no tags specified")
}
org, err := s.getOrgByID(ctx, orgID)
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching org")
}
newPool := Pool{
ProviderName: param.ProviderName,
MaxRunners: param.MaxRunners,
MinIdleRunners: param.MinIdleRunners,
RunnerPrefix: param.GetRunnerPrefix(),
Image: param.Image,
Flavor: param.Flavor,
OSType: param.OSType,
OSArch: param.OSArch,
OrgID: &org.ID,
Enabled: param.Enabled,
RunnerBootstrapTimeout: param.RunnerBootstrapTimeout,
GitHubRunnerGroup: param.GitHubRunnerGroup,
Priority: param.Priority,
}
if len(param.ExtraSpecs) > 0 {
newPool.ExtraSpecs = datatypes.JSON(param.ExtraSpecs)
}
_, err = s.getOrgPoolByUniqueFields(ctx, orgID, newPool.ProviderName, newPool.Image, newPool.Flavor)
if err != nil {
if !errors.Is(err, runnerErrors.ErrNotFound) {
return params.Pool{}, errors.Wrap(err, "creating pool")
}
} else {
return params.Pool{}, runnerErrors.NewConflictError("pool with the same image and flavor already exists on this provider")
}
tags := []Tag{}
for _, val := range param.Tags {
t, err := s.getOrCreateTag(s.conn, val)
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching tag")
}
tags = append(tags, t)
}
q := s.conn.Create(&newPool)
if q.Error != nil {
return params.Pool{}, errors.Wrap(q.Error, "adding pool")
}
for i := range tags {
if err := s.conn.Model(&newPool).Association("Tags").Append(&tags[i]); err != nil {
return params.Pool{}, errors.Wrap(err, "saving tag")
}
}
pool, err := s.getPoolByID(s.conn, newPool.ID.String(), "Tags", "Instances", "Enterprise", "Organization", "Repository")
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching pool")
}
return s.sqlToCommonPool(pool)
}
func (s *sqlDatabase) ListOrgPools(ctx context.Context, orgID string) ([]params.Pool, error) {
pools, err := s.listEntityPools(ctx, params.GithubEntityTypeOrganization, orgID, "Tags", "Instances", "Organization")
if err != nil {
return nil, errors.Wrap(err, "fetching pools")
}
ret := make([]params.Pool, len(pools))
for idx, pool := range pools {
ret[idx], err = s.sqlToCommonPool(pool)
if err != nil {
return nil, errors.Wrap(err, "fetching pool")
}
}
return ret, nil
}
func (s *sqlDatabase) GetOrganizationPool(_ context.Context, orgID, poolID string) (params.Pool, error) {
pool, err := s.getEntityPool(s.conn, params.GithubEntityTypeOrganization, orgID, poolID, "Tags", "Instances")
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching pool")
}
return s.sqlToCommonPool(pool)
}
func (s *sqlDatabase) DeleteOrganizationPool(_ context.Context, orgID, poolID string) error {
pool, err := s.getEntityPool(s.conn, params.GithubEntityTypeOrganization, orgID, poolID)
if err != nil {
return errors.Wrap(err, "looking up org pool")
}
q := s.conn.Unscoped().Delete(&pool)
if q.Error != nil && !errors.Is(q.Error, gorm.ErrRecordNotFound) {
return errors.Wrap(q.Error, "deleting pool")
}
return nil
}
func (s *sqlDatabase) ListOrgInstances(ctx context.Context, orgID string) ([]params.Instance, error) {
pools, err := s.listEntityPools(ctx, params.GithubEntityTypeOrganization, orgID, "Tags", "Instances", "Instances.Job")
if err != nil {
return nil, errors.Wrap(err, "fetching org")
}
ret := []params.Instance{}
for _, pool := range pools {
for _, instance := range pool.Instances {
paramsInstance, err := s.sqlToParamsInstance(instance)
if err != nil {
return nil, errors.Wrap(err, "fetching instance")
}
ret = append(ret, paramsInstance)
}
}
return ret, nil
}
func (s *sqlDatabase) UpdateOrganizationPool(_ context.Context, orgID, poolID string, param params.UpdatePoolParams) (params.Pool, error) {
pool, err := s.getEntityPool(s.conn, params.GithubEntityTypeOrganization, orgID, poolID, "Tags", "Instances", "Enterprise", "Organization", "Repository")
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching pool")
}
return s.updatePool(s.conn, pool, param)
}
func (s *sqlDatabase) getOrgByID(_ context.Context, id string, preload ...string) (Organization, error) {
u, err := uuid.Parse(id)
if err != nil {
@ -319,22 +187,3 @@ func (s *sqlDatabase) getOrg(_ context.Context, name string) (Organization, erro
}
return org, nil
}
func (s *sqlDatabase) getOrgPoolByUniqueFields(ctx context.Context, orgID string, provider, image, flavor string) (Pool, error) {
org, err := s.getOrgByID(ctx, orgID)
if err != nil {
return Pool{}, errors.Wrap(err, "fetching org")
}
q := s.conn
var pool []Pool
err = q.Model(&org).Association("Pools").Find(&pool, "provider_name = ? and image = ? and flavor = ?", provider, image, flavor)
if err != nil {
return Pool{}, errors.Wrap(err, "fetching pool")
}
if len(pool) == 0 {
return Pool{}, runnerErrors.ErrNotFound
}
return pool[0], nil
}

View file

@ -405,10 +405,8 @@ func (s *OrgTestSuite) TestGetOrganizationByIDDBDecryptingErr() {
}
func (s *OrgTestSuite) TestCreateOrganizationPool() {
entity := params.GithubEntity{
ID: s.Fixtures.Orgs[0].ID,
EntityType: params.GithubEntityTypeOrganization,
}
entity, err := s.Fixtures.Orgs[0].GetEntity()
s.Require().Nil(err)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.Require().Nil(err)
@ -426,11 +424,9 @@ func (s *OrgTestSuite) TestCreateOrganizationPool() {
func (s *OrgTestSuite) TestCreateOrganizationPoolMissingTags() {
s.Fixtures.CreatePoolParams.Tags = []string{}
entity := params.GithubEntity{
ID: s.Fixtures.Orgs[0].ID,
EntityType: params.GithubEntityTypeOrganization,
}
_, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Orgs[0].GetEntity()
s.Require().Nil(err)
_, err = s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.Require().NotNil(err)
s.Require().Equal("no tags specified", err.Error())
@ -448,41 +444,37 @@ func (s *OrgTestSuite) TestCreateOrganizationPoolInvalidOrgID() {
}
func (s *OrgTestSuite) TestCreateOrganizationPoolDBCreateErr() {
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `organizations` WHERE id = ? AND `organizations`.`deleted_at` IS NULL ORDER BY `organizations`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Orgs[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Orgs[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `organizations` WHERE id = ? AND `organizations`.`deleted_at` IS NULL ORDER BY `organizations`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Orgs[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Orgs[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE `pools`.`org_id` = ? AND (provider_name = ? and image = ? and flavor = ?) AND `pools`.`deleted_at` IS NULL")).
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (provider_name = ? and image = ? and flavor = ? and org_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WillReturnError(fmt.Errorf("mocked creating pool error"))
_, err := s.StoreSQLMocked.CreateOrganizationPool(context.Background(), s.Fixtures.Orgs[0].ID, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Orgs[0].GetEntity()
s.Require().Nil(err)
_, err = s.StoreSQLMocked.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.assertSQLMockExpectations()
s.Require().NotNil(err)
s.Require().Equal("creating pool: fetching pool: mocked creating pool error", err.Error())
s.Require().Equal("checking pool existence: mocked creating pool error", err.Error())
s.assertSQLMockExpectations()
}
func (s *OrgTestSuite) TestCreateOrganizationDBPoolAlreadyExistErr() {
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `organizations` WHERE id = ? AND `organizations`.`deleted_at` IS NULL ORDER BY `organizations`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Orgs[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Orgs[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `organizations` WHERE id = ? AND `organizations`.`deleted_at` IS NULL ORDER BY `organizations`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Orgs[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Orgs[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE `pools`.`org_id` = ? AND (provider_name = ? and image = ? and flavor = ?) AND `pools`.`deleted_at` IS NULL")).
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (provider_name = ? and image = ? and flavor = ? and org_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WithArgs(
s.Fixtures.Orgs[0].ID,
s.Fixtures.CreatePoolParams.ProviderName,
s.Fixtures.CreatePoolParams.Image,
s.Fixtures.CreatePoolParams.Flavor).
s.Fixtures.CreatePoolParams.Flavor,
s.Fixtures.Orgs[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"org_id", "provider_name", "image", "flavor"}).
AddRow(
s.Fixtures.Orgs[0].ID,
@ -490,159 +482,142 @@ func (s *OrgTestSuite) TestCreateOrganizationDBPoolAlreadyExistErr() {
s.Fixtures.CreatePoolParams.Image,
s.Fixtures.CreatePoolParams.Flavor))
_, err := s.StoreSQLMocked.CreateOrganizationPool(context.Background(), s.Fixtures.Orgs[0].ID, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Orgs[0].GetEntity()
s.Require().Nil(err)
_, err = s.StoreSQLMocked.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.assertSQLMockExpectations()
s.Require().NotNil(err)
s.Require().Equal(runnerErrors.NewConflictError("pool with the same image and flavor already exists on this provider"), err)
s.assertSQLMockExpectations()
}
func (s *OrgTestSuite) TestCreateOrganizationPoolDBFetchTagErr() {
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `organizations` WHERE id = ? AND `organizations`.`deleted_at` IS NULL ORDER BY `organizations`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Orgs[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Orgs[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `organizations` WHERE id = ? AND `organizations`.`deleted_at` IS NULL ORDER BY `organizations`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Orgs[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Orgs[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE `pools`.`org_id` = ? AND (provider_name = ? and image = ? and flavor = ?) AND `pools`.`deleted_at` IS NULL")).
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (provider_name = ? and image = ? and flavor = ? and org_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WithArgs(
s.Fixtures.Orgs[0].ID,
s.Fixtures.CreatePoolParams.ProviderName,
s.Fixtures.CreatePoolParams.Image,
s.Fixtures.CreatePoolParams.Flavor).
s.Fixtures.CreatePoolParams.Flavor,
s.Fixtures.Orgs[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"org_id"}))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `tags` WHERE name = ? AND `tags`.`deleted_at` IS NULL ORDER BY `tags`.`id` LIMIT 1")).
WillReturnError(fmt.Errorf("mocked fetching tag error"))
_, err := s.StoreSQLMocked.CreateOrganizationPool(context.Background(), s.Fixtures.Orgs[0].ID, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Orgs[0].GetEntity()
s.Require().Nil(err)
_, err = s.StoreSQLMocked.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.assertSQLMockExpectations()
s.Require().NotNil(err)
s.Require().Equal("fetching tag: fetching tag from database: mocked fetching tag error", err.Error())
s.Require().Equal("creating tag: fetching tag from database: mocked fetching tag error", err.Error())
s.assertSQLMockExpectations()
}
func (s *OrgTestSuite) TestCreateOrganizationPoolDBAddingPoolErr() {
s.Fixtures.CreatePoolParams.Tags = []string{"linux"}
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `organizations` WHERE id = ? AND `organizations`.`deleted_at` IS NULL ORDER BY `organizations`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Orgs[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Orgs[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `organizations` WHERE id = ? AND `organizations`.`deleted_at` IS NULL ORDER BY `organizations`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Orgs[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Orgs[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE `pools`.`org_id` = ? AND (provider_name = ? and image = ? and flavor = ?) AND `pools`.`deleted_at` IS NULL")).
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (provider_name = ? and image = ? and flavor = ? and org_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WithArgs(
s.Fixtures.Orgs[0].ID,
s.Fixtures.CreatePoolParams.ProviderName,
s.Fixtures.CreatePoolParams.Image,
s.Fixtures.CreatePoolParams.Flavor).
s.Fixtures.CreatePoolParams.Flavor,
s.Fixtures.Orgs[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"org_id"}))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `tags` WHERE name = ? AND `tags`.`deleted_at` IS NULL ORDER BY `tags`.`id` LIMIT 1")).
WillReturnRows(sqlmock.NewRows([]string{"linux"}))
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("INSERT INTO `tags`")).
WillReturnResult(sqlmock.NewResult(1, 1))
s.Fixtures.SQLMock.ExpectCommit()
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("INSERT INTO `pools`")).
WillReturnError(fmt.Errorf("mocked adding pool error"))
s.Fixtures.SQLMock.ExpectRollback()
_, err := s.StoreSQLMocked.CreateOrganizationPool(context.Background(), s.Fixtures.Orgs[0].ID, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Orgs[0].GetEntity()
s.Require().Nil(err)
_, err = s.StoreSQLMocked.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.assertSQLMockExpectations()
s.Require().NotNil(err)
s.Require().Equal("adding pool: mocked adding pool error", err.Error())
s.Require().Equal("creating pool: mocked adding pool error", err.Error())
s.assertSQLMockExpectations()
}
func (s *OrgTestSuite) TestCreateOrganizationPoolDBSaveTagErr() {
s.Fixtures.CreatePoolParams.Tags = []string{"linux"}
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `organizations` WHERE id = ? AND `organizations`.`deleted_at` IS NULL ORDER BY `organizations`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Orgs[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Orgs[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `organizations` WHERE id = ? AND `organizations`.`deleted_at` IS NULL ORDER BY `organizations`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Orgs[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Orgs[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE `pools`.`org_id` = ? AND (provider_name = ? and image = ? and flavor = ?) AND `pools`.`deleted_at` IS NULL")).
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (provider_name = ? and image = ? and flavor = ? and org_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WithArgs(
s.Fixtures.Orgs[0].ID,
s.Fixtures.CreatePoolParams.ProviderName,
s.Fixtures.CreatePoolParams.Image,
s.Fixtures.CreatePoolParams.Flavor).
s.Fixtures.CreatePoolParams.Flavor,
s.Fixtures.Orgs[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"org_id"}))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `tags` WHERE name = ? AND `tags`.`deleted_at` IS NULL ORDER BY `tags`.`id` LIMIT 1")).
WillReturnRows(sqlmock.NewRows([]string{"linux"}))
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("INSERT INTO `tags`")).
WillReturnResult(sqlmock.NewResult(1, 1))
s.Fixtures.SQLMock.ExpectCommit()
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("INSERT INTO `pools`")).
WillReturnResult(sqlmock.NewResult(1, 1))
s.Fixtures.SQLMock.ExpectCommit()
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("UPDATE `pools` SET")).
WillReturnError(fmt.Errorf("mocked saving tag error"))
s.Fixtures.SQLMock.ExpectRollback()
_, err := s.StoreSQLMocked.CreateOrganizationPool(context.Background(), s.Fixtures.Orgs[0].ID, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Orgs[0].GetEntity()
s.Require().Nil(err)
_, err = s.StoreSQLMocked.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.assertSQLMockExpectations()
s.Require().NotNil(err)
s.Require().Equal("saving tag: mocked saving tag error", err.Error())
s.Require().Equal("associating tags: mocked saving tag error", err.Error())
s.assertSQLMockExpectations()
}
func (s *OrgTestSuite) TestCreateOrganizationPoolDBFetchPoolErr() {
s.Fixtures.CreatePoolParams.Tags = []string{"linux"}
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `organizations` WHERE id = ? AND `organizations`.`deleted_at` IS NULL ORDER BY `organizations`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Orgs[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Orgs[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `organizations` WHERE id = ? AND `organizations`.`deleted_at` IS NULL ORDER BY `organizations`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Orgs[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Orgs[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE `pools`.`org_id` = ? AND (provider_name = ? and image = ? and flavor = ?) AND `pools`.`deleted_at` IS NULL")).
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (provider_name = ? and image = ? and flavor = ? and org_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WithArgs(
s.Fixtures.Orgs[0].ID,
s.Fixtures.CreatePoolParams.ProviderName,
s.Fixtures.CreatePoolParams.Image,
s.Fixtures.CreatePoolParams.Flavor).
s.Fixtures.CreatePoolParams.Flavor,
s.Fixtures.Orgs[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"org_id"}))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `tags` WHERE name = ? AND `tags`.`deleted_at` IS NULL ORDER BY `tags`.`id` LIMIT 1")).
WillReturnRows(sqlmock.NewRows([]string{"linux"}))
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("INSERT INTO `tags`")).
WillReturnResult(sqlmock.NewResult(1, 1))
s.Fixtures.SQLMock.ExpectCommit()
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("INSERT INTO `pools`")).
WillReturnResult(sqlmock.NewResult(1, 1))
s.Fixtures.SQLMock.ExpectCommit()
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("UPDATE `pools` SET")).
WillReturnResult(sqlmock.NewResult(1, 1))
@ -657,19 +632,20 @@ func (s *OrgTestSuite) TestCreateOrganizationPoolDBFetchPoolErr() {
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE id = ? AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WillReturnRows(sqlmock.NewRows([]string{"id"}))
_, err := s.StoreSQLMocked.CreateOrganizationPool(context.Background(), s.Fixtures.Orgs[0].ID, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Orgs[0].GetEntity()
s.Require().Nil(err)
_, err = s.StoreSQLMocked.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.assertSQLMockExpectations()
s.Require().NotNil(err)
s.Require().Equal("fetching pool: not found", err.Error())
s.assertSQLMockExpectations()
}
func (s *OrgTestSuite) TestListOrgPools() {
orgPools := []params.Pool{}
entity := params.GithubEntity{
ID: s.Fixtures.Orgs[0].ID,
EntityType: params.GithubEntityTypeOrganization,
}
entity, err := s.Fixtures.Orgs[0].GetEntity()
s.Require().Nil(err)
for i := 1; i <= 2; i++ {
s.Fixtures.CreatePoolParams.Flavor = fmt.Sprintf("test-flavor-%v", i)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
@ -678,25 +654,26 @@ func (s *OrgTestSuite) TestListOrgPools() {
}
orgPools = append(orgPools, pool)
}
pools, err := s.Store.ListOrgPools(context.Background(), s.Fixtures.Orgs[0].ID)
pools, err := s.Store.ListEntityPools(context.Background(), entity)
s.Require().Nil(err)
garmTesting.EqualDBEntityID(s.T(), orgPools, pools)
}
func (s *OrgTestSuite) TestListOrgPoolsInvalidOrgID() {
_, err := s.Store.ListOrgPools(context.Background(), "dummy-org-id")
entity := params.GithubEntity{
ID: "dummy-org-id",
EntityType: params.GithubEntityTypeOrganization,
}
_, err := s.Store.ListEntityPools(context.Background(), entity)
s.Require().NotNil(err)
s.Require().Equal("fetching pools: parsing id: invalid request", err.Error())
}
func (s *OrgTestSuite) TestGetOrganizationPool() {
entity := params.GithubEntity{
ID: s.Fixtures.Orgs[0].ID,
EntityType: params.GithubEntityTypeOrganization,
}
entity, err := s.Fixtures.Orgs[0].GetEntity()
s.Require().Nil(err)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
if err != nil {
s.FailNow(fmt.Sprintf("cannot create org pool: %v", err))
@ -720,10 +697,8 @@ func (s *OrgTestSuite) TestGetOrganizationPoolInvalidOrgID() {
}
func (s *OrgTestSuite) TestDeleteOrganizationPool() {
entity := params.GithubEntity{
ID: s.Fixtures.Orgs[0].ID,
EntityType: params.GithubEntityTypeOrganization,
}
entity, err := s.Fixtures.Orgs[0].GetEntity()
s.Require().Nil(err)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
if err != nil {
s.FailNow(fmt.Sprintf("cannot create org pool: %v", err))
@ -748,38 +723,31 @@ func (s *OrgTestSuite) TestDeleteOrganizationPoolInvalidOrgID() {
}
func (s *OrgTestSuite) TestDeleteOrganizationPoolDBDeleteErr() {
entity := params.GithubEntity{
ID: s.Fixtures.Orgs[0].ID,
EntityType: params.GithubEntityTypeOrganization,
}
entity, err := s.Fixtures.Orgs[0].GetEntity()
s.Require().Nil(err)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
if err != nil {
s.FailNow(fmt.Sprintf("cannot create org pool: %v", err))
}
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (id = ? and org_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WithArgs(pool.ID, s.Fixtures.Orgs[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"org_id", "id"}).AddRow(s.Fixtures.Orgs[0].ID, pool.ID))
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("DELETE FROM `pools` WHERE `pools`.`id` = ?")).
WithArgs(pool.ID).
ExpectExec(regexp.QuoteMeta("DELETE FROM `pools` WHERE id = ? and org_id = ?")).
WithArgs(pool.ID, s.Fixtures.Orgs[0].ID).
WillReturnError(fmt.Errorf("mocked deleting pool error"))
s.Fixtures.SQLMock.ExpectRollback()
err = s.StoreSQLMocked.DeleteOrganizationPool(context.Background(), s.Fixtures.Orgs[0].ID, pool.ID)
err = s.StoreSQLMocked.DeleteEntityPool(context.Background(), entity, pool.ID)
s.assertSQLMockExpectations()
s.Require().NotNil(err)
s.Require().Equal("deleting pool: mocked deleting pool error", err.Error())
s.Require().Equal("removing pool: mocked deleting pool error", err.Error())
s.assertSQLMockExpectations()
}
func (s *OrgTestSuite) TestListOrgInstances() {
entity := params.GithubEntity{
ID: s.Fixtures.Orgs[0].ID,
EntityType: params.GithubEntityTypeOrganization,
}
entity, err := s.Fixtures.Orgs[0].GetEntity()
s.Require().Nil(err)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
if err != nil {
s.FailNow(fmt.Sprintf("cannot create org pool: %v", err))
@ -794,30 +762,32 @@ func (s *OrgTestSuite) TestListOrgInstances() {
poolInstances = append(poolInstances, instance)
}
instances, err := s.Store.ListOrgInstances(context.Background(), s.Fixtures.Orgs[0].ID)
instances, err := s.Store.ListEntityInstances(context.Background(), entity)
s.Require().Nil(err)
s.equalInstancesByName(poolInstances, instances)
}
func (s *OrgTestSuite) TestListOrgInstancesInvalidOrgID() {
_, err := s.Store.ListOrgInstances(context.Background(), "dummy-org-id")
entity := params.GithubEntity{
ID: "dummy-org-id",
EntityType: params.GithubEntityTypeOrganization,
}
_, err := s.Store.ListEntityInstances(context.Background(), entity)
s.Require().NotNil(err)
s.Require().Equal("fetching org: parsing id: invalid request", err.Error())
s.Require().Equal("fetching entity: parsing id: invalid request", err.Error())
}
func (s *OrgTestSuite) TestUpdateOrganizationPool() {
entity := params.GithubEntity{
ID: s.Fixtures.Orgs[0].ID,
EntityType: params.GithubEntityTypeOrganization,
}
entity, err := s.Fixtures.Orgs[0].GetEntity()
s.Require().Nil(err)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
if err != nil {
s.FailNow(fmt.Sprintf("cannot create org pool: %v", err))
}
pool, err = s.Store.UpdateOrganizationPool(context.Background(), s.Fixtures.Orgs[0].ID, pool.ID, s.Fixtures.UpdatePoolParams)
pool, err = s.Store.UpdateEntityPool(context.Background(), entity, pool.ID, s.Fixtures.UpdatePoolParams)
s.Require().Nil(err)
s.Require().Equal(*s.Fixtures.UpdatePoolParams.MaxRunners, pool.MaxRunners)
@ -827,7 +797,11 @@ func (s *OrgTestSuite) TestUpdateOrganizationPool() {
}
func (s *OrgTestSuite) TestUpdateOrganizationPoolInvalidOrgID() {
_, err := s.Store.UpdateOrganizationPool(context.Background(), "dummy-org-id", "dummy-pool-id", s.Fixtures.UpdatePoolParams)
entity := params.GithubEntity{
ID: "dummy-org-id",
EntityType: params.GithubEntityTypeOrganization,
}
_, err := s.Store.UpdateEntityPool(context.Background(), entity, "dummy-pool-id", s.Fixtures.UpdatePoolParams)
s.Require().NotNil(err)
s.Require().Equal("fetching pool: parsing id: invalid request", err.Error())

View file

@ -89,25 +89,30 @@ func (s *sqlDatabase) getEntityPool(tx *gorm.DB, entityType params.GithubEntityT
return Pool{}, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
}
var fieldName string
var entityField string
switch entityType {
case params.GithubEntityTypeRepository:
fieldName = entityTypeRepoName
entityField = "Repository"
case params.GithubEntityTypeOrganization:
fieldName = entityTypeOrgName
entityField = "Organization"
case params.GithubEntityTypeEnterprise:
fieldName = entityTypeEnterpriseName
entityField = "Enterprise"
default:
return Pool{}, fmt.Errorf("invalid entityType: %v", entityType)
}
q := tx
q = q.Preload(entityField)
if len(preload) > 0 {
for _, item := range preload {
q = q.Preload(item)
}
}
var fieldName string
switch entityType {
case params.GithubEntityTypeRepository:
fieldName = entityTypeRepoName
case params.GithubEntityTypeOrganization:
fieldName = entityTypeOrgName
case params.GithubEntityTypeEnterprise:
fieldName = entityTypeEnterpriseName
default:
return Pool{}, fmt.Errorf("invalid entityType: %v", entityType)
}
var pool Pool
condition := fmt.Sprintf("id = ? and %s = ?", fieldName)
err = q.Model(&Pool{}).
@ -123,30 +128,39 @@ func (s *sqlDatabase) getEntityPool(tx *gorm.DB, entityType params.GithubEntityT
return pool, nil
}
func (s *sqlDatabase) listEntityPools(_ context.Context, entityType params.GithubEntityType, entityID string, preload ...string) ([]Pool, error) {
func (s *sqlDatabase) listEntityPools(tx *gorm.DB, entityType params.GithubEntityType, entityID string, preload ...string) ([]Pool, error) {
if _, err := uuid.Parse(entityID); err != nil {
return nil, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
}
q := s.conn
if len(preload) > 0 {
for _, item := range preload {
q = q.Preload(item)
}
if err := s.hasGithubEntity(tx, entityType, entityID); err != nil {
return nil, errors.Wrap(err, "checking entity existence")
}
var preloadEntity string
var fieldName string
switch entityType {
case params.GithubEntityTypeRepository:
fieldName = entityTypeRepoName
preloadEntity = "Repository"
case params.GithubEntityTypeOrganization:
fieldName = entityTypeOrgName
preloadEntity = "Organization"
case params.GithubEntityTypeEnterprise:
fieldName = entityTypeEnterpriseName
preloadEntity = "Enterprise"
default:
return nil, fmt.Errorf("invalid entityType: %v", entityType)
}
q := tx
q = q.Preload(preloadEntity)
if len(preload) > 0 {
for _, item := range preload {
q = q.Preload(item)
}
}
var pools []Pool
condition := fmt.Sprintf("%s = ?", fieldName)
err := q.Model(&Pool{}).
@ -270,8 +284,7 @@ func (s *sqlDatabase) CreateEntityPool(_ context.Context, entity params.GithubEn
newPool.EnterpriseID = &entityID
}
err = s.conn.Transaction(func(tx *gorm.DB) error {
ok, err := s.hasGithubEntity(tx, entity.EntityType, entity.ID)
if err != nil || !ok {
if err := s.hasGithubEntity(tx, entity.EntityType, entity.ID); err != nil {
return errors.Wrap(err, "checking entity existence")
}
@ -305,7 +318,7 @@ func (s *sqlDatabase) CreateEntityPool(_ context.Context, entity params.GithubEn
return nil
})
if err != nil {
return params.Pool{}, errors.Wrap(err, "creating pool")
return params.Pool{}, err
}
pool, err := s.getPoolByID(s.conn, newPool.ID.String(), "Tags", "Instances", "Enterprise", "Organization", "Repository")
@ -353,16 +366,56 @@ func (s *sqlDatabase) DeleteEntityPool(_ context.Context, entity params.GithubEn
}
func (s *sqlDatabase) UpdateEntityPool(_ context.Context, entity params.GithubEntity, poolID string, param params.UpdatePoolParams) (params.Pool, error) {
fmt.Printf("UpdateEntityPool: %v %v %v\n", entity, poolID, param)
return params.Pool{}, nil
var updatedPool params.Pool
err := s.conn.Transaction(func(tx *gorm.DB) error {
pool, err := s.getEntityPool(tx, entity.EntityType, entity.ID, poolID, "Tags", "Instances")
if err != nil {
return errors.Wrap(err, "fetching pool")
}
updatedPool, err = s.updatePool(tx, pool, param)
if err != nil {
return errors.Wrap(err, "updating pool")
}
return nil
})
if err != nil {
return params.Pool{}, err
}
return updatedPool, nil
}
func (s *sqlDatabase) ListEntityPools(_ context.Context, entity params.GithubEntity) ([]params.Pool, error) {
fmt.Println(entity)
return nil, nil
pools, err := s.listEntityPools(s.conn, entity.EntityType, entity.ID, "Tags")
if err != nil {
return nil, errors.Wrap(err, "fetching pools")
}
ret := make([]params.Pool, len(pools))
for idx, pool := range pools {
ret[idx], err = s.sqlToCommonPool(pool)
if err != nil {
return nil, errors.Wrap(err, "fetching pool")
}
}
return ret, nil
}
func (s *sqlDatabase) ListEntityInstances(_ context.Context, entity params.GithubEntity) ([]params.Instance, error) {
fmt.Println(entity)
return nil, nil
pools, err := s.listEntityPools(s.conn, entity.EntityType, entity.ID, "Instances", "Instances.Job")
if err != nil {
return nil, errors.Wrap(err, "fetching entity")
}
ret := []params.Instance{}
for _, pool := range pools {
for _, instance := range pool.Instances {
paramsInstance, err := s.sqlToParamsInstance(instance)
if err != nil {
return nil, errors.Wrap(err, "fetching instance")
}
ret = append(ret, paramsInstance)
}
}
return ret, nil
}

View file

@ -66,10 +66,8 @@ func (s *PoolsTestSuite) SetupTest() {
s.FailNow(fmt.Sprintf("failed to create org: %s", err))
}
entity := params.GithubEntity{
ID: org.ID,
EntityType: params.GithubEntityTypeOrganization,
}
entity, err := org.GetEntity()
s.Require().Nil(err)
// create some pool objects in the database, for testing purposes
orgPools := []params.Pool{}
for i := 1; i <= 3; i++ {

View file

@ -20,7 +20,6 @@ import (
"github.com/google/uuid"
"github.com/pkg/errors"
"gorm.io/datatypes"
"gorm.io/gorm"
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
@ -151,138 +150,6 @@ func (s *sqlDatabase) GetRepositoryByID(ctx context.Context, repoID string) (par
return param, nil
}
func (s *sqlDatabase) CreateRepositoryPool(ctx context.Context, repoID string, param params.CreatePoolParams) (params.Pool, error) {
if len(param.Tags) == 0 {
return params.Pool{}, runnerErrors.NewBadRequestError("no tags specified")
}
repo, err := s.getRepoByID(ctx, repoID)
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching repo")
}
newPool := Pool{
ProviderName: param.ProviderName,
MaxRunners: param.MaxRunners,
MinIdleRunners: param.MinIdleRunners,
RunnerPrefix: param.GetRunnerPrefix(),
Image: param.Image,
Flavor: param.Flavor,
OSType: param.OSType,
OSArch: param.OSArch,
RepoID: &repo.ID,
Enabled: param.Enabled,
RunnerBootstrapTimeout: param.RunnerBootstrapTimeout,
GitHubRunnerGroup: param.GitHubRunnerGroup,
Priority: param.Priority,
}
if len(param.ExtraSpecs) > 0 {
newPool.ExtraSpecs = datatypes.JSON(param.ExtraSpecs)
}
_, err = s.getRepoPoolByUniqueFields(ctx, repoID, newPool.ProviderName, newPool.Image, newPool.Flavor)
if err != nil {
if !errors.Is(err, runnerErrors.ErrNotFound) {
return params.Pool{}, errors.Wrap(err, "creating pool")
}
} else {
return params.Pool{}, runnerErrors.NewConflictError("pool with the same image and flavor already exists on this provider")
}
tags := []Tag{}
for _, val := range param.Tags {
t, err := s.getOrCreateTag(s.conn, val)
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching tag")
}
tags = append(tags, t)
}
q := s.conn.Create(&newPool)
if q.Error != nil {
return params.Pool{}, errors.Wrap(q.Error, "adding pool")
}
for i := range tags {
if err := s.conn.Model(&newPool).Association("Tags").Append(&tags[i]); err != nil {
return params.Pool{}, errors.Wrap(err, "saving tag")
}
}
pool, err := s.getPoolByID(s.conn, newPool.ID.String(), "Tags", "Instances", "Enterprise", "Organization", "Repository")
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching pool")
}
return s.sqlToCommonPool(pool)
}
func (s *sqlDatabase) ListRepoPools(ctx context.Context, repoID string) ([]params.Pool, error) {
pools, err := s.listEntityPools(ctx, params.GithubEntityTypeRepository, repoID, "Tags", "Instances", "Repository")
if err != nil {
return nil, errors.Wrap(err, "fetching pools")
}
ret := make([]params.Pool, len(pools))
for idx, pool := range pools {
ret[idx], err = s.sqlToCommonPool(pool)
if err != nil {
return nil, errors.Wrap(err, "fetching pool")
}
}
return ret, nil
}
func (s *sqlDatabase) GetRepositoryPool(_ context.Context, repoID, poolID string) (params.Pool, error) {
pool, err := s.getEntityPool(s.conn, params.GithubEntityTypeRepository, repoID, poolID, "Tags", "Instances")
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching pool")
}
return s.sqlToCommonPool(pool)
}
func (s *sqlDatabase) DeleteRepositoryPool(_ context.Context, repoID, poolID string) error {
pool, err := s.getEntityPool(s.conn, params.GithubEntityTypeRepository, repoID, poolID)
if err != nil {
return errors.Wrap(err, "looking up repo pool")
}
q := s.conn.Unscoped().Delete(&pool)
if q.Error != nil && !errors.Is(q.Error, gorm.ErrRecordNotFound) {
return errors.Wrap(q.Error, "deleting pool")
}
return nil
}
func (s *sqlDatabase) ListRepoInstances(ctx context.Context, repoID string) ([]params.Instance, error) {
pools, err := s.listEntityPools(ctx, params.GithubEntityTypeRepository, repoID, "Tags", "Instances", "Instances.Job")
if err != nil {
return nil, errors.Wrap(err, "fetching repo")
}
ret := []params.Instance{}
for _, pool := range pools {
for _, instance := range pool.Instances {
paramsInstance, err := s.sqlToParamsInstance(instance)
if err != nil {
return nil, errors.Wrap(err, "fetching instance")
}
ret = append(ret, paramsInstance)
}
}
return ret, nil
}
func (s *sqlDatabase) UpdateRepositoryPool(_ context.Context, repoID, poolID string, param params.UpdatePoolParams) (params.Pool, error) {
pool, err := s.getEntityPool(s.conn, params.GithubEntityTypeRepository, repoID, poolID, "Tags", "Instances", "Enterprise", "Organization", "Repository")
if err != nil {
return params.Pool{}, errors.Wrap(err, "fetching pool")
}
return s.updatePool(s.conn, pool, param)
}
func (s *sqlDatabase) getRepo(_ context.Context, owner, name string) (Repository, error) {
var repo Repository
@ -325,25 +192,6 @@ func (s *sqlDatabase) getEntityPoolByUniqueFields(tx *gorm.DB, entity params.Git
return Pool{}, nil
}
func (s *sqlDatabase) getRepoPoolByUniqueFields(ctx context.Context, repoID string, provider, image, flavor string) (Pool, error) {
repo, err := s.getRepoByID(ctx, repoID)
if err != nil {
return Pool{}, errors.Wrap(err, "fetching repo")
}
q := s.conn
var pool []Pool
err = q.Model(&repo).Association("Pools").Find(&pool, "provider_name = ? and image = ? and flavor = ?", provider, image, flavor)
if err != nil {
return Pool{}, errors.Wrap(err, "fetching pool")
}
if len(pool) == 0 {
return Pool{}, runnerErrors.ErrNotFound
}
return pool[0], nil
}
func (s *sqlDatabase) getRepoByID(_ context.Context, id string, preload ...string) (Repository, error) {
u, err := uuid.Parse(id)
if err != nil {

View file

@ -443,10 +443,8 @@ func (s *RepoTestSuite) TestGetRepositoryByIDDBDecryptingErr() {
}
func (s *RepoTestSuite) TestCreateRepositoryPool() {
entity := params.GithubEntity{
ID: s.Fixtures.Repos[0].ID,
EntityType: params.GithubEntityTypeRepository,
}
entity, err := s.Fixtures.Repos[0].GetEntity()
s.Require().Nil(err)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.Require().Nil(err)
@ -463,11 +461,9 @@ func (s *RepoTestSuite) TestCreateRepositoryPool() {
func (s *RepoTestSuite) TestCreateRepositoryPoolMissingTags() {
s.Fixtures.CreatePoolParams.Tags = []string{}
entity := params.GithubEntity{
ID: s.Fixtures.Repos[0].ID,
EntityType: params.GithubEntityTypeRepository,
}
_, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Repos[0].GetEntity()
s.Require().Nil(err)
_, err = s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.Require().NotNil(err)
s.Require().Equal("no tags specified", err.Error())
@ -485,41 +481,37 @@ func (s *RepoTestSuite) TestCreateRepositoryPoolInvalidRepoID() {
}
func (s *RepoTestSuite) TestCreateRepositoryPoolDBCreateErr() {
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `repositories` WHERE id = ? AND `repositories`.`deleted_at` IS NULL ORDER BY `repositories`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Repos[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Repos[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `repositories` WHERE id = ? AND `repositories`.`deleted_at` IS NULL ORDER BY `repositories`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Repos[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Repos[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE `pools`.`repo_id` = ? AND (provider_name = ? and image = ? and flavor = ?) AND `pools`.`deleted_at` IS NULL")).
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (provider_name = ? and image = ? and flavor = ? and repo_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WillReturnError(fmt.Errorf("mocked creating pool error"))
_, err := s.StoreSQLMocked.CreateRepositoryPool(context.Background(), s.Fixtures.Repos[0].ID, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Repos[0].GetEntity()
s.Require().Nil(err)
_, err = s.StoreSQLMocked.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.assertSQLMockExpectations()
s.Require().NotNil(err)
s.Require().Equal("creating pool: fetching pool: mocked creating pool error", err.Error())
s.Require().Equal("checking pool existence: mocked creating pool error", err.Error())
s.assertSQLMockExpectations()
}
func (s *RepoTestSuite) TestCreateRepositoryPoolDBPoolAlreadyExistErr() {
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `repositories` WHERE id = ? AND `repositories`.`deleted_at` IS NULL ORDER BY `repositories`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Repos[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Repos[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `repositories` WHERE id = ? AND `repositories`.`deleted_at` IS NULL ORDER BY `repositories`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Repos[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Repos[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE `pools`.`repo_id` = ? AND (provider_name = ? and image = ? and flavor = ?) AND `pools`.`deleted_at` IS NULL")).
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (provider_name = ? and image = ? and flavor = ? and repo_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WithArgs(
s.Fixtures.Repos[0].ID,
s.Fixtures.CreatePoolParams.ProviderName,
s.Fixtures.CreatePoolParams.Image,
s.Fixtures.CreatePoolParams.Flavor).
s.Fixtures.CreatePoolParams.Flavor,
s.Fixtures.Repos[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"repo_id", "provider_name", "image", "flavor"}).
AddRow(
s.Fixtures.Repos[0].ID,
@ -527,159 +519,145 @@ func (s *RepoTestSuite) TestCreateRepositoryPoolDBPoolAlreadyExistErr() {
s.Fixtures.CreatePoolParams.Image,
s.Fixtures.CreatePoolParams.Flavor))
_, err := s.StoreSQLMocked.CreateRepositoryPool(context.Background(), s.Fixtures.Repos[0].ID, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Repos[0].GetEntity()
s.Require().Nil(err)
_, err = s.StoreSQLMocked.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.assertSQLMockExpectations()
s.Require().NotNil(err)
s.Require().Equal("pool with the same image and flavor already exists on this provider", err.Error())
s.assertSQLMockExpectations()
}
func (s *RepoTestSuite) TestCreateRepositoryPoolDBFetchTagErr() {
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `repositories` WHERE id = ? AND `repositories`.`deleted_at` IS NULL ORDER BY `repositories`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Repos[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Repos[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `repositories` WHERE id = ? AND `repositories`.`deleted_at` IS NULL ORDER BY `repositories`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Repos[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Repos[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE `pools`.`repo_id` = ? AND (provider_name = ? and image = ? and flavor = ?) AND `pools`.`deleted_at` IS NULL")).
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (provider_name = ? and image = ? and flavor = ? and repo_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WithArgs(
s.Fixtures.Repos[0].ID,
s.Fixtures.CreatePoolParams.ProviderName,
s.Fixtures.CreatePoolParams.Image,
s.Fixtures.CreatePoolParams.Flavor).
s.Fixtures.CreatePoolParams.Flavor,
s.Fixtures.Repos[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"repo_id"}))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `tags` WHERE name = ? AND `tags`.`deleted_at` IS NULL ORDER BY `tags`.`id` LIMIT 1")).
WillReturnError(fmt.Errorf("mocked fetching tag error"))
_, err := s.StoreSQLMocked.CreateRepositoryPool(context.Background(), s.Fixtures.Repos[0].ID, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Repos[0].GetEntity()
s.Require().Nil(err)
_, err = s.StoreSQLMocked.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.assertSQLMockExpectations()
s.Require().NotNil(err)
s.Require().Equal("fetching tag: fetching tag from database: mocked fetching tag error", err.Error())
s.Require().Equal("creating tag: fetching tag from database: mocked fetching tag error", err.Error())
s.assertSQLMockExpectations()
}
func (s *RepoTestSuite) TestCreateRepositoryPoolDBAddingPoolErr() {
s.Fixtures.CreatePoolParams.Tags = []string{"linux"}
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `repositories` WHERE id = ? AND `repositories`.`deleted_at` IS NULL ORDER BY `repositories`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Repos[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Repos[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `repositories` WHERE id = ? AND `repositories`.`deleted_at` IS NULL ORDER BY `repositories`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Repos[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Repos[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE `pools`.`repo_id` = ? AND (provider_name = ? and image = ? and flavor = ?) AND `pools`.`deleted_at` IS NULL")).
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (provider_name = ? and image = ? and flavor = ? and repo_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WithArgs(
s.Fixtures.Repos[0].ID,
s.Fixtures.CreatePoolParams.ProviderName,
s.Fixtures.CreatePoolParams.Image,
s.Fixtures.CreatePoolParams.Flavor).
s.Fixtures.CreatePoolParams.Flavor,
s.Fixtures.Repos[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"repo_id"}))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `tags` WHERE name = ? AND `tags`.`deleted_at` IS NULL ORDER BY `tags`.`id` LIMIT 1")).
WillReturnRows(sqlmock.NewRows([]string{"linux"}))
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("INSERT INTO `tags`")).
WillReturnResult(sqlmock.NewResult(1, 1))
s.Fixtures.SQLMock.ExpectCommit()
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("INSERT INTO `pools`")).
WillReturnError(fmt.Errorf("mocked adding pool error"))
s.Fixtures.SQLMock.ExpectRollback()
_, err := s.StoreSQLMocked.CreateRepositoryPool(context.Background(), s.Fixtures.Repos[0].ID, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Repos[0].GetEntity()
s.Require().Nil(err)
_, err = s.StoreSQLMocked.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.assertSQLMockExpectations()
s.Require().NotNil(err)
s.Require().Equal("adding pool: mocked adding pool error", err.Error())
s.Require().Equal("creating pool: mocked adding pool error", err.Error())
s.assertSQLMockExpectations()
}
func (s *RepoTestSuite) TestCreateRepositoryPoolDBSaveTagErr() {
s.Fixtures.CreatePoolParams.Tags = []string{"linux"}
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `repositories` WHERE id = ? AND `repositories`.`deleted_at` IS NULL ORDER BY `repositories`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Repos[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Repos[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `repositories` WHERE id = ? AND `repositories`.`deleted_at` IS NULL ORDER BY `repositories`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Repos[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Repos[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE `pools`.`repo_id` = ? AND (provider_name = ? and image = ? and flavor = ?) AND `pools`.`deleted_at` IS NULL")).
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (provider_name = ? and image = ? and flavor = ? and repo_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WithArgs(
s.Fixtures.Repos[0].ID,
s.Fixtures.CreatePoolParams.ProviderName,
s.Fixtures.CreatePoolParams.Image,
s.Fixtures.CreatePoolParams.Flavor).
s.Fixtures.CreatePoolParams.Flavor,
s.Fixtures.Repos[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"repo_id"}))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `tags` WHERE name = ? AND `tags`.`deleted_at` IS NULL ORDER BY `tags`.`id` LIMIT 1")).
WillReturnRows(sqlmock.NewRows([]string{"linux"}))
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("INSERT INTO `tags`")).
WillReturnResult(sqlmock.NewResult(1, 1))
s.Fixtures.SQLMock.ExpectCommit()
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("INSERT INTO `pools`")).
WillReturnResult(sqlmock.NewResult(1, 1))
s.Fixtures.SQLMock.ExpectCommit()
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("UPDATE `pools` SET")).
WillReturnError(fmt.Errorf("mocked saving tag error"))
s.Fixtures.SQLMock.ExpectRollback()
_, err := s.StoreSQLMocked.CreateRepositoryPool(context.Background(), s.Fixtures.Repos[0].ID, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Repos[0].GetEntity()
s.Require().Nil(err)
s.assertSQLMockExpectations()
_, err = s.StoreSQLMocked.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.Require().NotNil(err)
s.Require().Equal("saving tag: mocked saving tag error", err.Error())
s.Require().Equal("associating tags: mocked saving tag error", err.Error())
s.assertSQLMockExpectations()
}
func (s *RepoTestSuite) TestCreateRepositoryPoolDBFetchPoolErr() {
s.Fixtures.CreatePoolParams.Tags = []string{"linux"}
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `repositories` WHERE id = ? AND `repositories`.`deleted_at` IS NULL ORDER BY `repositories`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Repos[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Repos[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `repositories` WHERE id = ? AND `repositories`.`deleted_at` IS NULL ORDER BY `repositories`.`id` LIMIT 1")).
WithArgs(s.Fixtures.Repos[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(s.Fixtures.Repos[0].ID))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE `pools`.`repo_id` = ? AND (provider_name = ? and image = ? and flavor = ?) AND `pools`.`deleted_at` IS NULL")).
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (provider_name = ? and image = ? and flavor = ? and repo_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WithArgs(
s.Fixtures.Repos[0].ID,
s.Fixtures.CreatePoolParams.ProviderName,
s.Fixtures.CreatePoolParams.Image,
s.Fixtures.CreatePoolParams.Flavor).
s.Fixtures.CreatePoolParams.Flavor,
s.Fixtures.Repos[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"repo_id"}))
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `tags` WHERE name = ? AND `tags`.`deleted_at` IS NULL ORDER BY `tags`.`id` LIMIT 1")).
WillReturnRows(sqlmock.NewRows([]string{"linux"}))
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("INSERT INTO `tags`")).
WillReturnResult(sqlmock.NewResult(1, 1))
s.Fixtures.SQLMock.ExpectCommit()
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("INSERT INTO `pools`")).
WillReturnResult(sqlmock.NewResult(1, 1))
s.Fixtures.SQLMock.ExpectCommit()
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("UPDATE `pools` SET")).
WillReturnResult(sqlmock.NewResult(1, 1))
@ -694,18 +672,19 @@ func (s *RepoTestSuite) TestCreateRepositoryPoolDBFetchPoolErr() {
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE id = ? AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WillReturnRows(sqlmock.NewRows([]string{"id"}))
_, err := s.StoreSQLMocked.CreateRepositoryPool(context.Background(), s.Fixtures.Repos[0].ID, s.Fixtures.CreatePoolParams)
entity, err := s.Fixtures.Repos[0].GetEntity()
s.Require().Nil(err)
_, err = s.StoreSQLMocked.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
s.assertSQLMockExpectations()
s.Require().NotNil(err)
s.Require().Equal("fetching pool: not found", err.Error())
s.assertSQLMockExpectations()
}
func (s *RepoTestSuite) TestListRepoPools() {
entity := params.GithubEntity{
ID: s.Fixtures.Repos[0].ID,
EntityType: params.GithubEntityTypeRepository,
}
entity, err := s.Fixtures.Repos[0].GetEntity()
s.Require().Nil(err)
repoPools := []params.Pool{}
for i := 1; i <= 2; i++ {
s.Fixtures.CreatePoolParams.Flavor = fmt.Sprintf("test-flavor-%d", i)
@ -716,24 +695,26 @@ func (s *RepoTestSuite) TestListRepoPools() {
repoPools = append(repoPools, pool)
}
pools, err := s.Store.ListRepoPools(context.Background(), s.Fixtures.Repos[0].ID)
pools, err := s.Store.ListEntityPools(context.Background(), entity)
s.Require().Nil(err)
garmTesting.EqualDBEntityID(s.T(), repoPools, pools)
}
func (s *RepoTestSuite) TestListRepoPoolsInvalidRepoID() {
_, err := s.Store.ListRepoPools(context.Background(), "dummy-repo-id")
entity := params.GithubEntity{
ID: "dummy-repo-id",
EntityType: params.GithubEntityTypeRepository,
}
_, err := s.Store.ListEntityPools(context.Background(), entity)
s.Require().NotNil(err)
s.Require().Equal("fetching pools: parsing id: invalid request", err.Error())
}
func (s *RepoTestSuite) TestGetRepositoryPool() {
entity := params.GithubEntity{
ID: s.Fixtures.Repos[0].ID,
EntityType: params.GithubEntityTypeRepository,
}
entity, err := s.Fixtures.Repos[0].GetEntity()
s.Require().Nil(err)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
if err != nil {
s.FailNow(fmt.Sprintf("cannot create repo pool: %v", err))
@ -757,10 +738,8 @@ func (s *RepoTestSuite) TestGetRepositoryPoolInvalidRepoID() {
}
func (s *RepoTestSuite) TestDeleteRepositoryPool() {
entity := params.GithubEntity{
ID: s.Fixtures.Repos[0].ID,
EntityType: params.GithubEntityTypeRepository,
}
entity, err := s.Fixtures.Repos[0].GetEntity()
s.Require().Nil(err)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
if err != nil {
s.FailNow(fmt.Sprintf("cannot create repo pool: %v", err))
@ -785,38 +764,30 @@ func (s *RepoTestSuite) TestDeleteRepositoryPoolInvalidRepoID() {
}
func (s *RepoTestSuite) TestDeleteRepositoryPoolDBDeleteErr() {
entity := params.GithubEntity{
ID: s.Fixtures.Repos[0].ID,
EntityType: params.GithubEntityTypeRepository,
}
entity, err := s.Fixtures.Repos[0].GetEntity()
s.Require().Nil(err)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
if err != nil {
s.FailNow(fmt.Sprintf("cannot create repo pool: %v", err))
}
s.Fixtures.SQLMock.
ExpectQuery(regexp.QuoteMeta("SELECT * FROM `pools` WHERE (id = ? and repo_id = ?) AND `pools`.`deleted_at` IS NULL ORDER BY `pools`.`id` LIMIT 1")).
WithArgs(pool.ID, s.Fixtures.Repos[0].ID).
WillReturnRows(sqlmock.NewRows([]string{"repo_id", "id"}).AddRow(s.Fixtures.Repos[0].ID, pool.ID))
s.Fixtures.SQLMock.ExpectBegin()
s.Fixtures.SQLMock.
ExpectExec(regexp.QuoteMeta("DELETE FROM `pools` WHERE `pools`.`id` = ?")).
WithArgs(pool.ID).
ExpectExec(regexp.QuoteMeta("DELETE FROM `pools` WHERE id = ? and repo_id = ?")).
WithArgs(pool.ID, s.Fixtures.Repos[0].ID).
WillReturnError(fmt.Errorf("mocked deleting pool error"))
s.Fixtures.SQLMock.ExpectRollback()
err = s.StoreSQLMocked.DeleteRepositoryPool(context.Background(), s.Fixtures.Repos[0].ID, pool.ID)
s.assertSQLMockExpectations()
err = s.StoreSQLMocked.DeleteEntityPool(context.Background(), entity, pool.ID)
s.Require().NotNil(err)
s.Require().Equal("deleting pool: mocked deleting pool error", err.Error())
s.Require().Equal("removing pool: mocked deleting pool error", err.Error())
s.assertSQLMockExpectations()
}
func (s *RepoTestSuite) TestListRepoInstances() {
entity := params.GithubEntity{
ID: s.Fixtures.Repos[0].ID,
EntityType: params.GithubEntityTypeRepository,
}
entity, err := s.Fixtures.Repos[0].GetEntity()
s.Require().Nil(err)
pool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
if err != nil {
s.FailNow(fmt.Sprintf("cannot create repo pool: %v", err))
@ -831,30 +802,32 @@ func (s *RepoTestSuite) TestListRepoInstances() {
poolInstances = append(poolInstances, instance)
}
instances, err := s.Store.ListRepoInstances(context.Background(), s.Fixtures.Repos[0].ID)
instances, err := s.Store.ListEntityInstances(context.Background(), entity)
s.Require().Nil(err)
s.equalInstancesByID(poolInstances, instances)
}
func (s *RepoTestSuite) TestListRepoInstancesInvalidRepoID() {
_, err := s.Store.ListRepoInstances(context.Background(), "dummy-repo-id")
entity := params.GithubEntity{
ID: "dummy-repo-id",
EntityType: params.GithubEntityTypeRepository,
}
_, err := s.Store.ListEntityInstances(context.Background(), entity)
s.Require().NotNil(err)
s.Require().Equal("fetching repo: parsing id: invalid request", err.Error())
s.Require().Equal("fetching entity: parsing id: invalid request", err.Error())
}
func (s *RepoTestSuite) TestUpdateRepositoryPool() {
entity := params.GithubEntity{
ID: s.Fixtures.Repos[0].ID,
EntityType: params.GithubEntityTypeRepository,
}
entity, err := s.Fixtures.Repos[0].GetEntity()
s.Require().Nil(err)
repoPool, err := s.Store.CreateEntityPool(context.Background(), entity, s.Fixtures.CreatePoolParams)
if err != nil {
s.FailNow(fmt.Sprintf("cannot create repo pool: %v", err))
}
pool, err := s.Store.UpdateRepositoryPool(context.Background(), s.Fixtures.Repos[0].ID, repoPool.ID, s.Fixtures.UpdatePoolParams)
pool, err := s.Store.UpdateEntityPool(context.Background(), entity, repoPool.ID, s.Fixtures.UpdatePoolParams)
s.Require().Nil(err)
s.Require().Equal(*s.Fixtures.UpdatePoolParams.MaxRunners, pool.MaxRunners)
@ -864,7 +837,11 @@ func (s *RepoTestSuite) TestUpdateRepositoryPool() {
}
func (s *RepoTestSuite) TestUpdateRepositoryPoolInvalidRepoID() {
_, err := s.Store.UpdateRepositoryPool(context.Background(), "dummy-org-id", "dummy-repo-id", s.Fixtures.UpdatePoolParams)
entity := params.GithubEntity{
ID: "dummy-repo-id",
EntityType: params.GithubEntityTypeRepository,
}
_, err := s.Store.UpdateEntityPool(context.Background(), entity, "dummy-repo-id", s.Fixtures.UpdatePoolParams)
s.Require().NotNil(err)
s.Require().Equal("fetching pool: parsing id: invalid request", err.Error())

View file

@ -290,9 +290,8 @@ func (s *sqlDatabase) getOrCreateTag(tx *gorm.DB, tagName string) (Tag, error) {
Name: tagName,
}
q = tx.Create(&newTag)
if q.Error != nil {
return Tag{}, errors.Wrap(q.Error, "creating tag")
if err := tx.Create(&newTag).Error; err != nil {
return Tag{}, errors.Wrap(err, "creating tag")
}
return newTag, nil
}
@ -392,10 +391,10 @@ func (s *sqlDatabase) getPoolByID(tx *gorm.DB, poolID string, preload ...string)
return pool, nil
}
func (s *sqlDatabase) hasGithubEntity(tx *gorm.DB, entityType params.GithubEntityType, entityID string) (bool, error) {
func (s *sqlDatabase) hasGithubEntity(tx *gorm.DB, entityType params.GithubEntityType, entityID string) error {
u, err := uuid.Parse(entityID)
if err != nil {
return false, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
return errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
}
var q *gorm.DB
switch entityType {
@ -406,15 +405,15 @@ func (s *sqlDatabase) hasGithubEntity(tx *gorm.DB, entityType params.GithubEntit
case params.GithubEntityTypeEnterprise:
q = tx.Model(&Enterprise{}).Where("id = ?", u)
default:
return false, errors.Wrap(runnerErrors.ErrBadRequest, "invalid entity type")
return errors.Wrap(runnerErrors.ErrBadRequest, "invalid entity type")
}
var entity interface{}
if err := q.First(entity).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return false, errors.Wrap(runnerErrors.ErrNotFound, "entity not found")
return errors.Wrap(runnerErrors.ErrNotFound, "entity not found")
}
return false, errors.Wrap(err, "fetching entity from database")
return errors.Wrap(err, "fetching entity from database")
}
return true, nil
return nil
}