package services import ( "fmt" "git.linuxforward.com/byop/byop-engine/dbstore" "git.linuxforward.com/byop/byop-engine/models" "github.com/google/uuid" ) // BlueprintService handles business logic for Blueprints type BlueprintService struct { store *dbstore.BlueprintStore } // NewBlueprintService creates a new BlueprintService func NewBlueprintService(store *dbstore.BlueprintStore) *BlueprintService { return &BlueprintService{store: store} } // CreateBlueprint creates a new deployment Blueprint func (s *BlueprintService) CreateBlueprint(Blueprint *models.Blueprint) error { // Generate UUID if not provided if Blueprint.ID == "" { Blueprint.ID = uuid.New().String() } // Validate Blueprint configuration if err := validateBlueprintConfig(Blueprint.Config); err != nil { return fmt.Errorf("invalid Blueprint configuration: %w", err) } // Persist the Blueprint return s.store.Create(Blueprint) } // GetBlueprint retrieves a Blueprint by ID func (s *BlueprintService) GetBlueprint(id string) (*models.Blueprint, error) { Blueprint, err := s.store.GetByID(id) if err != nil { return nil, fmt.Errorf("failed to retrieve Blueprint: %w", err) } return Blueprint, nil } // UpdateBlueprint updates an existing Blueprint func (s *BlueprintService) UpdateBlueprint(Blueprint *models.Blueprint) error { if Blueprint.ID == "" { return fmt.Errorf("Blueprint ID is required for update") } // Check if Blueprint exists existingBlueprint, err := s.store.GetByID(Blueprint.ID) if err != nil { return fmt.Errorf("failed to check if Blueprint exists: %w", err) } if existingBlueprint == nil { return fmt.Errorf("Blueprint with ID %s not found", Blueprint.ID) } // Validate Blueprint configuration if err := validateBlueprintConfig(Blueprint.Config); err != nil { return fmt.Errorf("invalid Blueprint configuration: %w", err) } return s.store.Update(Blueprint) } // DeleteBlueprint deletes a Blueprint by ID func (s *BlueprintService) DeleteBlueprint(id string) error { // Check if Blueprint exists Blueprint, err := s.store.GetByID(id) if err != nil { return fmt.Errorf("failed to check if Blueprint exists: %w", err) } if Blueprint == nil { return fmt.Errorf("Blueprint with ID %s not found", id) } // Check if the Blueprint has deployments BlueprintWithDeployments, err := s.store.GetBlueprintWithDeployments(id) if err != nil { return fmt.Errorf("failed to check Blueprint deployments: %w", err) } // Don't allow deletion if there are active deployments if len(BlueprintWithDeployments.Deployments) > 0 { return fmt.Errorf("cannot delete Blueprint with active deployments") } return s.store.Delete(id) } // ListBlueprints retrieves all Blueprints with optional filtering func (s *BlueprintService) ListBlueprints(filter map[string]interface{}) ([]*models.Blueprint, error) { return s.store.List(filter) } // GetBlueprintDeployments retrieves all deployments for a Blueprint func (s *BlueprintService) GetBlueprintDeployments(id string) ([]models.Deployment, error) { // First check if the Blueprint exists Blueprint, err := s.store.GetByID(id) if err != nil { return nil, fmt.Errorf("failed to check if Blueprint exists: %w", err) } if Blueprint == nil { return nil, fmt.Errorf("Blueprint with ID %s not found", id) } // Get Blueprint with deployments BlueprintWithDeployments, err := s.store.GetBlueprintWithDeployments(id) if err != nil { return nil, fmt.Errorf("failed to retrieve Blueprint deployments: %w", err) } return BlueprintWithDeployments.Deployments, nil } // GetBlueprintByVersion retrieves a Blueprint by name and version func (s *BlueprintService) GetBlueprintByVersion(name, version string) (*models.Blueprint, error) { Blueprint, err := s.store.GetByVersion(name, version) if err != nil { return nil, fmt.Errorf("failed to retrieve Blueprint: %w", err) } return Blueprint, nil } // validateBlueprintConfig validates the Blueprint configuration func validateBlueprintConfig(config models.BlueprintConfig) error { // Validate that at least one app is defined if len(config.Components) == 0 { return fmt.Errorf("Blueprint must define at least one app") } // Validate each app in the Blueprint for i, app := range config.Components { if app.Name == "" { return fmt.Errorf("app at index %d must have a name", i) } // Validate resource configuration if app.Resources.CPU == "" { return fmt.Errorf("app '%s' must specify CPU resources", app.Name) } if app.Resources.Memory == "" { return fmt.Errorf("app '%s' must specify memory resources", app.Name) } } // Add additional validation logic as needed return nil }