...

Source file src/edge-infra.dev/pkg/edge/api/services/artifact_registry_service.go

Documentation: edge-infra.dev/pkg/edge/api/services

     1  package services
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"errors"
     7  
     8  	"github.com/google/uuid"
     9  
    10  	sqlerr "edge-infra.dev/pkg/edge/api/apierror/sql"
    11  	"edge-infra.dev/pkg/edge/api/graph/model"
    12  	sqlquery "edge-infra.dev/pkg/edge/api/sql"
    13  	"edge-infra.dev/pkg/edge/api/utils"
    14  )
    15  
    16  //go:generate mockgen -destination=../mocks/mock_artifact_registry_service.go -package=mocks edge-infra.dev/pkg/edge/api/services ArtifactRegistryService
    17  type ArtifactRegistryService interface {
    18  	// Retrieve the artifact registry entry with a given ID.
    19  	GetArtifactRegistry(ctx context.Context, registryEdgeID string) (*model.ArtifactRegistry, error)
    20  	// Retrieve all artifact registries entries for a given banner.
    21  	GetArtifactRegistriesForBanner(ctx context.Context, bannerEdgeID string) ([]*model.ArtifactRegistry, error)
    22  	// Retrieve all artifact registries entries for a given cluster.
    23  	GetArtifactRegistriesForCluster(ctx context.Context, clusterEdgeID string) ([]*model.ArtifactRegistry, error)
    24  	// Create a new artifact registry entry.
    25  	CreateArtifactRegistryEntry(ctx context.Context, createArtifactRegistry *model.ArtifactRegistryCreateInput) (*model.ArtifactRegistry, error)
    26  	// Update the artifact registry entry with a given ID.
    27  	UpdateArtifactRegistryEntry(ctx context.Context, registryEdgeID string, updateArtifactRegistry *model.ArtifactRegistryUpdateInput) (*model.ArtifactRegistry, error)
    28  	// Delete the artifact registry entry with a given ID.
    29  	DeleteArtifactRegistryEntry(ctx context.Context, registryEdgeID string) (bool, error)
    30  
    31  	// Retrieve the cluster artifact registry entry with a given ID.
    32  	GetClusterArtifactRegistry(ctx context.Context, clusterRegistryEdgeID string) (*model.ClusterArtifactRegistry, error)
    33  	// Retrieve all cluster artifact registries for a given cluster.
    34  	GetClusterArtifactRegistries(ctx context.Context, clusterEdgeID string) ([]*model.ClusterArtifactRegistry, error)
    35  	// Create a new cluster artifact registry entry.
    36  	CreateClusterArtifactRegistryEntry(ctx context.Context, createClusterArtifactRegistry *model.ClusterArtifactRegistryCreateInput) (*model.ClusterArtifactRegistry, error)
    37  	// Delete the cluster artifact registry entry with a given ID.
    38  	DeleteClusterArtifactRegistryEntry(ctx context.Context, clusterRegistryEdgeID string) (bool, error)
    39  }
    40  
    41  func NewArtifactRegistryService(sqlDB *sql.DB) ArtifactRegistryService {
    42  	return &artifactRegistryService{
    43  		SQLDB: sqlDB,
    44  	}
    45  }
    46  
    47  type artifactRegistryService struct {
    48  	SQLDB *sql.DB
    49  }
    50  
    51  func (s *artifactRegistryService) GetArtifactRegistry(ctx context.Context, registryEdgeID string) (*model.ArtifactRegistry, error) {
    52  	row := s.SQLDB.QueryRowContext(ctx, sqlquery.GetArtifactRegistryByIDQuery, registryEdgeID)
    53  	return s.scanArtifactRegistryRow(row)
    54  }
    55  
    56  func (s *artifactRegistryService) scanArtifactRegistryRow(row *sql.Row) (*model.ArtifactRegistry, error) {
    57  	artifactRegistry := &model.ArtifactRegistry{}
    58  	if err := row.Scan(&artifactRegistry.RegistryEdgeID, &artifactRegistry.BannerEdgeID, &artifactRegistry.Description, &artifactRegistry.URL); err != nil {
    59  		return nil, err
    60  	}
    61  	return artifactRegistry, nil
    62  }
    63  
    64  func (s *artifactRegistryService) GetArtifactRegistriesForBanner(ctx context.Context, bannerEdgeID string) ([]*model.ArtifactRegistry, error) {
    65  	rows, err := s.SQLDB.QueryContext(ctx, sqlquery.GetArtifactRegistriesForBannerQuery, bannerEdgeID)
    66  	if err != nil {
    67  		return nil, err
    68  	}
    69  	return s.scanArtifactRegistryRows(rows)
    70  }
    71  
    72  func (s *artifactRegistryService) GetArtifactRegistriesForCluster(ctx context.Context, clusterEdgeID string) ([]*model.ArtifactRegistry, error) {
    73  	rows, err := s.SQLDB.QueryContext(ctx, sqlquery.GetArtifactRegistriesForClusterQuery, clusterEdgeID)
    74  	if err != nil {
    75  		return nil, err
    76  	}
    77  	return s.scanArtifactRegistryRows(rows)
    78  }
    79  
    80  func (s *artifactRegistryService) scanArtifactRegistryRows(rows *sql.Rows) ([]*model.ArtifactRegistry, error) {
    81  	artifactRegistries := []*model.ArtifactRegistry{}
    82  
    83  	for rows.Next() {
    84  		artifactRegistry := &model.ArtifactRegistry{}
    85  		if err := rows.Scan(&artifactRegistry.RegistryEdgeID, &artifactRegistry.BannerEdgeID, &artifactRegistry.Description, &artifactRegistry.URL); err != nil {
    86  			return nil, err
    87  		}
    88  		artifactRegistries = append(artifactRegistries, artifactRegistry)
    89  	}
    90  
    91  	if err := rows.Err(); err != nil {
    92  		return nil, sqlerr.Wrap(err)
    93  	}
    94  
    95  	return artifactRegistries, nil
    96  }
    97  
    98  func (s *artifactRegistryService) CreateArtifactRegistryEntry(ctx context.Context, createArtifactRegistry *model.ArtifactRegistryCreateInput) (artifactRegistry *model.ArtifactRegistry, err error) {
    99  	if err := utils.ValidateArtifactRegistryCreateInput(createArtifactRegistry); err != nil {
   100  		return nil, err
   101  	}
   102  
   103  	transaction, err := s.SQLDB.BeginTx(ctx, nil)
   104  	if err != nil {
   105  		return nil, err
   106  	}
   107  
   108  	defer func() {
   109  		err = rollbackOnError(transaction, err)
   110  	}()
   111  
   112  	artifactRegistry = utils.CreateArtifactRegistryModel(
   113  		uuid.NewString(),
   114  		createArtifactRegistry.BannerEdgeID,
   115  		createArtifactRegistry.URL,
   116  		createArtifactRegistry.Description,
   117  	)
   118  
   119  	args := []any{
   120  		artifactRegistry.RegistryEdgeID,
   121  		artifactRegistry.BannerEdgeID,
   122  		artifactRegistry.Description,
   123  		artifactRegistry.URL,
   124  	}
   125  
   126  	if _, err = transaction.ExecContext(ctx, sqlquery.ArtifactRegistryCreateQuery, args...); err != nil {
   127  		return
   128  	}
   129  
   130  	if err = transaction.Commit(); err != nil {
   131  		return
   132  	}
   133  
   134  	return artifactRegistry, nil
   135  }
   136  
   137  func (s *artifactRegistryService) UpdateArtifactRegistryEntry(ctx context.Context, registryEdgeID string, updateArtifactRegistry *model.ArtifactRegistryUpdateInput) (artifactRegistry *model.ArtifactRegistry, err error) {
   138  	if err := utils.ValidateArtifactRegistryUpdateInput(updateArtifactRegistry); err != nil {
   139  		return nil, err
   140  	}
   141  
   142  	currentArtifactRegistry, err := s.GetArtifactRegistry(ctx, registryEdgeID)
   143  	if err != nil {
   144  		return nil, err
   145  	}
   146  
   147  	// return current if there are no changes to be made
   148  	if !utils.ArtifactRegistryNeedsUpdating(currentArtifactRegistry, updateArtifactRegistry) {
   149  		return currentArtifactRegistry, nil
   150  	}
   151  
   152  	transaction, err := s.SQLDB.BeginTx(ctx, nil)
   153  	if err != nil {
   154  		return nil, err
   155  	}
   156  
   157  	defer func() {
   158  		err = rollbackOnError(transaction, err)
   159  	}()
   160  
   161  	artifactRegistry = utils.UpdateArtifactRegistry(currentArtifactRegistry, updateArtifactRegistry)
   162  
   163  	args := []any{
   164  		artifactRegistry.Description,
   165  		artifactRegistry.URL,
   166  		registryEdgeID,
   167  	}
   168  
   169  	if _, err = transaction.ExecContext(ctx, sqlquery.ArtifactRegistryUpdateQuery, args...); err != nil {
   170  		return
   171  	}
   172  
   173  	if err = transaction.Commit(); err != nil {
   174  		return
   175  	}
   176  
   177  	return artifactRegistry, nil
   178  }
   179  
   180  func (s *artifactRegistryService) DeleteArtifactRegistryEntry(ctx context.Context, registryEdgeID string) (bool, error) {
   181  	// do nothing if entry does not exist
   182  	if exists, err := s.artifactRegistryEntryExists(ctx, registryEdgeID); err != nil {
   183  		return false, err
   184  	} else if !exists {
   185  		return false, nil
   186  	}
   187  
   188  	if _, err := s.SQLDB.ExecContext(ctx, sqlquery.ArtifactRegistryDeleteQuery, registryEdgeID); err != nil {
   189  		return false, err
   190  	}
   191  
   192  	return true, nil
   193  }
   194  
   195  func (s *artifactRegistryService) artifactRegistryEntryExists(ctx context.Context, registryEdgeID string) (bool, error) {
   196  	exists := false
   197  
   198  	row := s.SQLDB.QueryRowContext(ctx, sqlquery.ArtifactRegistryExistsQuery, registryEdgeID)
   199  	if err := row.Scan(&exists); err != nil {
   200  		return false, err
   201  	}
   202  
   203  	return exists, nil
   204  }
   205  
   206  func (s *artifactRegistryService) GetClusterArtifactRegistry(ctx context.Context, clusterRegistryEdgeID string) (*model.ClusterArtifactRegistry, error) {
   207  	row := s.SQLDB.QueryRowContext(ctx, sqlquery.GetClusterArtifactRegistryByIDQuery, clusterRegistryEdgeID)
   208  	return s.scanClusterArtifactRegistryRow(row)
   209  }
   210  
   211  func (s *artifactRegistryService) scanClusterArtifactRegistryRow(row *sql.Row) (*model.ClusterArtifactRegistry, error) {
   212  	clusterArtifactRegistry := &model.ClusterArtifactRegistry{}
   213  	if err := row.Scan(&clusterArtifactRegistry.ClusterRegistryEdgeID, &clusterArtifactRegistry.ClusterEdgeID, &clusterArtifactRegistry.RegistryEdgeID); err != nil {
   214  		return nil, err
   215  	}
   216  	return clusterArtifactRegistry, nil
   217  }
   218  
   219  func (s *artifactRegistryService) GetClusterArtifactRegistries(ctx context.Context, clusterEdgeID string) ([]*model.ClusterArtifactRegistry, error) {
   220  	rows, err := s.SQLDB.QueryContext(ctx, sqlquery.GetClusterArtifactRegistriesForClusterQuery, clusterEdgeID)
   221  	if err != nil {
   222  		return nil, err
   223  	}
   224  	return s.scanClusterArtifactRegistryRows(rows)
   225  }
   226  
   227  func (s *artifactRegistryService) scanClusterArtifactRegistryRows(rows *sql.Rows) ([]*model.ClusterArtifactRegistry, error) {
   228  	clusterArtifactRegistries := []*model.ClusterArtifactRegistry{}
   229  
   230  	for rows.Next() {
   231  		clusterArtifactRegistry := &model.ClusterArtifactRegistry{}
   232  		if err := rows.Scan(&clusterArtifactRegistry.ClusterRegistryEdgeID, &clusterArtifactRegistry.ClusterEdgeID, &clusterArtifactRegistry.RegistryEdgeID); err != nil {
   233  			return nil, err
   234  		}
   235  		clusterArtifactRegistries = append(clusterArtifactRegistries, clusterArtifactRegistry)
   236  	}
   237  
   238  	if err := rows.Err(); err != nil {
   239  		return nil, sqlerr.Wrap(err)
   240  	}
   241  
   242  	return clusterArtifactRegistries, nil
   243  }
   244  
   245  func (s *artifactRegistryService) CreateClusterArtifactRegistryEntry(ctx context.Context, createClusterArtifactRegistry *model.ClusterArtifactRegistryCreateInput) (clusterArtifactRegistry *model.ClusterArtifactRegistry, err error) {
   246  	transaction, err := s.SQLDB.BeginTx(ctx, nil)
   247  	if err != nil {
   248  		return nil, err
   249  	}
   250  
   251  	defer func() {
   252  		err = rollbackOnError(transaction, err)
   253  	}()
   254  
   255  	clusterArtifactRegistry = utils.CreateClusterArtifactRegistryModel(
   256  		uuid.NewString(),
   257  		createClusterArtifactRegistry.ClusterEdgeID,
   258  		createClusterArtifactRegistry.RegistryEdgeID,
   259  	)
   260  
   261  	args := []any{
   262  		clusterArtifactRegistry.ClusterRegistryEdgeID,
   263  		clusterArtifactRegistry.ClusterEdgeID,
   264  		clusterArtifactRegistry.RegistryEdgeID,
   265  	}
   266  
   267  	if _, err = transaction.ExecContext(ctx, sqlquery.ClusterArtifactRegistryCreateQuery, args...); err != nil {
   268  		return
   269  	}
   270  
   271  	if err = transaction.Commit(); err != nil {
   272  		return
   273  	}
   274  
   275  	return clusterArtifactRegistry, nil
   276  }
   277  
   278  func (s *artifactRegistryService) DeleteClusterArtifactRegistryEntry(ctx context.Context, clusterRegistryEdgeID string) (bool, error) {
   279  	// do nothing if entry does not exist
   280  	if exists, err := s.clusterArtifactRegistryEntryExists(ctx, clusterRegistryEdgeID); err != nil {
   281  		return false, err
   282  	} else if !exists {
   283  		return false, nil
   284  	}
   285  
   286  	if _, err := s.SQLDB.ExecContext(ctx, sqlquery.ClusterArtifactRegistryDeleteQuery, clusterRegistryEdgeID); err != nil {
   287  		return false, err
   288  	}
   289  
   290  	return true, nil
   291  }
   292  
   293  func (s *artifactRegistryService) clusterArtifactRegistryEntryExists(ctx context.Context, clusterRegistryEdgeID string) (bool, error) {
   294  	exists := false
   295  
   296  	row := s.SQLDB.QueryRowContext(ctx, sqlquery.ClusterArtifactRegistryExistsQuery, clusterRegistryEdgeID)
   297  	if err := row.Scan(&exists); err != nil {
   298  		return false, err
   299  	}
   300  
   301  	return exists, nil
   302  }
   303  
   304  func rollbackOnError(transaction *sql.Tx, err error) error {
   305  	if err != nil {
   306  		return errors.Join(err, transaction.Rollback())
   307  	}
   308  	return nil
   309  }
   310  

View as plain text