# kctrl - Package Helm Chart from Helm Repo
###### tags: `kctrl`
## Packaging Helm Chart from Helm Repo
In this tutorial, we will see how to package an helm chart from a helm repo. We will use [MongoDb enterprise operator](https://github.com/mongodb/helm-charts/tree/main/charts/enterprise-operator) as an example here.
### Prerequisites
1. Install Carvel tools - [imgpkg](https://carvel.dev/imgpkg/docs/latest/install/), [kapp](https://carvel.dev/kapp/docs/latest/install/), [kbld](https://carvel.dev/kbld/docs/latest/install/), [vendir](https://carvel.dev/vendir/docs/latest/install/), [ytt](https://carvel.dev/ytt/docs/latest/install/).
2. Identify helm chart and helm repo. [`MongoDb enterprise operator`](https://github.com/mongodb/mongodb-enterprise-kubernetes) is available in this [`repo`](https://mongodb.github.io/helm-charts/) with chart name as [`enterprise-operator`](https://github.com/mongodb/helm-charts/tree/main/charts/enterprise-operator) and is managed by `mongodb` itself. We will package this helm chart and make it available for distribution.
3. Kubernetes cluster (I will be using [minikube](https://minikube.sigs.k8s.io/docs/)).
4. OCI registry where the package bundle and repository bundles will be pushed (I will be using my [Docker Hub](https://hub.docker.com/) account).
### Initialize Package
```bash
$ mkdir tutorial-3
$ cd tutorial-3
$ kctrl pkg init
```
To initialize, we will use `kctrl pkg init`.
This command asks a few basic questions regarding how we want to initialize our package. Lets go through them together:
`> Enter the package reference name (samplepackage.corp.com):`
* In this question, we need to enter the package name which will be a valid DNS subdomain name. We will use `mongodb.carvel.dev` as our package name.
`> Enter source (1):`
* Here, we need to enter from where to get the Kubernetes manifest or helm chart which needs to be packaged. As mentioned earlier, we will use [`enterprise-operator`](https://github.com/mongodb/helm-charts/tree/main/charts/enterprise-operator) from this [`repo`](https://mongodb.github.io/helm-charts/). Hence, we will select Option `3`.
`> Enter helm chart repository URL ():`
* In this, we have to enter the helm repository URL. We will enter `https://mongodb.github.io/helm-charts`.
`> Enter helm chart name ():`
* We will use `enterprise-operator` as the chart name.
`> Enter helm chart version ():`
* We will use `1.17.0` version.
After entering all the above details, [`vendir`](https://carvel.dev/vendir/) will download the helm chart locally into `upstream` folder. `kctrl` will generate two files - package-build.yml and pacakge-resources.yml as output. `Package-resources.yml` file contain Package, PackageInstall and PackageMetadata while `package-build.yml` contains PackageBuild. All the values entered above have been recorded in these files. These files will be used by the `dev` and `pkg release` command subsequently.
### Release the package
`kctrl pkg release` will be used to release the package.
```bash
$ kctrl pkg release -v 1.0.0
```
This command will create an imgpkg bundle, upload it to the OCI registry, create `package.yml` and `metadata.yml` which can be released for consumption eventually. Also, we are versioning our package with `-v` flag.
`> Enter the registry URL ():`
* Here we need to enter the registry URL where we need to push our imgpkg bundle. While entering the registry URL, ensure to change the value from `docker.io/rohitagg2020/mongodb-bundle` to `docker.io/<YOUR_DOCKERHUB_ACCOUNT>/mongodb-bundle`. Alternatively, you can enter other valid OCI registry URL.
Now, we have created our Package and PackageMetadata.
Let's see how the Package and PackageMetadata files look like:
```bash
$ cat carvel-artifacts/packages/mongodb.carvel.dev/package.yml
apiVersion: data.packaging.carvel.dev/v1alpha1
kind: Package
metadata:
creationTimestamp: null
name: mongodb.carvel.dev.1.0.0
spec:
refName: mongodb.carvel.dev
releasedAt: "2022-11-10T08:34:33Z"
template:
spec:
deploy:
- kapp: {}
fetch:
- imgpkgBundle:
image: index.docker.io/rohitagg2020/mongodb-bundle@sha256:194e7f573a31a61653533742730143aedf62bf640d4145bf2220a6375380a36c
template:
- helmTemplate:
path: upstream
- ytt:
paths:
- '-'
- kbld:
paths:
- '-'
- .imgpkg/images.yml
valuesSchema:
openAPIv3:
properties:
agent:
properties:
name:
default: mongodb-agent
type: string
version:
default: 11.12.0.7388-1
type: string
type: object
...
type: object
version: 1.0.0
$ cat carvel-artifacts/packages/mongodb.carvel.dev/metadata.yml
apiVersion: data.packaging.carvel.dev/v1alpha1
kind: PackageMetadata
metadata:
creationTimestamp: null
name: mongodb.carvel.dev
spec:
displayName: mongodb
longDescription: mongodb.carvel.dev
shortDescription: mongodb.carvel.dev
```
Next step is to add it to package repository.
These files can be submitted to the version control tools like github, etc. so that next time while running `pkg init` or `pkg release`, these values can be picked up as default values.
### Add package to the package repository
`kctrl` can be used to release packages grouped together into a `PackageRepository`. Let’s bundle the `dynatrace` package created above into the PackageRepository.
We will reuse the package repository which was created in `tutorial-2`
`kctrl` will create a repo bundle from all the packages and metadata present in the `packages` folder.
We will copy the `package.yml` and `metadata.yml` created above into the `packages` folder. We will follow the bundle format as mentioned [here](https://carvel.dev/kapp-controller/docs/v0.32.0/packaging-artifact-formats/#package-repository-bundle). Alternatively, while running `pkg release`, `--repo-output` flag can be used to copy the `package.yml` and `metadata.yml` in the prescribed PackageRepository bundle format at a specified location.
```bash
$ mkdir -p packages/mongodb.carvel.dev
$ cp ../tutorial-3/carvel-artifacts/packages/mongodb.carvel.dev/package.yml packages/mongodb.carvel.dev/1.0.0.yml
$ cp ../tutorial-3/carvel-artifacts/packages/mongodb.carvel.dev/metadata.yml packages/mongodb.carvel.dev/
$ tree
.
└── packages
└── mongodb.carvel.dev
├── 1.0.0.yml
└── metadata.yml
```
Now, we will run `kctrl pkg repo release` to create and release the repository bundle. This repository bundle can be distributed to the the package consumer.
```bash
$ kctrl pkg repo release -v 2.0.0
```
In this command, it will ask for package repository name and where to push our repository bundle. Also, we are versioning our package repository with `-v` flag.
`> Enter the package repository name (sample-repo.carvel.dev):`
* We will use `demo-repo.carvel.dev` as our package repository name.
`> Enter the registry url ():`
* All the `packages` and `metadata` yaml files present in the `packages` folder will be bundled into `imgpkg bundle` and then pushed to the above registry url. While entering the registry URL, ensure to change the value from `docker.io/rohitagg2020/demo-repo-bundle` to `docker.io/<YOUR_DOCKERHUB_ACCOUNT>/demo-repo-bundle`. Alternatively, you can enter other valid OCI registry URL.
### Test the package (Optional)
To test the package, we will again use kctrl.
First step is to add the packageRepository to the Kubernetes cluster by using `kctrl pkg repo add` command. Once the package repository is added, all the packages in that repository becomes available to install.
Then we can install a package by using `kctrl pkg install` command.
Since package repository and package install are custom resources(CRs), we have to deploy the `kapp-controller` onto the cluster so that all these CRs become available on the cluster.
#### Install kapp controller
**_NOTE_**: In case you have already installed `kapp-controller`, skip this section.
To install, `kapp-controller`, run
```bash
$ kapp deploy -a kc -f https://github.com/vmware-tanzu/carvel-kapp-controller/releases/latest/download/release.yml
```
#### Add package repository
To add the package repo, we will run
```bash
$ kubectl create ns kctrl-test
$ kctrl pkg repo add -r demo-repo --url docker.io/rohitagg2020/demo-repo-bundle:2.0.0 -n kctrl-test
```
To list the available packages, run
```bash
$ kctrl pkg available --list -n kctrl-test
```
#### Install package
To install the package, we will run
```bash
$ kctrl pkg install -i pkg-install-demo -p mongodb.carvel.dev -v 1.0.0 -n kctrl-test
```
#### Confirm package installed successfully
To confirm that package has been installed successfully, list down the pods and ensure that `mongodb-operator` has been deployed successfully.
`$ kubectl get pods -n kctrl-test`