-
Notifications
You must be signed in to change notification settings - Fork 23
Description
The issue
I tried reclass an inventory with one yaml value referencing another value nested inside an Array and nested classes are involved.
The issue is very difficult for me to describe since I am not familiar with the "reclass" ontology, so I describe it with full reproduction instructions (see below).
I am using the develop branch from https://github.com/salt-formulas/reclass , that is version 1.7.0 of reclass.
My system is Ubuntu 18.04 on amd64 with python 3.6 (Python 3.6.9 according to python -v).
Here is the stacktrace that I get when I run python reclass.py -b mytest --inventory in my virtualenv :
Running:
Traceback (most recent call last):
File "reclass.py", line 15, in <module>
reclass.cli.main()
File "/home/julien/reclass/reclass/cli.py", line 48, in main
print(output(data, options.output, options.pretty_print, options.no_refs))
File "/home/julien/reclass/reclass/__init__.py", line 28, in output
return outputter.dump(data, pretty_print=pretty_print, no_refs=no_refs)
...
File "/home/julien/reclass/myenv/lib/python3.6/site-packages/PyYAML-5.3.1-py3.6-linux-x86_64.egg/yaml/representer.py", line 58, in represent_data
node = self.yaml_representers[None](self, data)
File "/home/julien/reclass/myenv/lib/python3.6/site-packages/PyYAML-5.3.1-py3.6-linux-x86_64.egg/yaml/representer.py", line 231, in represent_undefined
raise RepresenterError("cannot represent an object", data)
yaml.representer.RepresenterError: ('cannot represent an object', Value(RefItem([ScaItem('kubemanual:hosts:0:interfaces:public:ip')])))
I can work around by duplicating the indirect reference to use the direct reference everywhere in my inventory,
but I'd rather have a shorter and more flexible inventory.
How to reproduce
In my reproduction scenario, the directory structure is as follows:
julien:mytest(79078m|develop?) $ find mytest -type f
mytest/classes/kubemanual.yml
mytest/classes/kubespray.yml
mytest/nodes/mynode.ymlThe files are created as follows:
# install some dependencies needed to install the bundle
sudo apt-get install libyaml-dev
# checkout the reclass project and cd into it
git clone https://github.com/salt-formulas/reclass myreclass
cd myreclass
# install everything into a venv, activate it
virtualenv -p python3.6 myenv
source myenv/bin/activate
python setup.py install
# prepare the bug fixtures
mkdir -p mytest/classes mytest/nodes
# create mytest/nodes/mynode.yml
echo -n '---
classes:
- kubemanual
parameters:
kubemanual:
hosts:
- name: one
interfaces:
public:
name: eth0
ip: 8.8.8.8
private:
name: eth1
ip: 192.168.0.1
access-ip: ${kubemanual:hosts:0:interfaces:public:ip}
' | tee mytest/nodes/mynode.yml
# create mytest/classes/kubemanual.yml
echo -n '---
classes:
- kubespray
parameters:
kubemanual:
hosts: []
kubespray:
access-ip-using-indirect-item: ${kubemanual:hosts:0:interfaces:public:ip}
access-ip-using-direct-item: ${kubemanual:hosts:0:access-ip}
' | tee mytest/classes/kubemanual.yml
# create mytest/classes/kubespray.yml
echo -n '---
parameters:
kubespray: {}
' | tee mytest/classes/kubespray.ymlThis finishes setting up the bug fixture directory.
Some tests and comments
Running with both direct and indirect references and the kubespray class imported
Run:
python reclass.py -b mytest --inventoryShould trigger the exception reported above.
Running with only the indirect reference and the kubespray class imported
Run:
sed -i -e 's/^.*- kubespray/ - kubespray/' mytest/classes/kubemanual.yml
sed -i -e 's/^.*access-ip-using-direct-item:/ #access-ip-using-direct-item:/' mytest/classes/kubemanual.yml
sed -i -e 's/^.*access-ip-using-indirect-item:/ access-ip-using-indirect-item:/' mytest/classes/kubemanual.yml
egrep '(access-ip|kubespray)' mytest/classes/kubemanual.yml
python reclass.py -b mytest --inventoryShould result in a functional inventory
Running with only the direct reference and the kubespray class imported
Run:
sed -i -e 's/^.*- kubespray/ - kubespray/' mytest/classes/kubemanual.yml
sed -i -e 's/^.*access-ip-using-direct-item:/ access-ip-using-direct-item:/' mytest/classes/kubemanual.yml
sed -i -e 's/^.*access-ip-using-indirect-item:/ #access-ip-using-indirect-item:/' mytest/classes/kubemanual.yml
egrep '(access-ip|kubespray)' mytest/classes/kubemanual.yml
python reclass.py -b mytest --inventoryShould also trigger the exception reported above.
So, does it mean that the indirect reference alone triggers the bug?
Running with both direct and indirect references and the kubespray class commented
Run:
sed -i -e 's/^.*- kubespray/ #- kubespray/' mytest/classes/kubemanual.yml
sed -i -e 's/^.*access-ip-using-direct-item:/ access-ip-using-direct-item:/' mytest/classes/kubemanual.yml
sed -i -e 's/^.*access-ip-using-indirect-item:/ access-ip-using-indirect-item:/' mytest/classes/kubemanual.yml
egrep '(access-ip|kubespray)' mytest/classes/kubemanual.yml
python reclass.py -b mytest --inventoryShould result in a functional inventory.
Looks like the problem is in the kubespray class, not in the indirect reference !
Running the inventory with an empty kubespray class
Run:
sed -i -e 's/^.*- kubespray/ #- kubespray/' mytest/classes/kubemanual.yml
sed -i -e 's/^.*access-ip-using-direct-item:/ access-ip-using-direct-item:/' mytest/classes/kubemanual.yml
sed -i -e 's/^.*access-ip-using-indirect-item:/ access-ip-using-indirect-item:/' mytest/classes/kubemanual.yml
# this is the important part
sed -i -e s/kubespray/notkubespray/ mytest/classes/kubespray.yml
egrep '(access-ip|kubespray)' mytest/classes/kubemanual.yml
python reclass.py -b mytest --inventoryThis last example also results in a functional inventory.
The bug does not trigger !
Conclusion
The bug occurs when:
- the
kubesprayclass is imported from within thekubemanualclass - the node file declares
parameters.kubespray.access-ip-using-indirect-itemwhich indirectly references a value which is located inside an array item - the
kubesprayclass has already definedparameters.kubespray(even if it is an empty dictionary)
The bug does not occur when either:
- using the direct reference instead of the indirect one
- the
parameters.kubesprayis undefined at the time the indirect reference withinparameters.kubesprayis evaluated