You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by nf...@apache.org on 2018/12/21 11:05:54 UTC

[camel-k] 01/04: add support for a simple yaml flow

This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit e48fe409aad3aaafc650484a5ab66ffa6175d82c
Author: lburgazzoli <lb...@gmail.com>
AuthorDate: Thu Dec 20 12:04:06 2018 +0100

    add support for a simple yaml flow
---
 ...yaml => platform-integration-context-flow.yaml} |   6 +-
 deploy/platform-integration-context-groovy.yaml    |   2 +-
 deploy/platform-integration-context-jvm.yaml       |   2 +-
 deploy/platform-integration-context-kotlin.yaml    |   2 +-
 .../platform-integration-context-spring-boot.yaml  |   2 +-
 deploy/resources.go                                |  25 ++-
 examples/routes.flow                               |   5 +
 pkg/apis/camel/v1alpha1/types.go                   |  13 ++
 pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go   |  37 ++++
 pkg/metadata/languages.go                          |   3 +-
 pkg/metadata/metadata.go                           |   6 +-
 pkg/metadata/metadata_uri_test.go                  |  28 +++
 pkg/metadata/uris.go                               | 196 ++++++++++++++++++---
 pkg/stub/action/platform/create.go                 |   1 +
 pkg/trait/dependencies.go                          |   2 +
 .../java/org/apache/camel/k/InMemoryRegistry.java  |  81 +++++++++
 .../src/main/java/org/apache/camel/k/Language.java |   4 +
 .../org/apache/camel/k/support/RuntimeSupport.java | 108 ++++++++++++
 .../org/apache/camel/k/support}/URIResolver.java   |   2 +-
 .../camel/k/groovy/GroovyRoutesLoader.groovy       |   2 +-
 .../org/apache/camel/k/groovy/LoaderTest.groovy    |   6 +-
 .../java/org/apache/camel/k/jvm/Application.java   |   7 +-
 ...RuntimeSupport.java => ApplicationSupport.java} |  86 +--------
 .../main/java/org/apache/camel/k/jvm/Runtime.java  |  70 +-------
 .../camel/k/jvm/loader/JavaScriptLoader.java       |   2 +-
 .../camel/k/jvm/loader/JavaSourceLoader.java       |   2 +-
 .../org/apache/camel/k/jvm/loader/XmlLoader.java   |   2 +-
 .../org/apache/camel/k/jvm/PropertiesTest.java     |   2 +-
 .../org/apache/camel/k/jvm/RoutesLoadersTest.java  |  18 +-
 .../java/org/apache/camel/k/jvm/RuntimeTest.java   |   2 +-
 .../apache/camel/k/kotlin/KotlinRoutesLoader.kt    |   2 +-
 .../kotlin/org/apache/camel/k/kotlin/LoaderTest.kt |   6 +-
 .../apache/camel/k/spring/boot/Application.java    |   7 +-
 runtime/camel-k-runtime-yaml/pom.xml               |  88 +++++++++
 .../org/apache/camel/k/yaml/YamlFlowLoader.java    | 104 +++++++++++
 .../org/apache/camel/k/yaml/model/Endpoint.java    |  46 +++++
 .../java/org/apache/camel/k/yaml/model/Flow.java   |  31 ++++
 .../java/org/apache/camel/k/yaml/model/Step.java   |  38 ++++
 .../org/apache/camel/k/yaml/model/StepHandler.java |  30 ++++
 .../k/yaml/model/handler/EndpointHandler.java      |  36 ++++
 .../services/org/apache/camel/k/loader/yaml-flow   |  18 ++
 .../services/org/apache/camel/k/yaml/flow/endpoint |  18 ++
 .../org/apache/camel/k/yaml/RoutesLoaderTest.java  |  51 ++++++
 .../src/test/resources/log4j2-test.xml             |  17 ++
 .../src/test/resources/routes.flow                 |   5 +
 runtime/pom.xml                                    |   1 +
 46 files changed, 1001 insertions(+), 221 deletions(-)

diff --git a/deploy/platform-integration-context-groovy.yaml b/deploy/platform-integration-context-flow.yaml
similarity index 68%
copy from deploy/platform-integration-context-groovy.yaml
copy to deploy/platform-integration-context-flow.yaml
index 31aaeff..054f3c1 100644
--- a/deploy/platform-integration-context-groovy.yaml
+++ b/deploy/platform-integration-context-flow.yaml
@@ -1,14 +1,14 @@
 apiVersion: camel.apache.org/v1alpha1
 kind: IntegrationContext
 metadata:
-  name: groovy
+  name: flow
   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:
     - runtime:jvm
-    - runtime:groovy
+    - runtime:yaml
     - camel:core
\ No newline at end of file
diff --git a/deploy/platform-integration-context-groovy.yaml b/deploy/platform-integration-context-groovy.yaml
index 31aaeff..5265f51 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 28e8ff5..acaf7c3 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-kotlin.yaml b/deploy/platform-integration-context-kotlin.yaml
index 822b4a4..8eb5836 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 e52d9f7..5b86911 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 5ebc74b..6ceed46 100644
--- a/deploy/resources.go
+++ b/deploy/resources.go
@@ -2723,6 +2723,23 @@ spec:
     camelVersion: "2.23.0"
 
 `
+	Resources["platform-integration-context-flow.yaml"] =
+		`
+apiVersion: camel.apache.org/v1alpha1
+kind: IntegrationContext
+metadata:
+  name: flow
+  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
+`
 	Resources["platform-integration-context-groovy.yaml"] =
 		`
 apiVersion: camel.apache.org/v1alpha1
@@ -2732,7 +2749,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,7 +2766,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:
@@ -2765,7 +2782,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 +2799,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 0000000..ea69305
--- /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 0627da1..ef4dcc0 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 c61ab94..85e3be8 100644
--- a/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/camel/v1alpha1/zz_generated.deepcopy.go
@@ -74,6 +74,27 @@ func (in *DataSpec) DeepCopy() *DataSpec {
 }
 
 // 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
 	out.TypeMeta = in.TypeMeta
@@ -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/metadata/languages.go b/pkg/metadata/languages.go
index 2d0d2da..55389dc 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 30263e9..a696f99 100644
--- a/pkg/metadata/metadata.go
+++ b/pkg/metadata/metadata.go
@@ -70,8 +70,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, _ := GetInspectorForLanguage(language).FromURIs(source)
+	// TODO:: handle error
+	toURIs, _ := GetInspectorForLanguage(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 9dc26d4..6c13658 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/metadata/uris.go b/pkg/metadata/uris.go
index 0c08f9a..c267cfa 100644
--- a/pkg/metadata/uris.go
+++ b/pkg/metadata/uris.go
@@ -21,6 +21,7 @@ import (
 	"regexp"
 
 	"github.com/apache/camel-k/pkg/apis/camel/v1alpha1"
+	yaml "gopkg.in/yaml.v2"
 )
 
 var (
@@ -37,48 +38,185 @@ var (
 	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...)
+// LanguageInspector --
+type LanguageInspector 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...)
+type languageInspector struct {
+	from func(v1alpha1.SourceSpec) ([]string, error)
+	to   func(v1alpha1.SourceSpec) ([]string, error)
 }
 
-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 (i languageInspector) FromURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	return i.from(source)
+}
+func (i languageInspector) ToURIs(source v1alpha1.SourceSpec) ([]string, error) {
+	return i.to(source)
 }
 
-func getToRegexpsForLanguage(language v1alpha1.Language) []*regexp.Regexp {
+// GetInspectorForLanguage --
+func GetInspectorForLanguage(language v1alpha1.Language) LanguageInspector {
 	switch language {
 	case v1alpha1.LanguageJavaSource:
-		return []*regexp.Regexp{doubleQuotedTo, doubleQuotedToD, doubleQuotedToF}
+		return &languageInspector{
+			from: func(source v1alpha1.SourceSpec) ([]string, error) {
+				answer := findAllDistinctStringSubmatch(
+					source.Content,
+					doubleQuotedFrom,
+				)
+
+				return answer, nil
+			},
+			to: func(source v1alpha1.SourceSpec) ([]string, error) {
+				answer := findAllDistinctStringSubmatch(
+					source.Content,
+					doubleQuotedTo,
+					doubleQuotedToD,
+					doubleQuotedToF,
+				)
+
+				return answer, nil
+			},
+		}
 	case v1alpha1.LanguageXML:
-		return []*regexp.Regexp{xmlTagTo, xmlTagToD}
+		return &languageInspector{
+			from: func(source v1alpha1.SourceSpec) ([]string, error) {
+				answer := findAllDistinctStringSubmatch(
+					source.Content,
+					xmlTagFrom,
+				)
+
+				return answer, nil
+			},
+			to: func(source v1alpha1.SourceSpec) ([]string, error) {
+				answer := findAllDistinctStringSubmatch(
+					source.Content,
+					xmlTagTo,
+					xmlTagToD,
+				)
+
+				return answer, nil
+			},
+		}
 	case v1alpha1.LanguageGroovy:
-		return []*regexp.Regexp{singleQuotedTo, doubleQuotedTo, singleQuotedToD, doubleQuotedToD, singleQuotedToF, doubleQuotedToF}
+		return &languageInspector{
+			from: func(source v1alpha1.SourceSpec) ([]string, error) {
+				answer := findAllDistinctStringSubmatch(
+					source.Content,
+					singleQuotedFrom,
+					doubleQuotedFrom,
+				)
+
+				return answer, nil
+			},
+			to: func(source v1alpha1.SourceSpec) ([]string, error) {
+				answer := findAllDistinctStringSubmatch(
+					source.Content,
+					singleQuotedTo,
+					doubleQuotedTo,
+					singleQuotedToD,
+					doubleQuotedToD,
+					singleQuotedToF,
+					doubleQuotedToF,
+				)
+
+				return answer, nil
+			},
+		}
 	case v1alpha1.LanguageJavaScript:
-		return []*regexp.Regexp{singleQuotedTo, doubleQuotedTo, singleQuotedToD, doubleQuotedToD, singleQuotedToF, doubleQuotedToF}
+		return &languageInspector{
+			from: func(source v1alpha1.SourceSpec) ([]string, error) {
+				answer := findAllDistinctStringSubmatch(
+					source.Content,
+					singleQuotedFrom,
+					doubleQuotedFrom,
+				)
+
+				return answer, nil
+			},
+			to: func(source v1alpha1.SourceSpec) ([]string, error) {
+				answer := findAllDistinctStringSubmatch(
+					source.Content,
+					singleQuotedTo,
+					doubleQuotedTo,
+					singleQuotedToD,
+					doubleQuotedToD,
+					singleQuotedToF,
+					doubleQuotedToF,
+				)
+
+				return answer, nil
+			},
+		}
 	case v1alpha1.LanguageKotlin:
-		return []*regexp.Regexp{doubleQuotedTo, doubleQuotedToD, doubleQuotedToF}
+		return &languageInspector{
+			from: func(source v1alpha1.SourceSpec) ([]string, error) {
+				answer := findAllDistinctStringSubmatch(
+					source.Content,
+					doubleQuotedFrom,
+				)
+
+				return answer, nil
+			},
+			to: func(source v1alpha1.SourceSpec) ([]string, error) {
+				answer := findAllDistinctStringSubmatch(
+					source.Content,
+					doubleQuotedTo,
+					doubleQuotedToD,
+					doubleQuotedToF,
+				)
+
+				return answer, nil
+			},
+		}
+	case v1alpha1.LanguageYamlFlow:
+		var flows []v1alpha1.Flow
+
+		return &languageInspector{
+			from: func(source v1alpha1.SourceSpec) ([]string, error) {
+				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
+			},
+			to: func(source v1alpha1.SourceSpec) ([]string, error) {
+				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
+			},
+		}
+	}
+	return &languageInspector{
+		from: func(source v1alpha1.SourceSpec) ([]string, error) {
+			return []string{}, nil
+		},
+		to: func(source v1alpha1.SourceSpec) ([]string, error) {
+			return []string{}, nil
+		},
 	}
-	return []*regexp.Regexp{}
 }
 
 func findAllDistinctStringSubmatch(data string, regexps ...*regexp.Regexp) []string {
diff --git a/pkg/stub/action/platform/create.go b/pkg/stub/action/platform/create.go
index 5f8ea2f..5ab81ae 100644
--- a/pkg/stub/action/platform/create.go
+++ b/pkg/stub/action/platform/create.go
@@ -28,6 +28,7 @@ var resources = []string{
 	"platform-integration-context-jvm.yaml",
 	"platform-integration-context-groovy.yaml",
 	"platform-integration-context-kotlin.yaml",
+	"platform-integration-context-yaml.yaml",
 	"platform-integration-context-spring-boot.yaml",
 }
 
diff --git a/pkg/trait/dependencies.go b/pkg/trait/dependencies.go
index ccbc41b..3593dde 100644
--- a/pkg/trait/dependencies.go
+++ b/pkg/trait/dependencies.go
@@ -53,6 +53,8 @@ func (t *dependenciesTrait) Apply(e *Environment) error {
 			util.StringSliceUniqueAdd(&e.Integration.Spec.Dependencies, "runtime:groovy")
 		} else if meta.Language == v1alpha1.LanguageKotlin {
 			util.StringSliceUniqueAdd(&e.Integration.Spec.Dependencies, "runtime:kotlin")
+		} else if meta.Language == v1alpha1.LanguageYamlFlow {
+			util.StringSliceUniqueAdd(&e.Integration.Spec.Dependencies, "runtime:yaml")
 		}
 
 		// jvm runtime and camel-core required by default
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 0000000..203a03c
--- /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 1f7f9a3..5fb0194 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 @@ public enum Language {
         "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 0000000..9c92e5e
--- /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 30bee2e..3b20602 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 bb081d4..8493c48 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 87ce859..72fe2db 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 b98c95b..82ad36a 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 @@ package org.apache.camel.k.jvm;
 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 @@ public class Application {
         //
         // 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 class Application {
         }
 
         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 60d1cf9..97d6cea 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.Objects;
 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.LoggerContext;
 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 final class RuntimeSupport {
         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 final class RuntimeSupport {
         );
     }
 
-    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 4d5adb5..a68545d 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 final class Runtime extends MainSupport {
 
     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 @@ public final class Runtime extends MainSupport {
             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 650a4d1..ca05c10 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.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.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 767a6d4..bdcb6e3 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.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.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 7532f14..113104d 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.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.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 43e0d9c..808664c 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 @@ public class PropertiesTest {
 
     @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 88c29f9..64394c7 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 java.util.List;
 
 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.JavaClassLoader;
 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 @@ public class RoutesLoadersTest {
     @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 class RoutesLoadersTest {
     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 class RoutesLoadersTest {
     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 class RoutesLoadersTest {
     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 class RoutesLoadersTest {
     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 class RoutesLoadersTest {
     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 class RoutesLoadersTest {
     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 class RoutesLoadersTest {
     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 e434c26..533c353 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 @@ public class RuntimeTest {
 
     @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 d72bb60..efd01ee 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 be4dced..8b09000 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 a6fbb5a..91839aa 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.builder.RouteBuilder;
 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 @@ public class Application {
         // 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 class Application {
     @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 0000000..0e94a55
--- /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 0000000..d5b5a37
--- /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 0000000..6ad07ee
--- /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 0000000..89031dd
--- /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 0000000..f2e8a2e
--- /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 0000000..8a26030
--- /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 0000000..25b80b5
--- /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 0000000..242f874
--- /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 0000000..6af1c19
--- /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 0000000..1035306
--- /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 0000000..a505fd9
--- /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 0000000..1964535
--- /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 014e40b..29a6846 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>