github.com/choria-io/go-choria@v0.28.1-0.20240416190746-b3bf9c7d5a45/providers/provtarget/provtarget.go (about) 1 // Copyright (c) 2021, R.I. Pienaar and the Choria Project contributors 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 5 package provtarget 6 7 import ( 8 "context" 9 "fmt" 10 "sync" 11 12 "github.com/choria-io/go-choria/config" 13 "github.com/choria-io/go-choria/providers/provtarget/builddefaults" 14 "github.com/sirupsen/logrus" 15 16 "github.com/choria-io/go-choria/srvcache" 17 ) 18 19 // TargetResolver is capable of resolving the target brokers for provisioning into list of strings in the format host:port 20 type TargetResolver interface { 21 // Name the display name that will be shown in places like `choria buildinfo` 22 Name() string 23 24 // Targets will be called to determine the provisioning destination 25 Targets(context.Context, *logrus.Entry) []string 26 27 // Configure will be called during server configuration and can be used to configure the target or adjust build settings or configuration 28 // this will always be called even when not in provisioning mode, one can use this to programmatically set a provisioner token for example 29 // 30 // The intention of this function is that all the settings needed by provisioning (all the things in build) should be set during configure 31 // stage. Later when Targets() are called the intention is that either the configured targets are returned verbatim or if for example the 32 // plugin queries something like SRV records those queries are done there. 33 // 34 // Today Configure() is expected to set the JWT file using bi.SetProvisionJWTFile() and that the file should exist before probisioning will 35 // happen, this will be revisited in future. See the shouldProvision() function in server_run.go for current logic that would trigger a 36 // server into provisioning. 37 Configure(context.Context, *config.Config, *logrus.Entry) 38 } 39 40 var mu = &sync.Mutex{} 41 var resolver = TargetResolver(builddefaults.Provider()) 42 43 // RegisterTargetResolver registers a custom target resolver, else the default will be used 44 func RegisterTargetResolver(r TargetResolver) error { 45 mu.Lock() 46 defer mu.Unlock() 47 48 resolver = r 49 50 return nil 51 } 52 53 // Configure allows the resolver to adjust configuration 54 func Configure(ctx context.Context, cfg *config.Config, log *logrus.Entry) { 55 mu.Lock() 56 defer mu.Unlock() 57 58 if resolver == nil { 59 return 60 } 61 62 resolver.Configure(ctx, cfg, log) 63 } 64 65 // Targets is a list of brokers to connect to 66 func Targets(ctx context.Context, log *logrus.Entry) (srvcache.Servers, error) { 67 mu.Lock() 68 defer mu.Unlock() 69 70 if resolver == nil { 71 return srvcache.NewServers(), fmt.Errorf("no Provisioning Target Resolver registered") 72 } 73 74 s := resolver.Targets(ctx, log) 75 76 if len(s) == 0 { 77 return srvcache.NewServers(), fmt.Errorf("provisioning target plugin %s returned no servers", Name()) 78 } 79 80 servers, err := srvcache.StringHostsToServers(s, "nats") 81 if err != nil { 82 return srvcache.NewServers(), fmt.Errorf("could not determine provisioning servers using %s provisioning target plugin: %s", Name(), err) 83 } 84 85 if servers.Count() == 0 { 86 return srvcache.NewServers(), fmt.Errorf("provisioning broker urls from the %s plugin were not in the valid format, 0 server:port combinations were found in %v", Name(), s) 87 } 88 89 return servers, nil 90 } 91 92 // Name is the name of the plugin used 93 func Name() string { 94 if resolver == nil { 95 return "Unknown" 96 } 97 98 return resolver.Name() 99 }