From ef8e35e39bf088dd1e9e1fbdbfc732e9208f9061 Mon Sep 17 00:00:00 2001
From: Matthew Mosesohn <mmosesohn@mirantis.com>
Date: Mon, 18 Sep 2017 13:30:57 +0100
Subject: [PATCH] Create admin credential kubeconfig (#1647)

New files: /etc/kubernetes/admin.conf
           /root/.kube/config
           $GITDIR/artifacts/{kubectl,admin.conf}

Optional method to download kubectl and admin.conf if
kubeconfig_lcoalhost is set to true (default false)
---
 .gitignore                                    |  1 +
 cluster.yml                                   |  1 +
 docs/getting-started.md                       | 14 ++++
 inventory/group_vars/k8s-cluster.yml          |  5 ++
 roles/kubernetes/client/defaults/main.yml     |  7 ++
 roles/kubernetes/client/tasks/main.yml        | 66 +++++++++++++++++++
 .../kubernetes/client/templates/admin.conf.j2 | 19 ++++++
 roles/kubespray-defaults/defaults/main.yaml   |  5 ++
 tests/cloud_playbooks/create-gce.yml          |  2 +-
 upgrade-cluster.yml                           |  1 +
 10 files changed, 120 insertions(+), 1 deletion(-)
 create mode 100644 roles/kubernetes/client/defaults/main.yml
 create mode 100644 roles/kubernetes/client/tasks/main.yml
 create mode 100644 roles/kubernetes/client/templates/admin.conf.j2

diff --git a/.gitignore b/.gitignore
index 4df491aa1..4791280e9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,6 +22,7 @@ __pycache__/
 
 # Distribution / packaging
 .Python
+artifacts/
 env/
 build/
 credentials/
diff --git a/cluster.yml b/cluster.yml
index 7b842d917..d9240ac97 100644
--- a/cluster.yml
+++ b/cluster.yml
@@ -82,6 +82,7 @@
     - { role: kubespray-defaults}
     - { role: kubernetes-apps/network_plugin, tags: network }
     - { role: kubernetes-apps/policy_controller, tags: policy-controller }
+    - { role: kubernetes/client, tags: client }
 
 - hosts: calico-rr
   any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
diff --git a/docs/getting-started.md b/docs/getting-started.md
index 65b590a2f..f0c7c0014 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -101,3 +101,17 @@ access the Kubernetes Dashboard at the following URL:
 To see the password, refer to the section above, titled *Connecting to
 Kubernetes*. The host can be any kube-master or kube-node or loadbalancer
 (when enabled).
+
+Accessing Kubernetes API
+------------------------
+
+The main client of Kubernetes is `kubectl`. It is installed on each kube-master
+host and can optionally be configured on your ansible host by setting
+`kubeconfig_localhost: true` in the configuration. If enabled, kubectl and
+admin.conf will appear in the artifacts/ directory after deployment. You can
+see a list of nodes by running the following commands:
+
+    cd artifacts/
+    ./kubectl --kubeconfig admin.conf get nodes
+
+If desired, copy kubectl to your bin dir and admin.conf to ~/.kube/config.
diff --git a/inventory/group_vars/k8s-cluster.yml b/inventory/group_vars/k8s-cluster.yml
index bdcca73d4..c185fe46c 100644
--- a/inventory/group_vars/k8s-cluster.yml
+++ b/inventory/group_vars/k8s-cluster.yml
@@ -152,6 +152,11 @@ efk_enabled: false
 # Helm deployment
 helm_enabled: false
 
+# Make a copy of kubeconfig on the host that runs Ansible in GITDIR/artifacts
+# kubeconfig_localhost: false
+# Download kubectl onto the host that runs Ansible in GITDIR/artifacts
+# kubectl_localhost: false
+
 # dnsmasq
 # dnsmasq_upstream_dns_servers:
 #  - /resolvethiszone.with/10.0.4.250
diff --git a/roles/kubernetes/client/defaults/main.yml b/roles/kubernetes/client/defaults/main.yml
new file mode 100644
index 000000000..5864e991f
--- /dev/null
+++ b/roles/kubernetes/client/defaults/main.yml
@@ -0,0 +1,7 @@
+---
+kubeconfig_localhost: false
+kubectl_localhost: false
+artifacts_dir: "./artifacts"
+
+kube_config_dir: "/etc/kubernetes"
+kube_apiserver_port: "6443"
diff --git a/roles/kubernetes/client/tasks/main.yml b/roles/kubernetes/client/tasks/main.yml
new file mode 100644
index 000000000..06df5af68
--- /dev/null
+++ b/roles/kubernetes/client/tasks/main.yml
@@ -0,0 +1,66 @@
+---
+- name: Set first kube master
+  set_fact:
+    first_kube_master: "{{ hostvars[groups['kube-master'][0]]['access_ip'] | default(hostvars[groups['kube-master'][0]]['ip'] | default(hostvars[groups['kube-master'][0]]['ansible_default_ipv4']['address'])) }}"
+
+- name: Set external kube-apiserver endpoint
+  set_fact:
+    external_apiserver_endpoint: >-
+      {%- if loadbalancer_apiserver is defined and loadbalancer_apiserver.port is defined -%}
+      https://{{ apiserver_loadbalancer_domain_name|default('lb-apiserver.kubernetes.local') }}:{{ loadbalancer_apiserver.port|default(kube_apiserver_port) }}
+      {%- else -%}
+      https://{{ first_kube_master }}:{{ kube_apiserver_port }}
+      {%- endif -%}
+  tags: facts
+
+- name: Gather certs for admin kubeconfig
+  slurp:
+    src: "{{ item }}"
+  delegate_to: "{{ groups['kube-master'][0] }}"
+  delegate_facts: no
+  register: admin_certs
+  with_items:
+    - "{{ kube_cert_dir }}/ca.pem"
+    - "{{ kube_cert_dir }}/admin-{{ inventory_hostname }}.pem"
+    - "{{ kube_cert_dir }}/admin-{{ inventory_hostname }}-key.pem"
+  when: not kubeadm_enabled|d(false)|bool
+
+- name: Write admin kubeconfig
+  template:
+    src: admin.conf.j2
+    dest: "{{ kube_config_dir }}/admin.conf"
+  when: not kubeadm_enabled|d(false)|bool
+
+- name: Create kube config dir
+  file:
+    path: "/root/.kube"
+    mode: "0700"
+    state: directory
+
+- name: Copy admin kubeconfig to root user home
+  copy:
+    src: "{{ kube_config_dir }}/admin.conf"
+    dest: "/root/.kube/config"
+    remote_src: yes
+    mode: "0700"
+    backup: yes
+
+- name: Copy admin kubeconfig to ansible host
+  fetch:
+    src: "{{ kube_config_dir }}/admin.conf"
+    dest: "{{ artifacts_dir }}/admin.conf"
+    flat: yes
+    validate_checksum: no
+  become: no
+  run_once: yes
+  when: kubeconfig_localhost|default(false)
+
+- name: Copy kubectl binary to ansible host
+  fetch:
+    src: "{{ bin_dir }}/kubectl"
+    dest: "{{ artifacts_dir }}/kubectl"
+    flat: yes
+    validate_checksum: no
+  become: no
+  run_once: yes
+  when: kubectl_localhost|default(false)
diff --git a/roles/kubernetes/client/templates/admin.conf.j2 b/roles/kubernetes/client/templates/admin.conf.j2
new file mode 100644
index 000000000..b1640c1c5
--- /dev/null
+++ b/roles/kubernetes/client/templates/admin.conf.j2
@@ -0,0 +1,19 @@
+apiVersion: v1
+kind: Config
+current-context: admin-{{ cluster_name }}
+preferences: {}
+clusters:
+- cluster:
+    certificate-authority-data: {{ admin_certs.results[0]['content'] }}
+    server: {{ external_apiserver_endpoint }}
+  name: {{ cluster_name }}
+contexts:
+- context:
+    cluster: {{ cluster_name }}
+    user: admin-{{ cluster_name }}
+  name: admin-{{ cluster_name }}
+users:
+- name: admin-{{ cluster_name }}
+  user:
+    client-certificate-data: {{ admin_certs.results[1]['content'] }}
+    client-key-data: {{ admin_certs.results[2]['content'] }}
diff --git a/roles/kubespray-defaults/defaults/main.yaml b/roles/kubespray-defaults/defaults/main.yaml
index 5bd2fdc14..3c07147da 100644
--- a/roles/kubespray-defaults/defaults/main.yaml
+++ b/roles/kubespray-defaults/defaults/main.yaml
@@ -118,6 +118,11 @@ vault_deployment_type: docker
 kubeadm_enabled: false
 kubeadm_token: "abcdef.0123456789abcdef"
 
+# Make a copy of kubeconfig on the host that runs Ansible in GITDIR/artifacts
+kubeconfig_localhost: false
+# Download kubectl onto the host that runs Ansible in GITDIR/artifacts
+kubectl_localhost: false
+
 # K8s image pull policy (imagePullPolicy)
 k8s_image_pull_policy: IfNotPresent
 efk_enabled: false
diff --git a/tests/cloud_playbooks/create-gce.yml b/tests/cloud_playbooks/create-gce.yml
index 2b4822723..11cd9a646 100644
--- a/tests/cloud_playbooks/create-gce.yml
+++ b/tests/cloud_playbooks/create-gce.yml
@@ -63,4 +63,4 @@
   gather_facts: false
   tasks:
     - name: Wait for SSH to come up.
-      local_action: wait_for host={{inventory_hostname}} port=22 delay=60 timeout=240 state=started
+      local_action: wait_for host={{ansible_host}} port=22 delay=60 timeout=240 state=started
diff --git a/upgrade-cluster.yml b/upgrade-cluster.yml
index 3dcb69f29..b83681525 100644
--- a/upgrade-cluster.yml
+++ b/upgrade-cluster.yml
@@ -89,6 +89,7 @@
     - { role: kubespray-defaults}
     - { role: kubernetes-apps/network_plugin, tags: network }
     - { role: kubernetes-apps/policy_controller, tags: policy-controller }
+    - { role: kubernetes/client, tags: client }
 
 - hosts: calico-rr
   any_errors_fatal: "{{ any_errors_fatal | default(true) }}"
-- 
GitLab