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:
Dave Enyeart 2023-03-07 04:43:10 -05:00 committed by GitHub
parent 199e290f5e
commit 488e74ed08
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 83 additions and 61 deletions

View file

@ -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)
}
@ -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)
}

View file

@ -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);
}
}

View file

@ -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"));

View file

@ -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");
}
}

View file

@ -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();

View file

@ -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",

View file

@ -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',
},
{

View file

@ -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": [

View file

@ -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);
}
}

View file

@ -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 {

View file

@ -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

View file

@ -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 \