Skip to content

Commit ad22d8e

Browse files
author
Jason Yellick
committed
[FAB-2156] Move orderer viper utils to common
https://jira.hyperledger.org/browse/FAB-2156 Before moving the orderer genesis tooling to common, it requires some viper extensions which resided in the orderer, this CR moves them to common. Change-Id: I5c68cad8903819d490a0e908a7ac07a2f6d86fdc Signed-off-by: Jason Yellick <[email protected]>
1 parent 40cfff3 commit ad22d8e

File tree

4 files changed

+325
-291
lines changed

4 files changed

+325
-291
lines changed

common/viperutil/config_test.go

+312
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,312 @@
1+
/*
2+
Copyright IBM Corp. 2016 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package viperutil
18+
19+
import (
20+
"bytes"
21+
"fmt"
22+
"io/ioutil"
23+
"os"
24+
"reflect"
25+
"strings"
26+
"testing"
27+
28+
"github.com/hyperledger/fabric/orderer/mocks/util"
29+
"github.com/spf13/viper"
30+
)
31+
32+
const Prefix = "VIPERUTIL"
33+
34+
type testSlice struct {
35+
Inner struct {
36+
Slice []string
37+
}
38+
}
39+
40+
func TestEnvSlice(t *testing.T) {
41+
envVar := "VIPERUTIL_INNER_SLICE"
42+
envVal := "[a, b, c]"
43+
os.Setenv(envVar, envVal)
44+
defer os.Unsetenv(envVar)
45+
config := viper.New()
46+
config.SetEnvPrefix(Prefix)
47+
config.AutomaticEnv()
48+
replacer := strings.NewReplacer(".", "_")
49+
config.SetEnvKeyReplacer(replacer)
50+
config.SetConfigType("yaml")
51+
52+
data := "---\nInner:\n Slice: [d,e,f]"
53+
54+
err := config.ReadConfig(bytes.NewReader([]byte(data)))
55+
56+
if err != nil {
57+
t.Fatalf("Error reading %s plugin config: %s", Prefix, err)
58+
}
59+
60+
var uconf testSlice
61+
62+
err = EnhancedExactUnmarshal(config, &uconf)
63+
if err != nil {
64+
t.Fatalf("Failed to unmarshal with: %s", err)
65+
}
66+
67+
expected := []string{"a", "b", "c"}
68+
if !reflect.DeepEqual(uconf.Inner.Slice, expected) {
69+
t.Fatalf("Did not get back the right slice, expeced: %v got %v", expected, uconf.Inner.Slice)
70+
}
71+
}
72+
73+
type testByteSize struct {
74+
Inner struct {
75+
ByteSize uint32
76+
}
77+
}
78+
79+
func TestByteSize(t *testing.T) {
80+
config := viper.New()
81+
config.SetConfigType("yaml")
82+
83+
testCases := []struct {
84+
data string
85+
expected uint32
86+
}{
87+
{"", 0},
88+
{"42", 42},
89+
{"42k", 42 * 1024},
90+
{"42kb", 42 * 1024},
91+
{"42K", 42 * 1024},
92+
{"42KB", 42 * 1024},
93+
{"42 K", 42 * 1024},
94+
{"42 KB", 42 * 1024},
95+
{"42m", 42 * 1024 * 1024},
96+
{"42mb", 42 * 1024 * 1024},
97+
{"42M", 42 * 1024 * 1024},
98+
{"42MB", 42 * 1024 * 1024},
99+
{"42 M", 42 * 1024 * 1024},
100+
{"42 MB", 42 * 1024 * 1024},
101+
{"3g", 3 * 1024 * 1024 * 1024},
102+
{"3gb", 3 * 1024 * 1024 * 1024},
103+
{"3G", 3 * 1024 * 1024 * 1024},
104+
{"3GB", 3 * 1024 * 1024 * 1024},
105+
{"3 G", 3 * 1024 * 1024 * 1024},
106+
{"3 GB", 3 * 1024 * 1024 * 1024},
107+
}
108+
109+
for _, tc := range testCases {
110+
t.Run(tc.data, func(t *testing.T) {
111+
data := fmt.Sprintf("---\nInner:\n ByteSize: %s", tc.data)
112+
err := config.ReadConfig(bytes.NewReader([]byte(data)))
113+
if err != nil {
114+
t.Fatalf("Error reading config: %s", err)
115+
}
116+
var uconf testByteSize
117+
err = EnhancedExactUnmarshal(config, &uconf)
118+
if err != nil {
119+
t.Fatalf("Failed to unmarshal with: %s", err)
120+
}
121+
if uconf.Inner.ByteSize != tc.expected {
122+
t.Fatalf("Did not get back the right byte size, expeced: %v got %v", tc.expected, uconf.Inner.ByteSize)
123+
}
124+
})
125+
}
126+
}
127+
128+
func TestByteSizeOverflow(t *testing.T) {
129+
config := viper.New()
130+
config.SetConfigType("yaml")
131+
132+
data := "---\nInner:\n ByteSize: 4GB"
133+
err := config.ReadConfig(bytes.NewReader([]byte(data)))
134+
if err != nil {
135+
t.Fatalf("Error reading config: %s", err)
136+
}
137+
var uconf testByteSize
138+
err = EnhancedExactUnmarshal(config, &uconf)
139+
if err == nil {
140+
t.Fatalf("Should have failed to unmarshal")
141+
}
142+
}
143+
144+
type stringFromFileConfig struct {
145+
Inner struct {
146+
Single string
147+
Multiple []string
148+
}
149+
}
150+
151+
func TestStringNotFromFile(t *testing.T) {
152+
153+
expectedValue := "expected_value"
154+
yaml := fmt.Sprintf("---\nInner:\n Single: %s\n", expectedValue)
155+
156+
config := viper.New()
157+
config.SetConfigType("yaml")
158+
159+
if err := config.ReadConfig(bytes.NewReader([]byte(yaml))); err != nil {
160+
t.Fatalf("Error reading config: %s", err)
161+
}
162+
163+
var uconf stringFromFileConfig
164+
if err := EnhancedExactUnmarshal(config, &uconf); err != nil {
165+
t.Fatalf("Failed to unmarshall: %s", err)
166+
}
167+
168+
if uconf.Inner.Single != expectedValue {
169+
t.Fatalf(`Expected: "%s", Actual: "%s"`, expectedValue, uconf.Inner.Single)
170+
}
171+
172+
}
173+
174+
func TestStringFromFile(t *testing.T) {
175+
176+
expectedValue := "this is the text in the file"
177+
178+
// create temp file
179+
file, err := ioutil.TempFile(os.TempDir(), "test")
180+
if err != nil {
181+
t.Fatalf("Unable to create temp file.")
182+
}
183+
defer os.Remove(file.Name())
184+
185+
// write temp file
186+
if err = ioutil.WriteFile(file.Name(), []byte(expectedValue), 0777); err != nil {
187+
t.Fatalf("Unable to write to temp file.")
188+
}
189+
190+
yaml := fmt.Sprintf("---\nInner:\n Single:\n File: %s", file.Name())
191+
192+
config := viper.New()
193+
config.SetConfigType("yaml")
194+
195+
if err = config.ReadConfig(bytes.NewReader([]byte(yaml))); err != nil {
196+
t.Fatalf("Error reading config: %s", err)
197+
}
198+
var uconf stringFromFileConfig
199+
if err = EnhancedExactUnmarshal(config, &uconf); err != nil {
200+
t.Fatalf("Failed to unmarshall: %s", err)
201+
}
202+
203+
if uconf.Inner.Single != expectedValue {
204+
t.Fatalf(`Expected: "%s", Actual: "%s"`, expectedValue, uconf.Inner.Single)
205+
}
206+
}
207+
208+
func TestPEMBlocksFromFile(t *testing.T) {
209+
210+
// create temp file
211+
file, err := ioutil.TempFile(os.TempDir(), "test")
212+
if err != nil {
213+
t.Fatalf("Unable to create temp file.")
214+
}
215+
defer os.Remove(file.Name())
216+
217+
numberOfCertificates := 3
218+
var pems []byte
219+
for i := 0; i < numberOfCertificates; i++ {
220+
publicKeyCert, _, err := util.GenerateMockPublicPrivateKeyPairPEM(true)
221+
if err != nil {
222+
t.Fatalf("Enable to generate a signer certificate: %v", err)
223+
}
224+
pems = append(pems, publicKeyCert...)
225+
}
226+
227+
// write temp file
228+
if err := ioutil.WriteFile(file.Name(), pems, 0666); err != nil {
229+
t.Fatalf("Unable to write to temp file: %v", err)
230+
}
231+
232+
yaml := fmt.Sprintf("---\nInner:\n Multiple:\n File: %s", file.Name())
233+
234+
config := viper.New()
235+
config.SetConfigType("yaml")
236+
237+
if err := config.ReadConfig(bytes.NewReader([]byte(yaml))); err != nil {
238+
t.Fatalf("Error reading config: %v", err)
239+
}
240+
var uconf stringFromFileConfig
241+
if err := EnhancedExactUnmarshal(config, &uconf); err != nil {
242+
t.Fatalf("Failed to unmarshall: %v", err)
243+
}
244+
245+
if len(uconf.Inner.Multiple) != 3 {
246+
t.Fatalf(`Expected: "%v", Actual: "%v"`, numberOfCertificates, len(uconf.Inner.Multiple))
247+
}
248+
}
249+
250+
func TestStringFromFileNotSpecified(t *testing.T) {
251+
252+
yaml := fmt.Sprintf("---\nInner:\n Single:\n File:\n")
253+
254+
config := viper.New()
255+
config.SetConfigType("yaml")
256+
257+
if err := config.ReadConfig(bytes.NewReader([]byte(yaml))); err != nil {
258+
t.Fatalf("Error reading config: %s", err)
259+
}
260+
var uconf stringFromFileConfig
261+
if err := EnhancedExactUnmarshal(config, &uconf); err == nil {
262+
t.Fatalf("Should of failed to unmarshall.")
263+
}
264+
265+
}
266+
267+
func TestStringFromFileEnv(t *testing.T) {
268+
269+
expectedValue := "this is the text in the file"
270+
271+
// create temp file
272+
file, err := ioutil.TempFile(os.TempDir(), "test")
273+
if err != nil {
274+
t.Fatalf("Unable to create temp file.")
275+
}
276+
defer os.Remove(file.Name())
277+
278+
// write temp file
279+
if err = ioutil.WriteFile(file.Name(), []byte(expectedValue), 0777); err != nil {
280+
t.Fatalf("Unable to write to temp file.")
281+
}
282+
283+
envVar := "VIPERUTIL_INNER_SINGLE_FILE"
284+
envVal := file.Name()
285+
os.Setenv(envVar, envVal)
286+
defer os.Unsetenv(envVar)
287+
config := viper.New()
288+
config.SetEnvPrefix(Prefix)
289+
config.AutomaticEnv()
290+
replacer := strings.NewReplacer(".", "_")
291+
config.SetEnvKeyReplacer(replacer)
292+
config.SetConfigType("yaml")
293+
294+
data := "---\nInner:\n Single:\n File: wrong_file"
295+
296+
if err = config.ReadConfig(bytes.NewReader([]byte(data))); err != nil {
297+
t.Fatalf("Error reading %s plugin config: %s", Prefix, err)
298+
}
299+
300+
var uconf stringFromFileConfig
301+
302+
err = EnhancedExactUnmarshal(config, &uconf)
303+
if err != nil {
304+
t.Fatalf("Failed to unmarshal with: %s", err)
305+
}
306+
307+
t.Log(uconf.Inner.Single)
308+
309+
if !reflect.DeepEqual(uconf.Inner.Single, expectedValue) {
310+
t.Fatalf(`Expected: "%v", Actual: "%v"`, expectedValue, uconf.Inner.Single)
311+
}
312+
}

orderer/localconfig/config_util.go common/viperutil/config_util.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
1414
limitations under the License.
1515
*/
1616

17-
package config
17+
package viperutil
1818

1919
import (
2020
"fmt"
@@ -30,9 +30,12 @@ import (
3030
"encoding/pem"
3131

3232
"github.com/mitchellh/mapstructure"
33+
"github.com/op/go-logging"
3334
"github.com/spf13/viper"
3435
)
3536

37+
var logger = logging.MustGetLogger("viperutil")
38+
3639
func getKeysRecursively(base string, v *viper.Viper, nodeKeys map[string]interface{}) map[string]interface{} {
3740
result := make(map[string]interface{})
3841
for key := range nodeKeys {
@@ -228,10 +231,10 @@ func pemBlocksFromFileDecodeHook() mapstructure.DecodeHookFunc {
228231
}
229232
}
230233

231-
// ExactWithDateUnmarshal is intended to unmarshal a config file into a structure
234+
// EnhancedExactUnmarshal is intended to unmarshal a config file into a structure
232235
// producing error when extraneous variables are introduced and supporting
233236
// the time.Duration type
234-
func ExactWithDateUnmarshal(v *viper.Viper, output interface{}) error {
237+
func EnhancedExactUnmarshal(v *viper.Viper, output interface{}) error {
235238
baseKeys := v.AllSettings() // AllKeys doesn't actually return all keys, it only returns the base ones
236239
leafKeys := getKeysRecursively("", v, baseKeys)
237240

orderer/localconfig/config.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ import (
2323
"strings"
2424
"time"
2525

26+
"github.com/hyperledger/fabric/common/viperutil"
27+
2628
"github.com/Shopify/sarama"
2729
"github.com/op/go-logging"
2830
"github.com/spf13/viper"
@@ -358,7 +360,7 @@ func LoadGenesis() *GenesisTopLevel {
358360

359361
var uconf GenesisTopLevel
360362

361-
err = ExactWithDateUnmarshal(config, &uconf)
363+
err = viperutil.EnhancedExactUnmarshal(config, &uconf)
362364
if err != nil {
363365
panic(fmt.Errorf("Error unmarshaling into structure: %s", err))
364366
}
@@ -407,7 +409,7 @@ func Load() *TopLevel {
407409

408410
var uconf TopLevel
409411

410-
err = ExactWithDateUnmarshal(config, &uconf)
412+
err = viperutil.EnhancedExactUnmarshal(config, &uconf)
411413
if err != nil {
412414
panic(fmt.Errorf("Error unmarshaling into structure: %s", err))
413415
}

0 commit comments

Comments
 (0)