github.com/adnan-c/fabric_e2e_couchdb@v0.6.1-preview.0.20170228180935-21ce6b23cf91/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 err := recurseConfig(result, []string{RootGroupKey}, channelGroup) 41 if err != nil { 42 return nil, err 43 } 44 return result, nil 45 } 46 47 // addToMap is used only internally by mapConfig 48 func addToMap(cg comparable, result map[string]comparable) error { 49 var fqPath string 50 51 switch { 52 case cg.ConfigGroup != nil: 53 fqPath = GroupPrefix 54 case cg.ConfigValue != nil: 55 fqPath = ValuePrefix 56 case cg.ConfigPolicy != nil: 57 fqPath = PolicyPrefix 58 } 59 60 // TODO rename validateChainID to validateConfigID 61 if err := validateChainID(cg.key); err != nil { 62 return fmt.Errorf("Illegal characters in key: %s", fqPath) 63 } 64 65 if len(cg.path) == 0 { 66 fqPath += PathSeparator + cg.key 67 } else { 68 fqPath += PathSeparator + strings.Join(cg.path, PathSeparator) + PathSeparator + cg.key 69 } 70 71 logger.Debugf("Adding to config map: %s", fqPath) 72 73 result[fqPath] = cg 74 75 return nil 76 } 77 78 // recurseConfig is used only internally by mapConfig 79 func recurseConfig(result map[string]comparable, path []string, group *cb.ConfigGroup) error { 80 if err := addToMap(comparable{key: path[len(path)-1], path: path[:len(path)-1], ConfigGroup: group}, result); err != nil { 81 return err 82 } 83 84 for key, group := range group.Groups { 85 nextPath := append(path, key) 86 if err := recurseConfig(result, nextPath, group); err != nil { 87 return err 88 } 89 } 90 91 for key, value := range group.Values { 92 if err := addToMap(comparable{key: key, path: path, ConfigValue: value}, result); err != nil { 93 return err 94 } 95 } 96 97 for key, policy := range group.Policies { 98 if err := addToMap(comparable{key: key, path: path, ConfigPolicy: policy}, result); err != nil { 99 return err 100 } 101 } 102 103 return nil 104 } 105 106 // configMapToConfig is intended to be called from outside this file 107 // It takes a configMap and converts it back into a *cb.ConfigGroup structure 108 func configMapToConfig(configMap map[string]comparable) (*cb.ConfigGroup, error) { 109 rootPath := PathSeparator + RootGroupKey 110 return recurseConfigMap(rootPath, configMap) 111 } 112 113 // recurseConfigMap is used only internally by configMapToConfig 114 // Note, this function mutates the cb.Config* entrieswithin configMap, so errors are generally fatal 115 func recurseConfigMap(path string, configMap map[string]comparable) (*cb.ConfigGroup, error) { 116 groupPath := GroupPrefix + path 117 group, ok := configMap[groupPath] 118 if !ok { 119 return nil, fmt.Errorf("Missing group at path: %s", groupPath) 120 } 121 122 if group.ConfigGroup == nil { 123 return nil, fmt.Errorf("ConfigGroup not found at group path", groupPath) 124 } 125 126 for key, _ := range group.Groups { 127 updatedGroup, err := recurseConfigMap(path+PathSeparator+key, configMap) 128 if err != nil { 129 return nil, err 130 } 131 group.Groups[key] = updatedGroup 132 } 133 134 for key, _ := range group.Values { 135 valuePath := ValuePrefix + path + PathSeparator + key 136 value, ok := configMap[valuePath] 137 if !ok { 138 return nil, fmt.Errorf("Missing value at path: %s", valuePath) 139 } 140 if value.ConfigValue == nil { 141 return nil, fmt.Errorf("ConfigValue not found at value path", valuePath) 142 } 143 group.Values[key] = value.ConfigValue 144 } 145 146 for key, _ := range group.Policies { 147 policyPath := PolicyPrefix + path + PathSeparator + key 148 policy, ok := configMap[policyPath] 149 if !ok { 150 return nil, fmt.Errorf("Missing policy at path: %s", policyPath) 151 } 152 if policy.ConfigPolicy == nil { 153 return nil, fmt.Errorf("ConfigPolicy not found at policy path", policyPath) 154 } 155 group.Policies[key] = policy.ConfigPolicy 156 } 157 158 return group.ConfigGroup, nil 159 }