# kctrl - Package Aritfact from Github Release
###### tags: `kctrl`
## Packaging Artifacts from Github Release
In this tutorial, we will see how to package artifact from Github Release. Many Kubernetes(K8s) apps release K8s configurations as part of their release process. We will use [Dynatrace](https://www.dynatrace.com/) 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 Kubernetes manifest which needs to be packaged. [`Dynatrace Operator`](https://github.com/Dynatrace/dynatrace-operator) releases the [`kubernetes.yaml`](https://github.com/Dynatrace/dynatrace-operator/releases) which can be packaged and be 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 dynatrace
$ cd dynatrace
$ 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 the question 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 `dynatrace.carvel.dev` as our package name.
`> Enter source (1):`
* Here, we need to enter from where to get the Kubernetes manifest which needs to be packages. As mentioned earlier, `dynatrace` releases `kubernetes.yaml` as part of their GitHub release artifacts. Hence, we will select Option `2`.
`> Enter slug for repository ()`
* In this, we have to enter the github slug which is the `org/repo` format. We will enter `Dynatrace/dynatrace-operator`.
`> Enter the release tag to be used (latest):`
* We will use `v0.9.0` released version.
`> Enter the paths which contain Kubernetes manifests (*):`
* Many artifacts can be released during a release. We are interested in `kubernetes.yaml` artifact only. Hence, we will enter `kubernetes.yaml`
After entering all the above details, [`vendir`](https://carvel.dev/vendir/) will download all the mentioned manifest locally. `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 and 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/dynatrace-bundle` to `docker.io/<YOUR_DOCKERHUB_ACCOUNT>/dynatrace-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/dynatrace.carvel.dev/package.yml
apiVersion: data.packaging.carvel.dev/v1alpha1
kind: Package
metadata:
creationTimestamp: null
name: dynatrace.carvel.dev.1.0.0
spec:
refName: dynatrace.carvel.dev
releasedAt: "2022-08-15T11:54:50Z"
template:
spec:
deploy:
- kapp: {}
fetch:
- imgpkgBundle:
image: index.docker.io/rohitagg2020/dynatrace-bundle@sha256:d3fd67881ccba75134061451348130577ad0b2034d0a65b44b965b56e7d1c939
template:
- ytt:
paths:
- upstream
- kbld:
paths:
- '-'
- .imgpkg/images.yml
valuesSchema:
openAPIv3:
default: null
nullable: true
version: 1.0.0
$ cat carvel-artifacts/packages/dynatrace.carvel.dev/metadata.yml
apiVersion: data.packaging.carvel.dev/v1alpha1
kind: PackageMetadata
metadata:
creationTimestamp: null
name: dynatrace.carvel.dev
spec:
displayName: dynatrace
longDescription: dynatrace.carvel.dev
shortDescription: dynatrace.carvel.dev
```
Next step is to add it to package repository.
All the values entered as part of the `pkg init` and `pkg release` commands has been recorded in the `package-build.yml` and `package-resources.yml` file. 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 as a `PackageRepository`. Let’s bundle the `dynatrace` package created above into the PackageRepository.
Let's create a folder for our repository.
```bash
$ cd ../
$ mkdir pkg-repo && cd pkg-repo
```
`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/dynatrace.carvel.dev
$ cp ../dynatrace/carvel-artifacts/packages/dynatrace.carvel.dev/package.yml packages/dynatrace.carvel.dev/1.0.0.yml
$ cp ../dynatrace/carvel-artifacts/packages/dynatrace.carvel.dev/metadata.yml packages/dynatrace.carvel.dev/
$ tree
.
└── packages
└── dynatrace.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 1.0.0
```
In this command, it will ask for package repository name and only one question about 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 `dynatrace-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/github-repo-bundle` to `docker.io/<YOUR_DOCKERHUB_ACCOUNT>/github-repo-bundle`. Alternatively, you can enter other valid OCI registry URL.
### Test the package
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 github-repo --url docker.io/rohitagg2020/github-repo-bundle -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 github.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 `dynatrace-operator` has been deployed successfully.
`$ kubectl get pods -n kctrl-test`