diff options
author | Alessio Caiazza <acaiazza@gitlab.com> | 2018-12-06 15:13:04 +0300 |
---|---|---|
committer | Alessio Caiazza <acaiazza@gitlab.com> | 2018-12-06 15:13:04 +0300 |
commit | f65623e115dfe87521e22fe1afdff3b94ae9012e (patch) | |
tree | 938992cbfa9026b094a719ba9cacbac370c1e4e6 /internal/domain | |
parent | d09650e7227efca1d0a0bc0ca094b90f81be9497 (diff) |
Don't scan subgroups past gitlab-rails limit
Diffstat (limited to 'internal/domain')
-rw-r--r-- | internal/domain/domain.go | 7 | ||||
-rw-r--r-- | internal/domain/map.go | 16 | ||||
-rw-r--r-- | internal/domain/map_test.go | 52 |
3 files changed, 64 insertions, 11 deletions
diff --git a/internal/domain/domain.go b/internal/domain/domain.go index 3638c372..8345f69c 100644 --- a/internal/domain/domain.go +++ b/internal/domain/domain.go @@ -22,10 +22,11 @@ import ( ) const ( - // MaxProjectDepth is set to the maximum nested project depth in gitlab (21) plus 3. + subgroupScanLimit int = 21 + // maxProjectDepth is set to the maximum nested project depth in gitlab (21) plus 3. // One for the project, one for the first empty element of the split (URL.Path starts with /), // and one for the real file path - MaxProjectDepth int = 24 + maxProjectDepth int = subgroupScanLimit + 3 ) type locationDirectoryError struct { @@ -120,7 +121,7 @@ func getHost(r *http.Request) string { func (d *D) getProjectWithSubpath(r *http.Request) (*project, string, string) { // Check for a project specified in the URL: http://group.gitlab.io/projectA // If present, these projects shadow the group domain. - split := strings.SplitN(r.URL.Path, "/", MaxProjectDepth) + split := strings.SplitN(r.URL.Path, "/", maxProjectDepth) if len(split) >= 2 { project, projectPath, urlPath := d.digProjectWithSubpath("", split[1:]) if project != nil { diff --git a/internal/domain/map.go b/internal/domain/map.go index 26657a1c..2891a272 100644 --- a/internal/domain/map.go +++ b/internal/domain/map.go @@ -60,7 +60,7 @@ func (dm Map) updateGroupDomain(rootDomain, groupName, projectPath string, https } } - split := strings.SplitN(strings.ToLower(projectPath), "/", MaxProjectDepth) + split := strings.SplitN(strings.ToLower(projectPath), "/", maxProjectDepth) projectName := split[len(split)-1] g := &groupDomain.group @@ -108,7 +108,7 @@ func (dm Map) readProjectConfig(rootDomain string, group, projectName string, co } } -func readProject(group, parent, projectName string, fanIn chan<- jobResult) { +func readProject(group, parent, projectName string, level int, fanIn chan<- jobResult) { if strings.HasPrefix(projectName, ".") { return } @@ -121,8 +121,10 @@ func readProject(group, parent, projectName string, fanIn chan<- jobResult) { projectPath := filepath.Join(parent, projectName) if _, err := os.Lstat(filepath.Join(group, projectPath, "public")); err != nil { // maybe it's a subgroup - buf := make([]byte, 2*os.Getpagesize()) - readProjects(group, projectPath, buf, fanIn) + if level <= subgroupScanLimit { + buf := make([]byte, 2*os.Getpagesize()) + readProjects(group, projectPath, level+1, buf, fanIn) + } return } @@ -137,7 +139,7 @@ func readProject(group, parent, projectName string, fanIn chan<- jobResult) { fanIn <- jobResult{group: group, project: projectPath, config: config} } -func readProjects(group, parent string, buf []byte, fanIn chan<- jobResult) { +func readProjects(group, parent string, level int, buf []byte, fanIn chan<- jobResult) { subgroup := filepath.Join(group, parent) fis, err := godirwalk.ReadDirents(subgroup, buf) if err != nil { @@ -154,7 +156,7 @@ func readProjects(group, parent string, buf []byte, fanIn chan<- jobResult) { continue } - readProject(group, parent, project.Name(), fanIn) + readProject(group, parent, project.Name(), level, fanIn) } } @@ -178,7 +180,7 @@ func (dm Map) ReadGroups(rootDomain string, fis godirwalk.Dirents) { for group := range fanOutGroups { started := time.Now() - readProjects(group, "", buf, fanIn) + readProjects(group, "", 0, buf, fanIn) log.WithFields(log.Fields{ "group": group, diff --git a/internal/domain/map_test.go b/internal/domain/map_test.go index f7b065e4..dc5e8648 100644 --- a/internal/domain/map_test.go +++ b/internal/domain/map_test.go @@ -5,6 +5,7 @@ import ( "fmt" "io/ioutil" "os" + "strings" "testing" "time" @@ -78,7 +79,56 @@ func TestReadProjects(t *testing.T) { subgroup, ok := domain.subgroups["subgroup"] require.True(t, ok, "missing group.test.io subgroup") _, ok = subgroup.projects["project"] - require.True(t, ok, "missing project for subgrup in group.test.io domain") + require.True(t, ok, "missing project for subgroup in group.test.io domain") +} + +func TestReadProjectsMaxDepth(t *testing.T) { + nGroups := 3 + levels := subgroupScanLimit + 5 + cleanup := buildFakeDomainsDirectory(t, nGroups, levels) + defer cleanup() + + defaultDomain := "test.io" + dm := make(Map) + dm.ReadGroups(defaultDomain, getEntries(t)) + + var domains []string + for d := range dm { + domains = append(domains, d) + } + + var expectedDomains []string + for i := 0; i < nGroups; i++ { + expectedDomains = append(expectedDomains, fmt.Sprintf("group-%d.%s", i, defaultDomain)) + } + + for _, expected := range domains { + assert.Contains(t, domains, expected) + } + + for _, actual := range domains { + // we are not checking config.json domains here + if !strings.HasSuffix(actual, defaultDomain) { + continue + } + assert.Contains(t, expectedDomains, actual) + } + + // check subgroups + domain, ok := dm["group-0.test.io"] + require.True(t, ok, "missing group-0.test.io domain") + subgroup := &domain.group + for i := 0; i < levels; i++ { + subgroup, ok = subgroup.subgroups["sub"] + if i <= subgroupScanLimit { + require.True(t, ok, "missing group-0.test.io subgroup at level %d", i) + _, ok = subgroup.projects["project-0"] + require.True(t, ok, "missing project for subgroup in group-0.test.io domain at level %d", i) + } else { + require.False(t, ok, "subgroup level %d. Maximum allowed nesting level is %d", i, subgroupScanLimit) + break + } + } } // This write must be atomic, otherwise we cannot predict the state of the |