You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ya...@apache.org on 2026/10/19 05:15:21 UTC
(airavata-custos) 01/01: use origin-seq form for project folders
This is an automated email from the ASF dual-hosted git repository.
yasithdev pushed a commit to branch project-folder-name
in repository https://gitbox.apache.org/repos/asf/airavata-custos.git
commit d4d0af8e7c0e1e2f85df9efbd5fd48f46bdba4e3
Author: Yasith Jayawardana <ya...@icloud.com>
AuthorDate: Mon Oct 19 01:14:59 2026 -0400
use origin-seq form for project folders
---
internal/server/admin_project_integration_test.go | 2 +-
internal/server/project.go | 10 ++--------
pkg/posix/username.go | 6 ++++++
pkg/service/compute_allocation.go | 7 ++-----
pkg/service/compute_cluster_user_integration_test.go | 11 ++++++-----
5 files changed, 17 insertions(+), 19 deletions(-)
diff --git a/internal/server/admin_project_integration_test.go b/internal/server/admin_project_integration_test.go
index 5b63ace0a..1e83ae78b 100644
--- a/internal/server/admin_project_integration_test.go
+++ b/internal/server/admin_project_integration_test.go
@@ -61,7 +61,7 @@ func TestAdminProject_CreateAssignRoleAndBlockPIChange(t *testing.T) {
}
var got ProjectResponse
_ = json.NewDecoder(doGet(t, srv, "/projects/"+created.ID, "admin", models.ProjectsRead).Body).Decode(&got)
- if got.Ref != "INTERNAL-"+created.ID[:8] {
+ if got.Ref != "internal-"+created.ID[:8] {
t.Fatalf("ref: %q", got.Ref)
}
if roles := projectRoles(t, srv, created.ID); len(roles) != 1 || roles[f.piID] != "PI" {
diff --git a/internal/server/project.go b/internal/server/project.go
index 0221353d3..137b94e82 100644
--- a/internal/server/project.go
+++ b/internal/server/project.go
@@ -18,7 +18,6 @@
package server
import (
- "cmp"
"errors"
"net/http"
"strings"
@@ -27,6 +26,7 @@ import (
"github.com/apache/airavata-custos/pkg/common"
"github.com/apache/airavata-custos/pkg/identity"
"github.com/apache/airavata-custos/pkg/models"
+ "github.com/apache/airavata-custos/pkg/posix"
)
type updateProjectRequest struct {
@@ -79,7 +79,7 @@ func (s *Server) getProject(w http.ResponseWriter, r *http.Request) {
// projectResponseFrom builds the API response shape from a JOIN-fetched row.
func projectResponseFrom(p *store.ProjectWithPI) ProjectResponse {
- v := ProjectResponse{Project: p.Project, ProjectPIEmail: p.PIEmail, Ref: projectRef(p.Project)}
+ v := ProjectResponse{Project: p.Project, ProjectPIEmail: p.PIEmail, Ref: posix.ProjectRef(p.Project)}
if full := strings.TrimSpace(p.PIFirstName + " " + p.PILastName); full != "" {
v.ProjectPIDisplayName = full
} else if p.PIEmail != "" {
@@ -88,12 +88,6 @@ func projectResponseFrom(p *store.ProjectWithPI) ProjectResponse {
return v
}
-// projectRef names a project by its source, type first: ACCESS-TG-CIS230001, or INTERNAL-3f2a9c1e for an
-// internal project, which has no originated id.
-func projectRef(p models.Project) string {
- return strings.ToUpper(p.Origination) + "-" + cmp.Or(p.OriginatedID, p.ID[:min(8, len(p.ID))])
-}
-
// @Summary Update a project's status
// @Tags Projects
// @Security BearerAuth
diff --git a/pkg/posix/username.go b/pkg/posix/username.go
index 2e60f5e9f..9bc515e7a 100644
--- a/pkg/posix/username.go
+++ b/pkg/posix/username.go
@@ -20,6 +20,7 @@
package posix
import (
+ "cmp"
"errors"
"fmt"
"os"
@@ -36,6 +37,11 @@ const MaxLoginLen = 32
var ErrUnbuildableUsername = errors.New("posix: cannot build username from empty first and last name")
+// ProjectRef names a project by its source and id, e.g., ACCESS + TG-CIS230001 -> access-tgcis230001.
+func ProjectRef(p models.Project) string {
+ return strings.ToLower(p.Origination) + "-" + Normalize(cmp.Or(p.OriginatedID, p.ID[:min(8, len(p.ID))]))
+}
+
// BuildBase returns the unsuffixed username. 'truncated' is set when the name
// portion was shortened to fit the 32-char POSIX login cap.
func BuildBase(u *models.User, prefix string) (string, bool, error) {
diff --git a/pkg/service/compute_allocation.go b/pkg/service/compute_allocation.go
index e30a266b8..ce10c71b6 100644
--- a/pkg/service/compute_allocation.go
+++ b/pkg/service/compute_allocation.go
@@ -18,7 +18,6 @@
package service
import (
- "cmp"
"context"
"database/sql"
"fmt"
@@ -96,8 +95,7 @@ func (s *Service) CreateComputeAllocation(ctx context.Context, alloc *models.Com
return nil, fmt.Errorf("%w: compute cluster %q not found", ErrInvalidInput, alloc.ComputeClusterID)
}
- // Named after the project, remains same through renewals.
- name := cmp.Or(posix.Normalize(proj.OriginatedID), posix.Normalize(proj.ID))
+ // Named after the project's ref, the name the portal shows, so it remains the same through renewals.
siblings, err := s.allocs.FindByCluster(ctx, alloc.ComputeClusterID)
if err != nil {
return nil, fmt.Errorf("lookup cluster allocations: %w", err)
@@ -108,8 +106,7 @@ func (s *Service) CreateComputeAllocation(ctx context.Context, alloc *models.Com
taken[*a.PosixGroup] = true
}
}
- // Normalized names never contain "-", so a "-N" suffix cannot meet another allocation's base name.
- base := "proj-" + name
+ base := posix.ProjectRef(*proj)
group := base[:min(len(base), posix.MaxLoginLen)]
for n := 2; taken[group]; n++ {
suffix := "-" + strconv.Itoa(n)
diff --git a/pkg/service/compute_cluster_user_integration_test.go b/pkg/service/compute_cluster_user_integration_test.go
index 1016634de..6dd6fa63d 100644
--- a/pkg/service/compute_cluster_user_integration_test.go
+++ b/pkg/service/compute_cluster_user_integration_test.go
@@ -24,6 +24,7 @@ import (
"errors"
"fmt"
"slices"
+ "strings"
"sync"
"testing"
"time"
@@ -32,7 +33,6 @@ import (
"github.com/jmoiron/sqlx"
"github.com/apache/airavata-custos/pkg/models"
- "github.com/apache/airavata-custos/pkg/posix"
)
func TestMarkComputeClusterUserProvisioned_RoundTrip(t *testing.T) {
@@ -424,9 +424,10 @@ func TestCreateComputeAllocation_SuffixesACollidingPosixGroup(t *testing.T) {
t.Fatalf("create cluster: %v", err)
}
pi := seedUser(t, database, fmt.Sprintf("pi-%s@example.edu", uuid.NewString()))
- grant := uuid.NewString()[:8]
+ // Refs that agree up to the 32-character limit collide once cut.
+ grant := "CIS" + uuid.NewString()[:8] + strings.Repeat("X", 16)
var groups []string
- for _, originated := range []string{"CIS-" + grant, "cis" + grant, "CIS" + grant, ""} {
+ for _, originated := range []string{grant + "a", grant + "b", grant + "c", ""} {
project, err := svc.CreateProject(ctx(), &models.Project{Title: "grp", Origination: "TEST", ProjectPIID: pi, Status: models.ProjectActive, OriginatedID: originated})
if err != nil {
t.Fatalf("create project: %v", err)
@@ -438,11 +439,11 @@ func TestCreateComputeAllocation_SuffixesACollidingPosixGroup(t *testing.T) {
t.Fatalf("create allocation for %q: %v", originated, err)
}
groups = append(groups, *alloc.PosixGroup)
- if originated == "" && groups[3] != ("proj-" + posix.Normalize(project.ID))[:posix.MaxLoginLen] {
+ if originated == "" && groups[3] != "test-"+project.ID[:8] {
t.Fatalf("group %s, want one named after project id %s", groups[3], project.ID)
}
}
- if want := "proj-cis" + grant; !slices.Equal(groups[:3], []string{want, want + "-2", want + "-3"}) {
+ if want := "test-" + strings.ToLower(grant); !slices.Equal(groups[:3], []string{want, want[:30] + "-2", want[:30] + "-3"}) {
t.Fatalf("groups %v, want %s, -2, -3", groups, want)
}
}