Moves the `domain` and `ports` packages from `internal/core` to `internal`. This refactoring simplifies the directory structure by elevating the core architectural concepts of domain and ports to the top level of the `internal` directory. The `core` directory is now removed as its only purpose was to house these two packages. All import paths across the project have been updated to reflect this change.
185 lines
6.1 KiB
Go
185 lines
6.1 KiB
Go
package instance
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"edp.buildth.ing/DevFW-CICD/edge-connect-client/internal/domain"
|
|
"edp.buildth.ing/DevFW-CICD/edge-connect-client/internal/ports/driven"
|
|
"edp.buildth.ing/DevFW-CICD/edge-connect-client/internal/ports/driving"
|
|
)
|
|
|
|
type service struct {
|
|
appInstanceRepo driven.AppInstanceRepository
|
|
}
|
|
|
|
func NewService(appInstanceRepo driven.AppInstanceRepository) driving.AppInstanceService {
|
|
return &service{appInstanceRepo: appInstanceRepo}
|
|
}
|
|
|
|
func (s *service) CreateAppInstance(ctx context.Context, region string, appInst *domain.AppInstance) error {
|
|
if err := s.validateAppInstance(appInst); err != nil {
|
|
return err
|
|
}
|
|
|
|
if region == "" {
|
|
return domain.ErrMissingRegion
|
|
}
|
|
|
|
if err := s.appInstanceRepo.CreateAppInstance(ctx, region, appInst); err != nil {
|
|
if domain.IsNotFoundError(err) {
|
|
return domain.NewInstanceError(domain.ErrResourceConflict, "CreateAppInstance", appInst.Key, region,
|
|
"app instance may already exist or have conflicting configuration")
|
|
}
|
|
return domain.NewInstanceError(domain.ErrInternalError, "CreateAppInstance", appInst.Key, region,
|
|
"failed to create app instance").WithDetails(err.Error())
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *service) ShowAppInstance(ctx context.Context, region string, appInstKey domain.AppInstanceKey) (*domain.AppInstance, error) {
|
|
if err := s.validateAppInstanceKey(appInstKey); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if region == "" {
|
|
return nil, domain.ErrMissingRegion
|
|
}
|
|
|
|
instance, err := s.appInstanceRepo.ShowAppInstance(ctx, region, appInstKey)
|
|
if err != nil {
|
|
if domain.IsNotFoundError(err) {
|
|
return nil, domain.NewInstanceError(domain.ErrResourceNotFound, "ShowAppInstance", appInstKey, region,
|
|
"app instance does not exist")
|
|
}
|
|
return nil, domain.NewInstanceError(domain.ErrInternalError, "ShowAppInstance", appInstKey, region,
|
|
"failed to retrieve app instance").WithDetails(err.Error())
|
|
}
|
|
|
|
return instance, nil
|
|
}
|
|
|
|
func (s *service) ShowAppInstances(ctx context.Context, region string, appInstKey domain.AppInstanceKey) ([]domain.AppInstance, error) {
|
|
if region == "" {
|
|
return nil, domain.ErrMissingRegion
|
|
}
|
|
|
|
instances, err := s.appInstanceRepo.ShowAppInstances(ctx, region, appInstKey)
|
|
if err != nil {
|
|
return nil, domain.NewInstanceError(domain.ErrInternalError, "ShowAppInstances", appInstKey, region,
|
|
"failed to list app instances").WithDetails(err.Error())
|
|
}
|
|
|
|
return instances, nil
|
|
}
|
|
|
|
func (s *service) DeleteAppInstance(ctx context.Context, region string, appInstKey domain.AppInstanceKey) error {
|
|
if err := s.validateAppInstanceKey(appInstKey); err != nil {
|
|
return err
|
|
}
|
|
|
|
if region == "" {
|
|
return domain.ErrMissingRegion
|
|
}
|
|
|
|
if err := s.appInstanceRepo.DeleteAppInstance(ctx, region, appInstKey); err != nil {
|
|
if domain.IsNotFoundError(err) {
|
|
return domain.NewInstanceError(domain.ErrResourceNotFound, "DeleteAppInstance", appInstKey, region,
|
|
"app instance does not exist")
|
|
}
|
|
return domain.NewInstanceError(domain.ErrInternalError, "DeleteAppInstance", appInstKey, region,
|
|
"failed to delete app instance").WithDetails(err.Error())
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *service) UpdateAppInstance(ctx context.Context, region string, appInst *domain.AppInstance) error {
|
|
if err := s.validateAppInstance(appInst); err != nil {
|
|
return err
|
|
}
|
|
|
|
if region == "" {
|
|
return domain.ErrMissingRegion
|
|
}
|
|
|
|
if err := s.appInstanceRepo.UpdateAppInstance(ctx, region, appInst); err != nil {
|
|
if domain.IsNotFoundError(err) {
|
|
return domain.NewInstanceError(domain.ErrResourceConflict, "UpdateAppInstance", appInst.Key, region,
|
|
"app instance may already exist or have conflicting configuration")
|
|
}
|
|
return domain.NewInstanceError(domain.ErrInternalError, "UpdateAppInstance", appInst.Key, region,
|
|
"failed to update app instance").WithDetails(err.Error())
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *service) RefreshAppInstance(ctx context.Context, region string, appInstKey domain.AppInstanceKey) error {
|
|
if err := s.validateAppInstanceKey(appInstKey); err != nil {
|
|
return err
|
|
}
|
|
|
|
if region == "" {
|
|
return domain.ErrMissingRegion
|
|
}
|
|
|
|
// Note: The driven port (repository) does not currently have a Refresh method.
|
|
// This is a placeholder implementation.
|
|
// To fully implement this, we would need to add RefreshAppInstance to the AppInstanceRepository interface
|
|
// and implement it in the edgeconnect adapter.
|
|
// For now, we can just return nil or a 'not implemented' error.
|
|
// Let's delegate to the Show method as a temporary measure.
|
|
_, err := s.appInstanceRepo.ShowAppInstance(ctx, region, appInstKey)
|
|
if err != nil {
|
|
if domain.IsNotFoundError(err) {
|
|
return domain.NewInstanceError(domain.ErrResourceNotFound, "RefreshAppInstance", appInstKey, region,
|
|
"app instance does not exist")
|
|
}
|
|
return domain.NewInstanceError(domain.ErrInternalError, "RefreshAppInstance", appInstKey, region,
|
|
"failed to refresh app instance").WithDetails(err.Error())
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// validateAppInstance performs business logic validation on an app instance
|
|
func (s *service) validateAppInstance(appInst *domain.AppInstance) error {
|
|
if appInst == nil {
|
|
return domain.NewDomainError(domain.ErrValidationFailed, "app instance cannot be nil")
|
|
}
|
|
|
|
if err := s.validateAppInstanceKey(appInst.Key); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Validate flavor if present
|
|
if strings.TrimSpace(appInst.Flavor.Name) == "" {
|
|
return domain.NewDomainError(domain.ErrValidationFailed, "flavor name is required")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// validateAppInstanceKey performs business logic validation on an app instance key
|
|
func (s *service) validateAppInstanceKey(appInstKey domain.AppInstanceKey) error {
|
|
if strings.TrimSpace(appInstKey.Organization) == "" {
|
|
return domain.ErrInvalidInstanceKey.WithDetails("organization is required")
|
|
}
|
|
|
|
if strings.TrimSpace(appInstKey.Name) == "" {
|
|
return domain.ErrInvalidInstanceKey.WithDetails("name is required")
|
|
}
|
|
|
|
// Validate embedded cloudlet key
|
|
if strings.TrimSpace(appInstKey.CloudletKey.Organization) == "" {
|
|
return domain.ErrInvalidInstanceKey.WithDetails("cloudlet organization is required")
|
|
}
|
|
|
|
if strings.TrimSpace(appInstKey.CloudletKey.Name) == "" {
|
|
return domain.ErrInvalidInstanceKey.WithDetails("cloudlet name is required")
|
|
}
|
|
|
|
return nil
|
|
}
|