Repository: VictoriaMetrics/VictoriaMetrics
Pull request #5902 (2024-02-29 14:44:10)

Automatic update operator docs from VictoriaMetrics/operator@7e8f811


Patch:
diff --git a/app/vmselect/netstorage/netstorage.go b/app/vmselect/netstorage/netstorage.go
index 3d60b30a1..290fc506e 100644
--- a/app/vmselect/netstorage/netstorage.go
+++ b/app/vmselect/netstorage/netstorage.go
@@ -5,7 +5,6 @@ import (
 	"errors"
 	"flag"
 	"fmt"
-	"reflect"
 	"sort"
 	"sync"
 	"sync/atomic"
@@ -1312,9 +1311,11 @@ func canAppendToBlockRefPool(pool, a []blockRef) bool {
 		// a doesn't belong to pool
 		return false
 	}
-	shPool := (*reflect.SliceHeader)(unsafe.Pointer(&pool))
-	shA := (*reflect.SliceHeader)(unsafe.Pointer(&a))
-	return shPool.Data+uintptr(shPool.Len)*unsafe.Sizeof(blockRef{}) == shA.Data+uintptr(shA.Len)*unsafe.Sizeof(blockRef{})
+	return getBlockRefsEnd(pool) == getBlockRefsEnd(a)
+}
+
+func getBlockRefsEnd(a []blockRef) uintptr {
+	return uintptr(unsafe.Pointer(unsafe.SliceData(a))) + uintptr(len(a))*unsafe.Sizeof(blockRef{})
 }
 
 func setupTfss(qt *querytracer.Tracer, tr storage.TimeRange, tagFilterss [][]storage.TagFilter, maxMetrics int, deadline searchutils.Deadline) ([]*storage.TagFilters, error) {
diff --git a/app/vmselect/promql/timeseries.go b/app/vmselect/promql/timeseries.go
index 2aea3e3f5..5cb8cbdd4 100644
--- a/app/vmselect/promql/timeseries.go
+++ b/app/vmselect/promql/timeseries.go
@@ -2,7 +2,6 @@ package promql
 
 import (
 	"fmt"
-	"reflect"
 	"sort"
 	"strconv"
 	"sync"
@@ -308,60 +307,32 @@ func unmarshalBytesFast(src []byte) ([]byte, []byte, error) {
 	return src[n:], src[:n], nil
 }
 
-func float64ToByteSlice(a []float64) (b []byte) {
-	if len(a) == 0 {
-		return nil
-	}
-	sh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
-	sh.Data = uintptr(unsafe.Pointer(&a[0]))
-	sh.Len = len(a) * int(unsafe.Sizeof(a[0]))
-	sh.Cap = sh.Len
-	return
+func float64ToByteSlice(a []float64) []byte {
+	return unsafe.Slice((*byte)(unsafe.Pointer(unsafe.SliceData(a))), len(a)*8)
 }
 
-func int64ToByteSlice(a []int64) (b []byte) {
-	if len(a) == 0 {
-		return nil
-	}
-	sh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
-	sh.Data = uintptr(unsafe.Pointer(&a[0]))
-	sh.Len = len(a) * int(unsafe.Sizeof(a[0]))
-	sh.Cap = sh.Len
-	return
+func int64ToByteSlice(a []int64) []byte {
+	return unsafe.Slice((*byte)(unsafe.Pointer(unsafe.SliceData(a))), len(a)*8)
 }
 
-func byteSliceToInt64(b []byte) (a []int64) {
-	if len(b) == 0 {
-		return nil
-	}
-	sh := (*reflect.SliceHeader)(unsafe.Pointer(&a))
-	sh.Data = uintptr(unsafe.Pointer(&b[0]))
-	sh.Len = len(b) / int(unsafe.Sizeof(a[0]))
-	sh.Cap = sh.Len
+func byteSliceToInt64(b []byte) []int64 {
 	// Make sure that the returned slice is properly aligned to 8 bytes.
 	// This prevents from SIGBUS error on arm architectures, which deny unaligned access.
 	// See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/3927
-	if sh.Data%8 != 0 {
+	if uintptr(unsafe.Pointer(unsafe.SliceData(b)))%8 != 0 {
 		logger.Panicf("BUG: the input byte slice b must be aligned to 8 bytes")
 	}
-	return
+	return unsafe.Slice((*int64)(unsafe.Pointer(unsafe.SliceData(b))), len(b)/8)
 }
 
-func byteSliceToFloat64(b []byte) (a []float64) {
-	if len(b) == 0 {
-		return nil
-	}
-	sh := (*reflect.SliceHeader)(unsafe.Pointer(&a))
-	sh.Data = uintptr(unsafe.Pointer(&b[0]))
-	sh.Len = len(b) / int(unsafe.Sizeof(a[0]))
-	sh.Cap = sh.Len
+func byteSliceToFloat64(b []byte) []float64 {
 	// Make sure that the returned slice is properly aligned to 8 bytes.
 	// This prevents from SIGBUS error on arm architectures, which deny unaligned access.
 	// See https://github.com/VictoriaMetrics/VictoriaMetrics/pull/3927
-	if sh.Data%8 != 0 {
+	if uintptr(unsafe.Pointer(unsafe.SliceData(b)))%8 != 0 {
 		logger.Panicf("BUG: the input byte slice b must be aligned to 8 bytes")
 	}
-	return
+	return unsafe.Slice((*float64)(unsafe.Pointer(unsafe.SliceData(b))), len(b)/8)
 }
 
 func stringMetricName(mn *storage.MetricName) string {
diff --git a/docs/operator/CHANGELOG.md b/docs/operator/CHANGELOG.md
index 545155870..015c8e522 100644
--- a/docs/operator/CHANGELOG.md
+++ b/docs/operator/CHANGELOG.md
@@ -16,7 +16,7 @@ aliases:
 
 ## Next release
 
-- TODO
+- [vmauth](./api.html#vmauth): adds new field `spec.configSecret`, which allows to use vmauth with external configuration stored at secret under `config.yaml` key. Configuration changes can be tracked with extraArgs: `configCheckInterval: 10s` or manually defined config-reloader container.
 
 <a name="v0.41.2"></a>
 ## [v0.41.2](https://github.com/VictoriaMetrics/operator/releases/tag/v0.41.2) - 21 Feb 2024
diff --git a/docs/operator/api.md b/docs/operator/api.md
index c360e4f83..445bed5bb 100644
--- a/docs/operator/api.md
+++ b/docs/operator/api.md
@@ -2299,6 +2299,7 @@ VMAuthSpec defines the desired state of VMAuth
 | unauthorizedAccessConfig | UnauthorizedAccessConfig configures access for un authorized users | [][VMAuthUnauthorizedPath](#vmauthunauthorizedpath) | false |
 | useStrictSecurity | UseStrictSecurity enables strict security mode for component it restricts disk writes access uses non-root user out of the box drops not needed security permissions | *bool | false |
 | license | License allows to configure license key to be used for enterprise features. Using license key is supported starting from VictoriaMetrics v1.94.0. See: https://docs.victoriametrics.com/enterprise.html | *[License](#license) | false |
+| configSecret | ConfigSecret is the name of a Kubernetes Secret in the same namespace as the VMAuth object, which contains auth configuration for vmauth, configuration must be inside secret key: config.yaml. It must be created and managed manually. If it&#39;s defined, configuration for vmauth becomes unmanaged and operator&#39;ll not create any related secrets/config-reloaders | string | false |
 
 [Back to TOC](#table-of-contents)
 
diff --git a/docs/operator/vars.md b/docs/operator/vars.md
index 690105c9d..66d6267ea 100644
--- a/docs/operator/vars.md
+++ b/docs/operator/vars.md
@@ -10,7 +10,7 @@ menu:
 
 <!-- this doc autogenerated - don't edit it manually -->
 # Auto Generated vars for package config 
- updated at Thu Feb 29 01:43:08 UTC 2024 
+ updated at Thu Feb 29 14:44:07 UTC 2024 
 
 
 | varible name | variable default value | variable required | variable description |
diff --git a/lib/bytesutil/bytesutil.go b/lib/bytesutil/bytesutil.go
index daa01232d..969e63e83 100644
--- a/lib/bytesutil/bytesutil.go
+++ b/lib/bytesutil/bytesutil.go
@@ -2,7 +2,6 @@ package bytesutil
 
 import (
 	"math/bits"
-	"reflect"
 	"unsafe"
 )
 
@@ -65,17 +64,12 @@ func roundToNearestPow2(n int) int {
 //
 // The returned string is valid only until b is reachable and unmodified.
 func ToUnsafeString(b []byte) string {
-	return *(*string)(unsafe.Pointer(&b))
+	return unsafe.String(unsafe.SliceData(b), len(b))
 }
 
 // ToUnsafeBytes converts s to a byte slice without memory allocations.
 //
 // The returned byte slice is valid only until s is reachable and unmodified.
-func ToUnsafeBytes(s string) (b []byte) {
-	sh := (*reflect.StringHeader)(unsafe.Pointer(&s))
-	slh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
-	slh.Data = sh.Data
-	slh.Len = sh.Len
-	slh.Cap = sh.Len
-	return b
+func ToUnsafeBytes(s string) []byte {
+	return unsafe.Slice(unsafe.StringData(s), len(s))
 }
diff --git a/lib/fastnum/fastnum.go b/lib/fastnum/fastnum.go
index 524098bb2..34966947b 100644
--- a/lib/fastnum/fastnum.go
+++ b/lib/fastnum/fastnum.go
@@ -2,7 +2,6 @@ package fastnum
 
 import (
 	"bytes"
-	"reflect"
 	"unsafe"
 )
 
@@ -124,20 +123,12 @@ func isFloat64Data(a, data []float64) bool {
 	return true
 }
 
-func int64ToByteSlice(a []int64) (b []byte) {
-	sh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
-	sh.Data = uintptr(unsafe.Pointer(&a[0]))
-	sh.Len = len(a) * int(unsafe.Sizeof(a[0]))
-	sh.Cap = sh.Len
-	return
+func int64ToByteSlice(a []int64) []byte {
+	return unsafe.Slice((*byte)(unsafe.Pointer(unsafe.SliceData(a))), len(a)*8)
 }
 
-func float64ToByteSlice(a []float64) (b []byte) {
-	sh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
-	sh.Data = uintptr(unsafe.Pointer(&a[0]))
-	sh.Len = len(a) * int(unsafe.Sizeof(a[0]))
-	sh.Cap = sh.Len
-	return
+func float64ToByteSlice(a []float64) []byte {
+	return unsafe.Slice((*byte)(unsafe.Pointer(unsafe.SliceData(a))), len(a)*8)
 }
 
 var (
diff --git a/lib/fs/fs_windows.go b/lib/fs/fs_windows.go
index af2076afd..83b5483a1 100644
--- a/lib/fs/fs_windows.go
+++ b/lib/fs/fs_windows.go
@@ -89,11 +89,7 @@ func mmap(fd int, length int) ([]byte, error) {
 		windows.CloseHandle(h)
 		return nil, os.NewSyscallError("MapViewOfFile", errno)
 	}
-	data := make([]byte, 0)
-	hdr := (*reflect.SliceHeader)(unsafe.Pointer(&data))
-	hdr.Data = addr
-	hdr.Len = length
-	hdr.Cap = hdr.Len
+	data := unsafe.Slice(addr, length)
 
 	mmapByAddrLock.Lock()
 	mmapByAddr[addr] = h
@@ -105,8 +101,7 @@ func mmap(fd int, length int) ([]byte, error) {
 func mUnmap(data []byte) error {
 	// flush is not needed, since we perform only reading operation.
 	// In case of write, additional call FlushViewOfFile must be performed.
-	header := (*reflect.SliceHeader)(unsafe.Pointer(&data))
-	addr := header.Data
+	addr := uintptr(unsafe.Pointer(unsafe.SliceData(data)))
 
 	mmapByAddrLock.Lock()
 	h, ok := mmapByAddr[addr]
diff --git a/lib/mergeset/encoding.go b/lib/mergeset/encoding.go
index 3e2feedb8..93429744d 100644
--- a/lib/mergeset/encoding.go
+++ b/lib/mergeset/encoding.go
@@ -4,7 +4,6 @@ import (
 	"bytes"
 	"fmt"
 	"os"
-	"reflect"
 	"sort"
 	"strings"
 	"sync"
@@ -29,21 +28,15 @@ type Item struct {
 // The returned bytes representation belongs to data.
 func (it Item) Bytes(data []byte) []byte {
 	n := int(it.End - it.Start)
-	sh := (*reflect.SliceHeader)(unsafe.Pointer(&data))
-	sh.Cap = n
-	sh.Len = n
-	sh.Data += uintptr(it.Start)
-	return data
+	return unsafe.Slice((*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(unsafe.SliceData(data)))+uintptr(it.Start))), n)
 }
 
 // String returns string representation of it obtained from data.
 //
 // The returned string representation belongs to data.
 func (it Item) String(data []byte) string {
-	sh := (*reflect.SliceHeader)(unsafe.Pointer(&data))
-	sh.Data += uintptr(it.Start)
-	sh.Len = int(it.End - it.Start)
-	return *(*string)(unsafe.Pointer(sh))
+	n := int(it.End - it.Start)
+	return unsafe.String((*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(unsafe.SliceData(data)))+uintptr(it.Start))), n)
 }
 
 func (ib *inmemoryBlock) Len() int {
diff --git a/lib/storage/index_db.go b/lib/storage/index_db.go
index c81983d9f..a273e1b96 100644
--- a/lib/storage/index_db.go
+++ b/lib/storage/index_db.go
@@ -7,7 +7,6 @@ import (
 	"fmt"
 	"io"
 	"path/filepath"
-	"reflect"
 	"sort"
 	"strconv"
 	"sync"
@@ -402,14 +401,7 @@ func marshalMetricIDs(dst []byte, metricIDs []uint64) []byte {
 	// Compress metricIDs, so they occupy less space in the cache.
 	//
 	// The srcBuf is a []byte cast of metricIDs.
-	var srcBuf []byte
-	if len(metricIDs) > 0 {
-		sh := (*reflect.SliceHeader)(unsafe.Pointer(&srcBuf))
-		sh.Data = uintptr(unsafe.Pointer(&metricIDs[0]))
-		sh.Cap = 8 * len(metricIDs)
-		sh.Len = 8 * len(metricIDs)
-	}
-
+	srcBuf := unsafe.Slice((*byte)(unsafe.Pointer(unsafe.SliceData(metricIDs))), 8*len(metricIDs))
 	dst = encoding.CompressZSTDLevel(dst, srcBuf, 1)
 	return dst
 }
@@ -418,13 +410,8 @@ func mustUnmarshalMetricIDs(dst []uint64, src []byte) []uint64 {
 	// Decompress src into dstBuf.
 	//
 	// dstBuf is a []byte cast of dst.
-	var dstBuf []byte
-	if len(dst) > 0 {
-		sh := (*reflect.SliceHeader)(unsafe.Pointer(&dstBuf))
-		sh.Data = uintptr(unsafe.Pointer(&dst[0]))
-		sh.Cap = 8 * cap(dst)
-		sh.Len = 8 * len(dst)
-	}
+	dstBuf := unsafe.Slice((*byte)(unsafe.Pointer(unsafe.SliceData(dst))), 8*cap(dst))
+	dstBuf = dstBuf[:8*len(dst)]
 	dstBufLen := len(dstBuf)
 	var err error
 	dstBuf, err = encoding.DecompressZSTD(dstBuf, src)
@@ -440,10 +427,8 @@ func mustUnmarshalMetricIDs(dst []uint64, src []byte) []uint64 {
 	}
 
 	// Convert dstBuf back to dst
-	sh := (*reflect.SliceHeader)(unsafe.Pointer(&dst))
-	sh.Data = uintptr(unsafe.Pointer(&dstBuf[0]))
-	sh.Cap = cap(dstBuf) / 8
-	sh.Len = len(dstBuf) / 8
+	dst = unsafe.Slice((*uint64)(unsafe.Pointer(unsafe.SliceData(dstBuf))), cap(dstBuf)/8)
+	dst = dst[:len(dstBuf)/8]
 
 	return dst
 }


Test patch:
diff --git a/app/vmselect/promql/timeseries_test.go b/app/vmselect/promql/timeseries_test.go
index b0d14edb6..7186318b8 100644
--- a/app/vmselect/promql/timeseries_test.go
+++ b/app/vmselect/promql/timeseries_test.go
@@ -52,7 +52,9 @@ func TestMarshalTimeseriesFast(t *testing.T) {
 		MetricName: storage.MetricName{
 			MetricGroup: []byte{},
 		},
-		denyReuse: true,
+		Values:     []float64{},
+		Timestamps: []int64{},
+		denyReuse:  true,
 	}})
 	f([]*timeseries{{
 		MetricName: storage.MetricName{
diff --git a/lib/bytesutil/bytesutil_timing_test.go b/lib/bytesutil/bytesutil_timing_test.go
index 6ba8b0d90..03a15541d 100644
--- a/lib/bytesutil/bytesutil_timing_test.go
+++ b/lib/bytesutil/bytesutil_timing_test.go
@@ -6,14 +6,13 @@ import (
 )
 
 func BenchmarkToUnsafeString(b *testing.B) {
-	buf := []byte("foobarbaz abcde fafdsfds")
 	b.ReportAllocs()
-	b.SetBytes(int64(len(buf)))
+	b.SetBytes(int64(len(benchBytes)))
 	b.RunParallel(func(pb *testing.PB) {
 		n := 0
 		for pb.Next() {
-			for i := range buf {
-				s := ToUnsafeString(buf[:i])
+			for _, b := range benchBytes {
+				s := ToUnsafeString(b)
 				n += len(s)
 			}
 		}
@@ -22,19 +21,34 @@ func BenchmarkToUnsafeString(b *testing.B) {
 }
 
 func BenchmarkToUnsafeBytes(b *testing.B) {
-	s := "foobarbaz abcde fafdsfds"
 	b.ReportAllocs()
-	b.SetBytes(int64(len(s)))
+	b.SetBytes(int64(len(benchStrings)))
 	b.RunParallel(func(pb *testing.PB) {
 		n := 0
 		for pb.Next() {
-			for i := range s {
-				s := ToUnsafeBytes(s[:i])
-				n += len(s)
+			for _, s := range benchStrings {
+				b := ToUnsafeBytes(s)
+				n += len(b)
 			}
 		}
 		Sink.Add(uint64(n))
 	})
 }
 
+var benchBytes = func() [][]byte {
+	a := make([][]byte, 1000)
+	for i := range a {
+		a[i] = make([]byte, i)
+	}
+	return a
+}()
+
+var benchStrings = func() []string {
+	a := make([]string, 1000)
+	for i := range a {
+		a[i] = string(make([]byte, i))
+	}
+	return a
+}()
+
 var Sink atomic.Uint64
diff --git a/lib/protoparser/csvimport/column_descriptor_test.go b/lib/protoparser/csvimport/column_descriptor_test.go
index 11fad99c8..85a093b31 100644
--- a/lib/protoparser/csvimport/column_descriptor_test.go
+++ b/lib/protoparser/csvimport/column_descriptor_test.go
@@ -3,7 +3,6 @@ package csvimport
 import (
 	"bytes"
 	"fmt"
-	"reflect"
 	"testing"
 	"time"
 	"unsafe"
@@ -201,17 +200,8 @@ func equalColumnDescriptors(a, b []ColumnDescriptor) bool {
 }
 
 func equalColumnDescriptor(x, y ColumnDescriptor) bool {
-	var b1, b2 []byte
-
-	sh1 := (*reflect.SliceHeader)(unsafe.Pointer(&b1))
-	sh1.Data = uintptr(unsafe.Pointer(&x.ParseTimestamp))
-	sh1.Len = int(unsafe.Sizeof(x.ParseTimestamp))
-	sh1.Cap = int(unsafe.Sizeof(x.ParseTimestamp))
-
-	sh2 := (*reflect.SliceHeader)(unsafe.Pointer(&b2))
-	sh2.Data = uintptr(unsafe.Pointer(&y.ParseTimestamp))
-	sh2.Len = int(unsafe.Sizeof(y.ParseTimestamp))
-	sh2.Cap = int(unsafe.Sizeof(y.ParseTimestamp))
+	b1 := unsafe.Slice((*byte)(unsafe.Pointer(&x.ParseTimestamp)), int(unsafe.Sizeof(x.ParseTimestamp)))
+	b2 := unsafe.Slice((*byte)(unsafe.Pointer(&y.ParseTimestamp)), int(unsafe.Sizeof(y.ParseTimestamp)))
 
 	if !bytes.Equal(b1, b2) {
 		return false