Skip to content

Commit 6abde4b

Browse files
author
Jason Yellick
committedOct 13, 2017
[FAB-6103] Add printOrg to configtxgen
One of the most common questions when attempting to add an organization to a channel is how to get the JSON definition for that organization. The only real way to do this at present is to generate a genesis block, decode the block, then go look for the org definition. This CR adds a '-printOrg' flag to configtxgen which will print the organization's definition as JSON to make this process easier. Change-Id: Id12098f36feae8ca4751b82afaf2914166077e50 Signed-off-by: Jason Yellick <jyellick@us.ibm.com>
1 parent 2802430 commit 6abde4b

File tree

4 files changed

+120
-34
lines changed

4 files changed

+120
-34
lines changed
 

‎common/tools/configtxgen/encoder/encoder.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ func NewOrdererGroup(conf *genesisconfig.Orderer) (*cb.ConfigGroup, error) {
180180
func NewOrdererOrgGroup(conf *genesisconfig.Organization) (*cb.ConfigGroup, error) {
181181
mspConfig, err := msp.GetVerifyingMspConfig(conf.MSPDir, conf.ID)
182182
if err != nil {
183-
return nil, errors.Wrapf(err, "1 - Error loading MSP configuration for org %s: %s", conf.Name)
183+
return nil, errors.Wrapf(err, "1 - Error loading MSP configuration for org: %s", conf.Name)
184184
}
185185

186186
ordererOrgGroup := cb.NewConfigGroup()

‎common/tools/configtxgen/localconfig/config.go

+73-28
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,40 @@ var genesisDefaults = TopLevel{
168168
},
169169
}
170170

171+
// LoadTopLevel simply loads the configtx.yaml file into the structs above
172+
// and completes their initialization. Note, for environment overrides to work properly
173+
// within a profile, Load(profile string) should be called when attempting to work within
174+
// a particular profile.
175+
func LoadTopLevel() *TopLevel {
176+
config := viper.New()
177+
cf.InitViper(config, configName)
178+
179+
// For environment variables
180+
config.SetEnvPrefix(Prefix)
181+
config.AutomaticEnv()
182+
183+
replacer := strings.NewReplacer(".", "_")
184+
config.SetEnvKeyReplacer(replacer)
185+
186+
err := config.ReadInConfig()
187+
if err != nil {
188+
logger.Panic("Error reading configuration: ", err)
189+
}
190+
logger.Debugf("Using config file: %s", config.ConfigFileUsed())
191+
192+
var uconf TopLevel
193+
err = viperutil.EnhancedExactUnmarshal(config, &uconf)
194+
if err != nil {
195+
logger.Panic("Error unmarshaling config into struct: ", err)
196+
}
197+
198+
(&uconf).completeInitialization(filepath.Dir(config.ConfigFileUsed()))
199+
200+
logger.Infof("Loaded configuration: %s", config.ConfigFileUsed())
201+
202+
return &uconf
203+
}
204+
171205
// Load returns the orderer/application config combination that corresponds to a given profile.
172206
func Load(profile string) *Profile {
173207
config := viper.New()
@@ -176,6 +210,7 @@ func Load(profile string) *Profile {
176210
// For environment variables
177211
config.SetEnvPrefix(Prefix)
178212
config.AutomaticEnv()
213+
179214
// This replacer allows substitution within the particular profile without having to fully qualify the name
180215
replacer := strings.NewReplacer(strings.ToUpper(fmt.Sprintf("profiles.%s.", profile)), "", ".", "_")
181216
config.SetEnvKeyReplacer(replacer)
@@ -204,64 +239,74 @@ func Load(profile string) *Profile {
204239
return result
205240
}
206241

242+
func (t *TopLevel) completeInitialization(configDir string) {
243+
for _, org := range t.Organizations {
244+
org.completeInitialization(configDir)
245+
}
246+
247+
if t.Orderer != nil {
248+
t.Orderer.completeInitialization()
249+
}
250+
}
251+
207252
func (p *Profile) completeInitialization(configDir string) {
208253
if p.Orderer != nil {
209254
for _, org := range p.Orderer.Organizations {
210-
if org.AdminPrincipal == "" {
211-
org.AdminPrincipal = AdminRoleAdminPrincipal
212-
}
213-
translatePaths(configDir, org)
255+
org.completeInitialization(configDir)
214256
}
215257
}
216258

217259
if p.Application != nil {
218260
for _, org := range p.Application.Organizations {
219-
if org.AdminPrincipal == "" {
220-
org.AdminPrincipal = AdminRoleAdminPrincipal
221-
}
222-
translatePaths(configDir, org)
261+
org.completeInitialization(configDir)
223262
}
224263
}
225264

226265
if p.Consortiums != nil {
227266
for _, consortium := range p.Consortiums {
228267
for _, org := range consortium.Organizations {
229-
if org.AdminPrincipal == "" {
230-
org.AdminPrincipal = AdminRoleAdminPrincipal
231-
}
232-
translatePaths(configDir, org)
268+
org.completeInitialization(configDir)
233269
}
234270
}
235271
}
236272

237273
// Some profiles will not define orderer parameters
238-
if p.Orderer == nil {
239-
return
274+
if p.Orderer != nil {
275+
p.Orderer.completeInitialization()
240276
}
277+
}
278+
279+
func (org *Organization) completeInitialization(configDir string) {
280+
if org.AdminPrincipal == "" {
281+
org.AdminPrincipal = AdminRoleAdminPrincipal
282+
}
283+
translatePaths(configDir, org)
284+
}
241285

286+
func (oc *Orderer) completeInitialization() {
242287
for {
243288
switch {
244-
case p.Orderer.OrdererType == "":
289+
case oc.OrdererType == "":
245290
logger.Infof("Orderer.OrdererType unset, setting to %s", genesisDefaults.Orderer.OrdererType)
246-
p.Orderer.OrdererType = genesisDefaults.Orderer.OrdererType
247-
case p.Orderer.Addresses == nil:
291+
oc.OrdererType = genesisDefaults.Orderer.OrdererType
292+
case oc.Addresses == nil:
248293
logger.Infof("Orderer.Addresses unset, setting to %s", genesisDefaults.Orderer.Addresses)
249-
p.Orderer.Addresses = genesisDefaults.Orderer.Addresses
250-
case p.Orderer.BatchTimeout == 0:
294+
oc.Addresses = genesisDefaults.Orderer.Addresses
295+
case oc.BatchTimeout == 0:
251296
logger.Infof("Orderer.BatchTimeout unset, setting to %s", genesisDefaults.Orderer.BatchTimeout)
252-
p.Orderer.BatchTimeout = genesisDefaults.Orderer.BatchTimeout
253-
case p.Orderer.BatchSize.MaxMessageCount == 0:
297+
oc.BatchTimeout = genesisDefaults.Orderer.BatchTimeout
298+
case oc.BatchSize.MaxMessageCount == 0:
254299
logger.Infof("Orderer.BatchSize.MaxMessageCount unset, setting to %s", genesisDefaults.Orderer.BatchSize.MaxMessageCount)
255-
p.Orderer.BatchSize.MaxMessageCount = genesisDefaults.Orderer.BatchSize.MaxMessageCount
256-
case p.Orderer.BatchSize.AbsoluteMaxBytes == 0:
300+
oc.BatchSize.MaxMessageCount = genesisDefaults.Orderer.BatchSize.MaxMessageCount
301+
case oc.BatchSize.AbsoluteMaxBytes == 0:
257302
logger.Infof("Orderer.BatchSize.AbsoluteMaxBytes unset, setting to %s", genesisDefaults.Orderer.BatchSize.AbsoluteMaxBytes)
258-
p.Orderer.BatchSize.AbsoluteMaxBytes = genesisDefaults.Orderer.BatchSize.AbsoluteMaxBytes
259-
case p.Orderer.BatchSize.PreferredMaxBytes == 0:
303+
oc.BatchSize.AbsoluteMaxBytes = genesisDefaults.Orderer.BatchSize.AbsoluteMaxBytes
304+
case oc.BatchSize.PreferredMaxBytes == 0:
260305
logger.Infof("Orderer.BatchSize.PreferredMaxBytes unset, setting to %s", genesisDefaults.Orderer.BatchSize.PreferredMaxBytes)
261-
p.Orderer.BatchSize.PreferredMaxBytes = genesisDefaults.Orderer.BatchSize.PreferredMaxBytes
262-
case p.Orderer.Kafka.Brokers == nil:
306+
oc.BatchSize.PreferredMaxBytes = genesisDefaults.Orderer.BatchSize.PreferredMaxBytes
307+
case oc.Kafka.Brokers == nil:
263308
logger.Infof("Orderer.Kafka.Brokers unset, setting to %v", genesisDefaults.Orderer.Kafka.Brokers)
264-
p.Orderer.Kafka.Brokers = genesisDefaults.Orderer.Kafka.Brokers
309+
oc.Kafka.Brokers = genesisDefaults.Orderer.Kafka.Brokers
265310
default:
266311
return
267312
}

‎common/tools/configtxgen/main.go

+35-5
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
"github.com/hyperledger/fabric/protos/utils"
2626

2727
logging "github.com/op/go-logging"
28+
"github.com/pkg/errors"
2829
)
2930

3031
var exitCode = 0
@@ -204,8 +205,25 @@ func doInspectChannelCreateTx(inspectChannelCreateTx string) error {
204205
return nil
205206
}
206207

208+
func doPrintOrg(t *genesisconfig.TopLevel, printOrg string) error {
209+
for _, org := range t.Organizations {
210+
if org.Name == printOrg {
211+
og, err := encoder.NewOrdererOrgGroup(org)
212+
if err != nil {
213+
return errors.Wrapf(err, "bad org definition for org %s", org.Name)
214+
}
215+
216+
if err := protolator.DeepMarshalJSON(os.Stdout, og); err != nil {
217+
return errors.Wrapf(err, "malformed org definition for org: %s", org.Name)
218+
}
219+
return nil
220+
}
221+
}
222+
return errors.Errorf("organization %s not found", printOrg)
223+
}
224+
207225
func main() {
208-
var outputBlock, outputChannelCreateTx, profile, channelID, inspectBlock, inspectChannelCreateTx, outputAnchorPeersUpdate, asOrg string
226+
var outputBlock, outputChannelCreateTx, profile, channelID, inspectBlock, inspectChannelCreateTx, outputAnchorPeersUpdate, asOrg, printOrg string
209227

210228
flag.StringVar(&outputBlock, "outputBlock", "", "The path to write the genesis block to (if set)")
211229
flag.StringVar(&channelID, "channelID", genesisconfig.TestChainID, "The channel ID to use in the configtx")
@@ -215,6 +233,7 @@ func main() {
215233
flag.StringVar(&inspectChannelCreateTx, "inspectChannelCreateTx", "", "Prints the configuration contained in the transaction at the specified path")
216234
flag.StringVar(&outputAnchorPeersUpdate, "outputAnchorPeersUpdate", "", "Creates an config update to update an anchor peer (works only with the default channel creation, and only for the first update)")
217235
flag.StringVar(&asOrg, "asOrg", "", "Performs the config generation as a particular organization (by name), only including values in the write set that org (likely) has privilege to set")
236+
flag.StringVar(&printOrg, "printOrg", "", "Prints the definition of an organization as JSON. (useful for adding an org to a channel manually)")
218237

219238
version := flag.Bool("version", false, "Show version information")
220239

@@ -242,16 +261,21 @@ func main() {
242261

243262
logger.Info("Loading configuration")
244263
factory.InitFactories(nil)
245-
config := genesisconfig.Load(profile)
264+
var profileConfig *genesisconfig.Profile
265+
if outputBlock != "" || outputChannelCreateTx != "" || outputAnchorPeersUpdate != "" {
266+
profileConfig = genesisconfig.Load(profile)
267+
}
268+
269+
topLevelConfig := genesisconfig.LoadTopLevel()
246270

247271
if outputBlock != "" {
248-
if err := doOutputBlock(config, channelID, outputBlock); err != nil {
272+
if err := doOutputBlock(profileConfig, channelID, outputBlock); err != nil {
249273
logger.Fatalf("Error on outputBlock: %s", err)
250274
}
251275
}
252276

253277
if outputChannelCreateTx != "" {
254-
if err := doOutputChannelCreateTx(config, channelID, outputChannelCreateTx); err != nil {
278+
if err := doOutputChannelCreateTx(profileConfig, channelID, outputChannelCreateTx); err != nil {
255279
logger.Fatalf("Error on outputChannelCreateTx: %s", err)
256280
}
257281
}
@@ -269,10 +293,16 @@ func main() {
269293
}
270294

271295
if outputAnchorPeersUpdate != "" {
272-
if err := doOutputAnchorPeersUpdate(config, channelID, outputAnchorPeersUpdate, asOrg); err != nil {
296+
if err := doOutputAnchorPeersUpdate(profileConfig, channelID, outputAnchorPeersUpdate, asOrg); err != nil {
273297
logger.Fatalf("Error on inspectChannelCreateTx: %s", err)
274298
}
275299
}
300+
301+
if printOrg != "" {
302+
if err := doPrintOrg(topLevelConfig, printOrg); err != nil {
303+
logger.Fatalf("Error on printOrg: %s", err)
304+
}
305+
}
276306
}
277307

278308
func printVersion() {

‎common/tools/configtxgen/main_test.go

+11
Original file line numberDiff line numberDiff line change
@@ -141,3 +141,14 @@ func TestBlockFlags(t *testing.T) {
141141
_, err := os.Stat(blockDest)
142142
assert.NoError(t, err, "Block file is written successfully")
143143
}
144+
145+
func TestPrintOrg(t *testing.T) {
146+
factory.InitFactories(nil)
147+
config := genesisconfig.LoadTopLevel()
148+
149+
assert.NoError(t, doPrintOrg(config, genesisconfig.SampleOrgName), "Good org to print")
150+
151+
err := doPrintOrg(config, genesisconfig.SampleOrgName+".wrong")
152+
assert.Error(t, err, "Bad org name")
153+
assert.Regexp(t, "organization [^ ]* not found", err.Error())
154+
}

0 commit comments

Comments
 (0)
Please sign in to comment.