github.com/choria-io/go-choria@v0.28.1-0.20240416190746-b3bf9c7d5a45/internal/fs/client/discover.templ (about) 1 // generated code; DO NOT EDIT 2 3 package {{ .Package }} 4 5 import ( 6 "context" 7 "fmt" 8 "sync" 9 "time" 10 11 "github.com/choria-io/go-choria/client/discovery" 12 "github.com/choria-io/go-choria/providers/discovery/broadcast" 13 "github.com/choria-io/go-choria/providers/discovery/external" 14 "github.com/choria-io/go-choria/providers/discovery/puppetdb" 15 "github.com/choria-io/go-choria/protocol" 16 "github.com/choria-io/go-choria/inter" 17 ) 18 19 // BroadcastNS is a NodeSource that uses the Choria network broadcast method to discover nodes 20 type BroadcastNS struct { 21 nodeCache []string 22 f *protocol.Filter 23 24 sync.Mutex 25 } 26 27 // Reset resets the internal node cache 28 func (b *BroadcastNS) Reset() { 29 b.Lock() 30 defer b.Unlock() 31 32 b.nodeCache = []string{} 33 } 34 35 // Discover performs the discovery of nodes against the Choria Network 36 func (b *BroadcastNS) Discover(ctx context.Context, fw inter.Framework, filters []FilterFunc) ([]string, error) { 37 b.Lock() 38 defer b.Unlock() 39 40 copier := func() []string { 41 out := make([]string, len(b.nodeCache)) 42 copy(out, b.nodeCache) 43 44 return out 45 } 46 47 if !(b.nodeCache == nil || len(b.nodeCache) == 0) { 48 return copier(), nil 49 } 50 51 var err error 52 53 b.f, err = parseFilters(filters) 54 if err != nil { 55 return nil, err 56 } 57 58 if b.nodeCache == nil { 59 b.nodeCache = []string{} 60 } 61 62 cfg := fw.Configuration() 63 nodes, err := broadcast.New(fw).Discover(ctx, broadcast.Filter(b.f), broadcast.Timeout(time.Second*time.Duration(cfg.DiscoveryTimeout))) 64 if err != nil { 65 return []string{}, err 66 } 67 68 b.nodeCache = nodes 69 70 return copier(), nil 71 } 72 73 // ExternalNS is a NodeSource that calls an external command for discovery 74 type ExternalNS struct { 75 nodeCache []string 76 f *protocol.Filter 77 78 sync.Mutex 79 } 80 81 // Reset resets the internal node cache 82 func (p *ExternalNS) Reset() { 83 p.Lock() 84 defer p.Unlock() 85 86 p.nodeCache = []string{} 87 } 88 89 func (p *ExternalNS) Discover(ctx context.Context, fw inter.Framework, filters []FilterFunc) ([]string, error) { 90 p.Lock() 91 defer p.Unlock() 92 93 copier := func() []string { 94 out := make([]string, len(p.nodeCache)) 95 copy(out, p.nodeCache) 96 97 return out 98 } 99 100 if !(p.nodeCache == nil || len(p.nodeCache) == 0) { 101 return copier(), nil 102 } 103 104 var err error 105 p.f, err = parseFilters(filters) 106 if err != nil { 107 return nil, err 108 } 109 110 if p.nodeCache == nil { 111 p.nodeCache = []string{} 112 } 113 114 cfg := fw.Configuration() 115 nodes, err := external.New(fw).Discover(ctx, external.Filter(p.f), external.Timeout(time.Second*time.Duration(cfg.DiscoveryTimeout))) 116 if err != nil { 117 return []string{}, err 118 } 119 120 p.nodeCache = nodes 121 122 return copier(), nil 123 } 124 125 // PuppetDBNS is a NodeSource that uses the PuppetDB PQL Queries to discover nodes 126 type PuppetDBNS struct { 127 nodeCache []string 128 f *protocol.Filter 129 130 sync.Mutex 131 } 132 133 // Reset resets the internal node cache 134 func (p *PuppetDBNS) Reset() { 135 p.Lock() 136 defer p.Unlock() 137 138 p.nodeCache = []string{} 139 } 140 141 // Discover performs the discovery of nodes against the Choria Network 142 func (p *PuppetDBNS) Discover(ctx context.Context, fw inter.Framework, filters []FilterFunc) ([]string, error) { 143 p.Lock() 144 defer p.Unlock() 145 146 copier := func() []string { 147 out := make([]string, len(p.nodeCache)) 148 copy(out, p.nodeCache) 149 150 return out 151 } 152 153 if !(p.nodeCache == nil || len(p.nodeCache) == 0) { 154 return copier(), nil 155 } 156 157 var err error 158 p.f, err = parseFilters(filters) 159 if err != nil { 160 return nil, err 161 } 162 163 if len(p.f.Compound) > 0 { 164 return nil, fmt.Errorf("compound filters are not supported by PuppetDB") 165 } 166 167 if p.nodeCache == nil { 168 p.nodeCache = []string{} 169 } 170 171 cfg := fw.Configuration() 172 nodes, err := puppetdb.New(fw).Discover(ctx, puppetdb.Filter(p.f), puppetdb.Timeout(time.Second*time.Duration(cfg.DiscoveryTimeout))) 173 if err != nil { 174 return []string{}, err 175 } 176 177 p.nodeCache = nodes 178 179 return copier(), nil 180 } 181 182 // MetaNS is a NodeSource that assists CLI tools in creating Choria standard command line based discovery. 183 type MetaNS struct { 184 // Options is the CLI options to discover based on 185 Options *discovery.StandardOptions 186 187 // Agent should be the agent the request is targeted at 188 Agent string 189 190 // DisablePipedDiscovery prevents the STDIN being used as a discovery source 191 DisablePipedDiscovery bool 192 193 nodeCache []string 194 sync.Mutex 195 } 196 197 // NewMetaNS creates a new meta discovery node source 198 func NewMetaNS(opts *discovery.StandardOptions, enablePipeMode bool) *MetaNS { 199 return &MetaNS{ 200 Options: opts, 201 Agent: "{{ .DDL.Metadata.Name }}", 202 DisablePipedDiscovery: !enablePipeMode, 203 nodeCache: []string{}, 204 } 205 } 206 207 // Reset resets the internal node cache 208 func (p *MetaNS) Reset() { 209 p.Lock() 210 defer p.Unlock() 211 212 p.nodeCache = []string{} 213 } 214 215 // Discover performs the discovery of nodes against the Choria Network. 216 func (p *MetaNS) Discover(ctx context.Context, fw inter.Framework, _ []FilterFunc) ([]string, error) { 217 p.Lock() 218 defer p.Unlock() 219 220 copier := func() []string { 221 out := make([]string, len(p.nodeCache)) 222 copy(out, p.nodeCache) 223 224 return out 225 } 226 227 if !(p.nodeCache == nil || len(p.nodeCache) == 0) { 228 return copier(), nil 229 } 230 231 if p.nodeCache == nil { 232 p.nodeCache = []string{} 233 } 234 235 if p.Options == nil { 236 return nil, fmt.Errorf("options have not been set") 237 } 238 239 nodes, _, err := p.Options.Discover(ctx, fw, p.Agent, !p.DisablePipedDiscovery, false, fw.Logger("discovery")) 240 if err != nil { 241 return nil, err 242 } 243 244 p.nodeCache = nodes 245 246 return copier(), nil 247 } 248 249 func parseFilters(fs []FilterFunc) (*protocol.Filter, error) { 250 filter := protocol.NewFilter() 251 252 for _, f := range fs { 253 err := f(filter) 254 if err != nil { 255 return nil, err 256 } 257 } 258 259 return filter, nil 260 }