0

So I'm trying to create a bash script to pass the IP array needed to make inventory file for ansible the official docs say that this is achieved through

declare -a IPS=(10.10.1.3 10.10.1.4 10.10.1.5)
CONFIG_FILE=inventory/mycluster/hosts.yaml python3 contrib/inventory_builder/inventory.py ${IPS[@]}

however in a bash script CONFIG_FILE is set up as variable so it stop the inventory file being created as the variable is not passed into the python file

i have tried the following to try and pass the varible to the python file in an attempt to create the inventory file

declare -a IPS=(10.10.1.3 10.10.1.4 10.10.1.5)
CONFIG_FILE=kubespray/inventory/mycluster/hosts.yaml
python3 kubespray/contrib/inventory_builder/inventory.py ${IPS[@]}

which results in

DEBUG: Adding group all
DEBUG: Adding group kube-master
DEBUG: Adding group kube-node
DEBUG: Adding group etcd
DEBUG: Adding group k8s-cluster
DEBUG: Adding group calico-rr
DEBUG: adding host node1 to group all
DEBUG: adding host node2 to group all
DEBUG: adding host node3 to group all
DEBUG: adding host node1 to group etcd
DEBUG: adding host node2 to group etcd
DEBUG: adding host node3 to group etcd
DEBUG: adding host node1 to group kube-master
DEBUG: adding host node2 to group kube-master
DEBUG: adding host node1 to group kube-node
DEBUG: adding host node2 to group kube-node
DEBUG: adding host node3 to group kube-node
Traceback (most recent call last):
  File "kubespray/contrib/inventory_builder/inventory.py", line 431, in <module>
    sys.exit(main())
  File "kubespray/contrib/inventory_builder/inventory.py", line 427, in main
    KubesprayInventory(argv, CONFIG_FILE)
  File "kubespray/contrib/inventory_builder/inventory.py", line 116, in __init__
    self.write_config(self.config_file)
  File "kubespray/contrib/inventory_builder/inventory.py", line 120, in write_config
    with open(self.config_file, 'w') as f:
FileNotFoundError: [Errno 2] No such file or directory: './inventory/sample/hosts.yaml'

I have also tried

declare -a IPS=(10.10.1.3 10.10.1.4 10.10.1.5)
CONFIG_FILE=kubespray/inventory/mycluster/hosts.yaml
${CONFIG_FILE} python3 kubespray/contrib/inventory_builder/inventory.py ${IPS[@]}

which results in

-bash: kubespray/inventory/mycluster/hosts.yaml: No such file or directory

which is understandable but the idea is to have the file created by the python script

is is possible to get the bash script working so that it performs the actions set out by

CONFIG_FILE=inventory/mycluster/hosts.yaml python3 contrib/inventory_builder/inventory.py ${IPS[@]}

?

UPDATE

So after some tinkering I came to the conclusion that this is probably due to my pip virtual environment as my script tries to create one before running the commands so for more context

#!/bin/bash

echo "setting up virtual environment"
sleep 2

sudo apt-get install python3-venv -y

python3 -m venv tutorial-env
source tutorial-env/bin/activate
echo "installing pip requirements"
sudo pip3 install -r kubespray/requirements.txt
cp -rfp kubespray/inventory/sample kubespray/inventory/mycluster
declare -a IPS=(IP1 IP2 IP3)
echo "${IPS[@]}"
CONFIG_FILE=kubespray/inventory/mycluster/hosts.yaml python3  kubespray/contrib/inventory_builder/inventory.py ${IPS[@]}
cat kubespray/inventory/mycluster/hosts.yaml
sudo ansible-playbook -i kubespray/inventory/mycluster/hosts.yaml --ssh-extra-args="-oStrictHostKeyChecking=no" --key-file "~/.ssh/id_rsa" --become-user="provision" kubespray/cluster.yml

if I remove the lines

python3 -m venv tutorial-env
source tutorial-env/bin/activate

Then the script works as intended, well to some degree as ideally it should be in the virtual env, apologies for the badly worded question

zigarn
  • 10,892
  • 2
  • 31
  • 45
user3700919
  • 325
  • 2
  • 4
  • 19
  • 2
    `VAR_NAME=value command` is a shell syntax to execute the `command` with extra env var `VAR_NAME`, it's not defining the variable `VAR_NAME` with value "`value command`". So it should work. What is the results of this command that make you say it doesn't work? The second syntax you tried is valid but can you test it by adding `export` at the beginning of the variable definition? The last syntax is expanding the variable value and taking it as the command to execute. – zigarn Feb 26 '21 at 05:42
  • Your errors also indicate it is unable to open _for writing_ the path you specified, so you'll want to ensure the parent directory exists and that you can write files into it – mdaniel Feb 26 '21 at 07:01
  • Hi @zigarn so I ran the script in the way suggested it seems that it may be working? ```echo "${IPS[@]}" CONFIG_FILE=kubespray/inventory/mycluster/hosts.yaml python3 kubespray/contrib/inventory_builder/inventory.py ${IPS[@]} cat kubespray/inventory/mycluster/hosts.yaml``` however I do receive receive a weird error which I think is environment specific – user3700919 Feb 26 '21 at 08:11
  • which is ```Requirement already satisfied: ruamel.yaml.clib>=0.1.2 in /usr/local/lib/python3.6/dist-packages (from ruamel.yaml==0.16.10->-r kubespray/requirements.txt (line 6)) (0.2.2) 192.168.10.44 192.168.10.42 192.168.10.43 Traceback (most recent call last): File "kubespray/contrib/inventory_builder/inventory.py", line 40, in from ruamel.yaml import YAML ModuleNotFoundError: No module named 'ruamel' cat: kubespray/inventory/mycluster/hosts.yaml: No such file or directory ``` – user3700919 Feb 26 '21 at 08:16
  • You should add this output in your question after the first syntax example. Did you copy the sample inventory first as documented in https://kubespray.io/#/docs/getting-started ? Because it looks like the issue is that the inventory builder script is trying to write in a folder/file that does not exists. – zigarn Feb 26 '21 at 08:19
  • @zigarn i'm not sure on this if I run the experiment on the terminal without the shell i get this (i will be splitting this answer) ```dc@ansible:~/xcp/xcp-projects$ kubespray/inventory/mycluster/hosts.yaml -bash: kubespray/inventory/mycluster/hosts.yaml: No such file or directory ``` – user3700919 Feb 26 '21 at 08:27
  • ```dc@ansible:~/xcp/xcp-projects$ declare -a IPS=(192.168.10.44 192.168.10.42 192.168.10.43) dc@ansible:~/xcp/xcp-projects$ CONFIG_FILE=kubespray/inventory/mycluster/hosts.yaml python3 kubespray/contrib/inventory_builder/inventory.py ${IPS[@]} DEBUG: Adding group all DEBUG: Adding group kube-master DEBUG: Adding group kube-node DEBUG: Adding group etcd DEBUG: Adding group k8s-cluster DEBUG: Adding group calico-rr DEBUG: adding host node1 to group all DEBUG: adding host node2 to group all DEBUG: adding host node3 to group all DEBUG: adding host node1 to group etcd ``` – user3700919 Feb 26 '21 at 08:28
  • ```DEBUG: adding host node2 to group etcd DEBUG: adding host node3 to group etcd DEBUG: adding host node1 to group kube-master DEBUG: adding host node2 to group kube-master DEBUG: adding host node1 to group kube-node DEBUG: adding host node2 to group kube-node DEBUG: adding host node3 to group kube-node ``` – user3700919 Feb 26 '21 at 08:29
  • ```dc@ansible:~/xcp/xcp-projects$ cat kubespray/inventory/mycluster/hosts.yaml all: hosts: node1: ansible_host: 192.168.10.44 ip: 192.168.10.44 access_ip: 192.168.10.44 node2: ansible_host: 192.168.10.42 ip: 192.168.10.42 access_ip: 192.168.10.42 node3: ansible_host: 192.168.10.43 ip: 192.168.10.43 access_ip: 192.168.10.43 ``` – user3700919 Feb 26 '21 at 08:29
  • 1
    Can you give more context on your script? In which context you launch it, ... Compared by launching the command directly. Because from the output, when launching with the script, the inventory builder script is just failing because of python import issue with ruamel.yaml. Please edit your question to add more info, not in comments. – zigarn Feb 26 '21 at 08:43
  • Hi @zigarn you are correct that it is local environment problem with the python import issue, thank you so much, I have updated the context hopefully it provides more clarity into the problem – user3700919 Feb 26 '21 at 13:20

1 Answers1

2

The issue comes from the sudo in your script.

You create a virtualenv and activate it for the local session.
But then you change to root context to install the requirements, which are installed at system-level, not virtualenv level.
Then you execute back python in the virtualenv context without the requirements installed and it fails.

It explains why it works without virtualenv as you use the system-level installed requirements.

To solve the problem, just install the requirements without the sudo when you are working in the virtualenv: to install requirements and to execute ansible.

zigarn
  • 10,892
  • 2
  • 31
  • 45
  • 2
    At the end, it had nothing to do with the line you thought was an issue, that's why you should always give complete context when asking a question on SO ;-) – zigarn Feb 26 '21 at 13:44
  • fair enough, I naively assumed I had isolated the issue, thank you for helping me understand what the root cause was – user3700919 Feb 26 '21 at 17:43