Skip to content

Commit f4456b7

Browse files
committed
Support for TrueNAS' WebSocket APIs
1 parent 1816386 commit f4456b7

6 files changed

Lines changed: 57 additions & 54 deletions

File tree

frontend/src/core/i18n/I18nService.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,19 @@ export default class I18nService {
3636
if (!languageTag) this.repository.clear()
3737
else this.repository.set(languageTag)
3838

39+
await this.loadDictionary(languageTag)
40+
3941
I18nContext.replace({
4042
...I18nContext.get(),
4143
currentLanguage: languageTag,
4244
})
43-
44-
await this.loadDictionary(languageTag)
4545
}
4646

4747
private async loadDictionary(targetLanguage: string | null) {
4848
const context = I18nContext.get()
4949
const resolvedLanguage = resolveLanguageTag(
5050
context.availableLanguages,
51-
targetLanguage ?? context.currentLanguage,
51+
targetLanguage,
5252
context.defaultLanguage,
5353
)
5454

integration/truenas/client/cache.go

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,16 @@ import (
1111

1212
var (
1313
cacheDelegate *cache.Cache
14-
cacheInitLock = &sync.Once{}
15-
cacheMainLock = &sync.Mutex{}
14+
cacheInitOnce = &sync.Once{}
15+
cacheInitLock = &sync.Mutex{}
1616
)
1717

1818
func initCache(cfg *configuration.Configuration) error {
19-
var err error
19+
cacheInitLock.Lock()
20+
defer cacheInitLock.Unlock()
2021

21-
cacheInitLock.Do(func() {
22+
var err error
23+
cacheInitOnce.Do(func() {
2224
cacheDuration, innerErr := cfg.GetInt(
2325
"nginx-ignition.integration.truenas.api-cache-timeout-seconds",
2426
)
@@ -34,22 +36,22 @@ func initCache(cfg *configuration.Configuration) error {
3436
})
3537

3638
if err != nil {
37-
cacheInitLock = &sync.Once{}
39+
cacheInitOnce = &sync.Once{}
3840
}
3941

4042
return err
4143
}
4244

43-
func getFromCache[T any](key string, missProvider func() T) T {
44-
cacheMainLock.Lock()
45-
defer cacheMainLock.Unlock()
46-
45+
func getFromCache[T any](key string, missProvider func() (*T, error)) (*T, error) {
4746
if value, found := cacheDelegate.Get(key); found {
48-
return value.(T)
47+
return value.(*T), nil
4948
}
5049

51-
value := missProvider()
52-
cacheDelegate.Set(key, value, cache.DefaultExpiration)
50+
value, err := missProvider()
51+
if err != nil {
52+
return nil, err
53+
}
5354

54-
return value
55+
cacheDelegate.Set(key, value, cache.DefaultExpiration)
56+
return value, nil
5557
}

integration/truenas/client/client.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func For(cfg *configuration.Configuration, parameters map[string]any) (Client, e
2828
func useLegacyAPI(parameters map[string]any) bool {
2929
rawValue, found := parameters[fields.LegacyAPIFieldID]
3030
if !found {
31-
return false
31+
return true
3232
}
3333

3434
parsedValue, parsed := rawValue.(bool)

integration/truenas/client/rest_client.go

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,23 +35,26 @@ func (c *restClient) GetAvailableApps() ([]AvailableAppDTO, error) {
3535

3636
func (c *restClient) get(endpoint string, result any) error {
3737
cacheKey := fmt.Sprintf("%s:%s:rest:%s", c.baseURL, c.username, endpoint)
38-
response := getFromCache(cacheKey, func() []byte {
39-
output, err := c.executeGetRequest(endpoint, result)
38+
response, err := getFromCache(cacheKey, func() (*[]byte, error) {
39+
res, err := c.executeGetRequest(endpoint)
4040
if err != nil {
41-
panic(err)
41+
return nil, err
4242
}
4343

44-
return output
44+
return &res, nil
4545
})
46+
if err != nil {
47+
return err
48+
}
4649

4750
if response != nil {
48-
return json.Unmarshal(response, result)
51+
return json.Unmarshal(*response, result)
4952
}
5053

5154
return nil
5255
}
5356

54-
func (c *restClient) executeGetRequest(endpoint string, result any) ([]byte, error) {
57+
func (c *restClient) executeGetRequest(endpoint string) ([]byte, error) {
5558
req, err := http.NewRequest("GET", c.baseURL+"/api/v2.0/"+endpoint, nil)
5659
if err != nil {
5760
return nil, err
@@ -72,14 +75,5 @@ func (c *restClient) executeGetRequest(endpoint string, result any) ([]byte, err
7275
return nil, fmt.Errorf("unexpected HTTP status %d from TrueNAS REST API", resp.StatusCode)
7376
}
7477

75-
body, err := io.ReadAll(resp.Body)
76-
if err != nil {
77-
return nil, err
78-
}
79-
80-
if err = json.Unmarshal(body, result); err != nil {
81-
return nil, err
82-
}
83-
84-
return body, nil
78+
return io.ReadAll(resp.Body)
8579
}

integration/truenas/client/websocket_client.go

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -66,30 +66,21 @@ func newWebSocketClient(baseURL, username, password string) *webSocketClient {
6666
}
6767

6868
func (c *webSocketClient) GetAvailableApps() ([]AvailableAppDTO, error) {
69-
var apps []AvailableAppDTO
70-
7169
cacheKey := fmt.Sprintf("%s:%s:ws:app.query", c.baseURL, c.username)
72-
rawBytes := getFromCache(cacheKey, func() []byte {
73-
result, err := c.fetchApps()
74-
if err != nil {
75-
panic(err)
76-
}
77-
78-
b, err := json.Marshal(result)
70+
res, err := getFromCache(cacheKey, func() (*[]AvailableAppDTO, error) {
71+
res, err := c.fetchApps()
7972
if err != nil {
80-
panic(err)
73+
return nil, err
8174
}
8275

83-
return b
76+
return &res, nil
8477
})
8578

86-
if rawBytes != nil {
87-
if err := json.Unmarshal(rawBytes, &apps); err != nil {
88-
return nil, err
89-
}
79+
if err != nil || res == nil {
80+
return nil, err
9081
}
9182

92-
return apps, nil
83+
return *res, nil
9384
}
9485

9586
func (c *webSocketClient) fetchApps() ([]AvailableAppDTO, error) {
@@ -106,8 +97,13 @@ func (c *webSocketClient) fetchApps() ([]AvailableAppDTO, error) {
10697
//nolint:errcheck
10798
defer conn.Close()
10899

109-
if err = conn.SetReadDeadline(time.Now().Add(wsTimeout)); err != nil {
110-
return nil, fmt.Errorf("truenas websocket: set deadline: %w", err)
100+
deadline := time.Now().Add(wsTimeout)
101+
if err = conn.SetReadDeadline(deadline); err != nil {
102+
return nil, fmt.Errorf("truenas websocket: set read deadline: %w", err)
103+
}
104+
105+
if err = conn.SetWriteDeadline(deadline); err != nil {
106+
return nil, fmt.Errorf("truenas websocket: set write deadline: %w", err)
111107
}
112108

113109
if err = conn.WriteMessage(websocket.TextMessage, []byte(ddpConnectMsg)); err != nil {
@@ -190,7 +186,10 @@ func convertWSApps(raw []wsAppDTO) []AvailableAppDTO {
190186
}
191187

192188
func (c *webSocketClient) waitForMsg(conn *websocket.Conn, msgType string) error {
193-
for {
189+
remainingAttempts := 100
190+
for remainingAttempts > 0 {
191+
remainingAttempts--
192+
194193
_, raw, err := conn.ReadMessage()
195194
if err != nil {
196195
return err
@@ -205,10 +204,15 @@ func (c *webSocketClient) waitForMsg(conn *websocket.Conn, msgType string) error
205204
return nil
206205
}
207206
}
207+
208+
return errors.New("truenas websocket: timeout")
208209
}
209210

210211
func (c *webSocketClient) waitForResult(conn *websocket.Conn, id string) (json.RawMessage, error) {
211-
for {
212+
remainingAttempts := 100
213+
for remainingAttempts > 0 {
214+
remainingAttempts--
215+
212216
_, raw, err := conn.ReadMessage()
213217
if err != nil {
214218
return nil, err
@@ -227,6 +231,8 @@ func (c *webSocketClient) waitForResult(conn *websocket.Conn, id string) (json.R
227231
return msg.Result, nil
228232
}
229233
}
234+
235+
return nil, errors.New("truenas websocket: timeout")
230236
}
231237

232238
func buildWSURL(baseURL string) (string, error) {

integration/truenas/driver.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"net/url"
7+
"strconv"
78
"strings"
89

910
"dillmann.com.br/nginx-ignition/core/common/configuration"
@@ -158,7 +159,7 @@ func (a *Driver) getWorkloadPort(
158159
for _, app := range apps {
159160
if app.ID == appID {
160161
for _, port := range app.ActiveWorkloads.UsedPorts {
161-
if fmt.Sprintf("%d", port.ContainerPort) == containerPort {
162+
if strconv.Itoa(port.ContainerPort) == containerPort {
162163
return &app, &port, nil
163164
}
164165
}

0 commit comments

Comments
 (0)