mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-17 15:35:09 +00:00
asset-transfer-basic CI improvements (#998)
* Return exit(1) if application-java fails If application-java fails, return an exit(1) code, so that callers such as Github Actions CI can detect the failure. Signed-off-by: David Enyeart <enyeart@us.ibm.com> * asset-transfer-basic CI improvements - Application failure should result in CI failure - Automatically remove wallet from prior runs - Fix chaincode name issues, allow chaincode name to be passed from CI - Fix appUser collisions (duplicate registration failures) - Fix key create collisions across apps (in cases where same chaincode is used for multiple apps) Signed-off-by: David Enyeart <enyeart@us.ibm.com> --------- Signed-off-by: David Enyeart <enyeart@us.ibm.com>
This commit is contained in:
parent
199e290f5e
commit
488e74ed08
12 changed files with 83 additions and 61 deletions
|
|
@ -24,7 +24,10 @@ func main() {
|
|||
log.Fatalf("Error setting DISCOVERY_AS_LOCALHOST environment variable: %v", err)
|
||||
}
|
||||
|
||||
wallet, err := gateway.NewFileSystemWallet("wallet")
|
||||
walletPath := "wallet"
|
||||
// remove any existing wallet from prior runs
|
||||
os.RemoveAll(walletPath)
|
||||
wallet, err := gateway.NewFileSystemWallet(walletPath)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create wallet: %v", err)
|
||||
}
|
||||
|
|
@ -55,23 +58,23 @@ func main() {
|
|||
}
|
||||
defer gw.Close()
|
||||
|
||||
channelName := "mychannel"
|
||||
if cname := os.Getenv("CHANNEL_NAME"); cname != "" {
|
||||
channelName = cname
|
||||
}
|
||||
channelName := "mychannel"
|
||||
if cname := os.Getenv("CHANNEL_NAME"); cname != "" {
|
||||
channelName = cname
|
||||
}
|
||||
|
||||
log.Println("--> Connecting to channel", channelName)
|
||||
log.Println("--> Connecting to channel", channelName)
|
||||
network, err := gw.GetNetwork(channelName)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get network: %v", err)
|
||||
}
|
||||
|
||||
chaincodeName := "basic"
|
||||
if ccname := os.Getenv("CHAINCODE_NAME"); ccname != "" {
|
||||
chaincodeName = ccname
|
||||
}
|
||||
chaincodeName := "basic"
|
||||
if ccname := os.Getenv("CHAINCODE_NAME"); ccname != "" {
|
||||
chaincodeName = ccname
|
||||
}
|
||||
|
||||
log.Println("--> Using chaincode", chaincodeName)
|
||||
log.Println("--> Using chaincode", chaincodeName)
|
||||
contract := network.GetContract(chaincodeName)
|
||||
|
||||
log.Println("--> Submit Transaction: InitLedger, function creates the initial set of assets on the ledger")
|
||||
|
|
@ -89,14 +92,14 @@ func main() {
|
|||
log.Println(string(result))
|
||||
|
||||
log.Println("--> Submit Transaction: CreateAsset, creates new asset with ID, color, owner, size, and appraisedValue arguments")
|
||||
result, err = contract.SubmitTransaction("CreateAsset", "asset13", "yellow", "5", "Tom", "1300")
|
||||
result, err = contract.SubmitTransaction("CreateAsset", "asset113", "yellow", "5", "Tom", "1300")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to Submit transaction: %v", err)
|
||||
}
|
||||
log.Println(string(result))
|
||||
|
||||
log.Println("--> Evaluate Transaction: ReadAsset, function returns an asset with a given assetID")
|
||||
result, err = contract.EvaluateTransaction("ReadAsset", "asset13")
|
||||
result, err = contract.EvaluateTransaction("ReadAsset", "asset113")
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to evaluate transaction: %v\n", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ import org.hyperledger.fabric.gateway.Wallets;
|
|||
|
||||
public class App {
|
||||
|
||||
private static final String CHANNEL_NAME = System.getenv().getOrDefault("CHANNEL_NAME", "mychannel");
|
||||
private static final String CHAINCODE_NAME = System.getenv().getOrDefault("CHAINCODE_NAME", "basic");
|
||||
|
||||
static {
|
||||
System.setProperty("org.hyperledger.fabric.sdk.service_discovery.as_localhost", "true");
|
||||
}
|
||||
|
|
@ -33,7 +36,7 @@ public class App {
|
|||
Path networkConfigPath = Paths.get("..", "..", "test-network", "organizations", "peerOrganizations", "org1.example.com", "connection-org1.yaml");
|
||||
|
||||
Gateway.Builder builder = Gateway.createBuilder();
|
||||
builder.identity(wallet, "appUser").networkConfig(networkConfigPath).discovery(true);
|
||||
builder.identity(wallet, "javaAppUser").networkConfig(networkConfigPath).discovery(true);
|
||||
return builder.connect();
|
||||
}
|
||||
|
||||
|
|
@ -50,8 +53,8 @@ public class App {
|
|||
try (Gateway gateway = connect()) {
|
||||
|
||||
// get the network and contract
|
||||
Network network = gateway.getNetwork("mychannel");
|
||||
Contract contract = network.getContract("basic");
|
||||
Network network = gateway.getNetwork(CHANNEL_NAME);
|
||||
Contract contract = network.getContract(CHAINCODE_NAME);
|
||||
|
||||
byte[] result;
|
||||
|
||||
|
|
@ -63,14 +66,14 @@ public class App {
|
|||
System.out.println("Evaluate Transaction: GetAllAssets, result: " + new String(result));
|
||||
|
||||
System.out.println("\n");
|
||||
System.out.println("Submit Transaction: CreateAsset asset13");
|
||||
// CreateAsset creates an asset with ID asset13, color yellow, owner Tom, size 5 and appraisedValue of 1300
|
||||
contract.submitTransaction("CreateAsset", "asset13", "yellow", "5", "Tom", "1300");
|
||||
System.out.println("Submit Transaction: CreateAsset asset213");
|
||||
// CreateAsset creates an asset with ID asset213, color yellow, owner Tom, size 5 and appraisedValue of 1300
|
||||
contract.submitTransaction("CreateAsset", "asset213", "yellow", "5", "Tom", "1300");
|
||||
|
||||
System.out.println("\n");
|
||||
System.out.println("Evaluate Transaction: ReadAsset asset13");
|
||||
System.out.println("Evaluate Transaction: ReadAsset asset213");
|
||||
// ReadAsset returns an asset with given assetID
|
||||
result = contract.evaluateTransaction("ReadAsset", "asset13");
|
||||
result = contract.evaluateTransaction("ReadAsset", "asset213");
|
||||
System.out.println("result: " + new String(result));
|
||||
|
||||
System.out.println("\n");
|
||||
|
|
@ -110,6 +113,7 @@ public class App {
|
|||
}
|
||||
catch(Exception e){
|
||||
System.err.println(e);
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,9 @@ package application.java;
|
|||
import java.nio.file.Paths;
|
||||
import java.util.Properties;
|
||||
|
||||
import java.io.File;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import org.hyperledger.fabric.gateway.Wallet;
|
||||
import org.hyperledger.fabric.gateway.Wallets;
|
||||
import org.hyperledger.fabric.gateway.Identities;
|
||||
|
|
@ -32,6 +35,9 @@ public class EnrollAdmin {
|
|||
CryptoSuite cryptoSuite = CryptoSuiteFactory.getDefault().getCryptoSuite();
|
||||
caClient.setCryptoSuite(cryptoSuite);
|
||||
|
||||
// Delete wallet if it exists from prior runs
|
||||
FileUtils.deleteDirectory(new File("wallet"));
|
||||
|
||||
// Create a wallet for managing identities
|
||||
Wallet wallet = Wallets.newFileSystemWallet(Paths.get("wallet"));
|
||||
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ public class RegisterUser {
|
|||
Wallet wallet = Wallets.newFileSystemWallet(Paths.get("wallet"));
|
||||
|
||||
// Check to see if we've already enrolled the user.
|
||||
if (wallet.get("appUser") != null) {
|
||||
System.out.println("An identity for the user \"appUser\" already exists in the wallet");
|
||||
if (wallet.get("javaAppUser") != null) {
|
||||
System.out.println("An identity for the user \"javaAppUser\" already exists in the wallet");
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -94,14 +94,14 @@ public class RegisterUser {
|
|||
};
|
||||
|
||||
// Register the user, enroll the user, and import the new identity into the wallet.
|
||||
RegistrationRequest registrationRequest = new RegistrationRequest("appUser");
|
||||
RegistrationRequest registrationRequest = new RegistrationRequest("javaAppUser");
|
||||
registrationRequest.setAffiliation("org1.department1");
|
||||
registrationRequest.setEnrollmentID("appUser");
|
||||
registrationRequest.setEnrollmentID("javaAppUser");
|
||||
String enrollmentSecret = caClient.register(registrationRequest, admin);
|
||||
Enrollment enrollment = caClient.enroll("appUser", enrollmentSecret);
|
||||
Enrollment enrollment = caClient.enroll("javaAppUser", enrollmentSecret);
|
||||
Identity user = Identities.newX509Identity("Org1MSP", enrollment);
|
||||
wallet.put("appUser", user);
|
||||
System.out.println("Successfully enrolled user \"appUser\" and imported it into the wallet");
|
||||
wallet.put("javaAppUser", user);
|
||||
System.out.println("Successfully enrolled user \"javaAppUser\" and imported it into the wallet");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,11 +12,12 @@ const path = require('path');
|
|||
const { buildCAClient, registerAndEnrollUser, enrollAdmin } = require('../../test-application/javascript/CAUtil.js');
|
||||
const { buildCCPOrg1, buildWallet } = require('../../test-application/javascript/AppUtil.js');
|
||||
|
||||
const channelName = 'mychannel';
|
||||
const chaincodeName = 'basic';
|
||||
const channelName = process.env.CHANNEL_NAME || 'mychannel';
|
||||
const chaincodeName = process.env.CHAINCODE_NAME || 'basic';
|
||||
|
||||
const mspOrg1 = 'Org1MSP';
|
||||
const walletPath = path.join(__dirname, 'wallet');
|
||||
const org1UserId = 'appUser';
|
||||
const org1UserId = 'javascriptAppUser';
|
||||
|
||||
function prettyJSONString(inputString) {
|
||||
return JSON.stringify(JSON.parse(inputString), null, 2);
|
||||
|
|
@ -128,14 +129,14 @@ async function main() {
|
|||
// This will be sent to both peers and if both peers endorse the transaction, the endorsed proposal will be sent
|
||||
// to the orderer to be committed by each of the peer's to the channel ledger.
|
||||
console.log('\n--> Submit Transaction: CreateAsset, creates new asset with ID, color, owner, size, and appraisedValue arguments');
|
||||
result = await contract.submitTransaction('CreateAsset', 'asset13', 'yellow', '5', 'Tom', '1300');
|
||||
result = await contract.submitTransaction('CreateAsset', 'asset313', 'yellow', '5', 'Tom', '1300');
|
||||
console.log('*** Result: committed');
|
||||
if (`${result}` !== '') {
|
||||
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
|
||||
}
|
||||
|
||||
console.log('\n--> Evaluate Transaction: ReadAsset, function returns an asset with a given assetID');
|
||||
result = await contract.evaluateTransaction('ReadAsset', 'asset13');
|
||||
result = await contract.evaluateTransaction('ReadAsset', 'asset313');
|
||||
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
|
||||
|
||||
console.log('\n--> Evaluate Transaction: AssetExists, function returns "true" if an asset with given assetID exist');
|
||||
|
|
@ -174,7 +175,9 @@ async function main() {
|
|||
}
|
||||
} catch (error) {
|
||||
console.error(`******** FAILED to run the application: ${error}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
main();
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
"version": "1.0.0",
|
||||
"description": "Asset-transfer-basic application implemented in JavaScript",
|
||||
"engines": {
|
||||
"node": ">=12",
|
||||
"npm": ">=5"
|
||||
"node": ">=14.14",
|
||||
"npm": ">=6"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint *.js",
|
||||
|
|
|
|||
|
|
@ -53,13 +53,13 @@ const transactionsToSend: TransactionToSendFormat[] = [
|
|||
{
|
||||
request: 'submit',
|
||||
txName: 'CreateAsset',
|
||||
txArgs: ['asset13', 'yellow', '5', 'Tom', '1300'],
|
||||
txArgs: ['asset513', 'yellow', '5', 'Tom', '1300'],
|
||||
description: '\n--> Submit Transaction: CreateAsset, creates new asset with ID, color, owner, size, and appraisedValue arguments',
|
||||
},
|
||||
{
|
||||
request: 'evaluate',
|
||||
txName: 'ReadAsset',
|
||||
txArgs: ['asset13'],
|
||||
txArgs: ['asset513'],
|
||||
description: '\n--> Evaluate Transaction: ReadAsset, function returns an asset with a given assetID',
|
||||
},
|
||||
{
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"engines": {
|
||||
"node": ">=12",
|
||||
"npm": ">=5"
|
||||
"node": ">=14.14",
|
||||
"npm": ">=6"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "tslint -c tslint.json 'src/**/*.ts'",
|
||||
|
|
@ -24,9 +24,9 @@
|
|||
"fabric-network": "^2.2.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^12.20.55",
|
||||
"@types/node": "^14.17.32",
|
||||
"tslint": "^5.11.0",
|
||||
"typescript": "^3.1.6"
|
||||
"typescript": "~4.9.4"
|
||||
},
|
||||
"nyc": {
|
||||
"extension": [
|
||||
|
|
|
|||
|
|
@ -8,11 +8,12 @@ import * as path from 'path';
|
|||
import { buildCCPOrg1, buildWallet, prettyJSONString } from './utils//AppUtil';
|
||||
import { buildCAClient, enrollAdmin, registerAndEnrollUser } from './utils/CAUtil';
|
||||
|
||||
const channelName = 'mychannel';
|
||||
const chaincodeName = 'basic';
|
||||
const channelName = process.env.CHANNEL_NAME || 'mychannel';
|
||||
const chaincodeName = process.env.CHAINCODE_NAME || 'basic';
|
||||
|
||||
const mspOrg1 = 'Org1MSP';
|
||||
const walletPath = path.join(__dirname, 'wallet');
|
||||
const org1UserId = 'appUser';
|
||||
const org1UserId = 'typescriptAppUser';
|
||||
|
||||
// pre-requisites:
|
||||
// - fabric-sample two organization test-network setup with two peers, ordering service,
|
||||
|
|
@ -121,11 +122,11 @@ async function main() {
|
|||
// This will be sent to both peers and if both peers endorse the transaction, the endorsed proposal will be sent
|
||||
// to the orderer to be committed by each of the peer's to the channel ledger.
|
||||
console.log('\n--> Submit Transaction: CreateAsset, creates new asset with ID, color, owner, size, and appraisedValue arguments');
|
||||
await contract.submitTransaction('CreateAsset', 'asset13', 'yellow', '5', 'Tom', '1300');
|
||||
await contract.submitTransaction('CreateAsset', 'asset413', 'yellow', '5', 'Tom', '1300');
|
||||
console.log('*** Result: committed');
|
||||
|
||||
console.log('\n--> Evaluate Transaction: ReadAsset, function returns an asset with a given assetID');
|
||||
result = await contract.evaluateTransaction('ReadAsset', 'asset13');
|
||||
result = await contract.evaluateTransaction('ReadAsset', 'asset413');
|
||||
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
|
||||
|
||||
console.log('\n--> Evaluate Transaction: AssetExists, function returns "true" if an asset with given assetID exist');
|
||||
|
|
@ -164,6 +165,7 @@ async function main() {
|
|||
}
|
||||
} catch (error) {
|
||||
console.error(`******** FAILED to run the application: ${error}`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,10 @@ const buildWallet = async (walletPath: string): Promise<Wallet> => {
|
|||
// Create a new wallet : Note that wallet is for managing identities.
|
||||
let wallet: Wallet;
|
||||
if (walletPath) {
|
||||
|
||||
// remove any pre-existing wallet from prior runs
|
||||
fs.rmSync(walletPath, { recursive: true, force: true });
|
||||
|
||||
wallet = await Wallets.newFileSystemWallet(walletPath);
|
||||
console.log(`Built a file system wallet at ${walletPath}`);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ createNetwork
|
|||
|
||||
# Run Go application
|
||||
print "Initializing Go application"
|
||||
export CHAINCODE_NAME=basic_go
|
||||
export CHAINCODE_NAME=basic_${CHAINCODE_LANGUAGE}_for_go_app
|
||||
deployChaincode
|
||||
pushd ../asset-transfer-basic/application-go
|
||||
print "Executing AssetTransfer.go"
|
||||
|
|
@ -46,7 +46,7 @@ popd
|
|||
|
||||
# Run Java application
|
||||
print "Initializing Java application"
|
||||
export CHAINCODE_NAME=basic_java
|
||||
export CHAINCODE_NAME=basic_${CHAINCODE_LANGUAGE}_for_java_app
|
||||
deployChaincode
|
||||
pushd ../asset-transfer-basic/application-java
|
||||
print "Executing Gradle Run"
|
||||
|
|
@ -55,7 +55,7 @@ popd
|
|||
|
||||
# Run Javascript application
|
||||
print "Initializing Javascript application"
|
||||
export CHAINCODE_NAME=basic_javascript
|
||||
export CHAINCODE_NAME=basic_${CHAINCODE_LANGUAGE}_for_javascript_app
|
||||
deployChaincode
|
||||
pushd ../asset-transfer-basic/application-javascript
|
||||
npm install
|
||||
|
|
@ -65,7 +65,7 @@ popd
|
|||
|
||||
# Run typescript application
|
||||
print "Initializing Typescript application"
|
||||
export CHAINCODE_NAME=basic_typescript
|
||||
export CHAINCODE_NAME=basic_${CHAINCODE_LANGUAGE}_for_typescript_app
|
||||
deployChaincode
|
||||
pushd ../asset-transfer-basic/application-typescript
|
||||
npm install
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ nginx:
|
|||
#!/bin/bash
|
||||
kubectl apply -k https://github.com/hyperledger-labs/fabric-operator.git/config/ingress/{{ cluster_runtime }}
|
||||
|
||||
sleep 10
|
||||
sleep 20
|
||||
|
||||
kubectl wait --namespace ingress-nginx \
|
||||
--for=condition=ready pod \
|
||||
|
|
|
|||
Loading…
Reference in a new issue