diff --git a/.gitignore b/.gitignore
index 77095eb5a..b3fe119b6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -71,3 +71,5 @@ releasenotes/build
 
 # Gate and Check Logs
 logs/
+tools/gate/local-overrides/
+tools/gate/playbooks/*.retry
diff --git a/calico/templates/daemonset-calico-etcd.yaml b/calico/templates/daemonset-calico-etcd.yaml
index 4b2b83533..018e4c38c 100644
--- a/calico/templates/daemonset-calico-etcd.yaml
+++ b/calico/templates/daemonset-calico-etcd.yaml
@@ -51,7 +51,7 @@ spec:
       hostNetwork: true
       containers:
         - name: calico-etcd
-          image: {{ .Values.images.tags.calico_etcd }}
+{{ tuple $envAll "calico_etcd" | include "helm-toolkit.snippets.image" | indent 10 }}
           env:
             - name: CALICO_ETCD_IP
               valueFrom:
diff --git a/calico/templates/daemonset-calico-node.yaml b/calico/templates/daemonset-calico-node.yaml
index b37ec04d6..02a94f8d5 100644
--- a/calico/templates/daemonset-calico-node.yaml
+++ b/calico/templates/daemonset-calico-node.yaml
@@ -57,7 +57,7 @@ spec:
         # container programs network policy and routes on each
         # host.
         - name: calico-node
-          image: {{ .Values.images.tags.calico_node }}
+{{ tuple $envAll "calico_node" | include "helm-toolkit.snippets.image" | indent 10 }}
           env:
             # The location of the Calico etcd cluster.
             - name: ETCD_ENDPOINTS
diff --git a/calico/templates/deployment-calico-policy-controller.yaml b/calico/templates/deployment-calico-policy-controller.yaml
index 4280690c1..20431bf69 100644
--- a/calico/templates/deployment-calico-policy-controller.yaml
+++ b/calico/templates/deployment-calico-policy-controller.yaml
@@ -55,7 +55,7 @@ spec:
       serviceAccountName: calico-policy-controller
       containers:
         - name: calico-policy-controller
-          image: {{ .Values.images.tags.calico_kube_policy_controller }}
+{{ tuple $envAll "calico_kube_policy_controller" | include "helm-toolkit.snippets.image" | indent 10 }}
           env:
             # The location of the Calico etcd cluster.
             - name: ETCD_ENDPOINTS
diff --git a/calico/values.yaml b/calico/values.yaml
index 5dae057e6..36f03aa67 100644
--- a/calico/values.yaml
+++ b/calico/values.yaml
@@ -26,6 +26,9 @@ images:
     calico_node: quay.io/calico/node:v2.4.1
     calico_cni: quay.io/calico/cni:v1.10.0
     calico_kube_policy_controller: quay.io/calico/kube-policy-controller:v0.7.0
+  pull_policy: IfNotPresent
+  registry:
+    prefix: null
 
 networking:
   podSubnet: 192.168.0.0/16
diff --git a/flannel/templates/daemonset-kube-flannel-ds.yaml b/flannel/templates/daemonset-kube-flannel-ds.yaml
index 192185acd..9fd628be6 100644
--- a/flannel/templates/daemonset-kube-flannel-ds.yaml
+++ b/flannel/templates/daemonset-kube-flannel-ds.yaml
@@ -42,7 +42,7 @@ spec:
       serviceAccountName: flannel
       containers:
         - name: kube-flannel
-          image: {{ .Values.images.tags.flannel }}
+{{ tuple $envAll "flannel" | include "helm-toolkit.snippets.image" | indent 10 }}
           command: [ "/opt/bin/flanneld", "--ip-masq", "--kube-subnet-mgr" ]
           securityContext:
             privileged: true
diff --git a/flannel/values.yaml b/flannel/values.yaml
index b295f0608..e89f45b36 100644
--- a/flannel/values.yaml
+++ b/flannel/values.yaml
@@ -17,6 +17,9 @@
 images:
   tags:
     flannel: quay.io/coreos/flannel:v0.8.0-amd64
+  pull_policy: IfNotPresent
+  registry:
+    prefix: null
 
 networking:
   podSubnet: 192.168.0.0/16
diff --git a/helm-toolkit/templates/snippets/_image.tpl b/helm-toolkit/templates/snippets/_image.tpl
new file mode 100644
index 000000000..428b8117e
--- /dev/null
+++ b/helm-toolkit/templates/snippets/_image.tpl
@@ -0,0 +1,27 @@
+{{/*
+Copyright 2017 The Openstack-Helm Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/}}
+
+{{- define "helm-toolkit.snippets.image" -}}
+{{- $envAll := index . 0 -}}
+{{- $image := index . 1 -}}
+{{- $imageTag := index $envAll.Values.images.tags $image -}}
+{{- if $envAll.Values.images.registry.prefix -}}
+image: {{ printf "%s/%s" $envAll.Values.images.registry.prefix $imageTag | quote }}
+{{- else -}}
+image: {{ $imageTag | quote }}
+{{- end }}
+imagePullPolicy: {{ $envAll.Values.images.pull_policy }}
+{{- end -}}
diff --git a/kube-dns/templates/deployment-kube-dns.yaml b/kube-dns/templates/deployment-kube-dns.yaml
index 2c0d447f4..847d5c4c7 100644
--- a/kube-dns/templates/deployment-kube-dns.yaml
+++ b/kube-dns/templates/deployment-kube-dns.yaml
@@ -51,8 +51,7 @@ spec:
                       - amd64
       containers:
         - name: kubedns
-          image: {{ .Values.images.tags.kube_dns }}
-          imagePullPolicy: IfNotPresent
+{{ tuple $envAll "kube_dns" | include "helm-toolkit.snippets.image" | indent 10 }}
           args:
             - --domain={{ .Values.networking.dnsDomain }}.
             - --dns-port=10053
@@ -103,8 +102,7 @@ spec:
             - mountPath: /kube-dns-config
               name: kube-dns-config
         - name: dnsmasq
-          image: {{ .Values.images.tags.kube_dns_nanny }}
-          imagePullPolicy: IfNotPresent
+{{ tuple $envAll "kube_dns_nanny" | include "helm-toolkit.snippets.image" | indent 10 }}
           args:
             - -v=2
             - -logtostderr
@@ -144,8 +142,7 @@ spec:
             - mountPath: /etc/k8s/dns/dnsmasq-nanny
               name: kube-dns-config
         - name: sidecar
-          image: {{ .Values.images.tags.kube_dns_sidecar }}
-          imagePullPolicy: IfNotPresent
+{{ tuple $envAll "kube_dns_sidecar" | include "helm-toolkit.snippets.image" | indent 10 }}
           args:
             - --v=2
             - --logtostderr
diff --git a/kube-dns/values.yaml b/kube-dns/values.yaml
index 824099837..da7b19e2d 100644
--- a/kube-dns/values.yaml
+++ b/kube-dns/values.yaml
@@ -19,6 +19,9 @@ images:
     kube_dns: gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.14.5
     kube_dns_nanny: gcr.io/google_containers/k8s-dns-dnsmasq-nanny-amd64:1.14.5
     kube_dns_sidecar: gcr.io/google_containers/k8s-dns-sidecar-amd64:1.14.5
+  pull_policy: IfNotPresent
+  registry:
+    prefix: null
 
 networking:
   dnsDomain: cluster.local
diff --git a/nfs-provisioner/Chart.yaml b/nfs-provisioner/Chart.yaml
new file mode 100644
index 000000000..1ac8815f7
--- /dev/null
+++ b/nfs-provisioner/Chart.yaml
@@ -0,0 +1,24 @@
+# Copyright 2017 The Openstack-Helm Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+apiVersion: v1
+description: OpenStack-Helm NFS
+name: nfs-provisioner
+version: 0.1.0
+home: https://github.com/kubernetes-incubator/external-storage
+sources:
+  - https://github.com/kubernetes-incubator/external-storage
+  - https://git.openstack.org/cgit/openstack/openstack-helm
+maintainers:
+  - name: OpenStack-Helm Authors
diff --git a/nfs-provisioner/requirements.yaml b/nfs-provisioner/requirements.yaml
new file mode 100644
index 000000000..00a045b4e
--- /dev/null
+++ b/nfs-provisioner/requirements.yaml
@@ -0,0 +1,19 @@
+
+# Copyright 2017 The Openstack-Helm Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+dependencies:
+  - name: helm-toolkit
+    repository: http://localhost:8879/charts
+    version: 0.1.0
diff --git a/nfs-provisioner/templates/deployment.yaml b/nfs-provisioner/templates/deployment.yaml
new file mode 100644
index 000000000..a333fbe9b
--- /dev/null
+++ b/nfs-provisioner/templates/deployment.yaml
@@ -0,0 +1,77 @@
+{{/*
+Copyright 2017 The Openstack-Helm Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/}}
+
+{{- if .Values.manifests.deployment }}
+{{- $envAll := . }}
+---
+kind: Deployment
+apiVersion: apps/v1beta1
+metadata:
+  name: nfs-provisioner
+spec:
+  replicas: {{ .Values.pod.replicas.server }}
+  strategy:
+    type: Recreate
+  template:
+    metadata:
+      labels:
+{{ tuple $envAll "nfs" "provisioner" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }}
+    spec:
+      affinity:
+{{ tuple $envAll "nfs" "provisioner" | include "helm-toolkit.snippets.kubernetes_pod_anti_affinity" | indent 8 }}
+      nodeSelector:
+        {{ .Values.labels.node_selector_key }}: {{ .Values.labels.node_selector_value }}
+      containers:
+        - name: nfs-provisioner
+{{ tuple $envAll "nfs_provisioner" | include "helm-toolkit.snippets.image" | indent 10 }}
+{{ tuple $envAll $envAll.Values.pod.resources.server | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
+          securityContext:
+            capabilities:
+              add:
+                - DAC_READ_SEARCH
+                - SYS_RESOURCE
+          ports:
+            - name: nfs
+              containerPort: 2049
+            - name: mountd
+              containerPort: 20048
+            - name: rpcbind
+              containerPort: 111
+            - name: rpcbind-udp
+              containerPort: 111
+              protocol: UDP
+          env:
+            - name: POD_IP
+              valueFrom:
+                fieldRef:
+                  fieldPath: status.podIP
+            - name: SERVICE_NAME
+              value: {{ tuple "nfs" "internal" . | include "helm-toolkit.endpoints.hostname_short_endpoint_lookup" }}
+            - name: POD_NAMESPACE
+              valueFrom:
+                fieldRef:
+                  fieldPath: metadata.namespace
+          args:
+            - "-provisioner={{ .Values.storageclass.provisioner }}"
+            - "-grace-period=10"
+          volumeMounts:
+            - name: export-volume
+              mountPath: /export
+      volumes:
+        - name: export-volume
+          hostPath:
+            path: {{ .Values.storage.host.host_path }}
+{{- end }}
diff --git a/nfs-provisioner/templates/service.yaml b/nfs-provisioner/templates/service.yaml
new file mode 100644
index 000000000..7ece1f5cb
--- /dev/null
+++ b/nfs-provisioner/templates/service.yaml
@@ -0,0 +1,39 @@
+{{/*
+Copyright 2017 The Openstack-Helm Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/}}
+
+{{- if .Values.manifests.service }}
+{{- $envAll := . }}
+---
+kind: Service
+apiVersion: v1
+metadata:
+  name: {{ tuple "nfs" "internal" . | include "helm-toolkit.endpoints.hostname_short_endpoint_lookup" }}
+  labels:
+{{ tuple $envAll "nfs" "provisioner" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }}
+spec:
+  ports:
+    - name: nfs
+      port: 2049
+    - name: mountd
+      port: 20048
+    - name: rpcbind
+      port: 111
+    - name: rpcbind-udp
+      port: 111
+      protocol: UDP
+  selector:
+{{ tuple $envAll "nfs" "provisioner" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }}
+{{- end }}
diff --git a/nfs-provisioner/templates/storage_class.yaml b/nfs-provisioner/templates/storage_class.yaml
new file mode 100644
index 000000000..1fa0c8946
--- /dev/null
+++ b/nfs-provisioner/templates/storage_class.yaml
@@ -0,0 +1,27 @@
+{{/*
+Copyright 2017 The Openstack-Helm Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/}}
+
+{{- if .Values.manifests.storage_class }}
+{{- $envAll := . }}
+---
+kind: StorageClass
+apiVersion: storage.k8s.io/v1
+metadata:
+  name: {{ .Values.storageclass.name }}
+provisioner: {{ .Values.storageclass.provisioner }}
+parameters:
+  mountOptions: vers=4.1
+{{- end }}
diff --git a/nfs-provisioner/values.yaml b/nfs-provisioner/values.yaml
new file mode 100644
index 000000000..d9bc1ede5
--- /dev/null
+++ b/nfs-provisioner/values.yaml
@@ -0,0 +1,74 @@
+# Copyright 2017 The Openstack-Helm Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Default values for NFS.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+pod:
+  affinity:
+    anti:
+      type:
+        default: preferredDuringSchedulingIgnoredDuringExecution
+      topologyKey:
+        default: kubernetes.io/hostname
+  replicas:
+    #only 1 replica currently supported
+    server: 1
+  resources:
+    enabled: false
+    server:
+      requests:
+        memory: "128Mi"
+        cpu: "100m"
+      limits:
+        memory: "1024Mi"
+        cpu: "2000m"
+
+images:
+  tags:
+    nfs_provisioner: quay.io/kubernetes_incubator/nfs-provisioner:v1.0.8
+  pull_policy: IfNotPresent
+  registry:
+    prefix: null
+
+storage:
+  host:
+    host_path: /var/lib/openstack-helm/nfs
+
+labels:
+  node_selector_key: openstack-control-plane
+  node_selector_value: enabled
+
+storageclass:
+  provisioner: example.com/nfs
+  name: general
+
+endpoints:
+  cluster_domain_suffix: cluster.local
+  nfs:
+    hosts:
+      default: nfs-provisioner
+    host_fqdn_override:
+      default: null
+    path: null
+    scheme: null
+    port:
+      nfs:
+        default: null
+
+manifests:
+  deployment: true
+  service: true
+  storage_class: true
diff --git a/redis/Chart.yaml b/redis/Chart.yaml
new file mode 100644
index 000000000..0fc101471
--- /dev/null
+++ b/redis/Chart.yaml
@@ -0,0 +1,18 @@
+# Copyright 2017 The Openstack-Helm Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+apiVersion: v1
+description: OpenStack-Helm Redis
+name: redis
+version: 0.1.0
diff --git a/redis/requirements.yaml b/redis/requirements.yaml
new file mode 100644
index 000000000..53782e69b
--- /dev/null
+++ b/redis/requirements.yaml
@@ -0,0 +1,18 @@
+# Copyright 2017 The Openstack-Helm Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+dependencies:
+  - name: helm-toolkit
+    repository: http://localhost:8879/charts
+    version: 0.1.0
diff --git a/redis/templates/deployment.yaml b/redis/templates/deployment.yaml
new file mode 100644
index 000000000..369e39122
--- /dev/null
+++ b/redis/templates/deployment.yaml
@@ -0,0 +1,47 @@
+{{/*
+Copyright 2017 The Openstack-Helm Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/}}
+
+{{- $envAll := . }}
+---
+apiVersion: apps/v1beta1
+kind: Deployment
+metadata:
+  name: redis
+spec:
+  replicas: {{ .Values.pod.replicas.server }}
+{{ tuple $envAll | include "helm-toolkit.snippets.kubernetes_upgrades_deployment" | indent 2 }}
+  template:
+    metadata:
+      labels:
+{{ tuple $envAll "redis" "server" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }}
+    spec:
+      affinity:
+{{ tuple $envAll "redis" "server" | include "helm-toolkit.snippets.kubernetes_pod_anti_affinity" | indent 8 }}
+      nodeSelector:
+        {{ .Values.labels.node_selector_key }}: {{ .Values.labels.node_selector_value }}
+      containers:
+        - name: redis
+{{ tuple $envAll "redis" | include "helm-toolkit.snippets.image" | indent 10 }}
+{{ tuple $envAll $envAll.Values.pod.resources.server | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
+          command: ["sh", "-xec"]
+          args:
+            - |
+              exec redis-server --port {{ .Values.network.port }}
+          ports:
+            - containerPort: {{ .Values.network.port }}
+          readinessProbe:
+            tcpSocket:
+              port: {{ .Values.network.port }}
diff --git a/redis/templates/service.yaml b/redis/templates/service.yaml
new file mode 100644
index 000000000..66cbc467d
--- /dev/null
+++ b/redis/templates/service.yaml
@@ -0,0 +1,27 @@
+{{/*
+Copyright 2017 The Openstack-Helm Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/}}
+{{- $envAll := . }}
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: redis
+spec:
+  clusterIP: None
+  ports:
+    - port: {{ .Values.network.port }}
+  selector:
+{{ tuple $envAll "redis" "server" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }}
diff --git a/redis/values.yaml b/redis/values.yaml
new file mode 100644
index 000000000..036300d01
--- /dev/null
+++ b/redis/values.yaml
@@ -0,0 +1,59 @@
+# Copyright 2017 The Openstack-Helm Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Default values for redis.
+# This is a YAML-formatted file.
+# Declare name/value pairs to be passed into your templates.
+# name: value
+
+images:
+  tags:
+    redis: docker.io/redis:4.0.1
+  pull_policy: "IfNotPresent"
+  registry:
+    prefix: null
+
+pod:
+  affinity:
+      anti:
+        type:
+          default: preferredDuringSchedulingIgnoredDuringExecution
+        topologyKey:
+          default: kubernetes.io/hostname
+  replicas:
+    server: 1
+  lifecycle:
+    upgrades:
+      deployments:
+        revision_history: 3
+        pod_replacement_strategy: RollingUpdate
+        rolling_update:
+          max_unavailable: 1
+          max_surge: 3
+  resources:
+    enabled: false
+    server:
+      limits:
+        memory: "128Mi"
+        cpu: "500m"
+      requests:
+        memory: "128Mi"
+        cpu: "500m"
+
+labels:
+  node_selector_key: openstack-control-plane
+  node_selector_value: enabled
+
+network:
+  port: 6379
diff --git a/registry/Chart.yaml b/registry/Chart.yaml
new file mode 100644
index 000000000..116bec42d
--- /dev/null
+++ b/registry/Chart.yaml
@@ -0,0 +1,22 @@
+# Copyright 2017 The Openstack-Helm Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+description: OpenStack-Helm Docker Registry
+name: registry
+version: 0.1.0
+home: https://github.com/kubernetes/ingress
+sources:
+  - https://git.openstack.org/cgit/openstack/openstack-helm
+maintainers:
+  - name: OpenStack-Helm Authors
diff --git a/registry/requirements.yaml b/registry/requirements.yaml
new file mode 100644
index 000000000..53782e69b
--- /dev/null
+++ b/registry/requirements.yaml
@@ -0,0 +1,18 @@
+# Copyright 2017 The Openstack-Helm Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+dependencies:
+  - name: helm-toolkit
+    repository: http://localhost:8879/charts
+    version: 0.1.0
diff --git a/registry/templates/bin/_bootstrap.sh.tpl b/registry/templates/bin/_bootstrap.sh.tpl
new file mode 100644
index 000000000..bd93ee4f1
--- /dev/null
+++ b/registry/templates/bin/_bootstrap.sh.tpl
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+{{/*
+Copyright 2017 The Openstack-Helm Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/}}
+
+set -ex
+
+{{ .Values.bootstrap.script | default "echo 'Not Enabled'" }}
+
+IFS=',' ; for IMAGE in ${PRELOAD_IMAGES}; do
+  docker pull ${IMAGE}
+  docker tag ${IMAGE} ${LOCAL_REPO}/${IMAGE}
+  docker push ${LOCAL_REPO}/${IMAGE}
+done
diff --git a/registry/templates/bin/_registry-proxy.sh.tpl b/registry/templates/bin/_registry-proxy.sh.tpl
new file mode 100644
index 000000000..2744bb2f0
--- /dev/null
+++ b/registry/templates/bin/_registry-proxy.sh.tpl
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+{{/*
+Copyright 2017 The Openstack-Helm Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/}}
+
+set -ex
+
+exec nginx -g "daemon off;"
diff --git a/registry/templates/bin/_registry.sh.tpl b/registry/templates/bin/_registry.sh.tpl
new file mode 100644
index 000000000..d17a7d06a
--- /dev/null
+++ b/registry/templates/bin/_registry.sh.tpl
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+{{/*
+Copyright 2017 The Openstack-Helm Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/}}
+
+set -ex
+
+exec registry serve /etc/docker/registry/config.yml
diff --git a/registry/templates/configmap-bin.yaml b/registry/templates/configmap-bin.yaml
new file mode 100644
index 000000000..92a86a406
--- /dev/null
+++ b/registry/templates/configmap-bin.yaml
@@ -0,0 +1,31 @@
+{{/*
+Copyright 2017 The Openstack-Helm Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/}}
+
+{{- if .Values.manifests.configmap_bin }}
+{{- $envAll := . }}
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: registry-bin
+data:
+  bootstrap.sh: |+
+{{ tuple "bin/_bootstrap.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
+  registry.sh: |+
+{{ tuple "bin/_registry.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
+  registry-proxy.sh: |+
+{{ tuple "bin/_registry-proxy.sh.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
+{{- end }}
diff --git a/registry/templates/configmap-etc.yaml b/registry/templates/configmap-etc.yaml
new file mode 100644
index 000000000..839da4a1c
--- /dev/null
+++ b/registry/templates/configmap-etc.yaml
@@ -0,0 +1,38 @@
+{{/*
+Copyright 2017 The Openstack-Helm Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/}}
+
+{{- if .Values.manifests.configmap_bin }}
+{{- $envAll := . }}
+
+{{- if empty .Values.conf.registry.http.addr -}}
+{{ cat "0.0.0.0" (tuple "docker_registry" "internal" "registry" . | include "helm-toolkit.endpoints.endpoint_port_lookup") | replace " " ":" | set .Values.conf.registry.http "addr" | quote | trunc 0 -}}
+{{- end -}}
+
+{{- if empty .Values.conf.registry.redis.addr -}}
+{{ tuple "redis" "internal" "redis" . | include "helm-toolkit.endpoints.host_and_port_endpoint_uri_lookup" | set .Values.conf.registry.redis "addr" | quote | trunc 0 -}}
+{{- end -}}
+
+---
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: registry-etc
+data:
+  config.yml: |+
+{{  toYaml .Values.conf.registry | indent 4 }}
+  default.conf: |+
+{{ tuple "etc/_default.conf.tpl" . | include "helm-toolkit.utils.template" | indent 4 }}
+{{- end }}
diff --git a/registry/templates/daemonset-registry-proxy.yaml b/registry/templates/daemonset-registry-proxy.yaml
new file mode 100644
index 000000000..0212528cb
--- /dev/null
+++ b/registry/templates/daemonset-registry-proxy.yaml
@@ -0,0 +1,64 @@
+{{/*
+Copyright 2017 The Openstack-Helm Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/}}
+
+{{- if .Values.manifests.daemonset_registry_proxy }}
+{{- $envAll := . }}
+{{- $dependencies := .Values.dependencies.registry_proxy }}
+---
+apiVersion: extensions/v1beta1
+kind: DaemonSet
+metadata:
+  name: docker-registry-proxy
+spec:
+  template:
+    metadata:
+      labels:
+{{ tuple $envAll "docker" "registry-proxy" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }}
+      annotations:
+        configmap-bin-hash: {{ tuple "configmap-bin.yaml" . | include "helm-toolkit.utils.hash" }}
+        configmap-etc-hash: {{ tuple "configmap-etc.yaml" . | include "helm-toolkit.utils.hash" }}
+    spec:
+      nodeSelector:
+        {{ .Values.labels.node_selector_key }}: {{ .Values.labels.node_selector_value }}
+      dnsPolicy: ClusterFirstWithHostNet
+      hostNetwork: true
+      initContainers:
+{{ tuple $envAll $dependencies "[]" | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }}
+      containers:
+      - name: registry-proxy
+{{ tuple $envAll "registry_proxy" | include "helm-toolkit.snippets.image" | indent 8 }}
+{{ tuple $envAll $envAll.Values.pod.resources.registry_proxy | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
+        command:
+          - /tmp/registry-proxy.sh
+        volumeMounts:
+          - name: registry-bin
+            mountPath: /tmp/registry-proxy.sh
+            subPath: registry-proxy.sh
+            readOnly: true
+          - name: registry-etc
+            mountPath: /etc/nginx/conf.d/default.conf
+            subPath: default.conf
+            readOnly: true
+      volumes:
+        - name: registry-bin
+          configMap:
+            name: registry-bin
+            defaultMode: 0555
+        - name: registry-etc
+          configMap:
+            name: registry-etc
+            defaultMode: 0444
+{{- end }}
diff --git a/registry/templates/deployment-registry.yaml b/registry/templates/deployment-registry.yaml
new file mode 100644
index 000000000..6f2b9da73
--- /dev/null
+++ b/registry/templates/deployment-registry.yaml
@@ -0,0 +1,74 @@
+{{/*
+Copyright 2017 The Openstack-Helm Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/}}
+
+{{- if .Values.manifests.deployment_registry }}
+{{- $envAll := . }}
+{{- $dependencies := .Values.dependencies.registry }}
+---
+apiVersion: apps/v1beta1
+kind: Deployment
+metadata:
+  name: docker-registry
+spec:
+  replicas: {{ .Values.pod.replicas.registry }}
+{{ tuple $envAll | include "helm-toolkit.snippets.kubernetes_upgrades_deployment" | indent 2 }}
+  template:
+    metadata:
+      labels:
+{{ tuple $envAll "docker" "registry" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }}
+      annotations:
+        configmap-bin-hash: {{ tuple "configmap-bin.yaml" . | include "helm-toolkit.utils.hash" }}
+        configmap-etc-hash: {{ tuple "configmap-etc.yaml" . | include "helm-toolkit.utils.hash" }}
+    spec:
+      affinity:
+{{ tuple $envAll "docker" "registry" | include "helm-toolkit.snippets.kubernetes_pod_anti_affinity" | indent 8 }}
+      nodeSelector:
+        {{ .Values.labels.node_selector_key }}: {{ .Values.labels.node_selector_value }}
+      initContainers:
+{{ tuple $envAll $dependencies "[]" | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container" | indent 8 }}
+      containers:
+        - name: registry
+{{ tuple $envAll "registry" | include "helm-toolkit.snippets.image" | indent 10 }}
+{{ tuple $envAll $envAll.Values.pod.resources.registry | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
+          ports:
+            - name: d-reg
+              containerPort: {{ tuple "docker_registry" "internal" "registry" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
+          command:
+            - /tmp/registry.sh
+          volumeMounts:
+          - name: registry-bin
+            mountPath: /tmp/registry.sh
+            subPath: registry.sh
+            readOnly: true
+          - name: registry-etc
+            mountPath: /etc/docker/registry/config.yml
+            subPath: config.yml
+            readOnly: true
+          - name: docker-images
+            mountPath: {{ .Values.conf.registry.storage.filesystem.rootdirectory }}
+      volumes:
+        - name: registry-bin
+          configMap:
+            name: registry-bin
+            defaultMode: 0555
+        - name: registry-etc
+          configMap:
+            name: registry-etc
+            defaultMode: 0444
+        - name: docker-images
+          persistentVolumeClaim:
+            claimName: docker-images
+{{- end }}
diff --git a/registry/templates/etc/_default.conf.tpl b/registry/templates/etc/_default.conf.tpl
new file mode 100644
index 000000000..c387fe4cc
--- /dev/null
+++ b/registry/templates/etc/_default.conf.tpl
@@ -0,0 +1,28 @@
+# Docker registry proxy for api version 2
+
+upstream docker-registry {
+    server {{ tuple "docker_registry" "internal" "registry" . | include "helm-toolkit.endpoints.host_and_port_endpoint_uri_lookup" }};
+}
+
+# No client auth or TLS
+# TODO(bacongobbler): experiment with authenticating the registry if it's using TLS
+server {
+    listen {{ tuple "docker_registry" "public" "registry" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }};
+    server_name localhost;
+
+    # disable any limits to avoid HTTP 413 for large image uploads
+    client_max_body_size 0;
+
+    # required to avoid HTTP 411: see Issue #1486 (https://github.com/docker/docker/issues/1486)
+    chunked_transfer_encoding on;
+
+    location / {
+        # Do not allow connections from docker 1.5 and earlier
+        # docker pre-1.6.0 did not properly set the user agent on ping, catch "Go *" user agents
+        if ($http_user_agent ~ "^(docker\/1\.(3|4|5(?!\.[0-9]-dev))|Go ).*$" ) {
+            return 404;
+        }
+
+        include docker-registry.conf;
+    }
+}
diff --git a/registry/templates/job-bootstrap.yaml b/registry/templates/job-bootstrap.yaml
new file mode 100644
index 000000000..d873eb5d9
--- /dev/null
+++ b/registry/templates/job-bootstrap.yaml
@@ -0,0 +1,64 @@
+{{/*
+Copyright 2017 The Openstack-Helm Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/}}
+
+{{- if .Values.manifests.job_bootstrap }}
+{{- $envAll := . }}
+{{- if .Values.bootstrap.enabled }}
+{{- $dependencies := .Values.dependencies.bootstrap }}
+---
+apiVersion: batch/v1
+kind: Job
+metadata:
+  name: docker-bootstrap
+spec:
+  template:
+    metadata:
+      labels:
+{{ tuple $envAll "docker" "bootstrap" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 8 }}
+    spec:
+      restartPolicy: OnFailure
+      nodeSelector:
+        {{ .Values.labels.node_selector_key }}: {{ .Values.labels.node_selector_value }}
+      initContainers:
+{{ tuple $envAll $dependencies "[]" | include "helm-toolkit.snippets.kubernetes_entrypoint_init_container"  | indent 8 }}
+      containers:
+        - name: docker-bootstrap
+{{ tuple $envAll "bootstrap" | include "helm-toolkit.snippets.image" | indent 10 }}
+{{ tuple $envAll $envAll.Values.pod.resources.jobs.bootstrap | include "helm-toolkit.snippets.kubernetes_resources" | indent 10 }}
+          env:
+            - name: LOCAL_REPO
+              value: "localhost:{{ tuple "docker_registry" "public" "registry" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}"
+            - name: PRELOAD_IMAGES
+              value: "{{  include "helm-toolkit.utils.joinListWithComma" .Values.bootstrap.preload_images }}"
+          command:
+            - /tmp/bootstrap.sh
+          volumeMounts:
+            - name: registry-bin
+              mountPath: /tmp/bootstrap.sh
+              subPath: bootstrap.sh
+              readOnly: true
+            - name: docker-socket
+              mountPath: /var/run/docker.sock
+      volumes:
+        - name: registry-bin
+          configMap:
+            name: registry-bin
+            defaultMode: 0555
+        - name: docker-socket
+          hostPath:
+            path: /var/run/docker.sock
+{{- end }}
+{{- end }}
diff --git a/registry/templates/pvc-images.yaml b/registry/templates/pvc-images.yaml
new file mode 100644
index 000000000..375446ff6
--- /dev/null
+++ b/registry/templates/pvc-images.yaml
@@ -0,0 +1,30 @@
+{{/*
+Copyright 2017 The Openstack-Helm Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/}}
+
+{{- if .Values.manifests.pvc_images }}
+{{- $envAll := . }}
+---
+kind: PersistentVolumeClaim
+apiVersion: v1
+metadata:
+  name: docker-images
+spec:
+  accessModes: [ "ReadWriteOnce" ]
+  resources:
+    requests:
+      storage: {{ .Values.volume.size }}
+  storageClassName: {{ .Values.volume.class_name }}
+{{- end }}
diff --git a/registry/templates/service-registry.yaml b/registry/templates/service-registry.yaml
new file mode 100644
index 000000000..b2bad736d
--- /dev/null
+++ b/registry/templates/service-registry.yaml
@@ -0,0 +1,36 @@
+{{/*
+Copyright 2017 The Openstack-Helm Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/}}
+
+{{- if .Values.manifests.service_registry }}
+{{- $envAll := . }}
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ tuple "docker_registry" "internal" . | include "helm-toolkit.endpoints.hostname_short_endpoint_lookup" }}
+spec:
+  ports:
+    - name: d-reg
+      port: {{ tuple "docker_registry" "internal" "registry" . | include "helm-toolkit.endpoints.endpoint_port_lookup" }}
+    {{ if .Values.network.registry.node_port.enabled }}
+      nodePort: {{ .Values.network.registry.node_port.port }}
+    {{ end }}
+  selector:
+{{ tuple $envAll "docker" "registry" | include "helm-toolkit.snippets.kubernetes_metadata_labels" | indent 4 }}
+  {{ if .Values.network.registry.node_port.enabled }}
+  type: NodePort
+  {{ end }}
+{{- end }}
diff --git a/registry/values.yaml b/registry/values.yaml
new file mode 100644
index 000000000..ff7637710
--- /dev/null
+++ b/registry/values.yaml
@@ -0,0 +1,167 @@
+# Copyright 2017 The Openstack-Helm Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Default values for docker registry.
+# This is a YAML-formatted file.
+# Declare name/value pairs to be passed into your templates.
+# name: value
+
+labels:
+  node_selector_key: openstack-control-plane
+  node_selector_value: enabled
+
+release_group: null
+
+images:
+  tags:
+    registry: docker.io/registry:2
+    registry_proxy: gcr.io/google_containers/kube-registry-proxy:0.4
+    bootstrap: docker.io/docker:17.07.0
+    dep_check: quay.io/stackanetes/kubernetes-entrypoint:v0.2.1
+  pull_policy: "IfNotPresent"
+  registry:
+    prefix: null
+
+volume:
+  class_name: general
+  size: 2Gi
+
+network:
+  registry:
+    ingress:
+      public: false
+    node_port:
+      enabled: false
+      port: 5000
+
+conf:
+  registry:
+    version: 0.1
+    log:
+      fields:
+        service: registry
+    storage:
+      cache:
+        blobdescriptor: redis
+      filesystem:
+        rootdirectory: /var/lib/registry
+    http:
+      secret: not-so-secret-secret
+      headers:
+        X-Content-Type-Options: [nosniff]
+    health:
+      storagedriver:
+        enabled: true
+        interval: 10s
+        threshold: 3
+    redis:
+      addr: null
+
+pod:
+  affinity:
+      anti:
+        type:
+          default: preferredDuringSchedulingIgnoredDuringExecution
+        topologyKey:
+          default: kubernetes.io/hostname
+  replicas:
+    registry: 1
+  lifecycle:
+    upgrades:
+      deployments:
+        revision_history: 3
+        pod_replacement_strategy: RollingUpdate
+        rolling_update:
+          max_unavailable: 1
+          max_surge: 3
+  resources:
+    enabled: false
+    registry:
+      requests:
+        memory: "128Mi"
+        cpu: "100m"
+      limits:
+        memory: "1024Mi"
+        cpu: "2000m"
+    registry_proxy:
+      requests:
+        memory: "128Mi"
+        cpu: "100m"
+      limits:
+        memory: "1024Mi"
+        cpu: "2000m"
+    jobs:
+      bootstrap:
+        requests:
+          memory: "128Mi"
+          cpu: "100m"
+        limits:
+          memory: "1024Mi"
+          cpu: "2000m"
+
+bootstrap:
+  enabled: true
+  script:
+    docker info
+  preload_images:
+    - gcr.io/google_containers/ubuntu-slim:0.14
+
+dependencies:
+  registry:
+    services:
+    - service: redis
+      endpoint: internal
+  registry_proxy:
+    services:
+    - service: docker_registry
+      endpoint: internal
+  bootstrap:
+    daemonset:
+    - docker-registry-proxy
+    services:
+    - service: docker_registry
+      endpoint: internal
+
+endpoints:
+  cluster_domain_suffix: cluster.local
+  docker_registry:
+    name: docker-registry
+    hosts:
+      default: docker-registry
+    host_fqdn_override:
+      default: null
+    path:
+      default: null
+    scheme:
+      default: http
+    port:
+      registry:
+        default: 5000
+  redis:
+    namespace: null
+    hosts:
+      default: redis
+    host_fqdn_override:
+      default: null
+    port:
+      redis:
+        default: 6379
+
+manifests:
+  configmap_bin: true
+  daemonset_registry_proxy: true
+  deployment_registry: true
+  job_bootstrap: true
+  pvc_images: true
+  service_registry: true
diff --git a/tiller/requirements.yaml b/tiller/requirements.yaml
new file mode 100644
index 000000000..53782e69b
--- /dev/null
+++ b/tiller/requirements.yaml
@@ -0,0 +1,18 @@
+# Copyright 2017 The Openstack-Helm Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+dependencies:
+  - name: helm-toolkit
+    repository: http://localhost:8879/charts
+    version: 0.1.0
diff --git a/tiller/templates/deployment-tiller.yaml b/tiller/templates/deployment-tiller.yaml
index 6a7744e90..366751837 100644
--- a/tiller/templates/deployment-tiller.yaml
+++ b/tiller/templates/deployment-tiller.yaml
@@ -46,8 +46,7 @@ spec:
           value: {{ .Release.Namespace }}
         - name: TILLER_HISTORY_MAX
           value: "0"
-        image: gcr.io/kubernetes-helm/tiller:v2.7.0-rc1
-        imagePullPolicy: IfNotPresent
+{{ tuple $envAll "tiller" | include "helm-toolkit.snippets.image" | indent 8 }}
         livenessProbe:
           failureThreshold: 3
           httpGet:
diff --git a/tiller/values.yaml b/tiller/values.yaml
new file mode 100644
index 000000000..c34aa330f
--- /dev/null
+++ b/tiller/values.yaml
@@ -0,0 +1,31 @@
+# Copyright 2017 The Openstack-Helm Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Default values for helm tiller
+# This is a YAML-formatted file.
+# Declare name/value pairs to be passed into your templates.
+# name: value
+
+labels:
+  node_selector_key: openstack-control-plane
+  node_selector_value: enabled
+
+release_group: null
+
+images:
+  tags:
+    tiller: gcr.io/kubernetes-helm/tiller:v2.7.0-rc1
+  pull_policy: "IfNotPresent"
+  registry:
+    prefix: null
diff --git a/tools/gate/playbooks/build-helm-packages/tasks/setup-helm-serve.yaml b/tools/gate/playbooks/build-helm-packages/tasks/setup-helm-serve.yaml
index 819c2b5dc..ff1a65ea6 100644
--- a/tools/gate/playbooks/build-helm-packages/tasks/setup-helm-serve.yaml
+++ b/tools/gate/playbooks/build-helm-packages/tasks/setup-helm-serve.yaml
@@ -33,14 +33,8 @@
       shell: curl -s 127.0.0.1:8879 | grep -q 'Helm Repository'
       register: helm_server_running
       ignore_errors: True
-    - name: launching local helm server via systemd
-      when: ( ansible_distribution == 'Fedora' ) and ( helm_server_running | failed )
-      shell: |
-              export XDG_RUNTIME_DIR="/run/user/$UID"
-              export DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/bus"
-              systemd-run --user --unit helm-server helm serve
     - name: launching local helm server via shell
-      when: ( ansible_distribution != 'Fedora' ) and ( helm_server_running | failed )
+      when: helm_server_running | failed
       shell: helm serve &
     - name: wait for helm server to be ready
       shell: curl -s 127.0.0.1:8879 | grep -q 'Helm Repository'
diff --git a/tools/gate/playbooks/clean-host/tasks/main.yaml b/tools/gate/playbooks/clean-host/tasks/main.yaml
new file mode 100644
index 000000000..77eee4369
--- /dev/null
+++ b/tools/gate/playbooks/clean-host/tasks/main.yaml
@@ -0,0 +1,22 @@
+# Copyright 2017 The Openstack-Helm Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+- name: remove osh directory
+  become: yes
+  become_user: root
+  file:
+    path: "{{ item }}"
+    state: absent
+  with_items:
+    - /var/lib/openstack-helm
diff --git a/tools/gate/playbooks/deploy-helm-packages/tasks/generate-dynamic-over-rides.yaml b/tools/gate/playbooks/deploy-helm-packages/tasks/generate-dynamic-over-rides.yaml
new file mode 100644
index 000000000..e04a2e375
--- /dev/null
+++ b/tools/gate/playbooks/deploy-helm-packages/tasks/generate-dynamic-over-rides.yaml
@@ -0,0 +1,32 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This set of tasks creates over-rides that need to be generated dyamicly and
+# injected at runtime.
+
+- name: Ensure docker python packages deployed
+  include_role:
+    name: deploy-package
+    tasks_from: pip
+  vars:
+    packages:
+      - yq
+
+- name: setup directorys on host
+  file:
+    path: "{{ work_dir }}/tools/gate/local-overrides/"
+    state: directory
+
+- name: generate overides for bootstrap-registry-registry release
+  shell: "./tools/image-repo-overides.sh > ./tools/gate/local-overrides/bootstrap-registry-registry.yaml"
+  args:
+    chdir: "{{ work_dir }}"
diff --git a/tools/gate/playbooks/deploy-helm-packages/tasks/helm-setup-dev-environment.yaml b/tools/gate/playbooks/deploy-helm-packages/tasks/helm-setup-dev-environment.yaml
new file mode 100644
index 000000000..d782546e3
--- /dev/null
+++ b/tools/gate/playbooks/deploy-helm-packages/tasks/helm-setup-dev-environment.yaml
@@ -0,0 +1,55 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+- name: installing OS-H dev tools
+  include_role:
+    name: deploy-package
+    tasks_from: dist
+  vars:
+    packages:
+      deb:
+        - git
+        - make
+        - curl
+        - ca-certificates
+        - jq
+      rpm:
+        - git
+        - make
+        - curl
+        - jq
+
+- block:
+    - name: removing jq binary on centos
+      become: true
+      become_user: root
+      when: ansible_distribution == 'CentOS' or ansible_distribution == 'Red Hat Enterprise Linux'
+      file:
+        path: "{{ item }}"
+        state: absent
+      with_items:
+        - /usr/bin/jq
+    - name: installing jq 1.5 binary for centos
+      become: true
+      become_user: root
+      when: ansible_distribution == 'CentOS' or ansible_distribution == 'Red Hat Enterprise Linux'
+      get_url:
+        url: https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64
+        dest: /usr/bin/jq
+        mode: 0555
+
+- name: assemble charts
+  make:
+    chdir: "{{ work_dir }}"
+  register: out
+
+- include: util-setup-dev-environment.yaml
diff --git a/tools/gate/playbooks/deploy-helm-packages/tasks/main.yaml b/tools/gate/playbooks/deploy-helm-packages/tasks/main.yaml
new file mode 100644
index 000000000..8a3098310
--- /dev/null
+++ b/tools/gate/playbooks/deploy-helm-packages/tasks/main.yaml
@@ -0,0 +1,24 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+- include: helm-setup-dev-environment.yaml
+
+- include: generate-dynamic-over-rides.yaml
+
+- name: "iterating through Helm chart groups"
+  vars:
+    chart_group_name: "{{ helm_chart_group.name }}"
+    chart_group_items: "{{ helm_chart_group.charts }}"
+  include: util-chart-group.yaml
+  loop_control:
+    loop_var: helm_chart_group
+  with_items: "{{ chart_groups }}"
diff --git a/tools/gate/playbooks/deploy-helm-packages/tasks/util-chart-group.yaml b/tools/gate/playbooks/deploy-helm-packages/tasks/util-chart-group.yaml
new file mode 100644
index 000000000..a114ff370
--- /dev/null
+++ b/tools/gate/playbooks/deploy-helm-packages/tasks/util-chart-group.yaml
@@ -0,0 +1,29 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+- name: "{{ helm_chart_group.name }}"
+  vars:
+    chart_def: "{{ charts[helm_chart] }}"
+  loop_control:
+    loop_var: helm_chart
+  include: util-common-helm-chart.yaml
+  with_items: "{{ helm_chart_group.charts }}"
+
+- name: "Running wait for pods for the charts in the {{ helm_chart_group.name }} group"
+  when: ('timeout' in helm_chart_group)
+  include: util-common-wait-for-pods.yaml
+  vars:
+    namespace: "{{ charts[helm_chart].namespace }}"
+    timeout: "{{ helm_chart_group.timeout }}"
+  loop_control:
+    loop_var: helm_chart
+  with_items: "{{ helm_chart_group.charts }}"
diff --git a/tools/gate/playbooks/deploy-helm-packages/tasks/util-common-helm-chart.yaml b/tools/gate/playbooks/deploy-helm-packages/tasks/util-common-helm-chart.yaml
new file mode 100644
index 000000000..e3f4865f9
--- /dev/null
+++ b/tools/gate/playbooks/deploy-helm-packages/tasks/util-common-helm-chart.yaml
@@ -0,0 +1,76 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+- name: Helm management common block
+  vars:
+    check_deployed_result: null
+    chart_values_file: null
+    upgrade:
+      pre:
+        delete: null
+
+  block:
+    - name: "create temporary file for {{ chart_def['release'] }}'s values .yaml"
+      tempfile:
+        state: file
+        suffix: .yaml
+      register: chart_values_file
+    - name: "write out values.yaml for {{ chart_def['release'] }}"
+      copy:
+        dest: "{{ chart_values_file.path }}"
+        content: "{% if 'values' in chart_def %}{{ chart_def['values'] | to_nice_yaml }}{% else %}{% endif %}"
+
+    - name: "check if {{ chart_def['release'] }} is deployed"
+      command: helm status "{{ chart_def['release'] }}"
+      register: check_deployed_result
+      ignore_errors: True
+
+    - name: "check if local overrides are present in {{ work_dir }}/tools/gate/local-overrides/{{ chart_def['release'] }}.yaml"
+      stat:
+        path: "{{ work_dir }}/tools/gate/local-overrides/{{ chart_def['release'] }}.yaml"
+      register: local_overrides
+
+    - name: "try to deploy release {{ chart_def['release'] }} in {{ chart_def['namespace'] }} namespace with {{ chart_def['chart_name'] }} chart"
+      when: check_deployed_result | failed
+      command: "helm install {{ work_dir }}/{{ chart_def['chart_name'] }} --namespace {{ chart_def['namespace'] }} --name {{ chart_def['release'] }} --values={{ chart_values_file.path }}{% if local_overrides.stat.exists %} --values {{ work_dir }}/tools/gate/local-overrides/{{ chart_def['release'] }}.yaml{% endif %}"
+      register: out
+    - name: "display info for the helm {{ chart_def['release'] }} release deploy"
+      when: check_deployed_result | failed
+      debug:
+        var: out.stdout_lines
+
+    - name: "pre-upgrade, delete jobs for {{ chart_def['release'] }} release"
+      when: (check_deployed_result | succeeded) and ( 'upgrade' in chart_def ) and ( 'pre' in chart_def['upgrade'] ) and ( 'delete' in chart_def['upgrade']['pre'] ) and (chart_def.upgrade.pre.delete is not none)
+      with_items: "{{ chart_def.upgrade.pre.delete }}"
+      loop_control:
+        loop_var: helm_upgrade_delete_job
+      command: "kubectl delete --namespace {{ chart_def['namespace'] }} job -l application={{ helm_upgrade_delete_job.labels.application }},component={{ helm_upgrade_delete_job.labels.component }} --ignore-not-found=true"
+    - name: "try to upgrade release {{ chart_def['release'] }} in {{ chart_def['namespace'] }} namespace with {{ chart_def['chart_name'] }} chart"
+      when: check_deployed_result | succeeded
+      command: "helm upgrade {{ chart_def['release'] }} {{ work_dir }}/{{ chart_def['chart_name'] }} --values={{ chart_values_file.path }}{% if local_overrides.stat.exists %} --values {{ work_dir }}/tools/gate/local-overrides/{{ chart_def['release'] }}.yaml{% endif %}"
+      register: out
+    - name: "display info for the helm {{ chart_def['release'] }} release upgrade"
+      when: check_deployed_result | succeeded
+      debug:
+        var: out.stdout_lines
+
+    - include: util-common-wait-for-pods.yaml
+      when: ('timeout' in chart_def)
+      vars:
+        namespace: "{{ chart_def['namespace'] }}"
+        timeout: "{{ chart_def['timeout'] }}"
+
+  always:
+    - name: "remove values.yaml for {{ chart_def['release'] }}"
+      file:
+        path: "{{ chart_values_file.path }}"
+        state: absent
diff --git a/tools/gate/playbooks/deploy-helm-packages/tasks/util-common-wait-for-pods.yaml b/tools/gate/playbooks/deploy-helm-packages/tasks/util-common-wait-for-pods.yaml
new file mode 100644
index 000000000..19d8785b1
--- /dev/null
+++ b/tools/gate/playbooks/deploy-helm-packages/tasks/util-common-wait-for-pods.yaml
@@ -0,0 +1,50 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+- name: wait for pods in namespace
+  vars:
+    namespace: null
+    timeout: 600
+    wait_return_code:
+      rc: 1
+  block:
+    - name: "wait for pods in {{ namespace }} namespace to be ready"
+      shell: |-
+              set -e
+              kubectl get pods --namespace="{{ namespace }}" -o json | jq -r \
+                  '.items[].status.phase' | grep Pending > /dev/null && \
+                  PENDING=True || PENDING=False
+
+              query='.items[]|select(.status.phase=="Running")'
+              query="$query|.status.containerStatuses[].ready"
+              kubectl get pods --namespace="{{ namespace }}" -o json | jq -r "$query" | \
+                  grep false > /dev/null && READY="False" || READY="True"
+
+              kubectl get jobs -o json --namespace="{{ namespace }}" | jq -r \
+                  '.items[] | .spec.completions == .status.succeeded' | \
+                  grep false > /dev/null && JOBR="False" || JOBR="True"
+              [ $PENDING == "False" -a $READY == "True" -a $JOBR == "True" ] && \
+                  exit 0 || exit 1
+      args:
+        executable: /bin/bash
+      register: wait_return_code
+      until: wait_return_code.rc == 0
+      retries: "{{ timeout }}"
+      delay: 1
+  rescue:
+    - name: "pods failed to come up in time, getting kubernetes objects status"
+      command: kubectl get --all-namespaces  all -o wide --show-all
+      register: out
+    - name: "pods failed to come up in time, displaying kubernetes objects status"
+      debug: var=out.stdout_lines
+    - name: "pods failed to come up in time, stopping execution"
+      command: exit 1
diff --git a/tools/gate/playbooks/deploy-helm-packages/tasks/util-setup-dev-environment.yaml b/tools/gate/playbooks/deploy-helm-packages/tasks/util-setup-dev-environment.yaml
new file mode 100644
index 000000000..cee4c8108
--- /dev/null
+++ b/tools/gate/playbooks/deploy-helm-packages/tasks/util-setup-dev-environment.yaml
@@ -0,0 +1,31 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+- name: disable rbac
+  block:
+    - name: rbac | moving manifests into place
+      template:
+        src: "{{ item }}.j2"
+        dest: "/tmp/{{ item }}"
+        mode: 0666
+      with_items:
+        - clusterrolebinding.yaml
+    - name: rbac | creating objects
+      command: "kubectl replace -f /tmp/{{ item }}"
+      with_items:
+        - clusterrolebinding.yaml
+    - name: rbac | removing manifests
+      file:
+        path: "/tmp/{{ item }}"
+        state: absent
+      with_items:
+        - clusterrolebinding.yaml
diff --git a/tools/gate/playbooks/deploy-helm-packages/templates/clusterrolebinding.yaml.j2 b/tools/gate/playbooks/deploy-helm-packages/templates/clusterrolebinding.yaml.j2
new file mode 100644
index 000000000..fb3e98427
--- /dev/null
+++ b/tools/gate/playbooks/deploy-helm-packages/templates/clusterrolebinding.yaml.j2
@@ -0,0 +1,18 @@
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: cluster-admin
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: cluster-admin
+subjects:
+- apiGroup: rbac.authorization.k8s.io
+  kind: Group
+  name: system:masters
+- apiGroup: rbac.authorization.k8s.io
+  kind: Group
+  name: system:authenticated
+- apiGroup: rbac.authorization.k8s.io
+  kind: Group
+  name: system:unauthenticated
diff --git a/tools/gate/playbooks/deploy-kubeadm-aio-common/tasks/deploy-kubelet.yaml b/tools/gate/playbooks/deploy-kubeadm-aio-common/tasks/deploy-kubelet.yaml
index 91fb234e5..968faebaf 100644
--- a/tools/gate/playbooks/deploy-kubeadm-aio-common/tasks/deploy-kubelet.yaml
+++ b/tools/gate/playbooks/deploy-kubeadm-aio-common/tasks/deploy-kubelet.yaml
@@ -12,7 +12,16 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-- name: master
+
+- name: setting node labels
+  vars:
+    kubeadm_kubelet_labels_node:
+      - "{% if nodes.labels.all is defined %}{% set comma = joiner(\",\") %}{% for item in nodes.labels.all %}{{ comma() }}{{ item.name }}={{ item.value }}{% endfor %}{% else %}\"\"{% endif %}"
+      - "{% set comma = joiner(\",\") %}{% for group in group_names %}{% if nodes.labels[group] is defined %}{% for item in nodes.labels[group] %}{{ comma() }}{{ item.name }}={{ item.value }}{% endfor %}{% else %}\"\"{% endif %}{% endfor %}"
+  set_fact:
+    kubeadm_kubelet_labels: "{% set comma = joiner(\",\") %}{% for item in kubeadm_kubelet_labels_node %}{{ comma() }}{{ item }}{% endfor %}"
+
+- name: deploy-kubelet
   vars:
     kubeadm_aio_action: deploy-kubelet
   include: util-kubeadm-aio-run.yaml
diff --git a/tools/gate/playbooks/deploy-kubeadm-aio-common/tasks/util-kubeadm-aio-run.yaml b/tools/gate/playbooks/deploy-kubeadm-aio-common/tasks/util-kubeadm-aio-run.yaml
index 073a7ba57..75098e09c 100644
--- a/tools/gate/playbooks/deploy-kubeadm-aio-common/tasks/util-kubeadm-aio-run.yaml
+++ b/tools/gate/playbooks/deploy-kubeadm-aio-common/tasks/util-kubeadm-aio-run.yaml
@@ -15,6 +15,7 @@
 - name: Run Kubeadm-AIO container
   vars:
     kubeadm_aio_action: null
+    kubeadm_kubelet_labels: ""
   block:
     - name: "perfoming {{ kubeadm_aio_action }} action"
       become: true
@@ -48,6 +49,7 @@
           KUBE_NET_POD_SUBNET=192.168.0.0/16
           KUBE_NET_DNS_DOMAIN=cluster.local
           CONTAINER_RUNTIME=docker
+          KUBELET_NODE_LABELS="{{ kubeadm_kubelet_labels }}"
       register: kubeadm_master_deploy
   rescue:
     - name: "getting logs for {{ kubeadm_aio_action }} action"
diff --git a/tools/gate/playbooks/pull-images/tasks/main.yaml b/tools/gate/playbooks/pull-images/tasks/main.yaml
index 7271b8282..ec335009d 100644
--- a/tools/gate/playbooks/pull-images/tasks/main.yaml
+++ b/tools/gate/playbooks/pull-images/tasks/main.yaml
@@ -12,6 +12,14 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+- name: Ensure docker python packages deployed
+  include_role:
+    name: deploy-package
+    tasks_from: pip
+  vars:
+    packages:
+      - yq
+
 - name: pull all images used in repo
   make:
     chdir: "{{ work_dir }}"
diff --git a/tools/gate/playbooks/vars.yaml b/tools/gate/playbooks/vars.yaml
index 7962f639e..56090fb9a 100644
--- a/tools/gate/playbooks/vars.yaml
+++ b/tools/gate/playbooks/vars.yaml
@@ -24,3 +24,75 @@ kubernetes:
     default_device: null
   cluster:
     cni: calico
+
+nodes:
+  labels:
+    primary:
+      - name: openstack-helm-node-class
+        value: primary
+    nodes:
+      - name: openstack-helm-node-class
+        value: general
+    all:
+      - name: openstack-control-plane
+        value: enabled
+      - name: openstack-compute-node
+        value: enabled
+      - name: openvswitch
+        value: enabled
+      - name: ceph-mon
+        value: enabled
+      - name: ceph-osd
+        value: enabled
+      - name: ceph-mds
+        value: enabled
+      - name: ceph-rgw
+        value: enabled
+
+chart_groups:
+  - name: bootstrap_registry
+    timeout: 600
+    charts:
+      - bootstrap_registry_nfs_provisioner
+      - bootstrap_registry_redis
+      - bootstrap_registry_registry
+
+charts:
+  bootstrap_registry_nfs_provisioner:
+    chart_name: nfs-provisioner
+    release: bootstrap-registry-nfs-provisioner
+    namespace: bootstrap-registry
+    upgrade:
+      pre:
+        delete:
+          - name: docker-bootstrap
+            type: job
+            labels:
+              application: docker
+              component: bootstrap
+    values:
+      labels:
+        node_selector_key: openstack-helm-node-class
+        node_selector_value: primary
+      storageclass:
+        name: openstack-helm-bootstrap
+
+  bootstrap_registry_redis:
+    chart_name: redis
+    release: bootstrap-registry-redis
+    namespace: bootstrap-registry
+    values:
+      labels:
+        node_selector_key: openstack-helm-node-class
+        node_selector_value: primary
+
+  bootstrap_registry_registry:
+    chart_name: registry
+    release: bootstrap-registry-registry
+    namespace: bootstrap-registry
+    values:
+      labels:
+        node_selector_key: openstack-helm-node-class
+        node_selector_value: primary
+      volume:
+        class_name: openstack-helm-bootstrap
diff --git a/tools/gate/playbooks/zuul-run.yaml b/tools/gate/playbooks/zuul-run.yaml
index 14c3b8220..46abb99a2 100644
--- a/tools/gate/playbooks/zuul-run.yaml
+++ b/tools/gate/playbooks/zuul-run.yaml
@@ -12,6 +12,16 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+- hosts: all
+  vars_files:
+    - vars.yaml
+  vars:
+    work_dir: "{{ zuul.project.src_dir }}"
+  roles:
+    - clean-host
+  tags:
+    - clean-host
+
 - hosts: primary
   vars_files:
     - vars.yaml
@@ -31,3 +41,13 @@
     - deploy-kubeadm-aio-node
   tags:
     - deploy-kubeadm-aio-node
+
+- hosts: primary
+  vars_files:
+    - vars.yaml
+  vars:
+    work_dir: "{{ zuul.project.src_dir }}"
+  roles:
+    - deploy-helm-packages
+  tags:
+    - deploy-helm-packages
diff --git a/tools/image-repo-overides.sh b/tools/image-repo-overides.sh
new file mode 100755
index 000000000..ea217d17e
--- /dev/null
+++ b/tools/image-repo-overides.sh
@@ -0,0 +1,37 @@
+#!/usr/bin/env bash
+
+# Copyright 2017 The Openstack-Helm Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+KUBE_VERSION=v1.8.1
+KUBE_IMAGES="gcr.io/google_containers/hyperkube-amd64:${KUBE_VERSION}
+gcr.io/google_containers/kube-apiserver-amd64:${KUBE_VERSION}
+gcr.io/google_containers/kube-controller-manager-amd64:${KUBE_VERSION}
+gcr.io/google_containers/kube-proxy-amd64:${KUBE_VERSION}
+gcr.io/google_containers/kube-scheduler-amd64:${KUBE_VERSION}
+gcr.io/google_containers/pause-amd64:3.0
+gcr.io/google_containers/etcd-amd64:3.0.17"
+
+CHART_IMAGES=""
+for CHART_DIR in ./*/ ; do
+  if [ -e ${CHART_DIR}values.yaml ] && [ "${CHART_DIR}" != "./helm-toolkit/" ]; then
+    CHART_IMAGES+=" $(cat ${CHART_DIR}values.yaml | yq '.images.tags | map(.) | join(" ")' | tr -d '"' )"
+  fi
+done
+ALL_IMAGES="${KUBE_IMAGES} ${CHART_IMAGES}"
+
+jq -n -c -M \
+--arg devclass "$(echo ${ALL_IMAGES})" \
+'{"bootstrap": {"preload_images": ($devclass|split(" "))}}' | \
+python -c 'import sys, yaml, json; yaml.safe_dump(json.load(sys.stdin), sys.stdout, default_flow_style=False)'
diff --git a/tools/images/kubeadm-aio/assets/entrypoint.sh b/tools/images/kubeadm-aio/assets/entrypoint.sh
index 1edb2508e..3a60abdc0 100755
--- a/tools/images/kubeadm-aio/assets/entrypoint.sh
+++ b/tools/images/kubeadm-aio/assets/entrypoint.sh
@@ -52,6 +52,7 @@ fi
 : ${KUBE_API_BIND_ADDR:="${KUBE_BIND_ADDR}"}
 : ${KUBE_CERTS_DIR:="/etc/kubernetes/pki"}
 : ${KUBE_SELF_HOSTED:="false"}
+: ${KUBELET_NODE_LABELS:=""}
 
 PLAYBOOK_VARS="{
   \"my_container_name\": \"${CONTAINER_NAME}\",
@@ -90,12 +91,18 @@ PLAYBOOK_VARS="{
 
 set -x
 if [ "x${ACTION}" == "xdeploy-kubelet" ]; then
+
   if [ "x${KUBE_BIND_ADDR}" != "x" ]; then
     PLAYBOOK_VARS=$(echo $PLAYBOOK_VARS | jq ".kubelet += {\"bind_addr\": \"${KUBE_BIND_ADDR}\"}")
   elif [ "x${KUBE_BIND_DEVICE}" != "x" ]; then
     PLAYBOOK_VARS=$(echo $PLAYBOOK_VARS | jq ".kubelet += {\"bind_device\": \"${KUBE_BIND_DEVICE}\"}")
   fi
-  ansible-playbook /opt/playbooks/kubeadm-aio-deploy-kubelet.yaml \
+
+  if [ "x${KUBELET_NODE_LABELS}" != "x" ]; then
+    PLAYBOOK_VARS=$(echo $PLAYBOOK_VARS | jq ".kubelet += {\"kubelet_labels\": \"${KUBELET_NODE_LABELS}\"}")
+  fi
+
+  exec ansible-playbook /opt/playbooks/kubeadm-aio-deploy-kubelet.yaml \
     --inventory=/opt/playbooks/inventory.ini \
     --inventory=/opt/playbooks/vars.yaml \
     --extra-vars="${PLAYBOOK_VARS}"
@@ -105,12 +112,12 @@ elif [ "x${ACTION}" == "xdeploy-kube" ]; then
   elif [ "x${KUBE_API_BIND_DEVICE}" != "x" ]; then
     PLAYBOOK_VARS=$(echo $PLAYBOOK_VARS | jq ".k8s.api += {\"advertiseAddressDevice\": \"${KUBE_API_BIND_DEVICE}\"}")
   fi
-  ansible-playbook /opt/playbooks/kubeadm-aio-deploy-master.yaml \
+  exec ansible-playbook /opt/playbooks/kubeadm-aio-deploy-master.yaml \
     --inventory=/opt/playbooks/inventory.ini \
     --inventory=/opt/playbooks/vars.yaml \
     --extra-vars="${PLAYBOOK_VARS}"
 elif [ "x${ACTION}" == "xclean-host" ]; then
-  ansible-playbook /opt/playbooks/kubeadm-aio-clean.yaml \
+  exec ansible-playbook /opt/playbooks/kubeadm-aio-clean.yaml \
     --inventory=/opt/playbooks/inventory.ini \
     --inventory=/opt/playbooks/vars.yaml \
     --extra-vars="${PLAYBOOK_VARS}"
diff --git a/tools/images/kubeadm-aio/assets/opt/playbooks/roles/deploy-kubelet/templates/10-kubeadm.conf.j2 b/tools/images/kubeadm-aio/assets/opt/playbooks/roles/deploy-kubelet/templates/10-kubeadm.conf.j2
index 6a557fbf8..f12679ea2 100644
--- a/tools/images/kubeadm-aio/assets/opt/playbooks/roles/deploy-kubelet/templates/10-kubeadm.conf.j2
+++ b/tools/images/kubeadm-aio/assets/opt/playbooks/roles/deploy-kubelet/templates/10-kubeadm.conf.j2
@@ -6,6 +6,7 @@ Environment="KUBELET_DNS_ARGS=--cluster-dns=10.96.0.10 --cluster-domain={{ k8s.n
 Environment="KUBELET_AUTHZ_ARGS=--authorization-mode=Webhook --client-ca-file=/etc/kubernetes/pki/ca.crt"
 Environment="KUBELET_CADVISOR_ARGS=--cadvisor-port=0"
 Environment="KUBELET_CERTIFICATE_ARGS=--rotate-certificates=true --cert-dir=/var/lib/kubelet/pki"
+Environment="KUBELET_NODE_LABELS=--node-labels {{ kubelet.kubelet_labels }}"
 #ExecStartPre=-+/sbin/restorecon -v /usr/bin/kubelet #SELinux
 ExecStart=
-ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_SYSTEM_PODS_ARGS $KUBELET_NETWORK_ARGS $KUBELET_DNS_ARGS $KUBELET_AUTHZ_ARGS $KUBELET_CADVISOR_ARGS $KUBELET_CERTIFICATE_ARGS $KUBELET_EXTRA_ARGS
+ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_SYSTEM_PODS_ARGS $KUBELET_NETWORK_ARGS $KUBELET_DNS_ARGS $KUBELET_AUTHZ_ARGS $KUBELET_CADVISOR_ARGS $KUBELET_CERTIFICATE_ARGS $KUBELET_NODE_LABELS $KUBELET_EXTRA_ARGS
diff --git a/tools/pull-images.sh b/tools/pull-images.sh
index 837333796..79b7daa4a 100755
--- a/tools/pull-images.sh
+++ b/tools/pull-images.sh
@@ -15,23 +15,9 @@
 # limitations under the License.
 
 set -x
-KUBE_VERSION=v1.8.1
-KUBE_IMAGES="gcr.io/google_containers/hyperkube-amd64:${KUBE_VERSION}
-gcr.io/google_containers/kube-apiserver-amd64:${KUBE_VERSION}
-gcr.io/google_containers/kube-controller-manager-amd64:${KUBE_VERSION}
-gcr.io/google_containers/kube-proxy-amd64:${KUBE_VERSION}
-gcr.io/google_containers/kube-scheduler-amd64:${KUBE_VERSION}
-gcr.io/google_containers/pause-amd64:3.0
-gcr.io/google_containers/etcd-amd64:3.0.17"
-
-CHART_IMAGES=""
-for CHART_DIR in ./*/ ; do
-  if [ -e ${CHART_DIR}values.yaml ]; then
-    CHART_IMAGES+=" $(cat ${CHART_DIR}values.yaml | yq '.images.tags | map(.) | join(" ")' | tr -d '"')"
-  fi
-done
-ALL_IMAGES="${KUBE_IMAGES} ${CHART_IMAGES}"
-
+ALL_IMAGES="$(./tools/image-repo-overides.sh | \
+  python -c 'import sys, yaml, json; json.dump(yaml.safe_load(sys.stdin), sys.stdout)' | \
+  jq '.bootstrap.preload_images |map(.) | join(" ")' | tr -d '"')"
 for IMAGE in ${ALL_IMAGES}; do
-  docker inspect $IMAGE >/dev/null|| docker pull $IMAGE
+  docker inspect $IMAGE > /dev/null || docker pull $IMAGE
 done