Repository: apache/camel-k
Pull request #1134 (2019-12-11 17:50:35)

Update to maven 3.6.3
<!-- Description -->




<!--
Enter your extended release note in the below block. If the PR requires
additional action from users switching to the new release, include the string
"action required". If no release note is required, write "NONE". 

You can (optionally) mark this PR with labels "kind/bug" or "kind/feature" to make sure
the text is added to the right section of the release notes. 
-->

**Release Note**
```release-note
NONE
```


Patch:
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
index b6e678122..d6f02e60b 100755
--- a/.mvn/wrapper/maven-wrapper.properties
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -1,1 +1,1 @@
-distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip
\ No newline at end of file
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip
\ No newline at end of file
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/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 72aaea779..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"`
@@ -108,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/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/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/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/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 83c2e8217..5ecae34b3 100644
--- a/pkg/platform/platform.go
+++ b/pkg/platform/platform.go
@@ -21,6 +21,7 @@ import (
 	"context"
 
 	"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"
@@ -98,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
@@ -110,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:
@@ -124,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/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_catalog.go b/pkg/trait/trait_catalog.go
index 32d5faab3..b095c6e1e 100644
--- a/pkg/trait/trait_catalog.go
+++ b/pkg/trait/trait_catalog.go
@@ -279,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/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/knative/apis.go b/pkg/util/knative/apis.go
index 43708bc95..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: "v1",
+			GroupVersionKind: schema.GroupVersionKind{
+				Kind:    "Service",
+				Group:   "serving.knative.dev",
+				Version: "v1",
+			},
+			Resource: "services",
 		},
 		{
-			Kind:    "Service",
-			Group:   "serving.knative.dev",
-			Version: "v1beta1",
+			GroupVersionKind: schema.GroupVersionKind{
+				Kind:    "Service",
+				Group:   "serving.knative.dev",
+				Version: "v1beta1",
+			},
+			Resource: "services",
 		},
 		{
-			Kind:    "Service",
-			Group:   "serving.knative.dev",
-			Version: "v1alpha1",
+			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 003912b28..ebbb76176 100644
--- a/pkg/util/knative/knative.go
+++ b/pkg/util/knative/knative.go
@@ -24,52 +24,21 @@ import (
 
 	"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"
 	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) runtime.Object {
 	subs := messaging.Subscription{
diff --git a/script/Makefile b/script/Makefile
index 5e610b339..7de91f828 100644
--- a/script/Makefile
+++ b/script/Makefile
@@ -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
@@ -241,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
diff --git a/script/package_maven_artifacts.sh b/script/package_maven_artifacts.sh
index c9d1c9fa5..09b004748 100755
--- a/script/package_maven_artifacts.sh
+++ b/script/package_maven_artifacts.sh
@@ -30,6 +30,8 @@ cd ${location}/..
 
 if [ "$strategy" = "copy" ]; then
     ./mvnw \
+        -V \
+        --no-transfer-progress \
         -f build/maven/pom-runtime.xml \
         -DoutputDirectory=$PWD/build/_maven_output \
         -Druntime.version=$version \
@@ -37,6 +39,8 @@ if [ "$strategy" = "copy" ]; then
         dependency:copy-dependencies
 elif [ "$strategy" = "download" ]; then
     ./mvnw \
+        -V \
+        --no-transfer-progress \
         -f build/maven/pom-runtime.xml \
         -Dmaven.repo.local=$PWD/build/_maven_output \
         -Druntime.version=$version \


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
index b792d24fb..3edb8384d 100644
--- a/e2e/platformless_run_test.go
+++ b/e2e/platformless_run_test.go
@@ -39,8 +39,7 @@ func TestPlatformlessRun(t *testing.T) {
 		return
 	}
 
-	withNewTestNamespace(func(ns string) {
-		RegisterTestingT(t)
+	withNewTestNamespace(t, func(ns string) {
 		Expect(kamel("install", "-n", ns).Execute()).Should(BeNil())
 
 		// Delete the platform from the namespace before running the integration
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 582c39043..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) {
@@ -549,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/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 b68d374ab..92d91bfa7 100644
--- a/pkg/trait/istio_test.go
+++ b/pkg/trait/istio_test.go
@@ -64,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"
diff --git a/pkg/trait/knative_service_test.go b/pkg/trait/knative_service_test.go
index faad1b299..5da9b5431 100644
--- a/pkg/trait/knative_service_test.go
+++ b/pkg/trait/knative_service_test.go
@@ -112,6 +112,7 @@ func TestKnativeService(t *testing.T) {
 		Resources:      kubernetes.NewCollection(),
 		Classpath:      strset.New(),
 	}
+	environment.Platform.ResyncStatusFullConfig()
 
 	err = traitCatalog.apply(&environment)
 
@@ -238,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 35961884d..716059cdc 100644
--- a/pkg/trait/knative_test.go
+++ b/pkg/trait/knative_test.go
@@ -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)
@@ -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)
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 67faa617e..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{
@@ -433,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{
@@ -471,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"])