Skip to content

Commit 972ef53

Browse files
author
Luis Sanchez
committed
[FAB-1653] Enable human-readable byte sizes in config
Byte sizes can be specified with the following case insensitive suffixes: - 'k', 'kb', 'm', 'mb', 'g', 'gb' Change-Id: I36c3fd424ed52794562a6b50e7a3d400f053c52a Signed-off-by: Luis Sanchez <[email protected]>
1 parent 4f90cd9 commit 972ef53

File tree

3 files changed

+116
-3
lines changed

3 files changed

+116
-3
lines changed

orderer/localconfig/config_test.go

+71
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,77 @@ func TestEnvSlice(t *testing.T) {
9393
}
9494
}
9595

96+
type testByteSize struct {
97+
Inner struct {
98+
ByteSize uint32
99+
}
100+
}
101+
102+
func TestByteSize(t *testing.T) {
103+
config := viper.New()
104+
config.SetConfigType("yaml")
105+
106+
testCases := []struct {
107+
data string
108+
expected uint32
109+
}{
110+
{"", 0},
111+
{"42", 42},
112+
{"42k", 42 * 1024},
113+
{"42kb", 42 * 1024},
114+
{"42K", 42 * 1024},
115+
{"42KB", 42 * 1024},
116+
{"42 K", 42 * 1024},
117+
{"42 KB", 42 * 1024},
118+
{"42m", 42 * 1024 * 1024},
119+
{"42mb", 42 * 1024 * 1024},
120+
{"42M", 42 * 1024 * 1024},
121+
{"42MB", 42 * 1024 * 1024},
122+
{"42 M", 42 * 1024 * 1024},
123+
{"42 MB", 42 * 1024 * 1024},
124+
{"3g", 3 * 1024 * 1024 * 1024},
125+
{"3gb", 3 * 1024 * 1024 * 1024},
126+
{"3G", 3 * 1024 * 1024 * 1024},
127+
{"3GB", 3 * 1024 * 1024 * 1024},
128+
{"3 G", 3 * 1024 * 1024 * 1024},
129+
{"3 GB", 3 * 1024 * 1024 * 1024},
130+
}
131+
132+
for _, tc := range testCases {
133+
t.Run(tc.data, func(t *testing.T) {
134+
data := fmt.Sprintf("---\nInner:\n ByteSize: %s", tc.data)
135+
err := config.ReadConfig(bytes.NewReader([]byte(data)))
136+
if err != nil {
137+
t.Fatalf("Error reading config: %s", err)
138+
}
139+
var uconf testByteSize
140+
err = ExactWithDateUnmarshal(config, &uconf)
141+
if err != nil {
142+
t.Fatalf("Failed to unmarshal with: %s", err)
143+
}
144+
if uconf.Inner.ByteSize != tc.expected {
145+
t.Fatalf("Did not get back the right byte size, expeced: %v got %v", tc.expected, uconf.Inner.ByteSize)
146+
}
147+
})
148+
}
149+
}
150+
151+
func TestByteSizeOverflow(t *testing.T) {
152+
config := viper.New()
153+
config.SetConfigType("yaml")
154+
155+
data := "---\nInner:\n ByteSize: 4GB"
156+
err := config.ReadConfig(bytes.NewReader([]byte(data)))
157+
if err != nil {
158+
t.Fatalf("Error reading config: %s", err)
159+
}
160+
var uconf testByteSize
161+
err = ExactWithDateUnmarshal(config, &uconf)
162+
if err == nil {
163+
t.Fatalf("Should have failed to unmarshal")
164+
}
165+
}
166+
96167
// TestEnvInnerVar verifies that with the Unmarshal function that
97168
// the environmental overrides still work on internal vars. This was
98169
// a bug in the original viper implementation that is worked around in

orderer/localconfig/config_util.go

+43-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,11 @@ limitations under the License.
1717
package config
1818

1919
import (
20+
"fmt"
21+
"math"
2022
"reflect"
23+
"regexp"
24+
"strconv"
2125
"strings"
2226
"time"
2327

@@ -83,6 +87,41 @@ func customDecodeHook() mapstructure.DecodeHookFunc {
8387
}
8488
}
8589

90+
func byteSizeDecodeHook() mapstructure.DecodeHookFunc {
91+
return func(f reflect.Kind, t reflect.Kind, data interface{}) (interface{}, error) {
92+
if f != reflect.String || t != reflect.Uint32 {
93+
return data, nil
94+
}
95+
raw := data.(string)
96+
if raw == "" {
97+
return data, nil
98+
}
99+
var re = regexp.MustCompile(`^(?P<size>[0-9]+)\s*(?i)(?P<unit>(k|m|g))b?$`)
100+
if re.MatchString(raw) {
101+
size, err := strconv.ParseUint(re.ReplaceAllString(raw, "${size}"), 0, 64)
102+
if err != nil {
103+
return data, nil
104+
}
105+
unit := re.ReplaceAllString(raw, "${unit}")
106+
switch strings.ToLower(unit) {
107+
case "g":
108+
size = size << 10
109+
fallthrough
110+
case "m":
111+
size = size << 10
112+
fallthrough
113+
case "k":
114+
size = size << 10
115+
}
116+
if size > math.MaxUint32 {
117+
return size, fmt.Errorf("value '%s' overflows uint32", raw)
118+
}
119+
return size, nil
120+
}
121+
return data, nil
122+
}
123+
}
124+
86125
// ExactWithDateUnmarshal is intended to unmarshal a config file into a structure
87126
// producing error when extraneous variables are introduced and supporting
88127
// the time.Duration type
@@ -96,7 +135,10 @@ func ExactWithDateUnmarshal(v *viper.Viper, output interface{}) error {
96135
Metadata: nil,
97136
Result: output,
98137
WeaklyTypedInput: true,
99-
DecodeHook: customDecodeHook(),
138+
DecodeHook: mapstructure.ComposeDecodeHookFunc(
139+
customDecodeHook(),
140+
byteSizeDecodeHook(),
141+
),
100142
}
101143

102144
decoder, err := mapstructure.NewDecoder(config)

orderer/orderer.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,9 @@ Genesis:
124124

125125
# Absolute Max Bytes: The absolute maximum number of bytes allowed for
126126
# the serialized messages in a batch.
127-
AbsoluteMaxBytes: 100000000
127+
AbsoluteMaxBytes: 99 MB
128128

129129
# Preferred Max Bytes: The preferred maximum number of bytes allowed for
130130
# the serialized messages in a batch. A message larger than the preferred
131131
# max bytes will result in a batch larger than preferred max bytes.
132-
PreferredMaxBytes: 524288
132+
PreferredMaxBytes: 512 KB

0 commit comments

Comments
 (0)