@@ -22,22 +22,20 @@ import (
2222 "os"
2323 "path/filepath"
2424 "strings"
25- "sync"
2625
2726 "github.com/google/go-cmp/cmp"
28- "github.com/pkg/errors"
29-
3027 native_errors "github.com/haproxytech/client-native/v5/errors"
3128 "github.com/haproxytech/client-native/v5/misc"
3229 "github.com/haproxytech/client-native/v5/models"
3330 "github.com/haproxytech/client-native/v5/runtime/options"
31+ "github.com/pkg/errors"
32+ "golang.org/x/sync/singleflight"
3433)
3534
3635// Client handles multiple HAProxy clients
3736type client struct {
38- haproxyVersion * HAProxyVersion
39- options options.RuntimeOptions
40- runtimes []* SingleRuntime
37+ options options.RuntimeOptions
38+ runtimes []* SingleRuntime
4139}
4240
4341const (
@@ -104,44 +102,53 @@ func (c *client) GetInfo() (models.ProcessInfos, error) {
104102 return result , nil
105103}
106104
107- var versionSync sync.Once //nolint:gochecknoglobals
105+ var (
106+ haproxyVersion * HAProxyVersion //nolint:gochecknoglobals
107+ versionKey = "version" //nolint:gochecknoglobals
108+ versionSfg = singleflight.Group {} //nolint:gochecknoglobals
109+ )
108110
109111// GetVersion returns info from the socket
110112func (c * client ) GetVersion () (HAProxyVersion , error ) {
111113 var err error
112- versionSync .Do (func () {
114+ if haproxyVersion != nil {
115+ return * haproxyVersion , nil
116+ }
117+ _ , err , _ = versionSfg .Do (versionKey , func () (interface {}, error ) {
113118 version := & HAProxyVersion {}
114119 for _ , runtime := range c .runtimes {
115120 var response string
116121 response , err = runtime .ExecuteRaw ("show info" )
117122 if err != nil {
118- return
123+ return HAProxyVersion {}, err
119124 }
120125 for _ , line := range strings .Split (response , "\n " ) {
121126 if strings .HasPrefix (line , "Version: " ) {
122127 err = version .ParseHAProxyVersion (strings .TrimPrefix (line , "Version: " ))
123128 if err != nil {
124- return
129+ return HAProxyVersion {}, err
125130 }
126- c . haproxyVersion = version
127- return
131+ haproxyVersion = version
132+ return haproxyVersion , nil
128133 }
129134 }
130135 }
131- err = fmt .Errorf ("version data not found" )
136+ err = errors .New ("version data not found" )
137+ return HAProxyVersion {}, err // it's dereferenced in IsVersionBiggerOrEqual
132138 })
133139 if err != nil {
134140 return HAProxyVersion {}, err
135141 }
136142
137- if c . haproxyVersion == nil {
138- return HAProxyVersion {}, fmt . Errorf ("version data not found" )
143+ if haproxyVersion == nil {
144+ return HAProxyVersion {}, errors . New ("version data not found" )
139145 }
140- return * c .haproxyVersion , err
146+
147+ return * haproxyVersion , err
141148}
142149
143150func (c * client ) IsVersionBiggerOrEqual (minimumVersion * HAProxyVersion ) bool {
144- return IsBiggerOrEqual (minimumVersion , c . haproxyVersion )
151+ return IsBiggerOrEqual (minimumVersion , haproxyVersion )
145152}
146153
147154// Reloads HAProxy's configuration file. Similar to SIGUSR2. Returns the startup logs.
@@ -152,7 +159,7 @@ func (c *client) Reload() (string, error) {
152159 return "" , fmt .Errorf ("cannot reload: not connected to a master socket" )
153160 }
154161 if ! c .IsVersionBiggerOrEqual (& HAProxyVersion {Major : 2 , Minor : 7 }) {
155- return "" , fmt .Errorf ("cannot reload: requires HAProxy 2.7 or later" )
162+ return "" , fmt .Errorf ("cannot reload: requires HAProxy 2.7 or later but current version is %v" , haproxyVersion )
156163 }
157164
158165 for _ , runtime := range c .runtimes {
@@ -229,7 +236,7 @@ func (c *client) AddServer(backend, name, attributes string) error {
229236 return fmt .Errorf ("no valid runtimes found" )
230237 }
231238 if ! c .IsVersionBiggerOrEqual (& HAProxyVersion {Major : 2 , Minor : 6 }) {
232- return fmt .Errorf ("this operation requires HAProxy 2.6 or later" )
239+ return fmt .Errorf ("this operation requires HAProxy 2.6 or later but current version is %v" , haproxyVersion )
233240 }
234241 for _ , runtime := range c .runtimes {
235242 err := runtime .AddServer (backend , name , attributes )
0 commit comments