go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/extensible_schema.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package providers 5 6 import ( 7 "sync" 8 9 "github.com/rs/zerolog/log" 10 "go.mondoo.com/cnquery/providers-sdk/v1/resources" 11 ) 12 13 type extensibleSchema struct { 14 resources.Schema 15 16 loaded map[string]struct{} 17 runtime *Runtime 18 allLoaded bool 19 lockAll sync.Mutex // only used in getting all schemas 20 lockAdd sync.Mutex // only used when adding a schema 21 } 22 23 func (x *extensibleSchema) loadAllSchemas() { 24 x.lockAll.Lock() 25 defer x.lockAll.Unlock() 26 27 // If another goroutine started to load this before us, it will be locked until 28 // we complete to load everything and then it will be dumped into this 29 // position. At this point, if it has been loaded we can return safely, since 30 // we don't unlock until we are finished loading. 31 if x.allLoaded { 32 return 33 } 34 x.allLoaded = true 35 36 providers, err := ListActive() 37 if err != nil { 38 log.Error().Err(err).Msg("failed to list all providers, can't load additional schemas") 39 return 40 } 41 42 for name := range providers { 43 schema, err := x.runtime.coordinator.LoadSchema(name) 44 if err != nil { 45 log.Error().Err(err).Msg("load schema failed") 46 } else { 47 x.Add(name, schema) 48 } 49 } 50 } 51 52 func (x *extensibleSchema) Close() { 53 x.loaded = map[string]struct{}{} 54 x.Schema.Resources = nil 55 } 56 57 func (x *extensibleSchema) Lookup(name string) *resources.ResourceInfo { 58 if found, ok := x.Resources[name]; ok { 59 return found 60 } 61 if x.allLoaded { 62 return nil 63 } 64 65 x.loadAllSchemas() 66 return x.Resources[name] 67 } 68 69 func (x *extensibleSchema) LookupField(resource string, field string) (*resources.ResourceInfo, *resources.Field) { 70 found, ok := x.Resources[resource] 71 if !ok { 72 if x.allLoaded { 73 return nil, nil 74 } 75 76 x.loadAllSchemas() 77 78 found, ok = x.Resources[resource] 79 if !ok { 80 return nil, nil 81 } 82 return found, found.Fields[field] 83 } 84 85 fieldObj, ok := found.Fields[field] 86 if ok { 87 return found, fieldObj 88 } 89 if x.allLoaded { 90 return found, nil 91 } 92 93 x.loadAllSchemas() 94 return found, found.Fields[field] 95 } 96 97 func (x *extensibleSchema) Add(name string, schema *resources.Schema) { 98 if schema == nil { 99 return 100 } 101 if name == "" { 102 log.Error().Msg("tried to add a schema with no name") 103 return 104 } 105 106 x.lockAdd.Lock() 107 defer x.lockAdd.Unlock() 108 109 if _, ok := x.loaded[name]; ok { 110 return 111 } 112 113 x.loaded[name] = struct{}{} 114 x.Schema.Add(schema) 115 } 116 117 func (x *extensibleSchema) AllResources() map[string]*resources.ResourceInfo { 118 if !x.allLoaded { 119 x.loadAllSchemas() 120 } 121 122 return x.Resources 123 }