github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/docs/source/cc_launcher.md (about)

     1  # External Builders and Launchers
     2  
     3  Prior to Hechain 2.0, the process used to build and launch chaincode was part of the peer implementation and could not be easily customized. All chaincode installed on the peer would be "built" using language specific logic hard coded in the peer. This build process would generate a Docker container image that would be launched to execute chaincode that connected as a client to the peer.
     4  
     5  This approach limited chaincode implementations to a handful of languages, required Docker to be part of the deployment environment, and prevented running chaincode as a long running server process.
     6  
     7  Starting with Fabric 2.0, External Builders and Launchers address these limitations by enabling operators to extend the peer with programs that can build, launch, and discover chaincode. To leverage this capability you will need to create your own buildpack and then modify the peer core.yaml to include a new `externalBuilder` configuration element which lets the peer know an external builder is available. The following sections describe the details of this process.
     8  
     9  Note that if no configured external builder claims a chaincode package, the peer will attempt to process the package as if it were created with the standard Fabric packaging tools such as the peer CLI or node SDK.
    10  
    11  **Note:** This is an advanced feature which will likely require custom packaging of the peer image with everything your builders and launchers depend on unless your builders and launchers are simple enough, such as those used in the [basic asset transfer external chaincode Fabric sample](https://github.com/hyperledger/fabric-samples/blob/{BRANCH}/asset-transfer-basic/chaincode-external). For example, the following samples use `go` and `bash`, which are not included in the current official `fabric-peer` image.
    12  
    13  ## External builder model
    14  
    15  Hechain External Builders and Launchers are loosely based on Heroku [Buildpacks](https://devcenter.heroku.com/articles/buildpack-api). A buildpack implementation is simply a collection of programs or scripts that transform application artifacts into something that can run. The buildpack model has been adapted for chaincode packages and extended to support chaincode execution and discovery.
    16  
    17  ### External builder and launcher API
    18  
    19  An external builder and launcher consists of four programs or scripts:
    20  
    21  - `bin/detect`: Determine whether or not this buildpack should be used to build the chaincode package and launch it.
    22  - `bin/build`: Transform the chaincode package into executable chaincode.
    23  - `bin/release` (optional): Provide metadata to the peer about the chaincode.
    24  - `bin/run` (optional): Run the chaincode.
    25  
    26  #### `bin/detect`
    27  
    28  The `bin/detect` script is responsible for determining whether or not a buildpack should be used to build a chaincode package and launch it. The peer invokes `detect` with two arguments:
    29  
    30  ```sh
    31  bin/detect CHAINCODE_SOURCE_DIR CHAINCODE_METADATA_DIR
    32  ```
    33  
    34  When `detect` is invoked, `CHAINCODE_SOURCE_DIR` contains the chaincode source and `CHAINCODE_METADATA_DIR` contains the `metadata.json` file from the chaincode package installed to the peer. The `CHAINCODE_SOURCE_DIR` and `CHAINCODE_METADATA_DIR` should be treated as read only inputs. If the buildpack should be applied to the chaincode source package, `detect` must return an exit code of `0`; any other exit code will indicate that the buildpack should not be applied.
    35  
    36  The following is an example of a simple `detect` script for go chaincode:
    37  ```sh
    38  #!/bin/bash
    39  
    40  CHAINCODE_METADATA_DIR="$2"
    41  
    42  # use jq to extract the chaincode type from metadata.json and exit with
    43  # success if the chaincode type is golang
    44  if [ "$(jq -r .type "$CHAINCODE_METADATA_DIR/metadata.json" | tr '[:upper:]' '[:lower:]')" = "golang" ]; then
    45      exit 0
    46  fi
    47  
    48  exit 1
    49  ```
    50  
    51  #### `bin/build`
    52  
    53  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`. The peer invokes `build` with three arguments:
    54  
    55  ```sh
    56  bin/build CHAINCODE_SOURCE_DIR CHAINCODE_METADATA_DIR BUILD_OUTPUT_DIR
    57  ```
    58  
    59  When `build` is invoked, `CHAINCODE_SOURCE_DIR` contains the chaincode source and `CHAINCODE_METADATA_DIR` contains the `metadata.json` file from the chaincode package installed to the peer. `BUILD_OUTPUT_DIR` is the directory where `build` must place artifacts needed by `release` and `run`. The build script should treat the input directories `CHAINCODE_SOURCE_DIR` and `CHAINCODE_METADATA_DIR` as read only, but the `BUILD_OUTPUT_DIR` is writeable.
    60  
    61  When `build` completes with an exit code of `0`, the contents of `BUILD_OUTPUT_DIR` will be copied to the persistent storage maintained by the peer; any other exit code will be considered a failure.
    62  
    63  The following is an example of a simple `build` script for go chaincode:
    64  
    65  ```sh
    66  #!/bin/bash
    67  
    68  CHAINCODE_SOURCE_DIR="$1"
    69  CHAINCODE_METADATA_DIR="$2"
    70  BUILD_OUTPUT_DIR="$3"
    71  
    72  # extract package path from metadata.json
    73  GO_PACKAGE_PATH="$(jq -r .path "$CHAINCODE_METADATA_DIR/metadata.json")"
    74  if [ -f "$CHAINCODE_SOURCE_DIR/src/go.mod" ]; then
    75      cd "$CHAINCODE_SOURCE_DIR/src"
    76      go build -v -mod=readonly -o "$BUILD_OUTPUT_DIR/chaincode" "$GO_PACKAGE_PATH"
    77  else
    78      GO111MODULE=off go build -v  -o "$BUILD_OUTPUT_DIR/chaincode" "$GO_PACKAGE_PATH"
    79  fi
    80  
    81  # save statedb index metadata to provide at release
    82  if [ -d "$CHAINCODE_SOURCE_DIR/META-INF" ]; then
    83      cp -a "$CHAINCODE_SOURCE_DIR/META-INF" "$BUILD_OUTPUT_DIR/"
    84  fi
    85  ```
    86  
    87  #### `bin/release`
    88  
    89  The `bin/release` script is responsible for providing chaincode metadata to the peer. `bin/release` is optional. If it is not provided, this step is skipped. The peer invokes `release` with two arguments:
    90  
    91  ```sh
    92  bin/release BUILD_OUTPUT_DIR RELEASE_OUTPUT_DIR
    93  ```
    94  
    95  When `release` is invoked, `BUILD_OUTPUT_DIR` contains the artifacts populated by the `build` program and should be treated as read only input. `RELEASE_OUTPUT_DIR` is the directory where `release` must place artifacts to be consumed by the peer.
    96  
    97  When `release` completes, the peer will consume two types of metadata from `RELEASE_OUTPUT_DIR`:
    98  
    99  - state database index definitions for CouchDB
   100  - external chaincode server connection information (`chaincode/server/connection.json`)
   101  
   102  If CouchDB index definitions are required for the chaincode, `release` is responsible for placing the indexes into the `statedb/couchdb/indexes` directory under `RELEASE_OUTPUT_DIR`. The indexes must have a `.json` extension.  See the [CouchDB indexes](couchdb_as_state_database.html#couchdb-indexes) documentation for details.
   103  
   104  In cases where a chaincode server implementation is used, `release` is responsible for populating `chaincode/server/connection.json` with the address of the chaincode server and any TLS assets required to communicate with the chaincode. When server connection information is provided to the peer, `run` will not be called. See the [Chaincode Server](https://jira.hyperledger.org/browse/FAB-14086) documentation for details.
   105  
   106  The following is an example of a simple `release` script for go chaincode:
   107  
   108  ```sh
   109  #!/bin/bash
   110  
   111  BUILD_OUTPUT_DIR="$1"
   112  RELEASE_OUTPUT_DIR="$2"
   113  
   114  # copy indexes from META-INF/* to the output directory
   115  if [ -d "$BUILD_OUTPUT_DIR/META-INF" ] ; then
   116     cp -a "$BUILD_OUTPUT_DIR/META-INF/"* "$RELEASE_OUTPUT_DIR/"
   117  fi
   118  ```
   119  
   120  #### `bin/run`
   121  
   122  The `bin/run` script is responsible for running chaincode. The peer invokes `run` with two arguments:
   123  
   124  ```sh
   125  bin/run BUILD_OUTPUT_DIR RUN_METADATA_DIR
   126  ```
   127  
   128  When `run` is called, `BUILD_OUTPUT_DIR` contains the artifacts populated by the `build` program and `RUN_METADATA_DIR` is populated with a file called `chaincode.json` that contains the information necessary for chaincode to connect and register with the peer. Note that the `bin/run` script should treat these `BUILD_OUTPUT_DIR` and `RUN_METADATA_DIR` directories as read only input.  The keys included in `chaincode.json` are:
   129  
   130  - `chaincode_id`: The unique ID associated with the chaincode package.
   131  - `peer_address`: The address in `host:port` format of the `ChaincodeSupport` gRPC server endpoint hosted by the peer.
   132  - `client_cert`: The PEM encoded TLS client certificate generated by the peer that must be used when the chaincode establishes its connection to the peer.
   133  - `client_key`: The PEM encoded client key generated by the peer that must be used when the chaincode establishes its connection to the peer.
   134  - `root_cert`: The PEM encoded TLS root certificate for the `ChaincodeSupport` gRPC server endpoint hosted by the peer.
   135  - `mspid`: The local mspid of the peer.
   136  
   137  When `run` terminates, the peer considers the chaincode terminated. If another request arrives for the chaincode, the peer will attempt to start another instance of the chaincode by invoking `run` again. The contents of `chaincode.json` must not be cached across invocations.
   138  
   139  The following is an example of a simple `run` script for go chaincode:
   140  ```sh
   141  #!/bin/bash
   142  
   143  BUILD_OUTPUT_DIR="$1"
   144  RUN_METADATA_DIR="$2"
   145  
   146  # setup the environment expected by the go chaincode shim
   147  export CORE_CHAINCODE_ID_NAME="$(jq -r .chaincode_id "$RUN_METADATA_DIR/chaincode.json")"
   148  export CORE_PEER_TLS_ENABLED="true"
   149  export CORE_TLS_CLIENT_CERT_FILE="$RUN_METADATA_DIR/client.crt"
   150  export CORE_TLS_CLIENT_KEY_FILE="$RUN_METADATA_DIR/client.key"
   151  export CORE_PEER_TLS_ROOTCERT_FILE="$RUN_METADATA_DIR/root.crt"
   152  export CORE_PEER_LOCALMSPID="$(jq -r .mspid "$RUN_METADATA_DIR/chaincode.json")"
   153  
   154  # populate the key and certificate material used by the go chaincode shim
   155  jq -r .client_cert "$RUN_METADATA_DIR/chaincode.json" > "$CORE_TLS_CLIENT_CERT_FILE"
   156  jq -r .client_key  "$RUN_METADATA_DIR/chaincode.json" > "$CORE_TLS_CLIENT_KEY_FILE"
   157  jq -r .root_cert   "$RUN_METADATA_DIR/chaincode.json" > "$CORE_PEER_TLS_ROOTCERT_FILE"
   158  if [ -z "$(jq -r .client_cert "$RUN_METADATA_DIR/chaincode.json")" ]; then
   159      export CORE_PEER_TLS_ENABLED="false"
   160  fi
   161  
   162  # exec the chaincode to replace the script with the chaincode process
   163  exec "$BUILD_OUTPUT_DIR/chaincode" -peer.address="$(jq -r .peer_address "$ARTIFACTS/chaincode.json")"
   164  ```
   165  
   166  ## Configuring external builders and launchers
   167  
   168  Configuring the peer to use external builders involves adding an externalBuilder element under the chaincode configuration block in the  `core.yaml` that defines external builders. Each external builder definition must include a name (used for logging) and the path to parent of the `bin` directory containing the builder scripts.
   169  
   170  An optional list of environment variable names to propagate from the peer when invoking the external builder scripts can also be provided.
   171  
   172  The following example defines two external builders:
   173  
   174  ```yaml
   175  chaincode:
   176    externalBuilders:
   177    - name: my-golang-builder
   178      path: /builders/golang
   179      propagateEnvironment:
   180      - GOPROXY
   181      - GONOPROXY
   182      - GOSUMDB
   183      - GONOSUMDB
   184    - name: noop-builder
   185      path: /builders/binary
   186  ```
   187  
   188  In this example, the implementation of "my-golang-builder" is contained within the `/builders/golang` directory and its build scripts are located in `/builders/golang/bin`. When the peer invokes any of the build scripts associated with "my-golang-builder", it will propagate only the values of the environment variables in the `propagateEnvironment`.
   189  
   190  Note: The following environment variables are always propagated to external builders:
   191  
   192  - LD_LIBRARY_PATH
   193  - LIBPATH
   194  - PATH
   195  - TMPDIR
   196  
   197  When an `externalBuilder` configuration is present, the peer will iterate over the list of builders in the order provided, invoking `bin/detect` until one completes successfully. If no builder completes `detect` successfully, the peer will fallback to using the legacy Docker build process implemented within the peer. This means that external builders are completely optional.
   198  
   199  In the example above, the peer will attempt to use "my-golang-builder", followed by "noop-builder", and finally the peer internal build process.
   200  
   201  If you do not need to fallback to the legacy Docker build process for your chaincodes, you can remove the Docker endpoint from the peer `core.yaml` `vm.endpoint` configuration. This will also remove the Docker daemon health check.
   202  
   203  ## Chaincode packages
   204  
   205  As part of the new lifecycle introduced with Fabric 2.0, the chaincode package format changed from serialized protocol buffer messages to a gzip compressed POSIX tape archive. Chaincode packages created with `peer lifecycle chaincode package` use this new format.
   206  
   207  ### Lifecycle chaincode package contents
   208  
   209  A lifecycle chaincode package contains two files. The first file, `code.tar.gz` is a gzip compressed POSIX tape archive. This file includes the source artifacts for the chaincode. Packages created by the peer CLI will place the chaincode implementation source under the `src` directory and chaincode metadata (like CouchDB indexes) under the `META-INF` directory.
   210  
   211  The second file, `metadata.json` is a JSON document with three keys:
   212  - `type`: the chaincode type (e.g. GOLANG, JAVA, NODE)
   213  - `path`: for go chaincode, the GOPATH or GOMOD relative path to the main chaincode package; undefined for other types
   214  - `label`: the chaincode label that is used to generate the package-id by which the package is identified within the new chaincode lifecycle process.
   215  
   216  Note that the `type` and `path` fields are only utilized by docker platform builds.
   217  
   218  ### Chaincode packages and external builders
   219  
   220  When a chaincode package is installed to a peer, the contents of `code.tar.gz` and `metadata.json` are not processed prior to calling external builders, except for the `label` field that is used by the new lifecycle process to compute the package id. This affords users a great deal of flexibility in how they package source and metadata that will be processed by external builders and launchers.
   221  
   222  For example, a custom chaincode package could be constructed that contains a pre-compiled, implementation of chaincode in `code.tar.gz` with a `metadata.json` that allows a _binary buildpack_ to detect the custom package, validate the hash of the binary, and run the program as chaincode.
   223  
   224  Another example would be a chaincode package that only contains state database index definitions and the data necessary for an external launcher to connect to a running chaincode server. In this case, the `build` process would simply extract the metadata from the process and `release` would present it to the peer.
   225  
   226  The only requirements are that `code.tar.gz` can only contain regular file and directory entries, and that the entries cannot contain paths that would result in files being written outside of the logical root of the chaincode package.
   227  
   228  <!---
   229  Licensed under Creative Commons Attribution 4.0 International License https://creativecommons.org/licenses/by/4.0/
   230  -->