From 53743da690975f19c87fa892b49cd552c7b79271 Mon Sep 17 00:00:00 2001 From: Rafal Chrabaszcz Date: Thu, 17 Oct 2024 10:37:32 +0200 Subject: [PATCH] Add version detection to client (#10) --- client.go | 39 +++++++++++++++++++++++++++++++++++++++ client_test.go | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 73 insertions(+), 3 deletions(-) diff --git a/client.go b/client.go index 1346bfe..09a83ad 100644 --- a/client.go +++ b/client.go @@ -65,6 +65,8 @@ type Client struct { DomainUUID string // Map of domain names to domain UUIDs Domains map[string]string + // FMC Version + FMCVersion string RateLimiterBucket *ratelimit.Bucket @@ -105,9 +107,22 @@ func NewClient(url, usr, pwd string, mods ...func(*Client)) (Client, error) { for _, mod := range mods { mod(&client) } + + err := client.GetFMCVersion() + if err != nil { + return client, err + } + return client, nil } +// Replace the default HTTP client with a custom one. +func CustomHttpClient(httpClient *http.Client) func(*Client) { + return func(client *Client) { + client.HttpClient = httpClient + } +} + // Insecure determines if insecure https connections are allowed. Default value is true. func Insecure(x bool) func(*Client) { return func(client *Client) { @@ -460,3 +475,27 @@ func (client *Client) Backoff(attempts int) bool { log.Printf("[DEBUG] Exit from backoff method with return value true") return true } + +// Get FMC Version +func (client *Client) GetFMCVersion() error { + // If version is already known, no need to get it from FMC + if client.FMCVersion != "" { + return nil + } + + res, err := client.Get("/api/fmc_platform/v1/info/serverversion") + if err != nil { + log.Printf("[ERROR] Failed to retrieve FMC version: %s", err.Error()) + return fmt.Errorf("failed to retrieve FMC version: %s", err.Error()) + } + + fmcVersion := res.Get("items.0.serverVersion") + if !fmcVersion.Exists() { + log.Printf("[ERROR] Failed to retrieve FMC version: version not found in FMC responses") + return fmt.Errorf("failed to retrieve FMC version: version not found in FMC response") + } + + client.FMCVersion = fmcVersion.String() + + return nil +} diff --git a/client_test.go b/client_test.go index 728835c..88faae3 100644 --- a/client_test.go +++ b/client_test.go @@ -16,8 +16,19 @@ const ( ) func testClient() Client { - client, _ := NewClient(testURL, "usr", "pwd", MaxRetries(0)) - gock.InterceptClient(client.HttpClient) + defer gock.Off() + + // Client will try to get FMC version on creation, so we need to mock those + gock.New(testURL).Post("/api/fmc_platform/v1/auth/generatetoken").Reply(204) + gock.New(testURL).Get("/api/fmc_platform/v1/info/serverversion").Reply(200).BodyString(`{"items":[{"serverVersion":"7.2.4 (build 123)"}]}`) + + // Prepare client and intercept + httpClient := &http.Client{} + gock.InterceptClient(httpClient) + + // Create client + client, _ := NewClient(testURL, "usr", "pwd", CustomHttpClient(httpClient), MaxRetries(0)) + return client } @@ -41,7 +52,18 @@ func (r ErrReader) Read(buf []byte) (int, error) { // TestNewClient tests the NewClient function. func TestNewClient(t *testing.T) { - client, _ := NewClient(testURL, "usr", "pwd", RequestTimeout(120)) + defer gock.Off() + + // Client will try to get FMC version on creation, so we need to mock those + gock.New(testURL).Post("/api/fmc_platform/v1/auth/generatetoken").Reply(204) + gock.New(testURL).Get("/api/fmc_platform/v1/info/serverversion").Reply(200).BodyString(`{"items":[{"serverVersion":"7.2.4 (build 123)"}]}`) + + // Prepare client and intercept + httpClient := &http.Client{} + gock.InterceptClient(httpClient) + + // Create client + client, _ := NewClient(testURL, "usr", "pwd", CustomHttpClient(httpClient), RequestTimeout(120)) assert.Equal(t, client.HttpClient.Timeout, 120*time.Second) } @@ -59,6 +81,15 @@ func TestClientLogin(t *testing.T) { assert.Error(t, client.Login()) } +// TestClientGetFMCVersion tests the Client::GetFMCVersion method. +func TestClientGetFMCVersion(t *testing.T) { + defer gock.Off() + client := testClient() + + // Version already known + assert.Equal(t, "7.2.4 (build 123)", client.FMCVersion) +} + // TestClientGet tests the Client::Get method. func TestClientGet(t *testing.T) { defer gock.Off()