diff --git a/roles/download/defaults/kube_versions.yml b/roles/download/defaults/kube_versions.yml
new file mode 100644
index 0000000000000000000000000000000000000000..dabe543e5cc5fc479929ac73c1f3250fa8f1c574
--- /dev/null
+++ b/roles/download/defaults/kube_versions.yml
@@ -0,0 +1,9 @@
+kube_version:
+    v1.2.3:
+        kube_apiserver_checksum: ebaeeeb72cb29b358337b330617a96355ff2d08a5a523fc1a81beba36cc9d6f9
+        kubectl_checksum: 394853edd409a721bcafe4f1360009ef9f845050719fe7d6fc7176f45cc92a8c
+        kubelet_checksum: 633bb41c51c5c0df0645dd60ba82b12eba39d009eb87bae9227de7d9a89c0797
+    v1.2.4:
+        kube_apiserver_checksum: 6ac99b36b02968459e026fcfc234207c66064b5e11816b69dd8fc234b2ffec1e
+        kubectl_checksum: dac61fbd506f7a17540feca691cd8a9d9d628d59661eebce788a50511f578897
+        kubelet_checksum: 4adaf40592248eef6fd4fa126464915ea41e624a70dc77178089760ed235e341
diff --git a/roles/download/defaults/main.yml b/roles/download/defaults/main.yml
index 2be226e62111b04b214cc0e4b3d20f397aa7ee62..51db5d1b065c704ae6ae499abb45c4c0d1bc03d8 100644
--- a/roles/download/defaults/main.yml
+++ b/roles/download/defaults/main.yml
@@ -4,8 +4,10 @@ local_release_dir: /tmp
 # if this is set to true will only download files once
 download_run_once: False
 
+
 # Versions
-kube_version: "v1.2.4"
+include_vars: kube_versions.yml
+
 etcd_version: v2.3.7
 calico_version: v0.20.0
 calico_cni_version: v1.3.1
@@ -28,9 +30,6 @@ calico_cni_checksum: "ac05cb9254b5aaa5822cf10325983431bd25489147f2edf9dec7e43d99
 calico_cni_ipam_checksum: "3df6951a30749c279229e7e318e74ac4e41263996125be65257db7cd25097273"
 weave_checksum: "28d2c4e2b1ad8600da69882501eba697679aea10a5e61c769aa3a9ee72b0d89a"
 etcd_checksum: "ab102d271026a4060c9f85ecad11f454d82b1df7b8e676cc3da69f67eb078729"
-kubectl_checksum: "dac61fbd506f7a17540feca691cd8a9d9d628d59661eebce788a50511f578897"
-kubelet_checksum: "4adaf40592248eef6fd4fa126464915ea41e624a70dc77178089760ed235e341"
-kube_apiserver_checksum: "6ac99b36b02968459e026fcfc234207c66064b5e11816b69dd8fc234b2ffec1e"
 
 downloads:
   calico:
diff --git a/roles/uploads/defaults/kube_versions.yml b/roles/uploads/defaults/kube_versions.yml
new file mode 100644
index 0000000000000000000000000000000000000000..dabe543e5cc5fc479929ac73c1f3250fa8f1c574
--- /dev/null
+++ b/roles/uploads/defaults/kube_versions.yml
@@ -0,0 +1,9 @@
+kube_version:
+    v1.2.3:
+        kube_apiserver_checksum: ebaeeeb72cb29b358337b330617a96355ff2d08a5a523fc1a81beba36cc9d6f9
+        kubectl_checksum: 394853edd409a721bcafe4f1360009ef9f845050719fe7d6fc7176f45cc92a8c
+        kubelet_checksum: 633bb41c51c5c0df0645dd60ba82b12eba39d009eb87bae9227de7d9a89c0797
+    v1.2.4:
+        kube_apiserver_checksum: 6ac99b36b02968459e026fcfc234207c66064b5e11816b69dd8fc234b2ffec1e
+        kubectl_checksum: dac61fbd506f7a17540feca691cd8a9d9d628d59661eebce788a50511f578897
+        kubelet_checksum: 4adaf40592248eef6fd4fa126464915ea41e624a70dc77178089760ed235e341
diff --git a/roles/uploads/defaults/main.yml b/roles/uploads/defaults/main.yml
index 3dadb504be60c5aba437e1e265e15eb9f1d701f7..a776dfeaea070997b39232f9b0c539ca8d99c2e6 100644
--- a/roles/uploads/defaults/main.yml
+++ b/roles/uploads/defaults/main.yml
@@ -2,7 +2,8 @@
 local_release_dir: /tmp
 
 # Versions
-kube_version: "v1.2.4"
+include_vars: kube_versions.yml
+
 etcd_version: v2.3.7
 calico_version: v0.20.0
 calico_cni_version: v1.3.1
@@ -22,9 +23,6 @@ calico_cni_checksum: "ac05cb9254b5aaa5822cf10325983431bd25489147f2edf9dec7e43d99
 calico_cni_ipam_checksum: "3df6951a30749c279229e7e318e74ac4e41263996125be65257db7cd25097273"
 weave_checksum: "28d2c4e2b1ad8600da69882501eba697679aea10a5e61c769aa3a9ee72b0d89a"
 etcd_checksum: "ab102d271026a4060c9f85ecad11f454d82b1df7b8e676cc3da69f67eb078729"
-kubectl_checksum: "dac61fbd506f7a17540feca691cd8a9d9d628d59661eebce788a50511f578897"
-kubelet_checksum: "4adaf40592248eef6fd4fa126464915ea41e624a70dc77178089760ed235e341"
-kube_apiserver_checksum: "6ac99b36b02968459e026fcfc234207c66064b5e11816b69dd8fc234b2ffec1e"
 
 downloads:
   - name: calico
diff --git a/scripts/change_k8s_version.py b/scripts/change_k8s_version.py
new file mode 100644
index 0000000000000000000000000000000000000000..8db6aee07c1d2dba2c17231e0498535f2310d814
--- /dev/null
+++ b/scripts/change_k8s_version.py
@@ -0,0 +1,85 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+#
+# This file is part of Kargo.
+#
+#    Foobar is free software: you can redistribute it and/or modify
+#    it under the terms of the GNU General Public License as published by
+#    the Free Software Foundation, either version 3 of the License, or
+#    (at your option) any later version.
+#
+#    Foobar is distributed in the hope that it will be useful,
+#    but WITHOUT ANY WARRANTY; without even the implied warranty of
+#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#    GNU General Public License for more details.
+#
+#    You should have received a copy of the GNU General Public License
+#    along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
+import sys
+import hashlib
+import urllib2
+import yaml
+import argparse
+
+
+def get_remote_sha256_sum(url, max_file_size=100*1024*1024):
+    remote = urllib2.urlopen(url)
+    hash = hashlib.sha256()
+    total_read = 0
+    while True:
+        data = remote.read(4096)
+        total_read += 4096
+        if not data or total_read > max_file_size:
+            break
+        hash.update(data)
+    return hash.hexdigest()
+
+
+def read_vars(var_file):
+    """
+    Read the variables file
+    """
+    try:
+        with open(var_file, "r") as f:
+            kargovars = yaml.load(f)
+    except:
+        print(
+            "Can't read variables file %s" % var_file
+        )
+        sys.exit(1)
+    return kargovars
+
+
+def get_kube_sha256(version, download_url, binaries):
+    kube_sha256 = dict()
+    for k in binaries:
+        s = get_remote_sha256_sum(download_url + '/' + k)
+        kube_sha256[k] = s
+        kube_sha256[k + '_checksum'] = kube_sha256.pop(k)
+    kube_sha256['kube_apiserver_checksum'] = kube_sha256.pop('kube-apiserver_checksum')
+    return(kube_sha256)
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser(
+        prog='change_k8s_version',
+        description='%(prog)s changes the version to be installed with kargo',
+    )
+
+    parser.add_argument(
+        '-v', '--version', dest='kube_version', required=True,
+        help="kubernetes version"
+    )
+    args = parser.parse_args()
+
+    kube_binaries = ['kubelet', 'kubectl', 'kube-apiserver']
+    kargo_root = ".."
+    var_files = ['../roles/uploads/defaults/kube_versions.yml', '../roles/download/defaults/kube_versions.yml']
+    kube_download_url = "https://storage.googleapis.com/kubernetes-release/release/%s/bin/linux/amd64" % args.kube_version
+
+    new = get_kube_sha256(args.kube_version, kube_download_url, kube_binaries)
+    for f in var_files:
+        current = read_vars(f)
+        current['kube_version'][args.kube_version] = new
+        with open(f, 'w') as out:
+            out.write(yaml.dump(current, indent=4, default_flow_style=False))
diff --git a/scripts/change_k8s_version.sh b/scripts/change_k8s_version.sh
deleted file mode 100755
index 8c00e7168454ec6a1d9b2a7d2d76570043e558f2..0000000000000000000000000000000000000000
--- a/scripts/change_k8s_version.sh
+++ /dev/null
@@ -1,117 +0,0 @@
-#!/bin/bash
-
-# This file is part of Kargo.
-#
-#    Foobar is free software: you can redistribute it and/or modify
-#    it under the terms of the GNU General Public License as published by
-#    the Free Software Foundation, either version 3 of the License, or
-#    (at your option) any later version.
-#
-#    Foobar is distributed in the hope that it will be useful,
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-#    GNU General Public License for more details.
-#
-#    You should have received a copy of the GNU General Public License
-#    along with Foobar.  If not, see <http://www.gnu.org/licenses/>.
-
-#color variables
-txtbld=$(tput bold)             # Bold
-bldred=${txtbld}$(tput setaf 1) #  red
-bldgre=${txtbld}$(tput setaf 2) #  green
-bldylw=${txtbld}$(tput setaf 3) #  yellow
-txtrst=$(tput sgr0)             # Reset
-err=${bldred}ERROR${txtrst}
-info=${bldgre}INFO${txtrst}
-warn=${bldylw}WARNING${txtrst}
-
-usage()
-{
-    cat << EOF
-Update ansible playbook with a specific kubernetes version
-
-Usage : $(basename $0) -v <k8s version>
-      -h | --help         : Show this message
-      -i | --init         : Initial upgrade (download binaries)
-      -v | --version      : Kubernetes version
-               
-               ex : switch to kubernetes v1.2.4
-               $(basename $0) -v v1.2.4
-EOF
-}
-
-# Options parsing
-while (($#)); do
-    case "$1" in
-        -h | --help)   usage;   exit 0;;
-        -i | --init) INIT=1; shift;;
-        -v | --version) VERS=${2}; shift 2;;
-        *)
-            usage
-            echo "ERROR : Unknown option"
-            exit 3
-        ;;
-    esac
-done
-
-if [ -z ${VERS} ]; then
-    usage
-    echo -e "\n${err}: The option version must be defined"
-    exit 3
-else
-   if ! [[ ${VERS} =~ ^v[0-9]\.[0-9]\.[0-9]$ ]]; then
-       echo -e "\n${err}: Invalid version format (ex: v1.2.4)"
-       exit 1
-   fi
-fi
-
-UPLOAD_VARFILE="roles/uploads/defaults/main.yml"
-DOWNLOAD_VARFILE="roles/download/defaults/main.yml"
-K8S_BIN="kubelet kubectl kube-apiserver"
-
-if [[ ${INIT} -eq 1 ]]; then
-   DOWNLOAD_URL=https://storage.googleapis.com/kubernetes-release/release/${VERS}/bin/linux/amd64
-   TMP_DIR=$(mktemp -d --tmpdir kubernetes_tmpbin_XXXXXXX)
-   sed -i "s/^hyperkube_image_tag.*$/hyperkube_image_tag: \"${VERS}\"/" roles/kubernetes/node/defaults/main.yml
-   trap 'rm -rf "${tmpdir}"' EXIT
-   cd "${tmpdir}"
-
-   for BIN in ${K8S_BIN}; do
-       curl -s -o ${BIN} ${DOWNLOAD_URL}/${BIN}
-       if [ $? -ne 0 ]; then
-           echo -e "\n${err}: Downloading ${BIN} failed! Try again"
-           exit 1
-       else
-           echo -e "\n${info}: ${BIN} downloaded successfuly"
-       fi
-   done
-
-   for varfile in ${UPLOAD_VARFILE} ${DOWNLOAD_VARFILE}; do
-       sed -i "s/^kube_version.*$/kube_version: \"${VERS}\"/" ${varfile}
-   
-       for BIN in ${K8S_BIN}; do
-           CHECKSUM=$(sha256sum ${BIN} | cut -d' ' -f1)
-           BIN=$(echo ${BIN} | tr '-' '_')
-           sed  -i "s/^${BIN}_checksum.*$/${BIN}_checksum: \"${CHECKSUM}\"/" ${varfile}
-       done
-   done
-   
-   rm -rf "${tmpdir}"
-else
-   CHECKSUM_URL=https://storage.googleapis.com/kargo/${VERS}_k8s-sha256
-   sed -i "s/^hyperkube_image_tag.*$/hyperkube_image_tag: \"${VERS}\"/" roles/kubernetes/node/defaults/main.yml
-    for varfile in ${UPLOAD_VARFILE} ${DOWNLOAD_VARFILE}; do
-        sed -i "s/^kube_version.*$/kube_version: \"${VERS}\"/" ${varfile}
-        for BIN in ${K8S_BIN}; do
-            if [[ "${BIN}" =~ "apiserver" ]]; then
-                BIN="apiserver"
-            fi
-            line=$(curl -sk ${CHECKSUM_URL} | grep ${BIN})
-            CHECKSUM=$(echo ${line} | cut -d':' -f2)
-            if [[ "${BIN}" =~ "apiserver" ]]; then
-                BIN="kube_apiserver"
-            fi
-            sed  -i "s/^${BIN}_checksum.*$/${BIN}_checksum: \"${CHECKSUM}\"/" ${varfile}
-        done
-    done
-fi