Skip to content

Commit 54d08f6

Browse files
committed
Fix OpenSearch 3.4.0+ API compatibility and enhance test infrastructure
This commit resolves compatibility issues discovered during integration testing with OpenSearch 3.4.0+, ensuring the Go client works seamlessly with the latest OpenSearch versions. - **Nodes Stats API**: Add warmer fields to merges section with proper _count/_millis suffixes; add status_counter field with doc_status subfields - **Indices Stats API**: Add warmer fields to IndicesStatsMerges struct with proper _count/_millis suffixes - **Cat Thread Pool API**: Add parallelism field for thread pool metrics - **Cat APIs** (indices, shards, nodes): Add comprehensive merges warmer fields matching flattened JSON structure from OpenSearch responses - Fix Cat APIs JSON unmarshaling by changing byte fields from *int to *string to properly handle OpenSearch 3.4.0+ values like "0b" - Remove incorrect ,string JSON tags from string fields - Ensures compatibility with OpenSearch's mixed data type responses - Correctly implement different naming patterns across API families: - Cat APIs: total_invocations, total_time - Stats APIs: total_invocations_count, total_time_millis Signed-off-by: Sean Chittenden <sean.chittenden@crowdstrike.com>
1 parent ef30606 commit 54d08f6

7 files changed

Lines changed: 286 additions & 210 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
2929
- Fix cat APIs compatibility with OpenSearch 3.3.0+ by adding query_failed and startree_query_failed search fields
3030
- Fix cluster state API compatibility with OpenSearch 3.3.0+ by adding ingestion_status field to index metadata
3131
- Fix security config API compatibility with OpenSearch 3.3.0+ by adding jwks_uri field to JWT authentication configuration
32+
- Fix nodes stats API compatibility with OpenSearch 3.4.0+ by adding warmer field to merges section and status_counter field
33+
- Fix indices stats API compatibility with OpenSearch 3.4.0+ by adding warmer field to merges section
34+
- Fix cat APIs compatibility with OpenSearch 3.4.0+ by adding parallelism field to thread pool and warmer fields to merges section
35+
- Fix cat APIs data type compatibility by changing byte fields from int to string to properly handle values like "0b"
3236

3337
### Security
3438

opensearchapi/api_cat-indices.go

Lines changed: 118 additions & 101 deletions
Large diffs are not rendered by default.

opensearchapi/api_cat-nodes.go

Lines changed: 75 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -37,72 +37,81 @@ type CatNodesResp struct {
3737

3838
// CatNodesItemResp represents one index of the CatNodesResp
3939
type CatNodesItemResp struct {
40-
ID string `json:"id"`
41-
PID *string `json:"pid"`
42-
IP string `json:"ip"`
43-
Port int `json:"port,string"`
44-
HTTPAddress string `json:"http_address"`
45-
Version string `json:"version"`
46-
Type *string `json:"type"`
47-
Build *string `json:"build"`
48-
JDK *string `json:"jdk"`
49-
DiskTotal *string `json:"disk.total"`
50-
DiskUsed *string `json:"disk.used"`
51-
DiskAvail *string `json:"disk.avail"`
52-
DiskUsedPercent *string `json:"disk.used_percent"`
53-
HeapCurrent *string `json:"heap.current"`
54-
HeapPercent *int `json:"heap.percent,string"`
55-
HeapMax *string `json:"heap.max"`
56-
RAMCurrent *string `json:"ram.current"`
57-
RAMPercent *int `json:"ram.percent,string"`
58-
RAMMax *string `json:"ram.max"`
59-
FileDescCurrent *int `json:"file_desc.current,string"`
60-
FileDescPercent *int `json:"file_desc.percent,string"`
61-
FileDescMax *int `json:"file_desc.max,string"`
62-
CPU *int `json:"cpu,string"`
63-
Load1M *string `json:"load_1m"`
64-
Load5M *string `json:"load_5m"`
65-
Load15M *string `json:"load_15m"`
66-
Uptime *string `json:"uptime"`
67-
Role string `json:"node.role"`
68-
Roles string `json:"node.roles"`
69-
Master string `json:"master"`
70-
ClusterManager string `json:"cluster_manager"`
71-
Name string `json:"name"`
72-
CompletionSize *string `json:"completion.size"`
73-
FieldDataMemorySize *string `json:"fielddata.memory_size"`
74-
FileldDataEvictions *int `json:"fielddata.evictions,string"`
75-
QueryCacheMemorySize *string `json:"query_cache.memory_size"`
76-
QueryCacheEvictions *int `json:"query_cache.evictions,string"`
77-
QueryCacheHitCount *int `json:"query_cache.hit_count,string"`
78-
QueryCacheMissCount *int `json:"query_cache.miss_count,string"`
79-
RequestCacheMemorySize *string `json:"request_cache.memory_size"`
80-
RequestCacheEvictions *int `json:"request_cache.evictions,string"`
81-
RequestCacheHitCount *int `json:"request_cache.hit_count,string"`
82-
RequestCacheMissCount *int `json:"request_cache.miss_count,string"`
83-
FlushTotal *int `json:"flush.total,string"`
84-
FlushTotalTime *string `json:"flush.total_time"`
85-
GetCurrent *int `json:"get.current,string"`
86-
GetTime *string `json:"get.time"`
87-
GetTotal *int `json:"get.total,string"`
88-
GetExistsTime *string `json:"get.exists_time"`
89-
GetExistsTotal *int `json:"get.exists_total,string"`
90-
GetMissingTime *string `json:"get.missing_time"`
91-
GetMissingTotal *int `json:"get.missing_total,string"`
92-
IndexingDeleteCurrent *int `json:"indexing.delete_current,string"`
93-
IndexingDeleteTime *string `json:"indexing.delete_time"`
94-
IndexingDeleteTotal *int `json:"indexing.delete_total,string"`
95-
IndexingIndexCurrent *int `json:"indexing.index_current,string"`
96-
IndexingIndexTime *string `json:"indexing.index_time"`
97-
IndexingIndexTotal *int `json:"indexing.index_total,string"`
98-
IndexingIndexFailed *int `json:"indexing.index_failed,string"`
99-
MergesCurrent *int `json:"merges.current,string"`
100-
MergesCurrentDoc *int `json:"merges.current_docs,string"`
101-
MergesCurrentSize *string `json:"merges.current_size"`
102-
MergesTotal *int `json:"merges.total,string"`
103-
MergesTotalDocs *int `json:"merges.total_docs,string"`
104-
MergesTotalSize *string `json:"merges.total_size"`
105-
MergesTotalTime *string `json:"merges.total_time"`
40+
ID string `json:"id"`
41+
PID *string `json:"pid"`
42+
IP string `json:"ip"`
43+
Port int `json:"port,string"`
44+
HTTPAddress string `json:"http_address"`
45+
Version string `json:"version"`
46+
Type *string `json:"type"`
47+
Build *string `json:"build"`
48+
JDK *string `json:"jdk"`
49+
DiskTotal *string `json:"disk.total"`
50+
DiskUsed *string `json:"disk.used"`
51+
DiskAvail *string `json:"disk.avail"`
52+
DiskUsedPercent *string `json:"disk.used_percent"`
53+
HeapCurrent *string `json:"heap.current"`
54+
HeapPercent *int `json:"heap.percent,string"`
55+
HeapMax *string `json:"heap.max"`
56+
RAMCurrent *string `json:"ram.current"`
57+
RAMPercent *int `json:"ram.percent,string"`
58+
RAMMax *string `json:"ram.max"`
59+
FileDescCurrent *int `json:"file_desc.current,string"`
60+
FileDescPercent *int `json:"file_desc.percent,string"`
61+
FileDescMax *int `json:"file_desc.max,string"`
62+
CPU *int `json:"cpu,string"`
63+
Load1M *string `json:"load_1m"`
64+
Load5M *string `json:"load_5m"`
65+
Load15M *string `json:"load_15m"`
66+
Uptime *string `json:"uptime"`
67+
Role string `json:"node.role"`
68+
Roles string `json:"node.roles"`
69+
Master string `json:"master"`
70+
ClusterManager string `json:"cluster_manager"`
71+
Name string `json:"name"`
72+
CompletionSize *string `json:"completion.size"`
73+
FieldDataMemorySize *string `json:"fielddata.memory_size"`
74+
FileldDataEvictions *int `json:"fielddata.evictions,string"`
75+
QueryCacheMemorySize *string `json:"query_cache.memory_size"`
76+
QueryCacheEvictions *int `json:"query_cache.evictions,string"`
77+
QueryCacheHitCount *int `json:"query_cache.hit_count,string"`
78+
QueryCacheMissCount *int `json:"query_cache.miss_count,string"`
79+
RequestCacheMemorySize *string `json:"request_cache.memory_size"`
80+
RequestCacheEvictions *int `json:"request_cache.evictions,string"`
81+
RequestCacheHitCount *int `json:"request_cache.hit_count,string"`
82+
RequestCacheMissCount *int `json:"request_cache.miss_count,string"`
83+
FlushTotal *int `json:"flush.total,string"`
84+
FlushTotalTime *string `json:"flush.total_time"`
85+
GetCurrent *int `json:"get.current,string"`
86+
GetTime *string `json:"get.time"`
87+
GetTotal *int `json:"get.total,string"`
88+
GetExistsTime *string `json:"get.exists_time"`
89+
GetExistsTotal *int `json:"get.exists_total,string"`
90+
GetMissingTime *string `json:"get.missing_time"`
91+
GetMissingTotal *int `json:"get.missing_total,string"`
92+
IndexingDeleteCurrent *int `json:"indexing.delete_current,string"`
93+
IndexingDeleteTime *string `json:"indexing.delete_time"`
94+
IndexingDeleteTotal *int `json:"indexing.delete_total,string"`
95+
IndexingIndexCurrent *int `json:"indexing.index_current,string"`
96+
IndexingIndexTime *string `json:"indexing.index_time"`
97+
IndexingIndexTotal *int `json:"indexing.index_total,string"`
98+
IndexingIndexFailed *int `json:"indexing.index_failed,string"`
99+
MergesCurrent *int `json:"merges.current,string"`
100+
MergesCurrentDoc *int `json:"merges.current_docs,string"`
101+
MergesCurrentSize *string `json:"merges.current_size"`
102+
MergesTotal *int `json:"merges.total,string"`
103+
MergesTotalDocs *int `json:"merges.total_docs,string"`
104+
MergesTotalSize *string `json:"merges.total_size"`
105+
MergesTotalTime *string `json:"merges.total_time"`
106+
// Merges warmer fields added in OpenSearch 3.4.0+
107+
MergesWarmerOngoingCount *int `json:"merges.warmer.ongoing_count,string"`
108+
MergesWarmerTotalInvocations *int `json:"merges.warmer.total_invocations,string"`
109+
MergesWarmerTotalTime *string `json:"merges.warmer.total_time"`
110+
MergesWarmerTotalFailureCount *int `json:"merges.warmer.total_failure_count,string"`
111+
MergesWarmerTotalBytesSent *string `json:"merges.warmer.total_bytes_sent"`
112+
MergesWarmerTotalBytesReceived *string `json:"merges.warmer.total_bytes_received"`
113+
MergesWarmerTotalSendTime *string `json:"merges.warmer.total_send_time"`
114+
MergesWarmerTotalReceiveTime *string `json:"merges.warmer.total_receive_time"`
106115
RefreshTotal *int `json:"refresh.total,string"`
107116
RefreshTime *string `json:"refresh.time"`
108117
RefreshExternalTotal *int `json:"refresh.external_total,string"`

opensearchapi/api_cat-shards.go

Lines changed: 52 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -47,49 +47,58 @@ type CatShardsResp struct {
4747

4848
// CatShardResp represents one index of the CatShardsResp
4949
type CatShardResp struct {
50-
Index string `json:"index"`
51-
Shard int `json:"shard,string"`
52-
Prirep string `json:"prirep"`
53-
State string `json:"state"`
54-
Docs *string `json:"docs"`
55-
Store *string `json:"store"`
56-
IP *string `json:"ip"`
57-
ID *string `json:"id"`
58-
Node *string `json:"node"`
59-
SyncID *string `json:"sync_id"`
60-
UnassignedReason *string `json:"unassigned.reason"`
61-
UnassignedAt *string `json:"unassigned.at"`
62-
UnassignedFor *string `json:"unassigned.for"`
63-
UnassignedDetails *string `json:"unassigned.details"`
64-
RecoverysourceType *string `json:"recoverysource.type"`
65-
CompletionSize *string `json:"completion.size"`
66-
FielddataMemorySize *string `json:"fielddata.memory_size"`
67-
FielddataEvictions *int `json:"fielddata.evictions,string"`
68-
QueryCacheMemorySize *string `json:"query_cache.memory_size"`
69-
QueryCacheEvictions *int `json:"query_cache.evictions,string"`
70-
FlushTotal *int `json:"flush.total,string"`
71-
FlushTotalTime *string `json:"flush.total_time"`
72-
GetCurrent *int `json:"get.current,string"`
73-
GetTime *string `json:"get.time"`
74-
GetTotal *int `json:"get.total,string"`
75-
GetExistsTime *string `json:"get.exists_time"`
76-
GetExistsTotal *int `json:"get.exists_total,string"`
77-
GetMissingTime *string `json:"get.missing_time"`
78-
GetMissingTotal *int `json:"get.missing_total,string"`
79-
IndexingDeleteCurrent *int `json:"indexing.delete_current,string"`
80-
IndexingDeleteTime *string `json:"indexing.delete_time"`
81-
IndexingDeleteTotal *string `json:"indexing.delete_total"`
82-
IndexingIndexCurrent *int `json:"indexing.index_current,string"`
83-
IndexingIndexTime *string `json:"indexing.index_time"`
84-
IndexingIndexTotal *int `json:"indexing.index_total,string"`
85-
IndexingIndexFailed *int `json:"indexing.index_failed,string"`
86-
MergesCurrent *int `json:"merges.current,string"`
87-
MergesCurrentDocs *int `json:"merges.current_docs,string"`
88-
MergesCurrentSize *string `json:"merges.current_size"`
89-
MergesTotal *int `json:"merges.total,string"`
90-
MergesTotalDocs *int `json:"merges.total_docs,string"`
91-
MergesTotalSize *string `json:"merges.total_size"`
92-
MergesTotalTime *string `json:"merges.total_time"`
50+
Index string `json:"index"`
51+
Shard int `json:"shard,string"`
52+
Prirep string `json:"prirep"`
53+
State string `json:"state"`
54+
Docs *string `json:"docs"`
55+
Store *string `json:"store"`
56+
IP *string `json:"ip"`
57+
ID *string `json:"id"`
58+
Node *string `json:"node"`
59+
SyncID *string `json:"sync_id"`
60+
UnassignedReason *string `json:"unassigned.reason"`
61+
UnassignedAt *string `json:"unassigned.at"`
62+
UnassignedFor *string `json:"unassigned.for"`
63+
UnassignedDetails *string `json:"unassigned.details"`
64+
RecoverysourceType *string `json:"recoverysource.type"`
65+
CompletionSize *string `json:"completion.size"`
66+
FielddataMemorySize *string `json:"fielddata.memory_size"`
67+
FielddataEvictions *int `json:"fielddata.evictions,string"`
68+
QueryCacheMemorySize *string `json:"query_cache.memory_size"`
69+
QueryCacheEvictions *int `json:"query_cache.evictions,string"`
70+
FlushTotal *int `json:"flush.total,string"`
71+
FlushTotalTime *string `json:"flush.total_time"`
72+
GetCurrent *int `json:"get.current,string"`
73+
GetTime *string `json:"get.time"`
74+
GetTotal *int `json:"get.total,string"`
75+
GetExistsTime *string `json:"get.exists_time"`
76+
GetExistsTotal *int `json:"get.exists_total,string"`
77+
GetMissingTime *string `json:"get.missing_time"`
78+
GetMissingTotal *int `json:"get.missing_total,string"`
79+
IndexingDeleteCurrent *int `json:"indexing.delete_current,string"`
80+
IndexingDeleteTime *string `json:"indexing.delete_time"`
81+
IndexingDeleteTotal *string `json:"indexing.delete_total"`
82+
IndexingIndexCurrent *int `json:"indexing.index_current,string"`
83+
IndexingIndexTime *string `json:"indexing.index_time"`
84+
IndexingIndexTotal *int `json:"indexing.index_total,string"`
85+
IndexingIndexFailed *int `json:"indexing.index_failed,string"`
86+
MergesCurrent *int `json:"merges.current,string"`
87+
MergesCurrentDocs *int `json:"merges.current_docs,string"`
88+
MergesCurrentSize *string `json:"merges.current_size"`
89+
MergesTotal *int `json:"merges.total,string"`
90+
MergesTotalDocs *int `json:"merges.total_docs,string"`
91+
MergesTotalSize *string `json:"merges.total_size"`
92+
MergesTotalTime *string `json:"merges.total_time"`
93+
// Merges warmer fields added in OpenSearch 3.4.0+
94+
MergesWarmerOngoingCount *int `json:"merges.warmer.ongoing_count,string"`
95+
MergesWarmerTotalInvocations *int `json:"merges.warmer.total_invocations,string"`
96+
MergesWarmerTotalTime *string `json:"merges.warmer.total_time"`
97+
MergesWarmerTotalFailureCount *int `json:"merges.warmer.total_failure_count,string"`
98+
MergesWarmerTotalBytesSent *string `json:"merges.warmer.total_bytes_sent"`
99+
MergesWarmerTotalBytesReceived *string `json:"merges.warmer.total_bytes_received"`
100+
MergesWarmerTotalSendTime *string `json:"merges.warmer.total_send_time"`
101+
MergesWarmerTotalReceiveTime *string `json:"merges.warmer.total_receive_time"`
93102
RefreshTotal *int `json:"refresh.total,string"`
94103
RefreshTime *string `json:"refresh.time"`
95104
RefreshExternalTotal *int `json:"refresh.external_total,string"`

opensearchapi/api_cat-thread_pool.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ type CatThreadPoolItemResp struct {
6868
Size *int `json:"size,string"`
6969
KeepAlive *string `json:"keep_alive"`
7070
TotalWaitTime string `json:"total_wait_time"`
71+
// Parallelism field added in OpenSearch 3.4.0+
72+
Parallelism *int `json:"parallelism,string"`
7173
}
7274

7375
// Inspect returns the Inspect type containing the raw *opensearch.Response

opensearchapi/api_indices-stats.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,17 @@ type IndicesStatsMerges struct {
152152
TotalThrottledTimeInMillis int `json:"total_throttled_time_in_millis"`
153153
TotalAutoThrottleInBytes int `json:"total_auto_throttle_in_bytes"`
154154
UnreferencedFileCleanupsPerformed int `json:"unreferenced_file_cleanups_performed"`
155+
// Warmer field added in OpenSearch 3.4.0+
156+
Warmer *struct {
157+
TotalInvocationsCount int `json:"total_invocations_count"`
158+
TotalTimeMillis int `json:"total_time_millis"`
159+
TotalFailureCount int `json:"total_failure_count"`
160+
TotalBytesSent int `json:"total_bytes_sent"`
161+
TotalBytesReceived int `json:"total_bytes_received"`
162+
TotalSendTimeMillis int `json:"total_send_time_millis"`
163+
TotalReceiveTimeMillis int `json:"total_receive_time_millis"`
164+
OngoingCount int `json:"ongoing_count"`
165+
} `json:"warmer,omitempty"`
155166
}
156167

157168
// IndicesStatsRefresh is a sub type of IndicesStatsInfo containing stats about index refresh

opensearchapi/api_nodes-stats.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,17 @@ type NodesStatsIndices struct {
198198
TotalThrottledTimeInMillis int `json:"total_throttled_time_in_millis"`
199199
TotalAutoThrottleInBytes int `json:"total_auto_throttle_in_bytes"`
200200
UnreferencedFileCleanupsPerformed int `json:"unreferenced_file_cleanups_performed"`
201+
// Warmer field added in OpenSearch 3.4.0+
202+
Warmer *struct {
203+
TotalInvocationsCount int `json:"total_invocations_count"`
204+
TotalTimeMillis int `json:"total_time_millis"`
205+
TotalFailureCount int `json:"total_failure_count"`
206+
TotalBytesSent int `json:"total_bytes_sent"`
207+
TotalBytesReceived int `json:"total_bytes_received"`
208+
TotalSendTimeMillis int `json:"total_send_time_millis"`
209+
TotalReceiveTimeMillis int `json:"total_receive_time_millis"`
210+
OngoingCount int `json:"ongoing_count"`
211+
} `json:"warmer,omitempty"`
201212
} `json:"merges"`
202213
Refresh struct {
203214
Total int `json:"total"`
@@ -311,6 +322,19 @@ type NodesStatsIndices struct {
311322
CurrentAsTarget int `json:"current_as_target"`
312323
ThrottleTimeInMillis int `json:"throttle_time_in_millis"`
313324
} `json:"recovery"`
325+
// StatusCounter field added in OpenSearch 3.4.0+
326+
StatusCounter *struct {
327+
DocStatus struct {
328+
Success int `json:"success"`
329+
UserError int `json:"user_error"`
330+
SystemFailure int `json:"system_failure"`
331+
} `json:"doc_status"`
332+
SearchResponseStatus struct {
333+
Success int `json:"success"`
334+
UserError int `json:"user_error"`
335+
SystemFailure int `json:"system_failure"`
336+
} `json:"search_response_status"`
337+
} `json:"status_counter,omitempty"`
314338
}
315339

316340
// NodesStatsOS is a sub type of NodesStats representing operating system information of the node

0 commit comments

Comments
 (0)