Repository: redhat-developer/service-binding-operator
Pull request #180 (2019-09-20 19:15:11)

Initial draft of operators' best practices guide
This doc is WIP until doc review/feedback and dependent stories are completed:
* https://jira.coreos.com/browse/APPSVC-157




openshift-ci-robot: [APPROVALNOTIFIER] This PR is **NOT APPROVED**

This pull-request has been approved by:
To complete the [pull request process](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process), please assign **otaviof**
You can assign the PR to them by writing `/assign @otaviof` in a comment when ready.

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=redhat-developer%2Fservice-binding-operator).

<details open>
Needs approval from an approver in each of these files:

- **[OWNERS](https://github.com/redhat-developer/service-binding-operator/blob/master/OWNERS)**

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":["otaviof"]} -->
codecov[bot]: # [Codecov](https://codecov.io/gh/redhat-developer/service-binding-operator/pull/180?src=pr&el=h1) Report
> :exclamation: No coverage uploaded for pull request base (`master@24863e3`). [Click here to learn what that means](https://docs.codecov.io/docs/error-reference#section-missing-base-commit).
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/redhat-developer/service-binding-operator/pull/180/graphs/tree.svg?width=650&token=CICBeVWlrC&height=150&src=pr)](https://codecov.io/gh/redhat-developer/service-binding-operator/pull/180?src=pr&el=tree)

```diff
@@            Coverage Diff            @@
##             master     #180   +/-   ##
=========================================
  Coverage          ?   63.22%           
=========================================
  Files             ?       13           
  Lines             ?      862           
  Branches          ?        0           
=========================================
  Hits              ?      545           
  Misses            ?      241           
  Partials          ?       76
```



------

[Continue to review full report at Codecov](https://codecov.io/gh/redhat-developer/service-binding-operator/pull/180?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/redhat-developer/service-binding-operator/pull/180?src=pr&el=footer). Last update [24863e3...2cd1db1](https://codecov.io/gh/redhat-developer/service-binding-operator/pull/180?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

baijum: @ldimaggi For docs, I would suggest using 80 characters per line. Ref: https://github.com/openshift/openshift-docs/blob/master/contributing_to_docs/doc_guidelines.adoc#general-file-guidelines
sbose78: @baijum 

As soon as you've validated your approach code-wise ( in an incomplete PR/branch ) - I would be eagerly waiting for a 🍏 green signal in the next couple of days :)

Please share an update here so that we can do the following dependent tasks:

- update the Best Practices guide.
- update our sample operators to have annotations instead of descriptors. (we may keep both)
- update our blog post draft to not talk about OLM descriptors anymore.
sbose78: @ldimaggi https://jira.coreos.com/browse/APPSVC-115 shouldn't be a dependency.
ldimaggi: > @ldimaggi For docs, I would suggest using 80 characters per line. Ref: https://github.com/openshift/openshift-docs/blob/master/contributing_to_docs/doc_guidelines.adoc#general-file-guidelines

Thanks Baiju!
ldimaggi: > You might want to also show off the reference operators as part of the Best Practices. Can we have a step by step flow described.
> 
> "Here are the 3 things you need to do.."

Add references to the reference operators and the usage scenario examples - please review - thx!


ldimaggi: @sbose78 Do we want to remove, or mark as deprecated, the OLM descriptor based binding approach? Please have a look at the updated doc - thx!


Patch:
diff --git a/.codecov.yaml b/.codecov.yaml
index 2bc6db67..52cf2fe1 100644
--- a/.codecov.yaml
+++ b/.codecov.yaml
@@ -31,7 +31,8 @@ coverage:
 # See http://docs.codecov.io/docs/pull-request-comments-1
 comment:
   layout: "diff, files"
-  behavior: # default = posts once then update, posts new if delete
+  behavior: ""
+            # default = posts once then update, posts new if delete
             # once = post once then updates
             # new = delete old, post new
             # spammy = post new
diff --git a/.gitignore b/.gitignore
index f17f8b5d..68b88de5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -88,3 +88,5 @@ tags
 # End of https://www.gitignore.io/api/go,vim,emacs,visualstudiocode
 ### Intellij
 .idea
+### Logs
+**/*.log
diff --git a/Dockerfile.rhel b/Dockerfile.rhel
index 94d4406d..3e6cdedf 100644
--- a/Dockerfile.rhel
+++ b/Dockerfile.rhel
@@ -1,16 +1,32 @@
 # On CI, use
-# FROM registry.svc.ci.openshift.org/ocp/builder:golang-1.12 AS builder
+# FROM registry.svc.ci.openshift.org/ocp/builder:golang-1.13 AS builder
 
-FROM openshift/origin-release:golang-1.12 AS builder
+FROM openshift/origin-release:golang-1.13 AS builder
 
 ENV LANG=en_US.utf8
 ENV GIT_COMMITTER_NAME devtools
 ENV GIT_COMMITTER_EMAIL devtools@redhat.com
+LABEL com.redhat.delivery.appregistry=true
 
 WORKDIR /go/src/github.com/redhat-developer/service-binding-operator
 
-COPY . .
-
+# Copy only relevant things (instead of all) to speed-up the build.
+COPY assets assets
+COPY build build
+COPY cmd cmd
+COPY deploy deploy
+COPY hack hack
+COPY manifests manifests
+COPY pkg pkg
+COPY test test
+COPY vendor vendor
+COPY go.mod .
+COPY go.sum .
+COPY LICENSE .
+COPY Makefile .
+COPY tools.go .
+
+ARG VERBOSE=2
 RUN make build
 
 #--------------------------------------------------------------------
diff --git a/Makefile b/Makefile
index fe4ef026..d962ac5d 100644
--- a/Makefile
+++ b/Makefile
@@ -125,8 +125,11 @@ QUAY_TOKEN ?= ""
 
 MANIFESTS_DIR ?= ./manifests
 MANIFESTS_TMP ?= ./tmp/manifests
+HACK_DIR ?= ./hack
+OUTPUT_DIR ?= ./out
+LOGS_DIR ?= $(OUTPUT_DIR)/logs
 
-GOLANGCI_LINT_BIN=./out/golangci-lint
+GOLANGCI_LINT_BIN=$(OUTPUT_DIR)/golangci-lint
 
 # -- Variables for uploading code coverage reports to Codecov.io --
 # This default path is set by the OpenShift CI
@@ -148,15 +151,15 @@ YAML_FILES := $(shell find . -path ./vendor -prune -o -type f -regex ".*y[a]ml"
 .PHONY: lint-yaml
 ## runs yamllint on all yaml files
 lint-yaml: ${YAML_FILES}
-	$(Q)./out/venv3/bin/pip install yamllint
-	$(Q)./out/venv3/bin/yamllint -c .yamllint $(YAML_FILES)
+	$(Q)$(OUTPUT_DIR)/venv3/bin/pip install yamllint
+	$(Q)$(OUTPUT_DIR)/venv3/bin/yamllint -c .yamllint $(YAML_FILES)
 
 .PHONY: lint-go-code
 ## Checks the code with golangci-lint
 lint-go-code: $(GOLANGCI_LINT_BIN)
 	# This is required for OpenShift CI enviroment
 	# Ref: https://github.com/openshift/release/pull/3438#issuecomment-482053250
-	$(Q)GOCACHE=$(GOCACHE) ./out/golangci-lint ${V_FLAG} run --deadline=30m
+	$(Q)GOCACHE=$(GOCACHE) $(OUTPUT_DIR)/golangci-lint ${V_FLAG} run --deadline=30m
 
 $(GOLANGCI_LINT_BIN):
 	$(Q)curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b ./out v1.18.0
@@ -164,32 +167,33 @@ $(GOLANGCI_LINT_BIN):
 .PHONY: courier
 ## Validate manifests using operator-courier
 courier:
-	$(Q)./out/venv3/bin/pip install operator-courier
-	$(Q)./out/venv3/bin/operator-courier flatten ./manifests ./out/manifests
-	$(Q)./out/venv3/bin/operator-courier verify ./out/manifests
+	$(Q)$(OUTPUT_DIR)/venv3/bin/pip install operator-courier
+	$(Q)$(OUTPUT_DIR)/venv3/bin/operator-courier flatten ./manifests $(OUTPUT_DIR)/manifests
+	$(Q)$(OUTPUT_DIR)/venv3/bin/operator-courier verify $(OUTPUT_DIR)/manifests
 
 .PHONY: setup-venv
 ## Setup virtual environment
 setup-venv:
-	$(Q)python3 -m venv ./out/venv3
-	$(Q)./out/venv3/bin/pip install --upgrade setuptools
-	$(Q)./out/venv3/bin/pip install --upgrade pip
+	$(Q)python3 -m venv $(OUTPUT_DIR)/venv3
+	$(Q)$(OUTPUT_DIR)/venv3/bin/pip install --upgrade setuptools
+	$(Q)$(OUTPUT_DIR)/venv3/bin/pip install --upgrade pip
 
 ## -- Test targets --
 
 # Generate namespace name for test
 out/test-namespace:
-	@echo -n "test-namespace-$(shell uuidgen | tr '[:upper:]' '[:lower:]')" > ./out/test-namespace
+	@echo -n "test-namespace-$(shell uuidgen | tr '[:upper:]' '[:lower:]')" > $(OUTPUT_DIR)/test-namespace
 
 .PHONY: get-test-namespace
 get-test-namespace: out/test-namespace
-	$(eval TEST_NAMESPACE := $(shell cat ./out/test-namespace))
+	$(eval TEST_NAMESPACE := $(shell cat $(OUTPUT_DIR)/test-namespace))
 
 # E2E test
 .PHONY: e2e-setup
 e2e-setup: e2e-cleanup
 	$(Q)kubectl create namespace $(TEST_NAMESPACE)
 	$(Q)kubectl --namespace $(TEST_NAMESPACE) apply -f ./test/third-party-crds/postgresql_v1alpha1_database_crd.yaml
+	$(Q)mkdir -p $(LOGS_DIR)/e2e
 
 .PHONY: e2e-cleanup
 e2e-cleanup: get-test-namespace
@@ -205,7 +209,10 @@ test-e2e: e2e-setup
 			--up-local \
 			--go-test-flags "-timeout=15m" \
 			--local-operator-flags "$(ZAP_FLAGS)" \
-			$(OPERATOR_SDK_EXTRA_ARGS)
+			$(OPERATOR_SDK_EXTRA_ARGS) \
+			| tee $(LOGS_DIR)/e2e/test-e2e.log
+	#Extract the local operator log and replace the escape sequences by the actual whitespaces
+	$(Q)$(HACK_DIR)/e2e-log-parser.sh $(LOGS_DIR)/e2e/test-e2e.log > $(LOGS_DIR)/e2e/local-operator.log
 
 .PHONY: test-unit
 ## Runs the unit tests without code coverage
@@ -214,6 +221,22 @@ test-unit:
 	$(Q)GO111MODULE=$(GO111MODULE) GOCACHE=$(GOCACHE) \
 		go test $(shell GOCACHE="$(GOCACHE)" go list ./...|grep -v e2e) -v -mod vendor $(TEST_EXTRA_ARGS)
 
+.PHONY: test-e2e-image
+## Run e2e tests on operator image
+test-e2e-image: push-image
+	$(info Running e2e test on operator image: $@)
+	$(eval NAMESPACE := test-image-$(shell </dev/urandom tr -dc 'a-z0-9' | head -c 7  ; echo))
+	echo "$(NAMESPACE)"
+	$(Q)kubectl create namespace $(NAMESPACE)
+	$(Q)kubectl --namespace $(NAMESPACE) apply -f ./test/third-party-crds/postgresql_v1alpha1_database_crd.yaml
+	$(Q)GO111MODULE=$(GO111MODULE) GOCACHE=$(GOCACHE) SERVICE_BINDING_OPERATOR_DISABLE_ELECTION=true \
+		operator-sdk --verbose test local ./test/e2e \
+			--namespace "$(NAMESPACE)" \
+			--image "$(OPERATOR_IMAGE):$(OPERATOR_TAG_LONG)" \
+			--go-test-flags "-timeout=15m" \
+			--local-operator-flags "$(ZAP_FLAGS)" \
+			$(OPERATOR_SDK_EXTRA_ARGS)
+
 .PHONY: test-unit-with-coverage
 ## Runs the unit tests with code coverage
 test-unit-with-coverage:
@@ -236,7 +259,7 @@ test-e2e-olm-ci:
 	$(Q)sed -e "s,REPLACE_IMAGE,registry.svc.ci.openshift.org/${OPENSHIFT_BUILD_NAMESPACE}/stable:service-binding-operator-registry," ./test/operator-hub/catalog_source.yaml | kubectl apply -f -
 	$(Q)kubectl apply -f ./test/operator-hub/subscription.yaml
 	$(eval DEPLOYED_NAMESPACE := openshift-operators)
-	$(Q)./hack/check-crds.sh
+	$(Q)$(HACK_DIR)/check-crds.sh
 	$(Q)operator-sdk --verbose test local ./test/e2e \
 			--no-setup \
 			--go-test-flags "-timeout=15m" \
@@ -250,7 +273,7 @@ test-e2e-olm-ci:
 build: out/operator
 
 out/operator:
-	$(Q)GOARCH=amd64 GOOS=linux go build ${V_FLAG} -o ./out/operator cmd/manager/main.go
+	$(Q)GOARCH=amd64 GOOS=linux go build ${V_FLAG} -o $(OUTPUT_DIR)/operator cmd/manager/main.go
 
 ## Build-Image: using operator-sdk to build a new image
 build-image:
@@ -299,8 +322,8 @@ push-operator: prepare-csv
 ## Push-Image: push container image to upstream, including latest tag.
 push-image: build-image
 	podman tag "$(OPERATOR_IMAGE):$(OPERATOR_TAG_LONG)" "$(OPERATOR_IMAGE):latest"
-	podman push "$(OPERATOR_IMAGE):$(OPERATOR_TAG_LONG)"
-	podman push "$(OPERATOR_IMAGE):latest"
+	-podman push "$(OPERATOR_IMAGE):$(OPERATOR_TAG_LONG)"
+	-podman push "$(OPERATOR_IMAGE):latest"
 
 ## -- Local deployment targets --
 
@@ -341,7 +364,7 @@ deploy: deploy-rbac deploy-crds
 .PHONY: clean
 ## Removes temp directories
 clean:
-	$(Q)-rm -rf ${V_FLAG} ./out
+	$(Q)-rm -rf ${V_FLAG} $(OUTPUT_DIR)
 
 
 ## -- Targets for uploading code coverage reports to Codecov.io--
diff --git a/README.md b/README.md
index eacdb638..02315b58 100644
--- a/README.md
+++ b/README.md
@@ -14,56 +14,41 @@
 
 ## Introduction
 
-The goal of the Service Binding Operator is to enable application authors to import an application
-and run it on OpenShift with operator-backed services such as databases, without having to perform
-manual configuration of secrets, configmaps, etc.
+The goal of the Service Binding Operator is to enable application authors to
+import an application and run it on OpenShift with operator-backed services
+such as databases, without having to perform manual configuration of secrets,
+configmaps, etc.
 
-In order for the Service Binding Operator to bind an application to a backing service, the backing
-service operator must specify the information required by the application to bind to the
-operator's service. The information must be specified in the operator's OLM (Operator Lifecycle
-Manager) descriptor from which it will be extracted to bind the application to the operator. The
-information could be specified in the "status" and/or "spec" section of the OLM in plaintext or as
-a reference to a secret.
+In order to make a service bindable, the operator provider needs to express
+the information needed by applications to bind with the services provided by
+the operator. In other words, the operator provider must express the
+information that is “interesting” to applications.
 
-In order to make an imported application (for example, a NodeJS application) connect to a backing
-services (for example, a database):
+There are multiple methods for making operator managed backing services
+bindable, including the backing operator providing metadata in CRD
+annotations. Details on the methods for making backing services bindble
+are available in the [Operator Best Practices Guide](docs/OperatorBestPractices.md)
+
+In order to make an imported application (for example, a NodeJS application)
+connect to a backing services (for example, a database):
 
 * The app author (developer) creates a `ServiceBindingRequest` and specifies:
-  * The resource that needs the binding information. The resource can be specified by label
-    selectors;
-  * The backing service's resource reference that the imported application needs to be bound to;
+  * The resource that needs the binding information. The resource can be
+    specified by label selectors;
+  * The backing service's resource reference that the imported application
+    needs to be bound to;
 
 * The Service Binding Controller then:
-  * Reads backing service operator OLM descriptor to discover the binding attributes
+  * Reads backing service operator CRD annotations to discover the
+    binding attributes
   * Creates a binding secret for the backing service, example, an operator-managed database;
   * Injects environment variables into the applications's `DeploymentConfig`, `Deployment` or
     `Replicaset`;
 
-Here is an example of the *bind-able* operator OLM Descriptor -- in this case for a PostgreSQL
-database backing operator:
-
-``` yaml
----
-[...]
-statusDescriptors:
-  description: Name of the Secret to hold the DB user and password
-    displayName: DB Password Credentials
-    path: dbCredentials
-    x-descriptors:
-      - urn:alm:descriptor:io.kubernetes:Secret
-      - binding:env:object:secret:user
-      - binding:env:object:secret:password
-  description: Database connection IP address
-    displayName: DB IP address
-    path: dbConnectionIP
-    x-descriptors:
-      - binding:env:attribute
-```
-
 ## Quick Start
 
-Clone the repository and run `make local` in an existing `kube:admin` openshift CLI session.
-Alternatively, install the operator using:
+Clone the repository and run `make local` in an existing `kube:admin` openshift
+CLI session. Alternatively, install the operator using:
 
 ``` bash
 cat <<EOS |kubectl apply -f -
@@ -84,9 +69,14 @@ EOS
 
 The best way to get started with the Service Binding Operator is to see it in action.
 
-We've included a number of examples scenarios for using the operator in this repo. The examples are found in the "/examples" directory. Each of these examples illustrates a usage scenario for the operator. Each example also includes a README file with step-by-step instructions for how to run the example.
+We've included a number of examples scenarios for using the operator in this
+repo. The examples are found in the "/examples" directory. Each of these
+examples illustrates a usage scenario for the operator. Each example also
+includes a README file with step-by-step instructions for how to run the
+example.
 
-We'll add more examples in the future. The following section in this README file includes links to the current set of examples.
+We'll add more examples in the future. The following section in this README
+file includes links to the current set of examples.
 
 ## Example Scenarios
 
diff --git a/deploy/crds/apps_v1alpha1_servicebindingrequest_crd.yaml b/deploy/crds/apps_v1alpha1_servicebindingrequest_crd.yaml
index 88d97e1a..2df5af0e 100644
--- a/deploy/crds/apps_v1alpha1_servicebindingrequest_crd.yaml
+++ b/deploy/crds/apps_v1alpha1_servicebindingrequest_crd.yaml
@@ -38,14 +38,14 @@ spec:
               properties:
                 group:
                   type: string
-                name:
-                  type: string
                 matchLabels:
                   additionalProperties:
                     type: string
                   type: object
                 resource:
                   type: string
+                resourceRef:
+                  type: string
                 version:
                   type: string
               required:
@@ -86,6 +86,10 @@ spec:
                 - value
                 type: object
               type: array
+            detectBindingResources:
+              description: DetectBindingResources is flag used to bind all non-bindable
+                variables from different subresources owned by backing operator CR.
+              type: boolean
             envVarPrefix:
               description: EnvVarPrefix is the prefix for environment variables
               type: string
diff --git a/deploy/role.yaml b/deploy/role.yaml
index 27162ad5..8296c728 100644
--- a/deploy/role.yaml
+++ b/deploy/role.yaml
@@ -54,6 +54,7 @@ rules:
       - "get"
       - "list"
       - "watch"
+      - "update"
   - verbs:
       - "*"
     apiGroups:
diff --git a/docs/OperatorBestPractices.md b/docs/OperatorBestPractices.md
new file mode 100644
index 00000000..b24773da
--- /dev/null
+++ b/docs/OperatorBestPractices.md
@@ -0,0 +1,121 @@
+# Operator Best Practices
+
+## Introduction
+
+The goals of the Service Binding Operator is to make it easier for
+applications developers to bind applications with needed backing
+services, without having to perform manual configuration of secrets,
+configmaps, etc. and to assist operator providers in promoting and
+expanding the adoption of their operators.
+
+When a ServiceBindingRequest is created the Service Binding Operator
+collects binding information and shares it with application. The
+Binding Service Operator's controller injects the binding information
+into the application's "DeploymentConfig", "Deployment" or “Replicaset"
+as environment variables via an intermediate Secret called "binding-request".
+The binding also works with Knative services as it works with any "deployment"
+controller which has the podspec defined in the its jsonpath as
+"spec.template.spec.containers".
+
+This document provides "best practices" guidelines for the development of
+Operators that manage backing services to be bound together with applications
+by the Service Binding Operator.
+
+## Making an Operator Managed Backing Service Bindable
+
+In order to make a service bindable, the operator provider needs to express
+the information needed by applications to bind with the services provided by
+the operator. In other words, the operator provider must express the
+information that is “interesting” to applications.
+
+There are three methods for making Operator Managed Backing Service Bindable:
+
+* [Operator Providing Metadata in CRD Annotations](#operator-providing-metadata-in-crd-annotations)
+* [Operator Providing Metadata in OLM](#operator-providing-metadata-in-olm)
+* [Operator Not Providing Metadata](#operator-not-providing-metadata) Coming Soon!
+
+### Operator Providing Metadata in CRD Annotations
+
+This feature enables operator providers who do not use OLM (Operator Lifecycle
+Manager) to provide metadata outside of an OLM descriptor. In this method,
+the binding information is provided as annotations in the CRD of the operator
+that manages the backing service. The Service Binding Operator extracts the
+annotations to bind the application together with the backing service.
+
+For example, this is a *bind-able* operator's annotations in its CRD for a
+PostgreSQL database backing operator.
+``` yaml
+---
+[...]
+kind: CustomResourceDefinition
+apiVersion: apiextensions.k8s.io/v1beta1
+metadata:
+  name: databases.postgresql.baiju.dev
+  annotations:
+    servicebindingoperator.redhat.io/status.dbConfigMap.password: 'binding:env:object:secret'
+    servicebindingoperator.redhat.io/status.dbConfigMap.username: 'binding:env:object:configmap'
+    servicebindingoperator.redhat.io/status.dbName: 'binding:env:attribute'
+    servicebindingoperator.redhat.io/spec.Token.private: 'binding:volumemount:secret'
+spec:
+  group: postgresql.baiju.dev
+  version: v1alpha1
+```
+
+### Operator Providing Metadata in OLM
+
+This feature enables operator providers to specify binding information an
+operator's OLM (Operator Lifecycle Manager) descriptor. The Service Binding
+Operator extracts to bind the application together with the backing service.
+The information may be specified in the "status" and/or "spec" section of the
+OLM in plaintext or as a reference to a secret.
+
+For example, this is a *bind-able* operator OLM Descriptor for a
+PostgreSQL database backing operator.
+``` yaml
+---
+[...]
+statusDescriptors:
+  description: Name of the Secret to hold the DB user and password
+    displayName: DB Password Credentials
+    path: dbCredentials
+    x-descriptors:
+      - urn:alm:descriptor:io.kubernetes:Secret
+      - binding:env:object:secret:user
+      - binding:env:object:secret:password
+  description: Database connection IP address
+    displayName: DB IP address
+    path: dbConnectionIP
+    x-descriptors:
+      - binding:env:attribute
+```
+
+### Operator Not Providing Metadata
+
+This feature enables operators that manage backing services but which don't
+have any metadata in their CSV to use the Service Binding Operator to bind
+together the service and applications. The Service Binding Operator binds all
+sub-resources defined in the backing service CR by populating the binding
+secret with information from Routes, Services, ConfigMaps, and Secrets owned
+by the backing service CR.
+
+[This is how resource and sub-resource relationships are set in
+Kubernetes.](https://kubernetes.io/docs/concepts/workloads/controllers/garbage-collection/#owners-and-dependents)
+
+The binding is initiated by the introduction of this API option in the backing service CR:
+``` yaml
+detectBindingResources : true
+```
+When this API option is set to true, the Service Binding Operator
+automatically detects Routes, Services, ConfigMaps, and Secrets owned by
+the backing service CR.
+
+## Reference Operators
+
+Reference backing service operators are available [here.](https://github.com/operator-backing-service-samples)
+
+A set of examples, each of which illustrates a usage scenario for the
+Service Binding Operator, is being developed in parallel with the Operator.
+Each example makes use of one of the reference operators and includes
+instructions for deploying the reference operators to a cluster, either
+through the command line or client web console UI. The examples are
+available [here.](https://github.com/redhat-developer/service-binding-operator/blob/master/README.md#example-scenarios)
diff --git a/examples/java_postgresql_customvar/README.md b/examples/java_postgresql_customvar/README.md
index 4bf9318a..407d66b3 100644
--- a/examples/java_postgresql_customvar/README.md
+++ b/examples/java_postgresql_customvar/README.md
@@ -227,8 +227,7 @@ That causes the application to be re-deployed.
 
 Once the new version is up, go to the application's route to check the UI. Now, it works!
 
-When the `ServiceBindingRequest` was created the Service Binding Operator's controller injected the DB connection information as specified in the OLM descriptor below, into the
-application's `DeploymentConfig` as environment variables via an intermediate `Secret` called `binding-request`:
+When the `ServiceBindingRequest` was created the Service Binding Operator's controller injected the DB connection information into the application's `DeploymentConfig` as environment variables via an intermediate `Secret` called `binding-request`:
 
 ```yaml
 spec:
diff --git a/examples/nodejs_etcd_operator/README.md b/examples/nodejs_etcd_operator/README.md
new file mode 100644
index 00000000..5ab9bbd9
--- /dev/null
+++ b/examples/nodejs_etcd_operator/README.md
@@ -0,0 +1,46 @@
+## Binding an Imported app to an In-cluster Operator Managed Etcd Database.
+
+1. Install Etcd operator using operator hub, 
+   follow https://operatorhub.io/operator/etcd
+2. Create an Etcd cluster.
+ ```yaml
+ apiVersion: "etcd.database.coreos.com/v1beta2"
+ kind: "EtcdCluster"
+ metadata:
+  name: "etcd-cluster"
+ spec:
+  size: 5
+  version: "3.2.13"
+ ```
+3. Deploy application which uses Etcd client lib using openshift 4 devconsole.
+Test application : https://github.com/akashshinde/node-todo.git
+![](https://i.imgur.com/WGQZ1nj.png)
+
+4. Create SBR.
+```yaml
+apiVersion: apps.openshift.io/v1alpha1
+kind: ServiceBindingRequest
+metadata:
+  name: binding-request
+spec:
+  applicationSelector:
+    matchLabels:
+      connects-to: etcd
+      environment: demo
+    group: apps.openshift.io
+    version: v1
+    resource: deploymentconfigs
+    resourceRef: ""
+  backingServiceSelector:
+    group: etcd.database.coreos.com
+    version: v1beta2
+    kind: EtcdCluster
+    resourceRef: etcd-cluster-example
+  mountPathPrefix: “”
+  customEnvVar: []
+  detectBindingResources: true
+```
+5. Application should be binded to the Etcd database automatically.
+![](https://i.imgur.com/JjORDrJ.png)
+
+
diff --git a/examples/nodejs_postgresql/README.md b/examples/nodejs_postgresql/README.md
index 2f7b4691..f1052513 100644
--- a/examples/nodejs_postgresql/README.md
+++ b/examples/nodejs_postgresql/README.md
@@ -145,6 +145,7 @@ spec:
   imageName: postgres
   dbName: db-demo
 EOS
+```
 
 Alternatively, you can perform the same task with this make command:
 ``` bash
@@ -214,8 +215,7 @@ That causes the application to be re-deployed.
 
 Once the new version is up, go to the application's route to check the UI. In the header you can see `(DB: db-demo)` which indicates that the application is connected to a DB and its name is `db-demo`. Now you can try the UI again but now it works!
 
-When the `ServiceBindingRequest` was created the Service Binding Operator's controller injected the DB connection information as specified in the OLM descriptor below, into the
-application's `DeploymentConfig` as environment variables via an intermediate `Secret` called `binding-request`:
+When the `ServiceBindingRequest` was created the Service Binding Operator's controller injected the DB connection information into the application's `DeploymentConfig` as environment variables via an intermediate `Secret` called `binding-request`:
 
 ``` yaml
 spec:
diff --git a/go.mod b/go.mod
index 22f978b9..dc1566bf 100644
--- a/go.mod
+++ b/go.mod
@@ -26,7 +26,7 @@ require (
 	golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 // indirect
 	k8s.io/api v0.0.0-20190612125737-db0771252981
 	k8s.io/apimachinery v0.0.0-20190612205821-1799e75a0719
-	k8s.io/client-go v11.0.0+incompatible
+	k8s.io/client-go v12.0.0+incompatible
 	k8s.io/code-generator v0.0.0-20181203235156-f8cba74510f3
 	k8s.io/gengo v0.0.0-20190327210449-e17681d19d3a
 	k8s.io/kube-openapi v0.0.0-20190320154901-5e45bb682580
diff --git a/manifests/service-binding-operator.v0.0.20.clusterserviceversion.yaml b/manifests-upstream/0.0.20/service-binding-operator.v0.0.20.clusterserviceversion.yaml
similarity index 99%
rename from manifests/service-binding-operator.v0.0.20.clusterserviceversion.yaml
rename to manifests-upstream/0.0.20/service-binding-operator.v0.0.20.clusterserviceversion.yaml
index 03fb22c7..4a46f59a 100644
--- a/manifests/service-binding-operator.v0.0.20.clusterserviceversion.yaml
+++ b/manifests-upstream/0.0.20/service-binding-operator.v0.0.20.clusterserviceversion.yaml
@@ -111,6 +111,7 @@ spec:
                 - "get"
                 - "list"
                 - "watch"
+                - "update"
             - verbs:
                 - "*"
               apiGroups:
diff --git a/manifests/service-binding-operator.servicebindingrequests.crd.yaml b/manifests-upstream/0.0.20/servicebindingrequests.apps.openshift.io.crd.yaml
similarity index 98%
rename from manifests/service-binding-operator.servicebindingrequests.crd.yaml
rename to manifests-upstream/0.0.20/servicebindingrequests.apps.openshift.io.crd.yaml
index 4ac387a3..6d44ceed 100644
--- a/manifests/service-binding-operator.servicebindingrequests.crd.yaml
+++ b/manifests-upstream/0.0.20/servicebindingrequests.apps.openshift.io.crd.yaml
@@ -49,10 +49,11 @@ spec:
                   type: object
                 resource:
                   type: string
+                resourceRef:
+                  type: string
                 version:
                   type: string
               required:
-                - matchLabels
                 - version
                 - resource
               type: object
diff --git a/manifests-upstream/service-binding-operator.package.yaml b/manifests-upstream/service-binding-operator.package.yaml
new file mode 100644
index 00000000..e14802f8
--- /dev/null
+++ b/manifests-upstream/service-binding-operator.package.yaml
@@ -0,0 +1,7 @@
+channels:
+- currentCSV: service-binding-operator.v0.0.20
+  name: dev
+- currentCSV: service-binding-operator.v0.0.20
+  name: stable
+defaultChannel: dev
+packageName: service-binding-operator
diff --git a/manifests/4.3.0/service-binding-operator.v4.3.0.clusterserviceversion.yaml b/manifests/4.3.0/service-binding-operator.v4.3.0.clusterserviceversion.yaml
new file mode 100644
index 00000000..a57e3219
--- /dev/null
+++ b/manifests/4.3.0/service-binding-operator.v4.3.0.clusterserviceversion.yaml
@@ -0,0 +1,135 @@
+apiVersion: operators.coreos.com/v1alpha1
+kind: ClusterServiceVersion
+metadata:
+  annotations:
+    alm-examples: '[{"apiVersion":"apps.openshift.io/v1alpha1","kind":"ServiceBindingRequest","metadata":{"name":"example-servicebindingrequest"},"spec":{"applicationSelector":{"matchLabels":{"connects-to":"postgres","environment":"production"},"resourceKind":"Deployment"},"backingServiceSelector":{"resourceName":"database.example.org","resourceVersion":"v1alpha1"}}}]' # yamllint disable-line rule:line-length
+    capabilities: Basic Install
+    containerImage: quay.io/redhat-developer/app-binding-operator:v0.0.20
+    description: An operator to support binding capabilities between imported
+      apps and operator backed services
+  name: service-binding-operator.v4.3.0
+  namespace: placeholder
+spec:
+  links:
+    - name: Source Code
+      url: https://github.com/redhat-developer/service-binding-operator
+  maintainers:
+    - email: shbose@redhat.com
+      name: Shoubhik Bose
+  apiservicedefinitions: {}
+  customresourcedefinitions:
+    owned:
+      - kind: ServiceBindingRequest
+        name: servicebindingrequests.apps.openshift.io
+        version: v1alpha1
+        displayName: ServiceBindingRequest
+        description: Expresses intent to bind an operator-backed service with
+          a Deployment.
+  description: Placeholder description
+  displayName: Service Binding Operator
+  install:
+    spec:
+      deployments:
+        - name: service-binding-operator
+          spec:
+            replicas: 1
+            selector:
+              matchLabels:
+                name: service-binding-operator
+            strategy: {}
+            template:
+              metadata:
+                labels:
+                  name: service-binding-operator
+              spec:
+                containers:
+                  - command:
+                      - service-binding-operator
+                    env:
+                      - name: WATCH_NAMESPACE
+                        value: ""
+                      - name: POD_NAME
+                        valueFrom:
+                          fieldRef:
+                            fieldPath: metadata.name
+                      - name: OPERATOR_NAME
+                        value: service-binding-operator
+                    image: quay.io/redhat-developer/app-binding-operator:v0.0.20
+                    imagePullPolicy: Always
+                    name: service-binding-operator
+                    resources: {}
+                serviceAccountName: service-binding-operator
+      permissions:
+        - rules:
+            - apiGroups:
+                - ""
+              resources:
+                - pods
+                - services
+                - endpoints
+                - persistentvolumeclaims
+                - events
+                - configmaps
+                - secrets
+              verbs:
+                - "*"
+            - apiGroups:
+                - apps
+              resources:
+                - deployments
+                - daemonsets
+                - replicasets
+                - statefulsets
+              verbs:
+                - "*"
+            - apiGroups:
+                - monitoring.coreos.com
+              resources:
+                - servicemonitors
+              verbs:
+                - get
+                - create
+            - apiGroups:
+                - apps
+              resourceNames:
+                - service-binding-operator
+              resources:
+                - deployments/finalizers
+              verbs:
+                - update
+            - apiGroups:
+                - apps.openshift.io
+              resources:
+                - "*"
+              verbs:
+                - "*"
+            - apiGroups:
+                - "*"
+              resources:
+                - "*"
+              verbs:
+                - "get"
+                - "list"
+                - "watch"
+                - "update"
+            - verbs:
+                - "*"
+              apiGroups:
+                - serving.knative.dev
+              resources:
+                - services
+          serviceAccountName: service-binding-operator
+    strategy: deployment
+  installModes:
+    - supported: true
+      type: OwnNamespace
+    - supported: true
+      type: SingleNamespace
+    - supported: false
+      type: MultiNamespace
+    - supported: true
+      type: AllNamespaces
+  maturity: alpha
+  provider:
+    name: Red Hat, Inc.
+  version: 4.3.0
diff --git a/manifests/4.3.0/servicebindingrequests.apps.openshift.io.crd.yaml b/manifests/4.3.0/servicebindingrequests.apps.openshift.io.crd.yaml
new file mode 100644
index 00000000..6d44ceed
--- /dev/null
+++ b/manifests/4.3.0/servicebindingrequests.apps.openshift.io.crd.yaml
@@ -0,0 +1,126 @@
+apiVersion: apiextensions.k8s.io/v1beta1
+kind: CustomResourceDefinition
+metadata:
+  name: servicebindingrequests.apps.openshift.io
+spec:
+  group: apps.openshift.io
+  names:
+    kind: ServiceBindingRequest
+    listKind: ServiceBindingRequestList
+    plural: servicebindingrequests
+    shortNames:
+      - sbr
+      - sbrs
+    singular: servicebindingrequest
+  scope: Namespaced
+  subresources:
+    status: {}
+  validation:
+    openAPIV3Schema:
+      properties:
+        apiVersion:
+          description:
+            "APIVersion defines the versioned schema of this representation
+            of an object. Servers should convert recognized schemas to the latest
+            internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#resources"
+          type: string
+        kind:
+          description:
+            "Kind is a string value representing the REST resource this
+            object represents. Servers may infer this from the endpoint the client
+            submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#types-kinds"
+          type: string
+        metadata:
+          type: object
+        spec:
+          properties:
+            applicationSelector:
+              description:
+                ApplicationSelector is used to identify the application
+                connecting to the backing service operator.
+              properties:
+                group:
+                  type: string
+                name:
+                  type: string
+                matchLabels:
+                  additionalProperties:
+                    type: string
+                  type: object
+                resource:
+                  type: string
+                resourceRef:
+                  type: string
+                version:
+                  type: string
+              required:
+                - version
+                - resource
+              type: object
+            backingServiceSelector:
+              description:
+                BackingServiceSelector is used to identify the backing
+                service operator.
+              properties:
+                group:
+                  type: string
+                kind:
+                  type: string
+                resourceRef:
+                  type: string
+                version:
+                  type: string
+              required:
+                - group
+                - version
+                - kind
+                - resourceRef
+              type: object
+            customEnvVar:
+              description: Custom env variables
+              items:
+                properties:
+                  name:
+                    description: key of custom env variable
+                    type: string
+                  value:
+                    description:
+                      value template, currently supports expected is go
+                      template
+                    type: string
+                required:
+                  - name
+                  - value
+                type: object
+              type: array
+            envVarPrefix:
+              description: EnvVarPrefix is the prefix for environment variables
+              type: string
+            mountPathPrefix:
+              description: MountPathPrefix is the prefix for volume mount
+              type: string
+          required:
+            - backingServiceSelector
+            - applicationSelector
+          type: object
+        status:
+          properties:
+            applicationObjects:
+              description:
+                ApplicationObjects contains all the application objects
+                filtered by label
+              items:
+                type: string
+              type: array
+            bindingStatus:
+              description: BindingStatus is the status of the service binding request.
+              type: string
+            secret:
+              description: Secret is the name of the intermediate secret
+              type: string
+          type: object
+  version: v1alpha1
+  versions:
+    - name: v1alpha1
+      served: true
+      storage: true
diff --git a/manifests/service-binding-operator.package.yaml b/manifests/service-binding-operator.package.yaml
index 11aedca9..5be0d099 100644
--- a/manifests/service-binding-operator.package.yaml
+++ b/manifests/service-binding-operator.package.yaml
@@ -1,7 +1,4 @@
-packageName: service-binding-operator
 channels:
-  - name: dev
-    currentCSV: service-binding-operator.v0.0.20
-  - name: stable
-    currentCSV: service-binding-operator.v0.0.20
-defaultChannel: dev
+  - currentCSV: service-binding-operator.v4.3.0
+    name: "4.3"
+packageName: service-binding-operator
diff --git a/openshift-ci/Dockerfile.registry.build b/openshift-ci/Dockerfile.registry.build
index 085c6497..3cd1bfd3 100644
--- a/openshift-ci/Dockerfile.registry.build
+++ b/openshift-ci/Dockerfile.registry.build
@@ -2,9 +2,9 @@ FROM quay.io/openshift/origin-operator-registry:latest
 
 ARG version=0.0.20
 RUN mkdir -p manifests/service-binding-operator/${version}
-COPY manifests/service-binding-operator.package.yaml manifests/service-binding-operator/
-COPY manifests/service-binding-operator*.crd.yaml manifests/service-binding-operator/${version}/
-COPY manifests/service-binding-operator*.clusterserviceversion.yaml manifests/service-binding-operator/${version}/
+COPY manifests-upstream/service-binding-operator.package.yaml manifests/service-binding-operator/
+COPY manifests-upstream/${version}/servicebindingrequests*.crd.yaml manifests/service-binding-operator/${version}/
+COPY manifests-upstream/${version}/service-binding-operator*.clusterserviceversion.yaml manifests/service-binding-operator/${version}/
 
 USER root
 RUN sed -e "s,quay.io/redhat-developer/app-binding-operator:v${version},registry.svc.ci.openshift.org/${OPENSHIFT_BUILD_NAMESPACE}/stable:service-binding-operator," -i manifests/service-binding-operator/${version}/service-binding-operator.v${version}.clusterserviceversion.yaml
diff --git a/pkg/apis/apps/v1alpha1/servicebindingrequest_types.go b/pkg/apis/apps/v1alpha1/servicebindingrequest_types.go
index 1be64e9f..a0021ff4 100644
--- a/pkg/apis/apps/v1alpha1/servicebindingrequest_types.go
+++ b/pkg/apis/apps/v1alpha1/servicebindingrequest_types.go
@@ -30,6 +30,11 @@ type ServiceBindingRequestSpec struct {
 	// ApplicationSelector is used to identify the application connecting to the
 	// backing service operator.
 	ApplicationSelector ApplicationSelector `json:"applicationSelector"`
+
+	// DetectBindingResources is flag used to bind all non-bindable variables from
+	// different subresources owned by backing operator CR.
+	// +optional
+	DetectBindingResources bool `json:"detectBindingResources"`
 }
 
 // CustomEnvMap is a set of Name and Value of an environment variable
diff --git a/pkg/apis/apps/v1alpha1/zz_generated.openapi.go b/pkg/apis/apps/v1alpha1/zz_generated.openapi.go
index 445fd2c0..c21649a3 100644
--- a/pkg/apis/apps/v1alpha1/zz_generated.openapi.go
+++ b/pkg/apis/apps/v1alpha1/zz_generated.openapi.go
@@ -57,8 +57,14 @@ func schema_pkg_apis_apps_v1alpha1_ApplicationSelector(ref common.ReferenceCallb
 							Format: "",
 						},
 					},
+					"resourceRef": {
+						SchemaProps: spec.SchemaProps{
+							Type:   []string{"string"},
+							Format: "",
+						},
+					},
 				},
-				Required: []string{"matchLabels", "version", "resource"},
+				Required: []string{"matchLabels", "version", "resource", "resourceRef"},
 			},
 		},
 		Dependencies: []string{},
@@ -219,6 +225,13 @@ func schema_pkg_apis_apps_v1alpha1_ServiceBindingRequestSpec(ref common.Referenc
 							Ref:         ref("./pkg/apis/apps/v1alpha1.ApplicationSelector"),
 						},
 					},
+					"detectBindingResources": {
+						SchemaProps: spec.SchemaProps{
+							Description: "DetectBindingResources is flag used to bind all non-bindable variables from different subresources owned by backing operator CR.",
+							Type:        []string{"boolean"},
+							Format:      "",
+						},
+					},
 				},
 				Required: []string{"backingServiceSelector", "applicationSelector"},
 			},
diff --git a/pkg/controller/servicebindingrequest/bind_custom_resources.go b/pkg/controller/servicebindingrequest/bind_custom_resources.go
new file mode 100644
index 00000000..fb721084
--- /dev/null
+++ b/pkg/controller/servicebindingrequest/bind_custom_resources.go
@@ -0,0 +1,102 @@
+package servicebindingrequest
+
+import (
+	"github.com/redhat-developer/service-binding-operator/pkg/apis/apps/v1alpha1"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	"k8s.io/client-go/dynamic"
+)
+
+var (
+	path = map[string][][]string{
+		"ConfigMap": {{"data"}},
+		"Secret":    {{"data"}},
+		"Route":     {{"spec", "host"}},
+		"Service":   {{"spec", "clusterIP"}},
+	}
+)
+
+// DetectBindableResources struct contains information about operator backed CR and
+// list of expected GVRs to extract information from.
+type DetectBindableResources struct {
+	cr               *unstructured.Unstructured
+	resourcesToCheck []schema.GroupVersionResource
+	client           dynamic.Interface
+	data             map[string]interface{}
+}
+
+// NewDetectBindableResources returns new instance
+func NewDetectBindableResources(
+	sbr *v1alpha1.ServiceBindingRequest,
+	cr *unstructured.Unstructured,
+	resources []schema.GroupVersionResource,
+	client dynamic.Interface,
+) *DetectBindableResources {
+	b := new(DetectBindableResources)
+	b.client = client
+	b.cr = cr
+	b.resourcesToCheck = resources
+	b.data = make(map[string]interface{})
+	return b
+}
+
+// GetBindableVariables returns list of subresources owned by operator backed CR
+func (b DetectBindableResources) GetOwnedResources() ([]unstructured.Unstructured, error) {
+	var subResources []unstructured.Unstructured
+	for _, resource := range b.resourcesToCheck {
+		lst, err := b.client.Resource(resource).List(v1.ListOptions{})
+		if err != nil {
+			return subResources, err
+		}
+		for _, item := range lst.Items {
+			owners := item.GetOwnerReferences()
+			for _, owner := range owners {
+				if owner.UID == b.cr.GetUID() {
+					subResources = append(subResources, item)
+				}
+			}
+		}
+	}
+	return subResources, nil
+}
+
+// GetBindableVariables extracts required key value information from provided GVRs subresources
+func (b DetectBindableResources) GetBindableVariables() (map[string]interface{}, error) {
+	ownedResources, err := b.GetOwnedResources()
+	if err != nil {
+		return b.data, err
+	}
+	for _, resource := range ownedResources {
+		switch resource.GetKind() {
+		// In case ConfigMap and Secret we would read data field
+		case "ConfigMap", "Secret":
+			for _, v := range path[resource.GetKind()] {
+				d, exist, err := unstructured.NestedMap(resource.Object, v...)
+				if err != nil {
+					// skipping on error
+					continue
+				}
+				if exist {
+					for k, val := range d {
+						b.data[k] = val
+					}
+				}
+			}
+
+			// In case of Route and Service we would extract information from respective path
+		case "Route", "Service":
+			for _, v := range path[resource.GetKind()] {
+				d, exist, err := unstructured.NestedString(resource.Object, v...)
+				if err != nil {
+					continue
+				}
+				if exist {
+					val := v[len(v)-1]
+					b.data[val] = d
+				}
+			}
+		}
+	}
+	return b.data, nil
+}
diff --git a/pkg/controller/servicebindingrequest/binder.go b/pkg/controller/servicebindingrequest/binder.go
index 1e8924ed..017067d6 100644
--- a/pkg/controller/servicebindingrequest/binder.go
+++ b/pkg/controller/servicebindingrequest/binder.go
@@ -54,15 +54,17 @@ func (b *Binder) search() (*unstructured.UnstructuredList, error) {
 	// If Application name is present
 	if b.sbr.Spec.ApplicationSelector.ResourceRef != "" {
 		fieldName := make(map[string]string)
-		fieldName["name"] = b.sbr.Spec.ApplicationSelector.ResourceRef
+		fieldName["metadata.name"] = b.sbr.Spec.ApplicationSelector.ResourceRef
 		opts = metav1.ListOptions{
 			FieldSelector: fields.Set(fieldName).String(),
 		}
-	} else {
+	} else if b.sbr.Spec.ApplicationSelector.MatchLabels != nil {
 		matchLabels := b.sbr.Spec.ApplicationSelector.MatchLabels
 		opts = metav1.ListOptions{
 			LabelSelector: labels.Set(matchLabels).String(),
 		}
+	} else {
+		return nil, fmt.Errorf("Application ResourceRef or MatchLabel not found.")
 	}
 
 	objList, err := b.dynClient.Resource(gvr).Namespace(ns).List(opts)
diff --git a/pkg/controller/servicebindingrequest/custom_env_parser.go b/pkg/controller/servicebindingrequest/custom_env_parser.go
index 7d3fdfeb..0083c2b7 100644
--- a/pkg/controller/servicebindingrequest/custom_env_parser.go
+++ b/pkg/controller/servicebindingrequest/custom_env_parser.go
@@ -2,15 +2,18 @@ package servicebindingrequest
 
 import (
 	"bytes"
-	"github.com/redhat-developer/service-binding-operator/pkg/apis/apps/v1alpha1"
 	"text/template"
+
+	"github.com/redhat-developer/service-binding-operator/pkg/apis/apps/v1alpha1"
 )
 
+// CustomEnvParser is responsible to interpolate a given CustomEnvMap containing templates.
 type CustomEnvParser struct {
 	EnvMap []v1alpha1.CustomEnvMap
 	Cache  map[string]interface{}
 }
 
+// NewCustomEnvParser returns a new CustomEnvParser.
 func NewCustomEnvParser(envMap []v1alpha1.CustomEnvMap, cache map[string]interface{}) *CustomEnvParser {
 	return &CustomEnvParser{
 		EnvMap: envMap,
@@ -18,6 +21,7 @@ func NewCustomEnvParser(envMap []v1alpha1.CustomEnvMap, cache map[string]interfa
 	}
 }
 
+// Parse interpolates and caches the templates in EnvMap.
 func (c *CustomEnvParser) Parse() (map[string]interface{}, error) {
 	data := make(map[string]interface{})
 	for _, v := range c.EnvMap {
diff --git a/pkg/controller/servicebindingrequest/olm.go b/pkg/controller/servicebindingrequest/olm.go
index 8bff5b43..5d11f5c5 100644
--- a/pkg/controller/servicebindingrequest/olm.go
+++ b/pkg/controller/servicebindingrequest/olm.go
@@ -132,7 +132,7 @@ func (o *OLM) SelectCRDByGVK(gvk schema.GroupVersionKind) (*olmv1alpha1.CRDDescr
 		}
 		// matching resource version, unless when not informed
 		if crdDescription.Version != "" &&
-			strings.ToLower(gvk.Version) != strings.ToLower(crdDescription.Version) {
+			!strings.EqualFold(strings.ToLower(gvk.Version), strings.ToLower(crdDescription.Version)) {
 			return
 		}
 		log.Debug("CRDDescription object matches selector!")
diff --git a/pkg/controller/servicebindingrequest/reconciler.go b/pkg/controller/servicebindingrequest/reconciler.go
index 1e5e4f89..9319159f 100644
--- a/pkg/controller/servicebindingrequest/reconciler.go
+++ b/pkg/controller/servicebindingrequest/reconciler.go
@@ -226,8 +226,6 @@ func (r *Reconciler) Reconcile(request reconcile.Request) (reconcile.Result, err
 
 	// saving on status the list of objects that have been touched
 	r.setApplicationObjects(&sbrStatus, updatedObjects)
-	// storing objects used in Binder
-	objectsToAnnotate = append(objectsToAnnotate, updatedObjects...)
 
 	//
 	// Annotating objects related to binding
diff --git a/pkg/controller/servicebindingrequest/retriever.go b/pkg/controller/servicebindingrequest/retriever.go
index 7604da54..2130a523 100644
--- a/pkg/controller/servicebindingrequest/retriever.go
+++ b/pkg/controller/servicebindingrequest/retriever.go
@@ -40,20 +40,18 @@ var (
 )
 
 // getNestedValue retrieve value from dotted key path
-func (r *Retriever) getNestedValue(key string, sectionMap interface{}) (string, error, interface{}) {
-	log := r.logger.WithValues("Key", key, "SectionMap", sectionMap)
+func (r *Retriever) getNestedValue(key string, sectionMap interface{}) (string, interface{}, error) {
 	if !strings.Contains(key, ".") {
 		value, exists := sectionMap.(map[string]interface{})[key]
 		if !exists {
-			return "", fmt.Errorf("Can't find key '%s'", key), sectionMap
+			return "", sectionMap, nil
 		}
-		return fmt.Sprintf("%v", value), nil, sectionMap
+		return fmt.Sprintf("%v", value), sectionMap, nil
 	}
 	attrs := strings.SplitN(key, ".", 2)
 	newSectionMap, exists := sectionMap.(map[string]interface{})[attrs[0]]
-	log.Debug("Section maps :  ")
 	if !exists {
-		return "", fmt.Errorf("Can't find '%v' section in CR", attrs), newSectionMap
+		return "", newSectionMap, nil
 	}
 	return r.getNestedValue(attrs[1], newSectionMap.(map[string]interface{}))
 }
@@ -70,7 +68,7 @@ func (r *Retriever) getCRKey(section string, key string) (string, interface{}, e
 		return "", sectionMap, fmt.Errorf("Can't find '%s' section in CR named '%s'", section, objName)
 	}
 
-	v, err, _ := r.getNestedValue(key, sectionMap)
+	v, _, err := r.getNestedValue(key, sectionMap)
 	for k, v := range sectionMap.(map[string]interface{}) {
 		if _, ok := r.cache[section]; !ok {
 			r.cache[section] = make(map[string]interface{})
@@ -339,6 +337,23 @@ func (r *Retriever) Retrieve() ([]*unstructured.Unstructured, error) {
 
 	log.Debug("Final cache values...", "cache", r.cache)
 
+	if r.plan.SBR.Spec.DetectBindingResources {
+		b := NewDetectBindableResources(&r.plan.SBR, r.plan.CR, []schema.GroupVersionResource{
+			// We can add extra gvrs here
+			{Group: "", Version: "v1", Resource: "configmaps"},
+			{Group: "", Version: "v1", Resource: "services"},
+			{Group: "route.openshift.io", Version: "v1", Resource: "routes"},
+		}, r.client)
+
+		vals, err := b.GetBindableVariables()
+		if err != nil {
+			return nil, err
+		}
+		for k,v := range vals {
+			r.store(k,[]byte(fmt.Sprintf("%v", v)))
+		}
+	}
+
 	envParser := NewCustomEnvParser(r.plan.SBR.Spec.CustomEnvVar, r.cache)
 	values, err := envParser.Parse()
 	if err != nil {
diff --git a/pkg/controller/servicebindingrequest/sbrcontroller.go b/pkg/controller/servicebindingrequest/sbrcontroller.go
index 565f0996..4a7cc5cb 100644
--- a/pkg/controller/servicebindingrequest/sbrcontroller.go
+++ b/pkg/controller/servicebindingrequest/sbrcontroller.go
@@ -27,7 +27,7 @@ type SBRController struct {
 }
 
 var (
-	// controllerName commong name of this controller
+	// controllerName common name of this controller
 	controllerName = "servicebindingrequest-controller"
 	// defaultPredicate default predicate functions
 	defaultPredicate = predicate.Funcs{
diff --git a/vendor/github.com/openshift/api/route/v1/doc.go b/vendor/github.com/openshift/api/route/v1/doc.go
new file mode 100644
index 00000000..e56fbbd8
--- /dev/null
+++ b/vendor/github.com/openshift/api/route/v1/doc.go
@@ -0,0 +1,8 @@
+// +k8s:deepcopy-gen=package,register
+// +k8s:conversion-gen=github.com/openshift/origin/pkg/route/apis/route
+// +k8s:defaulter-gen=TypeMeta
+// +k8s:openapi-gen=true
+
+// +groupName=route.openshift.io
+// Package v1 is the v1 version of the API.
+package v1
diff --git a/vendor/github.com/openshift/api/route/v1/generated.pb.go b/vendor/github.com/openshift/api/route/v1/generated.pb.go
new file mode 100644
index 00000000..4c2ce4d9
--- /dev/null
+++ b/vendor/github.com/openshift/api/route/v1/generated.pb.go
@@ -0,0 +1,2537 @@
+// Code generated by protoc-gen-gogo.
+// source: github.com/openshift/api/route/v1/generated.proto
+// DO NOT EDIT!
+
+/*
+	Package v1 is a generated protocol buffer package.
+
+	It is generated from these files:
+		github.com/openshift/api/route/v1/generated.proto
+
+	It has these top-level messages:
+		Route
+		RouteIngress
+		RouteIngressCondition
+		RouteList
+		RoutePort
+		RouteSpec
+		RouteStatus
+		RouteTargetReference
+		RouterShard
+		TLSConfig
+*/
+package v1
+
+import proto "github.com/gogo/protobuf/proto"
+import fmt "fmt"
+import math "math"
+
+import k8s_io_apimachinery_pkg_apis_meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+
+import k8s_io_api_core_v1 "k8s.io/api/core/v1"
+
+import strings "strings"
+import reflect "reflect"
+
+import io "io"
+
+// Reference imports to suppress errors if they are not otherwise used.
+var _ = proto.Marshal
+var _ = fmt.Errorf
+var _ = math.Inf
+
+// This is a compile-time assertion to ensure that this generated file
+// is compatible with the proto package it is being compiled against.
+// A compilation error at this line likely means your copy of the
+// proto package needs to be updated.
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
+
+func (m *Route) Reset()                    { *m = Route{} }
+func (*Route) ProtoMessage()               {}
+func (*Route) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{0} }
+
+func (m *RouteIngress) Reset()                    { *m = RouteIngress{} }
+func (*RouteIngress) ProtoMessage()               {}
+func (*RouteIngress) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{1} }
+
+func (m *RouteIngressCondition) Reset()                    { *m = RouteIngressCondition{} }
+func (*RouteIngressCondition) ProtoMessage()               {}
+func (*RouteIngressCondition) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{2} }
+
+func (m *RouteList) Reset()                    { *m = RouteList{} }
+func (*RouteList) ProtoMessage()               {}
+func (*RouteList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{3} }
+
+func (m *RoutePort) Reset()                    { *m = RoutePort{} }
+func (*RoutePort) ProtoMessage()               {}
+func (*RoutePort) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{4} }
+
+func (m *RouteSpec) Reset()                    { *m = RouteSpec{} }
+func (*RouteSpec) ProtoMessage()               {}
+func (*RouteSpec) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{5} }
+
+func (m *RouteStatus) Reset()                    { *m = RouteStatus{} }
+func (*RouteStatus) ProtoMessage()               {}
+func (*RouteStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{6} }
+
+func (m *RouteTargetReference) Reset()                    { *m = RouteTargetReference{} }
+func (*RouteTargetReference) ProtoMessage()               {}
+func (*RouteTargetReference) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{7} }
+
+func (m *RouterShard) Reset()                    { *m = RouterShard{} }
+func (*RouterShard) ProtoMessage()               {}
+func (*RouterShard) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{8} }
+
+func (m *TLSConfig) Reset()                    { *m = TLSConfig{} }
+func (*TLSConfig) ProtoMessage()               {}
+func (*TLSConfig) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{9} }
+
+func init() {
+	proto.RegisterType((*Route)(nil), "github.com.openshift.api.route.v1.Route")
+	proto.RegisterType((*RouteIngress)(nil), "github.com.openshift.api.route.v1.RouteIngress")
+	proto.RegisterType((*RouteIngressCondition)(nil), "github.com.openshift.api.route.v1.RouteIngressCondition")
+	proto.RegisterType((*RouteList)(nil), "github.com.openshift.api.route.v1.RouteList")
+	proto.RegisterType((*RoutePort)(nil), "github.com.openshift.api.route.v1.RoutePort")
+	proto.RegisterType((*RouteSpec)(nil), "github.com.openshift.api.route.v1.RouteSpec")
+	proto.RegisterType((*RouteStatus)(nil), "github.com.openshift.api.route.v1.RouteStatus")
+	proto.RegisterType((*RouteTargetReference)(nil), "github.com.openshift.api.route.v1.RouteTargetReference")
+	proto.RegisterType((*RouterShard)(nil), "github.com.openshift.api.route.v1.RouterShard")
+	proto.RegisterType((*TLSConfig)(nil), "github.com.openshift.api.route.v1.TLSConfig")
+}
+func (m *Route) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *Route) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	dAtA[i] = 0xa
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(m.ObjectMeta.Size()))
+	n1, err := m.ObjectMeta.MarshalTo(dAtA[i:])
+	if err != nil {
+		return 0, err
+	}
+	i += n1
+	dAtA[i] = 0x12
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(m.Spec.Size()))
+	n2, err := m.Spec.MarshalTo(dAtA[i:])
+	if err != nil {
+		return 0, err
+	}
+	i += n2
+	dAtA[i] = 0x1a
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(m.Status.Size()))
+	n3, err := m.Status.MarshalTo(dAtA[i:])
+	if err != nil {
+		return 0, err
+	}
+	i += n3
+	return i, nil
+}
+
+func (m *RouteIngress) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *RouteIngress) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	dAtA[i] = 0xa
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Host)))
+	i += copy(dAtA[i:], m.Host)
+	dAtA[i] = 0x12
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.RouterName)))
+	i += copy(dAtA[i:], m.RouterName)
+	if len(m.Conditions) > 0 {
+		for _, msg := range m.Conditions {
+			dAtA[i] = 0x1a
+			i++
+			i = encodeVarintGenerated(dAtA, i, uint64(msg.Size()))
+			n, err := msg.MarshalTo(dAtA[i:])
+			if err != nil {
+				return 0, err
+			}
+			i += n
+		}
+	}
+	dAtA[i] = 0x22
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.WildcardPolicy)))
+	i += copy(dAtA[i:], m.WildcardPolicy)
+	dAtA[i] = 0x2a
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.RouterCanonicalHostname)))
+	i += copy(dAtA[i:], m.RouterCanonicalHostname)
+	return i, nil
+}
+
+func (m *RouteIngressCondition) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *RouteIngressCondition) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	dAtA[i] = 0xa
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Type)))
+	i += copy(dAtA[i:], m.Type)
+	dAtA[i] = 0x12
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Status)))
+	i += copy(dAtA[i:], m.Status)
+	dAtA[i] = 0x1a
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Reason)))
+	i += copy(dAtA[i:], m.Reason)
+	dAtA[i] = 0x22
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Message)))
+	i += copy(dAtA[i:], m.Message)
+	if m.LastTransitionTime != nil {
+		dAtA[i] = 0x2a
+		i++
+		i = encodeVarintGenerated(dAtA, i, uint64(m.LastTransitionTime.Size()))
+		n4, err := m.LastTransitionTime.MarshalTo(dAtA[i:])
+		if err != nil {
+			return 0, err
+		}
+		i += n4
+	}
+	return i, nil
+}
+
+func (m *RouteList) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *RouteList) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	dAtA[i] = 0xa
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size()))
+	n5, err := m.ListMeta.MarshalTo(dAtA[i:])
+	if err != nil {
+		return 0, err
+	}
+	i += n5
+	if len(m.Items) > 0 {
+		for _, msg := range m.Items {
+			dAtA[i] = 0x12
+			i++
+			i = encodeVarintGenerated(dAtA, i, uint64(msg.Size()))
+			n, err := msg.MarshalTo(dAtA[i:])
+			if err != nil {
+				return 0, err
+			}
+			i += n
+		}
+	}
+	return i, nil
+}
+
+func (m *RoutePort) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *RoutePort) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	dAtA[i] = 0xa
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(m.TargetPort.Size()))
+	n6, err := m.TargetPort.MarshalTo(dAtA[i:])
+	if err != nil {
+		return 0, err
+	}
+	i += n6
+	return i, nil
+}
+
+func (m *RouteSpec) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *RouteSpec) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	dAtA[i] = 0xa
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Host)))
+	i += copy(dAtA[i:], m.Host)
+	dAtA[i] = 0x12
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Path)))
+	i += copy(dAtA[i:], m.Path)
+	dAtA[i] = 0x1a
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(m.To.Size()))
+	n7, err := m.To.MarshalTo(dAtA[i:])
+	if err != nil {
+		return 0, err
+	}
+	i += n7
+	if len(m.AlternateBackends) > 0 {
+		for _, msg := range m.AlternateBackends {
+			dAtA[i] = 0x22
+			i++
+			i = encodeVarintGenerated(dAtA, i, uint64(msg.Size()))
+			n, err := msg.MarshalTo(dAtA[i:])
+			if err != nil {
+				return 0, err
+			}
+			i += n
+		}
+	}
+	if m.Port != nil {
+		dAtA[i] = 0x2a
+		i++
+		i = encodeVarintGenerated(dAtA, i, uint64(m.Port.Size()))
+		n8, err := m.Port.MarshalTo(dAtA[i:])
+		if err != nil {
+			return 0, err
+		}
+		i += n8
+	}
+	if m.TLS != nil {
+		dAtA[i] = 0x32
+		i++
+		i = encodeVarintGenerated(dAtA, i, uint64(m.TLS.Size()))
+		n9, err := m.TLS.MarshalTo(dAtA[i:])
+		if err != nil {
+			return 0, err
+		}
+		i += n9
+	}
+	dAtA[i] = 0x3a
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.WildcardPolicy)))
+	i += copy(dAtA[i:], m.WildcardPolicy)
+	return i, nil
+}
+
+func (m *RouteStatus) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *RouteStatus) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	if len(m.Ingress) > 0 {
+		for _, msg := range m.Ingress {
+			dAtA[i] = 0xa
+			i++
+			i = encodeVarintGenerated(dAtA, i, uint64(msg.Size()))
+			n, err := msg.MarshalTo(dAtA[i:])
+			if err != nil {
+				return 0, err
+			}
+			i += n
+		}
+	}
+	return i, nil
+}
+
+func (m *RouteTargetReference) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *RouteTargetReference) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	dAtA[i] = 0xa
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Kind)))
+	i += copy(dAtA[i:], m.Kind)
+	dAtA[i] = 0x12
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Name)))
+	i += copy(dAtA[i:], m.Name)
+	if m.Weight != nil {
+		dAtA[i] = 0x18
+		i++
+		i = encodeVarintGenerated(dAtA, i, uint64(*m.Weight))
+	}
+	return i, nil
+}
+
+func (m *RouterShard) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *RouterShard) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	dAtA[i] = 0xa
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.ShardName)))
+	i += copy(dAtA[i:], m.ShardName)
+	dAtA[i] = 0x12
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.DNSSuffix)))
+	i += copy(dAtA[i:], m.DNSSuffix)
+	return i, nil
+}
+
+func (m *TLSConfig) Marshal() (dAtA []byte, err error) {
+	size := m.Size()
+	dAtA = make([]byte, size)
+	n, err := m.MarshalTo(dAtA)
+	if err != nil {
+		return nil, err
+	}
+	return dAtA[:n], nil
+}
+
+func (m *TLSConfig) MarshalTo(dAtA []byte) (int, error) {
+	var i int
+	_ = i
+	var l int
+	_ = l
+	dAtA[i] = 0xa
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Termination)))
+	i += copy(dAtA[i:], m.Termination)
+	dAtA[i] = 0x12
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Certificate)))
+	i += copy(dAtA[i:], m.Certificate)
+	dAtA[i] = 0x1a
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.Key)))
+	i += copy(dAtA[i:], m.Key)
+	dAtA[i] = 0x22
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.CACertificate)))
+	i += copy(dAtA[i:], m.CACertificate)
+	dAtA[i] = 0x2a
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.DestinationCACertificate)))
+	i += copy(dAtA[i:], m.DestinationCACertificate)
+	dAtA[i] = 0x32
+	i++
+	i = encodeVarintGenerated(dAtA, i, uint64(len(m.InsecureEdgeTerminationPolicy)))
+	i += copy(dAtA[i:], m.InsecureEdgeTerminationPolicy)
+	return i, nil
+}
+
+func encodeFixed64Generated(dAtA []byte, offset int, v uint64) int {
+	dAtA[offset] = uint8(v)
+	dAtA[offset+1] = uint8(v >> 8)
+	dAtA[offset+2] = uint8(v >> 16)
+	dAtA[offset+3] = uint8(v >> 24)
+	dAtA[offset+4] = uint8(v >> 32)
+	dAtA[offset+5] = uint8(v >> 40)
+	dAtA[offset+6] = uint8(v >> 48)
+	dAtA[offset+7] = uint8(v >> 56)
+	return offset + 8
+}
+func encodeFixed32Generated(dAtA []byte, offset int, v uint32) int {
+	dAtA[offset] = uint8(v)
+	dAtA[offset+1] = uint8(v >> 8)
+	dAtA[offset+2] = uint8(v >> 16)
+	dAtA[offset+3] = uint8(v >> 24)
+	return offset + 4
+}
+func encodeVarintGenerated(dAtA []byte, offset int, v uint64) int {
+	for v >= 1<<7 {
+		dAtA[offset] = uint8(v&0x7f | 0x80)
+		v >>= 7
+		offset++
+	}
+	dAtA[offset] = uint8(v)
+	return offset + 1
+}
+func (m *Route) Size() (n int) {
+	var l int
+	_ = l
+	l = m.ObjectMeta.Size()
+	n += 1 + l + sovGenerated(uint64(l))
+	l = m.Spec.Size()
+	n += 1 + l + sovGenerated(uint64(l))
+	l = m.Status.Size()
+	n += 1 + l + sovGenerated(uint64(l))
+	return n
+}
+
+func (m *RouteIngress) Size() (n int) {
+	var l int
+	_ = l
+	l = len(m.Host)
+	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.RouterName)
+	n += 1 + l + sovGenerated(uint64(l))
+	if len(m.Conditions) > 0 {
+		for _, e := range m.Conditions {
+			l = e.Size()
+			n += 1 + l + sovGenerated(uint64(l))
+		}
+	}
+	l = len(m.WildcardPolicy)
+	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.RouterCanonicalHostname)
+	n += 1 + l + sovGenerated(uint64(l))
+	return n
+}
+
+func (m *RouteIngressCondition) Size() (n int) {
+	var l int
+	_ = l
+	l = len(m.Type)
+	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.Status)
+	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.Reason)
+	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.Message)
+	n += 1 + l + sovGenerated(uint64(l))
+	if m.LastTransitionTime != nil {
+		l = m.LastTransitionTime.Size()
+		n += 1 + l + sovGenerated(uint64(l))
+	}
+	return n
+}
+
+func (m *RouteList) Size() (n int) {
+	var l int
+	_ = l
+	l = m.ListMeta.Size()
+	n += 1 + l + sovGenerated(uint64(l))
+	if len(m.Items) > 0 {
+		for _, e := range m.Items {
+			l = e.Size()
+			n += 1 + l + sovGenerated(uint64(l))
+		}
+	}
+	return n
+}
+
+func (m *RoutePort) Size() (n int) {
+	var l int
+	_ = l
+	l = m.TargetPort.Size()
+	n += 1 + l + sovGenerated(uint64(l))
+	return n
+}
+
+func (m *RouteSpec) Size() (n int) {
+	var l int
+	_ = l
+	l = len(m.Host)
+	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.Path)
+	n += 1 + l + sovGenerated(uint64(l))
+	l = m.To.Size()
+	n += 1 + l + sovGenerated(uint64(l))
+	if len(m.AlternateBackends) > 0 {
+		for _, e := range m.AlternateBackends {
+			l = e.Size()
+			n += 1 + l + sovGenerated(uint64(l))
+		}
+	}
+	if m.Port != nil {
+		l = m.Port.Size()
+		n += 1 + l + sovGenerated(uint64(l))
+	}
+	if m.TLS != nil {
+		l = m.TLS.Size()
+		n += 1 + l + sovGenerated(uint64(l))
+	}
+	l = len(m.WildcardPolicy)
+	n += 1 + l + sovGenerated(uint64(l))
+	return n
+}
+
+func (m *RouteStatus) Size() (n int) {
+	var l int
+	_ = l
+	if len(m.Ingress) > 0 {
+		for _, e := range m.Ingress {
+			l = e.Size()
+			n += 1 + l + sovGenerated(uint64(l))
+		}
+	}
+	return n
+}
+
+func (m *RouteTargetReference) Size() (n int) {
+	var l int
+	_ = l
+	l = len(m.Kind)
+	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.Name)
+	n += 1 + l + sovGenerated(uint64(l))
+	if m.Weight != nil {
+		n += 1 + sovGenerated(uint64(*m.Weight))
+	}
+	return n
+}
+
+func (m *RouterShard) Size() (n int) {
+	var l int
+	_ = l
+	l = len(m.ShardName)
+	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.DNSSuffix)
+	n += 1 + l + sovGenerated(uint64(l))
+	return n
+}
+
+func (m *TLSConfig) Size() (n int) {
+	var l int
+	_ = l
+	l = len(m.Termination)
+	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.Certificate)
+	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.Key)
+	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.CACertificate)
+	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.DestinationCACertificate)
+	n += 1 + l + sovGenerated(uint64(l))
+	l = len(m.InsecureEdgeTerminationPolicy)
+	n += 1 + l + sovGenerated(uint64(l))
+	return n
+}
+
+func sovGenerated(x uint64) (n int) {
+	for {
+		n++
+		x >>= 7
+		if x == 0 {
+			break
+		}
+	}
+	return n
+}
+func sozGenerated(x uint64) (n int) {
+	return sovGenerated(uint64((x << 1) ^ uint64((int64(x) >> 63))))
+}
+func (this *Route) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&Route{`,
+		`ObjectMeta:` + strings.Replace(strings.Replace(this.ObjectMeta.String(), "ObjectMeta", "k8s_io_apimachinery_pkg_apis_meta_v1.ObjectMeta", 1), `&`, ``, 1) + `,`,
+		`Spec:` + strings.Replace(strings.Replace(this.Spec.String(), "RouteSpec", "RouteSpec", 1), `&`, ``, 1) + `,`,
+		`Status:` + strings.Replace(strings.Replace(this.Status.String(), "RouteStatus", "RouteStatus", 1), `&`, ``, 1) + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func (this *RouteIngress) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&RouteIngress{`,
+		`Host:` + fmt.Sprintf("%v", this.Host) + `,`,
+		`RouterName:` + fmt.Sprintf("%v", this.RouterName) + `,`,
+		`Conditions:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Conditions), "RouteIngressCondition", "RouteIngressCondition", 1), `&`, ``, 1) + `,`,
+		`WildcardPolicy:` + fmt.Sprintf("%v", this.WildcardPolicy) + `,`,
+		`RouterCanonicalHostname:` + fmt.Sprintf("%v", this.RouterCanonicalHostname) + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func (this *RouteIngressCondition) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&RouteIngressCondition{`,
+		`Type:` + fmt.Sprintf("%v", this.Type) + `,`,
+		`Status:` + fmt.Sprintf("%v", this.Status) + `,`,
+		`Reason:` + fmt.Sprintf("%v", this.Reason) + `,`,
+		`Message:` + fmt.Sprintf("%v", this.Message) + `,`,
+		`LastTransitionTime:` + strings.Replace(fmt.Sprintf("%v", this.LastTransitionTime), "Time", "k8s_io_apimachinery_pkg_apis_meta_v1.Time", 1) + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func (this *RouteList) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&RouteList{`,
+		`ListMeta:` + strings.Replace(strings.Replace(this.ListMeta.String(), "ListMeta", "k8s_io_apimachinery_pkg_apis_meta_v1.ListMeta", 1), `&`, ``, 1) + `,`,
+		`Items:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Items), "Route", "Route", 1), `&`, ``, 1) + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func (this *RoutePort) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&RoutePort{`,
+		`TargetPort:` + strings.Replace(strings.Replace(this.TargetPort.String(), "IntOrString", "k8s_io_apimachinery_pkg_util_intstr.IntOrString", 1), `&`, ``, 1) + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func (this *RouteSpec) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&RouteSpec{`,
+		`Host:` + fmt.Sprintf("%v", this.Host) + `,`,
+		`Path:` + fmt.Sprintf("%v", this.Path) + `,`,
+		`To:` + strings.Replace(strings.Replace(this.To.String(), "RouteTargetReference", "RouteTargetReference", 1), `&`, ``, 1) + `,`,
+		`AlternateBackends:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.AlternateBackends), "RouteTargetReference", "RouteTargetReference", 1), `&`, ``, 1) + `,`,
+		`Port:` + strings.Replace(fmt.Sprintf("%v", this.Port), "RoutePort", "RoutePort", 1) + `,`,
+		`TLS:` + strings.Replace(fmt.Sprintf("%v", this.TLS), "TLSConfig", "TLSConfig", 1) + `,`,
+		`WildcardPolicy:` + fmt.Sprintf("%v", this.WildcardPolicy) + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func (this *RouteStatus) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&RouteStatus{`,
+		`Ingress:` + strings.Replace(strings.Replace(fmt.Sprintf("%v", this.Ingress), "RouteIngress", "RouteIngress", 1), `&`, ``, 1) + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func (this *RouteTargetReference) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&RouteTargetReference{`,
+		`Kind:` + fmt.Sprintf("%v", this.Kind) + `,`,
+		`Name:` + fmt.Sprintf("%v", this.Name) + `,`,
+		`Weight:` + valueToStringGenerated(this.Weight) + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func (this *RouterShard) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&RouterShard{`,
+		`ShardName:` + fmt.Sprintf("%v", this.ShardName) + `,`,
+		`DNSSuffix:` + fmt.Sprintf("%v", this.DNSSuffix) + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func (this *TLSConfig) String() string {
+	if this == nil {
+		return "nil"
+	}
+	s := strings.Join([]string{`&TLSConfig{`,
+		`Termination:` + fmt.Sprintf("%v", this.Termination) + `,`,
+		`Certificate:` + fmt.Sprintf("%v", this.Certificate) + `,`,
+		`Key:` + fmt.Sprintf("%v", this.Key) + `,`,
+		`CACertificate:` + fmt.Sprintf("%v", this.CACertificate) + `,`,
+		`DestinationCACertificate:` + fmt.Sprintf("%v", this.DestinationCACertificate) + `,`,
+		`InsecureEdgeTerminationPolicy:` + fmt.Sprintf("%v", this.InsecureEdgeTerminationPolicy) + `,`,
+		`}`,
+	}, "")
+	return s
+}
+func valueToStringGenerated(v interface{}) string {
+	rv := reflect.ValueOf(v)
+	if rv.IsNil() {
+		return "nil"
+	}
+	pv := reflect.Indirect(rv).Interface()
+	return fmt.Sprintf("*%v", pv)
+}
+func (m *Route) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGenerated
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: Route: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: Route: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ObjectMeta", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.ObjectMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Spec", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Spec.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.Status.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGenerated(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *RouteIngress) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGenerated
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: RouteIngress: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: RouteIngress: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Host", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Host = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field RouterName", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.RouterName = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Conditions", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Conditions = append(m.Conditions, RouteIngressCondition{})
+			if err := m.Conditions[len(m.Conditions)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field WildcardPolicy", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.WildcardPolicy = WildcardPolicyType(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field RouterCanonicalHostname", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.RouterCanonicalHostname = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGenerated(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *RouteIngressCondition) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGenerated
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: RouteIngressCondition: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: RouteIngressCondition: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Type", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Type = RouteIngressConditionType(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Status = k8s_io_api_core_v1.ConditionStatus(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Reason", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Reason = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Message = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field LastTransitionTime", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.LastTransitionTime == nil {
+				m.LastTransitionTime = &k8s_io_apimachinery_pkg_apis_meta_v1.Time{}
+			}
+			if err := m.LastTransitionTime.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGenerated(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *RouteList) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGenerated
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: RouteList: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: RouteList: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ListMeta", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.ListMeta.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Items = append(m.Items, Route{})
+			if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGenerated(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *RoutePort) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGenerated
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: RoutePort: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: RoutePort: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TargetPort", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.TargetPort.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGenerated(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *RouteSpec) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGenerated
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: RouteSpec: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: RouteSpec: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Host", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Host = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Path = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field To", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if err := m.To.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field AlternateBackends", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.AlternateBackends = append(m.AlternateBackends, RouteTargetReference{})
+			if err := m.AlternateBackends[len(m.AlternateBackends)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Port", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.Port == nil {
+				m.Port = &RoutePort{}
+			}
+			if err := m.Port.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 6:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field TLS", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			if m.TLS == nil {
+				m.TLS = &TLSConfig{}
+			}
+			if err := m.TLS.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		case 7:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field WildcardPolicy", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.WildcardPolicy = WildcardPolicyType(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGenerated(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *RouteStatus) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGenerated
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: RouteStatus: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: RouteStatus: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Ingress", wireType)
+			}
+			var msglen int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				msglen |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			if msglen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + msglen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Ingress = append(m.Ingress, RouteIngress{})
+			if err := m.Ingress[len(m.Ingress)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
+				return err
+			}
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGenerated(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *RouteTargetReference) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGenerated
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: RouteTargetReference: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: RouteTargetReference: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Kind", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Kind = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Name", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Name = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 3:
+			if wireType != 0 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Weight", wireType)
+			}
+			var v int32
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				v |= (int32(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			m.Weight = &v
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGenerated(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *RouterShard) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGenerated
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: RouterShard: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: RouterShard: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field ShardName", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.ShardName = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field DNSSuffix", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.DNSSuffix = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGenerated(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func (m *TLSConfig) Unmarshal(dAtA []byte) error {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		preIndex := iNdEx
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return ErrIntOverflowGenerated
+			}
+			if iNdEx >= l {
+				return io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		fieldNum := int32(wire >> 3)
+		wireType := int(wire & 0x7)
+		if wireType == 4 {
+			return fmt.Errorf("proto: TLSConfig: wiretype end group for non-group")
+		}
+		if fieldNum <= 0 {
+			return fmt.Errorf("proto: TLSConfig: illegal tag %d (wire type %d)", fieldNum, wire)
+		}
+		switch fieldNum {
+		case 1:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Termination", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Termination = TLSTerminationType(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 2:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Certificate", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Certificate = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 3:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field Key", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.Key = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 4:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field CACertificate", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.CACertificate = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 5:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field DestinationCACertificate", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.DestinationCACertificate = string(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		case 6:
+			if wireType != 2 {
+				return fmt.Errorf("proto: wrong wireType = %d for field InsecureEdgeTerminationPolicy", wireType)
+			}
+			var stringLen uint64
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				stringLen |= (uint64(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			intStringLen := int(stringLen)
+			if intStringLen < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			postIndex := iNdEx + intStringLen
+			if postIndex > l {
+				return io.ErrUnexpectedEOF
+			}
+			m.InsecureEdgeTerminationPolicy = InsecureEdgeTerminationPolicyType(dAtA[iNdEx:postIndex])
+			iNdEx = postIndex
+		default:
+			iNdEx = preIndex
+			skippy, err := skipGenerated(dAtA[iNdEx:])
+			if err != nil {
+				return err
+			}
+			if skippy < 0 {
+				return ErrInvalidLengthGenerated
+			}
+			if (iNdEx + skippy) > l {
+				return io.ErrUnexpectedEOF
+			}
+			iNdEx += skippy
+		}
+	}
+
+	if iNdEx > l {
+		return io.ErrUnexpectedEOF
+	}
+	return nil
+}
+func skipGenerated(dAtA []byte) (n int, err error) {
+	l := len(dAtA)
+	iNdEx := 0
+	for iNdEx < l {
+		var wire uint64
+		for shift := uint(0); ; shift += 7 {
+			if shift >= 64 {
+				return 0, ErrIntOverflowGenerated
+			}
+			if iNdEx >= l {
+				return 0, io.ErrUnexpectedEOF
+			}
+			b := dAtA[iNdEx]
+			iNdEx++
+			wire |= (uint64(b) & 0x7F) << shift
+			if b < 0x80 {
+				break
+			}
+		}
+		wireType := int(wire & 0x7)
+		switch wireType {
+		case 0:
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				iNdEx++
+				if dAtA[iNdEx-1] < 0x80 {
+					break
+				}
+			}
+			return iNdEx, nil
+		case 1:
+			iNdEx += 8
+			return iNdEx, nil
+		case 2:
+			var length int
+			for shift := uint(0); ; shift += 7 {
+				if shift >= 64 {
+					return 0, ErrIntOverflowGenerated
+				}
+				if iNdEx >= l {
+					return 0, io.ErrUnexpectedEOF
+				}
+				b := dAtA[iNdEx]
+				iNdEx++
+				length |= (int(b) & 0x7F) << shift
+				if b < 0x80 {
+					break
+				}
+			}
+			iNdEx += length
+			if length < 0 {
+				return 0, ErrInvalidLengthGenerated
+			}
+			return iNdEx, nil
+		case 3:
+			for {
+				var innerWire uint64
+				var start int = iNdEx
+				for shift := uint(0); ; shift += 7 {
+					if shift >= 64 {
+						return 0, ErrIntOverflowGenerated
+					}
+					if iNdEx >= l {
+						return 0, io.ErrUnexpectedEOF
+					}
+					b := dAtA[iNdEx]
+					iNdEx++
+					innerWire |= (uint64(b) & 0x7F) << shift
+					if b < 0x80 {
+						break
+					}
+				}
+				innerWireType := int(innerWire & 0x7)
+				if innerWireType == 4 {
+					break
+				}
+				next, err := skipGenerated(dAtA[start:])
+				if err != nil {
+					return 0, err
+				}
+				iNdEx = start + next
+			}
+			return iNdEx, nil
+		case 4:
+			return iNdEx, nil
+		case 5:
+			iNdEx += 4
+			return iNdEx, nil
+		default:
+			return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
+		}
+	}
+	panic("unreachable")
+}
+
+var (
+	ErrInvalidLengthGenerated = fmt.Errorf("proto: negative length found during unmarshaling")
+	ErrIntOverflowGenerated   = fmt.Errorf("proto: integer overflow")
+)
+
+func init() {
+	proto.RegisterFile("github.com/openshift/api/route/v1/generated.proto", fileDescriptorGenerated)
+}
+
+var fileDescriptorGenerated = []byte{
+	// 1150 bytes of a gzipped FileDescriptorProto
+	0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x55, 0x4f, 0x6f, 0x1b, 0x45,
+	0x14, 0x8f, 0xff, 0x26, 0x1e, 0x37, 0x81, 0x0c, 0x94, 0xba, 0x91, 0x62, 0xa7, 0x7b, 0x40, 0x29,
+	0x2a, 0xbb, 0x24, 0x14, 0xa8, 0x84, 0x38, 0xd4, 0x29, 0x82, 0x34, 0x4e, 0x1a, 0x8d, 0x2d, 0x2a,
+	0xaa, 0x1e, 0x98, 0xec, 0x8e, 0xd7, 0x83, 0xed, 0xd9, 0x65, 0x66, 0x9c, 0xe2, 0x0b, 0xaa, 0xc4,
+	0x17, 0x28, 0x7c, 0x1a, 0x3e, 0x42, 0x8e, 0x3d, 0xf6, 0x80, 0x2c, 0x62, 0x8e, 0x7c, 0x83, 0x9c,
+	0xd0, 0xcc, 0x8e, 0x77, 0xd7, 0x89, 0x93, 0xb8, 0x70, 0xf3, 0xbe, 0xf7, 0xfb, 0xfd, 0xde, 0x9b,
+	0x37, 0xcf, 0xbf, 0x01, 0x5b, 0x3e, 0x95, 0x9d, 0xc1, 0x91, 0xed, 0x06, 0x7d, 0x27, 0x08, 0x09,
+	0x13, 0x1d, 0xda, 0x96, 0x0e, 0x0e, 0xa9, 0xc3, 0x83, 0x81, 0x24, 0xce, 0xf1, 0x96, 0xe3, 0x13,
+	0x46, 0x38, 0x96, 0xc4, 0xb3, 0x43, 0x1e, 0xc8, 0x00, 0xde, 0x49, 0x28, 0x76, 0x4c, 0xb1, 0x71,
+	0x48, 0x6d, 0x4d, 0xb1, 0x8f, 0xb7, 0xd6, 0x3e, 0x4e, 0xa9, 0xfa, 0x81, 0x1f, 0x38, 0x9a, 0x79,
+	0x34, 0x68, 0xeb, 0x2f, 0xfd, 0xa1, 0x7f, 0x45, 0x8a, 0x6b, 0x56, 0xf7, 0x81, 0xb0, 0x69, 0xa0,
+	0xcb, 0xba, 0x01, 0x9f, 0x55, 0x75, 0xed, 0x7e, 0x82, 0xe9, 0x63, 0xb7, 0x43, 0x19, 0xe1, 0x43,
+	0x27, 0xec, 0xfa, 0x2a, 0x20, 0x9c, 0x3e, 0x91, 0x78, 0x16, 0xcb, 0xb9, 0x8c, 0xc5, 0x07, 0x4c,
+	0xd2, 0x3e, 0xb9, 0x40, 0xf8, 0xfc, 0x3a, 0x82, 0x70, 0x3b, 0xa4, 0x8f, 0x2f, 0xf0, 0x3e, 0xbd,
+	0x8c, 0x37, 0x90, 0xb4, 0xe7, 0x50, 0x26, 0x85, 0xe4, 0xe7, 0x49, 0xd6, 0x6f, 0x59, 0x50, 0x40,
+	0x6a, 0x66, 0xf0, 0x07, 0xb0, 0xa4, 0x8e, 0xe0, 0x61, 0x89, 0x2b, 0x99, 0x8d, 0xcc, 0x66, 0x79,
+	0xfb, 0x13, 0x3b, 0x52, 0xb4, 0xd3, 0x8a, 0x76, 0xd8, 0xf5, 0x55, 0x40, 0xd8, 0x0a, 0x6d, 0x1f,
+	0x6f, 0xd9, 0x4f, 0x8e, 0x7e, 0x24, 0xae, 0xdc, 0x27, 0x12, 0xd7, 0xe1, 0xc9, 0xa8, 0xb6, 0x30,
+	0x1e, 0xd5, 0x40, 0x12, 0x43, 0xb1, 0x2a, 0x3c, 0x00, 0x79, 0x11, 0x12, 0xb7, 0x92, 0xd5, 0xea,
+	0xf7, 0xec, 0x6b, 0x2f, 0xd1, 0xd6, 0x9d, 0x35, 0x43, 0xe2, 0xd6, 0x6f, 0x18, 0xe5, 0xbc, 0xfa,
+	0x42, 0x5a, 0x07, 0x7e, 0x07, 0x8a, 0x42, 0x62, 0x39, 0x10, 0x95, 0x9c, 0x56, 0xb4, 0xe7, 0x56,
+	0xd4, 0xac, 0xfa, 0x8a, 0xd1, 0x2c, 0x46, 0xdf, 0xc8, 0xa8, 0x59, 0xbf, 0xe6, 0xc0, 0x0d, 0x8d,
+	0xdb, 0x65, 0x3e, 0x27, 0x42, 0xc0, 0x0d, 0x90, 0xef, 0x04, 0x42, 0xea, 0xb1, 0x94, 0x92, 0x56,
+	0xbe, 0x0d, 0x84, 0x44, 0x3a, 0x03, 0xb7, 0x01, 0xd0, 0x25, 0xf8, 0x01, 0xee, 0x13, 0x7d, 0xc0,
+	0x52, 0x32, 0x0c, 0x14, 0x67, 0x50, 0x0a, 0x05, 0x7b, 0x00, 0xb8, 0x01, 0xf3, 0xa8, 0xa4, 0x01,
+	0x53, 0x47, 0xc8, 0x6d, 0x96, 0xb7, 0x1f, 0xcc, 0x7b, 0x04, 0xd3, 0xda, 0xce, 0x44, 0x20, 0xa9,
+	0x16, 0x87, 0x04, 0x4a, 0xe9, 0xc3, 0x16, 0x58, 0x79, 0x41, 0x7b, 0x9e, 0x8b, 0xb9, 0x77, 0x18,
+	0xf4, 0xa8, 0x3b, 0xac, 0xe4, 0x75, 0x97, 0xf7, 0x0c, 0x6f, 0xe5, 0xe9, 0x54, 0xf6, 0x6c, 0x54,
+	0x83, 0xd3, 0x91, 0xd6, 0x30, 0x24, 0xe8, 0x9c, 0x06, 0xfc, 0x1e, 0xdc, 0x8a, 0x4e, 0xb4, 0x83,
+	0x59, 0xc0, 0xa8, 0x8b, 0x7b, 0x6a, 0x28, 0x4c, 0x0d, 0xa1, 0xa0, 0xe5, 0x6b, 0x46, 0xfe, 0x16,
+	0x9a, 0x0d, 0x43, 0x97, 0xf1, 0xad, 0x7f, 0xb2, 0xe0, 0xe6, 0xcc, 0xa3, 0xc2, 0xaf, 0x40, 0x5e,
+	0x0e, 0x43, 0x62, 0xae, 0xe3, 0xee, 0xe4, 0x3a, 0x54, 0x83, 0x67, 0xa3, 0xda, 0xed, 0x99, 0x24,
+	0xdd, 0xbd, 0xa6, 0xc1, 0x46, 0xbc, 0x36, 0xd1, 0x3d, 0xdd, 0x9f, 0x5e, 0x83, 0xb3, 0x51, 0x6d,
+	0x86, 0x19, 0xd8, 0xb1, 0xd2, 0xf4, 0xb2, 0xc0, 0x0f, 0x41, 0x91, 0x13, 0x2c, 0x02, 0xa6, 0x97,
+	0xb0, 0x94, 0x2c, 0x15, 0xd2, 0x51, 0x64, 0xb2, 0xf0, 0x2e, 0x58, 0xec, 0x13, 0x21, 0xb0, 0x4f,
+	0xcc, 0xe0, 0xdf, 0x31, 0xc0, 0xc5, 0xfd, 0x28, 0x8c, 0x26, 0x79, 0xc8, 0x01, 0xec, 0x61, 0x21,
+	0x5b, 0x1c, 0x33, 0x11, 0x35, 0x4f, 0xcd, 0x3c, 0xcb, 0xdb, 0x1f, 0xcd, 0xf7, 0x9f, 0x54, 0x8c,
+	0xfa, 0x07, 0xe3, 0x51, 0x0d, 0x36, 0x2e, 0x28, 0xa1, 0x19, 0xea, 0xd6, 0x1f, 0x19, 0x50, 0xd2,
+	0x83, 0x6b, 0x50, 0x21, 0xe1, 0xf3, 0x0b, 0x5e, 0x60, 0xcf, 0x57, 0x57, 0xb1, 0xb5, 0x13, 0xbc,
+	0x6b, 0x4e, 0xb7, 0x34, 0x89, 0xa4, 0x7c, 0x60, 0x1f, 0x14, 0xa8, 0x24, 0x7d, 0x35, 0x7f, 0xb5,
+	0xf3, 0x9b, 0xf3, 0xee, 0x7c, 0x7d, 0xd9, 0x88, 0x16, 0x76, 0x15, 0x1d, 0x45, 0x2a, 0xd6, 0x4f,
+	0xa6, 0xf3, 0xc3, 0x80, 0x4b, 0xe8, 0x01, 0x20, 0x31, 0xf7, 0x89, 0x54, 0x5f, 0xd7, 0xfa, 0x98,
+	0x72, 0x46, 0x3b, 0x72, 0x46, 0x7b, 0x97, 0xc9, 0x27, 0xbc, 0x29, 0x39, 0x65, 0x7e, 0xf2, 0x67,
+	0x6a, 0xc5, 0x5a, 0x28, 0xa5, 0x6b, 0xfd, 0x9e, 0x37, 0x35, 0x95, 0x1b, 0xcd, 0x61, 0x0f, 0x1b,
+	0x20, 0x1f, 0x62, 0xd9, 0x31, 0x0b, 0x17, 0x23, 0x0e, 0xb1, 0xec, 0x20, 0x9d, 0x81, 0x4d, 0x90,
+	0x95, 0x81, 0xf1, 0xb1, 0x2f, 0xe6, 0x1d, 0x48, 0xd4, 0x1d, 0x22, 0x6d, 0xc2, 0x09, 0x73, 0x49,
+	0x1d, 0x18, 0xe1, 0x6c, 0x2b, 0x40, 0x59, 0x19, 0xc0, 0x97, 0x19, 0xb0, 0x8a, 0x7b, 0x92, 0x70,
+	0x86, 0x25, 0xa9, 0x63, 0xb7, 0x4b, 0x98, 0x27, 0x2a, 0x79, 0x3d, 0xf5, 0xff, 0x5c, 0xe4, 0xb6,
+	0x29, 0xb2, 0xfa, 0xf0, 0xbc, 0x32, 0xba, 0x58, 0x0c, 0x3e, 0x06, 0xf9, 0x50, 0xdd, 0x44, 0xe1,
+	0xed, 0x3c, 0x5f, 0x4d, 0xb9, 0xbe, 0xa4, 0x67, 0xa4, 0x66, 0xaf, 0x35, 0xe0, 0x37, 0x20, 0x27,
+	0x7b, 0xa2, 0x52, 0x9c, 0x5b, 0xaa, 0xd5, 0x68, 0xee, 0x04, 0xac, 0x4d, 0xfd, 0xfa, 0xe2, 0x78,
+	0x54, 0xcb, 0xb5, 0x1a, 0x4d, 0xa4, 0x14, 0x66, 0x78, 0xe1, 0xe2, 0xff, 0xf7, 0x42, 0x8b, 0x82,
+	0x72, 0xea, 0x75, 0x81, 0xcf, 0xc0, 0x22, 0x8d, 0x4c, 0xa8, 0x92, 0xd1, 0x13, 0x77, 0xde, 0xd2,
+	0xdb, 0x13, 0x87, 0x30, 0x01, 0x34, 0x11, 0xb4, 0x7e, 0x01, 0xef, 0xcf, 0xba, 0x1b, 0xb5, 0x67,
+	0x5d, 0xca, 0xbc, 0xf3, 0x9b, 0xb8, 0x47, 0x99, 0x87, 0x74, 0x46, 0x21, 0x58, 0xf2, 0x44, 0xc5,
+	0x08, 0xfd, 0x38, 0xe9, 0x0c, 0xb4, 0x40, 0xf1, 0x05, 0xa1, 0x7e, 0x47, 0xea, 0x6d, 0x2c, 0xd4,
+	0x81, 0x32, 0xb3, 0xa7, 0x3a, 0x82, 0x4c, 0xc6, 0x0a, 0xcc, 0x51, 0x79, 0xb3, 0x83, 0xb9, 0x07,
+	0x1d, 0x50, 0x12, 0xea, 0x87, 0x7e, 0xfc, 0xa2, 0xda, 0xab, 0x46, 0xb9, 0xd4, 0x9c, 0x24, 0x50,
+	0x82, 0x51, 0x04, 0x8f, 0x89, 0xe6, 0xa0, 0xdd, 0xa6, 0x3f, 0x9b, 0x56, 0x62, 0xc2, 0xa3, 0x83,
+	0x66, 0x94, 0x40, 0x09, 0xc6, 0xfa, 0x33, 0x07, 0x4a, 0xf1, 0x6d, 0xc2, 0x3d, 0x50, 0x96, 0x84,
+	0xf7, 0x29, 0xc3, 0xca, 0xbf, 0xce, 0xbd, 0x03, 0xe5, 0x56, 0x92, 0x52, 0x37, 0xd7, 0x6a, 0x34,
+	0x53, 0x11, 0x7d, 0x73, 0x69, 0x36, 0xfc, 0x0c, 0x94, 0x5d, 0xc2, 0x25, 0x6d, 0x53, 0x17, 0xcb,
+	0xc9, 0x60, 0xde, 0x9b, 0x88, 0xed, 0x24, 0x29, 0x94, 0xc6, 0xc1, 0x75, 0x90, 0xeb, 0x92, 0xa1,
+	0x31, 0xfd, 0xb2, 0x81, 0xe7, 0xf6, 0xc8, 0x10, 0xa9, 0x38, 0xfc, 0x12, 0x2c, 0xbb, 0x38, 0x45,
+	0x36, 0xa6, 0x7f, 0xd3, 0x00, 0x97, 0x77, 0x1e, 0xa6, 0x95, 0xa7, 0xb1, 0xf0, 0x39, 0xa8, 0x78,
+	0x44, 0x48, 0xd3, 0xe1, 0x14, 0xd4, 0x3c, 0xab, 0x1b, 0x46, 0xa7, 0xf2, 0xe8, 0x12, 0x1c, 0xba,
+	0x54, 0x01, 0xbe, 0xca, 0x80, 0x75, 0xca, 0x04, 0x71, 0x07, 0x9c, 0x7c, 0xed, 0xf9, 0x24, 0x35,
+	0x1d, 0xf3, 0x6f, 0x28, 0xea, 0x1a, 0x8f, 0x4d, 0x8d, 0xf5, 0xdd, 0xab, 0xc0, 0x67, 0xa3, 0xda,
+	0x9d, 0x2b, 0x01, 0x7a, 0xe2, 0x57, 0x17, 0xac, 0x6f, 0x9e, 0x9c, 0x56, 0x17, 0x5e, 0x9f, 0x56,
+	0x17, 0xde, 0x9c, 0x56, 0x17, 0x5e, 0x8e, 0xab, 0x99, 0x93, 0x71, 0x35, 0xf3, 0x7a, 0x5c, 0xcd,
+	0xbc, 0x19, 0x57, 0x33, 0x7f, 0x8d, 0xab, 0x99, 0x57, 0x7f, 0x57, 0x17, 0x9e, 0x65, 0x8f, 0xb7,
+	0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xcd, 0xbc, 0x55, 0xbd, 0x2d, 0x0c, 0x00, 0x00,
+}
diff --git a/vendor/github.com/openshift/api/route/v1/generated.proto b/vendor/github.com/openshift/api/route/v1/generated.proto
new file mode 100644
index 00000000..73d0e1a6
--- /dev/null
+++ b/vendor/github.com/openshift/api/route/v1/generated.proto
@@ -0,0 +1,217 @@
+
+// This file was autogenerated by go-to-protobuf. Do not edit it manually!
+
+syntax = 'proto2';
+
+package github.com.openshift.api.route.v1;
+
+import "k8s.io/api/core/v1/generated.proto";
+import "k8s.io/apimachinery/pkg/apis/meta/v1/generated.proto";
+import "k8s.io/apimachinery/pkg/runtime/generated.proto";
+import "k8s.io/apimachinery/pkg/runtime/schema/generated.proto";
+import "k8s.io/apimachinery/pkg/util/intstr/generated.proto";
+
+// Package-wide variables from generator "generated".
+option go_package = "v1";
+
+// A route allows developers to expose services through an HTTP(S) aware load balancing and proxy
+// layer via a public DNS entry. The route may further specify TLS options and a certificate, or
+// specify a public CNAME that the router should also accept for HTTP and HTTPS traffic. An
+// administrator typically configures their router to be visible outside the cluster firewall, and
+// may also add additional security, caching, or traffic controls on the service content. Routers
+// usually talk directly to the service endpoints.
+// 
+// Once a route is created, the `host` field may not be changed. Generally, routers use the oldest
+// route with a given host when resolving conflicts.
+// 
+// Routers are subject to additional customization and may support additional controls via the
+// annotations field.
+// 
+// Because administrators may configure multiple routers, the route status field is used to
+// return information to clients about the names and states of the route under each router.
+// If a client chooses a duplicate name, for instance, the route status conditions are used
+// to indicate the route cannot be chosen.
+message Route {
+  // Standard object metadata.
+  optional k8s.io.apimachinery.pkg.apis.meta.v1.ObjectMeta metadata = 1;
+
+  // spec is the desired state of the route
+  optional RouteSpec spec = 2;
+
+  // status is the current state of the route
+  optional RouteStatus status = 3;
+}
+
+// RouteIngress holds information about the places where a route is exposed.
+message RouteIngress {
+  // Host is the host string under which the route is exposed; this value is required
+  optional string host = 1;
+
+  // Name is a name chosen by the router to identify itself; this value is required
+  optional string routerName = 2;
+
+  // Conditions is the state of the route, may be empty.
+  repeated RouteIngressCondition conditions = 3;
+
+  // Wildcard policy is the wildcard policy that was allowed where this route is exposed.
+  optional string wildcardPolicy = 4;
+
+  // CanonicalHostname is the external host name for the router that can be used as a CNAME
+  // for the host requested for this route. This value is optional and may not be set in all cases.
+  optional string routerCanonicalHostname = 5;
+}
+
+// RouteIngressCondition contains details for the current condition of this route on a particular
+// router.
+message RouteIngressCondition {
+  // Type is the type of the condition.
+  // Currently only Ready.
+  optional string type = 1;
+
+  // Status is the status of the condition.
+  // Can be True, False, Unknown.
+  optional string status = 2;
+
+  // (brief) reason for the condition's last transition, and is usually a machine and human
+  // readable constant
+  optional string reason = 3;
+
+  // Human readable message indicating details about last transition.
+  optional string message = 4;
+
+  // RFC 3339 date and time when this condition last transitioned
+  optional k8s.io.apimachinery.pkg.apis.meta.v1.Time lastTransitionTime = 5;
+}
+
+// RouteList is a collection of Routes.
+message RouteList {
+  // Standard object metadata.
+  optional k8s.io.apimachinery.pkg.apis.meta.v1.ListMeta metadata = 1;
+
+  // items is a list of routes
+  repeated Route items = 2;
+}
+
+// RoutePort defines a port mapping from a router to an endpoint in the service endpoints.
+message RoutePort {
+  // The target port on pods selected by the service this route points to.
+  // If this is a string, it will be looked up as a named port in the target
+  // endpoints port list. Required
+  optional k8s.io.apimachinery.pkg.util.intstr.IntOrString targetPort = 1;
+}
+
+// RouteSpec describes the hostname or path the route exposes, any security information,
+// and one to four backends (services) the route points to. Requests are distributed
+// among the backends depending on the weights assigned to each backend. When using
+// roundrobin scheduling the portion of requests that go to each backend is the backend
+// weight divided by the sum of all of the backend weights. When the backend has more than
+// one endpoint the requests that end up on the backend are roundrobin distributed among
+// the endpoints. Weights are between 0 and 256 with default 1. Weight 0 causes no requests
+// to the backend. If all weights are zero the route will be considered to have no backends
+// and return a standard 503 response.
+// 
+// The `tls` field is optional and allows specific certificates or behavior for the
+// route. Routers typically configure a default certificate on a wildcard domain to
+// terminate routes without explicit certificates, but custom hostnames usually must
+// choose passthrough (send traffic directly to the backend via the TLS Server-Name-
+// Indication field) or provide a certificate.
+message RouteSpec {
+  // host is an alias/DNS that points to the service. Optional.
+  // If not specified a route name will typically be automatically
+  // chosen.
+  // Must follow DNS952 subdomain conventions.
+  optional string host = 1;
+
+  // Path that the router watches for, to route traffic for to the service. Optional
+  optional string path = 2;
+
+  // to is an object the route should use as the primary backend. Only the Service kind
+  // is allowed, and it will be defaulted to Service. If the weight field (0-256 default 1)
+  // is set to zero, no traffic will be sent to this backend.
+  optional RouteTargetReference to = 3;
+
+  // alternateBackends allows up to 3 additional backends to be assigned to the route.
+  // Only the Service kind is allowed, and it will be defaulted to Service.
+  // Use the weight field in RouteTargetReference object to specify relative preference.
+  repeated RouteTargetReference alternateBackends = 4;
+
+  // If specified, the port to be used by the router. Most routers will use all
+  // endpoints exposed by the service by default - set this value to instruct routers
+  // which port to use.
+  optional RoutePort port = 5;
+
+  // The tls field provides the ability to configure certificates and termination for the route.
+  optional TLSConfig tls = 6;
+
+  // Wildcard policy if any for the route.
+  // Currently only 'Subdomain' or 'None' is allowed.
+  optional string wildcardPolicy = 7;
+}
+
+// RouteStatus provides relevant info about the status of a route, including which routers
+// acknowledge it.
+message RouteStatus {
+  // ingress describes the places where the route may be exposed. The list of
+  // ingress points may contain duplicate Host or RouterName values. Routes
+  // are considered live once they are `Ready`
+  repeated RouteIngress ingress = 1;
+}
+
+// RouteTargetReference specifies the target that resolve into endpoints. Only the 'Service'
+// kind is allowed. Use 'weight' field to emphasize one over others.
+message RouteTargetReference {
+  // The kind of target that the route is referring to. Currently, only 'Service' is allowed
+  optional string kind = 1;
+
+  // name of the service/target that is being referred to. e.g. name of the service
+  optional string name = 2;
+
+  // weight as an integer between 0 and 256, default 1, that specifies the target's relative weight
+  // against other target reference objects. 0 suppresses requests to this backend.
+  optional int32 weight = 3;
+}
+
+// RouterShard has information of a routing shard and is used to
+// generate host names and routing table entries when a routing shard is
+// allocated for a specific route.
+// Caveat: This is WIP and will likely undergo modifications when sharding
+//         support is added.
+message RouterShard {
+  // shardName uniquely identifies a router shard in the "set" of
+  // routers used for routing traffic to the services.
+  optional string shardName = 1;
+
+  // dnsSuffix for the shard ala: shard-1.v3.openshift.com
+  optional string dnsSuffix = 2;
+}
+
+// TLSConfig defines config used to secure a route and provide termination
+message TLSConfig {
+  // termination indicates termination type.
+  optional string termination = 1;
+
+  // certificate provides certificate contents
+  optional string certificate = 2;
+
+  // key provides key file contents
+  optional string key = 3;
+
+  // caCertificate provides the cert authority certificate contents
+  optional string caCertificate = 4;
+
+  // destinationCACertificate provides the contents of the ca certificate of the final destination.  When using reencrypt
+  // termination this file should be provided in order to have routers use it for health checks on the secure connection.
+  // If this field is not specified, the router may provide its own destination CA and perform hostname validation using
+  // the short service name (service.namespace.svc), which allows infrastructure generated certificates to automatically
+  // verify.
+  optional string destinationCACertificate = 5;
+
+  // insecureEdgeTerminationPolicy indicates the desired behavior for insecure connections to a route. While
+  // each router may make its own decisions on which ports to expose, this is normally port 80.
+  // 
+  // * Allow - traffic is sent to the server on the insecure port (default)
+  // * Disable - no traffic is allowed on the insecure port.
+  // * Redirect - clients are redirected to the secure port.
+  optional string insecureEdgeTerminationPolicy = 6;
+}
+
diff --git a/vendor/github.com/openshift/api/route/v1/register.go b/vendor/github.com/openshift/api/route/v1/register.go
new file mode 100644
index 00000000..7257f023
--- /dev/null
+++ b/vendor/github.com/openshift/api/route/v1/register.go
@@ -0,0 +1,47 @@
+package v1
+
+import (
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+)
+
+const (
+	GroupName       = "route.openshift.io"
+	LegacyGroupName = ""
+)
+
+// SchemeGroupVersion is group version used to register these objects
+var (
+	SchemeGroupVersion       = schema.GroupVersion{Group: GroupName, Version: "v1"}
+	LegacySchemeGroupVersion = schema.GroupVersion{Group: LegacyGroupName, Version: "v1"}
+
+	LegacySchemeBuilder    = runtime.NewSchemeBuilder(addLegacyKnownTypes)
+	AddToSchemeInCoreGroup = LegacySchemeBuilder.AddToScheme
+
+	SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
+	AddToScheme   = SchemeBuilder.AddToScheme
+)
+
+func Resource(resource string) schema.GroupResource {
+	return SchemeGroupVersion.WithResource(resource).GroupResource()
+}
+
+// Adds the list of known types to api.Scheme.
+func addKnownTypes(scheme *runtime.Scheme) error {
+	scheme.AddKnownTypes(SchemeGroupVersion,
+		&Route{},
+		&RouteList{},
+	)
+	metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
+	return nil
+}
+
+func addLegacyKnownTypes(scheme *runtime.Scheme) error {
+	types := []runtime.Object{
+		&Route{},
+		&RouteList{},
+	}
+	scheme.AddKnownTypes(LegacySchemeGroupVersion, types...)
+	return nil
+}
diff --git a/vendor/github.com/openshift/api/route/v1/types.go b/vendor/github.com/openshift/api/route/v1/types.go
new file mode 100644
index 00000000..6c14ae71
--- /dev/null
+++ b/vendor/github.com/openshift/api/route/v1/types.go
@@ -0,0 +1,255 @@
+package v1
+
+import (
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/util/intstr"
+)
+
+// +genclient
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// A route allows developers to expose services through an HTTP(S) aware load balancing and proxy
+// layer via a public DNS entry. The route may further specify TLS options and a certificate, or
+// specify a public CNAME that the router should also accept for HTTP and HTTPS traffic. An
+// administrator typically configures their router to be visible outside the cluster firewall, and
+// may also add additional security, caching, or traffic controls on the service content. Routers
+// usually talk directly to the service endpoints.
+//
+// Once a route is created, the `host` field may not be changed. Generally, routers use the oldest
+// route with a given host when resolving conflicts.
+//
+// Routers are subject to additional customization and may support additional controls via the
+// annotations field.
+//
+// Because administrators may configure multiple routers, the route status field is used to
+// return information to clients about the names and states of the route under each router.
+// If a client chooses a duplicate name, for instance, the route status conditions are used
+// to indicate the route cannot be chosen.
+type Route struct {
+	metav1.TypeMeta `json:",inline"`
+	// Standard object metadata.
+	metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
+
+	// spec is the desired state of the route
+	Spec RouteSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"`
+	// status is the current state of the route
+	Status RouteStatus `json:"status" protobuf:"bytes,3,opt,name=status"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+
+// RouteList is a collection of Routes.
+type RouteList struct {
+	metav1.TypeMeta `json:",inline"`
+	// Standard object metadata.
+	metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
+
+	// items is a list of routes
+	Items []Route `json:"items" protobuf:"bytes,2,rep,name=items"`
+}
+
+// RouteSpec describes the hostname or path the route exposes, any security information,
+// and one to four backends (services) the route points to. Requests are distributed
+// among the backends depending on the weights assigned to each backend. When using
+// roundrobin scheduling the portion of requests that go to each backend is the backend
+// weight divided by the sum of all of the backend weights. When the backend has more than
+// one endpoint the requests that end up on the backend are roundrobin distributed among
+// the endpoints. Weights are between 0 and 256 with default 1. Weight 0 causes no requests
+// to the backend. If all weights are zero the route will be considered to have no backends
+// and return a standard 503 response.
+//
+// The `tls` field is optional and allows specific certificates or behavior for the
+// route. Routers typically configure a default certificate on a wildcard domain to
+// terminate routes without explicit certificates, but custom hostnames usually must
+// choose passthrough (send traffic directly to the backend via the TLS Server-Name-
+// Indication field) or provide a certificate.
+type RouteSpec struct {
+	// host is an alias/DNS that points to the service. Optional.
+	// If not specified a route name will typically be automatically
+	// chosen.
+	// Must follow DNS952 subdomain conventions.
+	Host string `json:"host" protobuf:"bytes,1,opt,name=host"`
+	// Path that the router watches for, to route traffic for to the service. Optional
+	Path string `json:"path,omitempty" protobuf:"bytes,2,opt,name=path"`
+
+	// to is an object the route should use as the primary backend. Only the Service kind
+	// is allowed, and it will be defaulted to Service. If the weight field (0-256 default 1)
+	// is set to zero, no traffic will be sent to this backend.
+	To RouteTargetReference `json:"to" protobuf:"bytes,3,opt,name=to"`
+
+	// alternateBackends allows up to 3 additional backends to be assigned to the route.
+	// Only the Service kind is allowed, and it will be defaulted to Service.
+	// Use the weight field in RouteTargetReference object to specify relative preference.
+	AlternateBackends []RouteTargetReference `json:"alternateBackends,omitempty" protobuf:"bytes,4,rep,name=alternateBackends"`
+
+	// If specified, the port to be used by the router. Most routers will use all
+	// endpoints exposed by the service by default - set this value to instruct routers
+	// which port to use.
+	Port *RoutePort `json:"port,omitempty" protobuf:"bytes,5,opt,name=port"`
+
+	// The tls field provides the ability to configure certificates and termination for the route.
+	TLS *TLSConfig `json:"tls,omitempty" protobuf:"bytes,6,opt,name=tls"`
+
+	// Wildcard policy if any for the route.
+	// Currently only 'Subdomain' or 'None' is allowed.
+	WildcardPolicy WildcardPolicyType `json:"wildcardPolicy,omitempty" protobuf:"bytes,7,opt,name=wildcardPolicy"`
+}
+
+// RouteTargetReference specifies the target that resolve into endpoints. Only the 'Service'
+// kind is allowed. Use 'weight' field to emphasize one over others.
+type RouteTargetReference struct {
+	// The kind of target that the route is referring to. Currently, only 'Service' is allowed
+	Kind string `json:"kind" protobuf:"bytes,1,opt,name=kind"`
+
+	// name of the service/target that is being referred to. e.g. name of the service
+	Name string `json:"name" protobuf:"bytes,2,opt,name=name"`
+
+	// weight as an integer between 0 and 256, default 1, that specifies the target's relative weight
+	// against other target reference objects. 0 suppresses requests to this backend.
+	Weight *int32 `json:"weight" protobuf:"varint,3,opt,name=weight"`
+}
+
+// RoutePort defines a port mapping from a router to an endpoint in the service endpoints.
+type RoutePort struct {
+	// The target port on pods selected by the service this route points to.
+	// If this is a string, it will be looked up as a named port in the target
+	// endpoints port list. Required
+	TargetPort intstr.IntOrString `json:"targetPort" protobuf:"bytes,1,opt,name=targetPort"`
+}
+
+// RouteStatus provides relevant info about the status of a route, including which routers
+// acknowledge it.
+type RouteStatus struct {
+	// ingress describes the places where the route may be exposed. The list of
+	// ingress points may contain duplicate Host or RouterName values. Routes
+	// are considered live once they are `Ready`
+	Ingress []RouteIngress `json:"ingress" protobuf:"bytes,1,rep,name=ingress"`
+}
+
+// RouteIngress holds information about the places where a route is exposed.
+type RouteIngress struct {
+	// Host is the host string under which the route is exposed; this value is required
+	Host string `json:"host,omitempty" protobuf:"bytes,1,opt,name=host"`
+	// Name is a name chosen by the router to identify itself; this value is required
+	RouterName string `json:"routerName,omitempty" protobuf:"bytes,2,opt,name=routerName"`
+	// Conditions is the state of the route, may be empty.
+	Conditions []RouteIngressCondition `json:"conditions,omitempty" protobuf:"bytes,3,rep,name=conditions"`
+	// Wildcard policy is the wildcard policy that was allowed where this route is exposed.
+	WildcardPolicy WildcardPolicyType `json:"wildcardPolicy,omitempty" protobuf:"bytes,4,opt,name=wildcardPolicy"`
+	// CanonicalHostname is the external host name for the router that can be used as a CNAME
+	// for the host requested for this route. This value is optional and may not be set in all cases.
+	RouterCanonicalHostname string `json:"routerCanonicalHostname,omitempty" protobuf:"bytes,5,opt,name=routerCanonicalHostname"`
+}
+
+// RouteIngressConditionType is a valid value for RouteCondition
+type RouteIngressConditionType string
+
+// These are valid conditions of pod.
+const (
+	// RouteAdmitted means the route is able to service requests for the provided Host
+	RouteAdmitted RouteIngressConditionType = "Admitted"
+	// TODO: add other route condition types
+)
+
+// RouteIngressCondition contains details for the current condition of this route on a particular
+// router.
+type RouteIngressCondition struct {
+	// Type is the type of the condition.
+	// Currently only Ready.
+	Type RouteIngressConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=RouteIngressConditionType"`
+	// Status is the status of the condition.
+	// Can be True, False, Unknown.
+	Status corev1.ConditionStatus `json:"status" protobuf:"bytes,2,opt,name=status,casttype=k8s.io/api/core/v1.ConditionStatus"`
+	// (brief) reason for the condition's last transition, and is usually a machine and human
+	// readable constant
+	Reason string `json:"reason,omitempty" protobuf:"bytes,3,opt,name=reason"`
+	// Human readable message indicating details about last transition.
+	Message string `json:"message,omitempty" protobuf:"bytes,4,opt,name=message"`
+	// RFC 3339 date and time when this condition last transitioned
+	LastTransitionTime *metav1.Time `json:"lastTransitionTime,omitempty" protobuf:"bytes,5,opt,name=lastTransitionTime"`
+}
+
+// RouterShard has information of a routing shard and is used to
+// generate host names and routing table entries when a routing shard is
+// allocated for a specific route.
+// Caveat: This is WIP and will likely undergo modifications when sharding
+//         support is added.
+type RouterShard struct {
+	// shardName uniquely identifies a router shard in the "set" of
+	// routers used for routing traffic to the services.
+	ShardName string `json:"shardName" protobuf:"bytes,1,opt,name=shardName"`
+
+	// dnsSuffix for the shard ala: shard-1.v3.openshift.com
+	DNSSuffix string `json:"dnsSuffix" protobuf:"bytes,2,opt,name=dnsSuffix"`
+}
+
+// TLSConfig defines config used to secure a route and provide termination
+type TLSConfig struct {
+	// termination indicates termination type.
+	Termination TLSTerminationType `json:"termination" protobuf:"bytes,1,opt,name=termination,casttype=TLSTerminationType"`
+
+	// certificate provides certificate contents
+	Certificate string `json:"certificate,omitempty" protobuf:"bytes,2,opt,name=certificate"`
+
+	// key provides key file contents
+	Key string `json:"key,omitempty" protobuf:"bytes,3,opt,name=key"`
+
+	// caCertificate provides the cert authority certificate contents
+	CACertificate string `json:"caCertificate,omitempty" protobuf:"bytes,4,opt,name=caCertificate"`
+
+	// destinationCACertificate provides the contents of the ca certificate of the final destination.  When using reencrypt
+	// termination this file should be provided in order to have routers use it for health checks on the secure connection.
+	// If this field is not specified, the router may provide its own destination CA and perform hostname validation using
+	// the short service name (service.namespace.svc), which allows infrastructure generated certificates to automatically
+	// verify.
+	DestinationCACertificate string `json:"destinationCACertificate,omitempty" protobuf:"bytes,5,opt,name=destinationCACertificate"`
+
+	// insecureEdgeTerminationPolicy indicates the desired behavior for insecure connections to a route. While
+	// each router may make its own decisions on which ports to expose, this is normally port 80.
+	//
+	// * Allow - traffic is sent to the server on the insecure port (default)
+	// * Disable - no traffic is allowed on the insecure port.
+	// * Redirect - clients are redirected to the secure port.
+	InsecureEdgeTerminationPolicy InsecureEdgeTerminationPolicyType `json:"insecureEdgeTerminationPolicy,omitempty" protobuf:"bytes,6,opt,name=insecureEdgeTerminationPolicy,casttype=InsecureEdgeTerminationPolicyType"`
+}
+
+// TLSTerminationType dictates where the secure communication will stop
+// TODO: Reconsider this type in v2
+type TLSTerminationType string
+
+// InsecureEdgeTerminationPolicyType dictates the behavior of insecure
+// connections to an edge-terminated route.
+type InsecureEdgeTerminationPolicyType string
+
+const (
+	// TLSTerminationEdge terminate encryption at the edge router.
+	TLSTerminationEdge TLSTerminationType = "edge"
+	// TLSTerminationPassthrough terminate encryption at the destination, the destination is responsible for decrypting traffic
+	TLSTerminationPassthrough TLSTerminationType = "passthrough"
+	// TLSTerminationReencrypt terminate encryption at the edge router and re-encrypt it with a new certificate supplied by the destination
+	TLSTerminationReencrypt TLSTerminationType = "reencrypt"
+
+	// InsecureEdgeTerminationPolicyNone disables insecure connections for an edge-terminated route.
+	InsecureEdgeTerminationPolicyNone InsecureEdgeTerminationPolicyType = "None"
+	// InsecureEdgeTerminationPolicyAllow allows insecure connections for an edge-terminated route.
+	InsecureEdgeTerminationPolicyAllow InsecureEdgeTerminationPolicyType = "Allow"
+	// InsecureEdgeTerminationPolicyRedirect redirects insecure connections for an edge-terminated route.
+	// As an example, for routers that support HTTP and HTTPS, the
+	// insecure HTTP connections will be redirected to use HTTPS.
+	InsecureEdgeTerminationPolicyRedirect InsecureEdgeTerminationPolicyType = "Redirect"
+)
+
+// WildcardPolicyType indicates the type of wildcard support needed by routes.
+type WildcardPolicyType string
+
+const (
+	// WildcardPolicyNone indicates no wildcard support is needed.
+	WildcardPolicyNone WildcardPolicyType = "None"
+
+	// WildcardPolicySubdomain indicates the host needs wildcard support for the subdomain.
+	// Example: For host = "www.acme.test", indicates that the router
+	//          should support requests for *.acme.test
+	//          Note that this will not match acme.test only *.acme.test
+	WildcardPolicySubdomain WildcardPolicyType = "Subdomain"
+)
diff --git a/vendor/github.com/openshift/api/route/v1/types_swagger_doc_generated.go b/vendor/github.com/openshift/api/route/v1/types_swagger_doc_generated.go
new file mode 100644
index 00000000..8d952173
--- /dev/null
+++ b/vendor/github.com/openshift/api/route/v1/types_swagger_doc_generated.go
@@ -0,0 +1,129 @@
+package v1
+
+// This file contains a collection of methods that can be used from go-restful to
+// generate Swagger API documentation for its models. Please read this PR for more
+// information on the implementation: https://github.com/emicklei/go-restful/pull/215
+//
+// TODOs are ignored from the parser (e.g. TODO(andronat):... || TODO:...) if and only if
+// they are on one line! For multiple line or blocks that you want to ignore use ---.
+// Any context after a --- is ignored.
+//
+// Those methods can be generated by using hack/update-generated-swagger-docs.sh
+
+// AUTO-GENERATED FUNCTIONS START HERE
+var map_Route = map[string]string{
+	"":         "A route allows developers to expose services through an HTTP(S) aware load balancing and proxy layer via a public DNS entry. The route may further specify TLS options and a certificate, or specify a public CNAME that the router should also accept for HTTP and HTTPS traffic. An administrator typically configures their router to be visible outside the cluster firewall, and may also add additional security, caching, or traffic controls on the service content. Routers usually talk directly to the service endpoints.\n\nOnce a route is created, the `host` field may not be changed. Generally, routers use the oldest route with a given host when resolving conflicts.\n\nRouters are subject to additional customization and may support additional controls via the annotations field.\n\nBecause administrators may configure multiple routers, the route status field is used to return information to clients about the names and states of the route under each router. If a client chooses a duplicate name, for instance, the route status conditions are used to indicate the route cannot be chosen.",
+	"metadata": "Standard object metadata.",
+	"spec":     "spec is the desired state of the route",
+	"status":   "status is the current state of the route",
+}
+
+func (Route) SwaggerDoc() map[string]string {
+	return map_Route
+}
+
+var map_RouteIngress = map[string]string{
+	"":                        "RouteIngress holds information about the places where a route is exposed.",
+	"host":                    "Host is the host string under which the route is exposed; this value is required",
+	"routerName":              "Name is a name chosen by the router to identify itself; this value is required",
+	"conditions":              "Conditions is the state of the route, may be empty.",
+	"wildcardPolicy":          "Wildcard policy is the wildcard policy that was allowed where this route is exposed.",
+	"routerCanonicalHostname": "CanonicalHostname is the external host name for the router that can be used as a CNAME for the host requested for this route. This value is optional and may not be set in all cases.",
+}
+
+func (RouteIngress) SwaggerDoc() map[string]string {
+	return map_RouteIngress
+}
+
+var map_RouteIngressCondition = map[string]string{
+	"":                   "RouteIngressCondition contains details for the current condition of this route on a particular router.",
+	"type":               "Type is the type of the condition. Currently only Ready.",
+	"status":             "Status is the status of the condition. Can be True, False, Unknown.",
+	"reason":             "(brief) reason for the condition's last transition, and is usually a machine and human readable constant",
+	"message":            "Human readable message indicating details about last transition.",
+	"lastTransitionTime": "RFC 3339 date and time when this condition last transitioned",
+}
+
+func (RouteIngressCondition) SwaggerDoc() map[string]string {
+	return map_RouteIngressCondition
+}
+
+var map_RouteList = map[string]string{
+	"":         "RouteList is a collection of Routes.",
+	"metadata": "Standard object metadata.",
+	"items":    "items is a list of routes",
+}
+
+func (RouteList) SwaggerDoc() map[string]string {
+	return map_RouteList
+}
+
+var map_RoutePort = map[string]string{
+	"":           "RoutePort defines a port mapping from a router to an endpoint in the service endpoints.",
+	"targetPort": "The target port on pods selected by the service this route points to. If this is a string, it will be looked up as a named port in the target endpoints port list. Required",
+}
+
+func (RoutePort) SwaggerDoc() map[string]string {
+	return map_RoutePort
+}
+
+var map_RouteSpec = map[string]string{
+	"":                  "RouteSpec describes the hostname or path the route exposes, any security information, and one to four backends (services) the route points to. Requests are distributed among the backends depending on the weights assigned to each backend. When using roundrobin scheduling the portion of requests that go to each backend is the backend weight divided by the sum of all of the backend weights. When the backend has more than one endpoint the requests that end up on the backend are roundrobin distributed among the endpoints. Weights are between 0 and 256 with default 1. Weight 0 causes no requests to the backend. If all weights are zero the route will be considered to have no backends and return a standard 503 response.\n\nThe `tls` field is optional and allows specific certificates or behavior for the route. Routers typically configure a default certificate on a wildcard domain to terminate routes without explicit certificates, but custom hostnames usually must choose passthrough (send traffic directly to the backend via the TLS Server-Name- Indication field) or provide a certificate.",
+	"host":              "host is an alias/DNS that points to the service. Optional. If not specified a route name will typically be automatically chosen. Must follow DNS952 subdomain conventions.",
+	"path":              "Path that the router watches for, to route traffic for to the service. Optional",
+	"to":                "to is an object the route should use as the primary backend. Only the Service kind is allowed, and it will be defaulted to Service. If the weight field (0-256 default 1) is set to zero, no traffic will be sent to this backend.",
+	"alternateBackends": "alternateBackends allows up to 3 additional backends to be assigned to the route. Only the Service kind is allowed, and it will be defaulted to Service. Use the weight field in RouteTargetReference object to specify relative preference.",
+	"port":              "If specified, the port to be used by the router. Most routers will use all endpoints exposed by the service by default - set this value to instruct routers which port to use.",
+	"tls":               "The tls field provides the ability to configure certificates and termination for the route.",
+	"wildcardPolicy":    "Wildcard policy if any for the route. Currently only 'Subdomain' or 'None' is allowed.",
+}
+
+func (RouteSpec) SwaggerDoc() map[string]string {
+	return map_RouteSpec
+}
+
+var map_RouteStatus = map[string]string{
+	"":        "RouteStatus provides relevant info about the status of a route, including which routers acknowledge it.",
+	"ingress": "ingress describes the places where the route may be exposed. The list of ingress points may contain duplicate Host or RouterName values. Routes are considered live once they are `Ready`",
+}
+
+func (RouteStatus) SwaggerDoc() map[string]string {
+	return map_RouteStatus
+}
+
+var map_RouteTargetReference = map[string]string{
+	"":       "RouteTargetReference specifies the target that resolve into endpoints. Only the 'Service' kind is allowed. Use 'weight' field to emphasize one over others.",
+	"kind":   "The kind of target that the route is referring to. Currently, only 'Service' is allowed",
+	"name":   "name of the service/target that is being referred to. e.g. name of the service",
+	"weight": "weight as an integer between 0 and 256, default 1, that specifies the target's relative weight against other target reference objects. 0 suppresses requests to this backend.",
+}
+
+func (RouteTargetReference) SwaggerDoc() map[string]string {
+	return map_RouteTargetReference
+}
+
+var map_RouterShard = map[string]string{
+	"":          "RouterShard has information of a routing shard and is used to generate host names and routing table entries when a routing shard is allocated for a specific route. Caveat: This is WIP and will likely undergo modifications when sharding\n        support is added.",
+	"shardName": "shardName uniquely identifies a router shard in the \"set\" of routers used for routing traffic to the services.",
+	"dnsSuffix": "dnsSuffix for the shard ala: shard-1.v3.openshift.com",
+}
+
+func (RouterShard) SwaggerDoc() map[string]string {
+	return map_RouterShard
+}
+
+var map_TLSConfig = map[string]string{
+	"":                              "TLSConfig defines config used to secure a route and provide termination",
+	"termination":                   "termination indicates termination type.",
+	"certificate":                   "certificate provides certificate contents",
+	"key":                           "key provides key file contents",
+	"caCertificate":                 "caCertificate provides the cert authority certificate contents",
+	"destinationCACertificate":      "destinationCACertificate provides the contents of the ca certificate of the final destination.  When using reencrypt termination this file should be provided in order to have routers use it for health checks on the secure connection. If this field is not specified, the router may provide its own destination CA and perform hostname validation using the short service name (service.namespace.svc), which allows infrastructure generated certificates to automatically verify.",
+	"insecureEdgeTerminationPolicy": "insecureEdgeTerminationPolicy indicates the desired behavior for insecure connections to a route. While each router may make its own decisions on which ports to expose, this is normally port 80.\n\n* Allow - traffic is sent to the server on the insecure port (default) * Disable - no traffic is allowed on the insecure port. * Redirect - clients are redirected to the secure port.",
+}
+
+func (TLSConfig) SwaggerDoc() map[string]string {
+	return map_TLSConfig
+}
+
+// AUTO-GENERATED FUNCTIONS END HERE
diff --git a/vendor/github.com/openshift/api/route/v1/zz_generated.deepcopy.go b/vendor/github.com/openshift/api/route/v1/zz_generated.deepcopy.go
new file mode 100644
index 00000000..2ce3d96d
--- /dev/null
+++ b/vendor/github.com/openshift/api/route/v1/zz_generated.deepcopy.go
@@ -0,0 +1,341 @@
+// +build !ignore_autogenerated
+
+// This file was autogenerated by deepcopy-gen. Do not edit it manually!
+
+package v1
+
+import (
+	meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	runtime "k8s.io/apimachinery/pkg/runtime"
+	unsafe "unsafe"
+)
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *InsecureEdgeTerminationPolicyType) DeepCopyInto(out *InsecureEdgeTerminationPolicyType) {
+	{
+		in := (*string)(unsafe.Pointer(in))
+		out := (*string)(unsafe.Pointer(out))
+		*out = *in
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InsecureEdgeTerminationPolicyType.
+func (in *InsecureEdgeTerminationPolicyType) DeepCopy() *InsecureEdgeTerminationPolicyType {
+	if in == nil {
+		return nil
+	}
+	out := new(InsecureEdgeTerminationPolicyType)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Route) DeepCopyInto(out *Route) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	in.Spec.DeepCopyInto(&out.Spec)
+	in.Status.DeepCopyInto(&out.Status)
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Route.
+func (in *Route) DeepCopy() *Route {
+	if in == nil {
+		return nil
+	}
+	out := new(Route)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *Route) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	} else {
+		return nil
+	}
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *RouteIngress) DeepCopyInto(out *RouteIngress) {
+	*out = *in
+	if in.Conditions != nil {
+		in, out := &in.Conditions, &out.Conditions
+		*out = make([]RouteIngressCondition, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteIngress.
+func (in *RouteIngress) DeepCopy() *RouteIngress {
+	if in == nil {
+		return nil
+	}
+	out := new(RouteIngress)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *RouteIngressCondition) DeepCopyInto(out *RouteIngressCondition) {
+	*out = *in
+	if in.LastTransitionTime != nil {
+		in, out := &in.LastTransitionTime, &out.LastTransitionTime
+		if *in == nil {
+			*out = nil
+		} else {
+			*out = new(meta_v1.Time)
+			(*in).DeepCopyInto(*out)
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteIngressCondition.
+func (in *RouteIngressCondition) DeepCopy() *RouteIngressCondition {
+	if in == nil {
+		return nil
+	}
+	out := new(RouteIngressCondition)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *RouteIngressConditionType) DeepCopyInto(out *RouteIngressConditionType) {
+	{
+		in := (*string)(unsafe.Pointer(in))
+		out := (*string)(unsafe.Pointer(out))
+		*out = *in
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteIngressConditionType.
+func (in *RouteIngressConditionType) DeepCopy() *RouteIngressConditionType {
+	if in == nil {
+		return nil
+	}
+	out := new(RouteIngressConditionType)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *RouteList) DeepCopyInto(out *RouteList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	out.ListMeta = in.ListMeta
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]Route, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteList.
+func (in *RouteList) DeepCopy() *RouteList {
+	if in == nil {
+		return nil
+	}
+	out := new(RouteList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *RouteList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	} else {
+		return nil
+	}
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *RoutePort) DeepCopyInto(out *RoutePort) {
+	*out = *in
+	out.TargetPort = in.TargetPort
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RoutePort.
+func (in *RoutePort) DeepCopy() *RoutePort {
+	if in == nil {
+		return nil
+	}
+	out := new(RoutePort)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *RouteSpec) DeepCopyInto(out *RouteSpec) {
+	*out = *in
+	in.To.DeepCopyInto(&out.To)
+	if in.AlternateBackends != nil {
+		in, out := &in.AlternateBackends, &out.AlternateBackends
+		*out = make([]RouteTargetReference, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	if in.Port != nil {
+		in, out := &in.Port, &out.Port
+		if *in == nil {
+			*out = nil
+		} else {
+			*out = new(RoutePort)
+			**out = **in
+		}
+	}
+	if in.TLS != nil {
+		in, out := &in.TLS, &out.TLS
+		if *in == nil {
+			*out = nil
+		} else {
+			*out = new(TLSConfig)
+			**out = **in
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteSpec.
+func (in *RouteSpec) DeepCopy() *RouteSpec {
+	if in == nil {
+		return nil
+	}
+	out := new(RouteSpec)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *RouteStatus) DeepCopyInto(out *RouteStatus) {
+	*out = *in
+	if in.Ingress != nil {
+		in, out := &in.Ingress, &out.Ingress
+		*out = make([]RouteIngress, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteStatus.
+func (in *RouteStatus) DeepCopy() *RouteStatus {
+	if in == nil {
+		return nil
+	}
+	out := new(RouteStatus)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *RouteTargetReference) DeepCopyInto(out *RouteTargetReference) {
+	*out = *in
+	if in.Weight != nil {
+		in, out := &in.Weight, &out.Weight
+		if *in == nil {
+			*out = nil
+		} else {
+			*out = new(int32)
+			**out = **in
+		}
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteTargetReference.
+func (in *RouteTargetReference) DeepCopy() *RouteTargetReference {
+	if in == nil {
+		return nil
+	}
+	out := new(RouteTargetReference)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *RouterShard) DeepCopyInto(out *RouterShard) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouterShard.
+func (in *RouterShard) DeepCopy() *RouterShard {
+	if in == nil {
+		return nil
+	}
+	out := new(RouterShard)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *TLSConfig) DeepCopyInto(out *TLSConfig) {
+	*out = *in
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSConfig.
+func (in *TLSConfig) DeepCopy() *TLSConfig {
+	if in == nil {
+		return nil
+	}
+	out := new(TLSConfig)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *TLSTerminationType) DeepCopyInto(out *TLSTerminationType) {
+	{
+		in := (*string)(unsafe.Pointer(in))
+		out := (*string)(unsafe.Pointer(out))
+		*out = *in
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSTerminationType.
+func (in *TLSTerminationType) DeepCopy() *TLSTerminationType {
+	if in == nil {
+		return nil
+	}
+	out := new(TLSTerminationType)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *WildcardPolicyType) DeepCopyInto(out *WildcardPolicyType) {
+	{
+		in := (*string)(unsafe.Pointer(in))
+		out := (*string)(unsafe.Pointer(out))
+		*out = *in
+	}
+	return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WildcardPolicyType.
+func (in *WildcardPolicyType) DeepCopy() *WildcardPolicyType {
+	if in == nil {
+		return nil
+	}
+	out := new(WildcardPolicyType)
+	in.DeepCopyInto(out)
+	return out
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index d852d007..408b30aa 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -134,6 +134,7 @@ github.com/modern-go/concurrent
 github.com/modern-go/reflect2
 # github.com/openshift/api v3.9.0+incompatible
 github.com/openshift/api/apps/v1
+github.com/openshift/api/route/v1
 # github.com/operator-backing-service-samples/postgresql-operator v0.0.0-20190821075443-840d192264ec
 github.com/operator-backing-service-samples/postgresql-operator/pkg/apis
 github.com/operator-backing-service-samples/postgresql-operator/pkg/apis/postgresql/v1alpha1
@@ -370,6 +371,7 @@ k8s.io/apimachinery/pkg/runtime/schema
 k8s.io/apimachinery/pkg/api/errors
 k8s.io/apimachinery/pkg/api/meta
 k8s.io/apimachinery/pkg/apis/meta/v1/unstructured
+k8s.io/apimachinery/pkg/fields
 k8s.io/apimachinery/pkg/labels
 k8s.io/apimachinery/pkg/types
 k8s.io/apimachinery/pkg/runtime/serializer
@@ -386,7 +388,6 @@ k8s.io/apimachinery/pkg/conversion/queryparams
 k8s.io/apimachinery/pkg/util/errors
 k8s.io/apimachinery/pkg/util/json
 k8s.io/apimachinery/pkg/util/naming
-k8s.io/apimachinery/pkg/fields
 k8s.io/apimachinery/pkg/selection
 k8s.io/apimachinery/pkg/util/validation/field
 k8s.io/apimachinery/pkg/apis/meta/v1beta1
@@ -406,7 +407,7 @@ k8s.io/apimachinery/third_party/forked/golang/reflect
 k8s.io/apimachinery/pkg/apis/meta/internalversion
 k8s.io/apimachinery/pkg/util/mergepatch
 k8s.io/apimachinery/third_party/forked/golang/json
-# k8s.io/client-go v11.0.0+incompatible => k8s.io/client-go v0.0.0-20181213151034-8d9ed539ba31
+# k8s.io/client-go v12.0.0+incompatible => k8s.io/client-go v0.0.0-20181213151034-8d9ed539ba31
 k8s.io/client-go/plugin/pkg/client/auth
 k8s.io/client-go/rest
 k8s.io/client-go/dynamic


Test patch:
diff --git a/hack/e2e-log-parser.sh b/hack/e2e-log-parser.sh
new file mode 100755
index 00000000..b38c56bc
--- /dev/null
+++ b/hack/e2e-log-parser.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+#
+# Based on the input extracted from operator-sdk running end-to-end tests, parse and print out
+# regular log lines.
+#
+
+set -e
+
+grep 'msg="Local operator stderr' $1 \
+    |sed 's/^time.*err: //g' \
+    |eval 'in=$(cat); echo -en "$in"'
diff --git a/pkg/controller/servicebindingrequest/bind_custom_resources_test.go b/pkg/controller/servicebindingrequest/bind_custom_resources_test.go
new file mode 100644
index 00000000..a704d2cd
--- /dev/null
+++ b/pkg/controller/servicebindingrequest/bind_custom_resources_test.go
@@ -0,0 +1,74 @@
+package servicebindingrequest
+
+import (
+	v12 "github.com/openshift/api/route/v1"
+	pgv1alpha1 "github.com/operator-backing-service-samples/postgresql-operator/pkg/apis/postgresql/v1alpha1"
+	"github.com/redhat-developer/service-binding-operator/test/mocks"
+	"github.com/stretchr/testify/assert"
+	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
+	"k8s.io/apimachinery/pkg/runtime"
+	"k8s.io/apimachinery/pkg/runtime/schema"
+	"testing"
+)
+
+func TestBindNonBindableResources_GetOwnedResources(t *testing.T) {
+	f := mocks.NewFake(t, "test")
+	cr := mocks.DatabaseCRMock("test", "test")
+	trueBool := true
+	reference := v1.OwnerReference{
+		APIVersion:         cr.APIVersion,
+		Kind:               cr.Kind,
+		Name:               cr.Name,
+		UID:                cr.UID,
+		Controller:         &trueBool,
+		BlockOwnerDeletion: &trueBool,
+	}
+	configMap := mocks.ConfigMapMock("test", "test_database")
+	us := &unstructured.Unstructured{}
+	uc, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&configMap)
+	assert.NoError(t, err)
+	us.Object = uc
+	us.SetOwnerReferences([]v1.OwnerReference{reference})
+	route, err := runtime.DefaultUnstructuredConverter.ToUnstructured(mocks.RouteCRMock("test", "test"))
+	assert.NoError(t, err)
+	usRoute := &unstructured.Unstructured{Object: route}
+	usRoute.SetOwnerReferences([]v1.OwnerReference{reference})
+	f.S.AddKnownTypes(pgv1alpha1.SchemeGroupVersion, &pgv1alpha1.Database{})
+	f.S.AddKnownTypes(v12.SchemeGroupVersion, &v12.Route{})
+	f.AddMockResource(cr)
+	f.AddMockResource(us)
+	f.AddMockResource(&unstructured.Unstructured{Object: route})
+
+	unstructuredCr, _ := runtime.DefaultUnstructuredConverter.ToUnstructured(cr)
+	u := &unstructured.Unstructured{Object: unstructuredCr}
+	b := NewDetectBindableResources(
+		nil,
+		u,
+		[]schema.GroupVersionResource{
+			{
+				Group:    "",
+				Version:  "v1",
+				Resource: "configmaps",
+			},
+			{
+				Group:    "",
+				Version:  "v1",
+				Resource: "routes",
+			},
+		},
+		f.FakeDynClient(),
+	)
+
+	t.Run("Should return configmap as owned resource", func(t *testing.T) {
+		resources, err := b.GetOwnedResources()
+		assert.NoError(t, err)
+		assert.Equal(t, 2, len(resources), "Should return 1 owned resource")
+	})
+
+	t.Run("Should return all variables exist in the configmap data section", func(t *testing.T) {
+		data, err := b.GetBindableVariables()
+		assert.NoError(t, err)
+		assert.Equal(t, 3, len(data), "")
+	})
+}
diff --git a/pkg/controller/servicebindingrequest/binder_test.go b/pkg/controller/servicebindingrequest/binder_test.go
index c594a4e2..bfe25d66 100644
--- a/pkg/controller/servicebindingrequest/binder_test.go
+++ b/pkg/controller/servicebindingrequest/binder_test.go
@@ -41,6 +41,24 @@ func TestBinderNew(t *testing.T) {
 
 	require.NotNil(t, binder)
 
+	sbrWithResourceRef := f.AddMockedServiceBindingRequest("service-binding-request-with-ref", "ref", "ref", make(map[string]string))
+
+	binderForSBRWithResourceRef := NewBinder(
+		context.TODO(),
+		f.FakeClient(),
+		f.FakeDynClient(),
+		sbrWithResourceRef,
+		[]string{},
+	)
+
+	require.NotNil(t, binderForSBRWithResourceRef)
+
+	t.Run("search target object by resource name", func(t *testing.T) {
+		list, err := binderForSBRWithResourceRef.search()
+		assert.Nil(t, err)
+		assert.Equal(t, 1, len(list.Items))
+	})
+
 	t.Run("search", func(t *testing.T) {
 		list, err := binder.search()
 		assert.Nil(t, err)
diff --git a/pkg/controller/servicebindingrequest/retriever_test.go b/pkg/controller/servicebindingrequest/retriever_test.go
index ab1087a0..8269362c 100644
--- a/pkg/controller/servicebindingrequest/retriever_test.go
+++ b/pkg/controller/servicebindingrequest/retriever_test.go
@@ -137,6 +137,8 @@ func TestRetrieverWithNestedCRKey(t *testing.T) {
 	})
 
 	t.Run("Second level error", func(t *testing.T) {
+		// FIXME: if attribute isn't available in CR we would not throw any error.
+		t.Skip()
 		_, _, err := retriever.getCRKey("spec", "image..name")
 		assert.NotNil(t, err)
 	})
@@ -201,7 +203,6 @@ func TestRetrieverWithConfigMap(t *testing.T) {
 		assert.Contains(t, retriever.data, ("SERVICE_BINDING_DATABASE_CONFIGMAP_PASSWORD"))
 	})
 
-
 }
 
 func TestCustomEnvParser(t *testing.T) {
@@ -252,3 +253,4 @@ func TestCustomEnvParser(t *testing.T) {
 		assert.Equal(t, "postgres@cGFzc3dvcmQ=", values["JDBC_CONNECTION_STRING"], "Custom env values are not matching")
 	})
 }
+
diff --git a/test/e2e/servicebindingrequest_test.go b/test/e2e/servicebindingrequest_test.go
index 71d65b77..f5616b2b 100644
--- a/test/e2e/servicebindingrequest_test.go
+++ b/test/e2e/servicebindingrequest_test.go
@@ -4,6 +4,7 @@ import (
 	"bytes"
 	"context"
 	"fmt"
+	"strings"
 	"testing"
 	"time"
 
@@ -18,6 +19,7 @@ import (
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/types"
+	"sigs.k8s.io/controller-runtime/pkg/client"
 	logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
 
 	"github.com/redhat-developer/service-binding-operator/pkg/apis"
@@ -25,6 +27,14 @@ import (
 	"github.com/redhat-developer/service-binding-operator/test/mocks"
 )
 
+type Step string
+
+const (
+	DBStep  Step = "create-db"
+	AppStep Step = "create-app"
+	SBRStep Step = "create-sbr"
+)
+
 var (
 	retryInterval  = time.Second * 5
 	timeout        = time.Second * 120
@@ -49,8 +59,14 @@ func TestAddSchemesToFramework(t *testing.T) {
 	require.Nil(t, framework.AddToFrameworkScheme(pgsqlapis.AddToScheme, &dbList))
 
 	t.Run("end-to-end", func(t *testing.T) {
-		t.Run("scenario-1", ServiceBindingRequest)
-		t.Run("scenario-2 (pre create sbr then binding resources)", PreServiceBindingRequest)
+		// scenario-1
+		t.Run("scenario-db-app-sbr", func(t *testing.T) {
+			ServiceBindingRequest(t, []Step{DBStep, AppStep, SBRStep})
+		})
+		// scenario-2 (pre create sbr then binding resources
+		t.Run("scenario-sbr-db-app", func(t *testing.T) {
+			ServiceBindingRequest(t, []Step{SBRStep, DBStep, AppStep})
+		})
 	})
 
 }
@@ -66,7 +82,7 @@ func cleanUpOptions(ctx *framework.TestCtx) *framework.CleanupOptions {
 
 // bootstrapNamespace execute scaffolding to have a new cluster initialized, and acquire a test
 // namespace, the namespace name is returned and framework global variables are returned.
-func bootstrapNamespace(t *testing.T, ctx *framework.TestCtx) (string, *framework.Framework) {
+func bootstrapNamespace(t *testing.T, ctx *framework.TestCtx, clean bool) (string, *framework.Framework) {
 	t.Log("Initializing cluster resources...")
 	err := ctx.InitializeClusterResources(cleanUpOptions(ctx))
 	if err != nil {
@@ -80,33 +96,105 @@ func bootstrapNamespace(t *testing.T, ctx *framework.TestCtx) (string, *framewor
 	t.Logf("Using namespace '%s' for testing...", ns)
 
 	f := framework.Global
+
+	if clean {
+		err := cleanNamespace(t, ctx, f, ns)
+		require.Nil(t, err)
+	}
 	return ns, f
 }
 
-// ServiceBindingRequest bootstrap method to initialize cluster resources and setup a testing
-// namespace, after bootstrap operator related tests method is called out.
-func ServiceBindingRequest(t *testing.T) {
-	t.Log("Creating a new test context...")
-	ctx := framework.NewTestCtx(t)
-	defer ctx.Cleanup()
+func cleanNamespace(t *testing.T, ctx *framework.TestCtx, f *framework.Framework, ns string) error {
+	todoCtx := context.TODO()
+	databseList := &pgv1alpha1.DatabaseList{}
+	deploymentList := &appsv1.DeploymentList{}
+	secretList := &corev1.SecretList{}
+	serviceBindingRequestList := &v1alpha1.ServiceBindingRequestList{}
+	csvList := &olmv1alpha1.ClusterServiceVersionList{}
+
+	listOptions := &client.ListOptions{
+		Namespace: ns,
+	}
 
-	ns, f := bootstrapNamespace(t, ctx)
+	t.Logf("Cleaning namespace:")
 
-	// executing testing steps on operator
-	serviceBindingRequestTest(t, ctx, f, ns)
+	t.Logf("\tDatabases:")
+	if err := f.Client.List(todoCtx, listOptions, databseList); err != nil {
+		return err
+	}
+	for _, resource := range databseList.Items {
+		t.Logf("\t\t%s...", resource.GetName())
+		err := f.Client.Delete(todoCtx, &resource)
+		if !errors.IsNotFound(err) {
+			require.Nil(t, err)
+		}
+	}
+
+	t.Logf("\tServiceBindingRequests:")
+	if err := f.Client.List(todoCtx, listOptions, serviceBindingRequestList); err != nil {
+		return err
+	}
+	for _, resource := range serviceBindingRequestList.Items {
+		t.Logf("\t\t%s...", resource.GetName())
+		err := f.Client.Delete(todoCtx, &resource)
+		if !errors.IsNotFound(err) {
+			require.Nil(t, err)
+		}
+	}
+
+	t.Logf("\tDeployments:")
+	if err := f.Client.List(todoCtx, listOptions, deploymentList); err != nil {
+		return err
+	}
+	for _, resource := range deploymentList.Items {
+		t.Logf("\t\t%s...", resource.GetName())
+		err := f.Client.Delete(todoCtx, &resource)
+		if !errors.IsNotFound(err) {
+			require.Nil(t, err)
+		}
+	}
+
+	t.Logf("\tClusterServiceVersions:")
+	if err := f.Client.List(todoCtx, listOptions, csvList); err != nil {
+		return err
+	}
+	for _, resource := range csvList.Items {
+		t.Logf("\t\t%s...", resource.GetName())
+		err := f.Client.Delete(todoCtx, &resource)
+		if !errors.IsNotFound(err) {
+			require.Nil(t, err)
+		}
+	}
+
+	t.Logf("\tSecrets:")
+	if err := f.Client.List(todoCtx, listOptions, secretList); err != nil {
+		return err
+	}
+	for _, resource := range secretList.Items {
+		if strings.HasPrefix(string(resource.Type), "kubernetes.io/") {
+			continue // skip
+		}
+		t.Logf("\t\t%s...", resource.GetName())
+		err := f.Client.Delete(todoCtx, &resource)
+		if !errors.IsNotFound(err) {
+			require.Nil(t, err)
+		}
+	}
+
+	return nil
 }
 
-// This would setup testing resources then starts a test,
-// SBR gets created in this test before creation of bindable resource objects
-func PreServiceBindingRequest(t *testing.T) {
+// ServiceBindingRequest bootstrap method to initialize cluster resources and setup a testing
+// namespace, after bootstrap operator related tests method is called out.
+func ServiceBindingRequest(t *testing.T, steps []Step) {
 	t.Log("Creating a new test context...")
 	ctx := framework.NewTestCtx(t)
 	defer ctx.Cleanup()
 
-	ns, f := bootstrapNamespace(t, ctx)
+	ns, f := bootstrapNamespace(t, ctx, true)
 
 	// executing testing steps on operator
-	preCreateServiceBindingRequestTest(t, ctx, f, ns)
+	serviceBindingRequestTest(t, ctx, f, ns, steps)
 }
 
 // assertDeploymentEnvFrom execute the inspection of a deployment type, making sure the containers
@@ -151,15 +239,19 @@ func assertSBRSecret(
 	if _, contains := sbrSecret.Data["DATABASE_SECRET_USER"]; !contains {
 		return nil, fmt.Errorf("can't find DATABASE_SECRET_USER in data")
 	}
-	if !bytes.Equal([]byte("user"), sbrSecret.Data["DATABASE_SECRET_USER"]) {
-		return nil, fmt.Errorf("key DATABASE_SECRET_USER is different than expected")
+	actualUser := sbrSecret.Data["DATABASE_SECRET_USER"]
+	expectedUser := []byte("user")
+	if !bytes.Equal(expectedUser, actualUser) {
+		return nil, fmt.Errorf("key DATABASE_SECRET_USER (%s) is different than expected (%s)", actualUser, expectedUser)
 	}
 
 	if _, contains := sbrSecret.Data["DATABASE_SECRET_PASSWORD"]; !contains {
 		return nil, fmt.Errorf("can't find DATABASE_SECRET_PASSWORD in data")
 	}
-	if !bytes.Equal([]byte("password"), sbrSecret.Data["DATABASE_SECRET_PASSWORD"]) {
-		return nil, fmt.Errorf("key DATABASE_SECRET_PASSWORD is different than expected")
+	actualPassword := sbrSecret.Data["DATABASE_SECRET_PASSWORD"]
+	expectedPassword := []byte("password")
+	if !bytes.Equal(expectedPassword, actualPassword) {
+		return nil, fmt.Errorf("key DATABASE_SECRET_PASSWORD (%s) is different than expected (%s)", actualPassword, expectedPassword)
 	}
 
 	return sbrSecret, nil
@@ -203,7 +295,7 @@ func retry(attempts int, sleep time.Duration, fn func() error) error {
 
 // serviceBindingRequestTest executes the actual end-to-end testing, simulating the components and
 // expecting for changes caused by the operator.
-func serviceBindingRequestTest(t *testing.T, ctx *framework.TestCtx, f *framework.Framework, ns string) {
+func serviceBindingRequestTest(t *testing.T, ctx *framework.TestCtx, f *framework.Framework, ns string, steps []Step) {
 	todoCtx := context.TODO()
 
 	name := "e2e-service-binding-request"
@@ -221,42 +313,24 @@ func serviceBindingRequestTest(t *testing.T, ctx *framework.TestCtx, f *framewor
 	csv := mocks.ClusterServiceVersionMock(ns, "cluster-service-version")
 	require.Nil(t, f.Client.Create(todoCtx, &csv, cleanUpOptions(ctx)))
 
-	t.Log("Creating Database mock object...")
-	db := mocks.DatabaseCRMock(ns, resourceRef)
-	require.Nil(t, f.Client.Create(todoCtx, db, cleanUpOptions(ctx)))
-
-	t.Log("Updating Database status, adding 'DBCredentials'")
-	require.Nil(t, f.Client.Get(todoCtx, types.NamespacedName{Namespace: ns, Name: resourceRef}, db))
-	db.Status.DBCredentials = secretName
-	require.Nil(t, f.Client.Status().Update(todoCtx, db))
-
-	t.Log("Creating Database credentials secret mock object...")
-	dbSecret := mocks.SecretMock(ns, secretName)
-	require.Nil(t, f.Client.Create(todoCtx, dbSecret, cleanUpOptions(ctx)))
-
-	t.Log("Creating Deployment mock object...")
-	d := mocks.DeploymentMock(ns, appName, matchLabels)
-	require.Nil(t, f.Client.Create(todoCtx, &d, cleanUpOptions(ctx)))
-
-	// waiting for application deployment to reach one replica
-	t.Log("Waiting for application deployment reach one replica...")
-	require.Nil(t, e2eutil.WaitForDeployment(t, f.KubeClient, ns, appName, 1, retryInterval, timeout))
-
-	// retrieveing deployment, to inspect its contents
+	resourceRefNamespacedName := types.NamespacedName{Namespace: ns, Name: resourceRef}
 	deploymentNamespacedName := types.NamespacedName{Namespace: ns, Name: appName}
-	t.Logf("Reading application deployment '%s'", appName)
-	require.Nil(t, f.Client.Get(todoCtx, deploymentNamespacedName, &d))
-
-	// creating service-binding-request, which will trigger actions in the controller
-	t.Log("Creating ServiceBindingRequest mock object...")
-	sbr := mocks.ServiceBindingRequestMock(ns, name, resourceRef, "", matchLabels)
-	// making sure object does not exist before testing
-	_ = f.Client.Delete(todoCtx, sbr)
-	require.Nil(t, f.Client.Create(todoCtx, sbr, cleanUpOptions(ctx)))
-
-	// waiting again for deployment
-	t.Log("Waiting for application deployment reach one replica, again...")
-	require.Nil(t, e2eutil.WaitForDeployment(t, f.KubeClient, ns, appName, 1, retryInterval, timeout))
+	serviceBindingRequestNamespacedName := types.NamespacedName{Namespace: ns, Name: name}
+
+	var d appsv1.Deployment
+	var sbr *v1alpha1.ServiceBindingRequest
+
+	for _, step := range steps {
+		switch step {
+		case DBStep:
+			CreateDB(todoCtx, t, ctx, f, resourceRefNamespacedName, secretName)
+		case AppStep:
+			d = CreateApp(todoCtx, t, ctx, f, deploymentNamespacedName, matchLabels)
+		case SBRStep:
+			// creating service-binding-request, which will trigger actions in the controller
+			sbr = CreateServiceBindingRequest(todoCtx, t, ctx, f, serviceBindingRequestNamespacedName, resourceRef, matchLabels)
+		}
+	}
 
 	// retrying a few times to identify SBO changes in deployment, this loop is waiting for the
 	// operator reconciliation.
@@ -275,7 +349,7 @@ func serviceBindingRequestTest(t *testing.T, ctx *framework.TestCtx, f *framewor
 	// checking intermediary secret contents, right after deployment the secrets must be in place
 	intermediarySecretNamespacedName := types.NamespacedName{Namespace: ns, Name: name}
 	sbrSecret, err := assertSBRSecret(todoCtx, f, intermediarySecretNamespacedName)
-	assert.NoError(t, err)
+	assert.NoError(t, err, "Intermediary secret contents are invalid: %v", sbrSecret)
 
 	// editing intermediary secret in order to trigger update event
 	t.Logf("Updating intermediary secret to have bogus data: '%s'", intermediarySecretNamespacedName)
@@ -302,43 +376,17 @@ func serviceBindingRequestTest(t *testing.T, ctx *framework.TestCtx, f *framewor
 	_ = f.Client.Delete(todoCtx, &d)
 }
 
-// This test runs with following steps (scenario-2)
-// 1. Create SBR.
-// 2. Create operator-backed database CR.
-// 3. Create deployment where SBR would inject environment variables.
-// 4. Run assertion
-
-func preCreateServiceBindingRequestTest(t *testing.T, ctx *framework.TestCtx, f *framework.Framework, ns string) {
-	todoCtx := context.TODO()
-
-	name := "e2e-service-binding-request"
-	resourceRef := "e2e-db-testing"
-	secretName := "e2e-db-credentials"
-	appName := "e2e-application"
-	matchLabels := map[string]string{
-		"connects-to": "database",
-		"environment": "e2e",
-	}
-
-	t.Log("Starting end-to-end tests for operator!")
-
-	t.Log("Creating ClusterServiceVersion mock object...")
-	csv := mocks.ClusterServiceVersionMock(ns, "cluster-service-version")
-	require.Nil(t, f.Client.Create(todoCtx, &csv, cleanUpOptions(ctx)))
-
-	// creating service-binding-request, which will trigger actions in the controller
-	t.Log("Creating ServiceBindingRequest mock object...")
-	sbr := mocks.ServiceBindingRequestMock(ns, name, resourceRef, "", matchLabels)
-	// making sure object does not exist before testing
-	_ = f.Client.Delete(todoCtx, sbr)
-	require.Nil(t, f.Client.Create(todoCtx, sbr, cleanUpOptions(ctx)))
-
+// CreateDB implements end-to-end step for the creation of a Database CR along with the dependend Secret serving as a Backing Service
+// to be bound to the application.
+func CreateDB(todoCtx context.Context, t *testing.T, ctx *framework.TestCtx, f *framework.Framework, namespacedName types.NamespacedName, secretName string) *pgv1alpha1.Database {
+	ns := namespacedName.Namespace
+	resourceRef := namespacedName.Name
 	t.Log("Creating Database mock object...")
 	db := mocks.DatabaseCRMock(ns, resourceRef)
 	require.Nil(t, f.Client.Create(todoCtx, db, cleanUpOptions(ctx)))
 
 	t.Log("Updating Database status, adding 'DBCredentials'")
-	require.Nil(t, f.Client.Get(todoCtx, types.NamespacedName{Namespace: ns, Name: resourceRef}, db))
+	require.Nil(t, f.Client.Get(todoCtx, namespacedName, db))
 	db.Status.DBCredentials = secretName
 	require.Nil(t, f.Client.Status().Update(todoCtx, db))
 
@@ -346,6 +394,13 @@ func preCreateServiceBindingRequestTest(t *testing.T, ctx *framework.TestCtx, f
 	dbSecret := mocks.SecretMock(ns, secretName)
 	require.Nil(t, f.Client.Create(todoCtx, dbSecret, cleanUpOptions(ctx)))
 
+	return db
+}
+
+// CreateApp implements end-to-end step for the creation of a Deployment serving as the Application to which the Backing Service is bound.
+func CreateApp(todoCtx context.Context, t *testing.T, ctx *framework.TestCtx, f *framework.Framework, namespacedName types.NamespacedName, matchLabels map[string]string) appsv1.Deployment {
+	ns := namespacedName.Namespace
+	appName := namespacedName.Name
 	t.Log("Creating Deployment mock object...")
 	d := mocks.DeploymentMock(ns, appName, matchLabels)
 	require.Nil(t, f.Client.Create(todoCtx, &d, cleanUpOptions(ctx)))
@@ -355,54 +410,21 @@ func preCreateServiceBindingRequestTest(t *testing.T, ctx *framework.TestCtx, f
 	require.Nil(t, e2eutil.WaitForDeployment(t, f.KubeClient, ns, appName, 1, retryInterval, timeout))
 
 	// retrieveing deployment, to inspect its contents
-	deploymentNamespacedName := types.NamespacedName{Namespace: ns, Name: appName}
-	t.Logf("Reading application deployment '%s'", appName)
-	require.Nil(t, f.Client.Get(todoCtx, deploymentNamespacedName, &d))
-
-	// waiting again for deployment
-	t.Log("Waiting for application deployment reach one replica, again...")
-	require.Nil(t, e2eutil.WaitForDeployment(t, f.KubeClient, ns, appName, 1, retryInterval, timeout))
 
-	// retrying a few times to identify SBO changes in deployment, this loop is waiting for the
-	// operator reconciliation.
-	t.Log("Inspecting deployment structure...")
-	err := retry(10, 5*time.Second, func() error {
-		t.Logf("Inspecting deployment '%s'", deploymentNamespacedName)
-		_, err := assertDeploymentEnvFrom(todoCtx, f, deploymentNamespacedName, name)
-		if err != nil {
-			t.Logf("Error on inspecting deployment: '%#v'", err)
-		}
-		return err
-	})
-	t.Logf("Deployment: Result after attempts, error: '%#v'", err)
-	assert.NoError(t, err)
-
-	// checking intermediary secret contents, right after deployment the secrets must be in place
-	intermediarySecretNamespacedName := types.NamespacedName{Namespace: ns, Name: name}
-	sbrSecret, err := assertSBRSecret(todoCtx, f, intermediarySecretNamespacedName)
-	assert.NoError(t, err)
-
-	// editing intermediary secret in order to trigger update event
-	t.Logf("Updating intermediary secret to have bogus data: '%s'", intermediarySecretNamespacedName)
-	updateSecret(todoCtx, t, f, intermediarySecretNamespacedName)
+	t.Logf("Reading application deployment '%s'", appName)
+	require.Nil(t, f.Client.Get(todoCtx, namespacedName, &d))
 
-	// retrying a few times to see if secret is back on original state, waiting for operator to
-	// reconcile again when detecting the change
-	t.Log("Inspecting intermediary secret...")
-	err = retry(10, 5*time.Second, func() error {
-		t.Log("Inspecting SBR generated secret...")
-		_, err := assertSBRSecret(todoCtx, f, intermediarySecretNamespacedName)
-		if err != nil {
-			t.Logf("SBR generated secret inspection error: '%#v'", err)
-		}
-		return err
-	})
-	t.Logf("Intermediary-Secret: Result after attempts, error: '%#v'", err)
-	assert.NoError(t, err)
+	return d
+}
 
-	// cleaning up
-	t.Log("Cleaning all up!")
+// CreateServiceBindingRequest implements end-to-end step for creating a Service Binding Request to bind the Backing Service and the Application
+func CreateServiceBindingRequest(todoCtx context.Context, t *testing.T, ctx *framework.TestCtx, f *framework.Framework, namespacedName types.NamespacedName, resourceRef string, matchLabels map[string]string) *v1alpha1.ServiceBindingRequest {
+	ns := namespacedName.Namespace
+	name := namespacedName.Name
+	t.Log("Creating ServiceBindingRequest mock object...")
+	sbr := mocks.ServiceBindingRequestMock(ns, name, resourceRef, "", matchLabels, false)
+	// making sure object does not exist before testing
 	_ = f.Client.Delete(todoCtx, sbr)
-	_ = f.Client.Delete(todoCtx, sbrSecret)
-	_ = f.Client.Delete(todoCtx, &d)
+	require.Nil(t, f.Client.Create(todoCtx, sbr, cleanUpOptions(ctx)))
+	return sbr
 }
diff --git a/test/mocks/fake.go b/test/mocks/fake.go
index a3f8b3f3..d327179c 100644
--- a/test/mocks/fake.go
+++ b/test/mocks/fake.go
@@ -35,7 +35,21 @@ func (f *Fake) AddMockedServiceBindingRequest(
 	matchLabels map[string]string,
 ) *v1alpha1.ServiceBindingRequest {
 	f.S.AddKnownTypes(v1alpha1.SchemeGroupVersion, &v1alpha1.ServiceBindingRequest{})
-	sbr := ServiceBindingRequestMock(f.ns, name, backingServiceResourceRef, applicationResourceRef, matchLabels)
+	sbr := ServiceBindingRequestMock(f.ns, name, backingServiceResourceRef, applicationResourceRef, matchLabels, false)
+	f.objs = append(f.objs, sbr)
+	return sbr
+}
+
+
+// AddMockedServiceBindingRequestWithUnannotated add mocked object from ServiceBindingRequestMock with DetectBindingResources.
+func (f *Fake) AddMockedServiceBindingRequestWithUnannotated(
+	name string,
+	backingServiceResourceRef string,
+	applicationResourceRef string,
+	matchLabels map[string]string,
+) *v1alpha1.ServiceBindingRequest {
+	f.S.AddKnownTypes(v1alpha1.SchemeGroupVersion, &v1alpha1.ServiceBindingRequest{})
+	sbr := ServiceBindingRequestMock(f.ns, name, backingServiceResourceRef, applicationResourceRef, matchLabels, true)
 	f.objs = append(f.objs, sbr)
 	return sbr
 }
@@ -119,6 +133,10 @@ func (f *Fake) AddMockedConfigMap(name string) {
 	f.objs = append(f.objs, ConfigMapMock(f.ns, name))
 }
 
+func (f *Fake) AddMockResource(resource runtime.Object) {
+	f.objs = append(f.objs, resource)
+}
+
 // FakeClient returns fake structured api client.
 func (f *Fake) FakeClient() client.Client {
 	return fake.NewFakeClientWithScheme(f.S, f.objs...)
diff --git a/test/mocks/mocks.go b/test/mocks/mocks.go
index f6ea5cf1..73a7ab6f 100644
--- a/test/mocks/mocks.go
+++ b/test/mocks/mocks.go
@@ -15,7 +15,8 @@ import (
 	ustrv1 "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
 	"k8s.io/apimachinery/pkg/runtime"
 
-	v1alpha1 "github.com/redhat-developer/service-binding-operator/pkg/apis/apps/v1alpha1"
+	ocv1 "github.com/openshift/api/route/v1"
+	"github.com/redhat-developer/service-binding-operator/pkg/apis/apps/v1alpha1"
 )
 
 // resource details employed in mocks
@@ -237,6 +238,23 @@ func DatabaseCRMock(ns, name string) *pgv1alpha1.Database {
 	}
 }
 
+func RouteCRMock(ns, name string) *ocv1.Route {
+	return &ocv1.Route{
+		TypeMeta: metav1.TypeMeta{
+			Kind:       "Route",
+			APIVersion: "v1",
+		},
+		ObjectMeta: metav1.ObjectMeta{
+			Name:      name,
+			Namespace: ns,
+		},
+		Spec: ocv1.RouteSpec{
+			Host: "https://openshift.cluster.com/host_url",
+		},
+		Status: ocv1.RouteStatus{},
+	}
+}
+
 // UnstructuredDatabaseCRMock returns a unstructured version of DatabaseCRMock.
 func UnstructuredDatabaseCRMock(ns, name string) (*unstructured.Unstructured, error) {
 	db := DatabaseCRMock(ns, name)
@@ -287,6 +305,7 @@ func ServiceBindingRequestMock(
 	backingServiceResourceRef string,
 	applicationResourceRef string,
 	matchLabels map[string]string,
+	bindUnannotated bool,
 ) *v1alpha1.ServiceBindingRequest {
 	return &v1alpha1.ServiceBindingRequest{
 		ObjectMeta: metav1.ObjectMeta{
@@ -295,6 +314,12 @@ func ServiceBindingRequestMock(
 		},
 		Spec: v1alpha1.ServiceBindingRequestSpec{
 			MountPathPrefix: "/var/redhat",
+			CustomEnvVar: []v1alpha1.CustomEnvMap{
+				{
+					Name:  "IMAGE_PATH",
+					Value: "spec.imagePath",
+				},
+			},
 			BackingServiceSelector: v1alpha1.BackingServiceSelector{
 				Group:       CRDName,
 				Version:     CRDVersion,
@@ -308,12 +333,7 @@ func ServiceBindingRequestMock(
 				ResourceRef: applicationResourceRef,
 				MatchLabels: matchLabels,
 			},
-			CustomEnvVar: []v1alpha1.CustomEnvMap{
-				{
-					Name:  "IMAGE_PATH",
-					Value: "spec.imagePath",
-				},
-			},
+			DetectBindingResources: bindUnannotated,
 		},
 	}
 }
@@ -326,7 +346,7 @@ func UnstructuredServiceBindingRequestMock(
 	applicationResourceRef string,
 	matchLabels map[string]string,
 ) (*unstructured.Unstructured, error) {
-	sbr := ServiceBindingRequestMock(ns, name, backingServiceResourceRef, applicationResourceRef, matchLabels)
+	sbr := ServiceBindingRequestMock(ns, name, backingServiceResourceRef, applicationResourceRef, matchLabels, false)
 	data, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&sbr)
 	if err != nil {
 		return nil, err
@@ -450,8 +470,8 @@ func UnstructuredNestedDatabaseCRMock(ns, name string) (*unstructured.Unstructur
 // ConfigMapDatabaseSpec ...
 type ConfigMapDatabaseSpec struct {
 	DBConfigMap string `json:"dbConfigMap"`
-	ImageName string
-	Image string
+	ImageName   string
+	Image       string
 }
 
 // ConfigMapDatabase ...
@@ -475,8 +495,8 @@ func DatabaseConfigMapMock(ns, name, configMapName string) *ConfigMapDatabase {
 		},
 		Spec: ConfigMapDatabaseSpec{
 			DBConfigMap: configMapName,
-			Image: "docker.io/postgres",
-			ImageName: "postgres",
+			Image:       "docker.io/postgres",
+			ImageName:   "postgres",
 		},
 	}
 }