mirror of
https://github.com/paralus/paralus.git
synced 2026-05-19 14:56:57 +00:00
This was done inorder to support transactions which will be done in the next PR. This is the first step towards that.
353 lines
9.4 KiB
Go
353 lines
9.4 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/RafaySystems/rcloud-base/internal/models"
|
|
"github.com/RafaySystems/rcloud-base/internal/persistence/provider/pg"
|
|
v3 "github.com/RafaySystems/rcloud-base/proto/types/commonpb/v3"
|
|
systemv3 "github.com/RafaySystems/rcloud-base/proto/types/systempb/v3"
|
|
"github.com/google/uuid"
|
|
bun "github.com/uptrace/bun"
|
|
"google.golang.org/protobuf/types/known/timestamppb"
|
|
)
|
|
|
|
const (
|
|
projectKind = "Project"
|
|
projectListKind = "ProjectList"
|
|
)
|
|
|
|
// ProjectService is the interface for project operations
|
|
type ProjectService interface {
|
|
// create project
|
|
Create(ctx context.Context, project *systemv3.Project) (*systemv3.Project, error)
|
|
// get project by id
|
|
GetByID(ctx context.Context, id string) (*systemv3.Project, error)
|
|
// get project by name
|
|
GetByName(ctx context.Context, name string) (*systemv3.Project, error)
|
|
// create or update project
|
|
Update(ctx context.Context, project *systemv3.Project) (*systemv3.Project, error)
|
|
// delete project
|
|
Delete(ctx context.Context, project *systemv3.Project) (*systemv3.Project, error)
|
|
// list projects
|
|
List(ctx context.Context, project *systemv3.Project) (*systemv3.ProjectList, error)
|
|
//TODO Associate project with groups, user, roles
|
|
}
|
|
|
|
// projectService implements ProjectService
|
|
type projectService struct {
|
|
db *bun.DB
|
|
}
|
|
|
|
// NewProjectService return new project service
|
|
func NewProjectService(db *bun.DB) ProjectService {
|
|
return &projectService{db}
|
|
}
|
|
|
|
func (s *projectService) Create(ctx context.Context, project *systemv3.Project) (*systemv3.Project, error) {
|
|
|
|
if project.Metadata.Organization == "" {
|
|
return nil, fmt.Errorf("missing organization in metadata")
|
|
}
|
|
|
|
var org models.Organization
|
|
_, err := pg.GetByName(ctx, s.db, project.Metadata.Organization, &org)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
//convert v3 spec to internal models
|
|
proj := models.Project{
|
|
Name: project.GetMetadata().GetName(),
|
|
Description: project.GetMetadata().GetDescription(),
|
|
CreatedAt: time.Now(),
|
|
ModifiedAt: time.Now(),
|
|
Trash: false,
|
|
OrganizationId: org.ID,
|
|
PartnerId: org.PartnerId,
|
|
Default: project.GetSpec().GetDefault(),
|
|
}
|
|
entity, err := pg.Create(ctx, s.db, &proj)
|
|
if err != nil {
|
|
project.Status = &v3.Status{
|
|
ConditionType: "Create",
|
|
ConditionStatus: v3.ConditionStatus_StatusFailed,
|
|
LastUpdated: timestamppb.Now(),
|
|
}
|
|
return project, err
|
|
}
|
|
|
|
//update v3 spec
|
|
if createdProject, ok := entity.(*models.Project); ok {
|
|
project.Metadata.Id = createdProject.ID.String()
|
|
project.Spec = &systemv3.ProjectSpec{
|
|
Default: createdProject.Default,
|
|
}
|
|
if project.Status != nil {
|
|
project.Status = &v3.Status{
|
|
ConditionType: "Create",
|
|
ConditionStatus: v3.ConditionStatus_StatusOK,
|
|
LastUpdated: timestamppb.Now(),
|
|
}
|
|
}
|
|
}
|
|
|
|
return project, nil
|
|
|
|
}
|
|
|
|
func (s *projectService) GetByID(ctx context.Context, id string) (*systemv3.Project, error) {
|
|
|
|
project := &systemv3.Project{
|
|
ApiVersion: apiVersion,
|
|
Kind: projectKind,
|
|
Metadata: &v3.Metadata{
|
|
Id: id,
|
|
},
|
|
}
|
|
|
|
uid, err := uuid.Parse(id)
|
|
if err != nil {
|
|
project.Status = &v3.Status{
|
|
ConditionType: "Describe",
|
|
ConditionStatus: v3.ConditionStatus_StatusFailed,
|
|
LastUpdated: timestamppb.Now(),
|
|
Reason: err.Error(),
|
|
}
|
|
return project, err
|
|
}
|
|
entity, err := pg.GetByID(ctx, s.db, uid, &models.Project{})
|
|
if err != nil {
|
|
project.Status = &v3.Status{
|
|
ConditionType: "Describe",
|
|
ConditionStatus: v3.ConditionStatus_StatusFailed,
|
|
LastUpdated: timestamppb.Now(),
|
|
Reason: err.Error(),
|
|
}
|
|
return project, err
|
|
}
|
|
|
|
if proj, ok := entity.(*models.Project); ok {
|
|
|
|
project.Metadata = &v3.Metadata{
|
|
Name: proj.Name,
|
|
Description: proj.Description,
|
|
Id: proj.ID.String(),
|
|
Organization: proj.OrganizationId.String(),
|
|
Partner: proj.PartnerId.String(),
|
|
ModifiedAt: timestamppb.New(proj.ModifiedAt),
|
|
}
|
|
project.Spec = &systemv3.ProjectSpec{
|
|
Default: proj.Default,
|
|
}
|
|
project.Status = &v3.Status{
|
|
LastUpdated: timestamppb.Now(),
|
|
ConditionType: "Describe",
|
|
ConditionStatus: v3.ConditionStatus_StatusOK,
|
|
}
|
|
|
|
return project, nil
|
|
}
|
|
return project, nil
|
|
|
|
}
|
|
|
|
func (s *projectService) GetByName(ctx context.Context, name string) (*systemv3.Project, error) {
|
|
|
|
project := &systemv3.Project{
|
|
ApiVersion: apiVersion,
|
|
Kind: projectKind,
|
|
Metadata: &v3.Metadata{
|
|
Name: name,
|
|
},
|
|
}
|
|
|
|
entity, err := pg.GetByName(ctx, s.db, name, &models.Project{})
|
|
if err != nil {
|
|
project.Status = &v3.Status{
|
|
ConditionType: "Describe",
|
|
ConditionStatus: v3.ConditionStatus_StatusFailed,
|
|
LastUpdated: timestamppb.Now(),
|
|
Reason: err.Error(),
|
|
}
|
|
return project, err
|
|
}
|
|
|
|
if proj, ok := entity.(*models.Project); ok {
|
|
|
|
var org models.Organization
|
|
_, err := pg.GetByID(ctx, s.db, proj.OrganizationId, &org)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var partner models.Partner
|
|
_, err = pg.GetByID(ctx, s.db, proj.PartnerId, &partner)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
project.Metadata = &v3.Metadata{
|
|
Name: proj.Name,
|
|
Description: proj.Description,
|
|
Organization: org.Name,
|
|
Partner: partner.Name,
|
|
ModifiedAt: timestamppb.New(proj.ModifiedAt),
|
|
}
|
|
project.Spec = &systemv3.ProjectSpec{
|
|
Default: proj.Default,
|
|
}
|
|
project.Status = &v3.Status{
|
|
LastUpdated: timestamppb.Now(),
|
|
ConditionType: "Describe",
|
|
ConditionStatus: v3.ConditionStatus_StatusOK,
|
|
}
|
|
|
|
return project, nil
|
|
}
|
|
return project, nil
|
|
|
|
}
|
|
|
|
func (s *projectService) Update(ctx context.Context, project *systemv3.Project) (*systemv3.Project, error) {
|
|
|
|
entity, err := pg.GetByName(ctx, s.db, project.Metadata.Name, &models.Project{})
|
|
if err != nil {
|
|
project.Status = &v3.Status{
|
|
ConditionType: "Update",
|
|
ConditionStatus: v3.ConditionStatus_StatusFailed,
|
|
LastUpdated: timestamppb.Now(),
|
|
Reason: err.Error(),
|
|
}
|
|
return project, err
|
|
}
|
|
|
|
if proj, ok := entity.(*models.Project); ok {
|
|
//update project details
|
|
proj.Description = project.Metadata.Description
|
|
proj.Default = project.Spec.Default
|
|
proj.ModifiedAt = time.Now()
|
|
|
|
_, err = pg.Update(ctx, s.db, proj.ID, proj)
|
|
if err != nil {
|
|
project.Status = &v3.Status{
|
|
ConditionType: "Update",
|
|
ConditionStatus: v3.ConditionStatus_StatusFailed,
|
|
LastUpdated: timestamppb.Now(),
|
|
Reason: err.Error(),
|
|
}
|
|
return project, err
|
|
}
|
|
|
|
//update spec and status
|
|
project.Spec = &systemv3.ProjectSpec{
|
|
Default: proj.Default,
|
|
}
|
|
project.Status = &v3.Status{
|
|
ConditionType: "Update",
|
|
ConditionStatus: v3.ConditionStatus_StatusOK,
|
|
LastUpdated: timestamppb.Now(),
|
|
}
|
|
}
|
|
|
|
return project, nil
|
|
}
|
|
|
|
func (s *projectService) Delete(ctx context.Context, project *systemv3.Project) (*systemv3.Project, error) {
|
|
entity, err := pg.GetByName(ctx, s.db, project.Metadata.Name, &models.Project{})
|
|
if err != nil {
|
|
project.Status = &v3.Status{
|
|
ConditionType: "Delete",
|
|
ConditionStatus: v3.ConditionStatus_StatusFailed,
|
|
LastUpdated: timestamppb.Now(),
|
|
Reason: err.Error(),
|
|
}
|
|
return project, err
|
|
}
|
|
if proj, ok := entity.(*models.Project); ok {
|
|
proj.Trash = true
|
|
_, err := pg.Update(ctx, s.db, proj.ID, proj)
|
|
if err != nil {
|
|
project.Status = &v3.Status{
|
|
ConditionType: "Delete",
|
|
ConditionStatus: v3.ConditionStatus_StatusFailed,
|
|
LastUpdated: timestamppb.Now(),
|
|
Reason: err.Error(),
|
|
}
|
|
return project, err
|
|
}
|
|
//update v3 spec
|
|
project.Metadata.Id = proj.ID.String()
|
|
project.Metadata.Name = proj.Name
|
|
project.Status = &v3.Status{
|
|
ConditionType: "Delete",
|
|
ConditionStatus: v3.ConditionStatus_StatusOK,
|
|
LastUpdated: timestamppb.Now(),
|
|
}
|
|
}
|
|
|
|
return project, nil
|
|
}
|
|
|
|
func (s *projectService) List(ctx context.Context, project *systemv3.Project) (*systemv3.ProjectList, error) {
|
|
|
|
var projects []*systemv3.Project
|
|
projectList := &systemv3.ProjectList{
|
|
ApiVersion: apiVersion,
|
|
Kind: projectListKind,
|
|
Metadata: &v3.ListMetadata{
|
|
Count: 0,
|
|
},
|
|
}
|
|
if len(project.Metadata.Organization) > 0 {
|
|
var org models.Organization
|
|
_, err := pg.GetByName(ctx, s.db, project.Metadata.Organization, &org)
|
|
if err != nil {
|
|
return projectList, err
|
|
}
|
|
var part models.Partner
|
|
_, err = pg.GetByName(ctx, s.db, project.Metadata.Partner, &part)
|
|
if err != nil {
|
|
return projectList, err
|
|
}
|
|
var projs []models.Project
|
|
entities, err := pg.List(ctx, s.db, uuid.NullUUID{UUID: part.ID, Valid: true}, uuid.NullUUID{UUID: org.ID, Valid: true}, &projs)
|
|
if err != nil {
|
|
return projectList, err
|
|
}
|
|
if projs, ok := entities.(*[]models.Project); ok {
|
|
for _, proj := range *projs {
|
|
labels := make(map[string]string)
|
|
labels["organization"] = proj.OrganizationId.String()
|
|
labels["partner"] = proj.PartnerId.String()
|
|
|
|
project.Metadata = &v3.Metadata{
|
|
Name: proj.Name,
|
|
Description: proj.Description,
|
|
Id: proj.ID.String(),
|
|
Organization: proj.OrganizationId.String(),
|
|
Partner: proj.PartnerId.String(),
|
|
Labels: labels,
|
|
ModifiedAt: timestamppb.New(proj.ModifiedAt),
|
|
}
|
|
project.Spec = &systemv3.ProjectSpec{
|
|
Default: proj.Default,
|
|
}
|
|
projects = append(projects, project)
|
|
}
|
|
|
|
//update the list metadata and items response
|
|
projectList.Metadata = &v3.ListMetadata{
|
|
Count: int64(len(projects)),
|
|
}
|
|
projectList.Items = projects
|
|
}
|
|
|
|
} else {
|
|
return projectList, fmt.Errorf("missing organization id in metadata")
|
|
}
|
|
return projectList, nil
|
|
}
|