<commit_before>[![Coverage Status](https://coveralls.io/repos/github/cn-app-registry/cnr-server/badge.svg)](https://coveralls.io/github/cn-app-registry/cnr-server)

# cnr-server
CNR reuses as much knowledge from the container ecosystem as possible in building an API for hosting applications.

Some key points:
 - It reuses the OCI’s data structures (like descriptors) and its content addressable manifest pattern for security, signing, and non-trusted mirroring.
 - It is close to the docker registry data model to make it easy for existing systems.
 - It converges with ‘images’ data structure and returns a single manifest-list (oci-spec)
 
By building a common api to push/pull/search packaged applications so different tools, 
and dasboards share the same reference and effort to browse and fetch them.

## API ref
- Swagger-doc:  [cnr-api-swagger.yaml](Documentation/cnr-api-swagger.yaml)
- Examples: [test.sh](Documentation/tests)

## Basic usage
- Packages are indexed by 3 fields: 
 - package-name: it follows container-image format: `namespace/name`.
 - release: it's the version of the package, immutable it can be viewed as an alias to a digest
 - mediaType: the format of the package formats (eg: docker-compose, dab, helm, kpm)
- Blob: it's a tar+gz of the package encoded in base64
 
### Usage example with a Helm-chart
##### Publish the chart
- 1. Create and encode the chart tarball
```
~/charts/elasticsearch $
tar czvf ../elastichart.tar.gz  Chart.yaml manifests README.md 
cat ../elastichart.tar.gz | base64 -w 0    
H4sIAGBoF1gAA+2XTY/aMBCGc86vGKlngk02iRpVq1aUQw+VKlr1bowhVp0P2QZp/33tZFkCy0dVAburnUdCBs/EMyR5XyfjgmkbPbBSBVeDONL0zo80S0h/bInTLK<KEY>
```

- 2. POST the chart to cnr
```
curl -XPOST http://localhost:5000/api/v1/packages/myname/elasticsearch -d '
{ 
  "blob": "H4sIAP3mAFgAA....", 
  "release": "2.2.1", 
  "media_type": "helm"
}'
```
##### Pull the chart
- 1. Find the digest from the package-name/release/media-type
```
curl -XGET http://localhost:5000/api/v1/packages/myname/elasticsearch/2.2.1/helm   
{
  "channels": [], 
  "content": {
    "digest": "72ed15c9a65961ecd034cca098ec18eb99002cd402824aae8a674a8ae41bd0ef", 
    "mediaType": "application/vnd.cnr.package.helm.v1.tar+gzip", 
    "size": 583, 
    "urls": []
  }, 
  "created_at": "2016-11-16T17:13:07.806579", 
  "mediaType": "application/vnd.cnr.package-manifest.helm.v1.json", 
  "package": "myname/elasticsearch", 
  "release": "2.2.1"
}

```
2. Fetch the blob
```
curl -XGET \
http://localhost:5000/api/v1/packages/myname/elasticsearch/blobs/sha256/72ed15c9a65961ecd034cca098ec18eb99002cd402824aae8a674a8ae41bd0ef \
-o elasticsearch-chart.tar.gz
```

## Install
1. git clone https://github.com/cn-app-registry/cnr-server.git && cd cnr-server
2. pip install -e . && pip install gunicorn
3. Run the cnr-server on port 5000 `gunicorn cnr.api.wsgi:app -b :5000`
   or "./run-server"

## Storage

### Filesystem (default)
By default package are stored in `/tmp/cnr`
```
STORAGE=filesystem ./run-server.sh
```

### Etcd
```
STORAGE=etcd ./run-server.sh
```

### Redis
```
STORAGE=redis ./run-server.sh
```<commit_msg>README: reorganize and fix wording<commit_after># cnr-server

[![Coverage Status](https://coveralls.io/repos/github/cn-app-registry/cnr-server/badge.svg)](https://coveralls.io/github/cn-app-registry/cnr-server)
[![Swagger API Reference](https://img.shields.io/badge/swagger-docs-blue.svg)](Documentation/cnr-api-swagger.yaml)

CNR implements a registry for storing Kubernetes application manifests that attempts to reuse as much knowledge from the rest of the Linux container ecosystem as possible.

Differentiating features include:

- A protocol and data model that can more easily be implemented by pre-existing container registries
  - This includes a common API for uploading, downloading, and searching for applications
- The reuse and integration with many elements from [OCI](https://www.opencontainers.org)
  - Content addressable manifest scheme for security, signing, and non-trusted mirroring
  - Reuse of common data structures such as Descriptors
  - Unification of Manifest Lists as the means of content negoitation for both Images and Applications

## Getting started

1. git clone https://github.com/cn-app-registry/cnr-server.git && cd cnr-server
2. pip install -e . && pip install gunicorn
3. Run the cnr-server on port 5000 `gunicorn cnr.api.wsgi:app -b :5000`
   or "./run-server"
4. See the [curl-based examples](Documentation/test.sh)

## Architecture at a glance

There are two top-level objects:

- Package: metadata describing an application
- Blob: a gzipped tarball of the package encoded in base64

Packages are primarily indexed by 3 notable fields:

- package-name: it follows container-image format: `namespace/name`.
- release: it's the version of the package, immutable it can be viewed as an alias to a digest
- mediaType: the format of the package formats (eg: docker-compose, dab, helm, kpm)

Data storage is specified by the `STORAGE` environment variable. The following are supported:

- `filesystem` (default)
- [`etcd`](https://github.com/coreos/etcd)
- [`redis`](https://github.com/antirez/redis)

## Demo using using [Helm](https://github.com/kubernetes/helm) charts

### Publish a chart

Create and encode the chart tarball

```
~/charts/elasticsearch $
tar czvf ../elastichart.tar.gz  Chart.yaml manifests README.md
cat ../elastichart.tar.gz | base64 -w 0
<KEY>
```

POST the chart to CNR

```
curl -XPOST http://localhost:5000/api/v1/packages/myname/elasticsearch -d '
{
  "blob": "H4sIAP3mAFgAA....",
  "release": "2.2.1",
  "media_type": "helm"
}'
```

### Pull the chart

Find the digest from the package-name/release/media-type

```
curl -XGET http://localhost:5000/api/v1/packages/myname/elasticsearch/2.2.1/helm
{
  "channels": [],
  "content": {
    "digest": "72ed15c9a65961ecd034cca098ec18eb99002cd402824aae8a674a8ae41bd0ef",
    "mediaType": "application/vnd.cnr.package.helm.v1.tar+gzip",
    "size": 583,
    "urls": []
  },
  "created_at": "2016-11-16T17:13:07.806579",
  "mediaType": "application/vnd.cnr.package-manifest.helm.v1.json",
  "package": "myname/elasticsearch",
  "release": "2.2.1"
}

```

Fetch the blob

```
curl -XGET \
http://localhost:5000/api/v1/packages/myname/elasticsearch/blobs/sha256/72ed15c9a65961ecd034cca098ec18eb99002cd402824aae8a674a8ae41bd0ef \
-o elasticsearch-chart.tar.gz
```
{'fraction_non_alphanumeric': 0.13081623061256462, 'fraction_numerical': 0.04919316935610215, 'mean_word_length': 4.254320987654321, 'pattern_counts': {'":': 26, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 11, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6552301', 'n_tokens_mistral': 2444, 'n_tokens_neox': 2197, 'n_words': 591}