Counts per namespace

This commit is contained in:
Darren Shepherd 2019-08-12 21:32:57 -07:00
parent d61942f795
commit ecc80ef1e1
2 changed files with 36 additions and 19 deletions

View File

@ -15,8 +15,9 @@ import (
var ( var (
ignore = map[string]bool{ ignore = map[string]bool{
"count": true, "count": true,
"schema": true, "schema": true,
"apiRoot": true,
} }
slow = map[string]bool{ slow = map[string]bool{
"io.k8s.api.management.cattle.io.v3.CatalogTemplateVersion": true, "io.k8s.api.management.cattle.io.v3.CatalogTemplateVersion": true,
@ -28,7 +29,7 @@ var (
func Register(schemas *types.Schemas) { func Register(schemas *types.Schemas) {
schemas.MustImportAndCustomize(Count{}, func(schema *types.Schema) { schemas.MustImportAndCustomize(Count{}, func(schema *types.Schema) {
schema.CollectionMethods = []string{http.MethodGet} schema.CollectionMethods = []string{http.MethodGet}
schema.ResourceMethods = []string{} schema.ResourceMethods = []string{http.MethodGet}
schema.Attributes["access"] = accesscontrol.AccessListMap{ schema.Attributes["access"] = accesscontrol.AccessListMap{
"watch": accesscontrol.AccessList{ "watch": accesscontrol.AccessList{
{ {
@ -47,8 +48,9 @@ type Count struct {
} }
type ItemCount struct { type ItemCount struct {
Count int `json:"count,omitempty"` Count int `json:"count,omitempty"`
Revision string `json:"revision,omitempty"` Namespaces map[string]int `json:"namespaces,omitempty"`
Revision string `json:"revision,omitempty"`
} }
type Store struct { type Store struct {
@ -78,7 +80,7 @@ func (s *Store) Watch(apiOp *types.APIRequest, schema *types.Schema, w types.Wat
for name, countItem := range c.Counts { for name, countItem := range c.Counts {
wg.Add(1) wg.Add(1)
go func() { go func() {
s.watchItem(apiOp.WithContext(ctx), name, countItem.Count, countItem.Revision, cancel, child) s.watchItem(apiOp.WithContext(ctx), name, countItem, cancel, child)
wg.Done() wg.Done()
}() }()
} }
@ -114,7 +116,7 @@ func (s *Store) Watch(apiOp *types.APIRequest, schema *types.Schema, w types.Wat
return result, nil return result, nil
} }
func (s *Store) watchItem(apiOp *types.APIRequest, schemaID string, start int, revision string, cancel func(), counts chan Count) { func (s *Store) watchItem(apiOp *types.APIRequest, schemaID string, start ItemCount, cancel func(), counts chan Count) {
schema := apiOp.Schemas.Schema(schemaID) schema := apiOp.Schemas.Schema(schemaID)
if schema == nil || schema.Store == nil || apiOp.AccessControl.CanWatch(apiOp, schema) != nil { if schema == nil || schema.Store == nil || apiOp.AccessControl.CanWatch(apiOp, schema) != nil {
return return
@ -122,31 +124,35 @@ func (s *Store) watchItem(apiOp *types.APIRequest, schemaID string, start int, r
defer cancel() defer cancel()
w, err := schema.Store.Watch(apiOp, schema, types.WatchRequest{Revision: revision}) w, err := schema.Store.Watch(apiOp, schema, types.WatchRequest{Revision: start.Revision})
if err != nil { if err != nil {
logrus.Errorf("failed to watch %s for counts: %v", schema.ID, err) logrus.Errorf("failed to watch %s for counts: %v", schema.ID, err)
return return
} }
for event := range w { for event := range w {
if event.Revision == revision { if event.Revision == start.Revision {
continue continue
} }
ns := types.Namespace(event.Object.Map())
write := false write := false
if event.Name == "resource.create" { if event.Name == "resource.create" {
start++ start.Count++
write = true write = true
if ns != "" {
start.Namespaces[ns]++
}
} else if event.Name == "resource.remove" { } else if event.Name == "resource.remove" {
start-- start.Count--
write = true write = true
if ns != "" {
start.Namespaces[ns]--
}
} }
if write { if write {
counts <- Count{Counts: map[string]ItemCount{ counts <- Count{Counts: map[string]ItemCount{
schemaID: { schemaID: start,
Count: start,
Revision: event.Revision,
},
}} }}
} }
} }
@ -187,11 +193,21 @@ func (s *Store) getCount(apiOp *types.APIRequest, timeout time.Duration, ignoreS
return nil return nil
} }
countLock.Lock() itemCount := ItemCount{
counts[current.ID] = ItemCount{ Namespaces: map[string]int{},
Count: len(list.List()), Revision: list.ListRevision,
Revision: list.ListRevision,
} }
for _, item := range list.List() {
itemCount.Count++
ns := types.Namespace(item)
if ns != "" {
itemCount.Namespaces[ns]++
}
}
countLock.Lock()
counts[current.ID] = itemCount
countLock.Unlock() countLock.Unlock()
return nil return nil

View File

@ -16,6 +16,7 @@ func (a *apiServer) routes() error {
a.Path("/v1/{type:schemas}/{name}").Handler(a.handle(nil)) a.Path("/v1/{type:schemas}/{name}").Handler(a.handle(nil))
a.Path("/v1/{type:subscribe}").Handler(a.handle(nil)) a.Path("/v1/{type:subscribe}").Handler(a.handle(nil))
a.Path("/v1/{type:counts}").Handler(a.handle(nil)) a.Path("/v1/{type:counts}").Handler(a.handle(nil))
a.Path("/v1/{type:counts}/{name}").Handler(a.handle(nil))
a.Path("/{version:v1}/{resource}").Handler(a.handle(a.k8sAPI)) a.Path("/{version:v1}/{resource}").Handler(a.handle(a.k8sAPI))
a.Path("/{version:v1}/{resource}/{nameorns}").Handler(a.handle(a.k8sAPI)) a.Path("/{version:v1}/{resource}/{nameorns}").Handler(a.handle(a.k8sAPI))