[[promoting-integration]]
= Promoting Integrations across environments

As soon as you have an Integration running in your cluster, you will be challenged to move that Integration to an higher environment. Ie, you can test your Integration in a **development** environment, and, as soon as you're happy with the result, you will need to move it into a **production** environment.

[[cli-promote]]
== CLI `promote` command

Camel K has an opinionated way to achieve the promotion goal through the usage of `kamel promote` command. With this command you will be able to easily move an Integration from one namespace to another without worrying about any low level detail such as resources needed by the Integration. You only need to make sure that both the source operator and the destination operator are using the same container registry and that the destination namespace provides the required Configmaps, Secrets or Kamelets required by the Integration.

NOTE: use dry run option (`-o yaml`) and export the result to any separated cluster or Git repository to perform a GitOps strategy.

Let's see a simple Integration that uses a Configmap to expose some message on an HTTP endpoint. We can start creating such an Integration and testing in a namespace called `development`:

```
kubectl create configmap my-cm --from-literal=greeting="hello, I am development!" -n development
```
.PromoteServer.java
```java
import org.apache.camel.builder.RouteBuilder;

public class PromoteServer extends RouteBuilder {
  @Override
  public void configure() throws Exception {
    from("platform-http:/hello?httpMethodRestrict=GET").setBody(simple("resource:classpath:greeting"));
  }
}
```
Let's run it:
```
kamel run -n development PromoteServer.java --config configmap:my-cm [-t service.node-port=true]
```
Note that you may need to tweak the service trait, depending on the Kubernetes platform and the level of exposure you want to provide. As soon as it is finished, we can test it as well:
```
curl http://192.168.49.2:32116/hello
hello, I am development!
```

Now let's say we're happy with the testing of our Integration and we're ready to move it to a production environment. We need to have the destination environment (a Kubernetes namespace) ready with an operator (sharing the same operator source container registry) and any configuration, such as the configmap we have used here. For that scope, let's create one on the destination namespace:
```
kubectl create configmap my-cm --from-literal=greeting="hello, I am production!" -n production
```
Please, note that for security reason, there is a check to make sure that the expected resources such as Configmaps, Secrets and Kamelets are present on the destination. If any is missing, the Integration won't be moved. We can now "promote" our Integration:
```
kamel promote promote-server -n development --to production
kamel logs promote-server -n production
```
Let's test the promoted Integration:
```
curl http://192.168.49.2:30764/hello
hello, I am production!
```
Something nice is that since the Integration is reusing the very same container image, the execution of the new application will be immediate. Also from a release perspective we are guaranteeing the **immutability** of the Integration as the container used is exactly the same of the one we have tested in development (what we change are just the configurations).

Please notice that the Integration running in test is not altered in any way and will be running until any user will stop it.

[[traits]]
== Moving traits

When you use the `promote` subcommand, you're also keeping the status of any configured trait along with the new promoted Integration. The tool is in fact in charge to recover the trait configuration of the source Integration and port it over to the new Integration promoted.

This is particularly nice when you have certain traits which are requiring the scan the source code (for instance, Service trait). In this way, when you promote the new Integration, the traits will be automatically configured to copy any parameter, replicating the very exact behavior between the source and destination environment.

With this approach, you won't need to worry any longer about any trait which was requiring the source to be attached in order to automatically scan for features.

[[gitops]]
== Make your own GitOps

The promote has also the possibility to create a Kustomize based overlay structure in order to simplify the creation of a **GitOps based deployment** process. Let's pretend we want to create a GitOps pipeline for two environments, as an example, *staging* and *production*. For each environment we can call the export command:

```
$ kamel promote promote-server -n development --to staging --export-gitops-dir /tmp/integrations
$ kamel promote promote-server -n development --to production --export-gitops-dir /tmp/integrations
```

NOTE: you can call this command for as many environments you manage

The result will be a directory with the following structure:

```
$ tree /tmp/integrations/
/tmp/integrations/
├── all
│   └── overlays
│       ├── production
│       │   └── kustomization.yaml
│       └── staging
│           └── kustomization.yaml
└── promote-server
    ├── base
    │   ├── integration.yaml
    │   └── kustomization.yaml
    ├── overlays
    │   ├── production
    │   │   ├── kustomization.yaml
    │   │   └── patch-integration.yaml
    │   └── staging
    │       ├── kustomization.yaml
    │       └── patch-integration.yaml
    └── routes
        └── PromoteServer.java
```
The `all` directory contains an overlay structure for all the Integrations that are included in this project. This is of great help when you want to use the `promote` tool to append any other Integration to the same project. Beside adding the Integration specific resources (as described in the next paragraph), we include a `all` profile and add in the `kustomization.yaml` file the specific overlay of each new Integration added. Running `kubectl apply -k /tmp/integrations/all/overlays/production` will include all the Integrations added in such a profile.

The `promote-server` directory contains the Integration named as `promote-server` (the one we created in the previous chapter). Then, you can see a *base* directory which contains the base Integration custom resource. Additionally you will find the *staging* and *production* overlays which contains the patches you may want to apply in each given environment.

```
$ cat /tmp/integrations/promote-server/overlays/production/patch-integration.yaml
apiVersion: camel.apache.org/v1
kind: Integration
metadata:
  name: promote-server
spec:
  traits:
    mount:
      configs:
      - configmap:my-cm
status: {}
```

The CLI has a predetermined set of configuration (traits) which are typically subject of environment patching, such as Camel properties or any Kubernetes resource configuration. You will need to change those parameters accordingly or add any one else required for your specific use case.

The above structure could be used directly with `kubectl` (eg, `kubectl apply -k /tmp/integrations/promote-server/overlays/production`). For this reason it can be used *as is* to feed a Git repository and referenced in any CICD pipeline.

=== Predetermined configuration

The CLI will add a patch configuration for any of the following trait configuration found in the source base Integration:

* Affinity configuration
* Camel properties
* Container resources
* Environment variables
* JVM options
* Mount configuration
* Toleration configuration

NOTE: feel free to ask to add any further configuration you require.
