Repository: openshift/openshift-ansible

Issue:
openshift_facts.py should convert booleans to strings?
#### Description


I set the 'logging-infra-fluentd': true label on upgrade from 3.5 to 3.6 and that worked without problems and fluentd is deployed correctly.

I then tried to run minor configuration change using
/usr/share/ansible/openshift-ansible/playbooks/byo/config.yml playbook

this causes ansible-run to fail .

##### Version

```
ansible 2.3.2.0
atomic-openshift-utils-3.6.173.0.48-1.git.0.1609d30.el7.noarch
openshift-ansible-3.6.173.0.48-1.git.0.1609d30.el7.noarch
```

##### Steps To Reproduce
1. Set 'logging-infra-fluentd': true label on node
2. Run upgrade openshift-cluster/upgrades/v3_6/upgrade.yml
3. Change OpenShift configuration on host-file
4. Run playbooks/byo/config.yml


##### Expected Results
Config.yml playbooks gets executed without problems.

##### Observed Results
Ansible run stops at TASK [openshift_facts : Gather Cluster facts and set is_containerized if needed]
```
ansible-playbook /usr/share/ansible/openshift-ansible/playbooks/byo/config.yml
`TASK [openshift_facts : Gather Cluster facts and set is_containerized if needed] 
fatal: [master2.example.com]: FAILED! => {
    "changed": false, 
    "failed": true, 
    "module_stderr": "Shared connection to master2.example.com closed.\r\n", 
    "module_stdout": "Traceback (most recent call last):\r\n  File \"/tmp/ansible_sdWyTY/ansible_module_openshift_facts.py\", line 2553, in <module>\r\n    main()\r\n  File \"/tmp/ansible_sdWyTY/ansible_module_openshift_facts.py\", line 2540, in main\r\n    protected_facts_to_overwrite)\r\n  File \"/tmp/ansible_sdWyTY/ansible_module_openshift_facts.py\", line 1948, in __init__\r\n    protected_facts_to_overwrite)\r\n  File \"/tmp/ansible_sdWyTY/ansible_module_openshift_facts.py\", line 2006, in generate_facts\r\n    facts = build_kubelet_args(facts)\r\n  File \"/tmp/ansible_sdWyTY/ansible_module_openshift_facts.py\", line 1211, in build_kubelet_args\r\n    labels_str = list(map(lambda x: '='.join(x), facts['node']['labels'].items()))\r\n  File \"/tmp/ansible_sdWyTY/ansible_module_openshift_facts.py\", line 1211, in <lambda>\r\n    labels_str = list(map(lambda x: '='.join(x), facts['node']['labels'].items()))\r\nTypeError: sequence item 1: expected string or Unicode, bool found\r\n",                                                                                                                 
    "rc": 0
}
---- Repeated for each node----

Hosts-file:

[nodes]
master1.example.com openshift_hostname=m1t-svc.example.com openshift_node_labels="{'region': 'infra', 'purpose': 'reserved', 'logging-infra-fluentd': true}" openshift_schedulable=false
master2.example.com openshift_hostname=m2t-svc.example.com openshift_node_labels="{'region': 'infra', 'purpose': 'reserved', 'logging-infra-fluentd': true}" openshift_schedulable=false
master3.example.com openshift_hostname=m3t-svc.example.com openshift_node_labels="{'region': 'infra', 'purpose': 'reserved', 'logging-infra-fluentd': true}" openshift_schedulable=false

infra1.example.com openshift_hostname=i1t-svc.example.com openshift_node_labels="{'region': 'infra', 'node-role': 'platform', 'logging-infra-fluentd': true}"
infra2.example.com openshift_hostname=i2t-svc.example.com openshift_node_labels="{'region': 'infra', 'node-role': 'platform', 'logging-infra-fluentd': true}"

app-node1.example.com openshift_hostname=n1t-svc.example.com openshift_node_labels="{'region': 'primary', 'logging-infra-fluentd': true}"
app-node2.example.com openshift_hostname=n2t-svc.example.com openshift_node_labels="{'region': 'primary', 'logging-infra-fluentd': true}"
```
### Additional information:

On openshift_facts/library/openshift_facts.py (line 840) when parsing node labels. The parser expects that all labels are strings:
```
labels_str = list(map(lambda x: '='.join(x), facts['node']['labels'].items()))
```
but it is possible to set node-labels as non-strings:
https://github.com/openshift/openshift-ansible/pull/2607


On each node the /etc/ansible/facts.d/openshift.fact contains follwing:
```
{"node": {"schedulable": "false", "labels": {"logging-infra-fluentd": true, "region": "infra", "purpose": "reserved"}
```
Even if I change the logging-infra-fluentd label to: {"logging-infra-fluentd": "true"} NOTE: The true on quotes

The openshift.fact is not updated. And issue can't be resolved by any means. 



Discussion:
This issue seems to be fixed in 3.8 (commit https://github.com/openshift/openshift-ansible/commit/42d3824ba0d5a1e2cff3dc3a179cf02e735bc5da).

Quckfix for using release-3.7:
```
-            labels_str = list(map(lambda x: '='.join(x), facts['node']['labels'].items()))
+            labels_str = list(map(lambda x: '='.join(map(str, x)), facts['node']['labels'].items()))
```



Resolving patch:
diff --git a/roles/openshift_facts/library/openshift_facts.py b/roles/openshift_facts/library/openshift_facts.py
--- a/roles/openshift_facts/library/openshift_facts.py
+++ b/roles/openshift_facts/library/openshift_facts.py
@@ -1098,7 +1098,7 @@ def build_kubelet_args(facts):
             # map() seems to be returning an itertools.imap object
             # instead of a list. We cast it to a list ourselves.
             # pylint: disable=unnecessary-lambda
-            labels_str = list(map(lambda x: '='.join(x), facts['node']['labels'].items()))
+            labels_str = list(map(lambda x: '='.join(map(str, x)), facts['node']['labels'].items()))
             if labels_str != '':
                 kubelet_args['node-labels'] = labels_str
 


Test patch: