package services import ( "context" "database/sql" "errors" "github.com/google/uuid" sqlerr "edge-infra.dev/pkg/edge/api/apierror/sql" "edge-infra.dev/pkg/edge/api/graph/mapper" "edge-infra.dev/pkg/edge/api/graph/model" sqlquery "edge-infra.dev/pkg/edge/api/sql" "edge-infra.dev/pkg/edge/api/utils" ) type NamespaceService interface { CreateNamespaceEntry(ctx context.Context, createNamespace *model.NamespaceCreateInput) (*model.Namespace, error) DeleteNamespaceEntry(ctx context.Context, bannerEdgeID string, name string) error GetBannerNamespaces(ctx context.Context, bannerEdgeID string, name *string) ([]*model.Namespace, error) GetClusterNamespaces(ctx context.Context, clusterEdgeID string, name *string) ([]*model.Namespace, error) CreateDSDSKubeNamespaceCR(namespace *model.Namespace) (string, error) CreateClusterNamespaceEntry(ctx context.Context, transaction *sql.Tx, namespaceEdgeID string, clusterEdgeID string) error GetNumClustersUsingNamespace(ctx context.Context, namespaceEdgeID string) (int, error) GetClusterNamespaceEdgeID(ctx context.Context, transaction *sql.Tx, namespaceEdgeID string, clusterEdgeID string) (string, error) GetNamespaceName(ctx context.Context, namespaceEdgeID string) (string, error) } type namespaceService struct { SQLDB *sql.DB } func (n *namespaceService) CreateNamespaceEntry(ctx context.Context, createNamespace *model.NamespaceCreateInput) (namespace *model.Namespace, err error) { transaction, err := n.SQLDB.BeginTx(ctx, nil) if err != nil { return nil, err } defer func() { if err != nil { err = errors.Join(err, transaction.Rollback()) } }() modelNamespace := utils.CreateNamespaceModel(uuid.NewString(), createNamespace.BannerEdgeID, createNamespace.Name, createNamespace.Workload) namespace = &modelNamespace // validate Namespace if err = utils.ValidateNamespace(namespace); err != nil { return nil, err } args := []interface{}{ namespace.NamespaceEdgeID, namespace.BannerEdgeID, namespace.Name, namespace.Workload, } if _, err = transaction.ExecContext(ctx, sqlquery.NamespaceCreateQuery, args...); err != nil { return nil, err } if err = transaction.Commit(); err != nil { return nil, err } return namespace, nil } func (n *namespaceService) DeleteNamespaceEntry(ctx context.Context, bannerEdgeID string, name string) error { args := []interface{}{ bannerEdgeID, name, } _, err := n.SQLDB.ExecContext(ctx, sqlquery.NamespaceDeleteQuery, args...) return err } func (n *namespaceService) GetBannerNamespaces(ctx context.Context, bannerEdgeID string, name *string) ([]*model.Namespace, error) { if name == nil { return n.getAllBannerNamespaces(ctx, bannerEdgeID) } return n.getBannerNamespaces(ctx, bannerEdgeID, *name) } func (n *namespaceService) GetClusterNamespaces(ctx context.Context, clusterEdgeID string, name *string) ([]*model.Namespace, error) { if name == nil { return n.getClusterNamespacesByClusterEdgeID(ctx, clusterEdgeID) } return n.getClusterNamespaces(ctx, clusterEdgeID, *name) } func (n *namespaceService) CreateDSDSKubeNamespaceCR(namespace *model.Namespace) (string, error) { kubeNamespace, err := mapper.NamespaceToKubeNamespace(namespace) if err != nil { return "", err } encodedNamespace, err := utils.ConvertStructToBase64(kubeNamespace) if err != nil { return "", err } return encodedNamespace, nil } func (n *namespaceService) CreateClusterNamespaceEntry(ctx context.Context, transaction *sql.Tx, namespaceEdgeID string, clusterEdgeID string) error { args := []interface{}{ namespaceEdgeID, clusterEdgeID, } _, err := transaction.ExecContext(ctx, sqlquery.ClusterNamespaceCreateQuery, args...) return err } func (n *namespaceService) GetNumClustersUsingNamespace(ctx context.Context, namespaceEdgeID string) (int, error) { row := n.SQLDB.QueryRowContext(ctx, sqlquery.GetNumClustersUsingNamespaceQuery, namespaceEdgeID) var count int if err := row.Scan(&count); err != nil { return 0, err } return count, nil } func (n *namespaceService) GetClusterNamespaceEdgeID(ctx context.Context, transaction *sql.Tx, namespaceEdgeID string, clusterEdgeID string) (string, error) { args := []interface{}{ namespaceEdgeID, clusterEdgeID, } row := transaction.QueryRowContext(ctx, sqlquery.GetClusterNamespaceEdgeIDQuery, args...) var clusterNamespaceEdgeID string if err := row.Scan(&clusterNamespaceEdgeID); err != nil { return "", err } return clusterNamespaceEdgeID, nil } func (n *namespaceService) GetNamespaceName(ctx context.Context, namespaceEdgeID string) (string, error) { var namespace string row := n.SQLDB.QueryRowContext(ctx, sqlquery.GetNamespaceNameByNamespaceEdgeIDQuery, namespaceEdgeID) if err := row.Scan(&namespace); err != nil { return "", err } return namespace, nil } func (n *namespaceService) getAllBannerNamespaces(ctx context.Context, bannerEdgeID string) ([]*model.Namespace, error) { rows, err := n.SQLDB.QueryContext(ctx, sqlquery.GetAllBannerNamespacesQuery, bannerEdgeID) if err != nil { return nil, err } namespaces, err := n.scanNamespaceRows(rows) if err != nil { return nil, err } return namespaces, nil } func (n *namespaceService) getBannerNamespaces(ctx context.Context, bannerEdgeID string, name string) ([]*model.Namespace, error) { args := []interface{}{ bannerEdgeID, name, } rows, err := n.SQLDB.QueryContext(ctx, sqlquery.GetBannerNamespacesQuery, args...) if err != nil { return nil, err } namespaces, err := n.scanNamespaceRows(rows) if err != nil { return nil, err } return namespaces, nil } func (n *namespaceService) getClusterNamespacesByClusterEdgeID(ctx context.Context, clusterEdgeID string) ([]*model.Namespace, error) { rows, err := n.SQLDB.QueryContext(ctx, sqlquery.GetAllClusterNamespacesQuery, clusterEdgeID) if err != nil { return nil, err } namespaces, err := n.scanNamespaceRows(rows) if err != nil { return nil, err } return namespaces, nil } func (n *namespaceService) getClusterNamespaces(ctx context.Context, clusterEdgeID string, name string) ([]*model.Namespace, error) { args := []interface{}{ clusterEdgeID, name, } rows, err := n.SQLDB.QueryContext(ctx, sqlquery.GetClusterNamespacesQuery, args...) if err != nil { return nil, err } namespaces, err := n.scanNamespaceRows(rows) if err != nil { return nil, err } return namespaces, nil } func (n *namespaceService) scanNamespaceRows(rows *sql.Rows) ([]*model.Namespace, error) { namespaces := []*model.Namespace{} for rows.Next() { namespace := &model.Namespace{} err := rows.Scan(&namespace.NamespaceEdgeID, &namespace.BannerEdgeID, &namespace.Name, &namespace.Workload) if err != nil { return nil, err } namespaces = append(namespaces, namespace) } if err := rows.Err(); err != nil { return nil, sqlerr.Wrap(err) } return namespaces, nil } func NewNamespaceService(sqlDB *sql.DB) *namespaceService { //nolint return &namespaceService{ SQLDB: sqlDB, } }