Repository: apache/camel-k
Pull request #1109 (2019-11-29 05:58:38)

Update to add the saga example


Patch:
diff --git a/.github/workflows/pr-build.yml b/.github/workflows/pr-build.yml
new file mode 100644
index 000000000..412546856
--- /dev/null
+++ b/.github/workflows/pr-build.yml
@@ -0,0 +1,47 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+name: Build PR
+
+on:
+  pull_request:
+    branches:
+      - master
+jobs:
+  build:
+    strategy:
+      matrix:
+        # TODO: test an all the supported OS
+        # [ubuntu-latest, macos-latest, windows-latest]
+        os: [ubuntu-latest]
+    runs-on: ${{ matrix.os }}
+    steps:
+    - name: Install Go
+      uses: actions/setup-go@v1
+      with:
+        go-version: 1.13.x
+    - name: Checkout code
+      uses: actions/checkout@v1
+    - name: Cache modules
+      uses: actions/cache@v1
+      with:
+        path: ~/go/pkg/mod
+        key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
+        restore-keys: |
+          ${{ runner.os }}-go-
+    - name: Test
+      run: make
diff --git a/.github/workflows/pr-validate.yml b/.github/workflows/pr-validate.yml
new file mode 100644
index 000000000..8b2ec34b2
--- /dev/null
+++ b/.github/workflows/pr-validate.yml
@@ -0,0 +1,40 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+name: Validate PR
+
+on: 
+  pull_request:
+    branches: 
+      - master
+jobs:
+  build:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Check out code
+        uses: actions/checkout@v1
+      - name: Cache modules
+        uses: actions/cache@v1
+        with:
+          path: ~/go/pkg/mod
+          key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
+          restore-keys: |
+            ${{ runner.os }}-go-
+      - name: Lint
+        uses: reviewdog/action-golangci-lint@v1
+        with:
+          github_token: ${{ secrets.github_token }}
diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
index 468165c01..6169a8c0b 100644
--- a/docs/modules/ROOT/nav.adoc
+++ b/docs/modules/ROOT/nav.adoc
@@ -33,6 +33,7 @@
 ** xref:traits/knative-service.adoc[Knative Service]
 ** xref:traits/knative.adoc[Knative]
 ** xref:traits/owner.adoc[Owner]
+** xref:traits/platform.adoc[Platform]
 ** xref:traits/probes.adoc[Probes]
 ** xref:traits/prometheus.adoc[Prometheus]
 ** xref:traits/pull-secret.adoc[Pull Secret]
diff --git a/docs/modules/ROOT/pages/languages/groovy.adoc b/docs/modules/ROOT/pages/languages/groovy.adoc
index 5f2277b0f..fa4ac1035 100644
--- a/docs/modules/ROOT/pages/languages/groovy.adoc
+++ b/docs/modules/ROOT/pages/languages/groovy.adoc
@@ -147,10 +147,10 @@ beans {
 <1> define a bean
 <2> define a custom processor
 <3> define a custom predicate
-<3> define a custom bean with name `dataSource` and type `org.apache.commons.dbcp2.BasicDataSource`
+<4> define a custom bean with name `dataSource` and type `org.apache.commons.dbcp2.BasicDataSource`
 
 
-=== Rest Support
+== Rest Support
 
 Integrations's REST endpoints can be configured using the top level _rest_ block:
 
@@ -180,4 +180,4 @@ rest {
 ----
 <1> Configure the rest engine
 <2> Configure the behavior of the method GET for the path '/my/path/get' and invoke the endpoint 'direct:get'
-<2> Configure the behavior of the method POST for the path '/post' and invoke the endpoint 'direct:post'
+<3> Configure the behavior of the method POST for the path '/post' and invoke the endpoint 'direct:post'
diff --git a/docs/modules/ROOT/pages/traits/knative.adoc b/docs/modules/ROOT/pages/traits/knative.adoc
index f3b44a767..50d27e6a7 100755
--- a/docs/modules/ROOT/pages/traits/knative.adoc
+++ b/docs/modules/ROOT/pages/traits/knative.adoc
@@ -69,11 +69,6 @@ Can contain simple event types or full Camel URIs (to use a specific broker).
 that can be removed in a future version of Knative, filtering is enabled only when the integration is
 listening from more than 1 channel.
 
-| knative.knative-08-compat-mode
-| bool
-| The Knative 0.8 compatibility mode will check the installed version of Knative and
-use resource versions compatible with Knative 0.8 if found on the cluster.
-
 | knative.auto
 | bool
 | Enable automatic discovery of all trait properties.
diff --git a/docs/modules/ROOT/pages/traits/platform.adoc b/docs/modules/ROOT/pages/traits/platform.adoc
new file mode 100755
index 000000000..29d29ca49
--- /dev/null
+++ b/docs/modules/ROOT/pages/traits/platform.adoc
@@ -0,0 +1,43 @@
+= Platform Trait
+
+// Start of autogenerated code - DO NOT EDIT! (description)
+The platform trait is a base trait that is used to assign an integration platform to an integration.
+
+In case the platform is missing, the trait is allowed to create a default platform.
+This feature is especially useful in contexts where there's no need to provide a custom configuration for the platform
+(e.g. on OpenShift the default settings work, since there's an embedded container image registry).
+
+
+This trait is available in the following profiles: **Kubernetes, Knative, OpenShift**.
+
+WARNING: The platform trait is a *platform trait*: disabling it may compromise the platform functionality.
+
+// End of autogenerated code - DO NOT EDIT! (description)
+// Start of autogenerated code - DO NOT EDIT! (configuration)
+== Configuration
+
+Trait properties can be specified when running any integration with the CLI:
+```
+kamel run --trait platform.[key]=[value] integration.groovy
+```
+The following configuration options are available:
+
+[cols="2,1,5a"]
+|===
+|Property | Type | Description
+
+| platform.enabled
+| bool
+| Can be used to enable or disable a trait. All traits share this common property.
+
+| platform.create-default
+| bool
+| To create a default (empty) platform when the platform is missing.
+
+| platform.auto
+| bool
+| To automatically detect from the environment if a default platform can be created (it will be created on OpenShift only).
+
+|===
+
+// End of autogenerated code - DO NOT EDIT! (configuration)
diff --git a/docs/modules/ROOT/pages/traits/traits.adoc b/docs/modules/ROOT/pages/traits/traits.adoc
index 3a3d04389..1312b4d34 100644
--- a/docs/modules/ROOT/pages/traits/traits.adoc
+++ b/docs/modules/ROOT/pages/traits/traits.adoc
@@ -51,6 +51,7 @@ See the trait description pages for more information on a specific trait:
 * xref:traits/knative-service.adoc[Knative Service Trait]
 * xref:traits/knative.adoc[Knative Trait]
 * xref:traits/owner.adoc[Owner Trait]
+* xref:traits/platform.adoc[Platform Trait]
 * xref:traits/probes.adoc[Probes Trait]
 * xref:traits/prometheus.adoc[Prometheus Trait]
 * xref:traits/pull-secret.adoc[Pull Secret Trait]
diff --git a/examples/Readme.md b/examples/README.md
similarity index 100%
rename from examples/Readme.md
rename to examples/README.md
diff --git a/examples/saga/Flight.java b/examples/saga/Flight.java
new file mode 100644
index 000000000..0810c3c41
--- /dev/null
+++ b/examples/saga/Flight.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.SagaPropagation;
+import org.apache.camel.model.rest.RestParamType;
+import org.apache.camel.service.lra.LRASagaService;
+import org.apache.camel.Exchange;
+
+public class Flight extends RouteBuilder {
+	@Override
+	public void configure() throws Exception {
+                restConfiguration().port("8080");
+
+		LRASagaService service = new LRASagaService();
+		service.setCoordinatorUrl("http://lra-coordinator:8080");
+		service.setLocalParticipantUrl("http://flight:8080");
+		getContext().addService(service);
+
+		rest("/api").post("/flight/buy")
+			.param().type(RestParamType.header).name("id").required(true).endParam()
+			.route()
+			.saga()
+				.propagation(SagaPropagation.MANDATORY)
+				.option("id", header("id"))
+				.compensation("direct:cancelPurchase")
+			.log("Buying flight #${header.id}")
+			.to("http://payment:8080/api/pay?bridgeEndpoint=true&type=flight")
+			.log("Payment for flight #${header.id} done");
+
+		from("direct:cancelPurchase")
+			.log("Flight purchase #${header.id} has been cancelled");
+	}
+}
diff --git a/examples/saga/Payment.java b/examples/saga/Payment.java
new file mode 100644
index 000000000..a4a866b12
--- /dev/null
+++ b/examples/saga/Payment.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.SagaPropagation;
+import org.apache.camel.model.rest.RestParamType;
+import org.apache.camel.service.lra.LRASagaService;
+import org.apache.camel.Exchange;
+
+public class Payment extends RouteBuilder {
+	@Override
+	public void configure() throws Exception {
+                restConfiguration().port("8080");
+
+		LRASagaService service = new LRASagaService();
+		service.setCoordinatorUrl("http://lra-coordinator:8080");
+		service.setLocalParticipantUrl("http://payment:8080");
+		getContext().addService(service);
+
+		rest("/api/").post("/pay")
+                    .param().type(RestParamType.query).name("type").required(true).endParam()
+                    .param().type(RestParamType.header).name("id").required(true).endParam()
+                    .route()
+                    .saga()
+                        .propagation(SagaPropagation.MANDATORY)
+                        .option("id", header("id"))
+                        .compensation("direct:cancelPayment")
+                    .log("Paying ${header.type} for order #${header.id}")
+                    .choice()
+                        .when(x -> Math.random() >= 0.85)
+                            .throwException(new RuntimeException("Random failure during payment"))
+                    .end();
+
+                from("direct:cancelPayment")
+                    .log("Payment #${header.id} has been cancelled");
+	}
+}
diff --git a/examples/saga/Readme.md b/examples/saga/Readme.md
new file mode 100644
index 000000000..5856c85cc
--- /dev/null
+++ b/examples/saga/Readme.md
@@ -0,0 +1,22 @@
+# Saga example
+This example is from [camel-saga-quickstart](https://github.com/nicolaferraro/camel-saga-quickstart/) and could work with the camel-k.
+
+* Start the lra-coordinator by using the openshift
+```
+oc create -f lra-coordinator.yaml
+```
+* Or start the lra-coordinator by using the kubernetes
+```
+kubectl create -f lra-coordiantor-kub.yaml
+```
+* Start the three demo services
+```
+kamel run -t container.service-port=8080 --dependency=camel-rest --dependency=camel-undertow --dependency=camel-lra examples/saga/Flight.java
+kamel run -t container.service-port=8080 --dependency=camel-rest --dependency=camel-undertow --dependency=camel-lra examples/saga/Train.java
+kamel run -t container.service-port=8080 --dependency=camel-rest --dependency=camel-undertow --dependency=camel-lra examples/saga/Payment.java
+```
+* Start the saga application
+```
+kamel run -t container.service-port=8080 --dependency=camel-rest --dependency=camel-undertow --dependency=camel-lra examples/saga/Saga.java
+```
+Then you can use ```kamel log saga``` to check the output of the transactions.
diff --git a/examples/saga/Saga.java b/examples/saga/Saga.java
new file mode 100644
index 000000000..ff127b5ce
--- /dev/null
+++ b/examples/saga/Saga.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.service.lra.LRASagaService;
+import org.apache.camel.Exchange;
+
+public class Saga extends RouteBuilder {
+	@Override
+	public void configure() throws Exception {
+                restConfiguration().port("8080");
+
+		LRASagaService service = new LRASagaService();
+		service.setCoordinatorUrl("http://lra-coordinator:8080");
+		service.setLocalParticipantUrl("http://saga:8080");
+		getContext().addService(service);
+
+		from("timer:clock?period=5s")
+			.saga()
+			.setHeader("id", header(Exchange.TIMER_COUNTER))
+			.setHeader(Exchange.HTTP_METHOD, constant("POST"))
+			.log("Executing saga #${header.id}")
+			.to("http://train:8080/api/train/buy/seat")
+			.to("http://flight:8080/api/flight/buy");
+
+	}
+}
diff --git a/examples/saga/Train.java b/examples/saga/Train.java
new file mode 100644
index 000000000..2c71fc5a2
--- /dev/null
+++ b/examples/saga/Train.java
@@ -0,0 +1,48 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.SagaPropagation;
+import org.apache.camel.model.rest.RestParamType;
+import org.apache.camel.service.lra.LRASagaService;
+import org.apache.camel.Exchange;
+
+public class Train extends RouteBuilder {
+	@Override
+	public void configure() throws Exception {
+                restConfiguration().port("8080");
+
+		LRASagaService service = new LRASagaService();
+		service.setCoordinatorUrl("http://lra-coordinator:8080");
+		service.setLocalParticipantUrl("http://train:8080");
+		getContext().addService(service);
+
+		rest("/api/").post("/train/buy/seat")
+                    .param().type(RestParamType.header).name("id").required(true).endParam()
+                    .route()
+                    .saga()
+                        .propagation(SagaPropagation.SUPPORTS)
+                        .option("id", header("id"))
+                        .compensation("direct:cancelPurchase")
+                    .log("Buying train seat #${header.id}")
+                    .to("http://payment:8080/api/pay?bridgeEndpoint=true&type=train")
+                    .log("Payment for train #${header.id} done");
+
+               from("direct:cancelPurchase")
+                    .log("Train purchase #${header.id} has been cancelled");
+	}
+}
diff --git a/examples/saga/lra-coordinator-kub.yaml b/examples/saga/lra-coordinator-kub.yaml
new file mode 100644
index 000000000..c854fc282
--- /dev/null
+++ b/examples/saga/lra-coordinator-kub.yaml
@@ -0,0 +1,81 @@
+apiVersion: v1
+kind: List
+items:
+- apiVersion: v1
+  kind: Service
+  metadata:
+    labels:
+      app: lra-coordinator
+      template: lra-coordinator
+    name: lra-coordinator
+  spec:
+    ports:
+    - name: 8080-tcp
+      port: 8080
+      protocol: TCP
+      targetPort: 8080
+    selector:
+      app: lra-coordinator
+    type: ClusterIP
+- apiVersion: v1
+  kind: PersistentVolumeClaim
+  metadata:
+    labels:
+      app: lra-coordinator
+      template: lra-coordinator
+    name: lra-coordinator
+  spec:
+    accessModes:
+    - ReadWriteOnce
+    resources:
+      requests:
+        storage: 200Mi
+- apiVersion: apps/v1
+  kind: Deployment
+  metadata:
+    generation: 1
+    labels:
+      app: lra-coordinator
+      template: lra-coordinator
+    name: lra-coordinator
+  spec:
+    replicas: 1
+    selector:
+      matchLabels:
+        app: lra-coordinator
+    strategy:
+      type: Recreate
+    template:
+      metadata:
+        labels:
+          app: lra-coordinator
+      spec:
+        containers:
+        - imagePullPolicy: IfNotPresent
+          env:
+          - name: AB_JOLOKIA_OFF
+            value: "true"
+          livenessProbe:
+            httpGet:
+              path: /lra-coordinator
+              port: 8080
+              scheme: HTTP
+            initialDelaySeconds: 180
+          name: lra-coordinator
+          image: docker.io/jbosstm/lra-coordinator:5.9.4.Final
+          ports:
+          - containerPort: 8080
+            protocol: TCP
+          readinessProbe:
+            httpGet:
+              path: /lra-coordinator
+              port: 8080
+              scheme: HTTP
+            initialDelaySeconds: 10
+          volumeMounts:
+          - mountPath: /data
+            name: lra-coordinator-data
+        volumes:
+        - name: lra-coordinator-data
+          persistentVolumeClaim:
+            claimName: lra-coordinator
diff --git a/examples/saga/lra-coordinator.yaml b/examples/saga/lra-coordinator.yaml
new file mode 100644
index 000000000..c59fe26f1
--- /dev/null
+++ b/examples/saga/lra-coordinator.yaml
@@ -0,0 +1,111 @@
+apiVersion: v1
+kind: List
+items:
+- apiVersion: v1
+  kind: Service
+  metadata:
+    labels:
+      app: lra-coordinator
+      template: lra-coordinator
+    name: lra-coordinator
+  spec:
+    ports:
+    - name: 8080-tcp
+      port: 8080
+      protocol: TCP
+      targetPort: 8080
+    selector:
+      app: lra-coordinator
+      deploymentconfig: lra-coordinator
+    type: ClusterIP
+- apiVersion: v1
+  kind: PersistentVolumeClaim
+  metadata:
+    labels:
+      app: lra-coordinator
+      template: lra-coordinator
+    name: lra-coordinator
+  spec:
+    accessModes:
+    - ReadWriteOnce
+    resources:
+      requests:
+        storage: 200Mi
+- apiVersion: v1
+  kind: ImageStream
+  metadata:
+    labels:
+      app: lra-coordinator
+      template: lra-coordinator
+    name: lra-coordinator
+  spec:
+    lookupPolicy:
+      local: true
+    tags:
+    - from:
+        kind: DockerImage
+        name: docker.io/jbosstm/lra-coordinator:5.9.4.Final
+      generation: 0
+      importPolicy: {}
+      name: "5.9.4.Final"
+      referencePolicy:
+        type: Source
+- apiVersion: v1
+  kind: DeploymentConfig
+  metadata:
+    generation: 1
+    labels:
+      app: lra-coordinator
+      template: lra-coordinator
+    name: lra-coordinator
+  spec:
+    replicas: 1
+    selector:
+      app: lra-coordinator
+      deploymentconfig: lra-coordinator
+    strategy:
+      type: Recreate
+    template:
+      metadata:
+        labels:
+          app: lra-coordinator
+          deploymentconfig: lra-coordinator
+      spec:
+        containers:
+        - imagePullPolicy: IfNotPresent
+          env:
+          - name: AB_JOLOKIA_OFF
+            value: "true"
+          livenessProbe:
+            httpGet:
+              path: /lra-coordinator
+              port: 8080
+              scheme: HTTP
+            initialDelaySeconds: 180
+          name: lra-coordinator
+          ports:
+          - containerPort: 8080
+            protocol: TCP
+          readinessProbe:
+            httpGet:
+              path: /lra-coordinator
+              port: 8080
+              scheme: HTTP
+            initialDelaySeconds: 10
+          volumeMounts:
+          - mountPath: /data
+            name: lra-coordinator-data
+        volumes:
+        - name: lra-coordinator-data
+          persistentVolumeClaim:
+            claimName: lra-coordinator
+    triggers:
+    - type: ConfigChange
+    - imageChangeParams:
+        automatic: true
+        containerNames:
+        - lra-coordinator
+        from:
+          kind: ImageStreamTag
+          name: "lra-coordinator:5.9.4.Final"
+      type: ImageChange
diff --git a/go.mod b/go.mod
index d35bfdf56..5af83f59d 100644
--- a/go.mod
+++ b/go.mod
@@ -31,9 +31,9 @@ require (
 	k8s.io/apimachinery v0.0.0
 	k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible
 	k8s.io/gengo v0.0.0-20191010091904-7fa3014cb28f
-	knative.dev/eventing v0.9.0
-	knative.dev/pkg v0.0.0-20191017202117-b5a8deb92e5c
-	knative.dev/serving v0.9.0
+	knative.dev/eventing v0.10.0
+	knative.dev/pkg v0.0.0-20191107185656-884d50f09454
+	knative.dev/serving v0.10.0
 	sigs.k8s.io/controller-runtime v0.3.0
 )
 
diff --git a/go.sum b/go.sum
index cebac5f23..c55c3c8a1 100644
--- a/go.sum
+++ b/go.sum
@@ -776,12 +776,12 @@ k8s.io/utils v0.0.0-20190221042446-c2654d5206da/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3
 k8s.io/utils v0.0.0-20190308190857-21c4ce38f2a7/go.mod h1:8k8uAuAQ0rXslZKaEWd0c3oVhZz7sSzSiPnVZayjIX0=
 k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5 h1:VBM/0P5TWxwk+Nw6Z+lAw3DKgO76g90ETOiA6rfLV1Y=
 k8s.io/utils v0.0.0-20190506122338-8fab8cb257d5/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
-knative.dev/eventing v0.9.0 h1:0eqp7rES1E5DE5Hj3MOHHyM2BzCe/7Mtp5tPjYoeCxs=
-knative.dev/eventing v0.9.0/go.mod h1:UxweNv8yXhsdHJitcb9R6rmfNaUD2DFi9GWwNRyIs58=
-knative.dev/pkg v0.0.0-20191017202117-b5a8deb92e5c h1:8JcuEBoJQJ6XyR72emqB2cQg/3UZfRREY2lMAJw92n4=
-knative.dev/pkg v0.0.0-20191017202117-b5a8deb92e5c/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
-knative.dev/serving v0.9.0 h1:GVnsksAEX6vMXGygvzsGPIrFTypiesaseK7emm0LKWQ=
-knative.dev/serving v0.9.0/go.mod h1:x2n255JS2XBI39tmjZ8CwTxIf9EKNMCrkVuiOttLRm0=
+knative.dev/eventing v0.10.0 h1:dDrOjBWWgloOCUjxR8ixUIh8nqCTbmM5BbGo8rvf1bc=
+knative.dev/eventing v0.10.0/go.mod h1:UxweNv8yXhsdHJitcb9R6rmfNaUD2DFi9GWwNRyIs58=
+knative.dev/pkg v0.0.0-20191107185656-884d50f09454 h1:nkslWFyRWaJp3nPDm+GSQOSvN8NpZg8qIYTR+XssNNg=
+knative.dev/pkg v0.0.0-20191107185656-884d50f09454/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
+knative.dev/serving v0.10.0 h1:T1csznAQrc/DvCE4KROz4NqOtJ24mnU9eF9RMeeYaCc=
+knative.dev/serving v0.10.0/go.mod h1:x2n255JS2XBI39tmjZ8CwTxIf9EKNMCrkVuiOttLRm0=
 modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
 modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
 modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
diff --git a/pkg/apis/addtoscheme_knative_eventing_08_compat_v1alpha1.go b/pkg/apis/addtoscheme_knative_eventing_08_compat_v1alpha1.go
deleted file mode 100644
index 51734f44d..000000000
--- a/pkg/apis/addtoscheme_knative_eventing_08_compat_v1alpha1.go
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-   http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package apis
-
-import (
-	"github.com/apache/camel-k/pkg/apis/knative08compat"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/runtime"
-)
-
-var (
-	compat08SchemeBuilder = runtime.NewSchemeBuilder(eventing08CompatKnownTypes)
-	compat08AddToScheme   = compat08SchemeBuilder.AddToScheme
-)
-
-func init() {
-	AddToSchemes = append(AddToSchemes, compat08AddToScheme)
-}
-
-// eventing08CompatKnownTypes Adds the list of known types to Scheme.
-func eventing08CompatKnownTypes(scheme *runtime.Scheme) error {
-	scheme.AddKnownTypes(knative08compat.CompatSchemeGroupVersion,
-		&knative08compat.Subscription{},
-		&knative08compat.SubscriptionList{},
-	)
-	metav1.AddToGroupVersion(scheme, knative08compat.CompatSchemeGroupVersion)
-	return nil
-}
diff --git a/pkg/apis/addtoscheme_knative_serving_v1alpha1.go b/pkg/apis/addtoscheme_knative_serving_v1alpha1.go
index b96c913c2..f270608e9 100644
--- a/pkg/apis/addtoscheme_knative_serving_v1alpha1.go
+++ b/pkg/apis/addtoscheme_knative_serving_v1alpha1.go
@@ -18,7 +18,7 @@ limitations under the License.
 package apis
 
 import (
-	serving "knative.dev/serving/pkg/apis/serving/v1beta1"
+	serving "knative.dev/serving/pkg/apis/serving/v1"
 )
 
 func init() {
diff --git a/pkg/apis/camel/v1alpha1/common_types.go b/pkg/apis/camel/v1alpha1/common_types.go
index f54c19c30..c3472f6bd 100644
--- a/pkg/apis/camel/v1alpha1/common_types.go
+++ b/pkg/apis/camel/v1alpha1/common_types.go
@@ -77,9 +77,9 @@ type PlatformInjectable interface {
 
 // MavenSpec --
 type MavenSpec struct {
-	LocalRepository string          `json:"localRepository,omitempty"`
-	Settings        ValueSource     `json:"settings,omitempty"`
-	Timeout         metav1.Duration `json:"timeout,omitempty"`
+	LocalRepository string           `json:"localRepository,omitempty"`
+	Settings        ValueSource      `json:"settings,omitempty"`
+	Timeout         *metav1.Duration `json:"timeout,omitempty"`
 }
 
 // ValueSource --
@@ -87,7 +87,7 @@ type ValueSource struct {
 	// Selects a key of a ConfigMap.
 	ConfigMapKeyRef *corev1.ConfigMapKeySelector `json:"configMapKeyRef,omitempty"`
 	// Selects a key of a secret.
-	SecretKeyRef *corev1.SecretKeySelector `json:"secretKeyRef,omitempty" `
+	SecretKeyRef *corev1.SecretKeySelector `json:"secretKeyRef,omitempty"`
 }
 
 const (
diff --git a/pkg/apis/camel/v1alpha1/integrationplatform_types.go b/pkg/apis/camel/v1alpha1/integrationplatform_types.go
index 3e17daf31..67ebe24c1 100644
--- a/pkg/apis/camel/v1alpha1/integrationplatform_types.go
+++ b/pkg/apis/camel/v1alpha1/integrationplatform_types.go
@@ -41,6 +41,8 @@ type IntegrationPlatformResourcesSpec struct {
 
 // IntegrationPlatformStatus defines the observed state of IntegrationPlatform
 type IntegrationPlatformStatus struct {
+	IntegrationPlatformSpec `json:",inline"`
+
 	Phase      IntegrationPlatformPhase       `json:"phase,omitempty"`
 	Conditions []IntegrationPlatformCondition `json:"conditions,omitempty"`
 	Version    string                         `json:"version,omitempty"`
@@ -91,6 +93,8 @@ const (
 	TraitProfileKubernetes = "Kubernetes"
 	// TraitProfileKnative is used by default on OpenShift/Kubernetes clusters powered by Knative
 	TraitProfileKnative = "Knative"
+	// DefaultTraitProfile is the trait profile used as default when no other profile is set
+	DefaultTraitProfile = TraitProfileKubernetes
 )
 
 // AllTraitProfiles contains all allowed profiles
@@ -106,7 +110,7 @@ type IntegrationPlatformBuildSpec struct {
 	BaseImage             string                                  `json:"baseImage,omitempty"`
 	Properties            map[string]string                       `json:"properties,omitempty"`
 	Registry              IntegrationPlatformRegistrySpec         `json:"registry,omitempty"`
-	Timeout               metav1.Duration                         `json:"timeout,omitempty"`
+	Timeout               *metav1.Duration                        `json:"timeout,omitempty"`
 	PersistentVolumeClaim string                                  `json:"persistentVolumeClaim,omitempty"`
 	Maven                 MavenSpec                               `json:"maven,omitempty"`
 	HTTPProxySecret       string                                  `json:"httpProxySecret,omitempty"`
diff --git a/pkg/apis/camel/v1alpha1/integrationplatform_types_support.go b/pkg/apis/camel/v1alpha1/integrationplatform_types_support.go
index 1edbdbdfe..d85cc34c4 100644
--- a/pkg/apis/camel/v1alpha1/integrationplatform_types_support.go
+++ b/pkg/apis/camel/v1alpha1/integrationplatform_types_support.go
@@ -73,6 +73,10 @@ func (in *IntegrationPlatform) Configurations() []ConfigurationSpec {
 		return []ConfigurationSpec{}
 	}
 
+	if len(in.Status.Configuration) > 0 {
+		return in.Status.Configuration
+	}
+
 	return in.Spec.Configuration
 }
 
@@ -84,6 +88,21 @@ func (in *IntegrationPlatform) AddConfiguration(confType string, confValue strin
 	})
 }
 
+// GetActualValue can be used to extract information the platform spec or its derived config in the status
+func (in *IntegrationPlatform) GetActualValue(extractor func(spec IntegrationPlatformSpec) string) string {
+	res := extractor(in.Status.IntegrationPlatformSpec)
+	if res == "" {
+		res = extractor(in.Spec)
+	}
+	return res
+}
+
+// ResyncStatusFullConfig copies the spec configuration into the status-fullConfig field.
+func (in *IntegrationPlatform) ResyncStatusFullConfig() {
+	cl := in.Spec.DeepCopy()
+	in.Status.IntegrationPlatformSpec = *cl
+}
+
 // GetCondition returns the condition with the provided type.
 func (in *IntegrationPlatformStatus) GetCondition(condType IntegrationPlatformConditionType) *IntegrationPlatformCondition {
 	for i := range in.Conditions {
@@ -167,3 +186,19 @@ func (b IntegrationPlatformBuildSpec) IsKanikoCacheEnabled() bool {
 	}
 	return *b.KanikoBuildCache
 }
+
+// GetTimeout returns the specified duration or a default one
+func (b IntegrationPlatformBuildSpec) GetTimeout() metav1.Duration {
+	if b.Timeout == nil {
+		return metav1.Duration{}
+	}
+	return *b.Timeout
+}
+
+// GetTimeout returns the specified duration or a default one
+func (m MavenSpec) GetTimeout() metav1.Duration {
+	if m.Timeout == nil {
+		return metav1.Duration{}
+	}
+	return *m.Timeout
+}
diff --git a/pkg/apis/knative08compat/knative08compat.go b/pkg/apis/knative08compat/knative08compat.go
deleted file mode 100644
index 395aae34f..000000000
--- a/pkg/apis/knative08compat/knative08compat.go
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
-Licensed to the Apache Software Foundation (ASF) under one or more
-contributor license agreements.  See the NOTICE file distributed with
-this work for additional information regarding copyright ownership.
-The ASF licenses this file to You under the Apache License, Version 2.0
-(the "License"); you may not use this file except in compliance with
-the License.  You may obtain a copy of the License at
-
-   http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-*/
-
-package knative08compat
-
-import (
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/runtime"
-	"k8s.io/apimachinery/pkg/runtime/schema"
-	messaging "knative.dev/eventing/pkg/apis/messaging/v1alpha1"
-)
-
-// CompatSchemeGroupVersion is the old group version used in Knative 0.8
-var CompatSchemeGroupVersion = schema.GroupVersion{
-	Group:   "eventing.knative.dev",
-	Version: "v1alpha1",
-}
-
-// Subscription is a Knative 0.8 compatibility version for messaging.Subscription
-type Subscription struct {
-	metav1.TypeMeta   `json:",inline"`
-	metav1.ObjectMeta `json:"metadata"`
-	Spec              messaging.SubscriptionSpec   `json:"spec"`
-	Status            messaging.SubscriptionStatus `json:"status,omitempty"`
-}
-
-// SubscriptionList is a Knative 0.8 compatibility version for messaging.SubscriptionList
-type SubscriptionList struct {
-	metav1.TypeMeta `json:",inline"`
-	metav1.ListMeta `json:"metadata"`
-	Items           []Subscription `json:"items"`
-}
-
-// FromMessagingSubscription creates a compat08 subscription from a messaging.Subscription
-func FromMessagingSubscription(s messaging.Subscription) *Subscription {
-	in := s.DeepCopy()
-	out := Subscription{
-		TypeMeta:   in.TypeMeta,
-		ObjectMeta: in.ObjectMeta,
-		Spec:       in.Spec,
-		Status:     in.Status,
-	}
-	// fix API group
-	out.TypeMeta.APIVersion = CompatSchemeGroupVersion.String()
-	return &out
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *Subscription) DeepCopyInto(out *Subscription) {
-	*out = *in
-	out.TypeMeta = in.TypeMeta
-	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
-	in.Spec.DeepCopyInto(&out.Spec)
-	in.Status.DeepCopyInto(&out.Status)
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Subscription.
-func (in *Subscription) DeepCopy() *Subscription {
-	if in == nil {
-		return nil
-	}
-	out := new(Subscription)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
-func (in *Subscription) DeepCopyObject() runtime.Object {
-	if c := in.DeepCopy(); c != nil {
-		return c
-	}
-	return nil
-}
-
-// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
-func (in *SubscriptionList) DeepCopyInto(out *SubscriptionList) {
-	*out = *in
-	out.TypeMeta = in.TypeMeta
-	out.ListMeta = in.ListMeta
-	if in.Items != nil {
-		in, out := &in.Items, &out.Items
-		*out = make([]Subscription, len(*in))
-		for i := range *in {
-			(*in)[i].DeepCopyInto(&(*out)[i])
-		}
-	}
-}
-
-// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionList.
-func (in *SubscriptionList) DeepCopy() *SubscriptionList {
-	if in == nil {
-		return nil
-	}
-	out := new(SubscriptionList)
-	in.DeepCopyInto(out)
-	return out
-}
-
-// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
-func (in *SubscriptionList) DeepCopyObject() runtime.Object {
-	if c := in.DeepCopy(); c != nil {
-		return c
-	}
-	return nil
-}
diff --git a/pkg/builder/runtime/main.go b/pkg/builder/runtime/main.go
index 4f2cb3e9b..a191afd03 100644
--- a/pkg/builder/runtime/main.go
+++ b/pkg/builder/runtime/main.go
@@ -87,7 +87,7 @@ func computeDependencies(ctx *builder.Context) error {
 	mc := maven.NewContext(path.Join(ctx.Path, "maven"), ctx.Maven.Project)
 	mc.SettingsContent = ctx.Maven.SettingsData
 	mc.LocalRepository = ctx.Build.Platform.Build.Maven.LocalRepository
-	mc.Timeout = ctx.Build.Platform.Build.Maven.Timeout.Duration
+	mc.Timeout = ctx.Build.Platform.Build.Maven.GetTimeout().Duration
 	mc.AddArgumentf("org.apache.camel.k:camel-k-maven-plugin:%s:generate-dependency-list", ctx.Catalog.RuntimeVersion)
 
 	if err := maven.Run(mc); err != nil {
diff --git a/pkg/builder/runtime/quarkus.go b/pkg/builder/runtime/quarkus.go
index bd6d92a3e..f9c980902 100644
--- a/pkg/builder/runtime/quarkus.go
+++ b/pkg/builder/runtime/quarkus.go
@@ -107,7 +107,7 @@ func computeQuarkusDependencies(ctx *builder.Context) error {
 	mc := maven.NewContext(path.Join(ctx.Path, "maven"), ctx.Maven.Project)
 	mc.SettingsContent = ctx.Maven.SettingsData
 	mc.LocalRepository = ctx.Build.Platform.Build.Maven.LocalRepository
-	mc.Timeout = ctx.Build.Platform.Build.Maven.Timeout.Duration
+	mc.Timeout = ctx.Build.Platform.Build.Maven.GetTimeout().Duration
 
 	// Build the project
 	mc.AddArgument("package")
diff --git a/pkg/builder/s2i/publisher.go b/pkg/builder/s2i/publisher.go
index 9eadd472c..eb8c59885 100644
--- a/pkg/builder/s2i/publisher.go
+++ b/pkg/builder/s2i/publisher.go
@@ -156,7 +156,7 @@ func publisher(ctx *builder.Context) error {
 			}
 		}
 		return false, nil
-	}, ctx.Build.Platform.Build.Timeout.Duration)
+	}, ctx.Build.Platform.Build.GetTimeout().Duration)
 
 	if err != nil {
 		return err
diff --git a/pkg/cmd/describe_platform.go b/pkg/cmd/describe_platform.go
index 58e74a1fd..162a7a0b9 100644
--- a/pkg/cmd/describe_platform.go
+++ b/pkg/cmd/describe_platform.go
@@ -90,17 +90,37 @@ func (command *describePlatformCommand) describeIntegrationPlatform(platform v1a
 		describeObjectMeta(w, platform.ObjectMeta)
 		w.Write(0, "Phase:\t%s\n", platform.Status.Phase)
 		w.Write(0, "Version:\t%s\n", platform.Status.Version)
-		w.Write(0, "Base Image:\t%s\n", platform.Spec.Build.BaseImage)
-		w.Write(0, "Camel Version:\t%s\n", platform.Spec.Build.CamelVersion)
-		w.Write(0, "Local Repository:\t%s\n", platform.Spec.Build.Maven.LocalRepository)
-		w.Write(0, "Publish Strategy:\t%s\n", platform.Spec.Build.PublishStrategy)
-
-		if len(platform.Spec.Resources.Kits) > 0 {
+		w.Write(0, "Base Image:\t%s\n", platform.GetActualValue(getPlatformBaseImage))
+		w.Write(0, "Camel Version:\t%s\n", platform.GetActualValue(getPlatformCamelVersion))
+		w.Write(0, "Local Repository:\t%s\n", platform.GetActualValue(getPlatformMavenLocalRepository))
+		w.Write(0, "Publish Strategy:\t%s\n", platform.GetActualValue(getPlatformPublishStrategy))
+
+		kits := platform.Status.Resources.Kits
+		if len(kits) == 0 {
+			kits = platform.Spec.Resources.Kits
+		}
+		if len(kits) > 0 {
 			w.Write(0, "Resources:\n")
 			w.Write(1, "Kits:\n")
-			for _, kit := range platform.Spec.Resources.Kits {
+			for _, kit := range kits {
 				w.Write(2, "%s\n", kit)
 			}
 		}
 	})
 }
+
+func getPlatformBaseImage(spec v1alpha1.IntegrationPlatformSpec) string {
+	return spec.Build.BaseImage
+}
+
+func getPlatformCamelVersion(spec v1alpha1.IntegrationPlatformSpec) string {
+	return spec.Build.CamelVersion
+}
+
+func getPlatformMavenLocalRepository(spec v1alpha1.IntegrationPlatformSpec) string {
+	return spec.Build.Maven.LocalRepository
+}
+
+func getPlatformPublishStrategy(spec v1alpha1.IntegrationPlatformSpec) string {
+	return string(spec.Build.PublishStrategy)
+}
diff --git a/pkg/cmd/install.go b/pkg/cmd/install.go
index c3af624f8..56f8c33aa 100644
--- a/pkg/cmd/install.go
+++ b/pkg/cmd/install.go
@@ -25,6 +25,7 @@ import (
 
 	"github.com/apache/camel-k/pkg/util/registry"
 	"go.uber.org/multierr"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 
 	"github.com/apache/camel-k/deploy"
@@ -235,7 +236,9 @@ func (o *installCmdOptions) install(cobraCmd *cobra.Command, _ []string) error {
 				return err
 			}
 
-			platform.Spec.Build.Timeout.Duration = d
+			platform.Spec.Build.Timeout = &metav1.Duration{
+				Duration: d,
+			}
 		}
 		if o.traitProfile != "" {
 			platform.Spec.Profile = v1alpha1.TraitProfileByName(o.traitProfile)
@@ -269,12 +272,8 @@ func (o *installCmdOptions) install(cobraCmd *cobra.Command, _ []string) error {
 
 		kanikoBuildCacheFlag := cobraCmd.Flags().Lookup("kaniko-build-cache")
 
-		defaultKanikoBuildCache := true
-
 		if kanikoBuildCacheFlag.Changed {
 			platform.Spec.Build.KanikoBuildCache = &o.kanikoBuildCache
-		} else {
-			platform.Spec.Build.KanikoBuildCache = &defaultKanikoBuildCache
 		}
 
 		platform.Spec.Resources.Kits = o.kits
diff --git a/pkg/controller/build/build_controller.go b/pkg/controller/build/build_controller.go
index 761c1b58b..b6d227d32 100644
--- a/pkg/controller/build/build_controller.go
+++ b/pkg/controller/build/build_controller.go
@@ -14,6 +14,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
+
 package build
 
 import (
@@ -23,7 +24,6 @@ import (
 
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/errors"
-	k8serrors "k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/runtime"
 
 	k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
@@ -39,7 +39,6 @@ import (
 	"github.com/apache/camel-k/pkg/builder"
 	"github.com/apache/camel-k/pkg/client"
 	"github.com/apache/camel-k/pkg/platform"
-	"github.com/apache/camel-k/pkg/util/log"
 )
 
 // Add creates a new Build Controller and adds it to the Manager. The Manager will set fields on the Controller
@@ -153,7 +152,7 @@ func (r *ReconcileBuild) Reconcile(request reconcile.Request) (reconcile.Result,
 	targetLog := rlog.ForBuild(target)
 
 	if target.Status.Phase == v1alpha1.BuildPhaseNone || target.Status.Phase == v1alpha1.BuildPhaseWaitingForPlatform {
-		pl, err := platform.GetOrLookup(ctx, r.client, target.Namespace, target.Status.Platform)
+		pl, err := platform.GetOrLookupCurrent(ctx, r.client, target.Namespace, target.Status.Platform)
 		if err != nil || pl.Status.Phase != v1alpha1.IntegrationPlatformPhaseReady {
 			target.Status.Phase = v1alpha1.BuildPhaseWaitingForPlatform
 		} else {
@@ -169,7 +168,7 @@ func (r *ReconcileBuild) Reconcile(request reconcile.Request) (reconcile.Result,
 				target.SetIntegrationPlatform(pl)
 			}
 
-			return r.update(ctx, targetLog, target)
+			return r.update(ctx, &instance, target)
 		}
 
 		return reconcile.Result{}, err
@@ -199,7 +198,7 @@ func (r *ReconcileBuild) Reconcile(request reconcile.Request) (reconcile.Result,
 			}
 
 			if newTarget != nil {
-				if r, err := r.update(ctx, targetLog, newTarget); err != nil {
+				if r, err := r.update(ctx, &instance, newTarget); err != nil {
 					return r, err
 				}
 
@@ -230,18 +229,8 @@ func (r *ReconcileBuild) Reconcile(request reconcile.Request) (reconcile.Result,
 	return reconcile.Result{}, nil
 }
 
-// Update --
-func (r *ReconcileBuild) update(ctx context.Context, log log.Logger, target *v1alpha1.Build) (reconcile.Result, error) {
-	err := r.client.Status().Update(ctx, target)
-	if err != nil {
-		if k8serrors.IsConflict(err) {
-			log.Error(err, "conflict")
-
-			return reconcile.Result{
-				Requeue: true,
-			}, nil
-		}
-	}
+func (r *ReconcileBuild) update(ctx context.Context, base *v1alpha1.Build, target *v1alpha1.Build) (reconcile.Result, error) {
+	err := r.client.Status().Patch(ctx, target, k8sclient.MergeFrom(base))
 
 	return reconcile.Result{}, err
 }
diff --git a/pkg/controller/integration/integration_controller.go b/pkg/controller/integration/integration_controller.go
index 730368b44..f0302a1f3 100644
--- a/pkg/controller/integration/integration_controller.go
+++ b/pkg/controller/integration/integration_controller.go
@@ -14,6 +14,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
 */
+
 package integration
 
 import (
@@ -35,7 +36,6 @@ import (
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 	"github.com/apache/camel-k/pkg/client"
-	"github.com/apache/camel-k/pkg/platform"
 	"github.com/apache/camel-k/pkg/util/digest"
 	"github.com/apache/camel-k/pkg/util/log"
 )
@@ -238,30 +238,8 @@ func (r *ReconcileIntegration) Reconcile(request reconcile.Request) (reconcile.R
 	target := instance.DeepCopy()
 	targetLog := rlog.ForIntegration(target)
 
-	if target.Status.Phase == v1alpha1.IntegrationPhaseNone || target.Status.Phase == v1alpha1.IntegrationPhaseWaitingForPlatform {
-		pl, err := platform.GetOrLookup(ctx, r.client, target.Namespace, target.Status.Platform)
-		if err != nil || pl.Status.Phase != v1alpha1.IntegrationPlatformPhaseReady {
-			target.Status.Phase = v1alpha1.IntegrationPhaseWaitingForPlatform
-		} else {
-			target.Status.Phase = v1alpha1.IntegrationPhaseInitialization
-		}
-
-		if instance.Status.Phase != target.Status.Phase {
-			if err != nil {
-				target.Status.SetErrorCondition(v1alpha1.IntegrationConditionPlatformAvailable, v1alpha1.IntegrationConditionPlatformAvailableReason, err)
-			}
-
-			if pl != nil {
-				target.SetIntegrationPlatform(pl)
-			}
-
-			return r.update(ctx, &instance, target)
-		}
-
-		return reconcile.Result{}, err
-	}
-
 	actions := []Action{
+		NewPlatformSetupAction(),
 		NewInitializeAction(),
 		NewBuildKitAction(),
 		NewDeployAction(),
diff --git a/pkg/controller/integration/platform_setup.go b/pkg/controller/integration/platform_setup.go
new file mode 100644
index 000000000..108201740
--- /dev/null
+++ b/pkg/controller/integration/platform_setup.go
@@ -0,0 +1,54 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package integration
+
+import (
+	"context"
+
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/trait"
+)
+
+// NewPlatformSetupAction creates a new platform-setup action
+func NewPlatformSetupAction() Action {
+	return &platformSetupAction{}
+}
+
+type platformSetupAction struct {
+	baseAction
+}
+
+// Name returns a common name of the action
+func (action *platformSetupAction) Name() string {
+	return "platform-setup"
+}
+
+// CanHandle tells whether this action can handle the integration
+func (action *platformSetupAction) CanHandle(integration *v1alpha1.Integration) bool {
+	return integration.Status.Phase == v1alpha1.IntegrationPhaseNone ||
+		integration.Status.Phase == v1alpha1.IntegrationPhaseWaitingForPlatform
+}
+
+// Handle handles the integrations
+func (action *platformSetupAction) Handle(ctx context.Context, integration *v1alpha1.Integration) (*v1alpha1.Integration, error) {
+	if _, err := trait.Apply(ctx, action.client, integration, nil); err != nil {
+		return nil, err
+	}
+
+	return integration, nil
+}
diff --git a/pkg/controller/integrationkit/build.go b/pkg/controller/integrationkit/build.go
index a7f2319b2..ce430689d 100644
--- a/pkg/controller/integrationkit/build.go
+++ b/pkg/controller/integrationkit/build.go
@@ -96,7 +96,7 @@ func (action *buildAction) handleBuildSubmitted(ctx context.Context, kit *v1alph
 				CamelVersion:    env.CamelCatalog.Version,
 				RuntimeVersion:  env.CamelCatalog.RuntimeVersion,
 				RuntimeProvider: env.CamelCatalog.RuntimeProvider,
-				Platform:        env.Platform.Spec,
+				Platform:        env.Platform.Status.IntegrationPlatformSpec,
 				Dependencies:    kit.Spec.Dependencies,
 				// TODO: sort for easy read
 				Steps:    builder.StepIDsFor(env.Steps...),
diff --git a/pkg/controller/integrationkit/integrationkit_controller.go b/pkg/controller/integrationkit/integrationkit_controller.go
index ff518f1f1..ed84f1dfa 100644
--- a/pkg/controller/integrationkit/integrationkit_controller.go
+++ b/pkg/controller/integrationkit/integrationkit_controller.go
@@ -26,7 +26,6 @@ import (
 	"github.com/apache/camel-k/pkg/util/log"
 
 	"k8s.io/apimachinery/pkg/api/errors"
-	k8serrors "k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/types"
 	k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
@@ -186,7 +185,7 @@ func (r *ReconcileIntegrationKit) Reconcile(request reconcile.Request) (reconcil
 	targetLog := rlog.ForIntegrationKit(target)
 
 	if target.Status.Phase == v1alpha1.IntegrationKitPhaseNone || target.Status.Phase == v1alpha1.IntegrationKitPhaseWaitingForPlatform {
-		pl, err := platform.GetOrLookup(ctx, r.client, target.Namespace, target.Status.Platform)
+		pl, err := platform.GetOrLookupCurrent(ctx, r.client, target.Namespace, target.Status.Platform)
 		if err != nil || pl.Status.Phase != v1alpha1.IntegrationPlatformPhaseReady {
 			target.Status.Phase = v1alpha1.IntegrationKitPhaseWaitingForPlatform
 		} else {
@@ -202,7 +201,7 @@ func (r *ReconcileIntegrationKit) Reconcile(request reconcile.Request) (reconcil
 				target.SetIntegrationPlatform(pl)
 			}
 
-			return r.update(ctx, targetLog, target)
+			return r.update(ctx, &instance, target)
 		}
 
 		return reconcile.Result{}, err
@@ -228,7 +227,7 @@ func (r *ReconcileIntegrationKit) Reconcile(request reconcile.Request) (reconcil
 			}
 
 			if newTarget != nil {
-				if r, err := r.update(ctx, targetLog, newTarget); err != nil {
+				if r, err := r.update(ctx, &instance, newTarget); err != nil {
 					return r, err
 				}
 
@@ -250,8 +249,7 @@ func (r *ReconcileIntegrationKit) Reconcile(request reconcile.Request) (reconcil
 	return reconcile.Result{}, nil
 }
 
-// Update --
-func (r *ReconcileIntegrationKit) update(ctx context.Context, log log.Logger, target *v1alpha1.IntegrationKit) (reconcile.Result, error) {
+func (r *ReconcileIntegrationKit) update(ctx context.Context, base *v1alpha1.IntegrationKit, target *v1alpha1.IntegrationKit) (reconcile.Result, error) {
 	dgst, err := digest.ComputeForIntegrationKit(target)
 	if err != nil {
 		return reconcile.Result{}, err
@@ -259,16 +257,7 @@ func (r *ReconcileIntegrationKit) update(ctx context.Context, log log.Logger, ta
 
 	target.Status.Digest = dgst
 
-	err = r.client.Status().Update(ctx, target)
-	if err != nil {
-		if k8serrors.IsConflict(err) {
-			log.Error(err, "conflict")
-
-			return reconcile.Result{
-				Requeue: true,
-			}, nil
-		}
-	}
+	err = r.client.Status().Patch(ctx, target, k8sclient.MergeFrom(base))
 
 	return reconcile.Result{}, err
 }
diff --git a/pkg/controller/integrationplatform/create.go b/pkg/controller/integrationplatform/create.go
index 5fccaa75f..6bbe14fee 100644
--- a/pkg/controller/integrationplatform/create.go
+++ b/pkg/controller/integrationplatform/create.go
@@ -56,10 +56,10 @@ func (action *createAction) Handle(ctx context.Context, platform *v1alpha1.Integ
 		}
 	}
 
-	if l := len(platform.Spec.Resources.Kits); l > 0 {
+	if l := len(platform.Status.Resources.Kits); l > 0 {
 		res := make([]string, 0, l)
 
-		for _, c := range platform.Spec.Resources.Kits {
+		for _, c := range platform.Status.Resources.Kits {
 			//
 			// Assuming that if the resource ends with a yaml extension, the full
 			// resource name is provided
diff --git a/pkg/controller/integrationplatform/initialize.go b/pkg/controller/integrationplatform/initialize.go
index 663a3b52b..ce90c2e11 100644
--- a/pkg/controller/integrationplatform/initialize.go
+++ b/pkg/controller/integrationplatform/initialize.go
@@ -19,10 +19,6 @@ package integrationplatform
 
 import (
 	"context"
-	"fmt"
-	"time"
-
-	"github.com/apache/camel-k/pkg/util/maven"
 
 	corev1 "k8s.io/api/core/v1"
 	k8serrors "k8s.io/apimachinery/pkg/api/errors"
@@ -31,10 +27,8 @@ import (
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 	"github.com/apache/camel-k/pkg/client"
-	"github.com/apache/camel-k/pkg/util/defaults"
-	"github.com/apache/camel-k/pkg/util/openshift"
-
 	platformutil "github.com/apache/camel-k/pkg/platform"
+	"github.com/apache/camel-k/pkg/util/defaults"
 )
 
 // NewInitializeAction returns a action that initializes the platform configuration when not provided by the user
@@ -71,62 +65,11 @@ func (action *initializeAction) Handle(ctx context.Context, platform *v1alpha1.I
 		return nil, nil
 	}
 
-	// update missing fields in the resource
-	if platform.Spec.Cluster == "" {
-		// determine the kind of cluster the platform is installed into
-		isOpenShift, err := openshift.IsOpenShift(action.client)
-		switch {
-		case err != nil:
-			return nil, err
-		case isOpenShift:
-			platform.Spec.Cluster = v1alpha1.IntegrationPlatformClusterOpenShift
-		default:
-			platform.Spec.Cluster = v1alpha1.IntegrationPlatformClusterKubernetes
-		}
-	}
-
-	if platform.Spec.Build.PublishStrategy == "" {
-		if platform.Spec.Cluster == v1alpha1.IntegrationPlatformClusterOpenShift {
-			platform.Spec.Build.PublishStrategy = v1alpha1.IntegrationPlatformBuildPublishStrategyS2I
-		} else {
-			platform.Spec.Build.PublishStrategy = v1alpha1.IntegrationPlatformBuildPublishStrategyKaniko
-		}
-	}
-
-	if platform.Spec.Build.BuildStrategy == "" {
-		// If the operator is global, a global build strategy should be used
-		if platformutil.IsCurrentOperatorGlobal() {
-			// The only global strategy we have for now
-			platform.Spec.Build.BuildStrategy = v1alpha1.IntegrationPlatformBuildStrategyPod
-		} else {
-			if platform.Spec.Build.PublishStrategy == v1alpha1.IntegrationPlatformBuildPublishStrategyKaniko {
-				// The build output has to be shared with Kaniko via a persistent volume
-				platform.Spec.Build.BuildStrategy = v1alpha1.IntegrationPlatformBuildStrategyPod
-			} else {
-				platform.Spec.Build.BuildStrategy = v1alpha1.IntegrationPlatformBuildStrategyRoutine
-			}
-		}
-	}
-
-	err = action.setDefaults(ctx, platform)
-	if err != nil {
+	if err = platformutil.ConfigureDefaults(ctx, action.client, platform, true); err != nil {
 		return nil, err
 	}
 
-	if platform.Spec.Build.PublishStrategy == v1alpha1.IntegrationPlatformBuildPublishStrategyKaniko && platform.Spec.Build.Registry.Address == "" {
-		action.L.Info("No registry specified for publishing images")
-	}
-
-	if platform.Spec.Build.Maven.Timeout.Duration != 0 {
-		action.L.Infof("Maven Timeout set to %s", platform.Spec.Build.Maven.Timeout.Duration)
-	}
-
-	err = action.client.Update(ctx, platform)
-	if err != nil {
-		return nil, err
-	}
-
-	if platform.Spec.Build.PublishStrategy == v1alpha1.IntegrationPlatformBuildPublishStrategyKaniko {
+	if platform.Status.Build.PublishStrategy == v1alpha1.IntegrationPlatformBuildPublishStrategyKaniko {
 		// Create the persistent volume claim used to coordinate build pod output
 		// with Kaniko cache and build input
 		action.L.Info("Create persistent volume claim")
@@ -135,7 +78,7 @@ func (action *initializeAction) Handle(ctx context.Context, platform *v1alpha1.I
 			return nil, err
 		}
 
-		if platform.Spec.Build.IsKanikoCacheEnabled() {
+		if platform.Status.Build.IsKanikoCacheEnabled() {
 			// Create the Kaniko warmer pod that caches the base image into the Camel K builder volume
 			action.L.Info("Create Kaniko cache warmer pod")
 			err = createKanikoCacheWarmerPod(ctx, action.client, platform)
@@ -170,97 +113,6 @@ func (action *initializeAction) isDuplicate(ctx context.Context, thisPlatform *v
 	return false, nil
 }
 
-func (action *initializeAction) setDefaults(ctx context.Context, platform *v1alpha1.IntegrationPlatform) error {
-	if platform.Spec.Profile == "" {
-		platform.Spec.Profile = platformutil.DetermineBestProfile(ctx, action.client, platform)
-	}
-	if platform.Spec.Build.CamelVersion == "" {
-		platform.Spec.Build.CamelVersion = defaults.CamelVersionConstraint
-	}
-	if platform.Spec.Build.RuntimeVersion == "" {
-		platform.Spec.Build.RuntimeVersion = defaults.RuntimeVersionConstraint
-	}
-	if platform.Spec.Build.BaseImage == "" {
-		platform.Spec.Build.BaseImage = defaults.BaseImage
-	}
-	if platform.Spec.Build.Maven.LocalRepository == "" {
-		platform.Spec.Build.Maven.LocalRepository = defaults.LocalRepository
-	}
-	if platform.Spec.Build.PersistentVolumeClaim == "" {
-		platform.Spec.Build.PersistentVolumeClaim = platform.Name
-	}
-
-	if platform.Spec.Build.Timeout.Duration != 0 {
-		d := platform.Spec.Build.Timeout.Duration.Truncate(time.Second)
-
-		if platform.Spec.Build.Timeout.Duration != d {
-			action.L.Infof("Build timeout minimum unit is sec (configured: %s, truncated: %s)", platform.Spec.Build.Timeout.Duration, d)
-		}
-
-		platform.Spec.Build.Timeout.Duration = d
-	}
-	if platform.Spec.Build.Timeout.Duration == 0 {
-		platform.Spec.Build.Timeout.Duration = 5 * time.Minute
-	}
-
-	if platform.Spec.Build.Maven.Timeout.Duration != 0 {
-		d := platform.Spec.Build.Maven.Timeout.Duration.Truncate(time.Second)
-
-		if platform.Spec.Build.Maven.Timeout.Duration != d {
-			action.L.Infof("Maven timeout minimum unit is sec (configured: %s, truncated: %s)", platform.Spec.Build.Maven.Timeout.Duration, d)
-		}
-
-		platform.Spec.Build.Maven.Timeout.Duration = d
-	}
-	if platform.Spec.Build.Maven.Timeout.Duration == 0 {
-		n := platform.Spec.Build.Timeout.Duration.Seconds() * 0.75
-		platform.Spec.Build.Maven.Timeout.Duration = (time.Duration(n) * time.Second).Truncate(time.Second)
-	}
-
-	if platform.Spec.Build.Maven.Settings.ConfigMapKeyRef == nil && platform.Spec.Build.Maven.Settings.SecretKeyRef == nil {
-		var repositories []maven.Repository
-		for i, c := range platform.Spec.Configuration {
-			if c.Type == "repository" {
-				repository := maven.NewRepository(c.Value)
-				if repository.ID == "" {
-					repository.ID = fmt.Sprintf("repository-%03d", i)
-				}
-				repositories = append(repositories, repository)
-			}
-		}
-
-		settings := maven.NewDefaultSettings(repositories)
-
-		err := createMavenSettingsConfigMap(ctx, action.client, platform, settings)
-		if err != nil {
-			return err
-		}
-
-		platform.Spec.Build.Maven.Settings.ConfigMapKeyRef = &corev1.ConfigMapKeySelector{
-			LocalObjectReference: corev1.LocalObjectReference{
-				Name: platform.Name + "-maven-settings",
-			},
-			Key: "settings.xml",
-		}
-	}
-
-	if platform.Spec.Build.PublishStrategy == v1alpha1.IntegrationPlatformBuildPublishStrategyKaniko && platform.Spec.Build.KanikoBuildCache == nil {
-		// Default to using Kaniko cache warmer
-		defaultKanikoBuildCache := true
-		platform.Spec.Build.KanikoBuildCache = &defaultKanikoBuildCache
-		action.L.Infof("Kaniko cache set to %t", *platform.Spec.Build.KanikoBuildCache)
-	}
-
-	action.L.Infof("CamelVersion set to %s", platform.Spec.Build.CamelVersion)
-	action.L.Infof("RuntimeVersion set to %s", platform.Spec.Build.RuntimeVersion)
-	action.L.Infof("BaseImage set to %s", platform.Spec.Build.BaseImage)
-	action.L.Infof("LocalRepository set to %s", platform.Spec.Build.Maven.LocalRepository)
-	action.L.Infof("Timeout set to %s", platform.Spec.Build.Timeout)
-	action.L.Infof("Maven Timeout set to %s", platform.Spec.Build.Maven.Timeout.Duration)
-
-	return nil
-}
-
 func createPersistentVolumeClaim(ctx context.Context, client client.Client, platform *v1alpha1.IntegrationPlatform) error {
 	volumeSize, err := resource.ParseQuantity("1Gi")
 	if err != nil {
@@ -274,7 +126,7 @@ func createPersistentVolumeClaim(ctx context.Context, client client.Client, plat
 		},
 		ObjectMeta: metav1.ObjectMeta{
 			Namespace: platform.Namespace,
-			Name:      platform.Spec.Build.PersistentVolumeClaim,
+			Name:      platform.Status.Build.PersistentVolumeClaim,
 			Labels: map[string]string{
 				"app": "camel-k",
 			},
@@ -299,17 +151,3 @@ func createPersistentVolumeClaim(ctx context.Context, client client.Client, plat
 
 	return nil
 }
-
-func createMavenSettingsConfigMap(ctx context.Context, client client.Client, platform *v1alpha1.IntegrationPlatform, settings maven.Settings) error {
-	cm, err := maven.CreateSettingsConfigMap(platform.Namespace, platform.Name, settings)
-	if err != nil {
-		return err
-	}
-
-	err = client.Create(ctx, cm)
-	if err != nil && !k8serrors.IsAlreadyExists(err) {
-		return err
-	}
-
-	return nil
-}
diff --git a/pkg/controller/integrationplatform/integrationplatform_controller.go b/pkg/controller/integrationplatform/integrationplatform_controller.go
index 15a52f0e1..e162d4bcd 100644
--- a/pkg/controller/integrationplatform/integrationplatform_controller.go
+++ b/pkg/controller/integrationplatform/integrationplatform_controller.go
@@ -21,15 +21,10 @@ import (
 	"context"
 	"time"
 
-	camelv1alpha1 "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
-
-	"github.com/apache/camel-k/pkg/client"
-
 	"k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/runtime"
 
-	k8serrors "k8s.io/apimachinery/pkg/api/errors"
-
+	k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
 	"sigs.k8s.io/controller-runtime/pkg/controller"
 	"sigs.k8s.io/controller-runtime/pkg/event"
 	"sigs.k8s.io/controller-runtime/pkg/handler"
@@ -37,6 +32,9 @@ import (
 	"sigs.k8s.io/controller-runtime/pkg/predicate"
 	"sigs.k8s.io/controller-runtime/pkg/reconcile"
 	"sigs.k8s.io/controller-runtime/pkg/source"
+
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/client"
 )
 
 // Add creates a new IntegrationPlatform Controller and adds it to the Manager. The Manager will set fields on the Controller
@@ -66,10 +64,10 @@ func add(mgr manager.Manager, r reconcile.Reconciler) error {
 	}
 
 	// Watch for changes to primary resource IntegrationPlatform
-	err = c.Watch(&source.Kind{Type: &camelv1alpha1.IntegrationPlatform{}}, &handler.EnqueueRequestForObject{}, predicate.Funcs{
+	err = c.Watch(&source.Kind{Type: &v1alpha1.IntegrationPlatform{}}, &handler.EnqueueRequestForObject{}, predicate.Funcs{
 		UpdateFunc: func(e event.UpdateEvent) bool {
-			oldIntegrationPlatform := e.ObjectOld.(*camelv1alpha1.IntegrationPlatform)
-			newIntegrationPlatform := e.ObjectNew.(*camelv1alpha1.IntegrationPlatform)
+			oldIntegrationPlatform := e.ObjectOld.(*v1alpha1.IntegrationPlatform)
+			newIntegrationPlatform := e.ObjectNew.(*v1alpha1.IntegrationPlatform)
 			// Ignore updates to the integration platform status in which case metadata.Generation
 			// does not change, or except when the integration platform phase changes as it's used
 			// to transition from one phase to another
@@ -110,7 +108,7 @@ func (r *ReconcileIntegrationPlatform) Reconcile(request reconcile.Request) (rec
 	ctx := context.TODO()
 
 	// Fetch the IntegrationPlatform instance
-	var instance camelv1alpha1.IntegrationPlatform
+	var instance v1alpha1.IntegrationPlatform
 
 	if err := r.client.Get(ctx, request.NamespacedName, &instance); err != nil {
 		if errors.IsNotFound(err) {
@@ -132,7 +130,7 @@ func (r *ReconcileIntegrationPlatform) Reconcile(request reconcile.Request) (rec
 		NewMonitorAction(),
 	}
 
-	var targetPhase camelv1alpha1.IntegrationPlatformPhase
+	var targetPhase v1alpha1.IntegrationPlatformPhase
 	var err error
 
 	target := instance.DeepCopy()
@@ -153,14 +151,7 @@ func (r *ReconcileIntegrationPlatform) Reconcile(request reconcile.Request) (rec
 			}
 
 			if target != nil {
-				if err := r.client.Status().Update(ctx, target); err != nil {
-					if k8serrors.IsConflict(err) {
-						targetLog.Error(err, "conflict")
-						return reconcile.Result{
-							Requeue: true,
-						}, nil
-					}
-
+				if err := r.client.Status().Patch(ctx, target, k8sclient.MergeFrom(&instance)); err != nil {
 					return reconcile.Result{}, err
 				}
 
@@ -181,7 +172,7 @@ func (r *ReconcileIntegrationPlatform) Reconcile(request reconcile.Request) (rec
 		}
 	}
 
-	if targetPhase == camelv1alpha1.IntegrationPlatformPhaseReady {
+	if targetPhase == v1alpha1.IntegrationPlatformPhaseReady {
 		return reconcile.Result{}, nil
 	}
 
diff --git a/pkg/controller/integrationplatform/kaniko_cache.go b/pkg/controller/integrationplatform/kaniko_cache.go
index 217c50fa9..7ff25f649 100644
--- a/pkg/controller/integrationplatform/kaniko_cache.go
+++ b/pkg/controller/integrationplatform/kaniko_cache.go
@@ -59,7 +59,7 @@ func createKanikoCacheWarmerPod(ctx context.Context, client client.Client, platf
 					Image: fmt.Sprintf("gcr.io/kaniko-project/warmer:v%s", defaults.KanikoVersion),
 					Args: []string{
 						"--cache-dir=/workspace/cache",
-						"--image=" + platform.Spec.Build.BaseImage,
+						"--image=" + platform.Status.Build.BaseImage,
 					},
 					VolumeMounts: []corev1.VolumeMount{
 						{
@@ -91,7 +91,7 @@ func createKanikoCacheWarmerPod(ctx context.Context, client client.Client, platf
 					Name: "camel-k-builder",
 					VolumeSource: corev1.VolumeSource{
 						PersistentVolumeClaim: &corev1.PersistentVolumeClaimVolumeSource{
-							ClaimName: platform.Spec.Build.PersistentVolumeClaim,
+							ClaimName: platform.Status.Build.PersistentVolumeClaim,
 						},
 					},
 				},
diff --git a/pkg/controller/integrationplatform/monitor.go b/pkg/controller/integrationplatform/monitor.go
index d1e539062..380f3f1bb 100644
--- a/pkg/controller/integrationplatform/monitor.go
+++ b/pkg/controller/integrationplatform/monitor.go
@@ -21,6 +21,7 @@ import (
 	"context"
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	platformutils "github.com/apache/camel-k/pkg/platform"
 	"github.com/apache/camel-k/pkg/util/defaults"
 )
 
@@ -48,5 +49,10 @@ func (action *monitorAction) Handle(ctx context.Context, platform *v1alpha1.Inte
 		action.L.Info("IntegrationPlatform version updated", "version", platform.Status.Version)
 	}
 
+	// Refresh applied configuration
+	if err := platformutils.ConfigureDefaults(ctx, action.client, platform, false); err != nil {
+		return nil, err
+	}
+
 	return platform, nil
 }
diff --git a/pkg/install/operator.go b/pkg/install/operator.go
index d4b97c88f..0d401ed08 100644
--- a/pkg/install/operator.go
+++ b/pkg/install/operator.go
@@ -191,14 +191,6 @@ func PlatformOrCollect(ctx context.Context, c client.Client, clusterType string,
 		}
 	}
 
-	var knativeInstalled bool
-	if knativeInstalled, err = knative.IsInstalled(ctx, c); err != nil {
-		return nil, err
-	}
-	if knativeInstalled {
-		pl.Spec.Profile = v1alpha1.TraitProfileKnative
-	}
-
 	return pl, nil
 }
 
diff --git a/pkg/platform/defaults.go b/pkg/platform/defaults.go
new file mode 100644
index 000000000..640e385ee
--- /dev/null
+++ b/pkg/platform/defaults.go
@@ -0,0 +1,210 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package platform
+
+import (
+	"context"
+	"fmt"
+	"time"
+
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/client"
+	"github.com/apache/camel-k/pkg/util/defaults"
+	"github.com/apache/camel-k/pkg/util/log"
+	"github.com/apache/camel-k/pkg/util/maven"
+	"github.com/apache/camel-k/pkg/util/openshift"
+	corev1 "k8s.io/api/core/v1"
+	k8serrors "k8s.io/apimachinery/pkg/api/errors"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// ConfigureDefaults fills with default values all missing details about the integration platform.
+// Defaults are set in the status->appliedConfiguration fields, not in the spec.
+func ConfigureDefaults(ctx context.Context, c client.Client, p *v1alpha1.IntegrationPlatform, verbose bool) error {
+	// Reset the state to initial values
+	p.ResyncStatusFullConfig()
+
+	// update missing fields in the resource
+	if p.Status.Cluster == "" {
+		// determine the kind of cluster the platform is installed into
+		isOpenShift, err := openshift.IsOpenShift(c)
+		switch {
+		case err != nil:
+			return err
+		case isOpenShift:
+			p.Status.Cluster = v1alpha1.IntegrationPlatformClusterOpenShift
+		default:
+			p.Status.Cluster = v1alpha1.IntegrationPlatformClusterKubernetes
+		}
+	}
+
+	if p.Status.Build.PublishStrategy == "" {
+		if p.Status.Cluster == v1alpha1.IntegrationPlatformClusterOpenShift {
+			p.Status.Build.PublishStrategy = v1alpha1.IntegrationPlatformBuildPublishStrategyS2I
+		} else {
+			p.Status.Build.PublishStrategy = v1alpha1.IntegrationPlatformBuildPublishStrategyKaniko
+		}
+	}
+
+	if p.Status.Build.BuildStrategy == "" {
+		// If the operator is global, a global build strategy should be used
+		if IsCurrentOperatorGlobal() {
+			// The only global strategy we have for now
+			p.Status.Build.BuildStrategy = v1alpha1.IntegrationPlatformBuildStrategyPod
+		} else {
+			if p.Status.Build.PublishStrategy == v1alpha1.IntegrationPlatformBuildPublishStrategyKaniko {
+				// The build output has to be shared with Kaniko via a persistent volume
+				p.Status.Build.BuildStrategy = v1alpha1.IntegrationPlatformBuildStrategyPod
+			} else {
+				p.Status.Build.BuildStrategy = v1alpha1.IntegrationPlatformBuildStrategyRoutine
+			}
+		}
+	}
+
+	err := setPlatformDefaults(ctx, c, p, verbose)
+	if err != nil {
+		return err
+	}
+
+	if verbose && p.Status.Build.PublishStrategy == v1alpha1.IntegrationPlatformBuildPublishStrategyKaniko && p.Status.Build.Registry.Address == "" {
+		log.Log.Info("No registry specified for publishing images")
+	}
+
+	if verbose && p.Status.Build.Maven.GetTimeout().Duration != 0 {
+		log.Log.Infof("Maven Timeout set to %s", p.Status.Build.Maven.GetTimeout().Duration)
+	}
+
+	return nil
+}
+
+func setPlatformDefaults(ctx context.Context, c client.Client, p *v1alpha1.IntegrationPlatform, verbose bool) error {
+	if p.Status.Profile == "" {
+		p.Status.Profile = DetermineBestProfile(ctx, c, p)
+	}
+	if p.Status.Build.CamelVersion == "" {
+		p.Status.Build.CamelVersion = defaults.CamelVersionConstraint
+	}
+	if p.Status.Build.RuntimeVersion == "" {
+		p.Status.Build.RuntimeVersion = defaults.RuntimeVersionConstraint
+	}
+	if p.Status.Build.BaseImage == "" {
+		p.Status.Build.BaseImage = defaults.BaseImage
+	}
+	if p.Status.Build.Maven.LocalRepository == "" {
+		p.Status.Build.Maven.LocalRepository = defaults.LocalRepository
+	}
+	if p.Status.Build.PersistentVolumeClaim == "" {
+		p.Status.Build.PersistentVolumeClaim = p.Name
+	}
+
+	if p.Status.Build.GetTimeout().Duration != 0 {
+		d := p.Status.Build.GetTimeout().Duration.Truncate(time.Second)
+
+		if verbose && p.Status.Build.GetTimeout().Duration != d {
+			log.Log.Infof("Build timeout minimum unit is sec (configured: %s, truncated: %s)", p.Status.Build.GetTimeout().Duration, d)
+		}
+
+		p.Status.Build.Timeout = &v1.Duration{
+			Duration: d,
+		}
+	}
+	if p.Status.Build.GetTimeout().Duration == 0 {
+		p.Status.Build.Timeout = &v1.Duration{
+			Duration: 5 * time.Minute,
+		}
+	}
+
+	if p.Status.Build.Maven.GetTimeout().Duration != 0 {
+		d := p.Status.Build.Maven.GetTimeout().Duration.Truncate(time.Second)
+
+		if verbose && p.Status.Build.Maven.GetTimeout().Duration != d {
+			log.Log.Infof("Maven timeout minimum unit is sec (configured: %s, truncated: %s)", p.Status.Build.Maven.GetTimeout().Duration, d)
+		}
+
+		p.Status.Build.Maven.Timeout = &v1.Duration{
+			Duration: d,
+		}
+	}
+	if p.Status.Build.Maven.GetTimeout().Duration == 0 {
+		n := p.Status.Build.GetTimeout().Duration.Seconds() * 0.75
+		p.Status.Build.Maven.Timeout = &v1.Duration{
+			Duration: (time.Duration(n) * time.Second).Truncate(time.Second),
+		}
+	}
+
+	if p.Status.Build.Maven.Settings.ConfigMapKeyRef == nil && p.Status.Build.Maven.Settings.SecretKeyRef == nil {
+		var repositories []maven.Repository
+		for i, c := range p.Status.Configuration {
+			if c.Type == "repository" {
+				repository := maven.NewRepository(c.Value)
+				if repository.ID == "" {
+					repository.ID = fmt.Sprintf("repository-%03d", i)
+				}
+				repositories = append(repositories, repository)
+			}
+		}
+
+		settings := maven.NewDefaultSettings(repositories)
+
+		err := createDefaultMavenSettingsConfigMap(ctx, c, p, settings)
+		if err != nil {
+			return err
+		}
+
+		p.Status.Build.Maven.Settings.ConfigMapKeyRef = &corev1.ConfigMapKeySelector{
+			LocalObjectReference: corev1.LocalObjectReference{
+				Name: p.Name + "-maven-settings",
+			},
+			Key: "settings.xml",
+		}
+	}
+
+	if p.Status.Build.PublishStrategy == v1alpha1.IntegrationPlatformBuildPublishStrategyKaniko && p.Status.Build.KanikoBuildCache == nil {
+		// Default to using Kaniko cache warmer
+		defaultKanikoBuildCache := true
+		p.Status.Build.KanikoBuildCache = &defaultKanikoBuildCache
+		if verbose {
+			log.Log.Infof("Kaniko cache set to %t", *p.Status.Build.KanikoBuildCache)
+		}
+	}
+
+	if verbose {
+		log.Log.Infof("CamelVersion set to %s", p.Status.Build.CamelVersion)
+		log.Log.Infof("RuntimeVersion set to %s", p.Status.Build.RuntimeVersion)
+		log.Log.Infof("BaseImage set to %s", p.Status.Build.BaseImage)
+		log.Log.Infof("LocalRepository set to %s", p.Status.Build.Maven.LocalRepository)
+		log.Log.Infof("Timeout set to %s", p.Status.Build.GetTimeout())
+		log.Log.Infof("Maven Timeout set to %s", p.Status.Build.Maven.GetTimeout().Duration)
+	}
+
+	return nil
+}
+
+func createDefaultMavenSettingsConfigMap(ctx context.Context, client client.Client, p *v1alpha1.IntegrationPlatform, settings maven.Settings) error {
+	cm, err := maven.CreateSettingsConfigMap(p.Namespace, p.Name, settings)
+	if err != nil {
+		return err
+	}
+
+	err = client.Create(ctx, cm)
+	if err != nil && !k8serrors.IsAlreadyExists(err) {
+		return err
+	}
+
+	return nil
+}
diff --git a/pkg/platform/platform.go b/pkg/platform/platform.go
index 72ad4c0d3..5ecae34b3 100644
--- a/pkg/platform/platform.go
+++ b/pkg/platform/platform.go
@@ -19,16 +19,22 @@ package platform
 
 import (
 	"context"
-	"errors"
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/client"
 	"github.com/apache/camel-k/pkg/util/knative"
 	"github.com/apache/camel-k/pkg/util/kubernetes"
+	k8serrors "k8s.io/apimachinery/pkg/api/errors"
 	k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
 )
 
-// GetOrLookup --
-func GetOrLookup(ctx context.Context, c k8sclient.Reader, namespace string, name string) (*v1alpha1.IntegrationPlatform, error) {
+const (
+	// DefaultPlatformName is the standard name used for the integration platform
+	DefaultPlatformName = "camel-k"
+)
+
+// GetOrLookupCurrent --
+func GetOrLookupCurrent(ctx context.Context, c k8sclient.Reader, namespace string, name string) (*v1alpha1.IntegrationPlatform, error) {
 	if name != "" {
 		return Get(ctx, c, namespace, name)
 	}
@@ -36,6 +42,15 @@ func GetOrLookup(ctx context.Context, c k8sclient.Reader, namespace string, name
 	return GetCurrentPlatform(ctx, c, namespace)
 }
 
+// GetOrLookupAny returns the named platform or any other platform in the namespace
+func GetOrLookupAny(ctx context.Context, c k8sclient.Reader, namespace string, name string) (*v1alpha1.IntegrationPlatform, error) {
+	if name != "" {
+		return Get(ctx, c, namespace, name)
+	}
+
+	return getAnyPlatform(ctx, c, namespace, false)
+}
+
 // Get returns the currently installed platform
 func Get(ctx context.Context, c k8sclient.Reader, namespace string, name string) (*v1alpha1.IntegrationPlatform, error) {
 	return kubernetes.GetIntegrationPlatform(ctx, c, name, namespace)
@@ -43,6 +58,11 @@ func Get(ctx context.Context, c k8sclient.Reader, namespace string, name string)
 
 // GetCurrentPlatform returns the currently installed platform
 func GetCurrentPlatform(ctx context.Context, c k8sclient.Reader, namespace string) (*v1alpha1.IntegrationPlatform, error) {
+	return getAnyPlatform(ctx, c, namespace, true)
+}
+
+// getAnyPlatform returns the currently installed platform or any platform existing in the namespace
+func getAnyPlatform(ctx context.Context, c k8sclient.Reader, namespace string, active bool) (*v1alpha1.IntegrationPlatform, error) {
 	lst, err := ListPlatforms(ctx, c, namespace)
 	if err != nil {
 		return nil, err
@@ -54,7 +74,14 @@ func GetCurrentPlatform(ctx context.Context, c k8sclient.Reader, namespace strin
 			return &platform, nil
 		}
 	}
-	return nil, errors.New("no active integration platforms found in the namespace")
+
+	if !active && len(lst.Items) > 0 {
+		// does not require the platform to be active, just return one if present
+		res := lst.Items[0]
+		return &res, nil
+	}
+
+	return nil, k8serrors.NewNotFound(v1alpha1.Resource("IntegrationPlatform"), DefaultPlatformName)
 }
 
 // ListPlatforms returns all platforms installed in a given namespace (only one will be active)
@@ -72,9 +99,9 @@ func IsActive(p *v1alpha1.IntegrationPlatform) bool {
 }
 
 // DetermineBestProfile tries to detect the best trait profile for the platform
-func DetermineBestProfile(ctx context.Context, c k8sclient.Reader, p *v1alpha1.IntegrationPlatform) v1alpha1.TraitProfile {
-	if p.Spec.Profile != "" {
-		return p.Spec.Profile
+func DetermineBestProfile(ctx context.Context, c client.Client, p *v1alpha1.IntegrationPlatform) v1alpha1.TraitProfile {
+	if p.Status.Profile != "" {
+		return p.Status.Profile
 	}
 	if knative.IsEnabledInNamespace(ctx, c, p.Namespace) {
 		return v1alpha1.TraitProfileKnative
@@ -84,10 +111,11 @@ func DetermineBestProfile(ctx context.Context, c k8sclient.Reader, p *v1alpha1.I
 
 // GetProfile returns the current profile of the platform (if present) or returns the default one for the cluster
 func GetProfile(p *v1alpha1.IntegrationPlatform) v1alpha1.TraitProfile {
-	if p.Spec.Profile != "" {
-		return p.Spec.Profile
+	if p.Status.Profile != "" {
+		return p.Status.Profile
 	}
-	switch p.Spec.Cluster {
+
+	switch p.Status.Cluster {
 	case v1alpha1.IntegrationPlatformClusterKubernetes:
 		return v1alpha1.TraitProfileKubernetes
 	case v1alpha1.IntegrationPlatformClusterOpenShift:
@@ -98,10 +126,10 @@ func GetProfile(p *v1alpha1.IntegrationPlatform) v1alpha1.TraitProfile {
 
 // SupportsS2iPublishStrategy --
 func SupportsS2iPublishStrategy(p *v1alpha1.IntegrationPlatform) bool {
-	return p.Spec.Build.PublishStrategy == v1alpha1.IntegrationPlatformBuildPublishStrategyS2I
+	return p.Status.Build.PublishStrategy == v1alpha1.IntegrationPlatformBuildPublishStrategyS2I
 }
 
 // SupportsKanikoPublishStrategy --
 func SupportsKanikoPublishStrategy(p *v1alpha1.IntegrationPlatform) bool {
-	return p.Spec.Build.PublishStrategy == v1alpha1.IntegrationPlatformBuildPublishStrategyKaniko && p.Spec.Build.Registry.Address != ""
+	return p.Status.Build.PublishStrategy == v1alpha1.IntegrationPlatformBuildPublishStrategyKaniko && p.Status.Build.Registry.Address != ""
 }
diff --git a/pkg/trait/camel.go b/pkg/trait/camel.go
index ca59d115b..9b5f2ee2b 100644
--- a/pkg/trait/camel.go
+++ b/pkg/trait/camel.go
@@ -105,7 +105,7 @@ func (t *camelTrait) loadOrCreateCatalog(e *Environment, camelVersion string, ru
 		// the required versions (camel and runtime) are not expressed as
 		// semver constraints
 		if exactVersionRegexp.MatchString(camelVersion) && exactVersionRegexp.MatchString(runtimeVersion) {
-			catalog, err = camel.GenerateCatalog(e.C, e.Client, ns, e.Platform.Spec.Build.Maven, camelVersion, runtimeVersion)
+			catalog, err = camel.GenerateCatalog(e.C, e.Client, ns, e.Platform.Status.Build.Maven, camelVersion, runtimeVersion)
 			if err != nil {
 				return err
 			}
@@ -148,7 +148,7 @@ func (t *camelTrait) determineCamelVersion(e *Environment) string {
 	if e.IntegrationKit != nil && e.IntegrationKit.Status.CamelVersion != "" {
 		return e.IntegrationKit.Status.CamelVersion
 	}
-	return e.Platform.Spec.Build.CamelVersion
+	return e.Platform.Status.Build.CamelVersion
 }
 
 func (t *camelTrait) determineRuntimeVersion(e *Environment) string {
@@ -161,7 +161,7 @@ func (t *camelTrait) determineRuntimeVersion(e *Environment) string {
 	if e.IntegrationKit != nil && e.IntegrationKit.Status.RuntimeVersion != "" {
 		return e.IntegrationKit.Status.RuntimeVersion
 	}
-	return e.Platform.Spec.Build.RuntimeVersion
+	return e.Platform.Status.Build.RuntimeVersion
 }
 
 // IsPlatformTrait overrides base class method
diff --git a/pkg/trait/container.go b/pkg/trait/container.go
index 6bd3ae68e..558e1099e 100644
--- a/pkg/trait/container.go
+++ b/pkg/trait/container.go
@@ -27,7 +27,7 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/resource"
 	"k8s.io/apimachinery/pkg/util/intstr"
-	serving "knative.dev/serving/pkg/apis/serving/v1beta1"
+	serving "knative.dev/serving/pkg/apis/serving/v1"
 )
 
 const (
diff --git a/pkg/trait/deployer.go b/pkg/trait/deployer.go
index a996f5b00..6ba76a107 100644
--- a/pkg/trait/deployer.go
+++ b/pkg/trait/deployer.go
@@ -52,6 +52,8 @@ func newDeployerTrait() *deployerTrait {
 
 func (t *deployerTrait) Configure(e *Environment) (bool, error) {
 	return e.IntegrationInPhase(
+		v1alpha1.IntegrationPhaseNone,
+		v1alpha1.IntegrationPhaseWaitingForPlatform,
 		v1alpha1.IntegrationPhaseInitialization,
 		v1alpha1.IntegrationPhaseDeploying,
 		v1alpha1.IntegrationPhaseRunning,
@@ -61,7 +63,7 @@ func (t *deployerTrait) Configure(e *Environment) (bool, error) {
 func (t *deployerTrait) Apply(e *Environment) error {
 	switch e.Integration.Status.Phase {
 
-	case v1alpha1.IntegrationPhaseInitialization, v1alpha1.IntegrationPhaseDeploying:
+	case v1alpha1.IntegrationPhaseNone, v1alpha1.IntegrationPhaseWaitingForPlatform, v1alpha1.IntegrationPhaseInitialization, v1alpha1.IntegrationPhaseDeploying:
 		// Register a post action that updates the resources generated by the traits
 		e.PostActions = append(e.PostActions, func(env *Environment) error {
 			if err := kubernetes.ReplaceResources(env.C, env.Client, env.Resources.Items()); err != nil {
@@ -110,6 +112,11 @@ func (t *deployerTrait) IsPlatformTrait() bool {
 	return true
 }
 
+// RequiresIntegrationPlatform overrides base class method
+func (t *deployerTrait) RequiresIntegrationPlatform() bool {
+	return false
+}
+
 func positiveMergePatch(source runtime.Object, target runtime.Object) ([]byte, error) {
 	sourceJSON, err := json.Marshal(source)
 	if err != nil {
diff --git a/pkg/trait/knative.go b/pkg/trait/knative.go
index 13f36ffbc..125613685 100644
--- a/pkg/trait/knative.go
+++ b/pkg/trait/knative.go
@@ -26,15 +26,11 @@ import (
 	"github.com/apache/camel-k/pkg/metadata"
 	"github.com/apache/camel-k/pkg/util/envvar"
 	knativeutil "github.com/apache/camel-k/pkg/util/knative"
-	"github.com/apache/camel-k/pkg/util/kubernetes"
 	"github.com/pkg/errors"
 	v1 "k8s.io/api/core/v1"
 	k8serrors "k8s.io/apimachinery/pkg/api/errors"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	eventing "knative.dev/eventing/pkg/apis/eventing/v1alpha1"
-	messaging "knative.dev/eventing/pkg/apis/messaging/v1alpha1"
-	serving "knative.dev/serving/pkg/apis/serving/v1beta1"
-	k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
+	serving "knative.dev/serving/pkg/apis/serving/v1"
 )
 
 // The Knative trait automatically discovers addresses of Knative resources and inject them into the
@@ -71,9 +67,6 @@ type knativeTrait struct {
 	// that can be removed in a future version of Knative, filtering is enabled only when the integration is
 	// listening from more than 1 channel.
 	FilterSourceChannels *bool `property:"filter-source-channels"`
-	// The Knative 0.8 compatibility mode will check the installed version of Knative and
-	// use resource versions compatible with Knative 0.8 if found on the cluster.
-	Knative08CompatMode *bool `property:"knative-08-compat-mode"`
 	// Enable automatic discovery of all trait properties.
 	Auto *bool `property:"auto"`
 }
@@ -167,14 +160,6 @@ func (t *knativeTrait) Configure(e *Environment) (bool, error) {
 			filter := true
 			t.FilterSourceChannels = &filter
 		}
-
-		if t.Knative08CompatMode == nil {
-			compat, err := t.shouldUseKnative08CompatMode(e.Integration.Namespace)
-			if err != nil {
-				return false, err
-			}
-			t.Knative08CompatMode = &compat
-		}
 	}
 
 	return true, nil
@@ -258,8 +243,7 @@ func (t *knativeTrait) configureChannels(e *Environment, env *knativeapi.CamelEn
 }
 
 func (t *knativeTrait) createSubscription(e *Environment, ref *v1.ObjectReference) error {
-	compat := t.Knative08CompatMode != nil && *t.Knative08CompatMode
-	sub := knativeutil.CreateSubscription(*ref, e.Integration.Name, compat)
+	sub := knativeutil.CreateSubscription(*ref, e.Integration.Name)
 	e.Resources.Add(sub)
 	return nil
 }
@@ -429,17 +413,3 @@ func (t *knativeTrait) extractServices(names string, serviceType knativeapi.Came
 	}
 	return answer
 }
-
-func (t *knativeTrait) shouldUseKnative08CompatMode(namespace string) (bool, error) {
-	lst := messaging.SubscriptionList{
-		TypeMeta: metav1.TypeMeta{
-			Kind:       "Subscription",
-			APIVersion: messaging.SchemeGroupVersion.String(),
-		},
-	}
-	err := t.client.List(t.ctx, &lst, k8sclient.InNamespace(namespace))
-	if err != nil && kubernetes.IsUnknownAPIError(err) {
-		return true, nil
-	}
-	return false, err
-}
diff --git a/pkg/trait/knative_service.go b/pkg/trait/knative_service.go
index b57f76f77..f8d5d2560 100644
--- a/pkg/trait/knative_service.go
+++ b/pkg/trait/knative_service.go
@@ -23,8 +23,7 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
-	servingv1 "knative.dev/serving/pkg/apis/serving/v1"
-	serving "knative.dev/serving/pkg/apis/serving/v1beta1"
+	serving "knative.dev/serving/pkg/apis/serving/v1"
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 	"github.com/apache/camel-k/pkg/metadata"
@@ -280,14 +279,14 @@ func (t *knativeServiceTrait) getServiceFor(e *Environment) *serving.Service {
 			Labels:      labels,
 			Annotations: e.Integration.Annotations,
 		},
-		Spec: servingv1.ServiceSpec{
-			ConfigurationSpec: servingv1.ConfigurationSpec{
-				Template: servingv1.RevisionTemplateSpec{
+		Spec: serving.ServiceSpec{
+			ConfigurationSpec: serving.ConfigurationSpec{
+				Template: serving.RevisionTemplateSpec{
 					ObjectMeta: metav1.ObjectMeta{
 						Labels:      labels,
 						Annotations: annotations,
 					},
-					Spec: servingv1.RevisionSpec{
+					Spec: serving.RevisionSpec{
 						PodSpec: corev1.PodSpec{
 							ServiceAccountName: e.Integration.Spec.ServiceAccountName,
 						},
diff --git a/pkg/trait/owner.go b/pkg/trait/owner.go
index 3b1ff118b..784a650ac 100644
--- a/pkg/trait/owner.go
+++ b/pkg/trait/owner.go
@@ -24,7 +24,7 @@ import (
 
 	appsv1 "k8s.io/api/apps/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	serving "knative.dev/serving/pkg/apis/serving/v1beta1"
+	serving "knative.dev/serving/pkg/apis/serving/v1"
 )
 
 // The Owner trait ensures that all created resources belong to the integration being created
diff --git a/pkg/trait/platform.go b/pkg/trait/platform.go
new file mode 100644
index 000000000..c474814d6
--- /dev/null
+++ b/pkg/trait/platform.go
@@ -0,0 +1,123 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package trait
+
+import (
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/platform"
+	"github.com/apache/camel-k/pkg/util/openshift"
+	k8serrors "k8s.io/apimachinery/pkg/api/errors"
+)
+
+// The platform trait is a base trait that is used to assign an integration platform to an integration.
+//
+// In case the platform is missing, the trait is allowed to create a default platform.
+// This feature is especially useful in contexts where there's no need to provide a custom configuration for the platform
+// (e.g. on OpenShift the default settings work, since there's an embedded container image registry).
+//
+// +camel-k:trait=platform
+type platformTrait struct {
+	BaseTrait `property:",squash"`
+	// To create a default (empty) platform when the platform is missing.
+	CreateDefault *bool `property:"create-default"`
+	// To automatically detect from the environment if a default platform can be created (it will be created on OpenShift only).
+	Auto *bool `property:"auto"`
+}
+
+func newPlatformTrait() *platformTrait {
+	return &platformTrait{
+		BaseTrait: newBaseTrait("platform"),
+	}
+}
+
+func (t *platformTrait) Configure(e *Environment) (bool, error) {
+	if t.Enabled != nil && !*t.Enabled {
+		return false, nil
+	}
+
+	if !e.IntegrationInPhase(v1alpha1.IntegrationPhaseNone, v1alpha1.IntegrationPhaseWaitingForPlatform) {
+		return false, nil
+	}
+
+	if t.Auto == nil || !*t.Auto {
+		if e.Platform == nil && t.CreateDefault == nil {
+			// Calculate if the platform should be automatically created when missing.
+			if ocp, err := openshift.IsOpenShift(t.client); err != nil {
+				return false, err
+			} else if ocp {
+				t.CreateDefault = &ocp
+			}
+		}
+	}
+
+	return true, nil
+}
+
+func (t *platformTrait) Apply(e *Environment) error {
+	initial := e.Integration.DeepCopy()
+
+	pl, err := t.getOrCreatePlatform(e)
+	if err != nil || pl.Status.Phase != v1alpha1.IntegrationPlatformPhaseReady {
+		e.Integration.Status.Phase = v1alpha1.IntegrationPhaseWaitingForPlatform
+	} else {
+		e.Integration.Status.Phase = v1alpha1.IntegrationPhaseInitialization
+	}
+
+	if initial.Status.Phase != e.Integration.Status.Phase {
+		if err != nil {
+			e.Integration.Status.SetErrorCondition(v1alpha1.IntegrationConditionPlatformAvailable, v1alpha1.IntegrationConditionPlatformAvailableReason, err)
+		}
+
+		if pl != nil {
+			e.Integration.SetIntegrationPlatform(pl)
+		}
+	}
+
+	return nil
+}
+
+func (t *platformTrait) getOrCreatePlatform(e *Environment) (*v1alpha1.IntegrationPlatform, error) {
+	pl, err := platform.GetOrLookupAny(t.ctx, t.client, e.Integration.Namespace, e.Integration.Status.Platform)
+	if err != nil && k8serrors.IsNotFound(err) {
+		if t.CreateDefault != nil && *t.CreateDefault {
+			platformName := e.Integration.Status.Platform
+			if platformName == "" {
+				platformName = platform.DefaultPlatformName
+			}
+			defaultPlatform := v1alpha1.NewIntegrationPlatform(e.Integration.Namespace, platformName)
+			if defaultPlatform.Labels == nil {
+				defaultPlatform.Labels = make(map[string]string)
+			}
+			defaultPlatform.Labels["camel.apache.org/platform.generated"] = True
+			pl = &defaultPlatform
+			e.Resources.Add(pl)
+			return pl, nil
+		}
+	}
+	return pl, err
+}
+
+// IsPlatformTrait overrides base class method
+func (t *platformTrait) IsPlatformTrait() bool {
+	return true
+}
+
+// RequiresIntegrationPlatform overrides base class method
+func (t *platformTrait) RequiresIntegrationPlatform() bool {
+	return false
+}
diff --git a/pkg/trait/pull_secret.go b/pkg/trait/pull_secret.go
index db7963234..86ecbc594 100644
--- a/pkg/trait/pull_secret.go
+++ b/pkg/trait/pull_secret.go
@@ -60,7 +60,7 @@ func (t *pullSecretTrait) Configure(e *Environment) (bool, error) {
 
 	if t.Auto == nil || *t.Auto {
 		if t.SecretName == "" {
-			secret := e.Platform.Spec.Build.Registry.Secret
+			secret := e.Platform.Status.Build.Registry.Secret
 			if secret != "" {
 				key := client.ObjectKey{Namespace: e.Platform.Namespace, Name: secret}
 				obj := v1.Secret{}
diff --git a/pkg/trait/quarkus.go b/pkg/trait/quarkus.go
index 8cbb165a9..72a5be703 100644
--- a/pkg/trait/quarkus.go
+++ b/pkg/trait/quarkus.go
@@ -94,7 +94,7 @@ func (t *quarkusTrait) loadOrCreateCatalog(e *Environment, camelVersion string,
 		// semver constraints
 		if exactVersionRegexp.MatchString(camelVersion) && exactVersionRegexp.MatchString(runtimeVersion) &&
 			exactVersionRegexp.MatchString(camelQuarkusVersion) && exactVersionRegexp.MatchString(quarkusVersion) {
-			catalog, err = camel.GenerateCatalogWithProvider(e.C, e.Client, ns, e.Platform.Spec.Build.Maven, camelVersion, runtimeVersion,
+			catalog, err = camel.GenerateCatalogWithProvider(e.C, e.Client, ns, e.Platform.Status.Build.Maven, camelVersion, runtimeVersion,
 				"quarkus",
 				[]maven.Dependency{
 					{
@@ -201,9 +201,9 @@ func (t *quarkusTrait) determineQuarkusVersion(e *Environment) string {
 		e.IntegrationKit.Status.RuntimeProvider.Quarkus.QuarkusVersion != "" {
 		return e.IntegrationKit.Status.RuntimeProvider.Quarkus.QuarkusVersion
 	}
-	if e.Platform.Spec.Build.RuntimeProvider != nil && e.Platform.Spec.Build.RuntimeProvider.Quarkus != nil &&
-		e.Platform.Spec.Build.RuntimeProvider.Quarkus.QuarkusVersion != "" {
-		return e.Platform.Spec.Build.RuntimeProvider.Quarkus.QuarkusVersion
+	if e.Platform.Status.Build.RuntimeProvider != nil && e.Platform.Status.Build.RuntimeProvider.Quarkus != nil &&
+		e.Platform.Status.Build.RuntimeProvider.Quarkus.QuarkusVersion != "" {
+		return e.Platform.Status.Build.RuntimeProvider.Quarkus.QuarkusVersion
 	}
 	return defaults.QuarkusVersionConstraint
 }
@@ -220,9 +220,9 @@ func (t *quarkusTrait) determineCamelQuarkusVersion(e *Environment) string {
 		e.IntegrationKit.Status.RuntimeProvider.Quarkus.CamelQuarkusVersion != "" {
 		return e.IntegrationKit.Status.RuntimeProvider.Quarkus.CamelQuarkusVersion
 	}
-	if e.Platform.Spec.Build.RuntimeProvider != nil && e.Platform.Spec.Build.RuntimeProvider.Quarkus != nil &&
-		e.Platform.Spec.Build.RuntimeProvider.Quarkus.CamelQuarkusVersion != "" {
-		return e.Platform.Spec.Build.RuntimeProvider.Quarkus.CamelQuarkusVersion
+	if e.Platform.Status.Build.RuntimeProvider != nil && e.Platform.Status.Build.RuntimeProvider.Quarkus != nil &&
+		e.Platform.Status.Build.RuntimeProvider.Quarkus.CamelQuarkusVersion != "" {
+		return e.Platform.Status.Build.RuntimeProvider.Quarkus.CamelQuarkusVersion
 	}
 	return defaults.CamelQuarkusVersionConstraint
 }
diff --git a/pkg/trait/rest-dsl.go b/pkg/trait/rest-dsl.go
index efc5ecd00..5fbb82d48 100644
--- a/pkg/trait/rest-dsl.go
+++ b/pkg/trait/rest-dsl.go
@@ -114,12 +114,12 @@ func (t *restDslTrait) Apply(e *Environment) error {
 		}
 
 		mc := maven.NewContext(tmpDir, project)
-		mc.LocalRepository = e.Platform.Spec.Build.Maven.LocalRepository
-		mc.Timeout = e.Platform.Spec.Build.Maven.Timeout.Duration
+		mc.LocalRepository = e.Platform.Status.Build.Maven.LocalRepository
+		mc.Timeout = e.Platform.Status.Build.Maven.GetTimeout().Duration
 		mc.AddArgument("-Dopenapi.spec=" + in)
 		mc.AddArgument("-Ddsl.out=" + out)
 
-		settings, err := kubernetes.ResolveValueSource(e.C, e.Client, e.Integration.Namespace, &e.Platform.Spec.Build.Maven.Settings)
+		settings, err := kubernetes.ResolveValueSource(e.C, e.Client, e.Integration.Namespace, &e.Platform.Status.Build.Maven.Settings)
 		if err != nil {
 			return err
 		}
diff --git a/pkg/trait/trait.go b/pkg/trait/trait.go
index 8d691bcc1..2cca732d6 100644
--- a/pkg/trait/trait.go
+++ b/pkg/trait/trait.go
@@ -26,8 +26,8 @@ import (
 	"github.com/apache/camel-k/pkg/client"
 	"github.com/apache/camel-k/pkg/platform"
 	"github.com/apache/camel-k/pkg/util/kubernetes"
-
 	"github.com/pkg/errors"
+	k8serrors "k8s.io/apimachinery/pkg/api/errors"
 )
 
 // Apply --
@@ -72,7 +72,7 @@ func newEnvironment(ctx context.Context, c client.Client, integration *v1alpha1.
 	}
 
 	pl, err := platform.GetCurrentPlatform(ctx, c, namespace)
-	if err != nil {
+	if err != nil && !k8serrors.IsNotFound(err) {
 		return nil, err
 	}
 
diff --git a/pkg/trait/trait_catalog.go b/pkg/trait/trait_catalog.go
index 3e627ae81..b095c6e1e 100644
--- a/pkg/trait/trait_catalog.go
+++ b/pkg/trait/trait_catalog.go
@@ -19,6 +19,7 @@ package trait
 
 import (
 	"context"
+	"errors"
 	"reflect"
 	"strings"
 
@@ -31,6 +32,7 @@ import (
 // Catalog collects all information about traits in one place
 type Catalog struct {
 	L                 log.Logger
+	tPlatform         Trait
 	tAffinity         Trait
 	tCamel            Trait
 	tDebug            Trait
@@ -61,6 +63,7 @@ type Catalog struct {
 func NewCatalog(ctx context.Context, c client.Client) *Catalog {
 	catalog := Catalog{
 		L:                 log.Log.WithName("trait"),
+		tPlatform:         newPlatformTrait(),
 		tAffinity:         newAffinityTrait(),
 		tCamel:            newCamelTrait(),
 		tDebug:            newDebugTrait(),
@@ -100,6 +103,7 @@ func NewCatalog(ctx context.Context, c client.Client) *Catalog {
 
 func (c *Catalog) allTraits() []Trait {
 	return []Trait{
+		c.tPlatform,
 		c.tAffinity,
 		c.tCamel,
 		c.tDebug,
@@ -142,6 +146,7 @@ func (c *Catalog) TraitsForProfile(profile v1alpha1.TraitProfile) []Trait {
 	switch profile {
 	case v1alpha1.TraitProfileOpenShift:
 		return []Trait{
+			c.tPlatform,
 			c.tCamel,
 			c.tDebug,
 			c.tRestDsl,
@@ -166,6 +171,7 @@ func (c *Catalog) TraitsForProfile(profile v1alpha1.TraitProfile) []Trait {
 		}
 	case v1alpha1.TraitProfileKubernetes:
 		return []Trait{
+			c.tPlatform,
 			c.tCamel,
 			c.tDebug,
 			c.tRestDsl,
@@ -190,6 +196,7 @@ func (c *Catalog) TraitsForProfile(profile v1alpha1.TraitProfile) []Trait {
 		}
 	case v1alpha1.TraitProfileKnative:
 		return []Trait{
+			c.tPlatform,
 			c.tCamel,
 			c.tDebug,
 			c.tRestDsl,
@@ -223,7 +230,13 @@ func (c *Catalog) apply(environment *Environment) error {
 	}
 	traits := c.traitsFor(environment)
 
+	applicable := false
 	for _, trait := range traits {
+		if environment.Platform == nil && trait.RequiresIntegrationPlatform() {
+			c.L.Debug("Skipping trait because of missing integration platform: %s", trait.ID())
+			continue
+		}
+		applicable = true
 		enabled, err := trait.Configure(environment)
 		if err != nil {
 			return err
@@ -241,6 +254,10 @@ func (c *Catalog) apply(environment *Environment) error {
 		}
 	}
 
+	if !applicable && environment.Platform == nil {
+		return errors.New("no trait can be executed because of no integration platform found")
+	}
+
 	for _, processor := range environment.PostProcessors {
 		err := processor(environment)
 		if err != nil {
@@ -262,8 +279,8 @@ func (c *Catalog) GetTrait(id string) Trait {
 }
 
 func (c *Catalog) configure(env *Environment) error {
-	if env.Platform != nil && env.Platform.Spec.Traits != nil {
-		if err := c.configureTraits(env.Platform.Spec.Traits); err != nil {
+	if env.Platform != nil && env.Platform.Status.Traits != nil {
+		if err := c.configureTraits(env.Platform.Status.Traits); err != nil {
 			return err
 		}
 	}
diff --git a/pkg/trait/trait_types.go b/pkg/trait/trait_types.go
index d20738a5b..e21829adc 100644
--- a/pkg/trait/trait_types.go
+++ b/pkg/trait/trait_types.go
@@ -72,6 +72,9 @@ type Trait interface {
 
 	// IsPlatformTrait marks all fundamental traits that allow the platform to work
 	IsPlatformTrait() bool
+
+	// RequiresIntegrationPlatform indicates that the trait cannot work without an integration platform set
+	RequiresIntegrationPlatform() bool
 }
 
 /* Base trait */
@@ -118,6 +121,12 @@ func (trait *BaseTrait) IsPlatformTrait() bool {
 	return false
 }
 
+// RequiresIntegrationPlatform indicates that the trait cannot work without an integration platform set
+func (trait *BaseTrait) RequiresIntegrationPlatform() bool {
+	// All traits require a platform by default
+	return true
+}
+
 /* Environment */
 
 // A Environment provides the context where the trait is executed
@@ -208,7 +217,11 @@ func (e *Environment) DetermineProfile() v1alpha1.TraitProfile {
 		return e.IntegrationKit.Spec.Profile
 	}
 
-	return platform.GetProfile(e.Platform)
+	if e.Platform != nil {
+		return platform.GetProfile(e.Platform)
+	}
+
+	return v1alpha1.DefaultTraitProfile
 }
 
 // DetermineControllerStrategy determines the type of controller that should be used for the integration
diff --git a/pkg/util/camel/catalog.go b/pkg/util/camel/catalog.go
index 4ad5d6bd1..12289e26b 100644
--- a/pkg/util/camel/catalog.go
+++ b/pkg/util/camel/catalog.go
@@ -90,7 +90,7 @@ func GenerateCatalogWithProvider(ctx context.Context, client k8sclient.Reader, n
 
 	mc := maven.NewContext(tmpDir, project)
 	mc.LocalRepository = mvn.LocalRepository
-	mc.Timeout = mvn.Timeout.Duration
+	mc.Timeout = mvn.GetTimeout().Duration
 	mc.AddSystemProperty("catalog.path", tmpDir)
 	mc.AddSystemProperty("catalog.file", "catalog.yaml")
 	if providerName != "" {
diff --git a/pkg/util/defaults/defaults.go b/pkg/util/defaults/defaults.go
index c3ba995e4..d9ee9eb46 100644
--- a/pkg/util/defaults/defaults.go
+++ b/pkg/util/defaults/defaults.go
@@ -49,7 +49,7 @@ const (
 	QuarkusVersionConstraint = ">=0.27.0"
 
 	// KanikoVersion --
-	KanikoVersion = "0.14.0"
+	KanikoVersion = "0.9.0"
 
 	// BaseImage --
 	BaseImage = "fabric8/s2i-java:3.0-java8"
diff --git a/pkg/util/knative/apis.go b/pkg/util/knative/apis.go
index bb80509e1..ccb385b7f 100644
--- a/pkg/util/knative/apis.go
+++ b/pkg/util/knative/apis.go
@@ -26,63 +26,96 @@ import (
 
 var (
 	// KnownChannelKinds are known channel kinds belonging to Knative
-	KnownChannelKinds = []schema.GroupVersionKind{
+	KnownChannelKinds = []GroupVersionKindResource{
 		{
-			Kind:    "Channel",
-			Group:   "messaging.knative.dev",
-			Version: "v1alpha1",
+			GroupVersionKind: schema.GroupVersionKind{
+				Kind:    "Channel",
+				Group:   "messaging.knative.dev",
+				Version: "v1alpha1",
+			},
+			Resource: "channels",
 		},
 		{
-			Kind:    "Channel",
-			Group:   "eventing.knative.dev",
-			Version: "v1alpha1",
+			GroupVersionKind: schema.GroupVersionKind{
+				Kind:    "Channel",
+				Group:   "eventing.knative.dev",
+				Version: "v1alpha1",
+			},
+			Resource: "channels",
 		},
 		{
-			Kind:    "InMemoryChannel",
-			Group:   "messaging.knative.dev",
-			Version: "v1alpha1",
+			GroupVersionKind: schema.GroupVersionKind{
+				Kind:    "InMemoryChannel",
+				Group:   "messaging.knative.dev",
+				Version: "v1alpha1",
+			},
+			Resource: "inmemorychannels",
 		},
 		{
-			Kind:    "KafkaChannel",
-			Group:   "messaging.knative.dev",
-			Version: "v1alpha1",
+			GroupVersionKind: schema.GroupVersionKind{
+				Kind:    "KafkaChannel",
+				Group:   "messaging.knative.dev",
+				Version: "v1alpha1",
+			},
+			Resource: "kafkachannels",
 		},
 		{
-			Kind:    "NatssChannel",
-			Group:   "messaging.knative.dev",
-			Version: "v1alpha1",
+			GroupVersionKind: schema.GroupVersionKind{
+				Kind:    "NatssChannel",
+				Group:   "messaging.knative.dev",
+				Version: "v1alpha1",
+			},
+			Resource: "natsschannels",
 		},
 	}
 
 	// KnownEndpointKinds are known endpoint kinds belonging to Knative
-	KnownEndpointKinds = []schema.GroupVersionKind{
+	KnownEndpointKinds = []GroupVersionKindResource{
 		{
-			Kind:    "Service",
-			Group:   "serving.knative.dev",
-			Version: "v1beta1",
+			GroupVersionKind: schema.GroupVersionKind{
+				Kind:    "Service",
+				Group:   "serving.knative.dev",
+				Version: "v1",
+			},
+			Resource: "services",
 		},
 		{
-			Kind:    "Service",
-			Group:   "serving.knative.dev",
-			Version: "v1alpha1",
+			GroupVersionKind: schema.GroupVersionKind{
+				Kind:    "Service",
+				Group:   "serving.knative.dev",
+				Version: "v1beta1",
+			},
+			Resource: "services",
 		},
 		{
-			Kind:    "Service",
-			Group:   "serving.knative.dev",
-			Version: "v1",
+			GroupVersionKind: schema.GroupVersionKind{
+				Kind:    "Service",
+				Group:   "serving.knative.dev",
+				Version: "v1alpha1",
+			},
+			Resource: "services",
 		},
 	}
 
 	// KnownBrokerKinds are known broker kinds belonging to Knative
-	KnownBrokerKinds = []schema.GroupVersionKind{
+	KnownBrokerKinds = []GroupVersionKindResource{
 		{
-			Kind:    "Broker",
-			Group:   "eventing.knative.dev",
-			Version: "v1alpha1",
+			GroupVersionKind: schema.GroupVersionKind{
+				Kind:    "Broker",
+				Group:   "eventing.knative.dev",
+				Version: "v1alpha1",
+			},
+			Resource: "brokers",
 		},
 	}
 )
 
+// GroupVersionKindResource --
+type GroupVersionKindResource struct {
+	schema.GroupVersionKind
+	Resource string
+}
+
 func init() {
 	// Channels are also endpoints
 	KnownEndpointKinds = append(KnownEndpointKinds, KnownChannelKinds...)
@@ -107,7 +140,7 @@ func FillMissingReferenceData(serviceType knativev1.CamelServiceType, ref v1.Obj
 }
 
 // nolint: gocritic
-func fillMissingReferenceDataWith(serviceTypes []schema.GroupVersionKind, ref v1.ObjectReference) []v1.ObjectReference {
+func fillMissingReferenceDataWith(serviceTypes []GroupVersionKindResource, ref v1.ObjectReference) []v1.ObjectReference {
 	list := make([]v1.ObjectReference, 0)
 	if ref.APIVersion == "" && ref.Kind == "" {
 		for _, st := range serviceTypes {
@@ -134,7 +167,7 @@ func fillMissingReferenceDataWith(serviceTypes []schema.GroupVersionKind, ref v1
 	return list
 }
 
-func getGroupVersions(serviceTypes []schema.GroupVersionKind, kind string) []string {
+func getGroupVersions(serviceTypes []GroupVersionKindResource, kind string) []string {
 	res := make([]string, 0)
 	for _, st := range serviceTypes {
 		if st.Kind == kind {
@@ -144,7 +177,7 @@ func getGroupVersions(serviceTypes []schema.GroupVersionKind, kind string) []str
 	return res
 }
 
-func getKinds(serviceTypes []schema.GroupVersionKind, apiVersion string) []string {
+func getKinds(serviceTypes []GroupVersionKindResource, apiVersion string) []string {
 	res := make([]string, 0)
 	for _, st := range serviceTypes {
 		if st.GroupVersion().String() == apiVersion {
diff --git a/pkg/util/knative/enabled.go b/pkg/util/knative/enabled.go
new file mode 100644
index 000000000..b3099ec88
--- /dev/null
+++ b/pkg/util/knative/enabled.go
@@ -0,0 +1,93 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package knative
+
+import (
+	"context"
+
+	"github.com/apache/camel-k/pkg/client"
+	kubernetesutils "github.com/apache/camel-k/pkg/util/kubernetes"
+	"github.com/apache/camel-k/pkg/util/log"
+	k8serrors "k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	"k8s.io/client-go/dynamic"
+	"k8s.io/client-go/kubernetes"
+)
+
+// IsEnabledInNamespace returns true if we can list some basic knative objects in the given namespace.
+//
+// This method can be used at operator level to check if knative resources can be accessed.
+func IsEnabledInNamespace(ctx context.Context, c client.Client, namespace string) bool {
+	dyn, err := dynamic.NewForConfig(c.GetConfig())
+	if err != nil {
+		log.Infof("could not create dynamic client to check knative installation in namespace %s, got error: %v", namespace, err)
+		return false
+	}
+	for _, kgv := range KnownEndpointKinds {
+		_, err = dyn.Resource(schema.GroupVersionResource{
+			Group:    kgv.Group,
+			Version:  kgv.Version,
+			Resource: kgv.Resource,
+		}).Namespace(namespace).List(metav1.ListOptions{})
+
+		if err == nil {
+			return true
+		}
+	}
+
+	log.Infof("could not find any knative type in namespace %s, last error was: %v", namespace, err)
+	return false
+}
+
+// IsInstalled returns true if we are connected to a cluster with Knative installed
+//
+// This method should not be called from the operator, as it might require permissions that are not available.
+func IsInstalled(ctx context.Context, c kubernetes.Interface) (bool, error) {
+	// check some Knative APIs
+	for _, api := range getKnativeGroupVersions() {
+		if installed, err := isInstalled(c, api); err != nil {
+			return false, err
+		} else if installed {
+			return true, nil
+		}
+	}
+	return false, nil
+}
+
+func isInstalled(c kubernetes.Interface, api schema.GroupVersion) (bool, error) {
+	_, err := c.Discovery().ServerResourcesForGroupVersion(api.String())
+	if err != nil && (k8serrors.IsNotFound(err) || kubernetesutils.IsUnknownAPIError(err)) {
+		return false, nil
+	} else if err != nil {
+		return false, err
+	}
+	return true, nil
+}
+
+func getKnativeGroupVersions() []schema.GroupVersion {
+	apis := make(map[schema.GroupVersion]bool)
+	res := make([]schema.GroupVersion, 0)
+	for _, gvk := range KnownEndpointKinds {
+		if !apis[gvk.GroupVersion()] {
+			apis[gvk.GroupVersion()] = true
+			res = append(res, gvk.GroupVersion())
+		}
+	}
+	return res
+}
diff --git a/pkg/util/knative/knative.go b/pkg/util/knative/knative.go
index 13e2704db..ebbb76176 100644
--- a/pkg/util/knative/knative.go
+++ b/pkg/util/knative/knative.go
@@ -22,56 +22,25 @@ import (
 	"fmt"
 	"net/url"
 
-	"github.com/apache/camel-k/pkg/apis/knative08compat"
 	"github.com/apache/camel-k/pkg/client"
 	kubernetesutils "github.com/apache/camel-k/pkg/util/kubernetes"
-	"github.com/apache/camel-k/pkg/util/log"
+	corev1 "k8s.io/api/core/v1"
 	k8serrors "k8s.io/apimachinery/pkg/api/errors"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/apimachinery/pkg/runtime/schema"
-	"k8s.io/client-go/kubernetes"
-	controller "sigs.k8s.io/controller-runtime/pkg/client"
-	k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
-
-	corev1 "k8s.io/api/core/v1"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	eventing "knative.dev/eventing/pkg/apis/eventing/v1alpha1"
 	messaging "knative.dev/eventing/pkg/apis/messaging/v1alpha1"
 	"knative.dev/pkg/apis/duck"
-	duckv1alpha1 "knative.dev/pkg/apis/duck/v1alpha1"
-	serving "knative.dev/serving/pkg/apis/serving/v1beta1"
+	duckv1 "knative.dev/pkg/apis/duck/v1"
+	apisv1alpha1 "knative.dev/pkg/apis/v1alpha1"
+	serving "knative.dev/serving/pkg/apis/serving/v1"
+	controller "sigs.k8s.io/controller-runtime/pkg/client"
 )
 
-// IsEnabledInNamespace returns true if we can list some basic knative objects in the given namespace
-func IsEnabledInNamespace(ctx context.Context, c k8sclient.Reader, namespace string) bool {
-	channels := messaging.ChannelList{
-		TypeMeta: metav1.TypeMeta{
-			Kind:       "Channel",
-			APIVersion: eventing.SchemeGroupVersion.String(),
-		},
-	}
-	if err := c.List(ctx, &channels, k8sclient.InNamespace(namespace)); err != nil {
-		log.Infof("could not find knative in namespace %s, got error: %v", namespace, err)
-		return false
-	}
-	return true
-}
-
-// IsInstalled returns true if we are connected to a cluster with Knative installed
-func IsInstalled(ctx context.Context, c kubernetes.Interface) (bool, error) {
-	// check knative eventing, since serving may be on v1beta1 in some clusters
-	_, err := c.Discovery().ServerResourcesForGroupVersion("eventing.knative.dev/v1alpha1")
-	if err != nil && k8serrors.IsNotFound(err) {
-		return false, nil
-	} else if err != nil {
-		return false, err
-	}
-	return true, nil
-}
-
 // CreateSubscription ---
-func CreateSubscription(channelReference corev1.ObjectReference, serviceName string, compat08 bool) runtime.Object {
+func CreateSubscription(channelReference corev1.ObjectReference, serviceName string) runtime.Object {
 	subs := messaging.Subscription{
 		TypeMeta: metav1.TypeMeta{
 			APIVersion: messaging.SchemeGroupVersion.String(),
@@ -87,7 +56,7 @@ func CreateSubscription(channelReference corev1.ObjectReference, serviceName str
 				Kind:       channelReference.Kind,
 				Name:       channelReference.Name,
 			},
-			Subscriber: &messaging.SubscriberSpec{
+			Subscriber: &apisv1alpha1.Destination{
 				Ref: &corev1.ObjectReference{
 					APIVersion: serving.SchemeGroupVersion.String(),
 					Kind:       "Service",
@@ -97,9 +66,6 @@ func CreateSubscription(channelReference corev1.ObjectReference, serviceName str
 		},
 	}
 
-	if compat08 {
-		return knative08compat.FromMessagingSubscription(subs)
-	}
 	return &subs
 }
 
@@ -121,7 +87,7 @@ func CreateTrigger(brokerReference corev1.ObjectReference, serviceName string, e
 				},
 			},
 			Broker: brokerReference.Name,
-			Subscriber: &messaging.SubscriberSpec{
+			Subscriber: &apisv1alpha1.Destination{
 				Ref: &corev1.ObjectReference{
 					APIVersion: serving.SchemeGroupVersion.String(),
 					Kind:       "Service",
@@ -179,23 +145,23 @@ func GetSinkURI(ctx context.Context, c client.Client, sink *corev1.ObjectReferen
 
 	objIdentifier := fmt.Sprintf("\"%s/%s\" (%s)", u.GetNamespace(), u.GetName(), u.GroupVersionKind())
 	// Special case v1/Service to allow it be addressable
-	if u.GroupVersionKind().Kind == "Service" && u.GroupVersionKind().Version == "v1" {
+	if u.GroupVersionKind().Kind == "Service" && u.GroupVersionKind().Group == "" && u.GroupVersionKind().Version == "v1" {
 		return fmt.Sprintf("http://%s.%s.svc/", u.GetName(), u.GetNamespace()), nil
 	}
 
-	t := duckv1alpha1.AddressableType{}
+	t := duckv1.AddressableType{}
 	err = duck.FromUnstructured(u, &t)
 	if err != nil {
 		return "", fmt.Errorf("failed to deserialize sink %s: %v", objIdentifier, err)
 	}
 
-	if t.Status.Address == nil {
-		return "", fmt.Errorf("sink %s does not contain address", objIdentifier)
+	if t.Status.Address == nil || t.Status.Address.URL == nil {
+		return "", fmt.Errorf("sink %s does not contain address or URL", objIdentifier)
 	}
 
-	url := t.Status.Address.GetURL()
-	if url.Host == "" {
+	addressURL := t.Status.Address.URL
+	if addressURL.Host == "" {
 		return "", fmt.Errorf("sink %s contains an empty hostname", objIdentifier)
 	}
-	return url.String(), nil
+	return addressURL.String(), nil
 }
diff --git a/pkg/util/kubernetes/collection.go b/pkg/util/kubernetes/collection.go
index 20a2c251a..d825a7864 100644
--- a/pkg/util/kubernetes/collection.go
+++ b/pkg/util/kubernetes/collection.go
@@ -25,8 +25,7 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 	eventing "knative.dev/eventing/pkg/apis/eventing/v1alpha1"
-	servingv1 "knative.dev/serving/pkg/apis/serving/v1"
-	serving "knative.dev/serving/pkg/apis/serving/v1beta1"
+	serving "knative.dev/serving/pkg/apis/serving/v1"
 )
 
 // A Collection is a container of Kubernetes resources
@@ -298,7 +297,7 @@ func (c *Collection) VisitContainer(visitor func(container *corev1.Container)) {
 			visitor(cntref)
 		}
 	})
-	c.VisitKnativeConfigurationSpec(func(cs *servingv1.ConfigurationSpec) {
+	c.VisitKnativeConfigurationSpec(func(cs *serving.ConfigurationSpec) {
 		for id := range cs.Template.Spec.Containers {
 			cntref := &cs.Template.Spec.Containers[id]
 			visitor(cntref)
@@ -311,13 +310,13 @@ func (c *Collection) VisitPodSpec(visitor func(container *corev1.PodSpec)) {
 	c.VisitDeployment(func(d *appsv1.Deployment) {
 		visitor(&d.Spec.Template.Spec)
 	})
-	c.VisitKnativeConfigurationSpec(func(cs *servingv1.ConfigurationSpec) {
+	c.VisitKnativeConfigurationSpec(func(cs *serving.ConfigurationSpec) {
 		visitor(&cs.Template.Spec.PodSpec)
 	})
 }
 
 // VisitKnativeConfigurationSpec executes the visitor function on all knative ConfigurationSpec inside serving Services
-func (c *Collection) VisitKnativeConfigurationSpec(visitor func(container *servingv1.ConfigurationSpec)) {
+func (c *Collection) VisitKnativeConfigurationSpec(visitor func(container *serving.ConfigurationSpec)) {
 	c.VisitKnativeService(func(s *serving.Service) {
 		visitor(&s.Spec.ConfigurationSpec)
 	})
diff --git a/pkg/util/kubernetes/replace.go b/pkg/util/kubernetes/replace.go
index 7a25ab357..c0c417a0f 100644
--- a/pkg/util/kubernetes/replace.go
+++ b/pkg/util/kubernetes/replace.go
@@ -28,8 +28,7 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 	messaging "knative.dev/eventing/pkg/apis/messaging/v1alpha1"
-	servingv1 "knative.dev/serving/pkg/apis/serving/v1"
-	serving "knative.dev/serving/pkg/apis/serving/v1beta1"
+	serving "knative.dev/serving/pkg/apis/serving/v1"
 	k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
 )
 
@@ -121,8 +120,8 @@ func mapRequiredKnativeServiceV1Beta1Data(from runtime.Object, to runtime.Object
 }
 
 func mapRequiredKnativeServiceV1Data(from runtime.Object, to runtime.Object) {
-	if fromC, ok := from.(*servingv1.Service); ok {
-		if toC, ok := to.(*servingv1.Service); ok {
+	if fromC, ok := from.(*serving.Service); ok {
+		if toC, ok := to.(*serving.Service); ok {
 			if toC.ObjectMeta.Annotations == nil {
 				toC.ObjectMeta.Annotations = make(map[string]string)
 			}
diff --git a/script/Makefile b/script/Makefile
index c14e10496..7de91f828 100644
--- a/script/Makefile
+++ b/script/Makefile
@@ -24,7 +24,7 @@ CAMEL_QUARKUS_VERSION := 0.3.1
 CAMEL_QUARKUS_VERSION_CONSTRAINT := >=0.3.1
 QUARKUS_VERSION := 0.27.0
 QUARKUS_VERSION_CONSTRAINT := >=0.27.0
-KANIKO_VERSION := 0.14.0
+KANIKO_VERSION := 0.9.0
 BASE_IMAGE := fabric8/s2i-java:3.0-java8
 LOCAL_REPOSITORY := /tmp/artifacts/m2
 IMAGE_NAME := docker.io/apache/camel-k
@@ -138,10 +138,10 @@ test: build
 	go test ./...
 
 test-integration: build
-	STAGING_RUNTIME_REPO="$(STAGING_RUNTIME_REPO)" go test -timeout 30m -v ./e2e/... -tags=integration
+	STAGING_RUNTIME_REPO="$(STAGING_RUNTIME_REPO)" go test -timeout 30m -v ./e2e -tags=integration
 
 test-knative: build
-	STAGING_RUNTIME_REPO="$(STAGING_RUNTIME_REPO)" go test -timeout 30m -v ./e2e/... -tags=knative
+	STAGING_RUNTIME_REPO="$(STAGING_RUNTIME_REPO)" go test -timeout 30m -v ./e2e -tags=knative
 
 build-kamel:
 	go build $(GOFLAGS) -o kamel ./cmd/kamel/*.go
@@ -159,7 +159,11 @@ build-compile-integration-tests:
 	go test -c -tags="integration knative" ./e2e/*.go
 
 clean:
-	go clean
+	# disable gomodules when executing go clean:
+	#
+	#    https://github.com/golang/go/issues/31002
+	#
+	GO111MODULE=off go clean
 	rm -f camel-k
 	rm -f kamel
 	rm -f *.test
@@ -237,4 +241,4 @@ install-minikube:
 release-notes:
 	./script/gen_release_notes.sh $(LAST_RELEASED_VERSION) $(VERSION)
 
-.PHONY: build build-kamel build-resources build-olm unsnapshot-olm dep codegen images images-dec images-push images-push-staging test check test-integration clean release cross-compile package-examples set-version git-tag release-notes check-licenses generate-deepcopy generate-client generate-doc
+.PHONY: build build-kamel build-resources build-olm unsnapshot-olm dep codegen images images-dev images-push images-push-staging test check test-integration clean release cross-compile package-examples set-version git-tag release-notes check-licenses generate-deepcopy generate-client generate-doc


Test patch:
diff --git a/e2e/backward_compat_test.go b/e2e/backward_compat_test.go
index 54573aa26..2cd35c684 100644
--- a/e2e/backward_compat_test.go
+++ b/e2e/backward_compat_test.go
@@ -26,15 +26,13 @@ import (
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 	"github.com/apache/camel-k/pkg/util/kubernetes"
-	. "github.com/onsi/gomega"
 	"github.com/stretchr/testify/assert"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"sigs.k8s.io/controller-runtime/pkg/client"
 )
 
 func TestBackwardCompatibility(t *testing.T) {
-	withNewTestNamespace(func(ns string) {
-		RegisterTestingT(t)
+	withNewTestNamespace(t, func(ns string) {
 
 		data := `
 apiVersion: ` + v1alpha1.SchemeGroupVersion.String() + `
diff --git a/e2e/build_test.go b/e2e/build_test.go
index 6b3f34694..1e8fd5445 100644
--- a/e2e/build_test.go
+++ b/e2e/build_test.go
@@ -62,8 +62,7 @@ func TestKitKnativeFullBuild(t *testing.T) {
 }
 
 func doNamedKitFullBuild(t *testing.T, name string) {
-	withNewTestNamespace(func(ns string) {
-		RegisterTestingT(t)
+	withNewTestNamespace(t, func(ns string) {
 		Expect(kamel("install", "-n", ns, "--kit", name).Execute()).Should(BeNil())
 		Eventually(build(ns, name)).ShouldNot(BeNil())
 		Eventually(func() v1alpha1.BuildPhase {
diff --git a/e2e/client_test.go b/e2e/client_test.go
index 070a21e4c..912233ba4 100644
--- a/e2e/client_test.go
+++ b/e2e/client_test.go
@@ -26,16 +26,13 @@ import (
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 	"github.com/apache/camel-k/pkg/client/clientset/versioned"
-	. "github.com/onsi/gomega"
 	"github.com/stretchr/testify/assert"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"sigs.k8s.io/controller-runtime/pkg/client/config"
 )
 
 func TestClientFunctionalities(t *testing.T) {
-	withNewTestNamespace(func(ns string) {
-		RegisterTestingT(t)
-
+	withNewTestNamespace(t, func(ns string) {
 		cfg, err := config.GetConfig()
 		assert.Nil(t, err)
 		camel, err := versioned.NewForConfig(cfg)
diff --git a/e2e/docker_hub_test.go b/e2e/docker_hub_test.go
index 4e5d4f224..0b2e1cb1e 100644
--- a/e2e/docker_hub_test.go
+++ b/e2e/docker_hub_test.go
@@ -36,8 +36,7 @@ func TestRunWithDockerHubRegistry(t *testing.T) {
 	if user == "" || pass == "" {
 		t.Skip("no docker hub credentials: skipping")
 	} else {
-		withNewTestNamespace(func(ns string) {
-			RegisterTestingT(t)
+		withNewTestNamespace(t, func(ns string) {
 			Expect(kamel("install",
 				"-n", ns,
 				"--registry", "docker.io",
diff --git a/e2e/github_packages_test.go b/e2e/github_packages_test.go
index fa31782cc..c82e66ade 100644
--- a/e2e/github_packages_test.go
+++ b/e2e/github_packages_test.go
@@ -37,8 +37,7 @@ func TestRunWithGithubPackagesRegistry(t *testing.T) {
 	if user == "" || pass == "" || repo == "" {
 		t.Skip("no github packages data: skipping")
 	} else {
-		withNewTestNamespace(func(ns string) {
-			RegisterTestingT(t)
+		withNewTestNamespace(t, func(ns string) {
 			Expect(kamel("install",
 				"-n", ns,
 				"--registry", "docker.pkg.github.com",
diff --git a/e2e/install_test.go b/e2e/install_test.go
index f43bffd9c..c4f47af97 100644
--- a/e2e/install_test.go
+++ b/e2e/install_test.go
@@ -28,32 +28,28 @@ import (
 )
 
 func TestBasicInstallation(t *testing.T) {
-	withNewTestNamespace(func(ns string) {
-		RegisterTestingT(t)
+	withNewTestNamespace(t, func(ns string) {
 		Expect(kamel("install", "-n", ns).Execute()).Should(BeNil())
 		Eventually(operatorPod(ns)).ShouldNot(BeNil())
 	})
 }
 
 func TestAlternativeImageInstallation(t *testing.T) {
-	withNewTestNamespace(func(ns string) {
-		RegisterTestingT(t)
+	withNewTestNamespace(t, func(ns string) {
 		Expect(kamel("install", "-n", ns, "--operator-image", "x/y:latest").Execute()).Should(BeNil())
 		Eventually(operatorImage(ns)).Should(Equal("x/y:latest"))
 	})
 }
 
 func TestKitMainInstallation(t *testing.T) {
-	withNewTestNamespace(func(ns string) {
-		RegisterTestingT(t)
+	withNewTestNamespace(t, func(ns string) {
 		Expect(kamel("install", "-n", ns, "--kit", "main").Execute()).Should(BeNil())
 		Eventually(build(ns, "main")).ShouldNot(BeNil())
 	})
 }
 
 func TestMavenRepositoryInstallation(t *testing.T) {
-	withNewTestNamespace(func(ns string) {
-		RegisterTestingT(t)
+	withNewTestNamespace(t, func(ns string) {
 		Expect(kamel("install", "-n", ns, "--maven-repository", "https://my.repo.org/public/").Execute()).Should(BeNil())
 		Eventually(configmap(ns, "camel-k-maven-settings")).Should(Not(BeNil()))
 		Eventually(func() string {
diff --git a/e2e/knative_test.go b/e2e/knative_test.go
index 8f9446504..cbd09cd5c 100644
--- a/e2e/knative_test.go
+++ b/e2e/knative_test.go
@@ -30,8 +30,8 @@ import (
 )
 
 func TestRunServiceCombo(t *testing.T) {
-	withNewTestNamespace(func(ns string) {
-		RegisterTestingT(t)
+	withNewTestNamespace(t, func(ns string) {
+
 		Expect(kamel("install", "-n", ns, "--trait-profile", "knative").Execute()).Should(BeNil())
 		Expect(kamel("run", "-n", ns, "files/knative2.groovy").Execute()).Should(BeNil())
 		Expect(kamel("run", "-n", ns, "files/knative1.groovy").Execute()).Should(BeNil())
@@ -43,8 +43,8 @@ func TestRunServiceCombo(t *testing.T) {
 }
 
 func TestRunChannelCombo(t *testing.T) {
-	withNewTestNamespace(func(ns string) {
-		RegisterTestingT(t)
+	withNewTestNamespace(t, func(ns string) {
+
 		Expect(createKnativeChannel(ns, "messages")()).Should(BeNil())
 		Expect(kamel("install", "-n", ns, "--trait-profile", "knative").Execute()).Should(BeNil())
 		Expect(kamel("run", "-n", ns, "files/knativech2.groovy").Execute()).Should(BeNil())
@@ -57,8 +57,8 @@ func TestRunChannelCombo(t *testing.T) {
 }
 
 func TestRunChannelComboGetToPost(t *testing.T) {
-	withNewTestNamespace(func(ns string) {
-		RegisterTestingT(t)
+	withNewTestNamespace(t, func(ns string) {
+
 		Expect(createKnativeChannel(ns, "messages")()).Should(BeNil())
 		Expect(kamel("install", "-n", ns, "--trait-profile", "knative").Execute()).Should(BeNil())
 		Expect(kamel("run", "-n", ns, "files/knativegetpost2.groovy").Execute()).Should(BeNil())
@@ -71,8 +71,7 @@ func TestRunChannelComboGetToPost(t *testing.T) {
 }
 
 func TestRunMultiChannelChain(t *testing.T) {
-	withNewTestNamespace(func(ns string) {
-		RegisterTestingT(t)
+	withNewTestNamespace(t, func(ns string) {
 		Expect(createKnativeChannel(ns, "messages")()).Should(BeNil())
 		Expect(createKnativeChannel(ns, "words")()).Should(BeNil())
 		Expect(kamel("install", "-n", ns, "--trait-profile", "knative").Execute()).Should(BeNil())
@@ -94,8 +93,7 @@ func TestRunMultiChannelChain(t *testing.T) {
 }
 
 func TestRunBroker(t *testing.T) {
-	withNewTestNamespaceWithKnativeBroker(func(ns string) {
-		RegisterTestingT(t)
+	withNewTestNamespaceWithKnativeBroker(t, func(ns string) {
 		Expect(kamel("install", "-n", ns, "--trait-profile", "knative").Execute()).Should(BeNil())
 		Expect(kamel("run", "-n", ns, "files/knativeevt1.groovy").Execute()).Should(BeNil())
 		Expect(kamel("run", "-n", ns, "files/knativeevt2.groovy").Execute()).Should(BeNil())
diff --git a/e2e/platformless_run_test.go b/e2e/platformless_run_test.go
new file mode 100644
index 000000000..3edb8384d
--- /dev/null
+++ b/e2e/platformless_run_test.go
@@ -0,0 +1,56 @@
+// +build integration
+
+// To enable compilation of this file in Goland, go to "Settings -> Go -> Vendoring & Build Tags -> Custom Tags" and add "integration"
+
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package e2e
+
+import (
+	"testing"
+	"time"
+
+	"github.com/apache/camel-k/pkg/util/openshift"
+	. "github.com/onsi/gomega"
+	"github.com/stretchr/testify/assert"
+	v1 "k8s.io/api/core/v1"
+)
+
+func TestPlatformlessRun(t *testing.T) {
+	ocp, err := openshift.IsOpenShift(testClient)
+	assert.Nil(t, err)
+	if !ocp {
+		t.Skip("This test is for OpenShift only")
+		return
+	}
+
+	withNewTestNamespace(t, func(ns string) {
+		Expect(kamel("install", "-n", ns).Execute()).Should(BeNil())
+
+		// Delete the platform from the namespace before running the integration
+		Eventually(deletePlatform(ns)).Should(BeTrue())
+
+		Expect(kamel("run", "-n", ns, "files/yaml.yaml").Execute()).Should(BeNil())
+		Eventually(integrationPodPhase(ns, "yaml"), 5*time.Minute).Should(Equal(v1.PodRunning))
+		Eventually(integrationLogs(ns, "yaml"), 1*time.Minute).Should(ContainSubstring("Magicstring!"))
+
+		// Platform should be recreated
+		Eventually(platform(ns)).ShouldNot(BeNil())
+		Expect(kamel("delete", "--all", "-n", ns).Execute()).Should(BeNil())
+	})
+}
diff --git a/e2e/run_test.go b/e2e/run_test.go
index 90d2a351d..0d4404703 100644
--- a/e2e/run_test.go
+++ b/e2e/run_test.go
@@ -30,8 +30,7 @@ import (
 )
 
 func TestRunSimpleExamples(t *testing.T) {
-	withNewTestNamespace(func(ns string) {
-		RegisterTestingT(t)
+	withNewTestNamespace(t, func(ns string) {
 		Expect(kamel("install", "-n", ns).Execute()).Should(BeNil())
 
 		t.Run("run java", func(t *testing.T) {
diff --git a/e2e/tekton_test.go b/e2e/tekton_test.go
index fbb08d8b3..02b241233 100644
--- a/e2e/tekton_test.go
+++ b/e2e/tekton_test.go
@@ -30,9 +30,7 @@ import (
 // TestTektonLikeBehavior verifies that the kamel binary can be invoked from within the Camel K image.
 // This feature is used in Tekton pipelines.
 func TestTektonLikeBehavior(t *testing.T) {
-	withNewTestNamespace(func(ns string) {
-		RegisterTestingT(t)
-
+	withNewTestNamespace(t, func(ns string) {
 		Expect(createOperatorServiceAccount(ns)).Should(BeNil())
 		Expect(createOperatorRole(ns)).Should(BeNil())
 		Expect(createOperatorRoleBinding(ns)).Should(BeNil())
diff --git a/e2e/test_support.go b/e2e/test_support.go
index 1be93c369..e79aa3cc5 100644
--- a/e2e/test_support.go
+++ b/e2e/test_support.go
@@ -29,8 +29,10 @@ import (
 	"os"
 	"os/exec"
 	"strings"
+	"testing"
 	"time"
 
+	"github.com/apache/camel-k/e2e/util"
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 	"github.com/apache/camel-k/pkg/client"
 	"github.com/apache/camel-k/pkg/cmd"
@@ -77,6 +79,16 @@ func init() {
 
 	// Defaults for testing
 	gomega.SetDefaultEventuallyTimeout(60 * time.Second)
+
+	imageName := os.Getenv("CAMEL_K_TEST_IMAGE_NAME")
+	if imageName != "" {
+		testImageName = imageName
+	}
+	imageVersion := os.Getenv("CAMEL_K_TEST_IMAGE_VERSION")
+	if imageVersion != "" {
+		testImageVersion = imageVersion
+	}
+
 }
 
 func newTestClient() (client.Client, error) {
@@ -93,6 +105,9 @@ func kamel(args ...string) *cobra.Command {
 
 	kamelBin := os.Getenv("KAMEL_BIN")
 	if kamelBin != "" {
+		if _, e := os.Stat(kamelBin); e != nil && os.IsNotExist(e) {
+			panic(e)
+		}
 		fmt.Printf("Using external kamel binary on path %s\n", kamelBin)
 		c = &cobra.Command{
 			DisableFlagParsing: true,
@@ -350,6 +365,20 @@ func platform(ns string) func() *v1alpha1.IntegrationPlatform {
 	}
 }
 
+func deletePlatform(ns string) func() bool {
+	return func() bool {
+		pl := platform(ns)()
+		if pl == nil {
+			return true
+		}
+		err := testClient.Delete(testContext, pl)
+		if err != nil {
+			log.Error(err, "Got error while deleting the platform")
+		}
+		return false
+	}
+}
+
 func setPlatformVersion(ns string, version string) error {
 	p := platform(ns)()
 	if p == nil {
@@ -532,19 +561,33 @@ func numPods(ns string) func() int {
 	}
 }
 
-func withNewTestNamespace(doRun func(string)) {
+func withNewTestNamespace(t *testing.T, doRun func(string)) {
 	ns := newTestNamespace(false)
 	defer deleteTestNamespace(ns)
 
-	doRun(ns.GetName())
+	invokeUserTestCode(t, ns.GetName(), doRun)
 }
 
-func withNewTestNamespaceWithKnativeBroker(doRun func(string)) {
+func withNewTestNamespaceWithKnativeBroker(t *testing.T, doRun func(string)) {
 	ns := newTestNamespace(true)
 	defer deleteTestNamespace(ns)
 	defer deleteKnativeBroker(ns)
 
-	doRun(ns.GetName())
+	invokeUserTestCode(t, ns.GetName(), doRun)
+}
+
+func invokeUserTestCode(t *testing.T, ns string, doRun func(string)) {
+	defer func() {
+		if t.Failed() {
+
+			if err := util.Dump(testClient, ns, t); err != nil {
+				t.Logf("Error while dumping namespace %s: %v\n", ns, err)
+			}
+		}
+	}()
+
+	gomega.RegisterTestingT(t)
+	doRun(ns)
 }
 
 func deleteKnativeBroker(ns metav1.Object) {
diff --git a/e2e/upgrade_test.go b/e2e/upgrade_test.go
index 5531fdb38..2017670c4 100644
--- a/e2e/upgrade_test.go
+++ b/e2e/upgrade_test.go
@@ -31,8 +31,7 @@ import (
 )
 
 func TestPlatformUpgrade(t *testing.T) {
-	withNewTestNamespace(func(ns string) {
-		RegisterTestingT(t)
+	withNewTestNamespace(t, func(ns string) {
 		Expect(kamel("install", "-n", ns).Execute()).Should(BeNil())
 		Eventually(platformVersion(ns)).Should(Equal(defaults.Version))
 
@@ -54,8 +53,7 @@ func TestPlatformUpgrade(t *testing.T) {
 }
 
 func TestIntegrationUpgrade(t *testing.T) {
-	withNewTestNamespace(func(ns string) {
-		RegisterTestingT(t)
+	withNewTestNamespace(t, func(ns string) {
 		Expect(kamel("install", "-n", ns).Execute()).Should(BeNil())
 		Eventually(platformVersion(ns)).Should(Equal(defaults.Version))
 
diff --git a/e2e/util/dump.go b/e2e/util/dump.go
new file mode 100644
index 000000000..b07f2edce
--- /dev/null
+++ b/e2e/util/dump.go
@@ -0,0 +1,85 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package util
+
+import (
+	"bufio"
+	"fmt"
+	"testing"
+
+	"github.com/apache/camel-k/pkg/client"
+	v1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+// Dump prints all information about the given namespace to debug errors
+func Dump(c client.Client, ns string, t *testing.T) error {
+
+	t.Logf("-------------------- start dumping namespace %s --------------------\n", ns)
+
+	lst, err := c.CoreV1().Pods(ns).List(metav1.ListOptions{})
+	if err != nil {
+		return err
+	}
+
+	t.Logf("Found %d pods:\n", len(lst.Items))
+	for _, pod := range lst.Items {
+		t.Logf("name=%s\n", pod.Name)
+		dumpConditions("  ", pod.Status.Conditions, t)
+		t.Logf("  logs:\n")
+		for _, container := range pod.Spec.Containers {
+			pad := "    "
+			t.Logf("%s%s\n", pad, container.Name)
+			err := dumpLogs(c, fmt.Sprintf("%s> ", pad), ns, pod.Name, container.Name, t)
+			if err != nil {
+				t.Logf("%sERROR while reading the logs: %v\n", pad, err)
+			}
+		}
+	}
+
+	t.Logf("-------------------- end dumping namespace %s --------------------\n", ns)
+	return nil
+}
+
+func dumpConditions(prefix string, conditions []v1.PodCondition, t *testing.T) {
+	for _, cond := range conditions {
+		t.Logf("%scondition type=%s, status=%s, reason=%s, message=%q\n", prefix, cond.Type, cond.Status, cond.Reason, cond.Message)
+	}
+}
+
+func dumpLogs(c client.Client, prefix string, ns string, name string, container string, t *testing.T) error {
+	lines := int64(50)
+	stream, err := c.CoreV1().Pods(ns).GetLogs(name, &v1.PodLogOptions{
+		Container: container,
+		TailLines: &lines,
+	}).Stream()
+	if err != nil {
+		return err
+	}
+	defer stream.Close()
+	scanner := bufio.NewScanner(stream)
+	printed := false
+	for scanner.Scan() {
+		printed = true
+		t.Logf("%s%s\n", prefix, scanner.Text())
+	}
+	if !printed {
+		t.Logf("%s[no logs available]\n", prefix)
+	}
+	return nil
+}
diff --git a/pkg/controller/integrationplatform/create_test.go b/pkg/controller/integrationplatform/create_test.go
index 2670eb729..d963be694 100644
--- a/pkg/controller/integrationplatform/create_test.go
+++ b/pkg/controller/integrationplatform/create_test.go
@@ -23,8 +23,8 @@ import (
 	"testing"
 
 	"github.com/apache/camel-k/deploy"
-
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/platform"
 	"github.com/apache/camel-k/pkg/util/log"
 	"github.com/apache/camel-k/pkg/util/test"
 	"github.com/rs/xid"
@@ -37,10 +37,14 @@ func TestCreate(t *testing.T) {
 	ip.Namespace = "ns"
 	ip.Name = xid.New().String()
 	ip.Spec.Cluster = v1alpha1.IntegrationPlatformClusterOpenShift
+	ip.Spec.Profile = v1alpha1.TraitProfileOpenShift
 
 	c, err := test.NewFakeClient(&ip)
 	assert.Nil(t, err)
 
+	err = platform.ConfigureDefaults(context.TODO(), c, &ip, false)
+	assert.Nil(t, err)
+
 	h := NewCreateAction()
 	h.InjectLogger(log.Log)
 	h.InjectClient(c)
diff --git a/pkg/controller/integrationplatform/initialize_test.go b/pkg/controller/integrationplatform/initialize_test.go
index e744a9d75..9f7a04724 100644
--- a/pkg/controller/integrationplatform/initialize_test.go
+++ b/pkg/controller/integrationplatform/initialize_test.go
@@ -22,6 +22,7 @@ import (
 	"testing"
 	"time"
 
+	"github.com/apache/camel-k/pkg/platform"
 	"github.com/rs/xid"
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
@@ -38,10 +39,13 @@ func TestTimeouts_Default(t *testing.T) {
 	ip.Namespace = "ns"
 	ip.Name = xid.New().String()
 	ip.Spec.Cluster = v1alpha1.IntegrationPlatformClusterOpenShift
+	ip.Spec.Profile = v1alpha1.TraitProfileOpenShift
 
 	c, err := test.NewFakeClient(&ip)
 	assert.Nil(t, err)
 
+	assert.Nil(t, platform.ConfigureDefaults(context.TODO(), c, &ip, false))
+
 	h := NewInitializeAction()
 	h.InjectLogger(log.Log)
 	h.InjectClient(c)
@@ -50,11 +54,11 @@ func TestTimeouts_Default(t *testing.T) {
 	assert.Nil(t, err)
 	assert.NotNil(t, answer)
 
-	n := answer.Spec.Build.Timeout.Duration.Seconds() * 0.75
+	n := answer.Status.Build.GetTimeout().Duration.Seconds() * 0.75
 	d := (time.Duration(n) * time.Second).Truncate(time.Second)
 
-	assert.Equal(t, d, answer.Spec.Build.Maven.Timeout.Duration)
-	assert.Equal(t, 5*time.Minute, answer.Spec.Build.Timeout.Duration)
+	assert.Equal(t, d, answer.Status.Build.Maven.GetTimeout().Duration)
+	assert.Equal(t, 5*time.Minute, answer.Status.Build.GetTimeout().Duration)
 }
 
 func TestTimeouts_MavenComputedFromBuild(t *testing.T) {
@@ -62,17 +66,20 @@ func TestTimeouts_MavenComputedFromBuild(t *testing.T) {
 	ip.Namespace = "ns"
 	ip.Name = xid.New().String()
 	ip.Spec.Cluster = v1alpha1.IntegrationPlatformClusterOpenShift
+	ip.Spec.Profile = v1alpha1.TraitProfileOpenShift
 
 	timeout, err := time.ParseDuration("1m1ms")
 	assert.Nil(t, err)
 
-	ip.Spec.Build.Timeout = metav1.Duration{
+	ip.Spec.Build.Timeout = &metav1.Duration{
 		Duration: timeout,
 	}
 
 	c, err := test.NewFakeClient(&ip)
 	assert.Nil(t, err)
 
+	assert.Nil(t, platform.ConfigureDefaults(context.TODO(), c, &ip, false))
+
 	h := NewInitializeAction()
 	h.InjectLogger(log.Log)
 	h.InjectClient(c)
@@ -81,11 +88,11 @@ func TestTimeouts_MavenComputedFromBuild(t *testing.T) {
 	assert.Nil(t, err)
 	assert.NotNil(t, answer)
 
-	n := answer.Spec.Build.Timeout.Duration.Seconds() * 0.75
+	n := answer.Status.Build.GetTimeout().Duration.Seconds() * 0.75
 	d := (time.Duration(n) * time.Second).Truncate(time.Second)
 
-	assert.Equal(t, d, answer.Spec.Build.Maven.Timeout.Duration)
-	assert.Equal(t, 1*time.Minute, answer.Spec.Build.Timeout.Duration)
+	assert.Equal(t, d, answer.Status.Build.Maven.GetTimeout().Duration)
+	assert.Equal(t, 1*time.Minute, answer.Status.Build.GetTimeout().Duration)
 }
 
 func TestTimeouts_Truncated(t *testing.T) {
@@ -93,24 +100,27 @@ func TestTimeouts_Truncated(t *testing.T) {
 	ip.Namespace = "ns"
 	ip.Name = xid.New().String()
 	ip.Spec.Cluster = v1alpha1.IntegrationPlatformClusterOpenShift
+	ip.Spec.Profile = v1alpha1.TraitProfileOpenShift
 
 	bt, err := time.ParseDuration("5m1ms")
 	assert.Nil(t, err)
 
-	ip.Spec.Build.Timeout = metav1.Duration{
+	ip.Spec.Build.Timeout = &metav1.Duration{
 		Duration: bt,
 	}
 
 	mt, err := time.ParseDuration("2m1ms")
 	assert.Nil(t, err)
 
-	ip.Spec.Build.Maven.Timeout = metav1.Duration{
+	ip.Spec.Build.Maven.Timeout = &metav1.Duration{
 		Duration: mt,
 	}
 
 	c, err := test.NewFakeClient(&ip)
 	assert.Nil(t, err)
 
+	assert.Nil(t, platform.ConfigureDefaults(context.TODO(), c, &ip, false))
+
 	h := NewInitializeAction()
 	h.InjectLogger(log.Log)
 	h.InjectClient(c)
@@ -119,8 +129,8 @@ func TestTimeouts_Truncated(t *testing.T) {
 	assert.Nil(t, err)
 	assert.NotNil(t, answer)
 
-	assert.Equal(t, 2*time.Minute, answer.Spec.Build.Maven.Timeout.Duration)
-	assert.Equal(t, 5*time.Minute, answer.Spec.Build.Timeout.Duration)
+	assert.Equal(t, 2*time.Minute, answer.Status.Build.Maven.GetTimeout().Duration)
+	assert.Equal(t, 5*time.Minute, answer.Status.Build.GetTimeout().Duration)
 }
 
 func TestDefaultMavenSettingsApplied(t *testing.T) {
@@ -128,10 +138,13 @@ func TestDefaultMavenSettingsApplied(t *testing.T) {
 	ip.Namespace = "ns"
 	ip.Name = "test-platform"
 	ip.Spec.Cluster = v1alpha1.IntegrationPlatformClusterOpenShift
+	ip.Spec.Profile = v1alpha1.TraitProfileOpenShift
 
 	c, err := test.NewFakeClient(&ip)
 	assert.Nil(t, err)
 
+	assert.Nil(t, platform.ConfigureDefaults(context.TODO(), c, &ip, false))
+
 	h := NewInitializeAction()
 	h.InjectLogger(log.Log)
 	h.InjectClient(c)
@@ -140,7 +153,8 @@ func TestDefaultMavenSettingsApplied(t *testing.T) {
 	assert.Nil(t, err)
 	assert.NotNil(t, answer)
 
-	assert.NotNil(t, answer.Spec.Build.Maven.Settings.ConfigMapKeyRef)
-	assert.Equal(t, "test-platform-maven-settings", answer.Spec.Build.Maven.Settings.ConfigMapKeyRef.Name)
-	assert.Equal(t, "settings.xml", answer.Spec.Build.Maven.Settings.ConfigMapKeyRef.Key)
+	assert.NotNil(t, answer.Status.Build.Maven.Settings.ConfigMapKeyRef)
+	assert.Nil(t, answer.Spec.Build.Maven.Settings.ConfigMapKeyRef)
+	assert.Equal(t, "test-platform-maven-settings", answer.Status.Build.Maven.Settings.ConfigMapKeyRef.Name)
+	assert.Equal(t, "settings.xml", answer.Status.Build.Maven.Settings.ConfigMapKeyRef.Key)
 }
diff --git a/pkg/controller/integrationplatform/warm_test.go b/pkg/controller/integrationplatform/warm_test.go
index 160cbc63c..cdaaaa940 100644
--- a/pkg/controller/integrationplatform/warm_test.go
+++ b/pkg/controller/integrationplatform/warm_test.go
@@ -21,6 +21,7 @@ import (
 	"context"
 	"testing"
 
+	"github.com/apache/camel-k/pkg/platform"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
@@ -36,6 +37,7 @@ func TestWarm_Succeeded(t *testing.T) {
 	ip.Namespace = "ns"
 	ip.Name = xid.New().String()
 	ip.Spec.Cluster = v1alpha1.IntegrationPlatformClusterOpenShift
+	ip.Spec.Profile = v1alpha1.TraitProfileOpenShift
 
 	pod := corev1.Pod{
 		TypeMeta: metav1.TypeMeta{
@@ -54,6 +56,8 @@ func TestWarm_Succeeded(t *testing.T) {
 	c, err := test.NewFakeClient(&ip, &pod)
 	assert.Nil(t, err)
 
+	assert.Nil(t, platform.ConfigureDefaults(context.TODO(), c, &ip, false))
+
 	h := NewWarmAction()
 	h.InjectLogger(log.Log)
 	h.InjectClient(c)
@@ -68,6 +72,7 @@ func TestWarm_Failing(t *testing.T) {
 	ip.Namespace = "ns"
 	ip.Name = xid.New().String()
 	ip.Spec.Cluster = v1alpha1.IntegrationPlatformClusterOpenShift
+	ip.Spec.Profile = v1alpha1.TraitProfileOpenShift
 
 	pod := corev1.Pod{
 		TypeMeta: metav1.TypeMeta{
@@ -86,6 +91,8 @@ func TestWarm_Failing(t *testing.T) {
 	c, err := test.NewFakeClient(&ip, &pod)
 	assert.Nil(t, err)
 
+	assert.Nil(t, platform.ConfigureDefaults(context.TODO(), c, &ip, false))
+
 	h := NewWarmAction()
 	h.InjectLogger(log.Log)
 	h.InjectClient(c)
@@ -100,6 +107,7 @@ func TestWarm_WarmingUp(t *testing.T) {
 	ip.Namespace = "ns"
 	ip.Name = xid.New().String()
 	ip.Spec.Cluster = v1alpha1.IntegrationPlatformClusterOpenShift
+	ip.Spec.Profile = v1alpha1.TraitProfileOpenShift
 
 	pod := corev1.Pod{
 		TypeMeta: metav1.TypeMeta{
@@ -118,6 +126,8 @@ func TestWarm_WarmingUp(t *testing.T) {
 	c, err := test.NewFakeClient(&ip, &pod)
 	assert.Nil(t, err)
 
+	assert.Nil(t, platform.ConfigureDefaults(context.TODO(), c, &ip, false))
+
 	h := NewWarmAction()
 	h.InjectLogger(log.Log)
 	h.InjectClient(c)
diff --git a/pkg/trait/builder_test.go b/pkg/trait/builder_test.go
index 9fa42bff9..a9f2c0060 100644
--- a/pkg/trait/builder_test.go
+++ b/pkg/trait/builder_test.go
@@ -46,7 +46,7 @@ func TestBuilderTraitNotAppliedBecauseOfNilKit(t *testing.T) {
 		e := e // pin
 		e.IntegrationKit = nil
 
-		t.Run(string(e.Platform.Spec.Cluster), func(t *testing.T) {
+		t.Run(string(e.Platform.Status.Cluster), func(t *testing.T) {
 			err := NewBuilderTestCatalog().apply(e)
 
 			assert.Nil(t, err)
@@ -67,7 +67,7 @@ func TestBuilderTraitNotAppliedBecauseOfNilPhase(t *testing.T) {
 		e := e // pin
 		e.IntegrationKit.Status.Phase = v1alpha1.IntegrationKitPhaseInitialization
 
-		t.Run(string(e.Platform.Spec.Cluster), func(t *testing.T) {
+		t.Run(string(e.Platform.Status.Cluster), func(t *testing.T) {
 			err := NewBuilderTestCatalog().apply(e)
 
 			assert.Nil(t, err)
@@ -124,7 +124,7 @@ func createBuilderTestEnv(cluster v1alpha1.IntegrationPlatformCluster, strategy
 		panic(err)
 	}
 
-	return &Environment{
+	res := &Environment{
 		C:            context.TODO(),
 		CamelCatalog: c,
 		Catalog:      NewCatalog(context.TODO(), nil),
@@ -157,6 +157,10 @@ func createBuilderTestEnv(cluster v1alpha1.IntegrationPlatformCluster, strategy
 		Resources:      kubernetes.NewCollection(),
 		Classpath:      strset.New(),
 	}
+
+	res.Platform.ResyncStatusFullConfig()
+
+	return res
 }
 
 func NewBuilderTestCatalog() *Catalog {
diff --git a/pkg/trait/classpath_test.go b/pkg/trait/classpath_test.go
index 125d75e44..20d62dcbf 100644
--- a/pkg/trait/classpath_test.go
+++ b/pkg/trait/classpath_test.go
@@ -26,8 +26,7 @@ import (
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	servingv1 "knative.dev/serving/pkg/apis/serving/v1"
-	serving "knative.dev/serving/pkg/apis/serving/v1beta1"
+	serving "knative.dev/serving/pkg/apis/serving/v1"
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 	"github.com/apache/camel-k/pkg/util/kubernetes"
@@ -148,7 +147,7 @@ func TestApplyClasspathTraitWithKNativeResource(t *testing.T) {
 	trait, environment := createNominalClasspathTest()
 
 	s := serving.Service{}
-	s.Spec.ConfigurationSpec.Template = servingv1.RevisionTemplateSpec{}
+	s.Spec.ConfigurationSpec.Template = serving.RevisionTemplateSpec{}
 	s.Spec.ConfigurationSpec.Template.Spec.Containers = []corev1.Container{
 		{
 			Name: defaultContainerName,
diff --git a/pkg/trait/container_test.go b/pkg/trait/container_test.go
index 90b96138a..f66c0c81e 100644
--- a/pkg/trait/container_test.go
+++ b/pkg/trait/container_test.go
@@ -72,6 +72,7 @@ func TestContainerWithDefaults(t *testing.T) {
 		Resources:      kubernetes.NewCollection(),
 		Classpath:      strset.New(),
 	}
+	environment.Platform.ResyncStatusFullConfig()
 
 	err = traitCatalog.apply(&environment)
 
@@ -134,6 +135,7 @@ func TestContainerWithCustomName(t *testing.T) {
 		Resources:      kubernetes.NewCollection(),
 		Classpath:      strset.New(),
 	}
+	environment.Platform.ResyncStatusFullConfig()
 
 	err = traitCatalog.apply(&environment)
 
diff --git a/pkg/trait/deployment_test.go b/pkg/trait/deployment_test.go
index 15a30df42..9d4532856 100644
--- a/pkg/trait/deployment_test.go
+++ b/pkg/trait/deployment_test.go
@@ -199,6 +199,7 @@ func createNominalDeploymentTest() (*deploymentTrait, *Environment) {
 		},
 		Resources: kubernetes.NewCollection(),
 	}
+	environment.Platform.ResyncStatusFullConfig()
 
 	return trait, environment
 }
diff --git a/pkg/trait/environment_test.go b/pkg/trait/environment_test.go
index 977ab4be2..e13a472e6 100644
--- a/pkg/trait/environment_test.go
+++ b/pkg/trait/environment_test.go
@@ -66,6 +66,7 @@ func TestDefaultEnvironment(t *testing.T) {
 		Resources:      kubernetes.NewCollection(),
 		Classpath:      strset.New(),
 	}
+	env.Platform.ResyncStatusFullConfig()
 
 	err = NewEnvironmentTestCatalog().apply(&env)
 
@@ -134,6 +135,7 @@ func TestEnabledContainerMetaDataEnvVars(t *testing.T) {
 		Resources:      kubernetes.NewCollection(),
 		Classpath:      strset.New(),
 	}
+	env.Platform.ResyncStatusFullConfig()
 
 	err = NewEnvironmentTestCatalog().apply(&env)
 
@@ -202,6 +204,7 @@ func TestDisabledContainerMetaDataEnvVars(t *testing.T) {
 		Resources:      kubernetes.NewCollection(),
 		Classpath:      strset.New(),
 	}
+	env.Platform.ResyncStatusFullConfig()
 
 	err = NewEnvironmentTestCatalog().apply(&env)
 
diff --git a/pkg/trait/istio_test.go b/pkg/trait/istio_test.go
index 367142000..92d91bfa7 100644
--- a/pkg/trait/istio_test.go
+++ b/pkg/trait/istio_test.go
@@ -26,8 +26,7 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
-	servingv1 "knative.dev/serving/pkg/apis/serving/v1"
-	serving "knative.dev/serving/pkg/apis/serving/v1beta1"
+	serving "knative.dev/serving/pkg/apis/serving/v1"
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 	"github.com/apache/camel-k/pkg/util/camel"
@@ -50,11 +49,6 @@ func NewIstioTestEnv(t *testing.T, d *appsv1.Deployment, s *serving.Service, ena
 					"istio": {
 						Configuration: make(map[string]string),
 					},
-					"knative": {
-						Configuration: map[string]string{
-							"knative-08-compat-mode": "false", // disable it so it does not check resources in the cluster
-						},
-					},
 				},
 			},
 		},
@@ -70,6 +64,7 @@ func NewIstioTestEnv(t *testing.T, d *appsv1.Deployment, s *serving.Service, ena
 		EnvVars:   make([]corev1.EnvVar, 0),
 		Resources: kubernetes.NewCollection(s, d),
 	}
+	env.Platform.ResyncStatusFullConfig()
 
 	if enabled {
 		env.Integration.Spec.Traits["istio"].Configuration["enabled"] = "true"
@@ -80,9 +75,9 @@ func NewIstioTestEnv(t *testing.T, d *appsv1.Deployment, s *serving.Service, ena
 
 func TestIstioInject(t *testing.T) {
 	s := serving.Service{
-		Spec: servingv1.ServiceSpec{
-			ConfigurationSpec: servingv1.ConfigurationSpec{
-				Template: servingv1.RevisionTemplateSpec{},
+		Spec: serving.ServiceSpec{
+			ConfigurationSpec: serving.ConfigurationSpec{
+				Template: serving.RevisionTemplateSpec{},
 			},
 		},
 	}
@@ -102,9 +97,9 @@ func TestIstioInject(t *testing.T) {
 
 func TestIstioForcedInjectTrue(t *testing.T) {
 	s := serving.Service{
-		Spec: servingv1.ServiceSpec{
-			ConfigurationSpec: servingv1.ConfigurationSpec{
-				Template: servingv1.RevisionTemplateSpec{},
+		Spec: serving.ServiceSpec{
+			ConfigurationSpec: serving.ConfigurationSpec{
+				Template: serving.RevisionTemplateSpec{},
 			},
 		},
 	}
@@ -126,9 +121,9 @@ func TestIstioForcedInjectTrue(t *testing.T) {
 
 func TestIstioForcedInjectFalse(t *testing.T) {
 	s := serving.Service{
-		Spec: servingv1.ServiceSpec{
-			ConfigurationSpec: servingv1.ConfigurationSpec{
-				Template: servingv1.RevisionTemplateSpec{},
+		Spec: serving.ServiceSpec{
+			ConfigurationSpec: serving.ConfigurationSpec{
+				Template: serving.RevisionTemplateSpec{},
 			},
 		},
 	}
@@ -150,9 +145,9 @@ func TestIstioForcedInjectFalse(t *testing.T) {
 
 func TestIstioDisabled(t *testing.T) {
 	s := serving.Service{
-		Spec: servingv1.ServiceSpec{
-			ConfigurationSpec: servingv1.ConfigurationSpec{
-				Template: servingv1.RevisionTemplateSpec{},
+		Spec: serving.ServiceSpec{
+			ConfigurationSpec: serving.ConfigurationSpec{
+				Template: serving.RevisionTemplateSpec{},
 			},
 		},
 	}
diff --git a/pkg/trait/knative_service_test.go b/pkg/trait/knative_service_test.go
index 661afb41e..5da9b5431 100644
--- a/pkg/trait/knative_service_test.go
+++ b/pkg/trait/knative_service_test.go
@@ -26,7 +26,7 @@ import (
 
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	serving "knative.dev/serving/pkg/apis/serving/v1beta1"
+	serving "knative.dev/serving/pkg/apis/serving/v1"
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 	"github.com/apache/camel-k/pkg/util/camel"
@@ -45,9 +45,6 @@ func TestKnativeService(t *testing.T) {
 	assert.Nil(t, err)
 
 	traitCatalog := NewCatalog(context.TODO(), nil)
-	knativeTrait := traitCatalog.GetTrait("knative").(*knativeTrait)
-	falze := false
-	knativeTrait.Knative08CompatMode = &falze
 
 	environment := Environment{
 		CamelCatalog: catalog,
@@ -115,6 +112,7 @@ func TestKnativeService(t *testing.T) {
 		Resources:      kubernetes.NewCollection(),
 		Classpath:      strset.New(),
 	}
+	environment.Platform.ResyncStatusFullConfig()
 
 	err = traitCatalog.apply(&environment)
 
@@ -187,9 +185,6 @@ func TestKnativeServiceWithCustomContainerName(t *testing.T) {
 	assert.Nil(t, err)
 
 	traitCatalog := NewCatalog(context.TODO(), nil)
-	knativeTrait := traitCatalog.GetTrait("knative").(*knativeTrait)
-	falze := false
-	knativeTrait.Knative08CompatMode = &falze
 
 	environment := Environment{
 		CamelCatalog: catalog,
@@ -244,6 +239,7 @@ func TestKnativeServiceWithCustomContainerName(t *testing.T) {
 		Resources:      kubernetes.NewCollection(),
 		Classpath:      strset.New(),
 	}
+	environment.Platform.ResyncStatusFullConfig()
 
 	err = traitCatalog.apply(&environment)
 
diff --git a/pkg/trait/knative_test.go b/pkg/trait/knative_test.go
index 13038e550..716059cdc 100644
--- a/pkg/trait/knative_test.go
+++ b/pkg/trait/knative_test.go
@@ -31,8 +31,8 @@ import (
 	"knative.dev/pkg/apis"
 	duckv1 "knative.dev/pkg/apis/duck/v1"
 	duckv1alpha1 "knative.dev/pkg/apis/duck/v1alpha1"
-	servingv1 "knative.dev/serving/pkg/apis/serving/v1"
-	serving "knative.dev/serving/pkg/apis/serving/v1beta1"
+	duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1"
+	serving "knative.dev/serving/pkg/apis/serving/v1"
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
 	knativeapi "github.com/apache/camel-k/pkg/apis/camel/v1alpha1/knative"
@@ -98,6 +98,7 @@ func TestKnativeEnvConfigurationFromTrait(t *testing.T) {
 		Resources:      k8sutils.NewCollection(),
 		Classpath:      strset.New(),
 	}
+	environment.Platform.ResyncStatusFullConfig()
 
 	c, err := NewFakeClient("ns")
 	assert.Nil(t, err)
@@ -130,14 +131,14 @@ func TestKnativeEnvConfigurationFromTrait(t *testing.T) {
 	assert.NotNil(t, cSink1)
 	assert.Equal(t, "channel-sink-1.host", cSink1.Host)
 
-	eSource1 := ne.FindService("endpoint-source-1", knativeapi.CamelEndpointKindSource, knativeapi.CamelServiceTypeEndpoint, "serving.knative.dev/v1beta1", "Service")
+	eSource1 := ne.FindService("endpoint-source-1", knativeapi.CamelEndpointKindSource, knativeapi.CamelServiceTypeEndpoint, "serving.knative.dev/v1", "Service")
 	assert.NotNil(t, eSource1)
 	assert.Equal(t, "0.0.0.0", eSource1.Host)
 
-	eSink1 := ne.FindService("endpoint-sink-1", knativeapi.CamelEndpointKindSink, knativeapi.CamelServiceTypeEndpoint, "serving.knative.dev/v1beta1", "Service")
+	eSink1 := ne.FindService("endpoint-sink-1", knativeapi.CamelEndpointKindSink, knativeapi.CamelServiceTypeEndpoint, "serving.knative.dev/v1", "Service")
 	assert.NotNil(t, eSink1)
 	assert.Equal(t, "endpoint-sink-1.host", eSink1.Host)
-	eSink2 := ne.FindService("endpoint-sink-2", knativeapi.CamelEndpointKindSink, knativeapi.CamelServiceTypeEndpoint, "serving.knative.dev/v1beta1", "Service")
+	eSink2 := ne.FindService("endpoint-sink-2", knativeapi.CamelEndpointKindSink, knativeapi.CamelServiceTypeEndpoint, "serving.knative.dev/v1", "Service")
 	assert.NotNil(t, eSink2)
 	assert.Equal(t, "endpoint-sink-2.host", eSink2.Host)
 }
@@ -207,6 +208,7 @@ func TestKnativeEnvConfigurationFromSource(t *testing.T) {
 		Resources:      k8sutils.NewCollection(),
 		Classpath:      strset.New(),
 	}
+	environment.Platform.ResyncStatusFullConfig()
 
 	c, err := NewFakeClient("ns")
 	assert.Nil(t, err)
@@ -232,13 +234,21 @@ func TestKnativeEnvConfigurationFromSource(t *testing.T) {
 	err = ne.Deserialize(kc.Value)
 	assert.Nil(t, err)
 
-	source := ne.FindService("s3fileMover1", knativeapi.CamelEndpointKindSource, knativeapi.CamelServiceTypeEndpoint, "serving.knative.dev/v1beta1", "Service")
+	source := ne.FindService("s3fileMover1", knativeapi.CamelEndpointKindSource, knativeapi.CamelServiceTypeEndpoint, "serving.knative.dev/v1", "Service")
 	assert.NotNil(t, source)
 	assert.Equal(t, "0.0.0.0", source.Host)
 	assert.Equal(t, 8080, source.Port)
 }
 
 func NewFakeClient(namespace string) (client.Client, error) {
+	channelSourceURL, err := apis.ParseURL("http://channel-source-1.host/")
+	if err != nil {
+		return nil, err
+	}
+	channelSinkURL, err := apis.ParseURL("http://channel-sink-1.host/")
+	if err != nil {
+		return nil, err
+	}
 	sink1URL, err := apis.ParseURL("http://endpoint-sink-1.host/")
 	if err != nil {
 		return nil, err
@@ -260,7 +270,9 @@ func NewFakeClient(namespace string) (client.Client, error) {
 			Status: messaging.ChannelStatus{
 				AddressStatus: duckv1alpha1.AddressStatus{
 					Address: &duckv1alpha1.Addressable{
-						Hostname: "channel-source-1.host",
+						Addressable: duckv1beta1.Addressable{
+							URL: channelSourceURL,
+						},
 					},
 				},
 			},
@@ -277,7 +289,9 @@ func NewFakeClient(namespace string) (client.Client, error) {
 			Status: messaging.ChannelStatus{
 				AddressStatus: duckv1alpha1.AddressStatus{
 					Address: &duckv1alpha1.Addressable{
-						Hostname: "channel-sink-1.host",
+						Addressable: duckv1beta1.Addressable{
+							URL: channelSinkURL,
+						},
 					},
 				},
 			},
@@ -291,8 +305,8 @@ func NewFakeClient(namespace string) (client.Client, error) {
 				Namespace: namespace,
 				Name:      "endpoint-sink-1",
 			},
-			Status: servingv1.ServiceStatus{
-				RouteStatusFields: servingv1.RouteStatusFields{
+			Status: serving.ServiceStatus{
+				RouteStatusFields: serving.RouteStatusFields{
 
 					Address: &duckv1.Addressable{
 						URL: sink1URL,
@@ -309,8 +323,8 @@ func NewFakeClient(namespace string) (client.Client, error) {
 				Namespace: namespace,
 				Name:      "endpoint-sink-2",
 			},
-			Status: servingv1.ServiceStatus{
-				RouteStatusFields: servingv1.RouteStatusFields{
+			Status: serving.ServiceStatus{
+				RouteStatusFields: serving.RouteStatusFields{
 					Address: &duckv1.Addressable{
 						URL: sink2URL,
 					},
diff --git a/pkg/trait/platform_test.go b/pkg/trait/platform_test.go
new file mode 100644
index 000000000..0e75369e5
--- /dev/null
+++ b/pkg/trait/platform_test.go
@@ -0,0 +1,172 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package trait
+
+import (
+	"testing"
+
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	"github.com/apache/camel-k/pkg/platform"
+	"github.com/apache/camel-k/pkg/util/kubernetes"
+	"github.com/apache/camel-k/pkg/util/test"
+	"github.com/stretchr/testify/assert"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+func TestPlatformTraitChangeStatus(t *testing.T) {
+
+	table := []struct {
+		name         string
+		initialPhase v1alpha1.IntegrationPhase
+	}{
+		{
+			name:         "Setup from [none]",
+			initialPhase: v1alpha1.IntegrationPhaseNone,
+		},
+		{
+			name:         "Setup from WaitingForPlatform",
+			initialPhase: v1alpha1.IntegrationPhaseWaitingForPlatform,
+		},
+	}
+
+	for _, entry := range table {
+		input := entry
+		t.Run(input.name, func(t *testing.T) {
+			e := Environment{
+				Resources: kubernetes.NewCollection(),
+				Integration: &v1alpha1.Integration{
+					Status: v1alpha1.IntegrationStatus{
+						Phase: input.initialPhase,
+					},
+				},
+			}
+
+			trait := newPlatformTrait()
+			createPlatform := false
+			trait.CreateDefault = &createPlatform
+
+			var err error
+			trait.client, err = test.NewFakeClient()
+			assert.Nil(t, err)
+
+			enabled, err := trait.Configure(&e)
+			assert.Nil(t, err)
+			assert.True(t, enabled)
+
+			err = trait.Apply(&e)
+			assert.Nil(t, err)
+
+			assert.Equal(t, v1alpha1.IntegrationPhaseWaitingForPlatform, e.Integration.Status.Phase)
+			assert.Empty(t, e.Resources.Items())
+		})
+	}
+}
+
+func TestPlatformTraitCreatesDefaultPlatform(t *testing.T) {
+	e := Environment{
+		Resources: kubernetes.NewCollection(),
+		Integration: &v1alpha1.Integration{
+			ObjectMeta: v1.ObjectMeta{
+				Namespace: "ns1",
+				Name:      "xx",
+			},
+			Status: v1alpha1.IntegrationStatus{
+				Phase: v1alpha1.IntegrationPhaseNone,
+			},
+		},
+	}
+
+	trait := newPlatformTrait()
+	createPlatform := true
+	trait.CreateDefault = &createPlatform
+
+	var err error
+	trait.client, err = test.NewFakeClient()
+	assert.Nil(t, err)
+
+	enabled, err := trait.Configure(&e)
+	assert.Nil(t, err)
+	assert.True(t, enabled)
+
+	err = trait.Apply(&e)
+	assert.Nil(t, err)
+
+	assert.Equal(t, v1alpha1.IntegrationPhaseWaitingForPlatform, e.Integration.Status.Phase)
+	assert.Equal(t, 1, len(e.Resources.Items()))
+	defPlatform := v1alpha1.NewIntegrationPlatform("ns1", platform.DefaultPlatformName)
+	defPlatform.Labels = map[string]string{"camel.apache.org/platform.generated": True}
+	assert.Contains(t, e.Resources.Items(), &defPlatform)
+}
+
+func TestPlatformTraitExisting(t *testing.T) {
+
+	table := []struct {
+		name          string
+		platformPhase v1alpha1.IntegrationPlatformPhase
+		expectedPhase v1alpha1.IntegrationPhase
+	}{
+		{
+			name:          "Wait existing",
+			platformPhase: "",
+			expectedPhase: v1alpha1.IntegrationPhaseWaitingForPlatform,
+		},
+		{
+			name:          "Move state",
+			platformPhase: v1alpha1.IntegrationPlatformPhaseReady,
+			expectedPhase: v1alpha1.IntegrationPhaseInitialization,
+		},
+	}
+
+	for _, entry := range table {
+		input := entry
+		t.Run(input.name, func(t *testing.T) {
+			e := Environment{
+				Resources: kubernetes.NewCollection(),
+				Integration: &v1alpha1.Integration{
+					ObjectMeta: v1.ObjectMeta{
+						Namespace: "ns1",
+						Name:      "xx",
+					},
+					Status: v1alpha1.IntegrationStatus{
+						Phase: v1alpha1.IntegrationPhaseNone,
+					},
+				},
+			}
+
+			trait := newPlatformTrait()
+			createPlatform := true
+			trait.CreateDefault = &createPlatform
+
+			var err error
+			existingPlatform := v1alpha1.NewIntegrationPlatform("ns1", "existing")
+			existingPlatform.Status.Phase = input.platformPhase
+			trait.client, err = test.NewFakeClient(&existingPlatform)
+			assert.Nil(t, err)
+
+			enabled, err := trait.Configure(&e)
+			assert.Nil(t, err)
+			assert.True(t, enabled)
+
+			err = trait.Apply(&e)
+			assert.Nil(t, err)
+
+			assert.Equal(t, input.expectedPhase, e.Integration.Status.Phase)
+			assert.Empty(t, e.Resources.Items())
+		})
+	}
+}
diff --git a/pkg/trait/probes_test.go b/pkg/trait/probes_test.go
index e2d1b0974..69ab23544 100644
--- a/pkg/trait/probes_test.go
+++ b/pkg/trait/probes_test.go
@@ -27,8 +27,7 @@ import (
 
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
-	servingv1 "knative.dev/serving/pkg/apis/serving/v1"
-	serving "knative.dev/serving/pkg/apis/serving/v1beta1"
+	serving "knative.dev/serving/pkg/apis/serving/v1"
 )
 
 func TestProbesDeps(t *testing.T) {
@@ -101,10 +100,10 @@ func TestProbesOnDeployment(t *testing.T) {
 
 func TestProbesOnKnativeService(t *testing.T) {
 	target := serving.Service{
-		Spec: servingv1.ServiceSpec{
-			ConfigurationSpec: servingv1.ConfigurationSpec{
-				Template: servingv1.RevisionTemplateSpec{
-					Spec: servingv1.RevisionSpec{
+		Spec: serving.ServiceSpec{
+			ConfigurationSpec: serving.ConfigurationSpec{
+				Template: serving.RevisionTemplateSpec{
+					Spec: serving.RevisionSpec{
 						PodSpec: corev1.PodSpec{
 							Containers: []corev1.Container{
 								{
diff --git a/pkg/trait/route_test.go b/pkg/trait/route_test.go
index 24f489569..3a4315678 100644
--- a/pkg/trait/route_test.go
+++ b/pkg/trait/route_test.go
@@ -39,7 +39,7 @@ func createTestRouteEnvironment(t *testing.T, name string) *Environment {
 	catalog, err := camel.DefaultCatalog()
 	assert.Nil(t, err)
 
-	return &Environment{
+	res := &Environment{
 		CamelCatalog: catalog,
 		Catalog:      NewCatalog(context.TODO(), nil),
 		Integration: &v1alpha1.Integration{
@@ -92,6 +92,8 @@ func createTestRouteEnvironment(t *testing.T, name string) *Environment {
 			},
 		),
 	}
+	res.Platform.ResyncStatusFullConfig()
+	return res
 }
 
 func TestRoute_Default(t *testing.T) {
diff --git a/pkg/trait/service_test.go b/pkg/trait/service_test.go
index 5505de018..da72d7ad9 100644
--- a/pkg/trait/service_test.go
+++ b/pkg/trait/service_test.go
@@ -96,6 +96,7 @@ func TestServiceWithDefaults(t *testing.T) {
 		Resources:      kubernetes.NewCollection(),
 		Classpath:      strset.New(),
 	}
+	environment.Platform.ResyncStatusFullConfig()
 
 	err = traitCatalog.apply(&environment)
 
@@ -194,6 +195,7 @@ func TestService(t *testing.T) {
 		Resources:      kubernetes.NewCollection(),
 		Classpath:      strset.New(),
 	}
+	environment.Platform.ResyncStatusFullConfig()
 
 	err = traitCatalog.apply(&environment)
 
@@ -277,6 +279,7 @@ func TestServiceWithCustomContainerName(t *testing.T) {
 		Resources:      kubernetes.NewCollection(),
 		Classpath:      strset.New(),
 	}
+	environment.Platform.ResyncStatusFullConfig()
 
 	err = traitCatalog.apply(&environment)
 
diff --git a/pkg/trait/trait_test.go b/pkg/trait/trait_test.go
index be128f995..3a9f9e7e6 100644
--- a/pkg/trait/trait_test.go
+++ b/pkg/trait/trait_test.go
@@ -177,6 +177,7 @@ func TestTraitHierarchyDecode(t *testing.T) {
 			"autoscaling-target": "15",
 		},
 	}
+	env.Platform.ResyncStatusFullConfig()
 
 	env.IntegrationKit.Spec.Traits = make(map[string]v1alpha1.TraitSpec)
 	env.IntegrationKit.Spec.Traits["knative-service"] = v1alpha1.TraitSpec{
@@ -376,7 +377,7 @@ func TestOnlySomeTraitsInfluenceBuild(t *testing.T) {
 
 func TestOnlySomeTraitsArePlatform(t *testing.T) {
 	c := NewTraitTestCatalog()
-	platformTraits := []string{"builder", "camel", "classpath", "container", "dependencies", "deployer", "deployment", "environment", "rest-dsl", "owner"}
+	platformTraits := []string{"builder", "camel", "classpath", "container", "dependencies", "deployer", "deployment", "environment", "rest-dsl", "owner", "platform"}
 
 	for _, trait := range c.allTraits() {
 		if trait.IsPlatformTrait() {
@@ -387,6 +388,19 @@ func TestOnlySomeTraitsArePlatform(t *testing.T) {
 	}
 }
 
+func TestOnlySomeTraitsDoNotRequireIntegrationPlatform(t *testing.T) {
+	c := NewTraitTestCatalog()
+	doNotRequirePlatformTraits := []string{"deployer", "platform"}
+
+	for _, trait := range c.allTraits() {
+		if !trait.RequiresIntegrationPlatform() {
+			assert.Contains(t, doNotRequirePlatformTraits, string(trait.ID()))
+		} else {
+			assert.NotContains(t, doNotRequirePlatformTraits, trait.ID())
+		}
+	}
+}
+
 func findVolume(vols []corev1.Volume, condition func(corev1.Volume) bool) *corev1.Volume {
 	for _, v := range vols {
 		v := v
@@ -420,7 +434,7 @@ func createTestEnv(t *testing.T, cluster v1alpha1.IntegrationPlatformCluster, sc
 	catalog, err := camel.DefaultCatalog()
 	assert.Nil(t, err)
 
-	return &Environment{
+	res := &Environment{
 		CamelCatalog: catalog,
 		Catalog:      NewCatalog(context.TODO(), nil),
 		Integration: &v1alpha1.Integration{
@@ -458,6 +472,8 @@ func createTestEnv(t *testing.T, cluster v1alpha1.IntegrationPlatformCluster, sc
 		Resources:      kubernetes.NewCollection(),
 		Classpath:      strset.New(),
 	}
+	res.Platform.ResyncStatusFullConfig()
+	return res
 }
 
 func NewTraitTestCatalog() *Catalog {
diff --git a/pkg/trait/util_test.go b/pkg/trait/util_test.go
index ec2709e29..c6df916a9 100644
--- a/pkg/trait/util_test.go
+++ b/pkg/trait/util_test.go
@@ -54,6 +54,7 @@ func TestCollectConfigurationValues(t *testing.T) {
 			},
 		},
 	}
+	e.Platform.ResyncStatusFullConfig()
 
 	assert.Contains(t, e.CollectConfigurationValues("configmap"), "my-cm-integration")
 	assert.Contains(t, e.CollectConfigurationValues("secret"), "my-secret-platform")
@@ -90,6 +91,7 @@ func TestCollectConfigurationPairs(t *testing.T) {
 			},
 		},
 	}
+	e.Platform.ResyncStatusFullConfig()
 
 	pairs := e.CollectConfigurationPairs("property")
 	assert.Equal(t, "integration", pairs["p1"])
diff --git a/pkg/util/knative/apis_test.go b/pkg/util/knative/apis_test.go
index ab573b979..907827350 100644
--- a/pkg/util/knative/apis_test.go
+++ b/pkg/util/knative/apis_test.go
@@ -32,7 +32,7 @@ func TestAPIs(t *testing.T) {
 	checkValidRefs(t, refs)
 	assert.Equal(t, v1.ObjectReference{
 		Kind:       "Service",
-		APIVersion: "serving.knative.dev/v1beta1",
+		APIVersion: "serving.knative.dev/v1",
 		Name:       "ciao",
 	}, refs[0])
 
@@ -75,7 +75,7 @@ func TestAPIs(t *testing.T) {
 	checkValidRefs(t, refs)
 	assert.Equal(t, v1.ObjectReference{
 		Kind:       "Service",
-		APIVersion: "serving.knative.dev/v1beta1",
+		APIVersion: "serving.knative.dev/v1",
 		Name:       "ciao",
 	}, refs[0])