diff --git a/Gopkg.lock b/Gopkg.lock index af1aa6e938..9e4398163c 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -453,7 +453,7 @@ version = "v1.2.0" [[projects]] - digest = "1:b1ab65fa43650fb503aa710091eb9d13c6c5d7f0cf14684039827b457a1f2ac9" + digest = "1:9f01843d5ce98395a8af3da88dc6c67d169e0e94d253337026c423e2b18cdf4f" name = "github.com/lyft/flyteidl" packages = [ "clients/go/admin", @@ -466,9 +466,9 @@ "gen/pb-go/flyteidl/service", ] pruneopts = "UT" - revision = "6deb3c002d84b2012f02cdecc32902f475deda83" + revision = "28c0dfb6608b70262aac9cb1ff83a750521ded8e" source = "https://github.com/lyft/flyteidl" - version = "v0.16.4" + version = "v0.16.5" [[projects]] digest = "1:938998e14bd5e42c54f3b640a41d869eb79029ad7c623fa47c604b8480c781fc" diff --git a/Gopkg.toml b/Gopkg.toml index 134076a727..4f2891b3d8 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -60,7 +60,7 @@ [[override]] name = "github.com/lyft/flyteidl" source = "https://github.com/lyft/flyteidl" - version = "^0.16.x" + version = "^0.16.5" [[constraint]] name = "github.com/lyft/flytepropeller" diff --git a/pkg/manager/impl/project_attributes_manager.go b/pkg/manager/impl/project_attributes_manager.go index 810485d8e7..f4408c3559 100644 --- a/pkg/manager/impl/project_attributes_manager.go +++ b/pkg/manager/impl/project_attributes_manager.go @@ -36,6 +36,35 @@ func (m *ProjectAttributesManager) UpdateProjectAttributes( return &admin.ProjectAttributesUpdateResponse{}, nil } +func (m *ProjectAttributesManager) GetProjectAttributes(ctx context.Context, request admin.ProjectAttributesGetRequest) ( + *admin.ProjectAttributesGetResponse, error) { + if err := validation.ValidateProjectAttributesGetRequest(request); err != nil { + return nil, err + } + projectAttributesModel, err := m.db.ProjectAttributesRepo().Get(ctx, request.Project, request.ResourceType.String()) + if err != nil { + return nil, err + } + projectAttributes, err := transformers.FromProjectAttributesModel(projectAttributesModel) + if err != nil { + return nil, err + } + return &admin.ProjectAttributesGetResponse{ + Attributes: &projectAttributes, + }, nil +} + +func (m *ProjectAttributesManager) DeleteProjectAttributes(ctx context.Context, + request admin.ProjectAttributesDeleteRequest) (*admin.ProjectAttributesDeleteResponse, error) { + if err := validation.ValidateProjectAttributesDeleteRequest(request); err != nil { + return nil, err + } + if err := m.db.ProjectAttributesRepo().Delete(ctx, request.Project, request.ResourceType.String()); err != nil { + return nil, err + } + return &admin.ProjectAttributesDeleteResponse{}, nil +} + func NewProjectAttributesManager(db repositories.RepositoryInterface) interfaces.ProjectAttributesInterface { return &ProjectAttributesManager{ db: db, diff --git a/pkg/manager/impl/project_attributes_manager_test.go b/pkg/manager/impl/project_attributes_manager_test.go index 6add5fa418..7d8c264b73 100644 --- a/pkg/manager/impl/project_attributes_manager_test.go +++ b/pkg/manager/impl/project_attributes_manager_test.go @@ -35,3 +35,48 @@ func TestUpdateProjectAttributes(t *testing.T) { assert.Nil(t, err) assert.True(t, createOrUpdateCalled) } + +func TestGetProjectAttributes(t *testing.T) { + request := admin.ProjectAttributesGetRequest{ + Project: "project", + ResourceType: admin.MatchableResource_EXECUTION_QUEUE, + } + db := mocks.NewMockRepository() + db.ProjectAttributesRepo().(*mocks.MockProjectAttributesRepo).GetFunction = func( + ctx context.Context, project, resource string) (models.ProjectAttributes, error) { + assert.Equal(t, "project", project) + assert.Equal(t, admin.MatchableResource_EXECUTION_QUEUE.String(), resource) + expectedSerializedAttrs, _ := proto.Marshal(testutils.ExecutionQueueAttributes) + return models.ProjectAttributes{ + Project: project, + Resource: resource, + Attributes: expectedSerializedAttrs, + }, nil + } + manager := NewProjectAttributesManager(db) + response, err := manager.GetProjectAttributes(context.Background(), request) + assert.Nil(t, err) + assert.True(t, proto.Equal(&admin.ProjectAttributesGetResponse{ + Attributes: &admin.ProjectAttributes{ + Project: "project", + MatchingAttributes: testutils.ExecutionQueueAttributes, + }, + }, response)) +} + +func TestDeleteProjectAttributes(t *testing.T) { + request := admin.ProjectAttributesDeleteRequest{ + Project: "project", + ResourceType: admin.MatchableResource_EXECUTION_QUEUE, + } + db := mocks.NewMockRepository() + db.ProjectAttributesRepo().(*mocks.MockProjectAttributesRepo).DeleteFunction = func( + ctx context.Context, project, resource string) error { + assert.Equal(t, "project", project) + assert.Equal(t, admin.MatchableResource_EXECUTION_QUEUE.String(), resource) + return nil + } + manager := NewProjectAttributesManager(db) + _, err := manager.DeleteProjectAttributes(context.Background(), request) + assert.Nil(t, err) +} diff --git a/pkg/manager/impl/project_domain_attributes_manager.go b/pkg/manager/impl/project_domain_attributes_manager.go index a2831e58ee..f35cb1ff25 100644 --- a/pkg/manager/impl/project_domain_attributes_manager.go +++ b/pkg/manager/impl/project_domain_attributes_manager.go @@ -39,6 +39,38 @@ func (m *ProjectDomainAttributesManager) UpdateProjectDomainAttributes( return &admin.ProjectDomainAttributesUpdateResponse{}, nil } +func (m *ProjectDomainAttributesManager) GetProjectDomainAttributes( + ctx context.Context, request admin.ProjectDomainAttributesGetRequest) ( + *admin.ProjectDomainAttributesGetResponse, error) { + if err := validation.ValidateProjectDomainAttributesGetRequest(request); err != nil { + return nil, err + } + projectAttributesModel, err := m.db.ProjectDomainAttributesRepo().Get( + ctx, request.Project, request.Domain, request.ResourceType.String()) + if err != nil { + return nil, err + } + projectAttributes, err := transformers.FromProjectDomainAttributesModel(projectAttributesModel) + if err != nil { + return nil, err + } + return &admin.ProjectDomainAttributesGetResponse{ + Attributes: &projectAttributes, + }, nil +} + +func (m *ProjectDomainAttributesManager) DeleteProjectDomainAttributes(ctx context.Context, + request admin.ProjectDomainAttributesDeleteRequest) (*admin.ProjectDomainAttributesDeleteResponse, error) { + if err := validation.ValidateProjectDomainAttributesDeleteRequest(request); err != nil { + return nil, err + } + if err := m.db.ProjectDomainAttributesRepo().Delete( + ctx, request.Project, request.Domain, request.ResourceType.String()); err != nil { + return nil, err + } + return &admin.ProjectDomainAttributesDeleteResponse{}, nil +} + func NewProjectDomainAttributesManager( db repositories.RepositoryInterface) interfaces.ProjectDomainAttributesInterface { return &ProjectDomainAttributesManager{ diff --git a/pkg/manager/impl/project_domain_attributes_manager_test.go b/pkg/manager/impl/project_domain_attributes_manager_test.go index fc182fcb06..e5031afe19 100644 --- a/pkg/manager/impl/project_domain_attributes_manager_test.go +++ b/pkg/manager/impl/project_domain_attributes_manager_test.go @@ -37,3 +37,54 @@ func TestUpdateProjectDomainAttributes(t *testing.T) { assert.Nil(t, err) assert.True(t, createOrUpdateCalled) } + +func TestGetProjectDomainAttributes(t *testing.T) { + request := admin.ProjectDomainAttributesGetRequest{ + Project: "project", + Domain: "domain", + ResourceType: admin.MatchableResource_EXECUTION_QUEUE, + } + db := mocks.NewMockRepository() + db.ProjectDomainAttributesRepo().(*mocks.MockProjectDomainAttributesRepo).GetFunction = func( + ctx context.Context, project, domain, resource string) (models.ProjectDomainAttributes, error) { + assert.Equal(t, "project", project) + assert.Equal(t, "domain", domain) + assert.Equal(t, admin.MatchableResource_EXECUTION_QUEUE.String(), resource) + expectedSerializedAttrs, _ := proto.Marshal(testutils.ExecutionQueueAttributes) + return models.ProjectDomainAttributes{ + Project: project, + Domain: domain, + Resource: resource, + Attributes: expectedSerializedAttrs, + }, nil + } + manager := NewProjectDomainAttributesManager(db) + response, err := manager.GetProjectDomainAttributes(context.Background(), request) + assert.Nil(t, err) + assert.True(t, proto.Equal(&admin.ProjectDomainAttributesGetResponse{ + Attributes: &admin.ProjectDomainAttributes{ + Project: "project", + Domain: "domain", + MatchingAttributes: testutils.ExecutionQueueAttributes, + }, + }, response)) +} + +func TestDeleteProjectDomainAttributes(t *testing.T) { + request := admin.ProjectDomainAttributesDeleteRequest{ + Project: "project", + Domain: "domain", + ResourceType: admin.MatchableResource_EXECUTION_QUEUE, + } + db := mocks.NewMockRepository() + db.ProjectDomainAttributesRepo().(*mocks.MockProjectDomainAttributesRepo).DeleteFunction = func( + ctx context.Context, project, domain, resource string) error { + assert.Equal(t, "project", project) + assert.Equal(t, "domain", domain) + assert.Equal(t, admin.MatchableResource_EXECUTION_QUEUE.String(), resource) + return nil + } + manager := NewProjectDomainAttributesManager(db) + _, err := manager.DeleteProjectDomainAttributes(context.Background(), request) + assert.Nil(t, err) +} diff --git a/pkg/manager/impl/validation/attributes_validator.go b/pkg/manager/impl/validation/attributes_validator.go index 827879c895..4ae18ae8b9 100644 --- a/pkg/manager/impl/validation/attributes_validator.go +++ b/pkg/manager/impl/validation/attributes_validator.go @@ -38,6 +38,22 @@ func ValidateProjectAttributesUpdateRequest(request admin.ProjectAttributesUpdat return validateMatchingAttributes(request.Attributes.MatchingAttributes, request.Attributes.Project) } +func ValidateProjectAttributesGetRequest(request admin.ProjectAttributesGetRequest) error { + if err := ValidateEmptyStringField(request.Project, shared.Project); err != nil { + return err + } + + return nil +} + +func ValidateProjectAttributesDeleteRequest(request admin.ProjectAttributesDeleteRequest) error { + if err := ValidateEmptyStringField(request.Project, shared.Project); err != nil { + return err + } + + return nil +} + func ValidateProjectDomainAttributesUpdateRequest(request admin.ProjectDomainAttributesUpdateRequest) ( admin.MatchableResource, error) { if request.Attributes == nil { @@ -54,6 +70,28 @@ func ValidateProjectDomainAttributesUpdateRequest(request admin.ProjectDomainAtt fmt.Sprintf("%s-%s", request.Attributes.Project, request.Attributes.Domain)) } +func ValidateProjectDomainAttributesGetRequest(request admin.ProjectDomainAttributesGetRequest) error { + if err := ValidateEmptyStringField(request.Project, shared.Project); err != nil { + return err + } + if err := ValidateEmptyStringField(request.Domain, shared.Domain); err != nil { + return err + } + + return nil +} + +func ValidateProjectDomainAttributesDeleteRequest(request admin.ProjectDomainAttributesDeleteRequest) error { + if err := ValidateEmptyStringField(request.Project, shared.Project); err != nil { + return err + } + if err := ValidateEmptyStringField(request.Domain, shared.Domain); err != nil { + return err + } + + return nil +} + func ValidateWorkflowAttributesUpdateRequest(request admin.WorkflowAttributesUpdateRequest) ( admin.MatchableResource, error) { if request.Attributes == nil { @@ -72,3 +110,31 @@ func ValidateWorkflowAttributesUpdateRequest(request admin.WorkflowAttributesUpd return validateMatchingAttributes(request.Attributes.MatchingAttributes, fmt.Sprintf("%s-%s-%s", request.Attributes.Project, request.Attributes.Domain, request.Attributes.Workflow)) } + +func ValidateWorkflowAttributesGetRequest(request admin.WorkflowAttributesGetRequest) error { + if err := ValidateEmptyStringField(request.Project, shared.Project); err != nil { + return err + } + if err := ValidateEmptyStringField(request.Domain, shared.Domain); err != nil { + return err + } + if err := ValidateEmptyStringField(request.Workflow, shared.Name); err != nil { + return err + } + + return nil +} + +func ValidateWorkflowAttributesDeleteRequest(request admin.WorkflowAttributesDeleteRequest) error { + if err := ValidateEmptyStringField(request.Project, shared.Project); err != nil { + return err + } + if err := ValidateEmptyStringField(request.Domain, shared.Domain); err != nil { + return err + } + if err := ValidateEmptyStringField(request.Workflow, shared.Name); err != nil { + return err + } + + return nil +} diff --git a/pkg/manager/impl/validation/attributes_validator_test.go b/pkg/manager/impl/validation/attributes_validator_test.go index face354f78..56053b6563 100644 --- a/pkg/manager/impl/validation/attributes_validator_test.go +++ b/pkg/manager/impl/validation/attributes_validator_test.go @@ -95,6 +95,24 @@ func TestValidateProjectAttributesUpdateRequest(t *testing.T) { assert.Nil(t, err) } +func TestValidateProjectAttributesGetRequest(t *testing.T) { + err := ValidateProjectAttributesGetRequest(admin.ProjectAttributesGetRequest{}) + assert.Equal(t, "missing project", err.Error()) + + assert.Nil(t, ValidateProjectAttributesGetRequest(admin.ProjectAttributesGetRequest{ + Project: "project", + })) +} + +func TestValidateProjectAttributesDeleteRequest(t *testing.T) { + err := ValidateProjectAttributesDeleteRequest(admin.ProjectAttributesDeleteRequest{}) + assert.Equal(t, "missing project", err.Error()) + + assert.Nil(t, ValidateProjectAttributesDeleteRequest(admin.ProjectAttributesDeleteRequest{ + Project: "project", + })) +} + func TestValidateProjectDomainAttributesUpdateRequest(t *testing.T) { _, err := ValidateProjectDomainAttributesUpdateRequest(admin.ProjectDomainAttributesUpdateRequest{}) assert.Equal(t, "missing attributes", err.Error()) @@ -127,6 +145,36 @@ func TestValidateProjectDomainAttributesUpdateRequest(t *testing.T) { assert.Nil(t, err) } +func TestValidateProjectDomainAttributesGetRequest(t *testing.T) { + err := ValidateProjectDomainAttributesGetRequest(admin.ProjectDomainAttributesGetRequest{}) + assert.Equal(t, "missing project", err.Error()) + + err = ValidateProjectDomainAttributesGetRequest(admin.ProjectDomainAttributesGetRequest{ + Project: "project", + }) + assert.Equal(t, "missing domain", err.Error()) + + assert.Nil(t, ValidateProjectDomainAttributesGetRequest(admin.ProjectDomainAttributesGetRequest{ + Project: "project", + Domain: "domain", + })) +} + +func TestValidateProjectDomainAttributesDeleteRequest(t *testing.T) { + err := ValidateProjectDomainAttributesDeleteRequest(admin.ProjectDomainAttributesDeleteRequest{}) + assert.Equal(t, "missing project", err.Error()) + + err = ValidateProjectDomainAttributesDeleteRequest(admin.ProjectDomainAttributesDeleteRequest{ + Project: "project", + }) + assert.Equal(t, "missing domain", err.Error()) + + assert.Nil(t, ValidateProjectDomainAttributesDeleteRequest(admin.ProjectDomainAttributesDeleteRequest{ + Project: "project", + Domain: "domain", + })) +} + func TestValidateWorkflowAttributesUpdateRequest(t *testing.T) { _, err := ValidateWorkflowAttributesUpdateRequest(admin.WorkflowAttributesUpdateRequest{}) assert.Equal(t, "missing attributes", err.Error()) @@ -164,3 +212,47 @@ func TestValidateWorkflowAttributesUpdateRequest(t *testing.T) { assert.Equal(t, admin.MatchableResource_EXECUTION_QUEUE, matchableResource) assert.Nil(t, err) } + +func TestValidateWorkflowAttributesGetRequest(t *testing.T) { + err := ValidateWorkflowAttributesGetRequest(admin.WorkflowAttributesGetRequest{}) + assert.Equal(t, "missing project", err.Error()) + + err = ValidateWorkflowAttributesGetRequest(admin.WorkflowAttributesGetRequest{ + Project: "project", + }) + assert.Equal(t, "missing domain", err.Error()) + + err = ValidateWorkflowAttributesGetRequest(admin.WorkflowAttributesGetRequest{ + Project: "project", + Domain: "domain", + }) + assert.Equal(t, "missing name", err.Error()) + + assert.Nil(t, ValidateWorkflowAttributesGetRequest(admin.WorkflowAttributesGetRequest{ + Project: "project", + Domain: "domain", + Workflow: "workflow", + })) +} + +func TestValidateWorkflowAttributesDeleteRequest(t *testing.T) { + err := ValidateWorkflowAttributesDeleteRequest(admin.WorkflowAttributesDeleteRequest{}) + assert.Equal(t, "missing project", err.Error()) + + err = ValidateWorkflowAttributesDeleteRequest(admin.WorkflowAttributesDeleteRequest{ + Project: "project", + }) + assert.Equal(t, "missing domain", err.Error()) + + err = ValidateWorkflowAttributesDeleteRequest(admin.WorkflowAttributesDeleteRequest{ + Project: "project", + Domain: "domain", + }) + assert.Equal(t, "missing name", err.Error()) + + assert.Nil(t, ValidateWorkflowAttributesDeleteRequest(admin.WorkflowAttributesDeleteRequest{ + Project: "project", + Domain: "domain", + Workflow: "workflow", + })) +} diff --git a/pkg/manager/impl/workflow_attributes_manager.go b/pkg/manager/impl/workflow_attributes_manager.go index e20e2f2326..ac8e5fd3e1 100644 --- a/pkg/manager/impl/workflow_attributes_manager.go +++ b/pkg/manager/impl/workflow_attributes_manager.go @@ -36,6 +36,38 @@ func (m *WorkflowAttributesManager) UpdateWorkflowAttributes( return &admin.WorkflowAttributesUpdateResponse{}, nil } +func (m *WorkflowAttributesManager) GetWorkflowAttributes( + ctx context.Context, request admin.WorkflowAttributesGetRequest) ( + *admin.WorkflowAttributesGetResponse, error) { + if err := validation.ValidateWorkflowAttributesGetRequest(request); err != nil { + return nil, err + } + projectAttributesModel, err := m.db.WorkflowAttributesRepo().Get( + ctx, request.Project, request.Domain, request.Workflow, request.ResourceType.String()) + if err != nil { + return nil, err + } + projectAttributes, err := transformers.FromWorkflowAttributesModel(projectAttributesModel) + if err != nil { + return nil, err + } + return &admin.WorkflowAttributesGetResponse{ + Attributes: &projectAttributes, + }, nil +} + +func (m *WorkflowAttributesManager) DeleteWorkflowAttributes(ctx context.Context, + request admin.WorkflowAttributesDeleteRequest) (*admin.WorkflowAttributesDeleteResponse, error) { + if err := validation.ValidateWorkflowAttributesDeleteRequest(request); err != nil { + return nil, err + } + if err := m.db.WorkflowAttributesRepo().Delete( + ctx, request.Project, request.Domain, request.Workflow, request.ResourceType.String()); err != nil { + return nil, err + } + return &admin.WorkflowAttributesDeleteResponse{}, nil +} + func NewWorkflowAttributesManager(db repositories.RepositoryInterface) interfaces.WorkflowAttributesInterface { return &WorkflowAttributesManager{ db: db, diff --git a/pkg/manager/impl/workflow_attributes_manager_test.go b/pkg/manager/impl/workflow_attributes_manager_test.go index 052411b63f..12f40ad5c2 100644 --- a/pkg/manager/impl/workflow_attributes_manager_test.go +++ b/pkg/manager/impl/workflow_attributes_manager_test.go @@ -39,3 +39,60 @@ func TestUpdateWorkflowAttributes(t *testing.T) { assert.Nil(t, err) assert.True(t, createOrUpdateCalled) } + +func TestGetWorkflowAttributes(t *testing.T) { + request := admin.WorkflowAttributesGetRequest{ + Project: "project", + Domain: "domain", + Workflow: "workflow", + ResourceType: admin.MatchableResource_EXECUTION_QUEUE, + } + db := mocks.NewMockRepository() + db.WorkflowAttributesRepo().(*mocks.MockWorkflowAttributesRepo).GetFunction = func( + ctx context.Context, project, domain, workflow, resource string) (models.WorkflowAttributes, error) { + assert.Equal(t, "project", project) + assert.Equal(t, "domain", domain) + assert.Equal(t, "workflow", workflow) + assert.Equal(t, admin.MatchableResource_EXECUTION_QUEUE.String(), resource) + expectedSerializedAttrs, _ := proto.Marshal(testutils.ExecutionQueueAttributes) + return models.WorkflowAttributes{ + Project: project, + Domain: domain, + Workflow: workflow, + Resource: resource, + Attributes: expectedSerializedAttrs, + }, nil + } + manager := NewWorkflowAttributesManager(db) + response, err := manager.GetWorkflowAttributes(context.Background(), request) + assert.Nil(t, err) + assert.True(t, proto.Equal(&admin.WorkflowAttributesGetResponse{ + Attributes: &admin.WorkflowAttributes{ + Project: "project", + Domain: "domain", + Workflow: "workflow", + MatchingAttributes: testutils.ExecutionQueueAttributes, + }, + }, response)) +} + +func TestDeleteWorkflowAttributes(t *testing.T) { + request := admin.WorkflowAttributesDeleteRequest{ + Project: "project", + Domain: "domain", + Workflow: "workflow", + ResourceType: admin.MatchableResource_EXECUTION_QUEUE, + } + db := mocks.NewMockRepository() + db.WorkflowAttributesRepo().(*mocks.MockWorkflowAttributesRepo).DeleteFunction = func( + ctx context.Context, project, domain, workflow, resource string) error { + assert.Equal(t, "project", project) + assert.Equal(t, "domain", domain) + assert.Equal(t, "workflow", workflow) + assert.Equal(t, admin.MatchableResource_EXECUTION_QUEUE.String(), resource) + return nil + } + manager := NewWorkflowAttributesManager(db) + _, err := manager.DeleteWorkflowAttributes(context.Background(), request) + assert.Nil(t, err) +} diff --git a/pkg/manager/interfaces/project_attributes.go b/pkg/manager/interfaces/project_attributes.go index 9c0dcd43e3..85910d6992 100644 --- a/pkg/manager/interfaces/project_attributes.go +++ b/pkg/manager/interfaces/project_attributes.go @@ -10,4 +10,8 @@ import ( type ProjectAttributesInterface interface { UpdateProjectAttributes(ctx context.Context, request admin.ProjectAttributesUpdateRequest) ( *admin.ProjectAttributesUpdateResponse, error) + GetProjectAttributes(ctx context.Context, request admin.ProjectAttributesGetRequest) ( + *admin.ProjectAttributesGetResponse, error) + DeleteProjectAttributes(ctx context.Context, request admin.ProjectAttributesDeleteRequest) ( + *admin.ProjectAttributesDeleteResponse, error) } diff --git a/pkg/manager/interfaces/project_domain_attributes.go b/pkg/manager/interfaces/project_domain_attributes.go index c3f0b30133..4253f13eb6 100644 --- a/pkg/manager/interfaces/project_domain_attributes.go +++ b/pkg/manager/interfaces/project_domain_attributes.go @@ -10,4 +10,8 @@ import ( type ProjectDomainAttributesInterface interface { UpdateProjectDomainAttributes(ctx context.Context, request admin.ProjectDomainAttributesUpdateRequest) ( *admin.ProjectDomainAttributesUpdateResponse, error) + GetProjectDomainAttributes(ctx context.Context, request admin.ProjectDomainAttributesGetRequest) ( + *admin.ProjectDomainAttributesGetResponse, error) + DeleteProjectDomainAttributes(ctx context.Context, request admin.ProjectDomainAttributesDeleteRequest) ( + *admin.ProjectDomainAttributesDeleteResponse, error) } diff --git a/pkg/manager/interfaces/workflow_attributes.go b/pkg/manager/interfaces/workflow_attributes.go index 3897b36ef4..885ac0a9da 100644 --- a/pkg/manager/interfaces/workflow_attributes.go +++ b/pkg/manager/interfaces/workflow_attributes.go @@ -10,4 +10,8 @@ import ( type WorkflowAttributesInterface interface { UpdateWorkflowAttributes(ctx context.Context, request admin.WorkflowAttributesUpdateRequest) ( *admin.WorkflowAttributesUpdateResponse, error) + GetWorkflowAttributes(ctx context.Context, request admin.WorkflowAttributesGetRequest) ( + *admin.WorkflowAttributesGetResponse, error) + DeleteWorkflowAttributes(ctx context.Context, request admin.WorkflowAttributesDeleteRequest) ( + *admin.WorkflowAttributesDeleteResponse, error) } diff --git a/pkg/manager/mocks/project_domain.go b/pkg/manager/mocks/project_domain.go index d263b4a110..058687eb48 100644 --- a/pkg/manager/mocks/project_domain.go +++ b/pkg/manager/mocks/project_domain.go @@ -8,16 +8,22 @@ import ( type UpdateProjectDomainFunc func(ctx context.Context, request admin.ProjectDomainAttributesUpdateRequest) ( *admin.ProjectDomainAttributesUpdateResponse, error) +type GetProjectDomainFunc func(ctx context.Context, request admin.ProjectDomainAttributesGetRequest) ( + *admin.ProjectDomainAttributesGetResponse, error) +type DeleteProjectDomainFunc func(ctx context.Context, request admin.ProjectDomainAttributesDeleteRequest) ( + *admin.ProjectDomainAttributesDeleteResponse, error) -type MockProjectDomainManager struct { +type MockProjectDomainAttributesManager struct { updateProjectDomainFunc UpdateProjectDomainFunc + GetFunc GetProjectDomainFunc + DeleteFunc DeleteProjectDomainFunc } -func (m *MockProjectDomainManager) SetUpdateProjectDomainAttributes(updateProjectDomainFunc UpdateProjectDomainFunc) { +func (m *MockProjectDomainAttributesManager) SetUpdateProjectDomainAttributes(updateProjectDomainFunc UpdateProjectDomainFunc) { m.updateProjectDomainFunc = updateProjectDomainFunc } -func (m *MockProjectDomainManager) UpdateProjectDomainAttributes( +func (m *MockProjectDomainAttributesManager) UpdateProjectDomainAttributes( ctx context.Context, request admin.ProjectDomainAttributesUpdateRequest) ( *admin.ProjectDomainAttributesUpdateResponse, error) { if m.updateProjectDomainFunc != nil { @@ -25,3 +31,21 @@ func (m *MockProjectDomainManager) UpdateProjectDomainAttributes( } return nil, nil } + +func (m *MockProjectDomainAttributesManager) GetProjectDomainAttributes( + ctx context.Context, request admin.ProjectDomainAttributesGetRequest) ( + *admin.ProjectDomainAttributesGetResponse, error) { + if m.GetFunc != nil { + return m.GetFunc(ctx, request) + } + return nil, nil +} + +func (m *MockProjectDomainAttributesManager) DeleteProjectDomainAttributes( + ctx context.Context, request admin.ProjectDomainAttributesDeleteRequest) ( + *admin.ProjectDomainAttributesDeleteResponse, error) { + if m.DeleteFunc != nil { + return m.DeleteFunc(ctx, request) + } + return nil, nil +} diff --git a/pkg/repositories/gormimpl/metrics.go b/pkg/repositories/gormimpl/metrics.go index 353ca4cbb8..2efe492a9a 100644 --- a/pkg/repositories/gormimpl/metrics.go +++ b/pkg/repositories/gormimpl/metrics.go @@ -14,6 +14,7 @@ type gormMetrics struct { UpdateDuration promutils.StopWatch ListDuration promutils.StopWatch ListIdentifiersDuration promutils.StopWatch + DeleteDuration promutils.StopWatch } func newMetrics(scope promutils.Scope) gormMetrics { @@ -29,5 +30,6 @@ func newMetrics(scope promutils.Scope) gormMetrics { "list", "time taken to list entries", time.Millisecond), ListIdentifiersDuration: scope.MustNewStopWatch( "list_identifiers", "time taken to list identifier entries", time.Millisecond), + DeleteDuration: scope.MustNewStopWatch("delete", "time taken to delete an individual entry", time.Millisecond), } } diff --git a/pkg/repositories/gormimpl/project_attributes_repo.go b/pkg/repositories/gormimpl/project_attributes_repo.go index 63fa124df4..ce3d5c6701 100644 --- a/pkg/repositories/gormimpl/project_attributes_repo.go +++ b/pkg/repositories/gormimpl/project_attributes_repo.go @@ -59,6 +59,24 @@ func (r *ProjectAttributesRepo) Get(ctx context.Context, project, resource strin return model, nil } +func (r *ProjectAttributesRepo) Delete(ctx context.Context, project, resource string) error { + var tx *gorm.DB + r.metrics.DeleteDuration.Time(func() { + tx = r.db.Where(&models.ProjectAttributes{ + Project: project, + Resource: resource, + }).Unscoped().Delete(models.ProjectAttributes{}) + }) + if tx.Error != nil { + return r.errorTransformer.ToFlyteAdminError(tx.Error) + } + if tx.RecordNotFound() { + return flyteAdminErrors.NewFlyteAdminErrorf(codes.NotFound, + "project [%s] not found", project) + } + return nil +} + func NewProjectAttributesRepo(db *gorm.DB, errorTransformer errors.ErrorTransformer, scope promutils.Scope) interfaces.ProjectAttributesRepoInterface { metrics := newMetrics(scope) diff --git a/pkg/repositories/gormimpl/project_attributes_repo_test.go b/pkg/repositories/gormimpl/project_attributes_repo_test.go index f82bd84781..88bf53d6ef 100644 --- a/pkg/repositories/gormimpl/project_attributes_repo_test.go +++ b/pkg/repositories/gormimpl/project_attributes_repo_test.go @@ -55,3 +55,17 @@ func TestGetProjectAttributes(t *testing.T) { assert.Equal(t, testResourceAttr, output.Resource) assert.Equal(t, []byte("attrs"), output.Attributes) } + +func TestDeleteProjectAttributes(t *testing.T) { + projectRepo := NewProjectAttributesRepo(GetDbForTest(t), errors.NewTestErrorTransformer(), mockScope.NewTestScope()) + GlobalMock := mocket.Catcher.Reset() + + query := GlobalMock.NewMock() + fakeResponse := query.WithQuery( + `DELETE FROM "project_attributes" WHERE ("project_attributes"."project" = ?) AND ` + + `("project_attributes"."resource" = ?)`) + + err := projectRepo.Delete(context.Background(), "project", "resource") + assert.Nil(t, err) + assert.True(t, fakeResponse.Triggered) +} diff --git a/pkg/repositories/gormimpl/project_domain_attributes_repo.go b/pkg/repositories/gormimpl/project_domain_attributes_repo.go index 256f122222..7d8fe7eaa5 100644 --- a/pkg/repositories/gormimpl/project_domain_attributes_repo.go +++ b/pkg/repositories/gormimpl/project_domain_attributes_repo.go @@ -62,6 +62,25 @@ func (r *ProjectDomainAttributesRepo) Get(ctx context.Context, project, domain, return model, nil } +func (r *ProjectDomainAttributesRepo) Delete(ctx context.Context, project, domain, resource string) error { + var tx *gorm.DB + r.metrics.DeleteDuration.Time(func() { + tx = r.db.Where(&models.ProjectDomainAttributes{ + Project: project, + Domain: domain, + Resource: resource, + }).Unscoped().Delete(models.ProjectDomainAttributes{}) + }) + if tx.Error != nil { + return r.errorTransformer.ToFlyteAdminError(tx.Error) + } + if tx.RecordNotFound() { + return flyteAdminErrors.NewFlyteAdminErrorf(codes.NotFound, + "project-domain [%s-%s] not found", project, domain) + } + return nil +} + func NewProjectDomainAttributesRepo(db *gorm.DB, errorTransformer errors.ErrorTransformer, scope promutils.Scope) interfaces.ProjectDomainAttributesRepoInterface { metrics := newMetrics(scope) diff --git a/pkg/repositories/gormimpl/project_domain_attributes_repo_test.go b/pkg/repositories/gormimpl/project_domain_attributes_repo_test.go index 7648c2a505..0c70bdc3d1 100644 --- a/pkg/repositories/gormimpl/project_domain_attributes_repo_test.go +++ b/pkg/repositories/gormimpl/project_domain_attributes_repo_test.go @@ -12,7 +12,7 @@ import ( ) func TestCreateProjectDomainAttributes(t *testing.T) { - projectRepo := NewProjectDomainAttributesRepo(GetDbForTest(t), errors.NewTestErrorTransformer(), mockScope.NewTestScope()) + projectDomainRepo := NewProjectDomainAttributesRepo(GetDbForTest(t), errors.NewTestErrorTransformer(), mockScope.NewTestScope()) GlobalMock := mocket.Catcher.Reset() query := GlobalMock.NewMock() @@ -20,7 +20,7 @@ func TestCreateProjectDomainAttributes(t *testing.T) { `INSERT INTO "project_domain_attributes" ` + `("created_at","updated_at","deleted_at","project","domain","resource","attributes") VALUES (?,?,?,?,?,?,?)`) - err := projectRepo.CreateOrUpdate(context.Background(), models.ProjectDomainAttributes{ + err := projectDomainRepo.CreateOrUpdate(context.Background(), models.ProjectDomainAttributes{ Project: "project", Domain: "domain", Resource: "resource", @@ -31,7 +31,7 @@ func TestCreateProjectDomainAttributes(t *testing.T) { } func TestGetProjectDomainAttributes(t *testing.T) { - projectRepo := NewProjectDomainAttributesRepo(GetDbForTest(t), errors.NewTestErrorTransformer(), mockScope.NewTestScope()) + projectDomainRepo := NewProjectDomainAttributesRepo(GetDbForTest(t), errors.NewTestErrorTransformer(), mockScope.NewTestScope()) GlobalMock := mocket.Catcher.Reset() response := make(map[string]interface{}) @@ -49,10 +49,24 @@ func TestGetProjectDomainAttributes(t *testing.T) { response, }) - output, err := projectRepo.Get(context.Background(), "project", "domain", "resource") + output, err := projectDomainRepo.Get(context.Background(), "project", "domain", "resource") assert.Nil(t, err) assert.Equal(t, "project", output.Project) assert.Equal(t, "domain", output.Domain) assert.Equal(t, "resource", output.Resource) assert.Equal(t, []byte("attrs"), output.Attributes) } + +func TestDeleteProjectDomainAttributes(t *testing.T) { + projectDomainRepo := NewProjectDomainAttributesRepo(GetDbForTest(t), errors.NewTestErrorTransformer(), mockScope.NewTestScope()) + GlobalMock := mocket.Catcher.Reset() + + query := GlobalMock.NewMock() + fakeResponse := query.WithQuery( + `DELETE FROM "project_domain_attributes" WHERE ("project_domain_attributes"."project" = ?) AND ` + + `("project_domain_attributes"."domain" = ?) AND ("project_domain_attributes"."resource" = ?)`) + + err := projectDomainRepo.Delete(context.Background(), "project", "domain", "resource") + assert.Nil(t, err) + assert.True(t, fakeResponse.Triggered) +} diff --git a/pkg/repositories/gormimpl/workflow_attributes_repo.go b/pkg/repositories/gormimpl/workflow_attributes_repo.go index 96ac9822b2..1e32c228d5 100644 --- a/pkg/repositories/gormimpl/workflow_attributes_repo.go +++ b/pkg/repositories/gormimpl/workflow_attributes_repo.go @@ -59,11 +59,31 @@ func (r *WorkflowAttributesRepo) Get(ctx context.Context, project, domain, workf } if tx.RecordNotFound() { return models.WorkflowAttributes{}, flyteAdminErrors.NewFlyteAdminErrorf(codes.NotFound, - "project-domain [%s-%s] not found", project, domain) + "project-domain-workflow [%s-%s-%s] not found", project, domain, workflow) } return model, nil } +func (r *WorkflowAttributesRepo) Delete(ctx context.Context, project, domain, workflow, resource string) error { + var tx *gorm.DB + r.metrics.DeleteDuration.Time(func() { + tx = r.db.Where(&models.WorkflowAttributes{ + Project: project, + Domain: domain, + Workflow: workflow, + Resource: resource, + }).Unscoped().Delete(models.WorkflowAttributes{}) + }) + if tx.Error != nil { + return r.errorTransformer.ToFlyteAdminError(tx.Error) + } + if tx.RecordNotFound() { + return flyteAdminErrors.NewFlyteAdminErrorf(codes.NotFound, + "project-domain-workflow [%s-%s-%s] not found", project, domain, workflow) + } + return nil +} + func NewWorkflowAttributesRepo(db *gorm.DB, errorTransformer errors.ErrorTransformer, scope promutils.Scope) interfaces.WorkflowAttributesRepoInterface { metrics := newMetrics(scope) diff --git a/pkg/repositories/gormimpl/workflow_attributes_repo_test.go b/pkg/repositories/gormimpl/workflow_attributes_repo_test.go index 9d37cd7482..b8480cd1ea 100644 --- a/pkg/repositories/gormimpl/workflow_attributes_repo_test.go +++ b/pkg/repositories/gormimpl/workflow_attributes_repo_test.go @@ -60,3 +60,18 @@ func TestGetWorkflowAttributes(t *testing.T) { assert.Equal(t, "resource", output.Resource) assert.Equal(t, []byte("attrs"), output.Attributes) } + +func TestDeleteWorkflowAttributes(t *testing.T) { + workflowRepo := NewWorkflowAttributesRepo(GetDbForTest(t), errors.NewTestErrorTransformer(), mockScope.NewTestScope()) + GlobalMock := mocket.Catcher.Reset() + + query := GlobalMock.NewMock() + fakeResponse := query.WithQuery( + `DELETE FROM "workflow_attributes" WHERE ("workflow_attributes"."project" = ?) AND ` + + `("workflow_attributes"."domain" = ?) AND ("workflow_attributes"."workflow" = ?) AND ` + + `("workflow_attributes"."resource" = ?)`) + + err := workflowRepo.Delete(context.Background(), "project", "domain", "workflow", "resource") + assert.Nil(t, err) + assert.True(t, fakeResponse.Triggered) +} diff --git a/pkg/repositories/interfaces/project_attributes_repo.go b/pkg/repositories/interfaces/project_attributes_repo.go index 79c68213e0..fd77e31c92 100644 --- a/pkg/repositories/interfaces/project_attributes_repo.go +++ b/pkg/repositories/interfaces/project_attributes_repo.go @@ -11,4 +11,6 @@ type ProjectAttributesRepoInterface interface { CreateOrUpdate(ctx context.Context, input models.ProjectAttributes) error // Returns a matching ProjectAttributes model when it exists. Get(ctx context.Context, project, resource string) (models.ProjectAttributes, error) + // Deletes a matching ProjectAttributes model when it exists. + Delete(ctx context.Context, project, resource string) error } diff --git a/pkg/repositories/interfaces/project_domain_attributes_repo.go b/pkg/repositories/interfaces/project_domain_attributes_repo.go index f63ebb8277..e5e34451d3 100644 --- a/pkg/repositories/interfaces/project_domain_attributes_repo.go +++ b/pkg/repositories/interfaces/project_domain_attributes_repo.go @@ -11,4 +11,6 @@ type ProjectDomainAttributesRepoInterface interface { CreateOrUpdate(ctx context.Context, input models.ProjectDomainAttributes) error // Returns a matching ProjectDomainAttributes model when it exists. Get(ctx context.Context, project, domain, resource string) (models.ProjectDomainAttributes, error) + // Deletes a matching ProjectDomainAttributes model when it exists. + Delete(ctx context.Context, project, domain, resource string) error } diff --git a/pkg/repositories/interfaces/workflow_attributes_repo.go b/pkg/repositories/interfaces/workflow_attributes_repo.go index fdb61095ce..fed09ed489 100644 --- a/pkg/repositories/interfaces/workflow_attributes_repo.go +++ b/pkg/repositories/interfaces/workflow_attributes_repo.go @@ -11,4 +11,6 @@ type WorkflowAttributesRepoInterface interface { CreateOrUpdate(ctx context.Context, input models.WorkflowAttributes) error // Returns a matching WorkflowAttributes model when it exists. Get(ctx context.Context, project, domain, workflow, resource string) (models.WorkflowAttributes, error) + // Deletes a matching ProjectDomainAttributes model when it exists. + Delete(ctx context.Context, project, domain, workflow, resource string) error } diff --git a/pkg/repositories/mocks/project_attributes_repo.go b/pkg/repositories/mocks/project_attributes_repo.go index d7f4ebdaf5..24d91fbfc0 100644 --- a/pkg/repositories/mocks/project_attributes_repo.go +++ b/pkg/repositories/mocks/project_attributes_repo.go @@ -9,10 +9,12 @@ import ( type CreateOrUpdateProjectAttributesFunction func(ctx context.Context, input models.ProjectAttributes) error type GetProjectAttributesFunction func(ctx context.Context, project, resource string) (models.ProjectAttributes, error) +type DeleteProjectAttributesFunction func(ctx context.Context, project, resource string) error type MockProjectAttributesRepo struct { CreateOrUpdateFunction CreateOrUpdateProjectAttributesFunction GetFunction GetProjectAttributesFunction + DeleteFunction DeleteProjectAttributesFunction } func (r *MockProjectAttributesRepo) CreateOrUpdate(ctx context.Context, input models.ProjectAttributes) error { @@ -30,6 +32,13 @@ func (r *MockProjectAttributesRepo) Get(ctx context.Context, project, resource s return models.ProjectAttributes{}, nil } +func (r *MockProjectAttributesRepo) Delete(ctx context.Context, project, resource string) error { + if r.DeleteFunction != nil { + return r.DeleteFunction(ctx, project, resource) + } + return nil +} + func NewMockProjectAttributesRepo() interfaces.ProjectAttributesRepoInterface { return &MockProjectAttributesRepo{} } diff --git a/pkg/repositories/mocks/project_domain_attributes_repo.go b/pkg/repositories/mocks/project_domain_attributes_repo.go index ae243d0094..8c39a80ea2 100644 --- a/pkg/repositories/mocks/project_domain_attributes_repo.go +++ b/pkg/repositories/mocks/project_domain_attributes_repo.go @@ -9,10 +9,12 @@ import ( type CreateOrUpdateProjectDomainAttributesFunction func(ctx context.Context, input models.ProjectDomainAttributes) error type GetProjectDomainAttributesFunction func(ctx context.Context, project, domain, resource string) (models.ProjectDomainAttributes, error) +type DeleteProjectDomainAttributesFunction func(ctx context.Context, project, domain, resource string) error type MockProjectDomainAttributesRepo struct { CreateOrUpdateFunction CreateOrUpdateProjectDomainAttributesFunction GetFunction GetProjectDomainAttributesFunction + DeleteFunction DeleteProjectDomainAttributesFunction } func (r *MockProjectDomainAttributesRepo) CreateOrUpdate(ctx context.Context, input models.ProjectDomainAttributes) error { @@ -30,6 +32,13 @@ func (r *MockProjectDomainAttributesRepo) Get(ctx context.Context, project, doma return models.ProjectDomainAttributes{}, nil } +func (r *MockProjectDomainAttributesRepo) Delete(ctx context.Context, project, domain, resource string) error { + if r.DeleteFunction != nil { + return r.DeleteFunction(ctx, project, domain, resource) + } + return nil +} + func NewMockProjectDomainAttributesRepo() interfaces.ProjectDomainAttributesRepoInterface { return &MockProjectDomainAttributesRepo{} } diff --git a/pkg/repositories/mocks/workflow_attributes.go b/pkg/repositories/mocks/workflow_attributes.go index ede2e77728..8e8cf0fb50 100644 --- a/pkg/repositories/mocks/workflow_attributes.go +++ b/pkg/repositories/mocks/workflow_attributes.go @@ -10,11 +10,12 @@ import ( type CreateOrUpdateWorkflowAttributesFunction func(ctx context.Context, input models.WorkflowAttributes) error type GetWorkflowAttributesFunction func(ctx context.Context, project, domain, workflow, resource string) ( models.WorkflowAttributes, error) -type UpdateWorkflowAttributesFunction func(ctx context.Context, input models.WorkflowAttributes) error +type DeleteWorkflowAttributesFunction func(ctx context.Context, project, domain, workflow, resource string) error type MockWorkflowAttributesRepo struct { CreateOrUpdateFunction CreateOrUpdateWorkflowAttributesFunction GetFunction GetWorkflowAttributesFunction + DeleteFunction DeleteWorkflowAttributesFunction } func (r *MockWorkflowAttributesRepo) CreateOrUpdate(ctx context.Context, input models.WorkflowAttributes) error { @@ -32,6 +33,13 @@ func (r *MockWorkflowAttributesRepo) Get(ctx context.Context, project, domain, w return models.WorkflowAttributes{}, nil } +func (r *MockWorkflowAttributesRepo) Delete(ctx context.Context, project, domain, workflow, resource string) error { + if r.DeleteFunction != nil { + return r.DeleteFunction(ctx, project, domain, workflow, resource) + } + return nil +} + func NewMockWorkflowAttributesRepo() interfaces.WorkflowAttributesRepoInterface { return &MockWorkflowAttributesRepo{} } diff --git a/pkg/rpc/adminservice/attributes.go b/pkg/rpc/adminservice/attributes.go index c4fd131401..0548792a22 100644 --- a/pkg/rpc/adminservice/attributes.go +++ b/pkg/rpc/adminservice/attributes.go @@ -27,6 +27,42 @@ func (m *AdminService) UpdateWorkflowAttributes(ctx context.Context, request *ad return response, nil } +func (m *AdminService) GetWorkflowAttributes(ctx context.Context, request *admin.WorkflowAttributesGetRequest) ( + *admin.WorkflowAttributesGetResponse, error) { + defer m.interceptPanic(ctx, request) + if request == nil { + return nil, status.Errorf(codes.InvalidArgument, "Incorrect request, nil requests not allowed") + } + var response *admin.WorkflowAttributesGetResponse + var err error + m.Metrics.workflowAttributesEndpointMetrics.get.Time(func() { + response, err = m.WorkflowAttributesManager.GetWorkflowAttributes(ctx, *request) + }) + if err != nil { + return nil, util.TransformAndRecordError(err, &m.Metrics.workflowAttributesEndpointMetrics.get) + } + + return response, nil +} + +func (m *AdminService) DeleteWorkflowAttributes(ctx context.Context, request *admin.WorkflowAttributesDeleteRequest) ( + *admin.WorkflowAttributesDeleteResponse, error) { + defer m.interceptPanic(ctx, request) + if request == nil { + return nil, status.Errorf(codes.InvalidArgument, "Incorrect request, nil requests not allowed") + } + var response *admin.WorkflowAttributesDeleteResponse + var err error + m.Metrics.workflowAttributesEndpointMetrics.delete.Time(func() { + response, err = m.WorkflowAttributesManager.DeleteWorkflowAttributes(ctx, *request) + }) + if err != nil { + return nil, util.TransformAndRecordError(err, &m.Metrics.workflowAttributesEndpointMetrics.delete) + } + + return response, nil +} + func (m *AdminService) UpdateProjectDomainAttributes(ctx context.Context, request *admin.ProjectDomainAttributesUpdateRequest) ( *admin.ProjectDomainAttributesUpdateResponse, error) { defer m.interceptPanic(ctx, request) @@ -45,6 +81,42 @@ func (m *AdminService) UpdateProjectDomainAttributes(ctx context.Context, reques return response, nil } +func (m *AdminService) GetProjectDomainAttributes(ctx context.Context, request *admin.ProjectDomainAttributesGetRequest) ( + *admin.ProjectDomainAttributesGetResponse, error) { + defer m.interceptPanic(ctx, request) + if request == nil { + return nil, status.Errorf(codes.InvalidArgument, "Incorrect request, nil requests not allowed") + } + var response *admin.ProjectDomainAttributesGetResponse + var err error + m.Metrics.workflowAttributesEndpointMetrics.get.Time(func() { + response, err = m.ProjectDomainAttributesManager.GetProjectDomainAttributes(ctx, *request) + }) + if err != nil { + return nil, util.TransformAndRecordError(err, &m.Metrics.workflowAttributesEndpointMetrics.get) + } + + return response, nil +} + +func (m *AdminService) DeleteProjectDomainAttributes(ctx context.Context, request *admin.ProjectDomainAttributesDeleteRequest) ( + *admin.ProjectDomainAttributesDeleteResponse, error) { + defer m.interceptPanic(ctx, request) + if request == nil { + return nil, status.Errorf(codes.InvalidArgument, "Incorrect request, nil requests not allowed") + } + var response *admin.ProjectDomainAttributesDeleteResponse + var err error + m.Metrics.workflowAttributesEndpointMetrics.delete.Time(func() { + response, err = m.ProjectDomainAttributesManager.DeleteProjectDomainAttributes(ctx, *request) + }) + if err != nil { + return nil, util.TransformAndRecordError(err, &m.Metrics.workflowAttributesEndpointMetrics.delete) + } + + return response, nil +} + func (m *AdminService) UpdateProjectAttributes(ctx context.Context, request *admin.ProjectAttributesUpdateRequest) ( *admin.ProjectAttributesUpdateResponse, error) { defer m.interceptPanic(ctx, request) @@ -62,3 +134,39 @@ func (m *AdminService) UpdateProjectAttributes(ctx context.Context, request *adm return response, nil } + +func (m *AdminService) GetProjectAttributes(ctx context.Context, request *admin.ProjectAttributesGetRequest) ( + *admin.ProjectAttributesGetResponse, error) { + defer m.interceptPanic(ctx, request) + if request == nil { + return nil, status.Errorf(codes.InvalidArgument, "Incorrect request, nil requests not allowed") + } + var response *admin.ProjectAttributesGetResponse + var err error + m.Metrics.workflowAttributesEndpointMetrics.get.Time(func() { + response, err = m.ProjectAttributesManager.GetProjectAttributes(ctx, *request) + }) + if err != nil { + return nil, util.TransformAndRecordError(err, &m.Metrics.workflowAttributesEndpointMetrics.get) + } + + return response, nil +} + +func (m *AdminService) DeleteProjectAttributes(ctx context.Context, request *admin.ProjectAttributesDeleteRequest) ( + *admin.ProjectAttributesDeleteResponse, error) { + defer m.interceptPanic(ctx, request) + if request == nil { + return nil, status.Errorf(codes.InvalidArgument, "Incorrect request, nil requests not allowed") + } + var response *admin.ProjectAttributesDeleteResponse + var err error + m.Metrics.workflowAttributesEndpointMetrics.delete.Time(func() { + response, err = m.ProjectAttributesManager.DeleteProjectAttributes(ctx, *request) + }) + if err != nil { + return nil, util.TransformAndRecordError(err, &m.Metrics.workflowAttributesEndpointMetrics.delete) + } + + return response, nil +} diff --git a/pkg/rpc/adminservice/metrics.go b/pkg/rpc/adminservice/metrics.go index 351b9d22ad..6271dce33b 100644 --- a/pkg/rpc/adminservice/metrics.go +++ b/pkg/rpc/adminservice/metrics.go @@ -60,6 +60,8 @@ type attributeEndpointMetrics struct { scope promutils.Scope update util.RequestMetrics + get util.RequestMetrics + delete util.RequestMetrics } type taskEndpointMetrics struct { @@ -154,14 +156,20 @@ func InitMetrics(adminScope promutils.Scope) AdminMetrics { projectAttributesEndpointMetrics: attributeEndpointMetrics{ scope: adminScope, update: util.NewRequestMetrics(adminScope, "update_project_attrs"), + get: util.NewRequestMetrics(adminScope, "get_project_attrs"), + delete: util.NewRequestMetrics(adminScope, "delete_project_attrs"), }, projectDomainAttributesEndpointMetrics: attributeEndpointMetrics{ scope: adminScope, update: util.NewRequestMetrics(adminScope, "update_project_domain_attrs"), + get: util.NewRequestMetrics(adminScope, "get_project_domain_attrs"), + delete: util.NewRequestMetrics(adminScope, "delete_project_domain_attrs"), }, workflowAttributesEndpointMetrics: attributeEndpointMetrics{ scope: adminScope, update: util.NewRequestMetrics(adminScope, "update_workflow_attrs"), + get: util.NewRequestMetrics(adminScope, "get_workflow_attrs"), + delete: util.NewRequestMetrics(adminScope, "delete_workflow_attrs"), }, taskEndpointMetrics: taskEndpointMetrics{ scope: adminScope, diff --git a/pkg/rpc/adminservice/tests/project_domain_test.go b/pkg/rpc/adminservice/tests/project_domain_test.go index 218b8b9589..2a8decd760 100644 --- a/pkg/rpc/adminservice/tests/project_domain_test.go +++ b/pkg/rpc/adminservice/tests/project_domain_test.go @@ -12,7 +12,7 @@ import ( func TestUpdateProjectDomain(t *testing.T) { ctx := context.Background() - mockProjectDomainManager := mocks.MockProjectDomainManager{} + mockProjectDomainManager := mocks.MockProjectDomainAttributesManager{} var updateCalled bool mockProjectDomainManager.SetUpdateProjectDomainAttributes( func(ctx context.Context, @@ -22,7 +22,7 @@ func TestUpdateProjectDomain(t *testing.T) { }, ) mockServer := NewMockAdminServer(NewMockAdminServerInput{ - projectDomainManager: &mockProjectDomainManager, + projectDomainAttributesManager: &mockProjectDomainManager, }) resp, err := mockServer.UpdateProjectDomainAttributes(ctx, &admin.ProjectDomainAttributesUpdateRequest{}) diff --git a/pkg/rpc/adminservice/tests/util.go b/pkg/rpc/adminservice/tests/util.go index a60aad68b6..36fefe74c1 100644 --- a/pkg/rpc/adminservice/tests/util.go +++ b/pkg/rpc/adminservice/tests/util.go @@ -7,14 +7,14 @@ import ( ) type NewMockAdminServerInput struct { - executionManager *mocks.MockExecutionManager - launchPlanManager *mocks.MockLaunchPlanManager - nodeExecutionManager *mocks.MockNodeExecutionManager - projectManager *mocks.MockProjectManager - projectDomainManager *mocks.MockProjectDomainManager - taskManager *mocks.MockTaskManager - workflowManager *mocks.MockWorkflowManager - taskExecutionManager *mocks.MockTaskExecutionManager + executionManager *mocks.MockExecutionManager + launchPlanManager *mocks.MockLaunchPlanManager + nodeExecutionManager *mocks.MockNodeExecutionManager + projectManager *mocks.MockProjectManager + projectDomainAttributesManager *mocks.MockProjectDomainAttributesManager + taskManager *mocks.MockTaskManager + workflowManager *mocks.MockWorkflowManager + taskExecutionManager *mocks.MockTaskExecutionManager } func NewMockAdminServer(input NewMockAdminServerInput) *adminservice.AdminService { @@ -25,7 +25,7 @@ func NewMockAdminServer(input NewMockAdminServerInput) *adminservice.AdminServic NodeExecutionManager: input.nodeExecutionManager, TaskManager: input.taskManager, ProjectManager: input.projectManager, - ProjectDomainAttributesManager: input.projectDomainManager, + ProjectDomainAttributesManager: input.projectDomainAttributesManager, WorkflowManager: input.workflowManager, TaskExecutionManager: input.taskExecutionManager, Metrics: adminservice.InitMetrics(testScope), diff --git a/tests/attributes_test.go b/tests/attributes_test.go index 7c425d6017..842a5860f4 100644 --- a/tests/attributes_test.go +++ b/tests/attributes_test.go @@ -8,10 +8,6 @@ import ( "github.com/golang/protobuf/proto" - "github.com/lyft/flyteadmin/pkg/repositories/errors" - "github.com/lyft/flyteadmin/pkg/repositories/gormimpl" - "github.com/lyft/flyteadmin/pkg/repositories/transformers" - "github.com/stretchr/testify/assert" databaseConfig "github.com/lyft/flyteadmin/pkg/repositories/config" @@ -28,8 +24,13 @@ var matchingAttributes = &admin.MatchingAttributes{ }, } -func TestUpdateProjectAttributes(t *testing.T) { +func TestProjectAttributes(t *testing.T) { ctx := context.Background() + + db := databaseConfig.OpenDbConnection(databaseConfig.NewPostgresConfigProvider(getLocalDbConfig(), adminScope)) + truncateTableForTesting(db, "project_attributes") + db.Close() + client, conn := GetTestAdminServiceClient() defer conn.Close() @@ -43,18 +44,29 @@ func TestUpdateProjectAttributes(t *testing.T) { _, err := client.UpdateProjectAttributes(ctx, &req) assert.Nil(t, err) - // If we ever expose get/list ProjectAttributes APIs update the test below to call those instead. - db := databaseConfig.OpenDbConnection(databaseConfig.NewPostgresConfigProvider(geDbConfig(), adminScope)) - defer db.Close() - - errorsTransformer := errors.NewPostgresErrorTransformer(adminScope.NewSubScope("project_attrs_errors")) - projectRepo := gormimpl.NewProjectAttributesRepo(db, errorsTransformer, adminScope.NewSubScope("project_attrs")) + response, err := client.GetProjectAttributes(ctx, &admin.ProjectAttributesGetRequest{ + Project: "admintests", + ResourceType: admin.MatchableResource_TASK_RESOURCE, + }) + assert.Nil(t, err) + assert.True(t, proto.Equal(&admin.ProjectAttributesGetResponse{ + Attributes: &admin.ProjectAttributes{ + Project: "admintests", + MatchingAttributes: matchingAttributes, + }, + }, response)) - attributes, err := projectRepo.Get(ctx, "admintests", admin.MatchableResource_TASK_RESOURCE.String()) + _, err = client.DeleteProjectAttributes(ctx, &admin.ProjectAttributesDeleteRequest{ + Project: "admintests", + ResourceType: admin.MatchableResource_TASK_RESOURCE, + }) assert.Nil(t, err) - projectAttributes, err := transformers.FromProjectAttributesModel(attributes) - assert.True(t, proto.Equal(matchingAttributes, projectAttributes.MatchingAttributes)) + _, err = client.GetProjectAttributes(ctx, &admin.ProjectAttributesGetRequest{ + Project: "admintests", + ResourceType: admin.MatchableResource_TASK_RESOURCE, + }) + assert.EqualError(t, err, "rpc error: code = NotFound desc = entry not found") } func TestUpdateProjectDomainAttributes(t *testing.T) { @@ -62,6 +74,10 @@ func TestUpdateProjectDomainAttributes(t *testing.T) { client, conn := GetTestAdminServiceClient() defer conn.Close() + db := databaseConfig.OpenDbConnection(databaseConfig.NewPostgresConfigProvider(getLocalDbConfig(), adminScope)) + truncateTableForTesting(db, "project_domain_attributes") + db.Close() + req := admin.ProjectDomainAttributesUpdateRequest{ Attributes: &admin.ProjectDomainAttributes{ Project: "admintests", @@ -73,19 +89,33 @@ func TestUpdateProjectDomainAttributes(t *testing.T) { _, err := client.UpdateProjectDomainAttributes(ctx, &req) assert.Nil(t, err) - // If we ever expose get/list ProjectDomainAttributes APIs update the test below to call those instead. - db := databaseConfig.OpenDbConnection(databaseConfig.NewPostgresConfigProvider(getLocalDbConfig(), adminScope)) - defer db.Close() - - errorsTransformer := errors.NewPostgresErrorTransformer(adminScope.NewSubScope("project_domain_attrs_errors")) - projectDomainRepo := gormimpl.NewProjectDomainAttributesRepo(db, errorsTransformer, adminScope.NewSubScope("project_domain_attrs")) + response, err := client.GetProjectDomainAttributes(ctx, &admin.ProjectDomainAttributesGetRequest{ + Project: "admintests", + Domain: "development", + ResourceType: admin.MatchableResource_TASK_RESOURCE, + }) + assert.Nil(t, err) + assert.True(t, proto.Equal(&admin.ProjectDomainAttributesGetResponse{ + Attributes: &admin.ProjectDomainAttributes{ + Project: "admintests", + Domain: "development", + MatchingAttributes: matchingAttributes, + }, + }, response)) - attributes, err := projectDomainRepo.Get(ctx, "admintests", "development", - admin.MatchableResource_TASK_RESOURCE.String()) + _, err = client.DeleteProjectDomainAttributes(ctx, &admin.ProjectDomainAttributesDeleteRequest{ + Project: "admintests", + Domain: "development", + ResourceType: admin.MatchableResource_TASK_RESOURCE, + }) assert.Nil(t, err) - projectDomainAttributes, err := transformers.FromProjectDomainAttributesModel(attributes) - assert.True(t, proto.Equal(matchingAttributes, projectDomainAttributes.MatchingAttributes)) + _, err = client.GetProjectDomainAttributes(ctx, &admin.ProjectDomainAttributesGetRequest{ + Project: "admintests", + Domain: "development", + ResourceType: admin.MatchableResource_TASK_RESOURCE, + }) + assert.EqualError(t, err, "rpc error: code = NotFound desc = entry not found") } func TestUpdateWorkflowAttributes(t *testing.T) { @@ -93,6 +123,10 @@ func TestUpdateWorkflowAttributes(t *testing.T) { client, conn := GetTestAdminServiceClient() defer conn.Close() + db := databaseConfig.OpenDbConnection(databaseConfig.NewPostgresConfigProvider(getLocalDbConfig(), adminScope)) + truncateTableForTesting(db, "workflow_attributes") + db.Close() + req := admin.WorkflowAttributesUpdateRequest{ Attributes: &admin.WorkflowAttributes{ Project: "admintests", @@ -105,17 +139,35 @@ func TestUpdateWorkflowAttributes(t *testing.T) { _, err := client.UpdateWorkflowAttributes(ctx, &req) assert.Nil(t, err) - // If we ever expose get/list WorkflowAttributes APIs update the test below to call those instead. - db := databaseConfig.OpenDbConnection(databaseConfig.NewPostgresConfigProvider(getLocalDbConfig(), adminScope)) - defer db.Close() - - errorsTransformer := errors.NewPostgresErrorTransformer(adminScope.NewSubScope("workflow_attrs_errors")) - workflowRepo := gormimpl.NewWorkflowAttributesRepo(db, errorsTransformer, adminScope.NewSubScope("workflow_attrs")) - - attributes, err := workflowRepo.Get(ctx, "admintests", "development", "workflow", - admin.MatchableResource_TASK_RESOURCE.String()) + response, err := client.GetWorkflowAttributes(ctx, &admin.WorkflowAttributesGetRequest{ + Project: "admintests", + Domain: "development", + Workflow: "workflow", + ResourceType: admin.MatchableResource_TASK_RESOURCE, + }) + assert.Nil(t, err) + assert.True(t, proto.Equal(&admin.WorkflowAttributesGetResponse{ + Attributes: &admin.WorkflowAttributes{ + Project: "admintests", + Domain: "development", + Workflow: "workflow", + MatchingAttributes: matchingAttributes, + }, + }, response)) + + _, err = client.DeleteWorkflowAttributes(ctx, &admin.WorkflowAttributesDeleteRequest{ + Project: "admintests", + Domain: "development", + Workflow: "workflow", + ResourceType: admin.MatchableResource_TASK_RESOURCE, + }) assert.Nil(t, err) - workflowAttributes, err := transformers.FromWorkflowAttributesModel(attributes) - assert.True(t, proto.Equal(matchingAttributes, workflowAttributes.MatchingAttributes)) + _, err = client.GetWorkflowAttributes(ctx, &admin.WorkflowAttributesGetRequest{ + Project: "admintests", + Domain: "development", + Workflow: "workflow", + ResourceType: admin.MatchableResource_TASK_RESOURCE, + }) + assert.EqualError(t, err, "rpc error: code = NotFound desc = entry not found") } diff --git a/tests/bootstrap.go b/tests/bootstrap.go index a317f4d481..559b70ba0f 100644 --- a/tests/bootstrap.go +++ b/tests/bootstrap.go @@ -5,6 +5,8 @@ package tests import ( "fmt" + "github.com/jinzhu/gorm" + database_config "github.com/lyft/flyteadmin/pkg/repositories/config" "github.com/lyft/flytestdlib/promutils" ) @@ -34,6 +36,10 @@ func getLocalDbConfig() database_config.DbConfig { } } +func truncateTableForTesting(db *gorm.DB, tableName string) { + db.Exec(fmt.Sprintf("TRUNCATE TABLE %s;", tableName)) +} + func truncateAllTablesForTestingOnly() { // Load the running configuration in order to talk to the running flyteadmin instance fmt.Println("Truncating tables")