mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-25 11:05:10 +00:00
Basic working version
This commit is contained in:
parent
41717d76f2
commit
ccc1045468
9 changed files with 410 additions and 165 deletions
|
|
@ -4,110 +4,44 @@
|
||||||
|
|
||||||
import { Context, Contract } from 'fabric-contract-api';
|
import { Context, Contract } from 'fabric-contract-api';
|
||||||
import { Car } from './car';
|
import { Car } from './car';
|
||||||
|
import {Ruleset} from './ruleset';
|
||||||
|
import {Validation} from './validation';
|
||||||
|
|
||||||
export class FabCar extends Contract {
|
export class FabCar extends Contract {
|
||||||
|
|
||||||
public async initLedger(ctx: Context) {
|
public currentContractNumber = 0;
|
||||||
console.info('============= START : Initialize Ledger ===========');
|
public async validateAge(ctx: Context, age: string) {
|
||||||
const cars: Car[] = [
|
const rulesets: Ruleset[] = [
|
||||||
{
|
{
|
||||||
color: 'blue',
|
minimumAge: 16,
|
||||||
make: 'Toyota',
|
name: 'First ruleset',
|
||||||
model: 'Prius',
|
|
||||||
owner: 'Tomoko',
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
color: 'red',
|
minimumAge: 18,
|
||||||
make: 'Ford',
|
name: 'Second ruleset',
|
||||||
model: 'Mustang',
|
|
||||||
owner: 'Brad',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
color: 'green',
|
|
||||||
make: 'Hyundai',
|
|
||||||
model: 'Tucson',
|
|
||||||
owner: 'Jin Soo',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
color: 'yellow',
|
|
||||||
make: 'Volkswagen',
|
|
||||||
model: 'Passat',
|
|
||||||
owner: 'Max',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
color: 'black',
|
|
||||||
make: 'Tesla',
|
|
||||||
model: 'S',
|
|
||||||
owner: 'Adriana',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
color: 'purple',
|
|
||||||
make: 'Peugeot',
|
|
||||||
model: '205',
|
|
||||||
owner: 'Michel',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
color: 'white',
|
|
||||||
make: 'Chery',
|
|
||||||
model: 'S22L',
|
|
||||||
owner: 'Aarav',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
color: 'violet',
|
|
||||||
make: 'Fiat',
|
|
||||||
model: 'Punto',
|
|
||||||
owner: 'Pari',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
color: 'indigo',
|
|
||||||
make: 'Tata',
|
|
||||||
model: 'Nano',
|
|
||||||
owner: 'Valeria',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
color: 'brown',
|
|
||||||
make: 'Holden',
|
|
||||||
model: 'Barina',
|
|
||||||
owner: 'Shotaro',
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
const validation: Validation = new Validation();
|
||||||
|
validation.id = this.getNewId();
|
||||||
|
const minimumAge: number = Math.max(rulesets[0].minimumAge, rulesets[1].minimumAge);
|
||||||
|
const ageToValidate = Number(age);
|
||||||
|
// Validate age
|
||||||
|
validation.isValid = (minimumAge <= ageToValidate);
|
||||||
|
|
||||||
for (let i = 0; i < cars.length; i++) {
|
await ctx.stub.putState('VALIDATION' + validation.id, Buffer.from(JSON.stringify(validation.toString())));
|
||||||
cars[i].docType = 'car';
|
console.log('Added <--> ', validation);
|
||||||
await ctx.stub.putState('CAR' + i, Buffer.from(JSON.stringify(cars[i])));
|
|
||||||
console.info('Added <--> ', cars[i]);
|
}
|
||||||
}
|
public async initLedger(ctx: Context) {
|
||||||
|
console.log('============= START : Initialize Ledger ===========');
|
||||||
console.info('============= END : Initialize Ledger ===========');
|
console.info('============= END : Initialize Ledger ===========');
|
||||||
}
|
}
|
||||||
|
|
||||||
public async queryCar(ctx: Context, carNumber: string): Promise<string> {
|
public async queryAllValidations(ctx: Context): Promise<string> {
|
||||||
const carAsBytes = await ctx.stub.getState(carNumber); // get the car from chaincode state
|
|
||||||
if (!carAsBytes || carAsBytes.length === 0) {
|
|
||||||
throw new Error(`${carNumber} does not exist`);
|
|
||||||
}
|
|
||||||
console.log(carAsBytes.toString());
|
|
||||||
return carAsBytes.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async createCar(ctx: Context, carNumber: string, make: string, model: string, color: string, owner: string) {
|
|
||||||
console.info('============= START : Create Car ===========');
|
|
||||||
|
|
||||||
const car: Car = {
|
|
||||||
color,
|
|
||||||
docType: 'car',
|
|
||||||
make,
|
|
||||||
model,
|
|
||||||
owner,
|
|
||||||
};
|
|
||||||
|
|
||||||
await ctx.stub.putState(carNumber, Buffer.from(JSON.stringify(car)));
|
|
||||||
console.info('============= END : Create Car ===========');
|
|
||||||
}
|
|
||||||
|
|
||||||
public async queryAllCars(ctx: Context): Promise<string> {
|
|
||||||
const startKey = '';
|
const startKey = '';
|
||||||
const endKey = '';
|
const endKey = '';
|
||||||
const allResults = [];
|
const allResults = [];
|
||||||
|
|
||||||
for await (const {key, value} of ctx.stub.getStateByRange(startKey, endKey)) {
|
for await (const {key, value} of ctx.stub.getStateByRange(startKey, endKey)) {
|
||||||
const strValue = Buffer.from(value).toString('utf8');
|
const strValue = Buffer.from(value).toString('utf8');
|
||||||
let record;
|
let record;
|
||||||
|
|
@ -122,19 +56,17 @@ export class FabCar extends Contract {
|
||||||
console.info(allResults);
|
console.info(allResults);
|
||||||
return JSON.stringify(allResults);
|
return JSON.stringify(allResults);
|
||||||
}
|
}
|
||||||
|
public async getValidationById(ctx: Context, validationId: string): Promise<string> {
|
||||||
public async changeCarOwner(ctx: Context, carNumber: string, newOwner: string) {
|
const validationrAsBytes = await ctx.stub.getState(validationId); // get the validation from chaincode state
|
||||||
console.info('============= START : changeCarOwner ===========');
|
if (!validationrAsBytes || validationrAsBytes.length === 0) {
|
||||||
|
throw new Error(`${validationId} does not exist`);
|
||||||
const carAsBytes = await ctx.stub.getState(carNumber); // get the car from chaincode state
|
|
||||||
if (!carAsBytes || carAsBytes.length === 0) {
|
|
||||||
throw new Error(`${carNumber} does not exist`);
|
|
||||||
}
|
}
|
||||||
const car: Car = JSON.parse(carAsBytes.toString());
|
console.log(validationrAsBytes.toString());
|
||||||
car.owner = newOwner;
|
return validationrAsBytes.toString();
|
||||||
|
}
|
||||||
await ctx.stub.putState(carNumber, Buffer.from(JSON.stringify(car)));
|
private getNewId(): number {
|
||||||
console.info('============= END : changeCarOwner ===========');
|
this.currentContractNumber++;
|
||||||
|
return this.currentContractNumber;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { FabCar } from './fabcar';
|
import {FabCar} from './fabcar';
|
||||||
export { FabCar } from './fabcar';
|
|
||||||
|
|
||||||
export const contracts: any[] = [ FabCar ];
|
export const contracts: any[] = [ FabCar ];
|
||||||
|
|
|
||||||
4
chaincode/fabcar/typescript/src/ruleset.ts
Normal file
4
chaincode/fabcar/typescript/src/ruleset.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
export class Ruleset {
|
||||||
|
public minimumAge: number;
|
||||||
|
public name: string;
|
||||||
|
}
|
||||||
8
chaincode/fabcar/typescript/src/validation.ts
Normal file
8
chaincode/fabcar/typescript/src/validation.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
export class Validation {
|
||||||
|
public executeDate: Date = new Date();
|
||||||
|
public id: number;
|
||||||
|
public isValid: boolean;
|
||||||
|
public toString(): string {
|
||||||
|
return '{id: ' + this.id + '; executeDate: ' + this.executeDate + '; isValid: ' + this.isValid + '}' ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,7 +10,7 @@ set -e
|
||||||
# don't rewrite paths for Windows Git Bash users
|
# don't rewrite paths for Windows Git Bash users
|
||||||
export MSYS_NO_PATHCONV=1
|
export MSYS_NO_PATHCONV=1
|
||||||
starttime=$(date +%s)
|
starttime=$(date +%s)
|
||||||
CC_SRC_LANGUAGE=${1:-"go"}
|
CC_SRC_LANGUAGE=${1:-"typescript"}
|
||||||
CC_SRC_LANGUAGE=`echo "$CC_SRC_LANGUAGE" | tr [:upper:] [:lower:]`
|
CC_SRC_LANGUAGE=`echo "$CC_SRC_LANGUAGE" | tr [:upper:] [:lower:]`
|
||||||
|
|
||||||
if [ "$CC_SRC_LANGUAGE" = "go" -o "$CC_SRC_LANGUAGE" = "golang" ] ; then
|
if [ "$CC_SRC_LANGUAGE" = "go" -o "$CC_SRC_LANGUAGE" = "golang" ] ; then
|
||||||
|
|
@ -45,30 +45,6 @@ cat <<EOF
|
||||||
Total setup execution time : $(($(date +%s) - starttime)) secs ...
|
Total setup execution time : $(($(date +%s) - starttime)) secs ...
|
||||||
|
|
||||||
Next, use the FabCar applications to interact with the deployed FabCar contract.
|
Next, use the FabCar applications to interact with the deployed FabCar contract.
|
||||||
The FabCar applications are available in multiple programming languages.
|
|
||||||
Follow the instructions for the programming language of your choice:
|
|
||||||
|
|
||||||
JavaScript:
|
|
||||||
|
|
||||||
Start by changing into the "javascript" directory:
|
|
||||||
cd javascript
|
|
||||||
|
|
||||||
Next, install all required packages:
|
|
||||||
npm install
|
|
||||||
|
|
||||||
Then run the following applications to enroll the admin user, and register a new user
|
|
||||||
called appUser which will be used by the other applications to interact with the deployed
|
|
||||||
FabCar contract:
|
|
||||||
node enrollAdmin
|
|
||||||
node registerUser
|
|
||||||
|
|
||||||
You can run the invoke application as follows. By default, the invoke application will
|
|
||||||
create a new car, but you can update the application to submit other transactions:
|
|
||||||
node invoke
|
|
||||||
|
|
||||||
You can run the query application as follows. By default, the query application will
|
|
||||||
return all cars, but you can update the application to evaluate other transactions:
|
|
||||||
node query
|
|
||||||
|
|
||||||
TypeScript:
|
TypeScript:
|
||||||
|
|
||||||
|
|
@ -95,34 +71,4 @@ TypeScript:
|
||||||
return all cars, but you can update the application to evaluate other transactions:
|
return all cars, but you can update the application to evaluate other transactions:
|
||||||
node dist/query
|
node dist/query
|
||||||
|
|
||||||
Java:
|
|
||||||
|
|
||||||
Start by changing into the "java" directory:
|
|
||||||
cd java
|
|
||||||
|
|
||||||
Then, install dependencies and run the test using:
|
|
||||||
mvn test
|
|
||||||
|
|
||||||
The test will invoke the sample client app which perform the following:
|
|
||||||
- Enroll admin and appUser and import them into the wallet (if they don't already exist there)
|
|
||||||
- Submit a transaction to create a new car
|
|
||||||
- Evaluate a transaction (query) to return details of this car
|
|
||||||
- Submit a transaction to change the owner of this car
|
|
||||||
- Evaluate a transaction (query) to return the updated details of this car
|
|
||||||
|
|
||||||
Go:
|
|
||||||
|
|
||||||
Start by changing into the "go" directory:
|
|
||||||
cd go
|
|
||||||
|
|
||||||
Then, install dependencies and run the test using:
|
|
||||||
go run fabcar.go
|
|
||||||
|
|
||||||
The test will invoke the sample client app which perform the following:
|
|
||||||
- Import user credentials into the wallet (if they don't already exist there)
|
|
||||||
- Submit a transaction to create a new car
|
|
||||||
- Evaluate a transaction (query) to return details of this car
|
|
||||||
- Submit a transaction to change the owner of this car
|
|
||||||
- Evaluate a transaction (query) to return the updated details of this car
|
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ import * as path from 'path';
|
||||||
async function main() {
|
async function main() {
|
||||||
try {
|
try {
|
||||||
// load the network configuration
|
// load the network configuration
|
||||||
const ccpPath = path.resolve(__dirname, '..', '..', '..','test-network','organizations','peerOrganizations','org1.example.com', 'connection-org1.json');
|
const ccpPath = path.resolve(__dirname, '..', '..', '..', 'test-network', 'organizations', 'peerOrganizations', 'org1.example.com', 'connection-org1.json');
|
||||||
const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
|
const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
|
||||||
|
|
||||||
// Create a new CA client for interacting with the CA.
|
// Create a new CA client for interacting with the CA.
|
||||||
|
|
|
||||||
50
fabcar/typescript/src/getValidationById.ts
Normal file
50
fabcar/typescript/src/getValidationById.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { Gateway, Wallets } from 'fabric-network';
|
||||||
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
try {
|
||||||
|
// load the network configuration
|
||||||
|
const ccpPath = path.resolve(__dirname, '..', '..', '..', 'test-network', 'organizations', 'peerOrganizations', 'org1.example.com', 'connection-org1.json');
|
||||||
|
const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
|
||||||
|
|
||||||
|
// Create a new file system based wallet for managing identities.
|
||||||
|
const walletPath = path.join(process.cwd(), 'wallet');
|
||||||
|
const wallet = await Wallets.newFileSystemWallet(walletPath);
|
||||||
|
console.log(`Wallet path: ${walletPath}`);
|
||||||
|
|
||||||
|
// Check to see if we've already enrolled the user.
|
||||||
|
const identity = await wallet.get('appUser');
|
||||||
|
if (!identity) {
|
||||||
|
console.log('An identity for the user "appUser" does not exist in the wallet');
|
||||||
|
console.log('Run the registerUser.ts application before retrying');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new gateway for connecting to our peer node.
|
||||||
|
const gateway = new Gateway();
|
||||||
|
await gateway.connect(ccp, { wallet, identity: 'appUser', discovery: { enabled: true, asLocalhost: true } });
|
||||||
|
|
||||||
|
// Get the network (channel) our contract is deployed to.
|
||||||
|
const network = await gateway.getNetwork('mychannel');
|
||||||
|
|
||||||
|
// Get the contract from the network.
|
||||||
|
const contract = network.getContract('DJINN');
|
||||||
|
|
||||||
|
// Evaluate the specified transaction.
|
||||||
|
// queryCar transaction - requires 1 argument, ex: ('queryCar', 'CAR4')
|
||||||
|
// queryAllCars transaction - requires no arguments, ex: ('queryAllCars')
|
||||||
|
const result = await contract.evaluateTransaction('getValidationById', 'VALIDATION2');
|
||||||
|
console.log(`Transaction has been evaluated, result is: ${result.toString()}`);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Failed to evaluate transaction: ${error}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
||||||
|
|
@ -2,16 +2,16 @@
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Wallets, X509Identity } from 'fabric-network';
|
|
||||||
import * as FabricCAServices from 'fabric-ca-client';
|
import * as FabricCAServices from 'fabric-ca-client';
|
||||||
import * as path from 'path';
|
import { Wallets, X509Identity } from 'fabric-network';
|
||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
|
import * as path from 'path';
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
try {
|
try {
|
||||||
// load the network configuration
|
// load the network configuration
|
||||||
const ccpPath = path.resolve(__dirname, '..', '..', '..','test-network','organizations','peerOrganizations','org1.example.com', 'connection-org1.json');
|
const ccpPath = path.resolve(__dirname, '..', '..', '..', 'test-network', 'organizations', 'peerOrganizations', 'org1.example.com', 'connection-org1.json');
|
||||||
let ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
|
const ccp = JSON.parse(fs.readFileSync(ccpPath, 'utf8'));
|
||||||
|
|
||||||
// Create a new CA client for interacting with the CA.
|
// Create a new CA client for interacting with the CA.
|
||||||
const caURL = ccp.certificateAuthorities['ca.org1.example.com'].url;
|
const caURL = ccp.certificateAuthorities['ca.org1.example.com'].url;
|
||||||
|
|
@ -38,8 +38,8 @@ async function main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// build a user object for authenticating with the CA
|
// build a user object for authenticating with the CA
|
||||||
const provider = wallet.getProviderRegistry().getProvider(adminIdentity.type);
|
const provider = wallet.getProviderRegistry().getProvider(adminIdentity.type);
|
||||||
const adminUser = await provider.getUserContext(adminIdentity, 'admin');
|
const adminUser = await provider.getUserContext(adminIdentity, 'admin');
|
||||||
|
|
||||||
// Register the user, enroll the user, and import the new identity into the wallet.
|
// Register the user, enroll the user, and import the new identity into the wallet.
|
||||||
const secret = await ca.register({ affiliation: 'org1.department1', enrollmentID: 'appUser', role: 'client' }, adminUser);
|
const secret = await ca.register({ affiliation: 'org1.department1', enrollmentID: 'appUser', role: 'client' }, adminUser);
|
||||||
|
|
|
||||||
306
install-fabric.sh
Executable file
306
install-fabric.sh
Executable file
|
|
@ -0,0 +1,306 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Copyright IBM Corp. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
#
|
||||||
|
|
||||||
|
# A modified version of the Fabric bootstrap script
|
||||||
|
# Use positional arguments to select componenets to install
|
||||||
|
#
|
||||||
|
# Has exactly the same functional power of bootstrap.sh
|
||||||
|
|
||||||
|
### START OF CODE GENERATED BY Argbash v2.9.0 ###
|
||||||
|
# Argbash is a bash code generator used to get arguments parsing right.
|
||||||
|
# Argbash is FREE SOFTWARE, see https://argbash.io for more info
|
||||||
|
# Generated online by https://argbash.io/generate
|
||||||
|
|
||||||
|
# Default values
|
||||||
|
_positionals=()
|
||||||
|
_arg_comp=('' )
|
||||||
|
|
||||||
|
# if version not passed in, default to latest released version
|
||||||
|
# if ca version not passed in, default to latest released version
|
||||||
|
_arg_fabric_version="2.4.4"
|
||||||
|
_arg_ca_version="1.5.5"
|
||||||
|
|
||||||
|
ARCH=$(echo "$(uname -s|tr '[:upper:]' '[:lower:]'|sed 's/mingw64_nt.*/windows/')-$(uname -m |sed 's/x86_64/amd64/g')" |sed 's/darwin-arm64/darwin-amd64/g')
|
||||||
|
MARCH=$(uname -m)
|
||||||
|
|
||||||
|
die()
|
||||||
|
{
|
||||||
|
local _ret="${2:-1}"
|
||||||
|
test "${_PRINT_HELP:-no}" = yes && print_help >&2
|
||||||
|
echo "$1" >&2
|
||||||
|
exit "${_ret}"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
begins_with_short_option()
|
||||||
|
{
|
||||||
|
local first_option all_short_options='fc'
|
||||||
|
first_option="${1:0:1}"
|
||||||
|
test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
print_help()
|
||||||
|
{
|
||||||
|
printf 'Usage: %s [-f|--fabric-version <arg>] [-c|--ca-version <arg>] <comp-1> [<comp-2>] ... [<comp-n>] ...\n' "$0"
|
||||||
|
printf '\t%s\n' "<comp> Component to install, one or more of docker | binary | samples | podman First letter of component also accepted; If none specified docker | binary | samples is assumed"
|
||||||
|
printf '\t%s\n' "-f, --fabric-version: FabricVersion (default: '2.4.4')"
|
||||||
|
printf '\t%s\n' "-c, --ca-version: Fabric CA Version (default: '1.5.5')"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
parse_commandline()
|
||||||
|
{
|
||||||
|
_positionals_count=0
|
||||||
|
while test $# -gt 0
|
||||||
|
do
|
||||||
|
_key="$1"
|
||||||
|
case "$_key" in
|
||||||
|
-f|--fabric-version)
|
||||||
|
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
|
||||||
|
_arg_fabric_version="$2"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--fabric-version=*)
|
||||||
|
_arg_fabric_version="${_key##--fabric-version=}"
|
||||||
|
;;
|
||||||
|
-f*)
|
||||||
|
_arg_fabric_version="${_key##-f}"
|
||||||
|
;;
|
||||||
|
-c|--ca-version)
|
||||||
|
test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1
|
||||||
|
_arg_ca_version="$2"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-h|--help)
|
||||||
|
print_help
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
-h*)
|
||||||
|
print_help
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
--ca-version=*)
|
||||||
|
_arg_ca_version="${_key##--ca-version=}"
|
||||||
|
;;
|
||||||
|
-c*)
|
||||||
|
_arg_ca_version="${_key##-c}"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
_last_positional="$1"
|
||||||
|
_positionals+=("$_last_positional")
|
||||||
|
_positionals_count=$((_positionals_count + 1))
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
handle_passed_args_count()
|
||||||
|
{
|
||||||
|
local _required_args_string="'comp'"
|
||||||
|
# test "${_positionals_count}" -ge 1 || _PRINT_HELP=yes die "FATAL ERROR: Not enough positional arguments - we require at least 1 (namely: $_required_args_string), but got only ${_positionals_count}." 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
assign_positional_args()
|
||||||
|
{
|
||||||
|
local _positional_name _shift_for=$1
|
||||||
|
_positional_names="_arg_comp "
|
||||||
|
_our_args=$((${#_positionals[@]} - 1))
|
||||||
|
for ((ii = 0; ii < _our_args; ii++))
|
||||||
|
do
|
||||||
|
_positional_names="$_positional_names _arg_comp[$((ii + 1))]"
|
||||||
|
done
|
||||||
|
|
||||||
|
shift "$_shift_for"
|
||||||
|
for _positional_name in ${_positional_names}
|
||||||
|
do
|
||||||
|
test $# -gt 0 || break
|
||||||
|
eval "$_positional_name=\${1}" || die "Error during argument parsing, possibly an Argbash bug." 1
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# End of ARGBASH code
|
||||||
|
|
||||||
|
# dockerPull() pulls docker images from fabric and chaincode repositories
|
||||||
|
# note, if a docker image doesn't exist for a requested release, it will simply
|
||||||
|
# be skipped, since this script doesn't terminate upon errors.
|
||||||
|
|
||||||
|
singleImagePull() {
|
||||||
|
#three_digit_image_tag is passed in, e.g. "1.4.7"
|
||||||
|
three_digit_image_tag=$1
|
||||||
|
shift
|
||||||
|
#two_digit_image_tag is derived, e.g. "1.4", especially useful as a local tag for two digit references to most recent baseos, ccenv, javaenv, nodeenv patch releases
|
||||||
|
two_digit_image_tag=$(echo "$three_digit_image_tag" | cut -d'.' -f1,2)
|
||||||
|
while [[ $# -gt 0 ]]
|
||||||
|
do
|
||||||
|
image_name="$1"
|
||||||
|
echo "====> hyperledger/fabric-$image_name:$three_digit_image_tag"
|
||||||
|
${CONTAINER_CLI} pull "hyperledger/fabric-$image_name:$three_digit_image_tag"
|
||||||
|
${CONTAINER_CLI} tag "hyperledger/fabric-$image_name:$three_digit_image_tag" "hyperledger/fabric-$image_name"
|
||||||
|
${CONTAINER_CLI} tag "hyperledger/fabric-$image_name:$three_digit_image_tag" "hyperledger/fabric-$image_name:$two_digit_image_tag"
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
cloneSamplesRepo() {
|
||||||
|
# clone (if needed) hyperledger/fabric-samples and checkout corresponding
|
||||||
|
# version to the binaries and docker images to be downloaded
|
||||||
|
if [ -d test-network ]; then
|
||||||
|
# if we are in the fabric-samples repo, checkout corresponding version
|
||||||
|
echo "==> Already in fabric-samples repo"
|
||||||
|
elif [ -d fabric-samples ]; then
|
||||||
|
# if fabric-samples repo already cloned and in current directory,
|
||||||
|
# cd fabric-samples
|
||||||
|
echo "===> Changing directory to fabric-samples"
|
||||||
|
cd fabric-samples
|
||||||
|
else
|
||||||
|
echo "===> Cloning hyperledger/fabric-samples repo"
|
||||||
|
git clone -b main https://github.com/hyperledger/fabric-samples.git && cd fabric-samples
|
||||||
|
fi
|
||||||
|
|
||||||
|
if GIT_DIR=.git git rev-parse v${VERSION} >/dev/null 2>&1; then
|
||||||
|
echo "===> Checking out v${VERSION} of hyperledger/fabric-samples"
|
||||||
|
git checkout -q v${VERSION}
|
||||||
|
else
|
||||||
|
echo "fabric-samples v${VERSION} does not exist, defaulting to main. fabric-samples main branch is intended to work with recent versions of fabric."
|
||||||
|
git checkout -q main
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# This will download the .tar.gz
|
||||||
|
download() {
|
||||||
|
local BINARY_FILE=$1
|
||||||
|
local URL=$2
|
||||||
|
local DEST_DIR=$(pwd)
|
||||||
|
echo "===> Downloading: " "${URL}"
|
||||||
|
if [ -d fabric-samples ]; then
|
||||||
|
DEST_DIR="fabric-samples"
|
||||||
|
fi
|
||||||
|
echo "===> Will unpack to: ${DEST_DIR}"
|
||||||
|
curl -L --retry 5 --retry-delay 3 "${URL}" | tar xz -C ${DEST_DIR}|| rc=$?
|
||||||
|
if [ -n "$rc" ]; then
|
||||||
|
echo "==> There was an error downloading the binary file."
|
||||||
|
return 22
|
||||||
|
else
|
||||||
|
echo "==> Done."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
pullBinaries() {
|
||||||
|
echo "===> Downloading version ${FABRIC_TAG} platform specific fabric binaries"
|
||||||
|
download "${BINARY_FILE}" "https://github.com/hyperledger/fabric/releases/download/v${VERSION}/${BINARY_FILE}"
|
||||||
|
if [ $? -eq 22 ]; then
|
||||||
|
echo
|
||||||
|
echo "------> ${FABRIC_TAG} platform specific fabric binary is not available to download <----"
|
||||||
|
echo
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "===> Downloading version ${CA_TAG} platform specific fabric-ca-client binary"
|
||||||
|
download "${CA_BINARY_FILE}" "https://github.com/hyperledger/fabric-ca/releases/download/v${CA_VERSION}/${CA_BINARY_FILE}"
|
||||||
|
if [ $? -eq 22 ]; then
|
||||||
|
echo
|
||||||
|
echo "------> ${CA_TAG} fabric-ca-client binary is not available to download (Available from 1.1.0-rc1) <----"
|
||||||
|
echo
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
pullImages() {
|
||||||
|
command -v ${CONTAINER_CLI} >& /dev/null
|
||||||
|
NODOCKER=$?
|
||||||
|
if [ "${NODOCKER}" == 0 ]; then
|
||||||
|
FABRIC_IMAGES=(peer orderer ccenv tools)
|
||||||
|
case "$VERSION" in
|
||||||
|
2.*)
|
||||||
|
FABRIC_IMAGES+=(baseos)
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "FABRIC_IMAGES:" "${FABRIC_IMAGES[@]}"
|
||||||
|
echo "===> Pulling fabric Images"
|
||||||
|
singleImagePull "${FABRIC_TAG}" "${FABRIC_IMAGES[@]}"
|
||||||
|
echo "===> Pulling fabric ca Image"
|
||||||
|
CA_IMAGE=(ca)
|
||||||
|
singleImagePull "${CA_TAG}" "${CA_IMAGE[@]}"
|
||||||
|
echo "===> List out hyperledger images"
|
||||||
|
${CONTAINER_CLI} images | grep hyperledger
|
||||||
|
else
|
||||||
|
echo "========================================================="
|
||||||
|
echo "${CONTAINER_CLI} not installed, bypassing download of Fabric images"
|
||||||
|
echo "========================================================="
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Main code starts here
|
||||||
|
parse_commandline "$@"
|
||||||
|
handle_passed_args_count
|
||||||
|
assign_positional_args 1 "${_positionals[@]}"
|
||||||
|
|
||||||
|
|
||||||
|
VERSION=$_arg_fabric_version
|
||||||
|
CA_VERSION=$_arg_ca_version
|
||||||
|
|
||||||
|
# prior to 1.2.0 architecture was determined by uname -m
|
||||||
|
if [[ $VERSION =~ ^1\.[0-1]\.* ]]; then
|
||||||
|
export FABRIC_TAG=${MARCH}-${VERSION}
|
||||||
|
export CA_TAG=${MARCH}-${CA_VERSION}
|
||||||
|
else
|
||||||
|
# starting with 1.2.0, multi-arch images will be default
|
||||||
|
: "${CA_TAG:="$CA_VERSION"}"
|
||||||
|
: "${FABRIC_TAG:="$VERSION"}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
BINARY_FILE=hyperledger-fabric-${ARCH}-${VERSION}.tar.gz
|
||||||
|
CA_BINARY_FILE=hyperledger-fabric-ca-${ARCH}-${CA_VERSION}.tar.gz
|
||||||
|
|
||||||
|
# if nothing has been specified, assume everything
|
||||||
|
if [[ ${_arg_comp[@]} =~ ^$ ]]; then
|
||||||
|
echo "No options selected: Getting all samples, binaries, and docker images"
|
||||||
|
echo "Abort now if not the intention"
|
||||||
|
sleep 3 # just to give a chance to abort if this wasn't intended
|
||||||
|
_arg_comp=('samples','binary','docker')
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Process samples first then the binaries. So if the fabric-samples dir is present
|
||||||
|
# the binaries will go there
|
||||||
|
if [[ "${_arg_comp[@]}" =~ (^| |,)s(amples)? ]]; then
|
||||||
|
echo
|
||||||
|
echo "Clone hyperledger/fabric-samples repo"
|
||||||
|
echo
|
||||||
|
cloneSamplesRepo
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${_arg_comp[@]}" =~ (^| |,)b(inary)? ]]; then
|
||||||
|
echo
|
||||||
|
echo "Pull Hyperledger Fabric binaries"
|
||||||
|
echo
|
||||||
|
pullBinaries
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${_arg_comp[@]}" =~ (^| |,)p(odman)? ]]; then
|
||||||
|
echo
|
||||||
|
echo "Pull Hyperledger Fabric podman images"
|
||||||
|
echo
|
||||||
|
CONTAINER_CLI=podman
|
||||||
|
pullImages
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${_arg_comp[@]}" =~ (^| |,)d(ocker)? ]]; then
|
||||||
|
echo
|
||||||
|
echo "Pull Hyperledger Fabric docker images"
|
||||||
|
echo
|
||||||
|
CONTAINER_CLI=docker
|
||||||
|
pullImages
|
||||||
|
fi
|
||||||
Loading…
Reference in a new issue