# kctrl - Package Kubernetes manifest from Git
###### tags: `kctrl`
## Packaging manifest from Git
In this tutorial, we will see how to create a package from Kuberenetes manifest present in a Git repository. We will again use [MongoDb enterprise operator](https://github.com/mongodb/mongodb-enterprise-kubernetes) 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 git and the Kubernetes artifact. [`MongoDb enterprise operator`](https://github.com/mongodb/mongodb-enterprise-kubernetes) Github Repository mentions that [`crds.yaml`](https://github.com/mongodb/mongodb-enterprise-kubernetes/blob/master/crds.yaml) and [`mongodb-enterprise.yaml`](https://github.com/mongodb/mongodb-enterprise-kubernetes/blob/master/mongodb-enterprise.yaml) are the Kubernetes resources which can be installed directly to the cluster to make the operator available. We will package `crds.yaml` and `mongodb-enterprise.yaml` into a Carvel package 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-4
$ cd tutorial-4
$ 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-operator.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 Kubernetes manifest from this [`repo`](https://github.com/mongodb/mongodb-enterprise-kubernetes). Hence, we will select Option `4`.
`> Enter Git URL ():`
* In this, we will enter the github URL. We will enter `https://github.com/mongodb/mongodb-enterprise-kubernetes`.
`> Enter Git Reference (origin/main):`
* We need to provide the branch from where we want to fetch our Kubernetes manifest. We will use `1.17.2`.
`> Enter the paths which contain Kubernetes manifests ():`
* As mentioned above, we will use `crds.yaml,mongodb-enterprise.yaml`
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-operator-bundle` to `docker.io/<YOUR_DOCKERHUB_ACCOUNT>/mongodb-operator-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-operator.carvel.dev/package.yml
apiVersion: data.packaging.carvel.dev/v1alpha1
kind: Package
metadata:
creationTimestamp: null
name: mongodb-operator.carvel.dev.1.0.0
spec:
refName: mongodb-operator.carvel.dev
releasedAt: "2022-11-10T08:34:33Z"
template:
spec:
deploy:
- kapp: {}
fetch:
- imgpkgBundle:
image: index.docker.io/rohitagg2020/mongodb-operator-bundle@sha256:234e7f573a31a61653533742730143aedf62bf640d4145bf2220a6375380aabc
template:
- ytt:
paths:
- upstream
- kbld:
paths:
- '-'
- .imgpkg/images.yml
valuesSchema:
openAPIv3:
default: null
nullable: true
version: 1.0.0
$ cat carvel-artifacts/packages/mongodb-operator.carvel.dev/metadata.yml
apiVersion: data.packaging.carvel.dev/v1alpha1
kind: PackageMetadata
metadata:
creationTimestamp: null
name: mongodb-operator.carvel.dev
spec:
displayName: mongodb-operator
longDescription: mongodb-operator.carvel.dev
shortDescription: mongodb-operator.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-operator.carvel.dev
$ cp ../tutorial-3/carvel-artifacts/packages/mongodb-operator.carvel.dev/package.yml packages/mongodb.carvel.dev/1.0.0.yml
$ cp ../tutorial-3/carvel-artifacts/packages/mongodb-operator.carvel.dev/metadata.yml packages/mongodb.carvel.dev/
$ tree
.
└── packages
└── mongodb-operator.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 3.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:3.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-operator.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`