Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

getNamespaceByPrefix now checks topology for namespace existence #1021

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions registry/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ func keySignChallengeCommit(ctx *gin.Context, data *registrationData) (bool, map
}
ns.Pubkey = string(pubkeyData)
ns.Identity = data.Identity
ns.Topology = false

if data.Identity != "" {
idMap := map[string]interface{}{}
Expand Down Expand Up @@ -855,6 +856,11 @@ func checkNamespaceStatusHandler(ctx *gin.Context) {
return
}
ns, err := getNamespaceByPrefix(req.Prefix)
if ns.Topology {
res := server_structs.CheckNamespaceStatusRes{Approved: true}
ctx.JSON(http.StatusOK, res)
return
}
if err != nil || ns == nil {
log.Errorf("Error in getNamespaceByPrefix with prefix %s. %v", req.Prefix, err)
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Error getting namespace"})
Expand Down
45 changes: 31 additions & 14 deletions registry/registry_db.go
turetske marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ type Namespace struct {
Identity string `json:"identity" post:"exclude"`
AdminMetadata AdminMetadata `json:"admin_metadata" gorm:"serializer:json"`
CustomFields map[string]interface{} `json:"custom_fields" gorm:"serializer:json"`
Topology bool `json:"topology" gorm:"-:all" post:"exclude"` //This field is an extra field that's not included in the db
}

type NamespaceWOPubkey struct {
Expand Down Expand Up @@ -162,7 +163,7 @@ func IsValidRegStatus(s string) bool {
func createTopologyTable() error {
err := db.AutoMigrate(&Topology{})
if err != nil {
return fmt.Errorf("Failed to migrate topology table: %v", err)
return fmt.Errorf("failed to migrate topology table: %v", err)
}
return nil
}
Expand All @@ -171,23 +172,19 @@ func createTopologyTable() error {
func namespaceExistsByPrefix(prefix string) (bool, error) {
var count int64

err := db.Model(&Namespace{}).Where("prefix = ?", prefix).Count(&count).Error
err := db.Model(&Topology{}).Where("prefix = ?", prefix).Count(&count).Error
if err != nil {
return false, err
}
if count > 0 {
return true, nil
} else {
if config.GetPreferredPrefix() == "OSDF" {
// Perform a count across both 'namespace' and 'topology' tables
err := db.Model(&Topology{}).Where("prefix = ?", prefix).Count(&count).Error
if err != nil {
return false, err
}
return count > 0, nil
err = db.Model(&Namespace{}).Where("prefix = ?", prefix).Count(&count).Error
if err != nil {
return false, err
}
return count > 0, nil
}
return false, nil
}

func namespaceSupSubChecks(prefix string) (superspaces []string, subspaces []string, inTopo bool, err error) {
Expand Down Expand Up @@ -273,6 +270,11 @@ func getNamespaceJwksById(id int) (jwk.Set, error) {
}

func getNamespaceJwksByPrefix(prefix string) (jwk.Set, *AdminMetadata, error) {
// Note that this cannot retrieve public keys from topology as the topology table
// doesn't contain that information.
if prefix == "" {
return nil, nil, errors.New("Invalid prefix. Prefix must not be empty")
}
var result Namespace
err := db.Select("pubkey", "admin_metadata").Where("prefix = ?", prefix).Last(&result).Error
if errors.Is(err, gorm.ErrRecordNotFound) {
Expand Down Expand Up @@ -333,15 +335,30 @@ func getNamespaceById(id int) (*Namespace, error) {
}

func getNamespaceByPrefix(prefix string) (*Namespace, error) {
// This function will check the topology table first to see if the
// namespace exists there before checking the namespace table
// If the namespace exists in the topology table, it will be wrapped
// as a pelican namespace before being returned
if prefix == "" {
turetske marked this conversation as resolved.
Show resolved Hide resolved
return nil, errors.New("Invalid prefix. Prefix must not be empty")
}
ns := Namespace{}
err := db.Where("prefix = ? ", prefix).Last(&ns).Error
tp := Topology{}
err := db.Where("prefix = ?", prefix).Last(&tp).Error
var ns = Namespace{}
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("namespace with id %q not found in database", prefix)
err := db.Where("prefix = ? ", prefix).Last(&ns).Error
ns.Topology = false
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, fmt.Errorf("namespace with prefix %q not found in database", prefix)
} else if err != nil {
return nil, errors.Wrap(err, "error retrieving the namespace by its prefix")
}
} else if err != nil {
return nil, errors.Wrap(err, "error retrieving pubkey")
return nil, errors.Wrap(err, "error retrieving the namespace by its prefix")
} else {
ns.ID = tp.ID
ns.Prefix = tp.Prefix
ns.Topology = true
}

// By default, JSON unmarshal will convert any generic number to float
Expand Down
53 changes: 53 additions & 0 deletions registry/registry_db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,59 @@ func topologyMockup(t *testing.T, namespaces []string) *httptest.Server {
return svr
}

func TestGetNamespaceByPrefix(t *testing.T) {
ctx, cancel, egrp := test_utils.TestContext(context.Background(), t)
defer func() { require.NoError(t, egrp.Wait()) }()
defer cancel()

viper.Reset()

topoNamespaces := []string{"/topo/foo"}
svr := topologyMockup(t, topoNamespaces)
defer svr.Close()

registryDB := t.TempDir()
viper.Set("Registry.DbLocation", filepath.Join(registryDB, "test.sqlite"))
viper.Set("Federation.TopologyNamespaceURL", svr.URL)
config.InitConfig()

err := InitializeDB(ctx)
require.NoError(t, err)
defer func() {
err := ShutdownDB()
assert.NoError(t, err)
}()

//Test topology table population
err = createTopologyTable()
require.NoError(t, err)
err = PopulateTopology()
require.NoError(t, err)

//Test that getNamespaceByPrefix wraps a pelican namespace around a topology one
ns, err := getNamespaceByPrefix("/topo/foo")
require.NoError(t, err)
require.True(t, ns.Topology)

// Add a test namespace so we can test that checkExists still works
new_ns := Namespace{
ID: 0,
Prefix: "/regular/foo",
Pubkey: "",
Identity: "",
AdminMetadata: AdminMetadata{},
}
err = AddNamespace(&new_ns)
require.NoError(t, err)

//Test that getNamespaceByPrefix returns namespace with a false topology variable
ns_reg, err := getNamespaceByPrefix("/regular/foo")
require.NoError(t, err)
require.False(t, ns_reg.Topology)

viper.Reset()
}

func TestRegistryTopology(t *testing.T) {
ctx, cancel, egrp := test_utils.TestContext(context.Background(), t)
defer func() { require.NoError(t, egrp.Wait()) }()
Expand Down
2 changes: 2 additions & 0 deletions registry/registry_ui.go
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ func createUpdateNamespace(ctx *gin.Context, isUpdate bool) {
}

ns := Namespace{}
ns.Topology = false
if ctx.ShouldBindJSON(&ns) != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "Invalid create or update namespace request"})
return
Expand All @@ -441,6 +442,7 @@ func createUpdateNamespace(ctx *gin.Context, isUpdate bool) {
return
}
ns.Prefix = updated_prefix
ns.Topology = false

if !isUpdate {
// Check if prefix exists before doing anything else. Skip check if it's update operation
Expand Down
Loading