diff --git a/cmd/document/document.go b/cmd/document/document.go
index b355dd205..49132548a 100644
--- a/cmd/document/document.go
+++ b/cmd/document/document.go
@@ -35,7 +35,6 @@ func NewDocumentCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Com
 	}
 
 	documentRootCmd.AddCommand(NewPullCommand(rootSettings))
-	documentRootCmd.AddCommand(NewRenderCommand(rootSettings))
 	documentRootCmd.AddCommand(NewPluginCommand(rootSettings))
 
 	return documentRootCmd
diff --git a/cmd/document/document_test.go b/cmd/document/document_test.go
index da61bf386..1642cc8a9 100644
--- a/cmd/document/document_test.go
+++ b/cmd/document/document_test.go
@@ -28,11 +28,6 @@ func TestDocument(t *testing.T) {
 			CmdLine: "-h",
 			Cmd:     document.NewDocumentCommand(nil),
 		},
-		{
-			Name:    "document-render-with-help",
-			CmdLine: "-h",
-			Cmd:     document.NewRenderCommand(nil),
-		},
 		{
 			Name:    "document-plugin-with-help",
 			CmdLine: "-h",
diff --git a/cmd/document/testdata/TestDocumentGoldenOutput/document-render-with-help.golden b/cmd/document/testdata/TestDocumentGoldenOutput/document-render-with-help.golden
deleted file mode 100644
index aea59a5b8..000000000
--- a/cmd/document/testdata/TestDocumentGoldenOutput/document-render-with-help.golden
+++ /dev/null
@@ -1,12 +0,0 @@
-Render documents from model
-
-Usage:
-  render [flags]
-
-Flags:
-  -a, --annotation stringArray   filter documents by Annotations
-  -g, --apiversion stringArray   filter documents by API version
-  -f, --filter string            logical expression for document filtering
-  -h, --help                     help for render
-  -k, --kind stringArray         filter documents by Kinds
-  -l, --label stringArray        filter documents by Labels
diff --git a/cmd/document/testdata/TestDocumentGoldenOutput/document-with-help.golden b/cmd/document/testdata/TestDocumentGoldenOutput/document-with-help.golden
index a0b6c4a38..7781f2416 100644
--- a/cmd/document/testdata/TestDocumentGoldenOutput/document-with-help.golden
+++ b/cmd/document/testdata/TestDocumentGoldenOutput/document-with-help.golden
@@ -7,7 +7,6 @@ Available Commands:
   help        Help about any command
   plugin      Run as a kustomize exec plugin
   pull        Pulls documents from remote git repository
-  render      Render documents from model
 
 Flags:
   -h, --help   help for document
diff --git a/cmd/phase/phase.go b/cmd/phase/phase.go
index 8d7673528..c04627e1d 100644
--- a/cmd/phase/phase.go
+++ b/cmd/phase/phase.go
@@ -44,6 +44,7 @@ func NewPhaseCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Comman
 	}
 
 	phaseRootCmd.AddCommand(NewApplyCommand(rootSettings, client.DefaultClient))
+	phaseRootCmd.AddCommand(NewRenderCommand(rootSettings))
 
 	return phaseRootCmd
 }
diff --git a/cmd/document/render.go b/cmd/phase/render.go
similarity index 64%
rename from cmd/document/render.go
rename to cmd/phase/render.go
index 7db291e65..edc8eeccd 100644
--- a/cmd/document/render.go
+++ b/cmd/phase/render.go
@@ -12,24 +12,41 @@
  limitations under the License.
 */
 
-package document
+package phase
 
 import (
 	"github.com/spf13/cobra"
 
-	"opendev.org/airship/airshipctl/pkg/document/render"
 	"opendev.org/airship/airshipctl/pkg/environment"
-	"opendev.org/airship/airshipctl/pkg/errors"
+	"opendev.org/airship/airshipctl/pkg/phase/render"
+)
+
+const (
+	renderExample = `
+# Get all 'initinfra' phase documents containing labels "app=helm" and
+# "service=tiller"
+airshipctl phase render initinfra -l app=helm,service=tiller
+
+# Get all documents containing labels "app=helm" and "service=tiller"
+# and kind 'Deployment'
+airshipctl phase render initinfra -l app=helm,service=tiller -k Deployment
+`
 )
 
 // NewRenderCommand create a new command for document rendering
 func NewRenderCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command {
 	renderSettings := &render.Settings{AirshipCTLSettings: rootSettings}
 	renderCmd := &cobra.Command{
-		Use:   "render",
-		Short: "Render documents from model",
+		Use:     "render PHASE_NAME",
+		Short:   "Render phase documents from model",
+		Example: renderExample,
+		Args:    cobra.ExactArgs(1),
 		RunE: func(cmd *cobra.Command, args []string) error {
-			return errors.ErrNotImplemented{}
+			path, err := renderSettings.Config.CurrentContextEntryPoint(args[0])
+			if err != nil {
+				return err
+			}
+			return renderSettings.Render(path, cmd.OutOrStdout())
 		},
 	}
 
@@ -41,38 +58,31 @@ func NewRenderCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Comma
 func addRenderFlags(settings *render.Settings, cmd *cobra.Command) {
 	flags := cmd.Flags()
 
-	flags.StringArrayVarP(
+	flags.StringVarP(
 		&settings.Label,
 		"label",
 		"l",
-		nil,
+		"",
 		"filter documents by Labels")
 
-	flags.StringArrayVarP(
+	flags.StringVarP(
 		&settings.Annotation,
 		"annotation",
 		"a",
-		nil,
+		"",
 		"filter documents by Annotations")
 
-	flags.StringArrayVarP(
-		&settings.GroupVersion,
+	flags.StringVarP(
+		&settings.APIVersion,
 		"apiversion",
 		"g",
-		nil,
+		"",
 		"filter documents by API version")
 
-	flags.StringArrayVarP(
+	flags.StringVarP(
 		&settings.Kind,
 		"kind",
 		"k",
-		nil,
-		"filter documents by Kinds")
-
-	flags.StringVarP(
-		&settings.RawFilter,
-		"filter",
-		"f",
 		"",
-		"logical expression for document filtering")
+		"filter documents by Kinds")
 }
diff --git a/cmd/phase/render_test.go b/cmd/phase/render_test.go
new file mode 100644
index 000000000..90b4efdf3
--- /dev/null
+++ b/cmd/phase/render_test.go
@@ -0,0 +1,61 @@
+/*
+ Licensed 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
+
+     https://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 phase_test
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/require"
+
+	"opendev.org/airship/airshipctl/cmd/phase"
+	"opendev.org/airship/airshipctl/pkg/config"
+	"opendev.org/airship/airshipctl/pkg/environment"
+	"opendev.org/airship/airshipctl/testutil"
+)
+
+func TestRender(t *testing.T) {
+	cfg, cleanupCfg := testutil.InitConfig(t)
+	defer cleanupCfg(t)
+	cfg.CurrentContext = "def_ephemeral"
+	cfg.Manifests["test"] = &config.Manifest{
+		TargetPath:            "testdata",
+		PrimaryRepositoryName: "testRepo",
+		Repositories: map[string]*config.Repository{
+			"testRepo": {
+				URLString: "http://localhost",
+			},
+		},
+	}
+	ctx, err := cfg.GetContext("def_ephemeral")
+	require.NoError(t, err)
+	ctx.Manifest = "test"
+	settings := &environment.AirshipCTLSettings{Config: cfg}
+
+	tests := []*testutil.CmdTest{
+		{
+			Name:    "render-with-help",
+			CmdLine: "-h",
+			Cmd:     phase.NewRenderCommand(nil),
+		},
+		{
+			Name:    "render-with-multiple-labels",
+			CmdLine: "initinfra -l app=helm,name=tiller",
+			Cmd:     phase.NewRenderCommand(settings),
+		},
+	}
+	for _, tt := range tests {
+		testutil.RunTest(t, tt)
+	}
+}
diff --git a/cmd/phase/testdata/TestNewPhaseCommandGoldenOutput/phase-cmd-with-help.golden b/cmd/phase/testdata/TestNewPhaseCommandGoldenOutput/phase-cmd-with-help.golden
index 3e4275035..a5c86e471 100644
--- a/cmd/phase/testdata/TestNewPhaseCommandGoldenOutput/phase-cmd-with-help.golden
+++ b/cmd/phase/testdata/TestNewPhaseCommandGoldenOutput/phase-cmd-with-help.golden
@@ -7,6 +7,7 @@ Usage:
 Available Commands:
   apply       Apply phase to a cluster
   help        Help about any command
+  render      Render phase documents from model
 
 Flags:
   -h, --help   help for phase
diff --git a/cmd/phase/testdata/TestRenderGoldenOutput/render-with-help.golden b/cmd/phase/testdata/TestRenderGoldenOutput/render-with-help.golden
new file mode 100644
index 000000000..de23dc9a4
--- /dev/null
+++ b/cmd/phase/testdata/TestRenderGoldenOutput/render-with-help.golden
@@ -0,0 +1,22 @@
+Render phase documents from model
+
+Usage:
+  render PHASE_NAME [flags]
+
+Examples:
+
+# Get all 'initinfra' phase documents containing labels "app=helm" and
+# "service=tiller"
+airshipctl phase render initinfra -l app=helm,service=tiller
+
+# Get all documents containing labels "app=helm" and "service=tiller"
+# and kind 'Deployment'
+airshipctl phase render initinfra -l app=helm,service=tiller -k Deployment
+
+
+Flags:
+  -a, --annotation string   filter documents by Annotations
+  -g, --apiversion string   filter documents by API version
+  -h, --help                help for render
+  -k, --kind string         filter documents by Kinds
+  -l, --label string        filter documents by Labels
diff --git a/cmd/phase/testdata/TestRenderGoldenOutput/render-with-multiple-labels.golden b/cmd/phase/testdata/TestRenderGoldenOutput/render-with-multiple-labels.golden
new file mode 100644
index 000000000..9f0539f47
--- /dev/null
+++ b/cmd/phase/testdata/TestRenderGoldenOutput/render-with-multiple-labels.golden
@@ -0,0 +1,52 @@
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  annotations:
+    airshipit.org/clustertype: ephemeral
+  creationTimestamp: null
+  labels:
+    app: helm
+    name: tiller
+  name: tiller-deploy
+  namespace: kube-system
+spec:
+  replicas: 1
+  strategy: {}
+  template:
+    metadata:
+      creationTimestamp: null
+      labels:
+        app: helm
+        name: tiller
+    spec:
+      automountServiceAccountToken: true
+      containers:
+      - env:
+        - name: TILLER_NAMESPACE
+          value: kube-system
+        - name: TILLER_HISTORY_MAX
+          value: "0"
+        image: gcr.io/kubernetes-helm/tiller:v2.12.3
+        imagePullPolicy: IfNotPresent
+        livenessProbe:
+          httpGet:
+            path: /liveness
+            port: 44135
+          initialDelaySeconds: 1
+          timeoutSeconds: 1
+        name: tiller
+        ports:
+        - containerPort: 44134
+          name: tiller
+        - containerPort: 44135
+          name: http
+        readinessProbe:
+          httpGet:
+            path: /readiness
+            port: 44135
+          initialDelaySeconds: 1
+          timeoutSeconds: 1
+        resources: {}
+status: {}
+...
diff --git a/cmd/phase/testdata/ephemeral/initinfra/kustomization.yaml b/cmd/phase/testdata/ephemeral/initinfra/kustomization.yaml
new file mode 100644
index 000000000..c1f4d1b64
--- /dev/null
+++ b/cmd/phase/testdata/ephemeral/initinfra/kustomization.yaml
@@ -0,0 +1,2 @@
+resources:
+ - tiller.yaml
\ No newline at end of file
diff --git a/cmd/phase/testdata/ephemeral/initinfra/tiller.yaml b/cmd/phase/testdata/ephemeral/initinfra/tiller.yaml
new file mode 100644
index 000000000..cdd081e39
--- /dev/null
+++ b/cmd/phase/testdata/ephemeral/initinfra/tiller.yaml
@@ -0,0 +1,74 @@
+---
+apiVersion: extensions/v1beta1
+kind: Deployment
+metadata:
+  annotations:
+    airshipit.org/clustertype: ephemeral
+  creationTimestamp: null
+  labels:
+    app: helm
+    name: tiller
+  name: tiller-deploy
+  namespace: kube-system
+spec:
+  replicas: 1
+  strategy: {}
+  template:
+    metadata:
+      creationTimestamp: null
+      labels:
+        app: helm
+        name: tiller
+    spec:
+      automountServiceAccountToken: true
+      containers:
+      - env:
+        - name: TILLER_NAMESPACE
+          value: kube-system
+        - name: TILLER_HISTORY_MAX
+          value: "0"
+        image: gcr.io/kubernetes-helm/tiller:v2.12.3
+        imagePullPolicy: IfNotPresent
+        livenessProbe:
+          httpGet:
+            path: /liveness
+            port: 44135
+          initialDelaySeconds: 1
+          timeoutSeconds: 1
+        name: tiller
+        ports:
+        - containerPort: 44134
+          name: tiller
+        - containerPort: 44135
+          name: http
+        readinessProbe:
+          httpGet:
+            path: /readiness
+            port: 44135
+          initialDelaySeconds: 1
+          timeoutSeconds: 1
+        resources: {}
+status: {}
+---
+apiVersion: v1
+kind: Service
+metadata:
+  annotations:
+    airshipit.org/clustertype: ephemeral
+  creationTimestamp: null
+  labels:
+    app: helm
+  name: tiller-deploy
+  namespace: kube-system
+spec:
+  ports:
+  - name: tiller
+    port: 44134
+    targetPort: tiller
+  selector:
+    app: helm
+    name: tiller
+  type: ClusterIP
+status:
+  loadBalancer: {}
+...
\ No newline at end of file
diff --git a/docs/source/cli/airshipctl_cluster.md b/docs/source/cli/airshipctl_cluster.md
index 68e30a648..7aaee8c75 100644
--- a/docs/source/cli/airshipctl_cluster.md
+++ b/docs/source/cli/airshipctl_cluster.md
@@ -26,5 +26,4 @@ such as getting status and deploying initial infrastructure.
 
 * [airshipctl](airshipctl.md)	 - A unified entrypoint to various airship components
 * [airshipctl cluster init](airshipctl_cluster_init.md)	 - Deploy cluster-api provider components
-* [airshipctl cluster initinfra](airshipctl_cluster_initinfra.md)	 - Deploy initinfra components to cluster
 
diff --git a/docs/source/cli/airshipctl_document.md b/docs/source/cli/airshipctl_document.md
index 9b0e20fc6..efdbf2efc 100644
--- a/docs/source/cli/airshipctl_document.md
+++ b/docs/source/cli/airshipctl_document.md
@@ -25,5 +25,4 @@ Manage deployment documents
 * [airshipctl](airshipctl.md)	 - A unified entrypoint to various airship components
 * [airshipctl document plugin](airshipctl_document_plugin.md)	 - Run as a kustomize exec plugin
 * [airshipctl document pull](airshipctl_document_pull.md)	 - Pulls documents from remote git repository
-* [airshipctl document render](airshipctl_document_render.md)	 - Render documents from model
 
diff --git a/docs/source/cli/airshipctl_phase.md b/docs/source/cli/airshipctl_phase.md
index 263ce9e88..593dea90d 100644
--- a/docs/source/cli/airshipctl_phase.md
+++ b/docs/source/cli/airshipctl_phase.md
@@ -26,4 +26,5 @@ such as getting list and applying specific one.
 
 * [airshipctl](airshipctl.md)	 - A unified entrypoint to various airship components
 * [airshipctl phase apply](airshipctl_phase_apply.md)	 - Apply phase to a cluster
+* [airshipctl phase render](airshipctl_phase_render.md)	 - Render phase documents from model
 
diff --git a/docs/source/cli/airshipctl_phase_render.md b/docs/source/cli/airshipctl_phase_render.md
new file mode 100644
index 000000000..17463b4f0
--- /dev/null
+++ b/docs/source/cli/airshipctl_phase_render.md
@@ -0,0 +1,48 @@
+## airshipctl phase render
+
+Render phase documents from model
+
+### Synopsis
+
+Render phase documents from model
+
+```
+airshipctl phase render PHASE_NAME [flags]
+```
+
+### Examples
+
+```
+
+#Get all 'initinfra' phase documents containing labels "app=helm" and
+#"service=tiller"
+airshipctl phase render initinfra -l app=helm,service=tiller
+
+#Get all documents containing labels "app=helm" and "service=tiller"
+#and kind 'Deployment'
+airshipctl phase render initinfra -l app=helm,service=tiller -k Deployment
+
+```
+
+### Options
+
+```
+  -a, --annotation string   filter documents by Annotations
+  -g, --apiversion string   filter documents by API version
+  -h, --help                help for render
+  -k, --kind string         filter documents by Kinds
+  -l, --label string        filter documents by Labels
+```
+
+### Options inherited from parent commands
+
+```
+      --airshipconf string   Path to file for airshipctl configuration. (default "$HOME/.airship/config")
+      --debug                enable verbose output
+      --kubeconfig string    Path to kubeconfig associated with airshipctl configuration. (default "$HOME/.airship/kubeconfig")
+```
+
+### SEE ALSO
+
+* [airshipctl phase](airshipctl_phase.md)	 - Manage phases
+
diff --git a/pkg/phase/render/render.go b/pkg/phase/render/render.go
new file mode 100644
index 000000000..7e698c40f
--- /dev/null
+++ b/pkg/phase/render/render.go
@@ -0,0 +1,49 @@
+/*
+ Licensed 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
+
+     https://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 render
+
+import (
+	"io"
+	"strings"
+
+	"opendev.org/airship/airshipctl/pkg/document"
+)
+
+// Render prints out filtered documents
+func (s *Settings) Render(path string, out io.Writer) error {
+	if err := s.Config.EnsureComplete(); err != nil {
+		return err
+	}
+	docBundle, err := document.NewBundleByPath(path)
+	if err != nil {
+		return err
+	}
+
+	groupVersion := strings.Split(s.APIVersion, "/")
+	group := ""
+	version := groupVersion[0]
+	if len(groupVersion) > 1 {
+		group = groupVersion[0]
+		version = strings.Join(groupVersion[1:], "/")
+	}
+
+	sel := document.NewSelector().ByLabel(s.Label).ByAnnotation(s.Annotation).ByGvk(group, version, s.Kind)
+	filteredBundle, err := docBundle.SelectBundle(sel)
+	if err != nil {
+		return err
+	}
+
+	return filteredBundle.Write(out)
+}
diff --git a/pkg/phase/render/render_test.go b/pkg/phase/render/render_test.go
new file mode 100644
index 000000000..365b4f00c
--- /dev/null
+++ b/pkg/phase/render/render_test.go
@@ -0,0 +1,94 @@
+/*
+ Licensed 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
+
+     https://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 render_test
+
+import (
+	"bytes"
+	"fmt"
+	"io/ioutil"
+	"path"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+	"github.com/stretchr/testify/require"
+
+	"opendev.org/airship/airshipctl/pkg/environment"
+	"opendev.org/airship/airshipctl/pkg/phase/render"
+	"opendev.org/airship/airshipctl/testutil"
+)
+
+func TestRender(t *testing.T) {
+	rs := &environment.AirshipCTLSettings{Config: testutil.DummyConfig()}
+	fixturePath := "testdata/phase"
+	tests := []struct {
+		name       string
+		settings   *render.Settings
+		expResFile string
+		expErr     error
+	}{
+		{
+			name:       "No Filters",
+			settings:   &render.Settings{AirshipCTLSettings: rs},
+			expResFile: "noFilter.yaml",
+			expErr:     nil,
+		},
+		{
+			name: "All Filters",
+			settings: &render.Settings{
+				AirshipCTLSettings: rs,
+				Label:              "airshipit.org/deploy-k8s=false",
+				Annotation:         "airshipit.org/clustertype=ephemeral",
+				APIVersion:         "metal3.io/v1alpha1",
+				Kind:               "BareMetalHost",
+			},
+			expResFile: "allFilters.yaml",
+			expErr:     nil,
+		},
+		{
+			name: "Multiple Labels",
+			settings: &render.Settings{
+				AirshipCTLSettings: rs,
+				Label:              "airshipit.org/deploy-k8s=false, airshipit.org/ephemeral-node=true",
+			},
+			expResFile: "multiLabels.yaml",
+			expErr:     nil,
+		},
+		{
+			name: "Malformed Label",
+			settings: &render.Settings{
+				AirshipCTLSettings: rs,
+				Label:              "app=(",
+			},
+			expResFile: "",
+			expErr:     fmt.Errorf("unable to parse requirement: found '(', expected: identifier"),
+		},
+	}
+
+	for _, tt := range tests {
+		tt := tt
+		t.Run(tt.name, func(t *testing.T) {
+			var expectedOut []byte
+			var err error
+			if tt.expResFile != "" {
+				expectedOut, err = ioutil.ReadFile(path.Join("testdata", "expected", tt.expResFile))
+				require.NoError(t, err)
+			}
+			out := &bytes.Buffer{}
+			err = tt.settings.Render(fixturePath, out)
+			assert.Equal(t, tt.expErr, err)
+			assert.Equal(t, expectedOut, out.Bytes())
+		})
+	}
+}
diff --git a/pkg/phase/render/testdata/expected/allFilters.yaml b/pkg/phase/render/testdata/expected/allFilters.yaml
new file mode 100644
index 000000000..4ada4c244
--- /dev/null
+++ b/pkg/phase/render/testdata/expected/allFilters.yaml
@@ -0,0 +1,23 @@
+---
+apiVersion: metal3.io/v1alpha1
+kind: BareMetalHost
+metadata:
+  annotations:
+    airshipit.org/clustertype: ephemeral
+  labels:
+    airshipit.org/deploy-k8s: "false"
+    airshipit.org/ephemeral-node: "true"
+  name: node02
+spec:
+  bmc:
+    address: redfish+https://localhost:8443/redfish/v1/Systems/air-ephemeral
+    credentialsName: node02-bmc-secret
+  bootMACAddress: 00:3b:8b:0c:ec:8b
+  networkData:
+    name: node02-network-data
+    namespace: default
+  online: true
+status:
+  provisioning:
+    state: externally provisioned
+...
diff --git a/pkg/phase/render/testdata/expected/multiLabels.yaml b/pkg/phase/render/testdata/expected/multiLabels.yaml
new file mode 100644
index 000000000..4ada4c244
--- /dev/null
+++ b/pkg/phase/render/testdata/expected/multiLabels.yaml
@@ -0,0 +1,23 @@
+---
+apiVersion: metal3.io/v1alpha1
+kind: BareMetalHost
+metadata:
+  annotations:
+    airshipit.org/clustertype: ephemeral
+  labels:
+    airshipit.org/deploy-k8s: "false"
+    airshipit.org/ephemeral-node: "true"
+  name: node02
+spec:
+  bmc:
+    address: redfish+https://localhost:8443/redfish/v1/Systems/air-ephemeral
+    credentialsName: node02-bmc-secret
+  bootMACAddress: 00:3b:8b:0c:ec:8b
+  networkData:
+    name: node02-network-data
+    namespace: default
+  online: true
+status:
+  provisioning:
+    state: externally provisioned
+...
diff --git a/pkg/phase/render/testdata/expected/noFilter.yaml b/pkg/phase/render/testdata/expected/noFilter.yaml
new file mode 100644
index 000000000..0cf846316
--- /dev/null
+++ b/pkg/phase/render/testdata/expected/noFilter.yaml
@@ -0,0 +1,42 @@
+---
+apiVersion: v1
+data:
+  password: cGFzc3dvcmQ=
+  username: dXNlcm5hbWU=
+kind: Secret
+metadata:
+  name: node02-bmc-secret
+type: Opaque
+...
+---
+apiVersion: v1
+kind: Secret
+metadata:
+  name: node02-network-data
+stringData:
+  networkData: someData
+type: Opaque
+...
+---
+apiVersion: metal3.io/v1alpha1
+kind: BareMetalHost
+metadata:
+  annotations:
+    airshipit.org/clustertype: ephemeral
+  labels:
+    airshipit.org/deploy-k8s: "false"
+    airshipit.org/ephemeral-node: "true"
+  name: node02
+spec:
+  bmc:
+    address: redfish+https://localhost:8443/redfish/v1/Systems/air-ephemeral
+    credentialsName: node02-bmc-secret
+  bootMACAddress: 00:3b:8b:0c:ec:8b
+  networkData:
+    name: node02-network-data
+    namespace: default
+  online: true
+status:
+  provisioning:
+    state: externally provisioned
+...
diff --git a/pkg/phase/render/testdata/expected/rawFilter.yaml b/pkg/phase/render/testdata/expected/rawFilter.yaml
new file mode 100644
index 000000000..5f11c2a1d
--- /dev/null
+++ b/pkg/phase/render/testdata/expected/rawFilter.yaml
@@ -0,0 +1,14 @@
+---
+apiVersion: metal3.io/v1alpha1
+kind: BareMetalHost
+metadata:
+  annotations:
+    airshipit.org/clustertype: target
+  name: master-1
+spec:
+  bmc:
+    address: ipmi://192.168.111.2:6230
+    credentialsName: master-1-bmc-secret
+  bootMACAddress: 01:3b:8b:0c:ec:8b
+  online: true
+...
diff --git a/pkg/phase/render/testdata/phase/baremetal.yaml b/pkg/phase/render/testdata/phase/baremetal.yaml
new file mode 100644
index 000000000..06b00f260
--- /dev/null
+++ b/pkg/phase/render/testdata/phase/baremetal.yaml
@@ -0,0 +1,38 @@
+apiVersion: v1
+data:
+  password: cGFzc3dvcmQ=
+  username: dXNlcm5hbWU=
+kind: Secret
+metadata:
+  name: node02-bmc-secret
+type: Opaque
+---
+apiVersion: v1
+stringData:
+  networkData: someData
+kind: Secret
+metadata:
+  name: node02-network-data
+type: Opaque
+---
+apiVersion: metal3.io/v1alpha1
+kind: BareMetalHost
+metadata:
+  labels:
+    airshipit.org/deploy-k8s: "false"
+    airshipit.org/ephemeral-node: "true"
+  annotations:
+    airshipit.org/clustertype: ephemeral
+  name: node02
+spec:
+  bmc:
+    address: redfish+https://localhost:8443/redfish/v1/Systems/air-ephemeral
+    credentialsName: node02-bmc-secret
+  bootMACAddress: 00:3b:8b:0c:ec:8b
+  networkData:
+    name: node02-network-data
+    namespace: default
+  online: true
+status:
+  provisioning:
+    state: externally provisioned
\ No newline at end of file
diff --git a/pkg/phase/render/testdata/phase/kustomization.yaml b/pkg/phase/render/testdata/phase/kustomization.yaml
new file mode 100644
index 000000000..66a539cb4
--- /dev/null
+++ b/pkg/phase/render/testdata/phase/kustomization.yaml
@@ -0,0 +1,2 @@
+resources:
+  - baremetal.yaml
\ No newline at end of file
diff --git a/pkg/document/render/type.go b/pkg/phase/render/type.go
similarity index 67%
rename from pkg/document/render/type.go
rename to pkg/phase/render/type.go
index c88c83764..f978a2570 100644
--- a/pkg/document/render/type.go
+++ b/pkg/phase/render/type.go
@@ -21,14 +21,12 @@ import (
 // Settings for document rendering
 type Settings struct {
 	*environment.AirshipCTLSettings
-	// Label filter documents by label string
-	Label []string
-	// Annotation filter documents by annotation string
-	Annotation []string
-	// GroupVersion filter documents by API version
-	GroupVersion []string
-	// Kind filter documents by document kind
-	Kind []string
-	// RawFilter contains logical expression to filter documents
-	RawFilter string
+	// Label filters documents by label string
+	Label string
+	// Annotation filters documents by annotation string
+	Annotation string
+	// APIVersion filters documents by API group and version
+	APIVersion string
+	// Kind filters documents by document kind
+	Kind string
 }