Added node actions and other fixes

This commit is contained in:
James Belleau 2020-05-15 19:38:19 -05:00
parent 8d3d43da90
commit 93311dbd4b
12 changed files with 1123 additions and 59 deletions

View File

@ -31,7 +31,18 @@ class ResourceNotFoundException(ManagedBlockchainClientError):
self.code = 404 self.code = 404
super(ResourceNotFoundException, self).__init__( super(ResourceNotFoundException, self).__init__(
"ResourceNotFoundException", "ResourceNotFoundException",
"An error occurred (BadRequestException) when calling the {0} operation: {1}".format( "An error occurred (ResourceNotFoundException) when calling the {0} operation: {1}".format(
pretty_called_method, operation_error
),
)
class ResourceAlreadyExistsException(ManagedBlockchainClientError):
def __init__(self, pretty_called_method, operation_error):
self.code = 409
super(ResourceAlreadyExistsException, self).__init__(
"ResourceAlreadyExistsException",
"An error occurred (ResourceAlreadyExistsException) when calling the {0} operation: {1}".format(
pretty_called_method, operation_error pretty_called_method, operation_error
), ),
) )

View File

@ -12,6 +12,7 @@ from .exceptions import (
ResourceNotFoundException, ResourceNotFoundException,
InvalidRequestException, InvalidRequestException,
ResourceLimitExceededException, ResourceLimitExceededException,
ResourceAlreadyExistsException,
) )
from .utils import ( from .utils import (
@ -22,6 +23,9 @@ from .utils import (
member_name_exist_in_network, member_name_exist_in_network,
number_of_members_in_network, number_of_members_in_network,
admin_password_ok, admin_password_ok,
get_node_id,
number_of_nodes_in_member,
nodes_in_member,
) )
FRAMEWORKS = [ FRAMEWORKS = [
@ -212,6 +216,10 @@ class ManagedBlockchainProposal(BaseModel):
return self.actions["Removals"] return self.actions["Removals"]
return default_return return default_return
def check_to_expire_proposal(self):
if datetime.datetime.utcnow() > self.expirtationdate:
self.status = "EXPIRED"
def to_dict(self): def to_dict(self):
# Format for list_proposals # Format for list_proposals
d = { d = {
@ -244,10 +252,6 @@ class ManagedBlockchainProposal(BaseModel):
return d return d
def set_vote(self, votermemberid, votermembername, vote): def set_vote(self, votermemberid, votermembername, vote):
if datetime.datetime.utcnow() > self.expirtationdate:
self.status = "EXPIRED"
return False
if vote.upper() == "YES": if vote.upper() == "YES":
self.yes_vote_count += 1 self.yes_vote_count += 1
else: else:
@ -273,7 +277,14 @@ class ManagedBlockchainProposal(BaseModel):
elif perct_no > self.network_threshold: elif perct_no > self.network_threshold:
self.status = "REJECTED" self.status = "REJECTED"
return True # It is a tie - reject
if (
self.status == "IN_PROGRESS"
and self.network_threshold_comp == "GREATER_THAN"
and self.outstanding_vote_count == 0
and perct_yes == perct_no
):
self.status = "REJECTED"
class ManagedBlockchainInvitation(BaseModel): class ManagedBlockchainInvitation(BaseModel):
@ -413,12 +424,92 @@ class ManagedBlockchainMember(BaseModel):
] = logpublishingconfiguration ] = logpublishingconfiguration
class ManagedBlockchainNode(BaseModel):
def __init__(
self,
id,
networkid,
memberid,
availabilityzone,
instancetype,
logpublishingconfiguration,
region,
):
self.creationdate = datetime.datetime.utcnow()
self.id = id
self.instancetype = instancetype
self.networkid = networkid
self.memberid = memberid
self.logpublishingconfiguration = logpublishingconfiguration
self.region = region
self.status = "AVAILABLE"
self.availabilityzone = availabilityzone
@property
def member_id(self):
return self.memberid
@property
def node_status(self):
return self.status
def to_dict(self):
# Format for list_nodes
d = {
"Id": self.id,
"Status": self.status,
"CreationDate": self.creationdate.strftime("%Y-%m-%dT%H:%M:%S.%f%z"),
"AvailabilityZone": self.availabilityzone,
"InstanceType": self.instancetype,
}
return d
def get_format(self):
# Format for get_node
frameworkattributes = {
"Fabric": {
"PeerEndpoint": "{0}.{1}.{2}.managedblockchain.{3}.amazonaws.com:30003".format(
self.id.lower(),
self.networkid.lower(),
self.memberid.lower(),
self.region,
),
"PeerEventEndpoint": "{0}.{1}.{2}.managedblockchain.{3}.amazonaws.com:30004".format(
self.id.lower(),
self.networkid.lower(),
self.memberid.lower(),
self.region,
),
}
}
d = {
"NetworkId": self.networkid,
"MemberId": self.memberid,
"Id": self.id,
"InstanceType": self.instancetype,
"AvailabilityZone": self.availabilityzone,
"FrameworkAttributes": frameworkattributes,
"LogPublishingConfiguration": self.logpublishingconfiguration,
"Status": self.status,
"CreationDate": self.creationdate.strftime("%Y-%m-%dT%H:%M:%S.%f%z"),
}
return d
def delete(self):
self.status = "DELETED"
def update(self, logpublishingconfiguration):
self.logpublishingconfiguration = logpublishingconfiguration
class ManagedBlockchainBackend(BaseBackend): class ManagedBlockchainBackend(BaseBackend):
def __init__(self, region_name): def __init__(self, region_name):
self.networks = {} self.networks = {}
self.members = {} self.members = {}
self.proposals = {} self.proposals = {}
self.invitations = {} self.invitations = {}
self.nodes = {}
self.region_name = region_name self.region_name = region_name
def reset(self): def reset(self):
@ -453,10 +544,10 @@ class ManagedBlockchainBackend(BaseBackend):
if frameworkconfiguration["Fabric"]["Edition"] not in EDITIONS: if frameworkconfiguration["Fabric"]["Edition"] not in EDITIONS:
raise BadRequestException("CreateNetwork", "Invalid request body") raise BadRequestException("CreateNetwork", "Invalid request body")
## Generate network ID # Generate network ID
network_id = get_network_id() network_id = get_network_id()
## Generate memberid ID and initial member # Generate memberid ID and initial member
member_id = get_member_id() member_id = get_member_id()
self.members[member_id] = ManagedBlockchainMember( self.members[member_id] = ManagedBlockchainMember(
id=member_id, id=member_id,
@ -524,7 +615,7 @@ class ManagedBlockchainBackend(BaseBackend):
"Member ID format specified in proposal is not valid.", "Member ID format specified in proposal is not valid.",
) )
## Generate proposal ID # Generate proposal ID
proposal_id = get_proposal_id() proposal_id = get_proposal_id()
self.proposals[proposal_id] = ManagedBlockchainProposal( self.proposals[proposal_id] = ManagedBlockchainProposal(
@ -558,6 +649,8 @@ class ManagedBlockchainBackend(BaseBackend):
proposalsfornetwork = [] proposalsfornetwork = []
for proposal_id in self.proposals: for proposal_id in self.proposals:
if self.proposals.get(proposal_id).network_id == networkid: if self.proposals.get(proposal_id).network_id == networkid:
# See if any are expired
self.proposals.get(proposal_id).check_to_expire_proposal()
proposalsfornetwork.append(self.proposals[proposal_id]) proposalsfornetwork.append(self.proposals[proposal_id])
return proposalsfornetwork return proposalsfornetwork
@ -572,6 +665,9 @@ class ManagedBlockchainBackend(BaseBackend):
raise ResourceNotFoundException( raise ResourceNotFoundException(
"GetProposal", "Proposal {0} not found.".format(proposalid) "GetProposal", "Proposal {0} not found.".format(proposalid)
) )
# See if it needs to be set to expipred
self.proposals.get(proposalid).check_to_expire_proposal()
return self.proposals.get(proposalid) return self.proposals.get(proposalid)
def vote_on_proposal(self, networkid, proposalid, votermemberid, vote): def vote_on_proposal(self, networkid, proposalid, votermemberid, vote):
@ -594,43 +690,65 @@ class ManagedBlockchainBackend(BaseBackend):
if vote.upper() not in VOTEVALUES: if vote.upper() not in VOTEVALUES:
raise BadRequestException("VoteOnProposal", "Invalid request body") raise BadRequestException("VoteOnProposal", "Invalid request body")
# See if it needs to be set to expipred
self.proposals.get(proposalid).check_to_expire_proposal()
# Exception if EXPIRED
if self.proposals.get(proposalid).proposal_status == "EXPIRED":
raise InvalidRequestException(
"VoteOnProposal",
"Proposal {0} is expired and you cannot vote on it.".format(proposalid),
)
# Check if IN_PROGRESS
if self.proposals.get(proposalid).proposal_status != "IN_PROGRESS":
raise InvalidRequestException(
"VoteOnProposal",
"Proposal {0} has status {1} and you cannot vote on it.".format(
proposalid, self.proposals.get(proposalid).proposal_status
),
)
# Check to see if this member already voted # Check to see if this member already voted
# TODO Verify exception
if votermemberid in self.proposals.get(proposalid).proposal_votes: if votermemberid in self.proposals.get(proposalid).proposal_votes:
raise BadRequestException("VoteOnProposal", "Invalid request body") raise ResourceAlreadyExistsException(
"VoteOnProposal",
"Member {0} has already voted on proposal {1}.".format(
votermemberid, proposalid
),
)
# Will return false if vote was not cast (e.g., status wrong) # Cast vote
if self.proposals.get(proposalid).set_vote( self.proposals.get(proposalid).set_vote(
votermemberid, self.members.get(votermemberid).name, vote.upper() votermemberid, self.members.get(votermemberid).name, vote.upper()
): )
if self.proposals.get(proposalid).proposal_status == "APPROVED":
## Generate invitations
for propinvitation in self.proposals.get(proposalid).proposal_actions(
"Invitations"
):
invitation_id = get_invitation_id()
self.invitations[invitation_id] = ManagedBlockchainInvitation(
id=invitation_id,
networkid=networkid,
networkname=self.networks.get(networkid).network_name,
networkframework=self.networks.get(networkid).network_framework,
networkframeworkversion=self.networks.get(
networkid
).network_framework_version,
networkcreationdate=self.networks.get(
networkid
).network_creationdate,
region=self.region_name,
networkdescription=self.networks.get(
networkid
).network_description,
)
## Delete members if self.proposals.get(proposalid).proposal_status == "APPROVED":
for propmember in self.proposals.get(proposalid).proposal_actions( # Generate invitations
"Removals" for propinvitation in self.proposals.get(proposalid).proposal_actions(
): "Invitations"
self.delete_member(networkid, propmember["MemberId"]) ):
invitation_id = get_invitation_id()
self.invitations[invitation_id] = ManagedBlockchainInvitation(
id=invitation_id,
networkid=networkid,
networkname=self.networks.get(networkid).network_name,
networkframework=self.networks.get(networkid).network_framework,
networkframeworkversion=self.networks.get(
networkid
).network_framework_version,
networkcreationdate=self.networks.get(
networkid
).network_creationdate,
region=self.region_name,
networkdescription=self.networks.get(networkid).network_description,
)
# Delete members
for propmember in self.proposals.get(proposalid).proposal_actions(
"Removals"
):
self.delete_member(networkid, propmember["MemberId"])
def list_proposal_votes(self, networkid, proposalid): def list_proposal_votes(self, networkid, proposalid):
# Check if network exists # Check if network exists
@ -754,7 +872,7 @@ class ManagedBlockchainBackend(BaseBackend):
"GetMember", "Member {0} not found.".format(memberid) "GetMember", "Member {0} not found.".format(memberid)
) )
## Cannot get a member than has been delted (it does show up in the list) # Cannot get a member than has been deleted (it does show up in the list)
if self.members.get(memberid).member_status == "DELETED": if self.members.get(memberid).member_status == "DELETED":
raise ResourceNotFoundException( raise ResourceNotFoundException(
"GetMember", "Member {0} not found.".format(memberid) "GetMember", "Member {0} not found.".format(memberid)
@ -791,6 +909,10 @@ class ManagedBlockchainBackend(BaseBackend):
# Remove network # Remove network
del self.networks[networkid] del self.networks[networkid]
# Remove any nodes associated
for nodeid in nodes_in_member(self.nodes, memberid):
del self.nodes[nodeid]
def update_member(self, networkid, memberid, logpublishingconfiguration): def update_member(self, networkid, memberid, logpublishingconfiguration):
# Check if network exists # Check if network exists
if networkid not in self.networks: if networkid not in self.networks:
@ -805,6 +927,173 @@ class ManagedBlockchainBackend(BaseBackend):
self.members.get(memberid).update(logpublishingconfiguration) self.members.get(memberid).update(logpublishingconfiguration)
def create_node(
self,
networkid,
memberid,
availabilityzone,
instancetype,
logpublishingconfiguration,
):
# Check if network exists
if networkid not in self.networks:
raise ResourceNotFoundException(
"CreateNode", "Network {0} not found.".format(networkid)
)
if memberid not in self.members:
raise ResourceNotFoundException(
"CreateNode", "Member {0} not found.".format(memberid)
)
networkedition = self.networks.get(networkid).network_edition
if (
number_of_nodes_in_member(self.nodes, memberid)
>= EDITIONS[networkedition]["MaxNodesPerMember"]
):
raise ResourceLimitExceededException(
"CreateNode",
"Maximum number of nodes exceeded in member {0}. The maximum number of nodes you can have in a member in a {1} Edition network is {2}".format(
memberid,
networkedition,
EDITIONS[networkedition]["MaxNodesPerMember"],
),
)
# See if the instance family is correct
correctinstancefamily = False
for chkinsttypepre in EDITIONS["STANDARD"]["AllowedNodeInstanceTypes"]:
chkinsttypepreregex = chkinsttypepre + ".*"
if re.match(chkinsttypepreregex, instancetype, re.IGNORECASE):
correctinstancefamily = True
break
if correctinstancefamily is False:
raise InvalidRequestException(
"CreateNode",
"Requested instance {0} isn't supported.".format(instancetype),
)
# Check for specific types for starter
if networkedition == "STARTER":
if instancetype not in EDITIONS["STARTER"]["AllowedNodeInstanceTypes"]:
raise InvalidRequestException(
"CreateNode",
"Instance type {0} is not supported with STARTER Edition networks.".format(
instancetype
),
)
# Simple availability zone check
chkregionpreregex = self.region_name + "[a-z]"
if re.match(chkregionpreregex, availabilityzone, re.IGNORECASE) is None:
raise InvalidRequestException(
"CreateNode", "Availability Zone is not valid",
)
node_id = get_node_id()
self.nodes[node_id] = ManagedBlockchainNode(
id=node_id,
networkid=networkid,
memberid=memberid,
availabilityzone=availabilityzone,
instancetype=instancetype,
logpublishingconfiguration=logpublishingconfiguration,
region=self.region_name,
)
# Return the node ID
d = {"NodeId": node_id}
return d
def list_nodes(self, networkid, memberid, status=None):
if networkid not in self.networks:
raise ResourceNotFoundException(
"ListNodes", "Network {0} not found.".format(networkid)
)
if memberid not in self.members:
raise ResourceNotFoundException(
"ListNodes", "Member {0} not found.".format(memberid)
)
# If member is deleted, cannot list nodes
if self.members.get(memberid).member_status == "DELETED":
raise ResourceNotFoundException(
"ListNodes", "Member {0} not found.".format(memberid)
)
nodesformember = []
for node_id in self.nodes:
if self.nodes.get(node_id).member_id == memberid and (
status is None or self.nodes.get(node_id).node_status == status
):
nodesformember.append(self.nodes[node_id])
return nodesformember
def get_node(self, networkid, memberid, nodeid):
# Check if network exists
if networkid not in self.networks:
raise ResourceNotFoundException(
"GetNode", "Network {0} not found.".format(networkid)
)
if memberid not in self.members:
raise ResourceNotFoundException(
"GetNode", "Member {0} not found.".format(memberid)
)
if nodeid not in self.nodes:
raise ResourceNotFoundException(
"GetNode", "Node {0} not found.".format(nodeid)
)
# Cannot get a node than has been deleted (it does show up in the list)
if self.nodes.get(nodeid).node_status == "DELETED":
raise ResourceNotFoundException(
"GetNode", "Node {0} not found.".format(nodeid)
)
return self.nodes.get(nodeid)
def delete_node(self, networkid, memberid, nodeid):
# Check if network exists
if networkid not in self.networks:
raise ResourceNotFoundException(
"DeleteNode", "Network {0} not found.".format(networkid)
)
if memberid not in self.members:
raise ResourceNotFoundException(
"DeleteNode", "Member {0} not found.".format(memberid)
)
if nodeid not in self.nodes:
raise ResourceNotFoundException(
"DeleteNode", "Node {0} not found.".format(nodeid)
)
self.nodes.get(nodeid).delete()
def update_node(self, networkid, memberid, nodeid, logpublishingconfiguration):
# Check if network exists
if networkid not in self.networks:
raise ResourceNotFoundException(
"UpdateNode", "Network {0} not found.".format(networkid)
)
if memberid not in self.members:
raise ResourceNotFoundException(
"UpdateNode", "Member {0} not found.".format(memberid)
)
if nodeid not in self.nodes:
raise ResourceNotFoundException(
"UpdateNode", "Node {0} not found.".format(nodeid)
)
self.nodes.get(nodeid).update(logpublishingconfiguration)
managedblockchain_backends = {} managedblockchain_backends = {}
for region in Session().get_available_regions("managedblockchain"): for region in Session().get_available_regions("managedblockchain"):

View File

@ -11,6 +11,7 @@ from .utils import (
proposalid_from_managedblockchain_url, proposalid_from_managedblockchain_url,
invitationid_from_managedblockchain_url, invitationid_from_managedblockchain_url,
memberid_from_managedblockchain_url, memberid_from_managedblockchain_url,
nodeid_from_managedblockchain_url,
) )
@ -324,3 +325,103 @@ class ManagedBlockchainResponse(BaseResponse):
self.backend.delete_member(network_id, member_id) self.backend.delete_member(network_id, member_id)
headers["content-type"] = "application/json" headers["content-type"] = "application/json"
return 200, headers, "" return 200, headers, ""
@classmethod
def node_response(clazz, request, full_url, headers):
region_name = region_from_managedblckchain_url(full_url)
response_instance = ManagedBlockchainResponse(
managedblockchain_backends[region_name]
)
return response_instance._node_response(request, full_url, headers)
def _node_response(self, request, full_url, headers):
method = request.method
if hasattr(request, "body"):
body = request.body
else:
body = request.data
parsed_url = urlparse(full_url)
querystring = parse_qs(parsed_url.query, keep_blank_values=True)
network_id = networkid_from_managedblockchain_url(full_url)
member_id = memberid_from_managedblockchain_url(full_url)
if method == "GET":
status = None
if "status" in querystring:
status = querystring["status"][0]
return self._all_nodes_response(network_id, member_id, status, headers)
elif method == "POST":
json_body = json.loads(body.decode("utf-8"))
return self._node_response_post(
network_id, member_id, json_body, querystring, headers
)
def _all_nodes_response(self, network_id, member_id, status, headers):
nodes = self.backend.list_nodes(network_id, member_id, status)
response = json.dumps({"Nodes": [node.to_dict() for node in nodes]})
headers["content-type"] = "application/json"
return 200, headers, response
def _node_response_post(
self, network_id, member_id, json_body, querystring, headers
):
instancetype = json_body["NodeConfiguration"]["InstanceType"]
availabilityzone = json_body["NodeConfiguration"]["AvailabilityZone"]
logpublishingconfiguration = json_body["NodeConfiguration"][
"LogPublishingConfiguration"
]
response = self.backend.create_node(
network_id,
member_id,
availabilityzone,
instancetype,
logpublishingconfiguration,
)
return 200, headers, json.dumps(response)
@classmethod
def nodeid_response(clazz, request, full_url, headers):
region_name = region_from_managedblckchain_url(full_url)
response_instance = ManagedBlockchainResponse(
managedblockchain_backends[region_name]
)
return response_instance._nodeid_response(request, full_url, headers)
def _nodeid_response(self, request, full_url, headers):
method = request.method
if hasattr(request, "body"):
body = request.body
else:
body = request.data
network_id = networkid_from_managedblockchain_url(full_url)
member_id = memberid_from_managedblockchain_url(full_url)
node_id = nodeid_from_managedblockchain_url(full_url)
if method == "GET":
return self._nodeid_response_get(network_id, member_id, node_id, headers)
elif method == "PATCH":
json_body = json.loads(body.decode("utf-8"))
return self._nodeid_response_patch(
network_id, member_id, node_id, json_body, headers
)
elif method == "DELETE":
return self._nodeid_response_delete(network_id, member_id, node_id, headers)
def _nodeid_response_get(self, network_id, member_id, node_id, headers):
node = self.backend.get_node(network_id, member_id, node_id)
response = json.dumps({"Node": node.get_format()})
headers["content-type"] = "application/json"
return 200, headers, response
def _nodeid_response_patch(
self, network_id, member_id, node_id, json_body, headers
):
logpublishingconfiguration = json_body
self.backend.update_node(
network_id, member_id, node_id, logpublishingconfiguration,
)
return 200, headers, ""
def _nodeid_response_delete(self, network_id, member_id, node_id, headers):
self.backend.delete_node(network_id, member_id, node_id)
headers["content-type"] = "application/json"
return 200, headers, ""

View File

@ -13,4 +13,7 @@ url_paths = {
"{0}/invitations/(?P<invitationid>[^/.]+)$": ManagedBlockchainResponse.invitationid_response, "{0}/invitations/(?P<invitationid>[^/.]+)$": ManagedBlockchainResponse.invitationid_response,
"{0}/networks/(?P<networkid>[^/.]+)/members$": ManagedBlockchainResponse.member_response, "{0}/networks/(?P<networkid>[^/.]+)/members$": ManagedBlockchainResponse.member_response,
"{0}/networks/(?P<networkid>[^/.]+)/members/(?P<memberid>[^/.]+)$": ManagedBlockchainResponse.memberid_response, "{0}/networks/(?P<networkid>[^/.]+)/members/(?P<memberid>[^/.]+)$": ManagedBlockchainResponse.memberid_response,
"{0}/networks/(?P<networkid>[^/.]+)/members/(?P<memberid>[^/.]+)/nodes$": ManagedBlockchainResponse.node_response,
"{0}/networks/(?P<networkid>[^/.]+)/members/(?P<memberid>[^/.]+)/nodes?(?P<querys>[^/.]+)$": ManagedBlockchainResponse.node_response,
"{0}/networks/(?P<networkid>[^/.]+)/members/(?P<memberid>[^/.]+)/nodes/(?P<nodeid>[^/.]+)$": ManagedBlockchainResponse.nodeid_response,
} }

View File

@ -104,3 +104,32 @@ def admin_password_ok(password):
return False return False
else: else:
return True return True
def nodeid_from_managedblockchain_url(full_url):
id_search = re.search("\/nd-[A-Z0-9]{26}", full_url, re.IGNORECASE)
return_id = None
if id_search:
return_id = id_search.group(0).replace("/", "")
return return_id
def get_node_id():
return "nd-" + "".join(
random.choice(string.ascii_uppercase + string.digits) for _ in range(26)
)
def number_of_nodes_in_member(nodes, memberid, node_status=None):
return len(
[
nodid
for nodid in nodes
if nodes.get(nodid).member_id == memberid
and (node_status is None or nodes.get(nodid).node_status == node_status)
]
)
def nodes_in_member(nodes, memberid):
return [nodid for nodid in nodes if nodes.get(nodid).member_id == memberid]

View File

@ -28,6 +28,17 @@ multiple_policy_actions = {
"Invitations": [{"Principal": "123456789012"}, {"Principal": "123456789013"}] "Invitations": [{"Principal": "123456789012"}, {"Principal": "123456789013"}]
} }
default_nodeconfiguration = {
"InstanceType": "bc.t3.small",
"AvailabilityZone": "us-east-1a",
"LogPublishingConfiguration": {
"Fabric": {
"ChaincodeLogs": {"Cloudwatch": {"Enabled": False}},
"PeerLogs": {"Cloudwatch": {"Enabled": False}},
}
},
}
def member_id_exist_in_list(members, memberid): def member_id_exist_in_list(members, memberid):
memberidxists = False memberidxists = False
@ -65,3 +76,12 @@ def select_invitation_id_for_network(invitations, networkid, status=None):
if status is None or invitation["Status"] == status: if status is None or invitation["Status"] == status:
invitationsfornetwork.append(invitation["InvitationId"]) invitationsfornetwork.append(invitation["InvitationId"])
return invitationsfornetwork return invitationsfornetwork
def node_id_exist_in_list(nodes, nodeid):
nodeidxists = False
for node in nodes:
if node["Id"] == nodeid:
nodeidxists = True
break
return nodeidxists

View File

@ -3,7 +3,6 @@ from __future__ import unicode_literals
import boto3 import boto3
import sure # noqa import sure # noqa
from moto.managedblockchain.exceptions import BadRequestException
from moto import mock_managedblockchain from moto import mock_managedblockchain
from . import helpers from . import helpers

View File

@ -3,7 +3,6 @@ from __future__ import unicode_literals
import boto3 import boto3
import sure # noqa import sure # noqa
from moto.managedblockchain.exceptions import BadRequestException
from moto import mock_managedblockchain from moto import mock_managedblockchain
from . import helpers from . import helpers
@ -204,7 +203,7 @@ def test_create_another_member_withopts():
@mock_managedblockchain @mock_managedblockchain
def test_create_and_delete_member(): def test_invite_and_remove_member():
conn = boto3.client("managedblockchain", region_name="us-east-1") conn = boto3.client("managedblockchain", region_name="us-east-1")
# Create network # Create network
@ -362,17 +361,14 @@ def test_create_too_many_members():
response["Invitations"], network_id, "PENDING" response["Invitations"], network_id, "PENDING"
)[0] )[0]
# Try to create member with already used invitation # Try to create one too many members
response = conn.create_member.when.called_with( response = conn.create_member.when.called_with(
InvitationId=invitation_id, InvitationId=invitation_id,
NetworkId=network_id, NetworkId=network_id,
MemberConfiguration=helpers.create_member_configuration( MemberConfiguration=helpers.create_member_configuration(
"testmember6", "admin", "Admin12345", False, "Test Member 6" "testmember6", "admin", "Admin12345", False, "Test Member 6"
), ),
).should.throw( ).should.throw(Exception, "is the maximum number of members allowed in a",)
Exception,
"5 is the maximum number of members allowed in a STARTER Edition network",
)
@mock_managedblockchain @mock_managedblockchain

View File

@ -3,7 +3,6 @@ from __future__ import unicode_literals
import boto3 import boto3
import sure # noqa import sure # noqa
from moto.managedblockchain.exceptions import BadRequestException
from moto import mock_managedblockchain from moto import mock_managedblockchain
from . import helpers from . import helpers

View File

@ -0,0 +1,477 @@
from __future__ import unicode_literals
import boto3
import sure # noqa
from moto import mock_managedblockchain
from . import helpers
@mock_managedblockchain
def test_create_node():
conn = boto3.client("managedblockchain", region_name="us-east-1")
# Create network
response = conn.create_network(
Name="testnetwork1",
Description="Test Network 1",
Framework="HYPERLEDGER_FABRIC",
FrameworkVersion="1.2",
FrameworkConfiguration=helpers.default_frameworkconfiguration,
VotingPolicy=helpers.default_votingpolicy,
MemberConfiguration=helpers.default_memberconfiguration,
)
network_id = response["NetworkId"]
member_id = response["MemberId"]
# Create a node
response = conn.create_node(
NetworkId=network_id,
MemberId=member_id,
NodeConfiguration=helpers.default_nodeconfiguration,
)
node_id = response["NodeId"]
# Find node in full list
response = conn.list_nodes(NetworkId=network_id, MemberId=member_id)
nodes = response["Nodes"]
nodes.should.have.length_of(1)
helpers.node_id_exist_in_list(nodes, node_id).should.equal(True)
# Get node details
response = conn.get_node(NetworkId=network_id, MemberId=member_id, NodeId=node_id)
response["Node"]["AvailabilityZone"].should.equal("us-east-1a")
# Update node
logconfignewenabled = not helpers.default_nodeconfiguration[
"LogPublishingConfiguration"
]["Fabric"]["ChaincodeLogs"]["Cloudwatch"]["Enabled"]
logconfignew = {
"Fabric": {"ChaincodeLogs": {"Cloudwatch": {"Enabled": logconfignewenabled}}}
}
conn.update_node(
NetworkId=network_id,
MemberId=member_id,
NodeId=node_id,
LogPublishingConfiguration=logconfignew,
)
# Delete node
conn.delete_node(
NetworkId=network_id, MemberId=member_id, NodeId=node_id,
)
# Find node in full list
response = conn.list_nodes(NetworkId=network_id, MemberId=member_id)
nodes = response["Nodes"]
nodes.should.have.length_of(1)
helpers.node_id_exist_in_list(nodes, node_id).should.equal(True)
# Find node in full list - only DELETED
response = conn.list_nodes(
NetworkId=network_id, MemberId=member_id, Status="DELETED"
)
nodes = response["Nodes"]
nodes.should.have.length_of(1)
helpers.node_id_exist_in_list(nodes, node_id).should.equal(True)
# But cannot get
response = conn.get_node.when.called_with(
NetworkId=network_id, MemberId=member_id, NodeId=node_id,
).should.throw(Exception, "Node {0} not found".format(node_id))
@mock_managedblockchain
def test_create_node_standard_edition():
conn = boto3.client("managedblockchain", region_name="us-east-1")
frameworkconfiguration = {"Fabric": {"Edition": "STANDARD"}}
response = conn.create_network(
Name="testnetwork1",
Description="Test Network 1",
Framework="HYPERLEDGER_FABRIC",
FrameworkVersion="1.2",
FrameworkConfiguration=frameworkconfiguration,
VotingPolicy=helpers.default_votingpolicy,
MemberConfiguration=helpers.default_memberconfiguration,
)
network_id = response["NetworkId"]
member_id = response["MemberId"]
# Instance type only allowed with standard edition
logconfigbad = dict(helpers.default_nodeconfiguration)
logconfigbad["InstanceType"] = "bc.t3.large"
response = conn.create_node(
NetworkId=network_id, MemberId=member_id, NodeConfiguration=logconfigbad,
)
node_id = response["NodeId"]
# Get node details
response = conn.get_node(NetworkId=network_id, MemberId=member_id, NodeId=node_id)
response["Node"]["InstanceType"].should.equal("bc.t3.large")
# Need another member so the network does not get deleted
# Create proposal
response = conn.create_proposal(
NetworkId=network_id,
MemberId=member_id,
Actions=helpers.default_policy_actions,
)
proposal_id = response["ProposalId"]
# Vote yes
response = conn.vote_on_proposal(
NetworkId=network_id,
ProposalId=proposal_id,
VoterMemberId=member_id,
Vote="YES",
)
# Get the invitation
response = conn.list_invitations()
invitation_id = response["Invitations"][0]["InvitationId"]
# Create the member
response = conn.create_member(
InvitationId=invitation_id,
NetworkId=network_id,
MemberConfiguration=helpers.create_member_configuration(
"testmember2", "admin", "Admin12345", False, "Test Member 2"
),
)
# Remove member 1 - should remove nodes
conn.delete_member(NetworkId=network_id, MemberId=member_id)
# Should now be an exception
response = conn.list_nodes.when.called_with(
NetworkId=network_id, MemberId=member_id,
).should.throw(Exception, "Member {0} not found".format(member_id))
@mock_managedblockchain
def test_create_too_many_nodes():
conn = boto3.client("managedblockchain", region_name="us-east-1")
# Create network
response = conn.create_network(
Name="testnetwork1",
Description="Test Network 1",
Framework="HYPERLEDGER_FABRIC",
FrameworkVersion="1.2",
FrameworkConfiguration=helpers.default_frameworkconfiguration,
VotingPolicy=helpers.default_votingpolicy,
MemberConfiguration=helpers.default_memberconfiguration,
)
network_id = response["NetworkId"]
member_id = response["MemberId"]
# Create a node
response = conn.create_node(
NetworkId=network_id,
MemberId=member_id,
NodeConfiguration=helpers.default_nodeconfiguration,
)
# Create another node
response = conn.create_node(
NetworkId=network_id,
MemberId=member_id,
NodeConfiguration=helpers.default_nodeconfiguration,
)
# Find node in full list
response = conn.list_nodes(NetworkId=network_id, MemberId=member_id)
nodes = response["Nodes"]
nodes.should.have.length_of(2)
# Try to create one too many nodes
response = conn.create_node.when.called_with(
NetworkId=network_id,
MemberId=member_id,
NodeConfiguration=helpers.default_nodeconfiguration,
).should.throw(
Exception, "Maximum number of nodes exceeded in member {0}".format(member_id),
)
@mock_managedblockchain
def test_create_node_badnetwork():
conn = boto3.client("managedblockchain", region_name="us-east-1")
response = conn.create_node.when.called_with(
NetworkId="n-ABCDEFGHIJKLMNOP0123456789",
MemberId="m-ABCDEFGHIJKLMNOP0123456789",
NodeConfiguration=helpers.default_nodeconfiguration,
).should.throw(Exception, "Network n-ABCDEFGHIJKLMNOP0123456789 not found")
@mock_managedblockchain
def test_create_node_badmember():
conn = boto3.client("managedblockchain", region_name="us-east-1")
response = conn.create_network(
Name="testnetwork1",
Description="Test Network 1",
Framework="HYPERLEDGER_FABRIC",
FrameworkVersion="1.2",
FrameworkConfiguration=helpers.default_frameworkconfiguration,
VotingPolicy=helpers.default_votingpolicy,
MemberConfiguration=helpers.default_memberconfiguration,
)
network_id = response["NetworkId"]
response = conn.create_node.when.called_with(
NetworkId=network_id,
MemberId="m-ABCDEFGHIJKLMNOP0123456789",
NodeConfiguration=helpers.default_nodeconfiguration,
).should.throw(Exception, "Member m-ABCDEFGHIJKLMNOP0123456789 not found")
@mock_managedblockchain
def test_create_node_badnodeconfig():
conn = boto3.client("managedblockchain", region_name="us-east-1")
response = conn.create_network(
Name="testnetwork1",
Description="Test Network 1",
Framework="HYPERLEDGER_FABRIC",
FrameworkVersion="1.2",
FrameworkConfiguration=helpers.default_frameworkconfiguration,
VotingPolicy=helpers.default_votingpolicy,
MemberConfiguration=helpers.default_memberconfiguration,
)
network_id = response["NetworkId"]
member_id = response["MemberId"]
# Incorrect instance type
logconfigbad = dict(helpers.default_nodeconfiguration)
logconfigbad["InstanceType"] = "foo"
response = conn.create_node.when.called_with(
NetworkId=network_id, MemberId=member_id, NodeConfiguration=logconfigbad,
).should.throw(Exception, "Requested instance foo isn't supported.")
# Incorrect instance type for edition
logconfigbad = dict(helpers.default_nodeconfiguration)
logconfigbad["InstanceType"] = "bc.t3.large"
response = conn.create_node.when.called_with(
NetworkId=network_id, MemberId=member_id, NodeConfiguration=logconfigbad,
).should.throw(
Exception,
"Instance type bc.t3.large is not supported with STARTER Edition networks",
)
# Incorrect availability zone
logconfigbad = dict(helpers.default_nodeconfiguration)
logconfigbad["AvailabilityZone"] = "us-east-11"
response = conn.create_node.when.called_with(
NetworkId=network_id, MemberId=member_id, NodeConfiguration=logconfigbad,
).should.throw(Exception, "Availability Zone is not valid")
@mock_managedblockchain
def test_list_nodes_badnetwork():
conn = boto3.client("managedblockchain", region_name="us-east-1")
response = conn.list_nodes.when.called_with(
NetworkId="n-ABCDEFGHIJKLMNOP0123456789",
MemberId="m-ABCDEFGHIJKLMNOP0123456789",
).should.throw(Exception, "Network n-ABCDEFGHIJKLMNOP0123456789 not found")
@mock_managedblockchain
def test_list_nodes_badmember():
conn = boto3.client("managedblockchain", region_name="us-east-1")
response = conn.create_network(
Name="testnetwork1",
Description="Test Network 1",
Framework="HYPERLEDGER_FABRIC",
FrameworkVersion="1.2",
FrameworkConfiguration=helpers.default_frameworkconfiguration,
VotingPolicy=helpers.default_votingpolicy,
MemberConfiguration=helpers.default_memberconfiguration,
)
network_id = response["NetworkId"]
response = conn.list_nodes.when.called_with(
NetworkId=network_id, MemberId="m-ABCDEFGHIJKLMNOP0123456789",
).should.throw(Exception, "Member m-ABCDEFGHIJKLMNOP0123456789 not found")
@mock_managedblockchain
def test_get_node_badnetwork():
conn = boto3.client("managedblockchain", region_name="us-east-1")
response = conn.get_node.when.called_with(
NetworkId="n-ABCDEFGHIJKLMNOP0123456789",
MemberId="m-ABCDEFGHIJKLMNOP0123456789",
NodeId="nd-ABCDEFGHIJKLMNOP0123456789",
).should.throw(Exception, "Network n-ABCDEFGHIJKLMNOP0123456789 not found")
@mock_managedblockchain
def test_get_node_badmember():
conn = boto3.client("managedblockchain", region_name="us-east-1")
response = conn.create_network(
Name="testnetwork1",
Description="Test Network 1",
Framework="HYPERLEDGER_FABRIC",
FrameworkVersion="1.2",
FrameworkConfiguration=helpers.default_frameworkconfiguration,
VotingPolicy=helpers.default_votingpolicy,
MemberConfiguration=helpers.default_memberconfiguration,
)
network_id = response["NetworkId"]
response = conn.get_node.when.called_with(
NetworkId=network_id,
MemberId="m-ABCDEFGHIJKLMNOP0123456789",
NodeId="nd-ABCDEFGHIJKLMNOP0123456789",
).should.throw(Exception, "Member m-ABCDEFGHIJKLMNOP0123456789 not found")
@mock_managedblockchain
def test_get_node_badnode():
conn = boto3.client("managedblockchain", region_name="us-east-1")
response = conn.create_network(
Name="testnetwork1",
Description="Test Network 1",
Framework="HYPERLEDGER_FABRIC",
FrameworkVersion="1.2",
FrameworkConfiguration=helpers.default_frameworkconfiguration,
VotingPolicy=helpers.default_votingpolicy,
MemberConfiguration=helpers.default_memberconfiguration,
)
network_id = response["NetworkId"]
member_id = response["MemberId"]
response = conn.get_node.when.called_with(
NetworkId=network_id,
MemberId=member_id,
NodeId="nd-ABCDEFGHIJKLMNOP0123456789",
).should.throw(Exception, "Node nd-ABCDEFGHIJKLMNOP0123456789 not found")
@mock_managedblockchain
def test_delete_node_badnetwork():
conn = boto3.client("managedblockchain", region_name="us-east-1")
response = conn.delete_node.when.called_with(
NetworkId="n-ABCDEFGHIJKLMNOP0123456789",
MemberId="m-ABCDEFGHIJKLMNOP0123456789",
NodeId="nd-ABCDEFGHIJKLMNOP0123456789",
).should.throw(Exception, "Network n-ABCDEFGHIJKLMNOP0123456789 not found")
@mock_managedblockchain
def test_delete_node_badmember():
conn = boto3.client("managedblockchain", region_name="us-east-1")
response = conn.create_network(
Name="testnetwork1",
Description="Test Network 1",
Framework="HYPERLEDGER_FABRIC",
FrameworkVersion="1.2",
FrameworkConfiguration=helpers.default_frameworkconfiguration,
VotingPolicy=helpers.default_votingpolicy,
MemberConfiguration=helpers.default_memberconfiguration,
)
network_id = response["NetworkId"]
response = conn.delete_node.when.called_with(
NetworkId=network_id,
MemberId="m-ABCDEFGHIJKLMNOP0123456789",
NodeId="nd-ABCDEFGHIJKLMNOP0123456789",
).should.throw(Exception, "Member m-ABCDEFGHIJKLMNOP0123456789 not found")
@mock_managedblockchain
def test_delete_node_badnode():
conn = boto3.client("managedblockchain", region_name="us-east-1")
response = conn.create_network(
Name="testnetwork1",
Description="Test Network 1",
Framework="HYPERLEDGER_FABRIC",
FrameworkVersion="1.2",
FrameworkConfiguration=helpers.default_frameworkconfiguration,
VotingPolicy=helpers.default_votingpolicy,
MemberConfiguration=helpers.default_memberconfiguration,
)
network_id = response["NetworkId"]
member_id = response["MemberId"]
response = conn.delete_node.when.called_with(
NetworkId=network_id,
MemberId=member_id,
NodeId="nd-ABCDEFGHIJKLMNOP0123456789",
).should.throw(Exception, "Node nd-ABCDEFGHIJKLMNOP0123456789 not found")
@mock_managedblockchain
def test_update_node_badnetwork():
conn = boto3.client("managedblockchain", region_name="us-east-1")
response = conn.update_node.when.called_with(
NetworkId="n-ABCDEFGHIJKLMNOP0123456789",
MemberId="m-ABCDEFGHIJKLMNOP0123456789",
NodeId="nd-ABCDEFGHIJKLMNOP0123456789",
LogPublishingConfiguration=helpers.default_nodeconfiguration[
"LogPublishingConfiguration"
],
).should.throw(Exception, "Network n-ABCDEFGHIJKLMNOP0123456789 not found")
@mock_managedblockchain
def test_update_node_badmember():
conn = boto3.client("managedblockchain", region_name="us-east-1")
response = conn.create_network(
Name="testnetwork1",
Description="Test Network 1",
Framework="HYPERLEDGER_FABRIC",
FrameworkVersion="1.2",
FrameworkConfiguration=helpers.default_frameworkconfiguration,
VotingPolicy=helpers.default_votingpolicy,
MemberConfiguration=helpers.default_memberconfiguration,
)
network_id = response["NetworkId"]
response = conn.update_node.when.called_with(
NetworkId=network_id,
MemberId="m-ABCDEFGHIJKLMNOP0123456789",
NodeId="nd-ABCDEFGHIJKLMNOP0123456789",
LogPublishingConfiguration=helpers.default_nodeconfiguration[
"LogPublishingConfiguration"
],
).should.throw(Exception, "Member m-ABCDEFGHIJKLMNOP0123456789 not found")
@mock_managedblockchain
def test_update_node_badnode():
conn = boto3.client("managedblockchain", region_name="us-east-1")
response = conn.create_network(
Name="testnetwork1",
Description="Test Network 1",
Framework="HYPERLEDGER_FABRIC",
FrameworkVersion="1.2",
FrameworkConfiguration=helpers.default_frameworkconfiguration,
VotingPolicy=helpers.default_votingpolicy,
MemberConfiguration=helpers.default_memberconfiguration,
)
network_id = response["NetworkId"]
member_id = response["MemberId"]
response = conn.update_node.when.called_with(
NetworkId=network_id,
MemberId=member_id,
NodeId="nd-ABCDEFGHIJKLMNOP0123456789",
LogPublishingConfiguration=helpers.default_nodeconfiguration[
"LogPublishingConfiguration"
],
).should.throw(Exception, "Node nd-ABCDEFGHIJKLMNOP0123456789 not found")

View File

@ -3,7 +3,6 @@ from __future__ import unicode_literals
import boto3 import boto3
import sure # noqa import sure # noqa
from moto.managedblockchain.exceptions import BadRequestException
from moto import mock_managedblockchain from moto import mock_managedblockchain
from . import helpers from . import helpers

View File

@ -7,7 +7,6 @@ import sure # noqa
from freezegun import freeze_time from freezegun import freeze_time
from nose import SkipTest from nose import SkipTest
from moto.managedblockchain.exceptions import BadRequestException
from moto import mock_managedblockchain, settings from moto import mock_managedblockchain, settings
from . import helpers from . import helpers
@ -186,6 +185,18 @@ def test_vote_on_proposal_yes_greater_than():
response["Proposal"]["NetworkId"].should.equal(network_id) response["Proposal"]["NetworkId"].should.equal(network_id)
response["Proposal"]["Status"].should.equal("IN_PROGRESS") response["Proposal"]["Status"].should.equal("IN_PROGRESS")
# Vote no with member 2
response = conn.vote_on_proposal(
NetworkId=network_id,
ProposalId=proposal_id,
VoterMemberId=member_id2,
Vote="NO",
)
# Get proposal details
response = conn.get_proposal(NetworkId=network_id, ProposalId=proposal_id)
response["Proposal"]["Status"].should.equal("REJECTED")
@mock_managedblockchain @mock_managedblockchain
def test_vote_on_proposal_no_greater_than(): def test_vote_on_proposal_no_greater_than():
@ -310,6 +321,47 @@ def test_vote_on_proposal_expiredproposal():
with freeze_time("2015-02-01 12:00:00"): with freeze_time("2015-02-01 12:00:00"):
# Vote yes - should set status to expired # Vote yes - should set status to expired
response = conn.vote_on_proposal.when.called_with(
NetworkId=network_id,
ProposalId=proposal_id,
VoterMemberId=member_id,
Vote="YES",
).should.throw(
Exception,
"Proposal {0} is expired and you cannot vote on it.".format(proposal_id),
)
# Get proposal details - should be EXPIRED
response = conn.get_proposal(NetworkId=network_id, ProposalId=proposal_id)
response["Proposal"]["Status"].should.equal("EXPIRED")
@mock_managedblockchain
def test_vote_on_proposal_status_check():
conn = boto3.client("managedblockchain", region_name="us-east-1")
# Create network
response = conn.create_network(
Name="testnetwork1",
Framework="HYPERLEDGER_FABRIC",
FrameworkVersion="1.2",
FrameworkConfiguration=helpers.default_frameworkconfiguration,
VotingPolicy=helpers.default_votingpolicy,
MemberConfiguration=helpers.default_memberconfiguration,
)
network_id = response["NetworkId"]
member_id = response["MemberId"]
# Create 2 more members
for counter in range(2, 4):
response = conn.create_proposal(
NetworkId=network_id,
MemberId=member_id,
Actions=helpers.default_policy_actions,
)
proposal_id = response["ProposalId"]
# Vote yes
response = conn.vote_on_proposal( response = conn.vote_on_proposal(
NetworkId=network_id, NetworkId=network_id,
ProposalId=proposal_id, ProposalId=proposal_id,
@ -317,9 +369,88 @@ def test_vote_on_proposal_expiredproposal():
Vote="YES", Vote="YES",
) )
# Get proposal details - should be EXPIRED memberidlist = [None, None, None]
response = conn.get_proposal(NetworkId=network_id, ProposalId=proposal_id) memberidlist[0] = member_id
response["Proposal"]["Status"].should.equal("EXPIRED") for counter in range(2, 4):
# Get the invitation
response = conn.list_invitations()
invitation_id = helpers.select_invitation_id_for_network(
response["Invitations"], network_id, "PENDING"
)[0]
# Create the member
response = conn.create_member(
InvitationId=invitation_id,
NetworkId=network_id,
MemberConfiguration=helpers.create_member_configuration(
"testmember" + str(counter),
"admin",
"Admin12345",
False,
"Test Member " + str(counter),
),
)
member_id = response["MemberId"]
memberidlist[counter - 1] = member_id
# Should be no more pending invitations
response = conn.list_invitations()
pendinginvs = helpers.select_invitation_id_for_network(
response["Invitations"], network_id, "PENDING"
)
pendinginvs.should.have.length_of(0)
# Create another proposal
response = conn.create_proposal(
NetworkId=network_id,
MemberId=member_id,
Actions=helpers.default_policy_actions,
)
proposal_id = response["ProposalId"]
# Vote yes with member 1
response = conn.vote_on_proposal(
NetworkId=network_id,
ProposalId=proposal_id,
VoterMemberId=memberidlist[0],
Vote="YES",
)
# Vote yes with member 2
response = conn.vote_on_proposal(
NetworkId=network_id,
ProposalId=proposal_id,
VoterMemberId=memberidlist[1],
Vote="YES",
)
# Get proposal details - now approved (2 yes, 1 outstanding)
response = conn.get_proposal(NetworkId=network_id, ProposalId=proposal_id)
response["Proposal"]["NetworkId"].should.equal(network_id)
response["Proposal"]["Status"].should.equal("APPROVED")
# Should be one pending invitation
response = conn.list_invitations()
pendinginvs = helpers.select_invitation_id_for_network(
response["Invitations"], network_id, "PENDING"
)
pendinginvs.should.have.length_of(1)
# Vote with member 3 - should throw an exception and not create a new invitation
response = conn.vote_on_proposal.when.called_with(
NetworkId=network_id,
ProposalId=proposal_id,
VoterMemberId=memberidlist[2],
Vote="YES",
).should.throw(Exception, "and you cannot vote on it")
# Should still be one pending invitation
response = conn.list_invitations()
pendinginvs = helpers.select_invitation_id_for_network(
response["Invitations"], network_id, "PENDING"
)
pendinginvs.should.have.length_of(1)
@mock_managedblockchain @mock_managedblockchain
@ -425,13 +556,21 @@ def test_vote_on_proposal_badvote():
def test_vote_on_proposal_alreadyvoted(): def test_vote_on_proposal_alreadyvoted():
conn = boto3.client("managedblockchain", region_name="us-east-1") conn = boto3.client("managedblockchain", region_name="us-east-1")
votingpolicy = {
"ApprovalThresholdPolicy": {
"ThresholdPercentage": 50,
"ProposalDurationInHours": 24,
"ThresholdComparator": "GREATER_THAN",
}
}
# Create network - need a good network # Create network - need a good network
response = conn.create_network( response = conn.create_network(
Name="testnetwork1", Name="testnetwork1",
Framework="HYPERLEDGER_FABRIC", Framework="HYPERLEDGER_FABRIC",
FrameworkVersion="1.2", FrameworkVersion="1.2",
FrameworkConfiguration=helpers.default_frameworkconfiguration, FrameworkConfiguration=helpers.default_frameworkconfiguration,
VotingPolicy=helpers.default_votingpolicy, VotingPolicy=votingpolicy,
MemberConfiguration=helpers.default_memberconfiguration, MemberConfiguration=helpers.default_memberconfiguration,
) )
network_id = response["NetworkId"] network_id = response["NetworkId"]
@ -465,7 +604,6 @@ def test_vote_on_proposal_alreadyvoted():
"testmember2", "admin", "Admin12345", False, "Test Member 2" "testmember2", "admin", "Admin12345", False, "Test Member 2"
), ),
) )
member_id2 = response["MemberId"]
# Create another proposal # Create another proposal
response = conn.create_proposal( response = conn.create_proposal(
@ -495,7 +633,10 @@ def test_vote_on_proposal_alreadyvoted():
ProposalId=proposal_id, ProposalId=proposal_id,
VoterMemberId=member_id, VoterMemberId=member_id,
Vote="YES", Vote="YES",
).should.throw(Exception, "Invalid request body") ).should.throw(
Exception,
"Member {0} has already voted on proposal {1}.".format(member_id, proposal_id),
)
@mock_managedblockchain @mock_managedblockchain