diff --git a/.gitlab-ci/terraform.yml b/.gitlab-ci/terraform.yml
index 5bdb33ef787a10c9035707653ce42445c8be886f..22b20812c123a440d9f0ee4fc3dca74d263a39b6 100644
--- a/.gitlab-ci/terraform.yml
+++ b/.gitlab-ci/terraform.yml
@@ -10,9 +10,9 @@
     - cp ansible.cfg ~/.ansible.cfg
     # Prepare inventory
     - if [ "$PROVIDER" == "openstack" ]; then VARIABLEFILE="cluster.tfvars"; else VARIABLEFILE="cluster.tf"; fi
-    - cp contrib/terraform/$PROVIDER/sample-inventory/$VARIABLEFILE .
     - ln -s contrib/terraform/$PROVIDER/hosts
     - terraform init contrib/terraform/$PROVIDER
+    - cp contrib/terraform/$PROVIDER/sample-inventory/$VARIABLEFILE .
     # Copy SSH keypair
     - mkdir -p ~/.ssh
     - echo "$PACKET_PRIVATE_KEY" | base64 -d > ~/.ssh/id_rsa
@@ -55,7 +55,7 @@ tf-validate-openstack:
 tf-validate-packet:
   extends: .terraform_validate
   variables:
-    TF_VERSION: 0.11.11
+    TF_VERSION: 0.12.12
     PROVIDER: packet
     CLUSTER: $CI_COMMIT_REF_NAME
 
diff --git a/contrib/terraform/packet/kubespray.tf b/contrib/terraform/packet/kubespray.tf
index e3b6bfc2f99cefe538bef5b8a3422c105c17d3d6..568db0dd771782e40bf60b00c6fdcad4bab8afc2 100644
--- a/contrib/terraform/packet/kubespray.tf
+++ b/contrib/terraform/packet/kubespray.tf
@@ -4,59 +4,60 @@ provider "packet" {
 }
 
 resource "packet_ssh_key" "k8s" {
-  count      = "${var.public_key_path != "" ? 1 : 0}"
+  count      = var.public_key_path != "" ? 1 : 0
   name       = "kubernetes-${var.cluster_name}"
-  public_key = "${chomp(file(var.public_key_path))}"
+  public_key = chomp(file(var.public_key_path))
 }
 
 resource "packet_device" "k8s_master" {
-  depends_on = ["packet_ssh_key.k8s"]
-
-  count            = "${var.number_of_k8s_masters}"
-  hostname         = "${var.cluster_name}-k8s-master-${count.index+1}"
-  plan             = "${var.plan_k8s_masters}"
-  facilities       = ["${var.facility}"]
-  operating_system = "${var.operating_system}"
-  billing_cycle    = "${var.billing_cycle}"
-  project_id       = "${var.packet_project_id}"
+  depends_on = [packet_ssh_key.k8s]
+
+  count            = var.number_of_k8s_masters
+  hostname         = "${var.cluster_name}-k8s-master-${count.index + 1}"
+  plan             = var.plan_k8s_masters
+  facilities       = [var.facility]
+  operating_system = var.operating_system
+  billing_cycle    = var.billing_cycle
+  project_id       = var.packet_project_id
   tags             = ["cluster-${var.cluster_name}", "k8s-cluster", "kube-master", "etcd", "kube-node"]
 }
 
 resource "packet_device" "k8s_master_no_etcd" {
-  depends_on = ["packet_ssh_key.k8s"]
-
-  count            = "${var.number_of_k8s_masters_no_etcd}"
-  hostname         = "${var.cluster_name}-k8s-master-${count.index+1}"
-  plan             = "${var.plan_k8s_masters_no_etcd}"
-  facilities       = ["${var.facility}"]
-  operating_system = "${var.operating_system}"
-  billing_cycle    = "${var.billing_cycle}"
-  project_id       = "${var.packet_project_id}"
+  depends_on = [packet_ssh_key.k8s]
+
+  count            = var.number_of_k8s_masters_no_etcd
+  hostname         = "${var.cluster_name}-k8s-master-${count.index + 1}"
+  plan             = var.plan_k8s_masters_no_etcd
+  facilities       = [var.facility]
+  operating_system = var.operating_system
+  billing_cycle    = var.billing_cycle
+  project_id       = var.packet_project_id
   tags             = ["cluster-${var.cluster_name}", "k8s-cluster", "kube-master"]
 }
 
 resource "packet_device" "k8s_etcd" {
-  depends_on = ["packet_ssh_key.k8s"]
-
-  count            = "${var.number_of_etcd}"
-  hostname         = "${var.cluster_name}-etcd-${count.index+1}"
-  plan             = "${var.plan_etcd}"
-  facilities       = ["${var.facility}"]
-  operating_system = "${var.operating_system}"
-  billing_cycle    = "${var.billing_cycle}"
-  project_id       = "${var.packet_project_id}"
+  depends_on = [packet_ssh_key.k8s]
+
+  count            = var.number_of_etcd
+  hostname         = "${var.cluster_name}-etcd-${count.index + 1}"
+  plan             = var.plan_etcd
+  facilities       = [var.facility]
+  operating_system = var.operating_system
+  billing_cycle    = var.billing_cycle
+  project_id       = var.packet_project_id
   tags             = ["cluster-${var.cluster_name}", "etcd"]
 }
 
 resource "packet_device" "k8s_node" {
-  depends_on = ["packet_ssh_key.k8s"]
-
-  count            = "${var.number_of_k8s_nodes}"
-  hostname         = "${var.cluster_name}-k8s-node-${count.index+1}"
-  plan             = "${var.plan_k8s_nodes}"
-  facilities       = ["${var.facility}"]
-  operating_system = "${var.operating_system}"
-  billing_cycle    = "${var.billing_cycle}"
-  project_id       = "${var.packet_project_id}"
+  depends_on = [packet_ssh_key.k8s]
+
+  count            = var.number_of_k8s_nodes
+  hostname         = "${var.cluster_name}-k8s-node-${count.index + 1}"
+  plan             = var.plan_k8s_nodes
+  facilities       = [var.facility]
+  operating_system = var.operating_system
+  billing_cycle    = var.billing_cycle
+  project_id       = var.packet_project_id
   tags             = ["cluster-${var.cluster_name}", "k8s-cluster", "kube-node"]
 }
+
diff --git a/contrib/terraform/packet/output.tf b/contrib/terraform/packet/output.tf
index 2f9633deaa89ee84ed9233a7633f1c1e6fb49dbb..c27b9b915cfed945d8e2f30cc9e11023338cbefd 100644
--- a/contrib/terraform/packet/output.tf
+++ b/contrib/terraform/packet/output.tf
@@ -1,15 +1,16 @@
 output "k8s_masters" {
-  value = "${packet_device.k8s_master.*.access_public_ipv4}"
+  value = packet_device.k8s_master.*.access_public_ipv4
 }
 
 output "k8s_masters_no_etc" {
-  value = "${packet_device.k8s_master_no_etcd.*.access_public_ipv4}"
+  value = packet_device.k8s_master_no_etcd.*.access_public_ipv4
 }
 
 output "k8s_etcds" {
-  value = "${packet_device.k8s_etcd.*.access_public_ipv4}"
+  value = packet_device.k8s_etcd.*.access_public_ipv4
 }
 
 output "k8s_nodes" {
-  value = "${packet_device.k8s_node.*.access_public_ipv4}"
+  value = packet_device.k8s_node.*.access_public_ipv4
 }
+
diff --git a/contrib/terraform/packet/variables.tf b/contrib/terraform/packet/variables.tf
index e71b78bbfa4c54c2657c6e19d6f84af652498d51..83bdb5d0340cdc3ea9b2d08c8f8a9713ed540764 100644
--- a/contrib/terraform/packet/variables.tf
+++ b/contrib/terraform/packet/variables.tf
@@ -54,3 +54,4 @@ variable "number_of_etcd" {
 variable "number_of_k8s_nodes" {
   default = 0
 }
+
diff --git a/contrib/terraform/packet/versions.tf b/contrib/terraform/packet/versions.tf
new file mode 100644
index 0000000000000000000000000000000000000000..ac97c6ac8e7c1ce3bd191e54af4c6c57fa93643e
--- /dev/null
+++ b/contrib/terraform/packet/versions.tf
@@ -0,0 +1,4 @@
+
+terraform {
+  required_version = ">= 0.12"
+}
diff --git a/contrib/terraform/terraform.py b/contrib/terraform/terraform.py
index fa490d816ab7152a0f3252afd1e2427fa80c93fa..b9f50db4830a6deaa881eede77f40dcc8f5db33b 100755
--- a/contrib/terraform/terraform.py
+++ b/contrib/terraform/terraform.py
@@ -73,7 +73,7 @@ def iterresources(filenames):
                 # In version 4 the structure changes so we need to iterate
                 # each instance inside the resource branch.
                 for resource in state['resources']:
-                    name = resource['module'].split('.')[-1]
+                    name = resource['provider'].split('.')[-1]
                     for instance in resource['instances']:
                         key = "{}.{}".format(resource['type'], resource['name'])
                         if 'index_key' in instance:
@@ -182,6 +182,9 @@ def parse_list(source, prefix, sep='.'):
 
 
 def parse_bool(string_form):
+    if type(string_form) is bool:
+        return string_form
+
     token = string_form.lower()[0]
 
     if token == 't':
@@ -210,7 +213,7 @@ def packet_device(resource, tfvars=None):
         'state': raw_attrs['state'],
         # ansible
         'ansible_ssh_host': raw_attrs['network.0.address'],
-        'ansible_ssh_user': 'root',  # it's always "root" on Packet
+        'ansible_ssh_user': 'root',  # Use root by default in packet
         # generic
         'ipv4_address': raw_attrs['network.0.address'],
         'public_ipv4': raw_attrs['network.0.address'],
@@ -220,6 +223,10 @@ def packet_device(resource, tfvars=None):
         'provider': 'packet',
     }
 
+    if raw_attrs['operating_system'] == 'coreos_stable':
+        # For CoreOS set the ssh_user to core
+        attrs.update({'ansible_ssh_user': 'core'})
+
     # add groups based on attrs
     groups.append('packet_operating_system=' + attrs['operating_system'])
     groups.append('packet_locked=%s' % attrs['locked'])
@@ -342,7 +349,7 @@ def iter_host_ips(hosts, ips):
         use_access_ip = host[1]['metadata']['use_access_ip']
         if host_id in ips:
             ip = ips[host_id]
-            
+
             host[1].update({
                 'access_ip_v4': ip,
                 'access_ip': ip,