Skip to content

Commit f02e00a

Browse files
committed
finish anchor peer of the last step of channel creation
1 parent f8d6944 commit f02e00a

File tree

5 files changed

+170
-61
lines changed

5 files changed

+170
-61
lines changed

src/api-engine/api/lib/configtxlator/configtxlator.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,8 @@ def proto_decode(self, input, type, output):
6060

6161
LOG.info(" ".join(command))
6262

63-
res = run(command,
64-
capture_output=True)
63+
call(command)
6564

66-
if res.returncode == 0 :
67-
return res.stdout
68-
else:
69-
return res.stderr
7065
except Exception as e:
7166
err_msg = "configtxlator proto decode fail! "
7267
raise Exception(err_msg + str(e))

src/api-engine/api/lib/jq/__init__.py

Whitespace-only changes.

src/api-engine/api/lib/jq/jq.py

Lines changed: 0 additions & 29 deletions
This file was deleted.

src/api-engine/api/routes/channel/views.py

Lines changed: 60 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
from api.config import CELLO_HOME
2020
from api.common.serializers import PageQuerySerializer
21-
from api.utils.common import with_common_response, parse_block_file, to_dict
21+
from api.utils.common import with_common_response, parse_block_file, to_dict, json_filter, json_add_anchor_peer, json_create_envelope
2222
from api.lib.configtxgen import ConfigTX, ConfigTxGen
2323
from api.lib.jq.jq import JQ
2424
from api.lib.peer.channel import Channel as PeerChannel
@@ -148,7 +148,8 @@ def create(self, request):
148148
peer_channel_join(name, peers, org)
149149

150150
# set anchor peer
151-
set_anchor_peer(name, org, peers, ordering_node)
151+
anchor_peer = Node.objects.get(id=peers[0])
152+
set_anchor_peer(name, org, anchor_peer, ordering_node)
152153

153154
# save channel to db
154155
channel = Channel(
@@ -426,33 +427,55 @@ def peer_channel_join(name, peers, org):
426427
CELLO_HOME, org.network.name, name)
427428
)
428429

429-
def set_anchor_peer(name, org, peers, ordering_node):
430+
def set_anchor_peer(name, org, anchor_peer, ordering_node):
430431
"""
431432
Set anchor peer for the channel.
432433
:param org: Organization object.
433-
:param peers: list of Node objects
434+
:param anchor_peer: Anchor peer node
435+
:param ordering_node: Orderer node
434436
:return: none
435437
"""
436-
org_msp = '{}MSP'.format(org.name.split(".", 1)[0].capitalize())
438+
org_msp = '{}'.format(org.name.split(".", 1)[0].capitalize())
437439
channel_artifacts_path = "{}/{}".format(CELLO_HOME, org.network.name)
438-
peer_channel_fetch(name, org, peers, ordering_node)
440+
441+
# Fetch the channel block from the orderer
442+
peer_channel_fetch(name, org, anchor_peer, ordering_node)
439443

440-
ConfigTxLator().proto_encode(
444+
# Decode block to JSON
445+
ConfigTxLator().proto_decode(
441446
input="{}/config_block.pb".format(channel_artifacts_path),
442447
type="common.Block",
443448
output="{}/config_block.json".format(channel_artifacts_path),
444449
)
445-
446-
JQ().filter(
450+
451+
# Get the config data from the block
452+
json_filter(
447453
input="{}/config_block.json".format(channel_artifacts_path),
448454
output="{}/config.json".format(channel_artifacts_path),
449455
expression=".data.data[0].payload.data.config"
450456
)
451457

452-
JQ().filter(
458+
# add anchor peer config
459+
anchor_peer_config = {
460+
"AnchorPeers": {
461+
"mod_policy": "Admins",
462+
"value": {
463+
"anchor_peers": [
464+
{
465+
"host": anchor_peer.name + "." + org.name,
466+
"port": 7051
467+
}
468+
]
469+
},
470+
"version": 0
471+
}
472+
}
473+
474+
json_add_anchor_peer(
453475
input="{}/config.json".format(channel_artifacts_path),
454476
output="{}/modified_config.json".format(channel_artifacts_path),
455-
expression=".channel_group.groups.Application.groups.{}.values += {{AnchorPeers:{{mod_policy: Admins,value:{{anchor_peers:[{{host: {},port: {}}}]}},version: 0}}}}".format(org_msp, peers[0].name, str(7051))
477+
anchor_peer_config=anchor_peer_config,
478+
org_msp=org_msp
456479
)
457480

458481
ConfigTxLator().proto_encode(
@@ -480,10 +503,11 @@ def set_anchor_peer(name, org, peers, ordering_node):
480503
output="{}/config_update.json".format(channel_artifacts_path),
481504
)
482505

483-
JQ().filter(
484-
input=".",
506+
# Create config update envelope
507+
json_create_envelope(
508+
input="{}/config_update.json".format(channel_artifacts_path),
485509
output="{}/config_update_in_envelope.json".format(channel_artifacts_path),
486-
expression=""
510+
channel=name
487511
)
488512

489513
ConfigTxLator().proto_encode(
@@ -492,31 +516,41 @@ def set_anchor_peer(name, org, peers, ordering_node):
492516
output="{}/config_update_in_envelope.pb".format(channel_artifacts_path),
493517
)
494518

495-
envs = init_env_vars(ordering_node, org)
496-
peer_channel_cli = PeerChannel(**envs)
497-
peer_channel_cli.update(
498-
channel=name,
499-
channel_tx="{}/config_update_in_envelope.pb".format(channel_artifacts_path),
500-
orderer_url="{}.{}:{}".format(
501-
ordering_node.name, org.name.split(".", 1)[1], str(7050)),
502-
)
519+
# Update the channel of anchor peer
520+
peer_channel_update(name, org, anchor_peer, ordering_node, channel_artifacts_path)
503521

504522

505-
def peer_channel_fetch(name, org, peers, ordering_node):
523+
def peer_channel_fetch(name, org, anchor_peer, ordering_node):
506524
"""
507525
Fetch the channel block from the orderer.
508-
:param peers: list of Node objects
526+
:param anchor_peer: Anchor peer node
509527
:param org: Organization object.
510528
:param channel_name: Name of the channel.
511529
:return: none
512530
"""
513-
peer_node = Node.objects.get(id=peers[0])
514-
envs = init_env_vars(peer_node, org)
531+
envs = init_env_vars(anchor_peer, org)
515532
peer_channel_cli = PeerChannel(**envs)
516533
peer_channel_cli.fetch(block_path="{}/{}/config_block.pb".format(CELLO_HOME, org.network.name),
517534
channel=name, orderer_general_url="{}.{}:{}".format(
518535
ordering_node.name, org.name.split(".", 1)[1], str(7050)))
519536

537+
def peer_channel_update(name, org, anchor_peer, ordering_node, channel_artifacts_path):
538+
"""
539+
Update the channel.
540+
:param anchor_peer: Anchor peer node
541+
:param org: Organization object.
542+
:param channel_name: Name of the channel.
543+
:return: none
544+
"""
545+
envs = init_env_vars(anchor_peer, org)
546+
peer_channel_cli = PeerChannel(**envs)
547+
peer_channel_cli.update(
548+
channel=name,
549+
channel_tx="{}/config_update_in_envelope.pb".format(channel_artifacts_path),
550+
orderer_url="{}.{}:{}".format(
551+
ordering_node.name, org.name.split(".", 1)[1], str(7050)),
552+
)
553+
520554

521555
def init_env_vars(node, org):
522556
"""

src/api-engine/api/utils/common.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,10 @@
1313
import uuid
1414
from zipfile import ZipFile
1515
from json import loads
16+
import json
17+
import logging
1618

19+
LOG = logging.getLogger(__name__)
1720

1821
def make_uuid():
1922
return str(uuid.uuid4())
@@ -153,3 +156,109 @@ def parse_block_file(data):
153156

154157
def to_dict(data):
155158
return loads(data)
159+
160+
161+
def json_filter(input, output, expression):
162+
"""
163+
Process JSON data using path expression similar to jq
164+
165+
Args:
166+
input (str): JSON data or file path to JSON
167+
output (str): Path expression like ".data.data[0].payload.data.config"
168+
169+
Returns:
170+
dict: Processed JSON data
171+
"""
172+
# if json_data is a file path, read the file
173+
if isinstance(input, str):
174+
with open(input, 'r', encoding='utf-8') as f:
175+
data = json.load(f)
176+
else:
177+
data = input
178+
179+
# parse the path expression
180+
path_parts = expression.strip('.').split('.')
181+
result = data
182+
183+
for part in path_parts:
184+
# handle array index, like data[0]
185+
if '[' in part and ']' in part:
186+
array_name = part.split('[')[0]
187+
index = int(part.split('[')[1].split(']')[0])
188+
result = result[array_name][index]
189+
else:
190+
result = result[part]
191+
192+
with open(output, 'w', encoding='utf-8') as f:
193+
json.dump(result, f, sort_keys=False, indent=4)
194+
195+
LOG.info("jq {} {} -> {}".format(expression, input, output))
196+
197+
def json_add_anchor_peer(input, output, anchor_peer_config, org_msp):
198+
"""
199+
Add anchor peer to the organization
200+
201+
Args:
202+
input (str): JSON data or file path to JSON
203+
output (str): Path expression like ".data.data[0].payload.data.config"
204+
expression (str): Anchor peer data
205+
"""
206+
# if json_data is a file path, read the file
207+
if isinstance(input, str):
208+
with open(input, 'r', encoding='utf-8') as f:
209+
data = json.load(f)
210+
else:
211+
data = input
212+
213+
if "groups" not in data["channel_group"]:
214+
data["channel_group"]["groups"] = {}
215+
if "Application" not in data["channel_group"]["groups"]:
216+
data["channel_group"]["groups"]["Application"] = {"groups": {}}
217+
if org_msp not in data["channel_group"]["groups"]["Application"]["groups"]:
218+
data["channel_group"]["groups"]["Application"]["groups"][org_msp] = {"values": {}}
219+
220+
data["channel_group"]["groups"]["Application"]["groups"][org_msp]["values"].update(anchor_peer_config)
221+
222+
with open(output, 'w', encoding='utf-8') as f:
223+
json.dump(data, f, sort_keys=False, indent=4)
224+
225+
LOG.info("jq '.channel_group.groups.Application.groups.Org1MSP.values += ... ' {} -> {}".format(input, output))
226+
227+
def json_create_envelope(input, output, channel):
228+
"""
229+
Create a config update envelope structure
230+
231+
Args:
232+
input (str): Path to the config update JSON file
233+
output (str): Path to save the envelope JSON
234+
channel (str): Name of the channel
235+
"""
236+
try:
237+
# Read the config update file
238+
with open(input, 'r', encoding='utf-8') as f:
239+
config_update = json.load(f)
240+
241+
# Create the envelope structure
242+
envelope = {
243+
"payload": {
244+
"header": {
245+
"channel_header": {
246+
"channel_id": channel,
247+
"type": 2
248+
}
249+
},
250+
"data": {
251+
"config_update": config_update
252+
}
253+
}
254+
}
255+
256+
# Write the envelope to output file
257+
with open(output, 'w', encoding='utf-8') as f:
258+
json.dump(envelope, f, sort_keys=False, indent=4)
259+
260+
LOG.info("echo 'payload ... ' | jq . > {}".format(output))
261+
262+
except Exception as e:
263+
LOG.error("Failed to create config update envelope: {}".format(str(e)))
264+
raise

0 commit comments

Comments
 (0)