Skip to content

Commit 86f65d3

Browse files
author
Jason Yellick
committed
[FAB-2577] Add JSON rendering of configResult
https://jira.hyperledger.org/browse/FAB-2577 FAB-2574 split the config result from the config manager to allow other pieces fo the system to utilize it. This CR adds the ability for the config result to render the config result as JSON to be used in a later changeset for inspecting the configuration. Change-Id: Ieeccaf8486706f0a47ea09196eca12caae007a2b Signed-off-by: Jason Yellick <[email protected]>
1 parent 093394b commit 86f65d3

File tree

2 files changed

+152
-0
lines changed

2 files changed

+152
-0
lines changed

common/configtx/config.go

+73
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@ limitations under the License.
1717
package configtx
1818

1919
import (
20+
"bytes"
2021
"fmt"
2122

2223
"github.com/hyperledger/fabric/common/config"
2324
"github.com/hyperledger/fabric/common/configtx/api"
2425
"github.com/hyperledger/fabric/common/policies"
2526
cb "github.com/hyperledger/fabric/protos/common"
2627

28+
"github.com/golang/protobuf/jsonpb"
2729
"github.com/golang/protobuf/proto"
2830
)
2931

@@ -37,6 +39,77 @@ type configResult struct {
3739
deserializedValues map[string]proto.Message
3840
}
3941

42+
func (cr *configResult) JSON() string {
43+
var buffer bytes.Buffer
44+
buffer.WriteString("{")
45+
cr.bufferJSON(&buffer)
46+
buffer.WriteString("}")
47+
return buffer.String()
48+
49+
}
50+
51+
// bufferJSON takes a buffer and writes a JSON representation of the configResult into the buffer
52+
// Note that we use some mildly ad-hoc JSON encoding because the proto documentation explicitly
53+
// mentions that the encoding/json package does not correctly marshal proto objects, and we
54+
// do not have a proto object (nor can one be defined) which presents the mixed-map style of
55+
// keys mapping to different types of the config
56+
func (cr *configResult) bufferJSON(buffer *bytes.Buffer) {
57+
jpb := &jsonpb.Marshaler{
58+
EmitDefaults: true,
59+
Indent: " ",
60+
}
61+
62+
// "GroupName": {
63+
buffer.WriteString("\"")
64+
buffer.WriteString(cr.groupName)
65+
buffer.WriteString("\": {")
66+
67+
// "Values": {
68+
buffer.WriteString("\"Values\": {")
69+
count := 0
70+
for key, value := range cr.group.Values {
71+
// "Key": {
72+
buffer.WriteString("\"")
73+
buffer.WriteString(key)
74+
buffer.WriteString("\": {")
75+
// "Version": "X",
76+
buffer.WriteString("\"Version\":\"")
77+
buffer.WriteString(fmt.Sprintf("%d", value.Version))
78+
buffer.WriteString("\",")
79+
// "ModPolicy": "foo",
80+
buffer.WriteString("\"ModPolicy\":\"")
81+
buffer.WriteString(value.ModPolicy)
82+
buffer.WriteString("\",")
83+
// "Value": protoAsJSON
84+
buffer.WriteString("\"Value\":")
85+
jpb.Marshal(buffer, cr.deserializedValues[key])
86+
// },
87+
buffer.WriteString("}")
88+
count++
89+
if count < len(cr.group.Values) {
90+
buffer.WriteString(",")
91+
}
92+
}
93+
// },
94+
buffer.WriteString("},")
95+
96+
// "Groups": {
97+
count = 0
98+
buffer.WriteString("\"Groups\": {")
99+
for _, subResult := range cr.subResults {
100+
subResult.bufferJSON(buffer)
101+
count++
102+
if count < len(cr.subResults) {
103+
buffer.WriteString(",")
104+
}
105+
}
106+
// }
107+
buffer.WriteString("}")
108+
109+
// }
110+
buffer.WriteString("}")
111+
}
112+
40113
func (cr *configResult) preCommit() error {
41114
for _, subResult := range cr.subResults {
42115
err := subResult.preCommit()

common/configtx/config_test.go

+79
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
Copyright IBM Corp. 2017 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 configtx
18+
19+
import (
20+
"bytes"
21+
"encoding/json"
22+
"strings"
23+
"testing"
24+
25+
cb "github.com/hyperledger/fabric/protos/common"
26+
ab "github.com/hyperledger/fabric/protos/orderer"
27+
28+
"github.com/golang/protobuf/proto"
29+
"github.com/stretchr/testify/assert"
30+
)
31+
32+
func TestJSON(t *testing.T) {
33+
cr := &configResult{
34+
groupName: "rootGroup",
35+
group: &cb.ConfigGroup{
36+
Values: map[string]*cb.ConfigValue{
37+
"outer": &cb.ConfigValue{Version: 1, ModPolicy: "mod1"},
38+
},
39+
},
40+
subResults: []*configResult{
41+
&configResult{
42+
groupName: "innerGroup1",
43+
group: &cb.ConfigGroup{
44+
Values: map[string]*cb.ConfigValue{
45+
"inner1": &cb.ConfigValue{ModPolicy: "mod3"},
46+
},
47+
},
48+
deserializedValues: map[string]proto.Message{
49+
"inner1": &ab.ConsensusType{Type: "inner1"},
50+
},
51+
},
52+
&configResult{
53+
groupName: "innerGroup2",
54+
group: &cb.ConfigGroup{
55+
Values: map[string]*cb.ConfigValue{
56+
"inner2": &cb.ConfigValue{ModPolicy: "mod3"},
57+
},
58+
},
59+
deserializedValues: map[string]proto.Message{
60+
"inner2": &ab.ConsensusType{Type: "inner2"},
61+
},
62+
},
63+
},
64+
deserializedValues: map[string]proto.Message{
65+
"outer": &ab.ConsensusType{Type: "outer"},
66+
},
67+
}
68+
69+
buffer := &bytes.Buffer{}
70+
assert.NoError(t, json.Indent(buffer, []byte(cr.JSON()), "", ""), "JSON should parse nicely")
71+
72+
expected := "{\"rootGroup\":{\"Values\":{\"outer\":{\"Version\":\"1\",\"ModPolicy\":\"mod1\",\"Value\":{\"type\":\"outer\"}}},\"Groups\":{\"innerGroup1\":{\"Values\":{\"inner1\":{\"Version\":\"0\",\"ModPolicy\":\"mod3\",\"Value\":{\"type\":\"inner1\"}}},\"Groups\":{}},\"innerGroup2\":{\"Values\":{\"inner2\":{\"Version\":\"0\",\"ModPolicy\":\"mod3\",\"Value\":{\"type\":\"inner2\"}}},\"Groups\":{}}}}}"
73+
74+
// Remove all newlines and spaces from the JSON
75+
compactedJSON := strings.Replace(strings.Replace(buffer.String(), "\n", "", -1), " ", "", -1)
76+
77+
assert.Equal(t, expected, compactedJSON)
78+
79+
}

0 commit comments

Comments
 (0)