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  }