github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/common/configtx/configmap.go (about) 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 "fmt" 21 "strings" 22 23 cb "github.com/hyperledger/fabric/protos/common" 24 ) 25 26 const ( 27 RootGroupKey = "Channel" 28 29 GroupPrefix = "[Groups] " 30 ValuePrefix = "[Values] " 31 PolicyPrefix = "[Policy] " // The plurarility doesn't match, but, it makes the logs much easier being the same lenght as "Groups" and "Values" 32 33 PathSeparator = "/" 34 ) 35 36 // MapConfig is intended to be called outside this file 37 // it takes a ConfigGroup and generates a map of fqPath to comparables (or error on invalid keys) 38 func MapConfig(channelGroup *cb.ConfigGroup) (map[string]comparable, error) { 39 result := make(map[string]comparable) 40 if channelGroup != nil { 41 err := recurseConfig(result, []string{RootGroupKey}, channelGroup) 42 if err != nil { 43 return nil, err 44 } 45 } 46 return result, nil 47 } 48 49 // addToMap is used only internally by MapConfig 50 func addToMap(cg comparable, result map[string]comparable) error { 51 var fqPath string 52 53 switch { 54 case cg.ConfigGroup != nil: 55 fqPath = GroupPrefix 56 case cg.ConfigValue != nil: 57 fqPath = ValuePrefix 58 case cg.ConfigPolicy != nil: 59 fqPath = PolicyPrefix 60 } 61 62 // TODO rename validateChainID to validateConfigID 63 if err := validateChainID(cg.key); err != nil { 64 return fmt.Errorf("Illegal characters in key: %s", fqPath) 65 } 66 67 if len(cg.path) == 0 { 68 fqPath += PathSeparator + cg.key 69 } else { 70 fqPath += PathSeparator + strings.Join(cg.path, PathSeparator) + PathSeparator + cg.key 71 } 72 73 logger.Debugf("Adding to config map: %s", fqPath) 74 75 result[fqPath] = cg 76 77 return nil 78 } 79 80 // recurseConfig is used only internally by MapConfig 81 func recurseConfig(result map[string]comparable, path []string, group *cb.ConfigGroup) error { 82 if err := addToMap(comparable{key: path[len(path)-1], path: path[:len(path)-1], ConfigGroup: group}, result); err != nil { 83 return err 84 } 85 86 for key, group := range group.Groups { 87 nextPath := append(path, key) 88 if err := recurseConfig(result, nextPath, group); err != nil { 89 return err 90 } 91 } 92 93 for key, value := range group.Values { 94 if err := addToMap(comparable{key: key, path: path, ConfigValue: value}, result); err != nil { 95 return err 96 } 97 } 98 99 for key, policy := range group.Policies { 100 if err := addToMap(comparable{key: key, path: path, ConfigPolicy: policy}, result); err != nil { 101 return err 102 } 103 } 104 105 return nil 106 } 107 108 // configMapToConfig is intended to be called from outside this file 109 // It takes a configMap and converts it back into a *cb.ConfigGroup structure 110 func configMapToConfig(configMap map[string]comparable) (*cb.ConfigGroup, error) { 111 rootPath := PathSeparator + RootGroupKey 112 return recurseConfigMap(rootPath, configMap) 113 } 114 115 // recurseConfigMap is used only internally by configMapToConfig 116 // Note, this function mutates the cb.Config* entrieswithin configMap, so errors are generally fatal 117 func recurseConfigMap(path string, configMap map[string]comparable) (*cb.ConfigGroup, error) { 118 groupPath := GroupPrefix + path 119 group, ok := configMap[groupPath] 120 if !ok { 121 return nil, fmt.Errorf("Missing group at path: %s", groupPath) 122 } 123 124 if group.ConfigGroup == nil { 125 return nil, fmt.Errorf("ConfigGroup not found at group path: %s", groupPath) 126 } 127 128 for key, _ := range group.Groups { 129 updatedGroup, err := recurseConfigMap(path+PathSeparator+key, configMap) 130 if err != nil { 131 return nil, err 132 } 133 group.Groups[key] = updatedGroup 134 } 135 136 for key, _ := range group.Values { 137 valuePath := ValuePrefix + path + PathSeparator + key 138 value, ok := configMap[valuePath] 139 if !ok { 140 return nil, fmt.Errorf("Missing value at path: %s", valuePath) 141 } 142 if value.ConfigValue == nil { 143 return nil, fmt.Errorf("ConfigValue not found at value path: %s", valuePath) 144 } 145 group.Values[key] = value.ConfigValue 146 } 147 148 for key, _ := range group.Policies { 149 policyPath := PolicyPrefix + path + PathSeparator + key 150 policy, ok := configMap[policyPath] 151 if !ok { 152 return nil, fmt.Errorf("Missing policy at path: %s", policyPath) 153 } 154 if policy.ConfigPolicy == nil { 155 return nil, fmt.Errorf("ConfigPolicy not found at policy path: %s", policyPath) 156 } 157 group.Policies[key] = policy.ConfigPolicy 158 } 159 160 return group.ConfigGroup, nil 161 }