osdir.com

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GitHub] nicolaferraro closed pull request #308: runtime: add support for a simple yaml flow


nicolaferraro closed pull request #308: runtime: add support for a simple yaml flow
URL: https://github.com/apache/camel-k/pull/308
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/deploy/platform-integration-context-groovy.yaml b/deploy/platform-integration-context-groovy.yaml
index 31aaeff5..5265f511 100644
--- a/deploy/platform-integration-context-groovy.yaml
+++ b/deploy/platform-integration-context-groovy.yaml
@@ -5,7 +5,7 @@ metadata:
   labels:
     app: "camel-k"
     camel.apache.org/context.created.by.kind: Operator
-    camel.apache.org/context.created.by.name: core
+    camel.apache.org/context.created.by.name: camel-k-operator
     camel.apache.org/context.type: platform
 spec:
   dependencies:
diff --git a/deploy/platform-integration-context-jvm.yaml b/deploy/platform-integration-context-jvm.yaml
index 28e8ff59..acaf7c3f 100644
--- a/deploy/platform-integration-context-jvm.yaml
+++ b/deploy/platform-integration-context-jvm.yaml
@@ -5,7 +5,7 @@ metadata:
   labels:
     app: "camel-k"
     camel.apache.org/context.created.by.kind: Operator
-    camel.apache.org/context.created.by.name: jvm
+    camel.apache.org/context.created.by.name: camel-k-operator
     camel.apache.org/context.type: platform
 spec:
   dependencies:
diff --git a/deploy/platform-integration-context-knative.yaml b/deploy/platform-integration-context-knative.yaml
new file mode 100644
index 00000000..895ef399
--- /dev/null
+++ b/deploy/platform-integration-context-knative.yaml
@@ -0,0 +1,15 @@
+apiVersion: camel.apache.org/v1alpha1
+kind: IntegrationContext
+metadata:
+  name: knative
+  labels:
+    app: "camel-k"
+    camel.apache.org/context.created.by.kind: Operator
+    camel.apache.org/context.created.by.name: camel-k-operator
+    camel.apache.org/context.type: platform
+spec:
+  dependencies:
+    - runtime:jvm
+    - runtime:yaml
+    - camel:core
+    - camel-k:knative
\ No newline at end of file
diff --git a/deploy/platform-integration-context-kotlin.yaml b/deploy/platform-integration-context-kotlin.yaml
index 822b4a45..8eb58362 100644
--- a/deploy/platform-integration-context-kotlin.yaml
+++ b/deploy/platform-integration-context-kotlin.yaml
@@ -5,7 +5,7 @@ metadata:
   labels:
     app: "camel-k"
     camel.apache.org/context.created.by.kind: Operator
-    camel.apache.org/context.created.by.name: jvm
+    camel.apache.org/context.created.by.name: camel-k-operator
     camel.apache.org/context.type: platform
 spec:
   dependencies:
diff --git a/deploy/platform-integration-context-spring-boot.yaml b/deploy/platform-integration-context-spring-boot.yaml
index e52d9f78..5b86911e 100644
--- a/deploy/platform-integration-context-spring-boot.yaml
+++ b/deploy/platform-integration-context-spring-boot.yaml
@@ -5,7 +5,7 @@ metadata:
   labels:
     app: "camel-k"
     camel.apache.org/context.created.by.kind: Operator
-    camel.apache.org/context.created.by.name: jvm
+    camel.apache.org/context.created.by.name: camel-k-operator
     camel.apache.org/context.type: platform
 spec:
   dependencies:
diff --git a/deploy/resources.go b/deploy/resources.go
index 5ebc74bc..7f6a7684 100644
--- a/deploy/resources.go
+++ b/deploy/resources.go
@@ -2732,7 +2732,7 @@ metadata:
   labels:
     app: "camel-k"
     camel.apache.org/context.created.by.kind: Operator
-    camel.apache.org/context.created.by.name: core
+    camel.apache.org/context.created.by.name: camel-k-operator
     camel.apache.org/context.type: platform
 spec:
   dependencies:
@@ -2749,12 +2749,30 @@ metadata:
   labels:
     app: "camel-k"
     camel.apache.org/context.created.by.kind: Operator
-    camel.apache.org/context.created.by.name: jvm
+    camel.apache.org/context.created.by.name: camel-k-operator
     camel.apache.org/context.type: platform
 spec:
   dependencies:
     - runtime:jvm
     - camel:core
+`
+	Resources["platform-integration-context-knative.yaml"] =
+		`
+apiVersion: camel.apache.org/v1alpha1
+kind: IntegrationContext
+metadata:
+  name: knative
+  labels:
+    app: "camel-k"
+    camel.apache.org/context.created.by.kind: Operator
+    camel.apache.org/context.created.by.name: camel-k-operator
+    camel.apache.org/context.type: platform
+spec:
+  dependencies:
+    - runtime:jvm
+    - runtime:yaml
+    - camel:core
+    - camel-k:knative
 `
 	Resources["platform-integration-context-kotlin.yaml"] =
 		`
@@ -2765,7 +2783,7 @@ metadata:
   labels:
     app: "camel-k"
     camel.apache.org/context.created.by.kind: Operator
-    camel.apache.org/context.created.by.name: jvm
+    camel.apache.org/context.created.by.name: camel-k-operator
     camel.apache.org/context.type: platform
 spec:
   dependencies:
@@ -2782,7 +2800,7 @@ metadata:
   labels:
     app: "camel-k"
     camel.apache.org/context.created.by.kind: Operator
-    camel.apache.org/context.created.by.name: jvm
+    camel.apache.org/context.created.by.name: camel-k-operator
     camel.apache.org/context.type: platform
 spec:
   dependencies:
diff --git a/examples/routes.flow b/examples/routes.flow
new file mode 100644
index 00000000..ea693052
--- /dev/null
+++ b/examples/routes.flow
@@ -0,0 +1,5 @@
+- steps:
+    - kind: "endpoint"
+      uri: "timer:tick?period=5s"
+    - kind: "endpoint"
+      uri: "log:info"
diff --git a/pkg/apis/camel/v1alpha1/types.go b/pkg/apis/camel/v1alpha1/types.go
index 0627da17..ef4dcc05 100644
--- a/pkg/apis/camel/v1alpha1/types.go
+++ b/pkg/apis/camel/v1alpha1/types.go
@@ -133,6 +133,8 @@ const (
 	LanguageXML Language = "xml"
 	// LanguageKotlin --
 	LanguageKotlin Language = "kts"
+	// LanguageYamlFlow --
+	LanguageYamlFlow Language = "flow"
 )
 
 // A IntegrationTraitSpec contains the configuration of a trait
@@ -355,3 +357,14 @@ type Artifact struct {
 func (in *Artifact) String() string {
 	return in.ID
 }
+
+// Flow --
+type Flow struct {
+	Steps []Step `json:"steps"`
+}
+
+// Step --
+type Step struct {
+	Kind string `json:"kind"`
+	URI  string `json:"uri"`
+}
diff --git a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
index c61ab94f..85e3be81 100644
--- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -73,6 +73,27 @@ func (in *DataSpec) DeepCopy() *DataSpec {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Flow) DeepCopyInto(out *Flow) {
+	*out = *in
+	if in.Steps != nil {
+		in, out := &in.Steps, &out.Steps
+		*out = make([]Step, len(*in))
+		copy(*out, *in)
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Flow.
+func (in *Flow) DeepCopy() *Flow {
+	if in == nil {
+		return nil
+	}
+	out := new(Flow)
+	in.DeepCopyInto(out)
+	return out
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Integration) DeepCopyInto(out *Integration) {
 	*out = *in
@@ -501,3 +522,19 @@ func (in *SourceSpec) DeepCopy() *SourceSpec {
 	in.DeepCopyInto(out)
 	return out
 }
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Step) DeepCopyInto(out *Step) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Step.
+func (in *Step) DeepCopy() *Step {
+	if in == nil {
+		return nil
+	}
+	out := new(Step)
+	in.DeepCopyInto(out)
+	return out
+}
diff --git a/pkg/builder/builder_steps.go b/pkg/builder/builder_steps.go
index b50fb9b1..ffe71372 100644
--- a/pkg/builder/builder_steps.go
+++ b/pkg/builder/builder_steps.go
@@ -81,6 +81,14 @@ func GenerateProject(ctx *Context) error {
 			}
 
 			deps.AddGAV("org.apache.camel", artifactID, "")
+		case strings.HasPrefix(d, "camel-k:"):
+			artifactID := strings.TrimPrefix(d, "camel-k:")
+
+			if !strings.HasPrefix(artifactID, "camel-") {
+				artifactID = "camel-" + artifactID
+			}
+
+			deps.AddGAV("org.apache.camel.k", artifactID, version.Version)
 		case strings.HasPrefix(d, "mvn:"):
 			mid := strings.TrimPrefix(d, "mvn:")
 			gav := strings.Replace(mid, "/", ":", -1)
@@ -242,7 +250,9 @@ func ListPublishedImages(context *Context) ([]PublishedImage, error) {
 		return nil, err
 	}
 	images := make([]PublishedImage, 0)
-	for _, ctx := range list.Items {
+	for _, item := range list.Items {
+		ctx := item
+
 		if ctx.Status.Phase != v1alpha1.IntegrationContextPhaseReady || ctx.Labels == nil {
 			continue
 		}
diff --git a/pkg/builder/springboot/generator.go b/pkg/builder/springboot/generator.go
index a50e04f0..e107a51b 100644
--- a/pkg/builder/springboot/generator.go
+++ b/pkg/builder/springboot/generator.go
@@ -125,6 +125,14 @@ func GenerateProject(ctx *builder.Context) error {
 					},
 				},
 			})
+		case strings.HasPrefix(d, "camel-k:"):
+			artifactID := strings.TrimPrefix(d, "camel-k:")
+
+			if !strings.HasPrefix(artifactID, "camel-") {
+				artifactID = "camel-" + artifactID
+			}
+
+			deps.AddGAV("org.apache.camel.k", artifactID, version.Version)
 		case strings.HasPrefix(d, "mvn:"):
 			mid := strings.TrimPrefix(d, "mvn:")
 			gav := strings.Replace(mid, "/", ":", -1)
diff --git a/pkg/client/cmd/install.go b/pkg/client/cmd/install.go
index 142f521c..6abe4bcf 100644
--- a/pkg/client/cmd/install.go
+++ b/pkg/client/cmd/install.go
@@ -83,7 +83,9 @@ func (o *installCmdOptions) install(cmd *cobra.Command, args []string) error {
 		err := install.SetupClusterwideResourcesOrCollect(collection)
 		if err != nil && k8serrors.IsForbidden(err) {
 			fmt.Println("Current user is not authorized to create cluster-wide objects like custom resource definitions or cluster roles: ", err)
-			return errors.New("please login as cluster-admin and execute \"kamel install --cluster-setup\" to install cluster-wide resources (one-time operation)")
+
+			meg := `please login as cluster-admin and execute "kamel install --cluster-setup" to install cluster-wide resources (one-time operation)`
+			return errors.New(meg)
 		} else if err != nil {
 			return err
 		}
diff --git a/pkg/install/operator.go b/pkg/install/operator.go
index 3088df3b..a35c344d 100644
--- a/pkg/install/operator.go
+++ b/pkg/install/operator.go
@@ -96,6 +96,7 @@ func Platform(namespace string, registry string, organization string, pushSecret
 }
 
 // PlatformOrCollect --
+// nolint: lll
 func PlatformOrCollect(namespace string, registry string, organization string, pushSecret string, collection *kubernetes.Collection) (*v1alpha1.IntegrationPlatform, error) {
 	if err := waitForPlatformCRDAvailable(namespace, 25*time.Second); err != nil {
 		return nil, err
diff --git a/pkg/metadata/dependencies.go b/pkg/metadata/dependencies.go
index c2bcc830..f70efdd1 100644
--- a/pkg/metadata/dependencies.go
+++ b/pkg/metadata/dependencies.go
@@ -68,6 +68,9 @@ func decodeComponent(uri string) string {
 		if component.GroupID == "org.apache.camel" && strings.HasPrefix(artifactID, "camel-") {
 			return "camel:" + artifactID[6:]
 		}
+		if component.GroupID == "org.apache.camel.k" && strings.HasPrefix(artifactID, "camel-") {
+			return "camel-k:" + artifactID[6:]
+		}
 		return "mvn:" + component.GroupID + ":" + artifactID + ":" + component.Version
 	}
 	return ""
diff --git a/pkg/metadata/languages.go b/pkg/metadata/languages.go
index 2d0d2dae..55389dcd 100644
--- a/pkg/metadata/languages.go
+++ b/pkg/metadata/languages.go
@@ -34,7 +34,8 @@ func discoverLanguage(source v1alpha1.SourceSpec) v1alpha1.Language {
 		v1alpha1.LanguageJavaScript,
 		v1alpha1.LanguageGroovy,
 		v1alpha1.LanguageJavaScript,
-		v1alpha1.LanguageKotlin} {
+		v1alpha1.LanguageKotlin,
+		v1alpha1.LanguageYamlFlow} {
 
 		if strings.HasSuffix(source.Name, "."+string(l)) {
 			return l
diff --git a/pkg/metadata/metadata.go b/pkg/metadata/metadata.go
index 30263e93..4f7d9806 100644
--- a/pkg/metadata/metadata.go
+++ b/pkg/metadata/metadata.go
@@ -21,6 +21,7 @@ import (
 	"sort"
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	src "github.com/apache/camel-k/pkg/util/source"
 )
 
 // ExtractAll returns metadata information from all listed source codes
@@ -70,8 +71,10 @@ func merge(m1 IntegrationMetadata, m2 IntegrationMetadata) IntegrationMetadata {
 // Extract returns metadata information from the source code
 func Extract(source v1alpha1.SourceSpec) IntegrationMetadata {
 	language := discoverLanguage(source)
-	fromURIs := discoverFromURIs(source, language)
-	toURIs := discoverToURIs(source, language)
+	// TODO: handle error
+	fromURIs, _ := src.InspectorForLanguage(language).FromURIs(source)
+	// TODO:: handle error
+	toURIs, _ := src.InspectorForLanguage(language).ToURIs(source)
 	dependencies := discoverDependencies(source, fromURIs, toURIs)
 	requiresHTTPService := requiresHTTPService(source, fromURIs)
 	passiveEndpoints := hasOnlyPassiveEndpoints(source, fromURIs)
diff --git a/pkg/metadata/metadata_uri_test.go b/pkg/metadata/metadata_uri_test.go
index 9dc26d49..6c136581 100644
--- a/pkg/metadata/metadata_uri_test.go
+++ b/pkg/metadata/metadata_uri_test.go
@@ -227,3 +227,31 @@ func TestJavascript1(t *testing.T) {
 	assert.Contains(t, metadata.ToURIs, "uri:%s") // resolution not supported yet
 	assert.Len(t, metadata.ToURIs, 4)
 }
+
+const yamlFlow = `
+- steps:
+  - kind: "endpoint"
+    uri: "timer:tick"
+  - kind: "endpoint"
+    uri: "log:info"
+`
+
+func TestJYamlFlow(t *testing.T) {
+	source := v1alpha1.SourceSpec{
+		DataSpec: v1alpha1.DataSpec{
+			Name:    "test",
+			Content: yamlFlow,
+		},
+		Language: v1alpha1.LanguageYamlFlow,
+	}
+
+	metadata := Extract(source)
+
+	assert.NotEmpty(t, metadata.FromURIs)
+	assert.Contains(t, metadata.FromURIs, "timer:tick")
+	assert.Len(t, metadata.FromURIs, 1)
+
+	assert.NotEmpty(t, metadata.ToURIs)
+	assert.Contains(t, metadata.ToURIs, "log:info")
+	assert.Len(t, metadata.ToURIs, 1)
+}
diff --git a/pkg/stub/action/platform/create.go b/pkg/stub/action/platform/create.go
index 5f8ea2fb..c5b70fd7 100644
--- a/pkg/stub/action/platform/create.go
+++ b/pkg/stub/action/platform/create.go
@@ -31,6 +31,10 @@ var resources = []string{
 	"platform-integration-context-spring-boot.yaml",
 }
 
+var knativeResources = []string{
+	"platform-integration-context-knative.yaml",
+}
+
 // NewCreateAction returns a action that creates resources needed by the platform
 func NewCreateAction() Action {
 	return &createAction{}
@@ -48,14 +52,23 @@ func (action *createAction) CanHandle(platform *v1alpha1.IntegrationPlatform) bo
 }
 
 func (action *createAction) Handle(platform *v1alpha1.IntegrationPlatform) error {
+	logrus.Info("Installing platform resources")
 	err := install.Resources(platform.Namespace, resources...)
 	if err != nil {
 		return err
 	}
 
+	if platform.Spec.Profile == v1alpha1.TraitProfileKnative {
+		logrus.Info("Installing knative resources")
+		err := install.Resources(platform.Namespace, knativeResources...)
+		if err != nil {
+			return err
+		}
+	}
+
 	target := platform.DeepCopy()
-	logrus.Info("Platform ", target.Name, " transitioning to state ", v1alpha1.IntegrationPlatformPhaseStarting)
 	target.Status.Phase = v1alpha1.IntegrationPlatformPhaseStarting
+	logrus.Info("Platform ", target.Name, " transitioning to state ", target.Status.Phase)
 
 	return sdk.Update(target)
 }
diff --git a/pkg/trait/dependencies.go b/pkg/trait/dependencies.go
index ccbc41b5..eddee8b3 100644
--- a/pkg/trait/dependencies.go
+++ b/pkg/trait/dependencies.go
@@ -49,10 +49,13 @@ func (t *dependenciesTrait) Apply(e *Environment) error {
 	for _, s := range e.Integration.Spec.Sources {
 		meta := metadata.Extract(s)
 
-		if meta.Language == v1alpha1.LanguageGroovy {
+		switch meta.Language {
+		case v1alpha1.LanguageGroovy:
 			util.StringSliceUniqueAdd(&e.Integration.Spec.Dependencies, "runtime:groovy")
-		} else if meta.Language == v1alpha1.LanguageKotlin {
+		case v1alpha1.LanguageKotlin:
 			util.StringSliceUniqueAdd(&e.Integration.Spec.Dependencies, "runtime:kotlin")
+		case v1alpha1.LanguageYamlFlow:
+			util.StringSliceUniqueAdd(&e.Integration.Spec.Dependencies, "runtime:yaml")
 		}
 
 		// jvm runtime and camel-core required by default
diff --git a/pkg/util/envvar/envvar.go b/pkg/util/envvar/envvar.go
index d8739cfe..ae0b9982 100644
--- a/pkg/util/envvar/envvar.go
+++ b/pkg/util/envvar/envvar.go
@@ -35,7 +35,8 @@ func Remove(vars *[]v1.EnvVar, name string) {
 	v := *vars
 	for i := 0; i < len(v); i++ {
 		if v[i].Name == name {
-			*vars = append(v[:i], v[i+1:]...)
+			v = append(v[:i], v[i+1:]...)
+			*vars = v
 			return
 		}
 	}
diff --git a/pkg/util/kubernetes/collection.go b/pkg/util/kubernetes/collection.go
index 54b340bd..6d7e1ce4 100644
--- a/pkg/util/kubernetes/collection.go
+++ b/pkg/util/kubernetes/collection.go
@@ -23,6 +23,7 @@ import (
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
 	"k8s.io/apimachinery/pkg/runtime"
 )
 
@@ -52,7 +53,7 @@ func (c *Collection) Items() []runtime.Object {
 func (c *Collection) AsKubernetesList() *corev1.List {
 	lst := corev1.List{
 		TypeMeta: metav1.TypeMeta{
-			Kind: "List",
+			Kind:       "List",
 			APIVersion: "v1",
 		},
 		Items: make([]runtime.RawExtension, 0, len(c.items)),
diff --git a/pkg/util/kubernetes/loader.go b/pkg/util/kubernetes/loader.go
index cd830da3..19085f18 100644
--- a/pkg/util/kubernetes/loader.go
+++ b/pkg/util/kubernetes/loader.go
@@ -19,6 +19,7 @@ package kubernetes
 
 import (
 	"encoding/json"
+
 	"github.com/operator-framework/operator-sdk/pkg/util/k8sutil"
 	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/runtime"
diff --git a/pkg/util/maven/maven_project.go b/pkg/util/maven/maven_project.go
index cba227ba..e9656774 100644
--- a/pkg/util/maven/maven_project.go
+++ b/pkg/util/maven/maven_project.go
@@ -151,11 +151,12 @@ func NewRepository(repo string) Repository {
 		r.URL = repo[:idx]
 
 		for _, attribute := range strings.Split(repo[idx+1:], "@") {
-			if attribute == "snapshots" {
+			switch {
+			case attribute == "snapshots":
 				r.Snapshots.Enabled = true
-			} else if attribute == "noreleases" {
+			case attribute == "noreleases":
 				r.Releases.Enabled = false
-			} else if strings.HasPrefix(attribute, "id=") {
+			case strings.HasPrefix(attribute, "id="):
 				r.ID = attribute[3:]
 			}
 		}
@@ -225,7 +226,9 @@ func (m Properties) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
 	}
 
 	for k, v := range m {
-		e.Encode(propertiesEntry{XMLName: xml.Name{Local: k}, Value: v})
+		if err := e.Encode(propertiesEntry{XMLName: xml.Name{Local: k}, Value: v}); err != nil {
+			return err
+		}
 	}
 
 	return e.EncodeToken(start.End())
diff --git a/pkg/metadata/uris.go b/pkg/util/source/inspector.go
similarity index 53%
rename from pkg/metadata/uris.go
rename to pkg/util/source/inspector.go
index 0c08f9ac..db76c490 100644
--- a/pkg/metadata/uris.go
+++ b/pkg/util/source/inspector.go
@@ -15,7 +15,7 @@ See the License for the specific language governing permissions and
 limitations under the License.
 */
 
-package metadata
+package source
 
 import (
 	"regexp"
@@ -32,53 +32,31 @@ var (
 	doubleQuotedTo   = regexp.MustCompile(`\.to\s*\(\s*"([a-z0-9-]+:[^"]+)"\s*\)`)
 	doubleQuotedToD  = regexp.MustCompile(`\.toD\s*\(\s*"([a-z0-9-]+:[^"]+)"\s*\)`)
 	doubleQuotedToF  = regexp.MustCompile(`\.toF\s*\(\s*"([a-z0-9-]+:[^"]+)"[^)]*\)`)
-	xmlTagFrom       = regexp.MustCompile(`<\s*from\s+[^>]*uri\s*=\s*"([a-z0-9-]+:[^"]+)"[^>]*>`)
-	xmlTagTo         = regexp.MustCompile(`<\s*to\s+[^>]*uri\s*=\s*"([a-z0-9-]+:[^"]+)"[^>]*>`)
-	xmlTagToD        = regexp.MustCompile(`<\s*toD\s+[^>]*uri\s*=\s*"([a-z0-9-]+:[^"]+)"[^>]*>`)
 )
 
-// discoverFromURIs returns all uris used in a from clause
-func discoverFromURIs(source v1alpha1.SourceSpec, language v1alpha1.Language) []string {
-	fromRegexps := getFromRegexpsForLanguage(language)
-	return findAllDistinctStringSubmatch(source.Content, fromRegexps...)
+// Inspector --
+type Inspector interface {
+	FromURIs(v1alpha1.SourceSpec) ([]string, error)
+	ToURIs(v1alpha1.SourceSpec) ([]string, error)
 }
 
-// discoverToURIs returns all uris used in a to clause
-func discoverToURIs(source v1alpha1.SourceSpec, language v1alpha1.Language) []string {
-	toRegexps := getToRegexpsForLanguage(language)
-	return findAllDistinctStringSubmatch(source.Content, toRegexps...)
-}
-
-func getFromRegexpsForLanguage(language v1alpha1.Language) []*regexp.Regexp {
-	switch language {
-	case v1alpha1.LanguageJavaSource:
-		return []*regexp.Regexp{doubleQuotedFrom}
-	case v1alpha1.LanguageXML:
-		return []*regexp.Regexp{xmlTagFrom}
-	case v1alpha1.LanguageGroovy:
-		return []*regexp.Regexp{singleQuotedFrom, doubleQuotedFrom}
-	case v1alpha1.LanguageJavaScript:
-		return []*regexp.Regexp{singleQuotedFrom, doubleQuotedFrom}
-	case v1alpha1.LanguageKotlin:
-		return []*regexp.Regexp{doubleQuotedFrom}
-	}
-	return []*regexp.Regexp{}
-}
-
-func getToRegexpsForLanguage(language v1alpha1.Language) []*regexp.Regexp {
+// InspectorForLanguage --
+func InspectorForLanguage(language v1alpha1.Language) Inspector {
 	switch language {
 	case v1alpha1.LanguageJavaSource:
-		return []*regexp.Regexp{doubleQuotedTo, doubleQuotedToD, doubleQuotedToF}
+		return &JavaSourceInspector{}
 	case v1alpha1.LanguageXML:
-		return []*regexp.Regexp{xmlTagTo, xmlTagToD}
+		return &XMLInspector{}
 	case v1alpha1.LanguageGroovy:
-		return []*regexp.Regexp{singleQuotedTo, doubleQuotedTo, singleQuotedToD, doubleQuotedToD, singleQuotedToF, doubleQuotedToF}
+		return &GroovyInspector{}
 	case v1alpha1.LanguageJavaScript:
-		return []*regexp.Regexp{singleQuotedTo, doubleQuotedTo, singleQuotedToD, doubleQuotedToD, singleQuotedToF, doubleQuotedToF}
+		return &JavaScriptInspector{}
 	case v1alpha1.LanguageKotlin:
-		return []*regexp.Regexp{doubleQuotedTo, doubleQuotedToD, doubleQuotedToF}
+		return &KotlinInspector{}
+	case v1alpha1.LanguageYamlFlow:
+		return &YAMLFlowInspector{}
 	}
-	return []*regexp.Regexp{}
+	return &noInspector{}
 }
 
 func findAllDistinctStringSubmatch(data string, regexps ...*regexp.Regexp) []string {
@@ -99,3 +77,13 @@ func findAllDistinctStringSubmatch(data string, regexps ...*regexp.Regexp) []str
 	}
 	return candidates
 }
+
+type noInspector struct {
+}
+
+func (i noInspector) FromURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	return []string{}, nil
+}
+func (i noInspector) ToURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	return []string{}, nil
+}
diff --git a/pkg/util/source/inspector_groovy.go b/pkg/util/source/inspector_groovy.go
new file mode 100644
index 00000000..ddcd8748
--- /dev/null
+++ b/pkg/util/source/inspector_groovy.go
@@ -0,0 +1,50 @@
+/*
+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 source
+
+import "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+
+// GroovyInspector --
+type GroovyInspector struct {
+}
+
+// FromURIs --
+func (i GroovyInspector) FromURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	answer := findAllDistinctStringSubmatch(
+		source.Content,
+		singleQuotedFrom,
+		doubleQuotedFrom,
+	)
+
+	return answer, nil
+}
+
+// ToURIs --
+func (i GroovyInspector) ToURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	answer := findAllDistinctStringSubmatch(
+		source.Content,
+		singleQuotedTo,
+		doubleQuotedTo,
+		singleQuotedToD,
+		doubleQuotedToD,
+		singleQuotedToF,
+		doubleQuotedToF,
+	)
+
+	return answer, nil
+}
diff --git a/pkg/util/source/inspector_java_script.go b/pkg/util/source/inspector_java_script.go
new file mode 100644
index 00000000..913fc8df
--- /dev/null
+++ b/pkg/util/source/inspector_java_script.go
@@ -0,0 +1,50 @@
+/*
+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 source
+
+import "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+
+// JavaScriptInspector --
+type JavaScriptInspector struct {
+}
+
+// FromURIs --
+func (i JavaScriptInspector) FromURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	answer := findAllDistinctStringSubmatch(
+		source.Content,
+		singleQuotedFrom,
+		doubleQuotedFrom,
+	)
+
+	return answer, nil
+}
+
+// ToURIs --
+func (i JavaScriptInspector) ToURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	answer := findAllDistinctStringSubmatch(
+		source.Content,
+		singleQuotedTo,
+		doubleQuotedTo,
+		singleQuotedToD,
+		doubleQuotedToD,
+		singleQuotedToF,
+		doubleQuotedToF,
+	)
+
+	return answer, nil
+}
diff --git a/pkg/util/source/inspector_java_source.go b/pkg/util/source/inspector_java_source.go
new file mode 100644
index 00000000..4a229539
--- /dev/null
+++ b/pkg/util/source/inspector_java_source.go
@@ -0,0 +1,46 @@
+/*
+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 source
+
+import "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+
+// JavaSourceInspector --
+type JavaSourceInspector struct {
+}
+
+// FromURIs --
+func (i JavaSourceInspector) FromURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	answer := findAllDistinctStringSubmatch(
+		source.Content,
+		doubleQuotedFrom,
+	)
+
+	return answer, nil
+}
+
+// ToURIs --
+func (i JavaSourceInspector) ToURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	answer := findAllDistinctStringSubmatch(
+		source.Content,
+		doubleQuotedTo,
+		doubleQuotedToD,
+		doubleQuotedToF,
+	)
+
+	return answer, nil
+}
diff --git a/pkg/util/source/inspector_kotlin.go b/pkg/util/source/inspector_kotlin.go
new file mode 100644
index 00000000..111bf14d
--- /dev/null
+++ b/pkg/util/source/inspector_kotlin.go
@@ -0,0 +1,46 @@
+/*
+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 source
+
+import "github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+
+// KotlinInspector --
+type KotlinInspector struct {
+}
+
+// FromURIs --
+func (i KotlinInspector) FromURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	answer := findAllDistinctStringSubmatch(
+		source.Content,
+		doubleQuotedFrom,
+	)
+
+	return answer, nil
+}
+
+// ToURIs --
+func (i KotlinInspector) ToURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	answer := findAllDistinctStringSubmatch(
+		source.Content,
+		doubleQuotedTo,
+		doubleQuotedToD,
+		doubleQuotedToF,
+	)
+
+	return answer, nil
+}
diff --git a/pkg/util/source/inspector_xml.go b/pkg/util/source/inspector_xml.go
new file mode 100644
index 00000000..c13f1e61
--- /dev/null
+++ b/pkg/util/source/inspector_xml.go
@@ -0,0 +1,89 @@
+/*
+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 source
+
+import (
+	"encoding/xml"
+	"strings"
+
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+)
+
+// XMLInspector --
+type XMLInspector struct {
+}
+
+// FromURIs --
+func (i XMLInspector) FromURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	content := strings.NewReader(source.Content)
+	decoder := xml.NewDecoder(content)
+
+	uris := make([]string, 0)
+
+	for {
+		// Read tokens from the XML document in a stream.
+		t, _ := decoder.Token()
+		if t == nil {
+			break
+		}
+
+		switch se := t.(type) {
+		case xml.StartElement:
+			switch se.Name.Local {
+			case "from", "fromF":
+				for _, a := range se.Attr {
+					if a.Name.Local == "uri" {
+						uris = append(uris, a.Value)
+					}
+				}
+			}
+		}
+	}
+
+	return uris, nil
+}
+
+// ToURIs --
+func (i XMLInspector) ToURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	content := strings.NewReader(source.Content)
+	decoder := xml.NewDecoder(content)
+
+	uris := make([]string, 0)
+
+	for {
+		// Read tokens from the XML document in a stream.
+		t, _ := decoder.Token()
+		if t == nil {
+			break
+		}
+
+		switch se := t.(type) {
+		case xml.StartElement:
+			switch se.Name.Local {
+			case "to", "toD", "toF":
+				for _, a := range se.Attr {
+					if a.Name.Local == "uri" {
+						uris = append(uris, a.Value)
+					}
+				}
+			}
+		}
+	}
+
+	return uris, nil
+}
diff --git a/pkg/util/source/inspector_yaml_flow.go b/pkg/util/source/inspector_yaml_flow.go
new file mode 100644
index 00000000..e677b4de
--- /dev/null
+++ b/pkg/util/source/inspector_yaml_flow.go
@@ -0,0 +1,67 @@
+/*
+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 source
+
+import (
+	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	yaml "gopkg.in/yaml.v2"
+)
+
+// YAMLFlowInspector --
+type YAMLFlowInspector struct {
+}
+
+// FromURIs --
+func (i YAMLFlowInspector) FromURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	var flows []v1alpha1.Flow
+
+	if err := yaml.Unmarshal([]byte(source.Content), &flows); err != nil {
+		return []string{}, nil
+	}
+
+	uris := make([]string, 0)
+
+	for _, flow := range flows {
+		if flow.Steps[0].URI != "" {
+			uris = append(uris, flow.Steps[0].URI)
+		}
+
+	}
+	return uris, nil
+}
+
+// ToURIs --
+func (i YAMLFlowInspector) ToURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	var flows []v1alpha1.Flow
+
+	if err := yaml.Unmarshal([]byte(source.Content), &flows); err != nil {
+		return []string{}, nil
+	}
+
+	uris := make([]string, 0)
+
+	for _, flow := range flows {
+		for i := 1; i < len(flow.Steps); i++ {
+			if flow.Steps[i].URI != "" {
+				uris = append(uris, flow.Steps[i].URI)
+			}
+		}
+	}
+
+	return uris, nil
+}
diff --git a/runtime/camel-k-runtime-core/src/main/java/org/apache/camel/k/InMemoryRegistry.java b/runtime/camel-k-runtime-core/src/main/java/org/apache/camel/k/InMemoryRegistry.java
new file mode 100644
index 00000000..203a03c7
--- /dev/null
+++ b/runtime/camel-k-runtime-core/src/main/java/org/apache/camel/k/InMemoryRegistry.java
@@ -0,0 +1,81 @@
+/**
+ * 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 org.apache.camel.k;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.stream.Collectors;
+
+import org.apache.camel.NoSuchBeanException;
+
+public final class InMemoryRegistry implements RuntimeRegistry {
+    private final ConcurrentMap<String, Object> registry;
+
+    public InMemoryRegistry() {
+        this.registry = new ConcurrentHashMap<>();
+    }
+
+    public void bind(String name, Object bean) {
+        this.registry.put(name, bean);
+    }
+
+    @Override
+    public Object lookupByName(String name) {
+        return registry.get(name);
+    }
+
+    @Override
+    public <T> T lookupByNameAndType(String name, Class<T> type) {
+        final Object answer = lookupByName(name);
+
+        if (answer != null) {
+            try {
+                return type.cast(answer);
+            } catch (Throwable t) {
+                throw new NoSuchBeanException(
+                    name,
+                    "Found bean: " + name + " in RuntimeRegistry: " + this + " of type: " + answer.getClass().getName() + " expected type was: " + type,
+                    t
+                );
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public <T> Map<String, T> findByTypeWithName(Class<T> type) {
+        final Map<String, T> result = new HashMap<>();
+
+        registry.entrySet().stream()
+            .filter(entry -> type.isInstance(entry.getValue()))
+            .forEach(entry -> result.put(entry.getKey(), type.cast(entry.getValue())));
+
+        return result;
+    }
+
+    @Override
+    public <T> Set<T> findByType(Class<T> type) {
+        return registry.values().stream()
+            .filter(type::isInstance)
+            .map(type::cast)
+            .collect(Collectors.toSet());
+    }
+}
diff --git a/runtime/camel-k-runtime-core/src/main/java/org/apache/camel/k/Language.java b/runtime/camel-k-runtime-core/src/main/java/org/apache/camel/k/Language.java
index 1f7f9a35..5fb01940 100644
--- a/runtime/camel-k-runtime-core/src/main/java/org/apache/camel/k/Language.java
+++ b/runtime/camel-k-runtime-core/src/main/java/org/apache/camel/k/Language.java
@@ -48,6 +48,10 @@
         "xml",
         Collections.singletonList("xml"),
         Collections.singletonList("xml")),
+    YamlFlow(
+        "yaml-flow",
+        Arrays.asList("yaml-flow", "flow"),
+        Collections.singletonList("flow")),
     Kotlin(
         "kotlin",
         Arrays.asList("kotlin", "kts"),
diff --git a/runtime/camel-k-runtime-core/src/main/java/org/apache/camel/k/support/RuntimeSupport.java b/runtime/camel-k-runtime-core/src/main/java/org/apache/camel/k/support/RuntimeSupport.java
new file mode 100644
index 00000000..9c92e5ed
--- /dev/null
+++ b/runtime/camel-k-runtime-core/src/main/java/org/apache/camel/k/support/RuntimeSupport.java
@@ -0,0 +1,108 @@
+/**
+ * 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 org.apache.camel.k.support;
+
+import java.util.Properties;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.NoFactoryAvailableException;
+import org.apache.camel.component.properties.PropertiesComponent;
+import org.apache.camel.k.Constants;
+import org.apache.camel.k.RoutesLoader;
+import org.apache.camel.k.RuntimeTrait;
+import org.apache.camel.k.Source;
+import org.apache.camel.spi.FactoryFinder;
+import org.apache.camel.util.IntrospectionSupport;
+
+
+public final class RuntimeSupport {
+    private RuntimeSupport() {
+    }
+
+    public static void configureContext(CamelContext context) {
+        try {
+            FactoryFinder finder = context.getFactoryFinder(Constants.RUNTIME_TRAIT_RESOURCE_PATH);
+            String traitIDs = System.getenv().getOrDefault(Constants.ENV_CAMEL_K_TRAITS, "");
+
+            for (String traitId: traitIDs.split(",", -1)) {
+                RuntimeTrait trait = (RuntimeTrait)finder.newInstance(traitId);
+
+                bindProperties(context, trait, "trait." + traitId);
+
+                trait.apply(context);
+            }
+        } catch (NoFactoryAvailableException e) {
+            // ignored
+        }
+
+        context.getRegistry().findByType(RuntimeTrait.class).forEach(
+            customizer -> {
+                customizer.apply(context);
+            }
+        );
+    }
+
+    public static void bindProperties(CamelContext context, Object target, String prefix) {
+        final PropertiesComponent component = context.getComponent("properties", PropertiesComponent.class);
+        final Properties properties = component.getInitialProperties();
+
+        if (properties == null) {
+            throw new IllegalStateException("PropertiesComponent has no properties");
+        }
+
+        bindProperties(properties, target, prefix);
+    }
+
+    public static void bindProperties(Properties properties, Object target, String prefix) {
+        properties.entrySet().stream()
+            .filter(entry -> entry.getKey() instanceof String)
+            .filter(entry -> entry.getValue() != null)
+            .filter(entry -> ((String)entry.getKey()).startsWith(prefix))
+            .forEach(entry -> {
+                    final String key = ((String)entry.getKey()).substring(prefix.length());
+                    final Object val = entry.getValue();
+
+                    try {
+                        IntrospectionSupport.setProperty(target, key, val, false);
+                    } catch (Exception ex) {
+                        throw new RuntimeException(ex);
+                    }
+                }
+            );
+    }
+
+    public static RoutesLoader loaderFor(CamelContext context, Source source) {
+        return  context.getRegistry().findByType(RoutesLoader.class).stream()
+            .filter(rl -> rl.getSupportedLanguages().contains(source.getLanguage()))
+            .findFirst()
+            .orElseGet(() -> lookupLoaderFromResource(context, source));
+    }
+
+    public static RoutesLoader lookupLoaderFromResource(CamelContext context, Source source) {
+        final FactoryFinder finder;
+        final RoutesLoader loader;
+
+        try {
+            finder = context.getFactoryFinder(Constants.ROUTES_LOADER_RESOURCE_PATH);
+            loader = (RoutesLoader)finder.newInstance(source.getLanguage().getId());
+        } catch (NoFactoryAvailableException e) {
+            throw new IllegalArgumentException("Unable to find loader for: " + source, e);
+        }
+
+        return loader;
+    }
+}
diff --git a/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/URIResolver.java b/runtime/camel-k-runtime-core/src/main/java/org/apache/camel/k/support/URIResolver.java
similarity index 98%
rename from runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/URIResolver.java
rename to runtime/camel-k-runtime-core/src/main/java/org/apache/camel/k/support/URIResolver.java
index 30bee2ea..3b20602d 100644
--- a/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/URIResolver.java
+++ b/runtime/camel-k-runtime-core/src/main/java/org/apache/camel/k/support/URIResolver.java
@@ -14,7 +14,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.camel.k.jvm;
+package org.apache.camel.k.support;
 
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
diff --git a/runtime/camel-k-runtime-groovy/src/main/groovy/org/apache/camel/k/groovy/GroovyRoutesLoader.groovy b/runtime/camel-k-runtime-groovy/src/main/groovy/org/apache/camel/k/groovy/GroovyRoutesLoader.groovy
index bb081d44..8493c483 100644
--- a/runtime/camel-k-runtime-groovy/src/main/groovy/org/apache/camel/k/groovy/GroovyRoutesLoader.groovy
+++ b/runtime/camel-k-runtime-groovy/src/main/groovy/org/apache/camel/k/groovy/GroovyRoutesLoader.groovy
@@ -22,8 +22,8 @@ import org.apache.camel.k.Language
 import org.apache.camel.k.RoutesLoader
 import org.apache.camel.k.RuntimeRegistry
 import org.apache.camel.k.Source
+import org.apache.camel.k.support.URIResolver
 import org.apache.camel.k.groovy.dsl.IntegrationConfiguration
-import org.apache.camel.k.jvm.*
 import org.codehaus.groovy.control.CompilerConfiguration
 
 class GroovyRoutesLoader implements RoutesLoader {
diff --git a/runtime/camel-k-runtime-groovy/src/test/groovy/org/apache/camel/k/groovy/LoaderTest.groovy b/runtime/camel-k-runtime-groovy/src/test/groovy/org/apache/camel/k/groovy/LoaderTest.groovy
index 87ce8590..72fe2db8 100644
--- a/runtime/camel-k-runtime-groovy/src/test/groovy/org/apache/camel/k/groovy/LoaderTest.groovy
+++ b/runtime/camel-k-runtime-groovy/src/test/groovy/org/apache/camel/k/groovy/LoaderTest.groovy
@@ -17,9 +17,9 @@
 package org.apache.camel.k.groovy
 
 import org.apache.camel.impl.DefaultCamelContext
-import org.apache.camel.k.jvm.Runtime
-import org.apache.camel.k.jvm.RuntimeSupport
+import org.apache.camel.k.InMemoryRegistry
 import org.apache.camel.k.Source
+import org.apache.camel.k.support.RuntimeSupport
 import org.apache.camel.model.ToDefinition
 import spock.lang.Specification
 
@@ -31,7 +31,7 @@ class LoaderTest extends Specification {
 
         when:
             def loader = RuntimeSupport.loaderFor(new DefaultCamelContext(), source)
-            def builder = loader.load(new Runtime.Registry(), source)
+            def builder = loader.load(new InMemoryRegistry(), source)
 
         then:
             loader instanceof GroovyRoutesLoader
diff --git a/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/Application.java b/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/Application.java
index b98c95be..82ad36af 100644
--- a/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/Application.java
+++ b/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/Application.java
@@ -19,6 +19,7 @@
 import org.apache.camel.CamelContext;
 import org.apache.camel.Component;
 import org.apache.camel.k.Constants;
+import org.apache.camel.k.support.RuntimeSupport;
 import org.apache.camel.main.MainListenerSupport;
 import org.apache.camel.support.LifecycleStrategySupport;
 import org.apache.camel.util.ObjectHelper;
@@ -33,14 +34,14 @@
         //
         // We now support setting the logging level only
         //
-        RuntimeSupport.configureLogging();
+        ApplicationSupport.configureLogging();
 
         //
         // Install a custom protocol handler to support discovering resources
         // from the platform i.e. in knative, resources are provided through
         // env var as it is not possible to mount config maps / secrets.
         //
-        RuntimeSupport.configureStreamHandler();
+        ApplicationSupport.configureStreamHandler();
     }
 
     // *******************************
@@ -57,7 +58,7 @@ public static void main(String[] args) throws Exception {
         }
 
         Runtime runtime = new Runtime();
-        runtime.setProperties(RuntimeSupport.loadProperties());
+        runtime.setProperties(ApplicationSupport.loadProperties());
         runtime.load(routes.split(",", -1));
         runtime.addMainListener(new ComponentPropertiesBinder());
         runtime.run();
diff --git a/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/RuntimeSupport.java b/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/ApplicationSupport.java
similarity index 72%
rename from runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/RuntimeSupport.java
rename to runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/ApplicationSupport.java
index 60d1cf93..97d6ceab 100644
--- a/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/RuntimeSupport.java
+++ b/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/ApplicationSupport.java
@@ -38,15 +38,8 @@
 import java.util.Properties;
 import java.util.zip.GZIPInputStream;
 
-import org.apache.camel.CamelContext;
-import org.apache.camel.NoFactoryAvailableException;
-import org.apache.camel.component.properties.PropertiesComponent;
 import org.apache.camel.k.Constants;
-import org.apache.camel.k.RoutesLoader;
-import org.apache.camel.k.RuntimeTrait;
-import org.apache.camel.k.Source;
-import org.apache.camel.spi.FactoryFinder;
-import org.apache.camel.util.IntrospectionSupport;
+import org.apache.camel.k.support.URIResolver;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.URISupport;
 import org.apache.commons.io.FilenameUtils;
@@ -57,8 +50,8 @@
 import org.apache.logging.log4j.core.config.LoggerConfig;
 
 
-public final class RuntimeSupport {
-    private RuntimeSupport() {
+public final class ApplicationSupport {
+    private ApplicationSupport() {
     }
 
     public static Properties loadProperties() {
@@ -122,29 +115,6 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
         return properties;
     }
 
-    public static void configureContext(CamelContext context) {
-        try {
-            FactoryFinder finder = context.getFactoryFinder(Constants.RUNTIME_TRAIT_RESOURCE_PATH);
-            String traitIDs = System.getenv().getOrDefault(Constants.ENV_CAMEL_K_TRAITS, "");
-
-            for (String traitId: traitIDs.split(",", -1)) {
-                RuntimeTrait trait = (RuntimeTrait)finder.newInstance(traitId);
-
-                bindProperties(context, trait, "trait." + traitId);
-
-                trait.apply(context);
-            }
-        } catch (NoFactoryAvailableException e) {
-            // ignored
-        }
-
-        context.getRegistry().findByType(RuntimeTrait.class).forEach(
-            customizer -> {
-                customizer.apply(context);
-            }
-        );
-    }
-
     public static void configureLogging() {
         final LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
         final Properties properties = loadProperties();
@@ -166,56 +136,6 @@ public static void configureLogging() {
         );
     }
 
-    public static void bindProperties(CamelContext context, Object target, String prefix) {
-        final PropertiesComponent component = context.getComponent("properties", PropertiesComponent.class);
-        final Properties properties = component.getInitialProperties();
-
-        if (properties == null) {
-            throw new IllegalStateException("PropertiesComponent has no properties");
-        }
-
-        bindProperties(properties, target, prefix);
-    }
-
-    public static void bindProperties(Properties properties, Object target, String prefix) {
-        properties.entrySet().stream()
-            .filter(entry -> entry.getKey() instanceof String)
-            .filter(entry -> entry.getValue() != null)
-            .filter(entry -> ((String)entry.getKey()).startsWith(prefix))
-            .forEach(entry -> {
-                    final String key = ((String)entry.getKey()).substring(prefix.length());
-                    final Object val = entry.getValue();
-
-                    try {
-                        IntrospectionSupport.setProperty(target, key, val, false);
-                    } catch (Exception ex) {
-                        throw new RuntimeException(ex);
-                    }
-                }
-            );
-    }
-
-    public static RoutesLoader loaderFor(CamelContext context, Source source) {
-        return  context.getRegistry().findByType(RoutesLoader.class).stream()
-            .filter(rl -> rl.getSupportedLanguages().contains(source.getLanguage()))
-            .findFirst()
-            .orElseGet(() -> lookupLoaderFromResource(context, source));
-    }
-
-    public static RoutesLoader lookupLoaderFromResource(CamelContext context, Source source) {
-        final FactoryFinder finder;
-        final RoutesLoader loader;
-
-        try {
-            finder = context.getFactoryFinder(Constants.ROUTES_LOADER_RESOURCE_PATH);
-            loader = (RoutesLoader)finder.newInstance(source.getLanguage().getId());
-        } catch (NoFactoryAvailableException e) {
-            throw new IllegalArgumentException("Unable to find loader for: " + source, e);
-        }
-
-        return loader;
-    }
-
     public static void configureStreamHandler() {
         URL.setURLStreamHandlerFactory(protocol -> "platform".equals(protocol) ? new PlatformStreamHandler() : null);
     }
diff --git a/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/Runtime.java b/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/Runtime.java
index 4d5adb5f..a68545da 100644
--- a/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/Runtime.java
+++ b/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/Runtime.java
@@ -16,24 +16,22 @@
  */
 package org.apache.camel.k.jvm;
 
-import java.util.HashMap;
 import java.util.Map;
 import java.util.Properties;
-import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
-import java.util.stream.Collectors;
 
 import org.apache.camel.CamelContext;
-import org.apache.camel.NoSuchBeanException;
 import org.apache.camel.ProducerTemplate;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.properties.PropertiesComponent;
 import org.apache.camel.impl.CompositeRegistry;
 import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.k.InMemoryRegistry;
 import org.apache.camel.k.RoutesLoader;
 import org.apache.camel.k.RuntimeRegistry;
 import org.apache.camel.k.Source;
+import org.apache.camel.k.support.RuntimeSupport;
 import org.apache.camel.main.MainSupport;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -46,7 +44,7 @@
 
     public Runtime() {
         this.contextMap = new ConcurrentHashMap<>();
-        this.registry = new Registry();
+        this.registry = new InMemoryRegistry();
     }
 
     public void load(String[] routes) throws Exception {
@@ -126,66 +124,4 @@ protected void doStop() throws Exception {
             getCamelContexts().get(0).stop();
         }
     }
-
-    // ********************************
-    //
-    // Registry
-    //
-    // ********************************
-
-    public static final class Registry implements RuntimeRegistry {
-        private final ConcurrentMap<String, Object> registry;
-
-        public Registry() {
-            this.registry = new ConcurrentHashMap<>();
-        }
-
-        public void bind(String name, Object bean) {
-            this.registry.put(name, bean);
-        }
-
-        @Override
-        public Object lookupByName(String name) {
-            return registry.get(name);
-        }
-
-        @Override
-        public <T> T lookupByNameAndType(String name, Class<T> type) {
-            final Object answer = lookupByName(name);
-
-            if (answer != null) {
-                try {
-                    return type.cast(answer);
-                } catch (Throwable t) {
-                    throw new NoSuchBeanException(
-                        name,
-                        "Found bean: " + name + " in RuntimeRegistry: " + this + " of type: " + answer.getClass().getName() + " expected type was: " + type,
-                        t
-                    );
-                }
-            }
-
-            return null;
-        }
-
-        @Override
-        public <T> Map<String, T> findByTypeWithName(Class<T> type) {
-            final Map<String, T> result = new HashMap<>();
-
-            registry.entrySet().stream()
-                .filter(entry -> type.isInstance(entry.getValue()))
-                .forEach(entry -> result.put(entry.getKey(), type.cast(entry.getValue())));
-
-            return result;
-        }
-
-        @Override
-        public <T> Set<T> findByType(Class<T> type) {
-            return registry.values().stream()
-                .filter(type::isInstance)
-                .map(type::cast)
-                .collect(Collectors.toSet());
-        }
-    }
-
 }
diff --git a/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/loader/JavaScriptLoader.java b/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/loader/JavaScriptLoader.java
index 650a4d1f..ca05c108 100644
--- a/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/loader/JavaScriptLoader.java
+++ b/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/loader/JavaScriptLoader.java
@@ -17,7 +17,7 @@
 import org.apache.camel.k.RoutesLoader;
 import org.apache.camel.k.RuntimeRegistry;
 import org.apache.camel.k.Source;
-import org.apache.camel.k.jvm.URIResolver;
+import org.apache.camel.k.support.URIResolver;
 import org.apache.camel.k.jvm.dsl.Components;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.rest.RestConfigurationDefinition;
diff --git a/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/loader/JavaSourceLoader.java b/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/loader/JavaSourceLoader.java
index 767a6d4a..bdcb6e30 100644
--- a/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/loader/JavaSourceLoader.java
+++ b/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/loader/JavaSourceLoader.java
@@ -10,7 +10,7 @@
 import org.apache.camel.k.RoutesLoader;
 import org.apache.camel.k.RuntimeRegistry;
 import org.apache.camel.k.Source;
-import org.apache.camel.k.jvm.URIResolver;
+import org.apache.camel.k.support.URIResolver;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.joor.Reflect;
diff --git a/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/loader/XmlLoader.java b/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/loader/XmlLoader.java
index 7532f141..113104de 100644
--- a/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/loader/XmlLoader.java
+++ b/runtime/camel-k-runtime-jvm/src/main/java/org/apache/camel/k/jvm/loader/XmlLoader.java
@@ -10,7 +10,7 @@
 import org.apache.camel.k.RoutesLoader;
 import org.apache.camel.k.RuntimeRegistry;
 import org.apache.camel.k.Source;
-import org.apache.camel.k.jvm.URIResolver;
+import org.apache.camel.k.support.URIResolver;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
diff --git a/runtime/camel-k-runtime-jvm/src/test/java/org/apache/camel/k/jvm/PropertiesTest.java b/runtime/camel-k-runtime-jvm/src/test/java/org/apache/camel/k/jvm/PropertiesTest.java
index 43e0d9c2..808664c8 100644
--- a/runtime/camel-k-runtime-jvm/src/test/java/org/apache/camel/k/jvm/PropertiesTest.java
+++ b/runtime/camel-k-runtime-jvm/src/test/java/org/apache/camel/k/jvm/PropertiesTest.java
@@ -30,7 +30,7 @@
 
     @Test
     public void testLoadProperties() throws Exception {
-        Properties properties = RuntimeSupport.loadProperties("src/test/resources/conf.properties", "src/test/resources/conf.d");
+        Properties properties = ApplicationSupport.loadProperties("src/test/resources/conf.properties", "src/test/resources/conf.d");
 
         Runtime runtime = new Runtime();
         runtime.setProperties(properties);
diff --git a/runtime/camel-k-runtime-jvm/src/test/java/org/apache/camel/k/jvm/RoutesLoadersTest.java b/runtime/camel-k-runtime-jvm/src/test/java/org/apache/camel/k/jvm/RoutesLoadersTest.java
index 88c29f99..64394c74 100644
--- a/runtime/camel-k-runtime-jvm/src/test/java/org/apache/camel/k/jvm/RoutesLoadersTest.java
+++ b/runtime/camel-k-runtime-jvm/src/test/java/org/apache/camel/k/jvm/RoutesLoadersTest.java
@@ -20,6 +20,7 @@
 
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.k.InMemoryRegistry;
 import org.apache.camel.k.RoutesLoader;
 import org.apache.camel.k.RuntimeRegistry;
 import org.apache.camel.k.Source;
@@ -27,6 +28,7 @@
 import org.apache.camel.k.jvm.loader.JavaScriptLoader;
 import org.apache.camel.k.jvm.loader.JavaSourceLoader;
 import org.apache.camel.k.jvm.loader.XmlLoader;
+import org.apache.camel.k.support.RuntimeSupport;
 import org.apache.camel.model.ProcessDefinition;
 import org.apache.camel.model.RouteDefinition;
 import org.apache.camel.model.SetBodyDefinition;
@@ -41,7 +43,7 @@
     @Test
     public void testLoaderFromRegistry() throws Exception {
         RoutesLoader myLoader = new JavaClassLoader();
-        RuntimeRegistry registry = new Runtime.Registry();
+        RuntimeRegistry registry = new InMemoryRegistry();
         registry.bind("my-loader", myLoader);
 
         Source source = Source.create("classpath:" + MyRoutes.class.getName() + ".class");
@@ -55,7 +57,7 @@ public void testLoaderFromRegistry() throws Exception {
     public void testLoadClass() throws Exception {
         Source source = Source.create("classpath:" + MyRoutes.class.getName() + ".class");
         RoutesLoader loader = RuntimeSupport.loaderFor(new DefaultCamelContext(), source);
-        RouteBuilder builder = loader.load(new Runtime.Registry(), source);
+        RouteBuilder builder = loader.load(new InMemoryRegistry(), source);
 
         assertThat(loader).isInstanceOf(JavaClassLoader.class);
         assertThat(builder).isNotNull();
@@ -72,7 +74,7 @@ public void testLoadClass() throws Exception {
     public void testLoadJava() throws Exception {
         Source source = Source.create("classpath:MyRoutes.java");
         RoutesLoader loader = RuntimeSupport.loaderFor(new DefaultCamelContext(), source);
-        RouteBuilder builder = loader.load(new Runtime.Registry(), source);
+        RouteBuilder builder = loader.load(new InMemoryRegistry(), source);
 
         assertThat(loader).isInstanceOf(JavaSourceLoader.class);
         assertThat(builder).isNotNull();
@@ -89,7 +91,7 @@ public void testLoadJava() throws Exception {
     public void testLoadJavaWithNestedClass() throws Exception {
         Source source = Source.create("classpath:MyRoutesWithNestedClass.java");
         RoutesLoader loader = RuntimeSupport.loaderFor(new DefaultCamelContext(), source);
-        RouteBuilder builder = loader.load(new Runtime.Registry(), source);
+        RouteBuilder builder = loader.load(new InMemoryRegistry(), source);
 
         assertThat(loader).isInstanceOf(JavaSourceLoader.class);
         assertThat(builder).isNotNull();
@@ -108,7 +110,7 @@ public void testLoadJavaWithNestedClass() throws Exception {
     public void testLoadJavaScript() throws Exception {
         Source source = Source.create("classpath:routes.js");
         RoutesLoader loader = RuntimeSupport.loaderFor(new DefaultCamelContext(), source);
-        RouteBuilder builder = loader.load(new Runtime.Registry(), source);
+        RouteBuilder builder = loader.load(new InMemoryRegistry(), source);
 
         assertThat(loader).isInstanceOf(JavaScriptLoader.class);
         assertThat(builder).isNotNull();
@@ -125,7 +127,7 @@ public void testLoadJavaScript() throws Exception {
     public void testLoadCompressedRoute() throws Exception {
         Source source = Source.create("classpath:routes-compressed.js.gz.b64?language=js&compression=true");
         RoutesLoader loader = RuntimeSupport.loaderFor(new DefaultCamelContext(), source);
-        RouteBuilder builder = loader.load(new Runtime.Registry(), source);
+        RouteBuilder builder = loader.load(new InMemoryRegistry(), source);
 
         assertThat(loader).isInstanceOf(JavaScriptLoader.class);
         assertThat(builder).isNotNull();
@@ -142,7 +144,7 @@ public void testLoadCompressedRoute() throws Exception {
     public void testLoadJavaScriptWithCustomExtension() throws Exception {
         Source source = Source.create("classpath:routes.mytype?language=js");
         RoutesLoader loader = RuntimeSupport.loaderFor(new DefaultCamelContext(), source);
-        RouteBuilder builder = loader.load(new Runtime.Registry(), source);
+        RouteBuilder builder = loader.load(new InMemoryRegistry(), source);
 
         assertThat(loader).isInstanceOf(JavaScriptLoader.class);
         assertThat(builder).isNotNull();
@@ -159,7 +161,7 @@ public void testLoadJavaScriptWithCustomExtension() throws Exception {
     public void testLoadXml() throws Exception {
         Source source = Source.create("classpath:routes.xml");
         RoutesLoader loader = RuntimeSupport.loaderFor(new DefaultCamelContext(), source);
-        RouteBuilder builder = loader.load(new Runtime.Registry(), source);
+        RouteBuilder builder = loader.load(new InMemoryRegistry(), source);
 
         assertThat(loader).isInstanceOf(XmlLoader.class);
         assertThat(builder).isNotNull();
diff --git a/runtime/camel-k-runtime-jvm/src/test/java/org/apache/camel/k/jvm/RuntimeTest.java b/runtime/camel-k-runtime-jvm/src/test/java/org/apache/camel/k/jvm/RuntimeTest.java
index e434c268..533c353f 100644
--- a/runtime/camel-k-runtime-jvm/src/test/java/org/apache/camel/k/jvm/RuntimeTest.java
+++ b/runtime/camel-k-runtime-jvm/src/test/java/org/apache/camel/k/jvm/RuntimeTest.java
@@ -56,7 +56,7 @@ void testLoadMultipleRoutes() throws Exception {
 
     @Test
     void testLoadResource() throws Exception {
-        RuntimeSupport.configureStreamHandler();
+        ApplicationSupport.configureStreamHandler();
 
         CamelContext context = new Runtime().getCamelContext();
 
diff --git a/runtime/camel-k-runtime-kotlin/src/main/kotlin/org/apache/camel/k/kotlin/KotlinRoutesLoader.kt b/runtime/camel-k-runtime-kotlin/src/main/kotlin/org/apache/camel/k/kotlin/KotlinRoutesLoader.kt
index d72bb605..efd01ee6 100644
--- a/runtime/camel-k-runtime-kotlin/src/main/kotlin/org/apache/camel/k/kotlin/KotlinRoutesLoader.kt
+++ b/runtime/camel-k-runtime-kotlin/src/main/kotlin/org/apache/camel/k/kotlin/KotlinRoutesLoader.kt
@@ -21,8 +21,8 @@ import org.apache.camel.k.Language
 import org.apache.camel.k.RoutesLoader
 import org.apache.camel.k.RuntimeRegistry
 import org.apache.camel.k.Source
-import org.apache.camel.k.jvm.URIResolver
 import org.apache.camel.k.kotlin.dsl.IntegrationConfiguration
+import org.apache.camel.k.support.URIResolver
 import org.slf4j.Logger
 import org.slf4j.LoggerFactory
 import java.io.File
diff --git a/runtime/camel-k-runtime-kotlin/src/test/kotlin/org/apache/camel/k/kotlin/LoaderTest.kt b/runtime/camel-k-runtime-kotlin/src/test/kotlin/org/apache/camel/k/kotlin/LoaderTest.kt
index be4dced0..8b090007 100644
--- a/runtime/camel-k-runtime-kotlin/src/test/kotlin/org/apache/camel/k/kotlin/LoaderTest.kt
+++ b/runtime/camel-k-runtime-kotlin/src/test/kotlin/org/apache/camel/k/kotlin/LoaderTest.kt
@@ -17,9 +17,9 @@
 package org.apache.camel.k.kotlin
 
 import org.apache.camel.impl.DefaultCamelContext
+import org.apache.camel.k.InMemoryRegistry
 import org.apache.camel.k.Source
-import org.apache.camel.k.jvm.Runtime
-import org.apache.camel.k.jvm.RuntimeSupport
+import org.apache.camel.k.support.RuntimeSupport
 import org.apache.camel.model.ProcessDefinition
 import org.apache.camel.model.ToDefinition
 import org.assertj.core.api.Assertions.assertThat
@@ -31,7 +31,7 @@ class LoaderTest {
     fun `load route from classpath`() {
         var source = Source.create("classpath:routes.kts")
         val loader = RuntimeSupport.loaderFor(DefaultCamelContext(), source)
-        val builder = loader.load(Runtime.Registry(), source)
+        val builder = loader.load(InMemoryRegistry(), source)
 
         assertThat(loader).isInstanceOf(KotlinRoutesLoader::class.java)
         assertThat(builder).isNotNull
diff --git a/runtime/camel-k-runtime-spring-boot/src/main/java/org/apache/camel/k/spring/boot/Application.java b/runtime/camel-k-runtime-spring-boot/src/main/java/org/apache/camel/k/spring/boot/Application.java
index a6fbb5a9..91839aac 100644
--- a/runtime/camel-k-runtime-spring-boot/src/main/java/org/apache/camel/k/spring/boot/Application.java
+++ b/runtime/camel-k-runtime-spring-boot/src/main/java/org/apache/camel/k/spring/boot/Application.java
@@ -25,8 +25,9 @@
 import org.apache.camel.k.RuntimeRegistry;
 import org.apache.camel.k.Constants;
 import org.apache.camel.k.RoutesLoader;
-import org.apache.camel.k.jvm.RuntimeSupport;
+import org.apache.camel.k.jvm.ApplicationSupport;
 import org.apache.camel.k.Source;
+import org.apache.camel.k.support.RuntimeSupport;
 import org.apache.camel.spi.Registry;
 import org.apache.camel.spring.boot.CamelContextConfiguration;
 import org.apache.camel.util.ObjectHelper;
@@ -48,7 +49,7 @@
         // from the platform i.e. in knative, resources are provided through
         // env var as it is not possible to mount config maps / secrets.
         //
-        RuntimeSupport.configureStreamHandler();
+        ApplicationSupport.configureStreamHandler();
     }
 
     public static void main(String[] args) {
@@ -64,7 +65,7 @@ public static void main(String[] args) {
     @Bean
     public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
         // load properties using default behaviour
-        final Properties properties = RuntimeSupport.loadProperties();
+        final Properties properties = ApplicationSupport.loadProperties();
 
         // set spring boot specific properties
         properties.put("camel.springboot.main-run-controller", "true");
diff --git a/runtime/camel-k-runtime-yaml/pom.xml b/runtime/camel-k-runtime-yaml/pom.xml
new file mode 100644
index 00000000..0e94a558
--- /dev/null
+++ b/runtime/camel-k-runtime-yaml/pom.xml
@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <parent>
+        <groupId>org.apache.camel.k</groupId>
+        <artifactId>camel-k-runtime-parent</artifactId>
+        <version>0.1.1-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>camel-k-runtime-yaml</artifactId>
+
+    <dependencies>
+
+        <!-- ****************************** -->
+        <!--                                -->
+        <!-- RUNTIME                        -->
+        <!--                                -->
+        <!-- ****************************** -->
+
+        <dependency>
+            <groupId>org.apache.camel.k</groupId>
+            <artifactId>camel-k-runtime-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel.k</groupId>
+            <artifactId>camel-k-runtime-jvm</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.core</groupId>
+            <artifactId>jackson-databind</artifactId>
+            <version>${jackson.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>com.fasterxml.jackson.dataformat</groupId>
+            <artifactId>jackson-dataformat-yaml</artifactId>
+            <version>${jackson.version}</version>
+        </dependency>
+
+        <!-- ****************************** -->
+        <!--                                -->
+        <!-- TESTS                          -->
+        <!--                                -->
+        <!-- ****************************** -->
+
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-api</artifactId>
+            <version>${junit-jupiter.version}</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-engine</artifactId>
+            <version>${junit-jupiter.version}</version>
+            <scope>test</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.assertj</groupId>
+            <artifactId>assertj-core</artifactId>
+            <version>${assertj.version}</version>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git a/runtime/camel-k-runtime-yaml/src/main/java/org/apache/camel/k/yaml/YamlFlowLoader.java b/runtime/camel-k-runtime-yaml/src/main/java/org/apache/camel/k/yaml/YamlFlowLoader.java
new file mode 100644
index 00000000..d5b5a37e
--- /dev/null
+++ b/runtime/camel-k-runtime-yaml/src/main/java/org/apache/camel/k/yaml/YamlFlowLoader.java
@@ -0,0 +1,104 @@
+/**
+ * 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 org.apache.camel.k.yaml;
+
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.List;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.jsontype.NamedType;
+import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
+import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.k.Language;
+import org.apache.camel.k.RoutesLoader;
+import org.apache.camel.k.RuntimeRegistry;
+import org.apache.camel.k.Source;
+import org.apache.camel.k.support.URIResolver;
+import org.apache.camel.k.yaml.model.Endpoint;
+import org.apache.camel.k.yaml.model.Flow;
+import org.apache.camel.k.yaml.model.Step;
+import org.apache.camel.k.yaml.model.StepHandler;
+import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.spi.FactoryFinder;
+
+public class YamlFlowLoader implements RoutesLoader {
+    private final ObjectMapper mapper;
+
+    public YamlFlowLoader() {
+        YAMLFactory yamlFactory = new YAMLFactory()
+            .configure(YAMLGenerator.Feature.MINIMIZE_QUOTES, true)
+            .configure(YAMLGenerator.Feature.ALWAYS_QUOTE_NUMBERS_AS_STRINGS, true)
+            .configure(YAMLGenerator.Feature.USE_NATIVE_TYPE_ID, false);
+
+        this.mapper = new ObjectMapper(yamlFactory)
+            .setSerializationInclusion(JsonInclude.Include.NON_EMPTY)
+            .enable(SerializationFeature.INDENT_OUTPUT);
+
+        mapper.registerSubtypes(new NamedType(Endpoint.class, Endpoint.KIND));
+    }
+
+    @Override
+    public List<Language> getSupportedLanguages() {
+        return Collections.singletonList(Language.YamlFlow);
+    }
+
+    @SuppressWarnings("uncheked")
+    @Override
+    public RouteBuilder load(RuntimeRegistry registry, Source source) throws Exception {
+        return new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                try (InputStream is = URIResolver.resolve(getContext(), source)) {
+                    for (Flow flow: mapper.readValue(is, Flow[].class)) {
+                        final List<Step> steps = flow.getSteps();
+                        final int size = steps.size();
+                        final FactoryFinder finder = getContext().getFactoryFinder(Step.RESOURCE_PATH);
+
+                        ProcessorDefinition<?> definition = null;
+
+                        for (int i = 0; i < size; i++) {
+                            Step step = steps.get(i);
+
+                            if (i == 0) {
+                                // force the cast so it will fail at runtime
+                                // if the step is not of the right type
+                                definition = from(((Endpoint) step).getUri());
+
+                                continue;
+                            }
+
+                            if (definition == null) {
+                                throw new IllegalStateException("No route definition");
+                            }
+
+                            StepHandler<Step> handler = (StepHandler<Step>)finder.newInstance(step.getKind());
+                            if (handler == null) {
+                                throw new IllegalStateException("No handler for step with kind: " + step.getKind());
+                            }
+
+                            definition = handler.handle(step, definition);
+                        }
+                    }
+                }
+            }
+        };
+    }
+}
diff --git a/runtime/camel-k-runtime-yaml/src/main/java/org/apache/camel/k/yaml/model/Endpoint.java b/runtime/camel-k-runtime-yaml/src/main/java/org/apache/camel/k/yaml/model/Endpoint.java
new file mode 100644
index 00000000..6ad07ee7
--- /dev/null
+++ b/runtime/camel-k-runtime-yaml/src/main/java/org/apache/camel/k/yaml/model/Endpoint.java
@@ -0,0 +1,46 @@
+/**
+ * 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 org.apache.camel.k.yaml.model;
+
+public class Endpoint extends Step {
+    public static final String KIND = "endpoint";
+
+    private String uri;
+
+    public Endpoint() {
+        super(KIND);
+    }
+
+    public Endpoint(String uri) {
+        super(KIND);
+
+        this.uri = uri;
+    }
+
+    @Override
+    public String toString() {
+        return "Endpoint: " + uri;
+    }
+
+    public String getUri() {
+        return uri;
+    }
+
+    public void setUri(String uri) {
+        this.uri = uri;
+    }
+}
diff --git a/runtime/camel-k-runtime-yaml/src/main/java/org/apache/camel/k/yaml/model/Flow.java b/runtime/camel-k-runtime-yaml/src/main/java/org/apache/camel/k/yaml/model/Flow.java
new file mode 100644
index 00000000..89031dd0
--- /dev/null
+++ b/runtime/camel-k-runtime-yaml/src/main/java/org/apache/camel/k/yaml/model/Flow.java
@@ -0,0 +1,31 @@
+/**
+ * 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 org.apache.camel.k.yaml.model;
+
+import java.util.List;
+
+public class Flow {
+    private List<Step> steps;
+
+    public List<Step> getSteps() {
+        return steps;
+    }
+
+    public void setSteps(List<Step> steps) {
+        this.steps = steps;
+    }
+}
diff --git a/runtime/camel-k-runtime-yaml/src/main/java/org/apache/camel/k/yaml/model/Step.java b/runtime/camel-k-runtime-yaml/src/main/java/org/apache/camel/k/yaml/model/Step.java
new file mode 100644
index 00000000..f2e8a2ea
--- /dev/null
+++ b/runtime/camel-k-runtime-yaml/src/main/java/org/apache/camel/k/yaml/model/Step.java
@@ -0,0 +1,38 @@
+/**
+ * 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 org.apache.camel.k.yaml.model;
+
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "kind")
+public abstract class Step {
+    public static final String RESOURCE_PATH = "META-INF/services/org/apache/camel/k/yaml/flow/";
+
+    private final String kind;
+
+    public Step(String kind) {
+        this.kind = kind;
+    }
+
+    @JsonIgnore
+    public String getKind() {
+        return kind;
+    }
+}
diff --git a/runtime/camel-k-runtime-yaml/src/main/java/org/apache/camel/k/yaml/model/StepHandler.java b/runtime/camel-k-runtime-yaml/src/main/java/org/apache/camel/k/yaml/model/StepHandler.java
new file mode 100644
index 00000000..8a260306
--- /dev/null
+++ b/runtime/camel-k-runtime-yaml/src/main/java/org/apache/camel/k/yaml/model/StepHandler.java
@@ -0,0 +1,30 @@
+/**
+ * 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 org.apache.camel.k.yaml.model;
+
+import org.apache.camel.model.ProcessorDefinition;
+
+@FunctionalInterface
+public interface StepHandler<T extends Step> {
+
+    /**
+     * @param step the step
+     * @param route the handler
+     * @return
+     */
+    ProcessorDefinition<?> handle(T step, ProcessorDefinition<?> route);
+}
diff --git a/runtime/camel-k-runtime-yaml/src/main/java/org/apache/camel/k/yaml/model/handler/EndpointHandler.java b/runtime/camel-k-runtime-yaml/src/main/java/org/apache/camel/k/yaml/model/handler/EndpointHandler.java
new file mode 100644
index 00000000..25b80b50
--- /dev/null
+++ b/runtime/camel-k-runtime-yaml/src/main/java/org/apache/camel/k/yaml/model/handler/EndpointHandler.java
@@ -0,0 +1,36 @@
+/**
+ * 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 org.apache.camel.k.yaml.model.handler;
+
+import org.apache.camel.k.yaml.model.Endpoint;
+import org.apache.camel.k.yaml.model.StepHandler;
+import org.apache.camel.model.ProcessorDefinition;
+import org.apache.camel.util.ObjectHelper;
+
+public class EndpointHandler implements StepHandler<Endpoint> {
+    @Override
+    public ProcessorDefinition<?> handle(Endpoint step, ProcessorDefinition<?> route) {
+        String uri = step.getUri();
+
+        if (!ObjectHelper.isEmpty(uri)) {
+            route = route.to(uri);
+        }
+
+        return route;
+    }
+}
+
diff --git a/runtime/camel-k-runtime-yaml/src/main/resources/META-INF/services/org/apache/camel/k/loader/yaml-flow b/runtime/camel-k-runtime-yaml/src/main/resources/META-INF/services/org/apache/camel/k/loader/yaml-flow
new file mode 100644
index 00000000..242f8741
--- /dev/null
+++ b/runtime/camel-k-runtime-yaml/src/main/resources/META-INF/services/org/apache/camel/k/loader/yaml-flow
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+class=org.apache.camel.k.yaml.YamlFlowLoader
\ No newline at end of file
diff --git a/runtime/camel-k-runtime-yaml/src/main/resources/META-INF/services/org/apache/camel/k/yaml/flow/endpoint b/runtime/camel-k-runtime-yaml/src/main/resources/META-INF/services/org/apache/camel/k/yaml/flow/endpoint
new file mode 100644
index 00000000..6af1c193
--- /dev/null
+++ b/runtime/camel-k-runtime-yaml/src/main/resources/META-INF/services/org/apache/camel/k/yaml/flow/endpoint
@@ -0,0 +1,18 @@
+#
+# 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.
+#
+
+class=org.apache.camel.k.yaml.model.handler.EndpointHandler
\ No newline at end of file
diff --git a/runtime/camel-k-runtime-yaml/src/test/java/org/apache/camel/k/yaml/RoutesLoaderTest.java b/runtime/camel-k-runtime-yaml/src/test/java/org/apache/camel/k/yaml/RoutesLoaderTest.java
new file mode 100644
index 00000000..1035306f
--- /dev/null
+++ b/runtime/camel-k-runtime-yaml/src/test/java/org/apache/camel/k/yaml/RoutesLoaderTest.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.
+ */
+package org.apache.camel.k.yaml;
+
+import java.util.List;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.k.RoutesLoader;
+import org.apache.camel.k.Source;
+import org.apache.camel.k.InMemoryRegistry;
+import org.apache.camel.k.support.RuntimeSupport;
+import org.apache.camel.model.RouteDefinition;
+import org.apache.camel.model.ToDefinition;
+import org.junit.jupiter.api.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class RoutesLoaderTest {
+
+    @Test
+    public void testLoadYamlFlow() throws Exception {
+        Source source = Source.create("classpath:routes.flow");
+        RoutesLoader loader = RuntimeSupport.loaderFor(new DefaultCamelContext(), source);
+        RouteBuilder builder = loader.load(new InMemoryRegistry(), source);
+
+        assertThat(loader).isInstanceOf(YamlFlowLoader.class);
+        assertThat(builder).isNotNull();
+
+        builder.configure();
+
+        List<RouteDefinition> routes = builder.getRouteCollection().getRoutes();
+        assertThat(routes).hasSize(1);
+        assertThat(routes.get(0).getInputs().get(0).getEndpointUri()).isEqualTo("timer:tick");
+        assertThat(routes.get(0).getOutputs().get(0)).isInstanceOf(ToDefinition.class);
+    }
+}
diff --git a/runtime/camel-k-runtime-yaml/src/test/resources/log4j2-test.xml b/runtime/camel-k-runtime-yaml/src/test/resources/log4j2-test.xml
new file mode 100644
index 00000000..a505fd91
--- /dev/null
+++ b/runtime/camel-k-runtime-yaml/src/test/resources/log4j2-test.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration status="INFO">
+  <Appenders>
+    <Console name="STDOUT" target="SYSTEM_OUT">
+      <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS}|%-5level|%t|%c{1} - %msg%n"/>
+    </Console>
+    <Null name="NONE"/>
+  </Appenders>
+
+  <Loggers>
+    <Root level="INFO">
+      <!-- <AppenderRef ref="STDOUT"/> -->
+      <AppenderRef ref="NONE"/>
+    </Root>
+  </Loggers>
+
+</Configuration>
\ No newline at end of file
diff --git a/runtime/camel-k-runtime-yaml/src/test/resources/routes.flow b/runtime/camel-k-runtime-yaml/src/test/resources/routes.flow
new file mode 100644
index 00000000..19645350
--- /dev/null
+++ b/runtime/camel-k-runtime-yaml/src/test/resources/routes.flow
@@ -0,0 +1,5 @@
+- steps:
+  - kind: "endpoint"
+    uri: "timer:tick"
+  - kind: "endpoint"
+    uri: "log:info"
\ No newline at end of file
diff --git a/runtime/pom.xml b/runtime/pom.xml
index 014e40bb..29a68460 100644
--- a/runtime/pom.xml
+++ b/runtime/pom.xml
@@ -98,6 +98,7 @@
         <module>camel-k-runtime-jvm</module>
         <module>camel-k-runtime-groovy</module>
         <module>camel-k-runtime-kotlin</module>
+        <module>camel-k-runtime-yaml</module>
         <module>camel-k-runtime-spring-boot</module>
         <module>catalog-builder</module>
         <module>dependency-lister</module>


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@xxxxxxxxxxxxxxxx


With regards,
Apache Git Services