ansible-collections / ansible-collections/google.cloud

Behaviour of kubectl_path of gcp_container_cluster is unintutive, deprecated and undocumented

Open
#255 3 comments 0 reactions 0 assignees View on GitHub
stale
Dominant language
Python
Stars
105
Forks
144
Avg merge
5d 10h
Merged PRs (30d)
4

Description

##### SUMMARY
Specifying the parameter `kubectl_path` of `gcp_container_cluster` seems to cause the master auth credentials to be written to the kubeconfig file created at the specified path (judging from the exception below). This is

* undocumented
* unintuitive as `gcloud container clusters create` creates a kubeconfig without a state-of-the-art token-based authentication
* not only favouring, but enforcing deprecated (master auth for clusters) practice

##### ISSUE TYPE
- Bug Report
- Documentation report
- Feature request

##### COMPONENT NAME
gcp_container_cluster

##### ANSIBLE VERSION
```
ansible-playbook 2.9.2
config file = None
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/lib/python3.6/site-packages/ansible
executable location = /usr/local/bin/ansible-playbook
python version = 3.6.8 (default, Aug 7 2019, 17:28:10) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
```
and
```ansible-playbook 2.10.0.dev0
config file = None
configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/lib/python3.6/site-packages/ansible
executable location = /usr/local/bin/ansible-playbook
python version = 3.6.8 (default, Aug 7 2019, 17:28:10) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
```

##### CONFIGURATION
```
No config file found; using defaults
```

##### OS / ENVIRONMENT
Docker image `centos/centos7`

##### STEPS TO REPRODUCE
Build
```
FROM centos:centos7

RUN yum upgrade -y && yum install -y epel-release git
RUN yum install -y python3-pip openssh-clients && yum clean all
RUN git clone https://github.com/ansible/ansible.git && cd ansible && pip3 install . && cd .. && rm -rf ansible
RUN pip3 install --upgrade pip lxml requests google-auth
```

with `docker build -t dev .` and run `docker run -v "$(pwd):/mnt" -it dev sh -c 'cd /mnt; ansible-config dump --only-changed; ansible-playbook --ask-vault-pass install_gke_cluster.yml -vvv'` with playbook

```
---
- hosts: localhost
roles:
- role: k8s.cluster.gke
...
```

and task `roles/k8s.cluster.gke/tasks/main.yml`:

```
- name: "Create Google Kubernetes Engine Cluster"
gcp_container_cluster:
name: "{{cluster_name}}"
project: "{{project_id}}"
auth_kind: "serviceaccount"
location: "{{cluster_location}}"
logging_service: "none"
monitoring_service: "none"
service_account_contents: "{{service_account_contents}}"
initial_node_count: 1
kubectl_path: "/tmp/1"
register: cluster
```

put values in `roles/k8s.cluster.gke/defaults/main.yml` as I can't give you my GKE credentials :)

##### EXPECTED RESULTS
`kubeconfig` to be created in `/tmp/1` (what `gcloud container clusters create` creates in `.kube/config`). The kubeconfig should contain token-based credentials as that is what `gcloud` creates.

If you tackle the feature request aspect and provide token-based authentication, then you still might want to support username/password authentication for backwards compatibility. Therefore the failure below should be handle more gracefully, at least with an intuitive error message that doesn't require to look into the source code.

Both the current requirement for master credentials and how to get a token-based kubeconfig (as soon as implemented) should be documented.

##### ACTUAL RESULTS
The command fails due to
```
host_list declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Skipping due to inventory source not existing or not being readable by the current user
script declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
auto declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Skipping due to inventory source not existing or not being readable by the current user
yaml declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Skipping due to inventory source not existing or not being readable by the current user
ini declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Skipping due to inventory source not existing or not being readable by the current user
toml declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
[WARNING]: No inventory was parsed, only implicit localhost is available

[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

PLAYBOOK: install_gke_cluster.yml *********************************************************************************************************************************************************************************
1 plays in install_gke_cluster.yml

PLAY [localhost] **************************************************************************************************************************************************************************************************

TASK [Gathering Facts] ********************************************************************************************************************************************************************************************
task path: /mnt/install_gke_cluster.yml:2
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: root
<127.0.0.1> EXEC /bin/sh -c 'echo ~root && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1577455971.2539594-163372358451818 `" && echo ansible-tmp-1577455971.2539594-163372358451818="` echo /root/.ansible/tmp/ansible-tmp-1577455971.2539594-163372358451818 `" ) && sleep 0'
Using module file /usr/local/lib/python3.6/site-packages/ansible/modules/system/setup.py
<127.0.0.1> PUT /root/.ansible/tmp/ansible-local-7udgzyfs8/tmpaeb2oavb TO /root/.ansible/tmp/ansible-tmp-1577455971.2539594-163372358451818/AnsiballZ_setup.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1577455971.2539594-163372358451818/ /root/.ansible/tmp/ansible-tmp-1577455971.2539594-163372358451818/AnsiballZ_setup.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/bin/python3 /root/.ansible/tmp/ansible-tmp-1577455971.2539594-163372358451818/AnsiballZ_setup.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1577455971.2539594-163372358451818/ > /dev/null 2>&1 && sleep 0'
ok: [localhost]
META: ran handlers

TASK [k8s.cluster.gke : Create Google Kubernetes Engine Cluster] **************************************************************************************************************************************************
task path: /mnt/roles/k8s.cluster.gke/tasks/main.yml:1
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: root
<127.0.0.1> EXEC /bin/sh -c 'echo ~root && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1577455972.5203164-148877134187943 `" && echo ansible-tmp-1577455972.5203164-148877134187943="` echo /root/.ansible/tmp/ansible-tmp-1577455972.5203164-148877134187943 `" ) && sleep 0'
Using module file /usr/local/lib/python3.6/site-packages/ansible/modules/cloud/google/gcp_container_cluster.py
<127.0.0.1> PUT /root/.ansible/tmp/ansible-local-7udgzyfs8/tmpwxrdvmj0 TO /root/.ansible/tmp/ansible-tmp-1577455972.5203164-148877134187943/AnsiballZ_gcp_container_cluster.py
<127.0.0.1> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1577455972.5203164-148877134187943/ /root/.ansible/tmp/ansible-tmp-1577455972.5203164-148877134187943/AnsiballZ_gcp_container_cluster.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c '/usr/bin/python3 /root/.ansible/tmp/ansible-tmp-1577455972.5203164-148877134187943/AnsiballZ_gcp_container_cluster.py && sleep 0'
<127.0.0.1> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-tmp-1577455972.5203164-148877134187943/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
File "/root/.ansible/tmp/ansible-tmp-1577455972.5203164-148877134187943/AnsiballZ_gcp_container_cluster.py", line 102, in
_ansiballz_main()
File "/root/.ansible/tmp/ansible-tmp-1577455972.5203164-148877134187943/AnsiballZ_gcp_container_cluster.py", line 94, in _ansiballz_main
invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
File "/root/.ansible/tmp/ansible-tmp-1577455972.5203164-148877134187943/AnsiballZ_gcp_container_cluster.py", line 40, in invoke_module
runpy.run_module(mod_name='ansible.modules.cloud.google.gcp_container_cluster', init_globals=None, run_name='__main__', alter_sys=True)
File "/usr/lib64/python3.6/runpy.py", line 205, in run_module
return _run_module_code(code, init_globals, run_name, mod_spec)
File "/usr/lib64/python3.6/runpy.py", line 96, in _run_module_code
mod_name, mod_spec, pkg_name, script_name)
File "/usr/lib64/python3.6/runpy.py", line 85, in _run_code
exec(code, run_globals)
File "/tmp/ansible_gcp_container_cluster_payload_d0jf0pd_/ansible_gcp_container_cluster_payload.zip/ansible/modules/cloud/google/gcp_container_cluster.py", line 2055, in
File "/tmp/ansible_gcp_container_cluster_payload_d0jf0pd_/ansible_gcp_container_cluster_payload.zip/ansible/modules/cloud/google/gcp_container_cluster.py", line 1373, in main
File "/tmp/ansible_gcp_container_cluster_payload_d0jf0pd_/ansible_gcp_container_cluster_payload.zip/ansible/modules/cloud/google/gcp_container_cluster.py", line 1598, in write_file
File "/tmp/ansible_gcp_container_cluster_payload_d0jf0pd_/ansible_gcp_container_cluster_payload.zip/ansible/modules/cloud/google/gcp_container_cluster.py", line 1634, in _contents
KeyError: 'username'

fatal: [localhost]: FAILED! => {
"changed": false,
"module_stderr": "Traceback (most recent call last):\n File \"/root/.ansible/tmp/ansible-tmp-1577455972.5203164-148877134187943/AnsiballZ_gcp_container_cluster.py\", line 102, in \n _ansiballz_main()\n File \"/root/.ansible/tmp/ansible-tmp-1577455972.5203164-148877134187943/AnsiballZ_gcp_container_cluster.py\", line 94, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n File \"/root/.ansible/tmp/ansible-tmp-1577455972.5203164-148877134187943/AnsiballZ_gcp_container_cluster.py\", line 40, in invoke_module\n runpy.run_module(mod_name='ansible.modules.cloud.google.gcp_container_cluster', init_globals=None, run_name='__main__', alter_sys=True)\n File \"/usr/lib64/python3.6/runpy.py\", line 205, in run_module\n return _run_module_code(code, init_globals, run_name, mod_spec)\n File \"/usr/lib64/python3.6/runpy.py\", line 96, in _run_module_code\n mod_name, mod_spec, pkg_name, script_name)\n File \"/usr/lib64/python3.6/runpy.py\", line 85, in _run_code\n exec(code, run_globals)\n File \"/tmp/ansible_gcp_container_cluster_payload_d0jf0pd_/ansible_gcp_container_cluster_payload.zip/ansible/modules/cloud/google/gcp_container_cluster.py\", line 2055, in \n File \"/tmp/ansible_gcp_container_cluster_payload_d0jf0pd_/ansible_gcp_container_cluster_payload.zip/ansible/modules/cloud/google/gcp_container_cluster.py\", line 1373, in main\n File \"/tmp/ansible_gcp_container_cluster_payload_d0jf0pd_/ansible_gcp_container_cluster_payload.zip/ansible/modules/cloud/google/gcp_container_cluster.py\", line 1598, in write_file\n File \"/tmp/ansible_gcp_container_cluster_payload_d0jf0pd_/ansible_gcp_container_cluster_payload.zip/ansible/modules/cloud/google/gcp_container_cluster.py\", line 1634, in _contents\nKeyError: 'username'\n",
"module_stdout": "",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
"rc": 1
}

PLAY RECAP ********************************************************************************************************************************************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=1 skipped=0 rescued=0 ignored=0
```

Contributor guide

Open the contributing guide

Research direction

Start with ansible/modules/cloud/google/gcp_container_cluster.py, especially write_file and _contents, and reproduce the kubectl_path task shown in roles/k8s.cluster.gke/tasks/main.yml. Determine the supported kubeconfig authentication behavior, then ensure the result or failure is intuitive and that the current requirement and usage are documented.

Written by the indexing model from the issue text.

Assessment

Tech stack
gcp, kubernetes, python
Domain
cloud, devops
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.