Skip to content

Commit

Permalink
external chaincode service doc update
Browse files Browse the repository at this point in the history
- Address doc change requests from previous iteration

Streamline doc to focus on external chaincode service documentation and
remove external builder and launcher details

FAB-14083

Signed-off-by: muralisr <srinivasan.muralidharan99@gmail.com>
  • Loading branch information
muralisrini authored and sykesm committed Jan 7, 2020
1 parent 12a2fd3 commit 269cb04
Showing 1 changed file with 61 additions and 83 deletions.
144 changes: 61 additions & 83 deletions docs/source/cc_service.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,59 +19,25 @@ With the Fabric v2.0 chaincode lifecycle, chaincode is [packaged](./cc_launcher.

```sh
$ tar xvfz myccpackage.tgz
code.tar.gz
metadata.json
code.tar.gz
```

### code.tar.gz archive requirements

The `code.tar.gz` archive must include connection information for the chaincode endpoint. This information is packaged into `connection.json` in the `/bin/release` step (see below). In this example we package `connection.json` directly in `code.tar.gz` so the `release` step can just copy it over.

* **address** - chaincode server endpoint accessible from peer. Must be specified in “<host>:<port>” format.
* **dial_timeout** - interval to wait for connection to complete. Specified as a string qualified with units (examples : "10s", "500ms", "1m"). Default is “3s” if not specified.
* **tls_required** - true or false. If false "client_auth_required", "key_path", "cert_path", "root_cert_path" are not required. Default is “true”.
* **client_auth_required** - if true then you need to specify "key_path" and "cert_path" for client authentication. Default is false. Ignored if tls_required is false.
* **key_path** - path to the key file. This path is relative to the “release directory” (see “release” below). Required if client_auth_required is true. Ignored if tls_required is false.
* **cert_path** - path to the certificate file. This path is relative to the “release directory” (see “release” below). Required if client_auth_required is true. Ignored if tls_required is false.
* **root_cert_path** - path to the root cert for authenticating the server. Required when tls_required is set to true.

For example:
```json
{
"address": "your.chaincode.host.com:9999",
"dial_timeout": "10s",
"tls_required": true,
"client_auth_required": "true",
"key_path": "path/rooted/in/release/directory/key.pem",
"cert_path": "path/rooted/in/release/directory/cert.pem",
"root_cert_path": "path/rooted/in/release/directory/rootcert.pem"
}
```

**Note:** The TLS files can be placed anywhere in the `code.tar.gz` archive because the directory of the contents of the `.tar.gz` will be provided to the external chaincode builder scripts. The `/bin/release` script, described later in this document, should move the files to the appropriate paths relative to the release directory. In the future, the PEM may be included in the JSON itself.

### metadata.json requirements
The chaincode package should be used to provide two pieces of information to the external builder and launcher process
* identify if the chaincode is an external service. The `bin/detect` section describes an approach using the `metadata.json` file
* provide chaincode endpoint information in a `connection.json` file placed in the release directory. The `bin/run` section describes the `connection.json` file

When using chaincode as an external service, you can set the `type` field in `metadata.json` to `external` in order to indicate that the external service is being used. For example:

```json
{"path":"","type":"external","label":"mycc"}
```
There is plenty of flexibility to gathering the above information. The sample scripts in the [External builder and launcher sample scripts](#external-builder-and-launcher-sample-scripts) illustrate a simple approach to providing the information.

## Configuring a peer to process external chaincode

If you have reviewed the external build and chaincode launcher documentation then these steps will be familiar to you. We leverage those scripts to define the external chaincode service information. These scripts are located on the peer file system that is accessible to the peer process from the `core.yaml` file in the `externalBuilders` element under the `chaincode` stanza. An example is included in the steps which follow.

### Create the set of external builder and launcher scripts on the peer

In order to configure chaincode as an external service, you must use the scripts as follows:
* **detect** - examines the chaincode package and accept if metadata.json `type` is set to `external`.
* **build** - builds the chaincode and places the build artifacts in the `BUILD_OUTPUT_DIR`. For chaincode as an external service, the peer does not build the chaincode. Instead, the script extracts the chaincode endpoint information in the `connection.json` file and other artifacts from the `code.tar.gz` and places them in the specified location.
* **release** - copies the built artifacts (in our case the `connection.json` file) to a specified release location.
In this section we go over the configuration needed
* to detect if the chaincode package identifies an external chaincode service
* to create the `connection.json` file in the release directory

You may notice that the external builder and launcher `bin/run` script is not required for the chaincode as an external service.
### Modify the peer core.yaml to include the externalBuilder

The scripts that are required to exist in the peer `/bin` directory:
Assume the scripts are on the peer in the `bin` directory as follows
```
<fully qualified path on the peer's env>
└── bin
Expand All @@ -80,77 +46,68 @@ The scripts that are required to exist in the peer `/bin` directory:
└── release
```

### Modify the peer core.yaml to include the externalBuilder

Finally, in order for the peer to use the external builder and launcher scripts, you need to modify the `chaincode` stanza of the peer `core.yaml` file to include the `externalBuilders` configuration element.
Modify the `chaincode` stanza of the peer `core.yaml` file to include the `externalBuilders` configuration element:

```yaml
externalBuilders:
- name: myexternal
path: <fully qualified path on the peer's env>
```

## External builder and launcher sample scripts
### External builder and launcher sample scripts

To help understand what each script needs to contain to work with the chaincode as an external service, this section contains samples of `bin/detect` `bin/build`, `bin/release`, and `bin/run` scripts.

To help understand what each script needs to contain to work with the chaincode as an external service, this section contains samples of `bin/detect` `bin/build`, `/bin/release`, and `bin/run` scripts.
**Note:** These samples use the `jq` command to parse json. You can run `jq --version` to check if you have it installed. Otherwise, install `jq` or suitably modify the scripts.

**Note:** These samples use the `jq` command to parse json. You can run `jq --version` to check if you have it installed. Otherwise, install `jq` or suitably modify the scripts yourself.
#### bin/detect

### /bin/detect
The `bin/detect script` is responsible for determining whether or not a buildpack should be used to build a chaincode package and launch it. For chaincode as an external service, the sample script looks for a `type` property set to `external` in the `metadata.json` file:

```json
{"path":"","type":"external","label":"mycc"}
```

The `bin/detect script` is responsible for determining whether or not a buildpack should be used to build a chaincode package and launch it. For chaincode as an external service, the script should detect that metadata.json `type` is set to `external`. The peer invokes detect with two arguments:
The peer invokes detect with two arguments:

```
bin/detect CHAINCODE_SOURCE_DIR CHAINCODE_METADATA_DIR
```

A typical `detect` script could contain:
A sample `bin/detect` script could contain:

```sh

#!/bin/bash

set -euo pipefail

if [ "$#" -ne 2 ]; then
>&2 echo "Expected 2 directories got $#"
exit 2
fi

METADIR=$2
#check if the "type" field is set to "external"
if [ "$(jq -r .type "$2/metadata.json")" == "external" ]; then
if [ "$(jq -r .type "$METADIR/metadata.json")" == "external" ]; then
exit 0
fi

exit 1
```
Recall that the metadata.json file should contain the following keys:

```json
{"path":"","type":"external","label":"mycc"}
```

### /bin/build
#### bin/build

The `bin/build` script is responsible for building, compiling, or transforming the contents of a chaincode package into artifacts that can be used by release and run. For chaincode as an external service, the build script copies the `connection.json` to the `BUILD_OUTPUT_DIR`. The peer invokes the build script with three arguments:
For chaincode as an external service, the sample build script assumes the chaincode package's `code.tar.gz` file contains `connection.json` which it simply copies to the `BUILD_OUTPUT_DIR`. The peer invokes the build script with three arguments:

```
bin/build CHAINCODE_SOURCE_DIR CHAINCODE_METADATA_DIR BUILD_OUTPUT_DIR
```

A typical `build` script could contain:
A sample `bin/build` script could contain:

```sh

#!/bin/bash

set -euo pipefail

if [ "$#" -ne 3 ]; then
>&2 echo "Expected 3 directories got $#"
exit 1
fi

SOURCE=$1
OUTPUT=$3

Expand All @@ -160,45 +117,66 @@ if [ ! -f "$SOURCE/connection.json" ] ; then
exit 1
fi

#do more validation here if needed

#simply copy the endpoint information to specified output location
cp $SOURCE/connection.json $OUTPUT/connection.json

exit 0

```

### /bin/release
#### bin/release

The `bin/release script` is responsible for providing metadata chaincode to the peer. For chaincode as an external service, the `bin/release` script is responsible for providing the connection.json to the peer by placing it in the `RELEASE_OUTPUT_DIR`. The peer invokes the release script with two arguments:
For chaincode as an external service, the `bin/release` script is responsible for providing the `connection.json` to the peer by placing it in the `RELEASE_OUTPUT_DIR`. The `connection.json` file has the following JSON structure

* **address** - chaincode server endpoint accessible from peer. Must be specified in “<host>:<port>” format.
* **dial_timeout** - interval to wait for connection to complete. Specified as a string qualified with units (examples : "10s", "500ms", "1m"). Default is “3s” if not specified.
* **tls_required** - true or false. If false "client_auth_required", "key_path", "cert_path", "root_cert_path" are not required. Default is “true”.
* **client_auth_required** - if true then you need to specify "key_path" and "cert_path" for client authentication. Default is false. Ignored if tls_required is false.
* **key_path** - path to the key file. This path is relative to the “release directory” (see “RELEASE_OUTPUT_DIR” below). Required if client_auth_required is true. Ignored if tls_required is false.
* **cert_path** - path to the certificate file. This path is relative to the “release directory” (see “RELEASE_OUTPUT_DIR” below). Required if client_auth_required is true. Ignored if tls_required is false.
* **root_cert_path** - path to the root cert for authenticating the server. This path is relative to the “release directory” (see “RELEASE_OUTPUT_DIR” below). Required when tls_required is set to true.

For example:

```json
{
"address": "your.chaincode.host.com:9999",
"dial_timeout": "10s",
"tls_required": true,
"client_auth_required": "true",
"key_path": "chaincode/server/tls/key.pem",
"cert_path": "chaincode/server/tls/cert.pem",
"root_cert_path": "chaincode/server/tls/rootcert.pem"
}
```

**Note:** As noted above, the TLS paths are relative to the RELEASE_OUTPUT_DIR directory. Also, in the future, the PEM may be included in the JSON itself.

As noted in the `bin/build` section, this sample assumes the chaincode package directly contains the `connection.json` file which the build script copied to the `BUILD_OUTPUT_DIR`. The peer invokes the release script with two arguments:

```
bin/release BUILD_OUTPUT_DIR RELEASE_OUTPUT_DIR
```

A typical `release` script could contain:
A sample `bin/release` script could contain:


```sh

#!/bin/bash

set -euo pipefail

set -x

if [ "$#" -ne 2 ]; then
>&2 echo "Expected 2 directories got $#"
exit 2
fi

BLD="$1"
RELEASE="$2"

#external chaincodes expect artifacts to be placed under "$RELEASE"/chaincode/server
if [ -f $BLD/connection.json ]; then
mkdir -p "$RELEASE"/chaincode/server
cp $BLD/connection.json "$RELEASE"/chaincode/server

#if tls_required is true, copy TLS files (using above example, the fully qualified path for these fils would be "$RELEASE"/chaincode/server/tls)

exit 0
fi

Expand Down

0 comments on commit 269cb04

Please sign in to comment.