Skip to content

Commit a2803bf

Browse files
refactor: use single http client instance (#459)
* refactor: use single http client instance * fix: use single http instance for cluster * fix(orchestration): remove timout from http client * fix: remove not needed methods * fix: resolve comments
1 parent 43b99ac commit a2803bf

File tree

27 files changed

+325
-330
lines changed

27 files changed

+325
-330
lines changed

cmd/beekeeper/cmd/cluster.go

Lines changed: 9 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func (c *command) deleteCluster(ctx context.Context, clusterName string, cfg *co
2929
return fmt.Errorf("cluster %s not defined", clusterName)
3030
}
3131

32-
cluster := initializeCluster(clusterConfig, c)
32+
cluster := orchestrationK8S.NewCluster(clusterConfig.GetName(), clusterConfig.Export(), c.k8sClient, c.swapClient, c.log)
3333

3434
// delete node groups
3535
for ngName, v := range clusterConfig.GetNodeGroups() {
@@ -44,7 +44,7 @@ func (c *command) deleteCluster(ctx context.Context, clusterName string, cfg *co
4444
cluster.AddNodeGroup(ngName, ngConfig.Export())
4545

4646
// delete nodes from the node group
47-
g, err := cluster.NodeGroup(ngName)
47+
ng, err := cluster.NodeGroup(ngName)
4848
if err != nil {
4949
return fmt.Errorf("get node group: %w", err)
5050
}
@@ -54,7 +54,7 @@ func (c *command) deleteCluster(ctx context.Context, clusterName string, cfg *co
5454
if len(v.Nodes[i].Name) > 0 {
5555
nName = v.Nodes[i].Name
5656
}
57-
if err := g.DeleteNode(ctx, nName); err != nil {
57+
if err := ng.DeleteNode(ctx, nName); err != nil {
5858
return fmt.Errorf("deleting node %s from the node group %s: %w", nName, ngName, err)
5959
}
6060

@@ -144,7 +144,7 @@ func (c *command) setupCluster(ctx context.Context, clusterName string, startClu
144144
fundOpts = ensureFundingDefaults(clusterConfig.Funding.Export(), c.log)
145145
}
146146

147-
cluster = initializeCluster(clusterConfig, c)
147+
cluster = orchestrationK8S.NewCluster(clusterConfig.GetName(), clusterConfig.Export(), c.k8sClient, c.swapClient, c.log)
148148

149149
nodeResultChan := make(chan nodeResult)
150150
defer close(nodeResultChan)
@@ -197,13 +197,6 @@ func ensureFundingDefaults(fundOpts orchestration.FundingOptions, log logging.Lo
197197
return fundOpts
198198
}
199199

200-
func initializeCluster(clusterConfig config.Cluster, c *command) orchestration.Cluster {
201-
clusterOpts := clusterConfig.Export()
202-
clusterOpts.SwapClient = c.swapClient
203-
clusterOpts.K8SClient = c.k8sClient
204-
return orchestrationK8S.NewCluster(clusterConfig.GetName(), clusterOpts, c.log)
205-
}
206-
207200
func setupNodes(ctx context.Context,
208201
clusterConfig config.Cluster,
209202
cfg *config.Config,
@@ -313,7 +306,7 @@ func setupOrAddNode(ctx context.Context,
313306
beeOpt orchestration.BeeClientOption,
314307
) {
315308
if startCluster {
316-
ethAddress, err := ng.SetupNode(ctx, nodeName, inCluster, nodeOpts)
309+
ethAddress, err := ng.DeployNode(ctx, nodeName, inCluster, nodeOpts)
317310
ch <- nodeResult{
318311
ethAddress: ethAddress,
319312
err: err,
@@ -326,17 +319,11 @@ func setupOrAddNode(ctx context.Context,
326319
}
327320

328321
func setupNodeOptions(node config.ClusterNode, bConfig *orchestration.Config) orchestration.NodeOptions {
329-
nOptions := orchestration.NodeOptions{
330-
Config: bConfig,
331-
}
332-
333-
if len(node.LibP2PKey) > 0 {
334-
nOptions.LibP2PKey = node.LibP2PKey
335-
}
336-
if node.SwarmKey != nil {
337-
nOptions.SwarmKey = node.SwarmKey
322+
return orchestration.NodeOptions{
323+
Config: bConfig,
324+
LibP2PKey: node.LibP2PKey,
325+
SwarmKey: node.SwarmKey,
338326
}
339-
return nOptions
340327
}
341328

342329
func fund(

cmd/beekeeper/cmd/cmd.go

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,23 @@ import (
55
"errors"
66
"fmt"
77
"io"
8+
"net/http"
89
"net/url"
910
"os"
1011
"path/filepath"
1112
"strings"
13+
"time"
1214

1315
"github.com/ethersphere/beekeeper/pkg/config"
16+
"github.com/ethersphere/beekeeper/pkg/httpx"
1417
"github.com/ethersphere/beekeeper/pkg/k8s"
1518
"github.com/ethersphere/beekeeper/pkg/logging"
1619
"github.com/ethersphere/beekeeper/pkg/scheduler"
1720
"github.com/ethersphere/beekeeper/pkg/swap"
1821
"github.com/go-git/go-billy/v5/memfs"
1922
"github.com/go-git/go-git/v5"
2023
"github.com/go-git/go-git/v5/plumbing"
21-
"github.com/go-git/go-git/v5/plumbing/transport/http"
24+
httptransport "github.com/go-git/go-git/v5/plumbing/transport/http"
2225
"github.com/go-git/go-git/v5/storage/memory"
2326
"github.com/sirupsen/logrus"
2427
"github.com/spf13/cobra"
@@ -61,7 +64,8 @@ type command struct {
6164
globalConfigFile string
6265
homeDir string
6366
config *config.Config // beekeeper clusters configuration (config dir)
64-
k8sClient *k8s.Client // kubernetes client
67+
httpClient *http.Client
68+
k8sClient *k8s.Client // kubernetes client
6569
swapClient swap.Client
6670
log logging.Logger
6771
}
@@ -79,6 +83,12 @@ func newCommand(opts ...option) (c *command, err error) {
7983
return c.initConfig(cmd.Flags().Changed(optionNameClusterName))
8084
},
8185
},
86+
httpClient: &http.Client{
87+
Transport: &httpx.HeaderRoundTripper{
88+
Next: http.DefaultTransport,
89+
},
90+
Timeout: 30 * time.Second,
91+
},
8292
}
8393

8494
for _, o := range opts {
@@ -248,7 +258,7 @@ func (c *command) initLogger() error {
248258
verbosity := c.globalConfig.GetString(optionNameLogVerbosity)
249259
lokiEndpoint := c.globalConfig.GetString(optionNameLokiEndpoint)
250260

251-
log, err := newLogger(c.root, verbosity, lokiEndpoint)
261+
log, err := newLogger(c.root, verbosity, lokiEndpoint, c.httpClient)
252262
if err != nil {
253263
return fmt.Errorf("new logger: %w", err)
254264
}
@@ -263,7 +273,7 @@ func (c *command) loadConfigDirectory() error {
263273
// read configuration from git repo
264274
fs := memfs.New()
265275
if _, err := git.Clone(memory.NewStorage(), fs, &git.CloneOptions{
266-
Auth: &http.BasicAuth{
276+
Auth: &httptransport.BasicAuth{
267277
Username: c.globalConfig.GetString(optionNameConfigGitUsername),
268278
Password: c.globalConfig.GetString(optionNameConfigGitPassword),
269279
},
@@ -429,6 +439,7 @@ func (c *command) setSwapClient() (err error) {
429439
c.swapClient = swap.NewGethClient(gethUrl, &swap.GethClientOptions{
430440
BzzTokenAddress: c.globalConfig.GetString("bzz-token-address"),
431441
EthAccount: c.globalConfig.GetString("eth-account"),
442+
HTTPClient: c.httpClient,
432443
}, c.log)
433444
} else {
434445
c.swapClient = &swap.NotSet{}
@@ -437,10 +448,10 @@ func (c *command) setSwapClient() (err error) {
437448
return
438449
}
439450

440-
func newLogger(cmd *cobra.Command, verbosity, lokiEndpoint string) (logging.Logger, error) {
451+
func newLogger(cmd *cobra.Command, verbosity, lokiEndpoint string, httpClient *http.Client) (logging.Logger, error) {
441452
var logger logging.Logger
442453
opts := []logging.LoggerOption{
443-
logging.WithLokiOption(lokiEndpoint),
454+
logging.WithLokiOption(lokiEndpoint, httpClient),
444455
logging.WithMetricsOption(),
445456
}
446457

config/config.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ checks:
194194
options:
195195
cache-size: 10
196196
reserve-size: 16
197+
postage-label: gc-check
197198
timeout: 5m
198199
type: gc
199200
kademlia:
@@ -236,6 +237,7 @@ checks:
236237
type: postage
237238
timeout: 5m
238239
options:
240+
postage-label: postage-check
239241
postage-amount: 1000
240242
postage-depth: 17
241243
postage-topup-amount: 100

config/local.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ checks:
196196
options:
197197
cache-size: 10
198198
reserve-size: 16
199+
postage-label: gc-check
199200
timeout: 5m
200201
type: gc
201202
ci-manifest:
@@ -311,6 +312,7 @@ checks:
311312
type: postage
312313
timeout: 5m
313314
options:
315+
postage-label: postage-check
314316
postage-amount: 1000
315317
postage-depth: 17
316318
postage-topup-amount: 100

config/public-testnet.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ checks:
123123
type: postage
124124
timeout: 30m
125125
options:
126+
postage-label: postage-check
126127
postage-amount: 140000000
127128
postage-depth: 17
128129
postage-topup-amount: 100

pkg/bee/api/api.go

Lines changed: 38 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ import (
1111
"net/url"
1212
"strconv"
1313
"strings"
14-
15-
"github.com/ethersphere/bee/v2/pkg/swarm"
16-
"github.com/ethersphere/beekeeper"
1714
)
1815

1916
const (
@@ -38,11 +35,10 @@ const (
3835
swarmErrorDocumentHeader = "Swarm-Error-Document"
3936
)
4037

41-
var userAgent = "beekeeper/" + beekeeper.Version
42-
4338
// Client manages communication with the Bee API.
4439
type Client struct {
4540
httpClient *http.Client // HTTP client must handle authentication implicitly.
41+
apiURL *url.URL // Base URL for API requests.
4642
service service // Reuse a single struct instead of allocating one for each service on the heap.
4743

4844
// Services that API provides.
@@ -70,22 +66,24 @@ type ClientOptions struct {
7066
}
7167

7268
// NewClient constructs a new Client.
73-
func NewClient(baseURL *url.URL, o *ClientOptions) (c *Client) {
74-
if o == nil {
75-
o = new(ClientOptions)
69+
func NewClient(apiURL *url.URL, httpClient *http.Client) (*Client, error) {
70+
if httpClient == nil {
71+
httpClient = &http.Client{}
7672
}
77-
if o.HTTPClient == nil {
78-
o.HTTPClient = new(http.Client)
73+
if apiURL == nil {
74+
return nil, errors.New("baseURL is required")
7975
}
8076

81-
c = newClient(httpClientWithTransport(baseURL, o.HTTPClient))
82-
return
77+
return newClient(apiURL, httpClient), nil
8378
}
8479

8580
// newClient constructs a new *Client with the provided http Client, which
8681
// should handle authentication implicitly, and sets all API services.
87-
func newClient(httpClient *http.Client) (c *Client) {
88-
c = &Client{httpClient: httpClient}
82+
func newClient(apiURL *url.URL, httpClient *http.Client) (c *Client) {
83+
c = &Client{
84+
httpClient: httpClient,
85+
apiURL: apiURL,
86+
}
8987
c.service.client = c
9088

9189
c.Act = (*ActService)(&c.service)
@@ -108,32 +106,6 @@ func newClient(httpClient *http.Client) (c *Client) {
108106
return c
109107
}
110108

111-
func httpClientWithTransport(baseURL *url.URL, c *http.Client) *http.Client {
112-
if c == nil {
113-
c = new(http.Client)
114-
}
115-
116-
transport := c.Transport
117-
if transport == nil {
118-
transport = http.DefaultTransport
119-
}
120-
121-
if !strings.HasSuffix(baseURL.Path, "/") {
122-
baseURL.Path += "/"
123-
}
124-
125-
c.Transport = roundTripperFunc(func(r *http.Request) (resp *http.Response, err error) {
126-
r.Header.Set("User-Agent", userAgent)
127-
u, err := baseURL.Parse(r.URL.String())
128-
if err != nil {
129-
return nil, err
130-
}
131-
r.URL = u
132-
return transport.RoundTrip(r)
133-
})
134-
return c
135-
}
136-
137109
// requestJSON handles the HTTP request response cycle. It JSON encodes the request
138110
// body, creates an HTTP request with provided method on a path with required
139111
// headers and decodes request body if the v argument is not nil and content type is
@@ -150,9 +122,22 @@ func (c *Client) requestJSON(ctx context.Context, method, path string, body, v i
150122
return c.request(ctx, method, path, bodyBuffer, v)
151123
}
152124

125+
func (c *Client) getFullURL(path string) (string, error) {
126+
rel, err := url.Parse(path)
127+
if err != nil {
128+
return "", fmt.Errorf("failed to parse path: %w", err)
129+
}
130+
return c.apiURL.ResolveReference(rel).String(), nil
131+
}
132+
153133
// request handles the HTTP request response cycle.
154134
func (c *Client) request(ctx context.Context, method, path string, body io.Reader, v interface{}) (err error) {
155-
req, err := http.NewRequest(method, path, body)
135+
fullURL, err := c.getFullURL(path)
136+
if err != nil {
137+
return err
138+
}
139+
140+
req, err := http.NewRequest(method, fullURL, body)
156141
if err != nil {
157142
return err
158143
}
@@ -196,7 +181,12 @@ func (c *Client) requestData(ctx context.Context, method, path string, body io.R
196181

197182
// requestDataGetHeader handles the HTTP request response cycle and returns the response body and header.
198183
func (c *Client) requestDataGetHeader(ctx context.Context, method, path string, body io.Reader, opts *DownloadOptions) (resp io.ReadCloser, h http.Header, err error) {
199-
req, err := http.NewRequest(method, path, body)
184+
fullURL, err := c.getFullURL(path)
185+
if err != nil {
186+
return nil, nil, err
187+
}
188+
189+
req, err := http.NewRequest(method, fullURL, body)
200190
if err != nil {
201191
return nil, nil, err
202192
}
@@ -245,7 +235,12 @@ func (c *Client) requestDataGetHeader(ctx context.Context, method, path string,
245235

246236
// requestWithHeader handles the HTTP request response cycle.
247237
func (c *Client) requestWithHeader(ctx context.Context, method, path string, header http.Header, body io.Reader, v interface{}, headerParser ...func(http.Header)) (err error) {
248-
req, err := http.NewRequest(method, path, body)
238+
fullURL, err := c.getFullURL(path)
239+
if err != nil {
240+
return err
241+
}
242+
243+
req, err := http.NewRequest(method, fullURL, body)
249244
if err != nil {
250245
return err
251246
}
@@ -324,40 +319,3 @@ func responseErrorHandler(r *http.Response) (err error) {
324319
type service struct {
325320
client *Client
326321
}
327-
328-
// Bool is a helper routine that allocates a new bool value to store v and
329-
// returns a pointer to it.
330-
func Bool(v bool) (p *bool) { return &v }
331-
332-
// roundTripperFunc type is an adapter to allow the use of ordinary functions as
333-
// http.RoundTripper interfaces. If f is a function with the appropriate
334-
// signature, roundTripperFunc(f) is a http.RoundTripper that calls f.
335-
type roundTripperFunc func(*http.Request) (*http.Response, error)
336-
337-
// RoundTrip calls f(r).
338-
func (f roundTripperFunc) RoundTrip(r *http.Request) (*http.Response, error) {
339-
return f(r)
340-
}
341-
342-
type UploadOptions struct {
343-
Act bool
344-
Pin bool
345-
Tag uint64
346-
BatchID string
347-
Direct bool
348-
ActHistoryAddress swarm.Address
349-
350-
// Dirs
351-
IndexDocument string
352-
ErrorDocument string
353-
}
354-
355-
type DownloadOptions struct {
356-
Act *bool
357-
ActHistoryAddress *swarm.Address
358-
ActPublicKey *swarm.Address
359-
ActTimestamp *uint64
360-
Cache *bool
361-
RedundancyFallbackMode *bool
362-
OnlyRootChunk *bool
363-
}

0 commit comments

Comments
 (0)