Ansible Simulate "Press Enter" for shell script - ansible

I am trying to run this script:
/usr/share/postgresql-common/pgdg/apt.postgresql.org.sh
When I run it without Ansible I get this:
This script will enable the PostgreSQL APT repository on apt.postgresql.org on
your system. The distribution codename used will be focal-pgdg.
Press Enter to continue, or Ctrl-C to abort.
I tried this and some other variations on this.
- name: 2) Run the PostgreSQL repository setup script
become: yes
expect:
command: /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh
responses:
Question:
- This script will enable the PostgreSQL APT repository on apt.postgresql.org on
- your system. The distribution codename used will be focal-pgdg.
-
- Press Enter to continue, or Ctrl-C to abort.: echo -e '\n\n'
timeout: 30
Output:
fatal: [eos-test2]: FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"cmd": "/usr/share/postgresql-common/pgdg/apt.postgresql.org.sh",
"delta": "0:00:30.137319",
"end": "2022-10-06 14:09:16.421921",
"invocation": {
"module_args": {
"chdir": null,
"command": "/usr/share/postgresql-common/pgdg/apt.postgresql.org.sh",
"creates": null,
"echo": false,
"removes": null,
"responses": {
"Question": [
"This script will enable the PostgreSQL APT repository on apt.postgresql.org on",
"your system. The distribution codename used will be focal-pgdg.",
null,
{
"Press Enter to continue, or Ctrl-C to abort.": "echo -e '\\n\\n'"
}
]
},
"timeout": 30
}
},
"msg": "command exceeded timeout",
"rc": null,
"start": "2022-10-06 14:08:46.284602",
"stdout": "This script will enable the PostgreSQL APT repository on apt.postgresql.org on\r\nyour system. The distribution codename used will be focal-pgdg.\r\n\r\nPress Enter to continue, or Ctrl-C to abort.",
"stdout_lines": [
"This script will enable the PostgreSQL APT repository on apt.postgresql.org on",
"your system. The distribution codename used will be focal-pgdg.",
"",
"Press Enter to continue, or Ctrl-C to abort."
]
}
The script itself has
if [ -z "${YES:-}" ]; then
echo -n "Press Enter to continue, or Ctrl-C to abort."
read enter
echo
fi
I was thinking of modifying the original script.
Any suggestions?
Thank you in advance.

If you look at that /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh script, you'll see at the beginning:
while getopts "c:f:h:ipstv:y" opt ; do
case $opt in
c) COMPONENTS="main $OPTARG" ;; # make these extra components available
f) SOURCESLIST=$OPTARG ;; # sources.list filename to write to
h) HOST="$OPTARG" ;; # hostname to use in sources.list
i) INSTALL="yes" ;; # install packages for version given with -v
p) PURGE="yes" ;; # purge existing postgresql packages
s) DEB_SRC="deb-src" ;; # include source repository as well
t) PGDG="pgdg-testing" ;; # use *-pgdg or *-pgdg-testing
v) PGVERSION="$OPTARG" ;; # set up sources.list to use this version (useful for beta/devel packages)
y) ;; # don't ask for confirmation
*) exit 5 ;;
esac
YES="yes" # don't ask for confirmation if any option is given
done
This tells us (explicitly, via the comment) that the script won't prompt if you specify any command line options:
- name: install postgres
command: /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh -i -v 14
Furthermore, based on the code you show in your question, you could just set the YES environment variable to a non-empty value to suppress prompting:
- name: install postgres
environment:
YES: yes
command: /usr/share/postgresql-common/pgdg/apt.postgresql.org.sh

pause module has the same behavior.
https://docs.ansible.com/ansible/latest/collections/ansible/builtin/pause_module.html

Related

Ansible Tower server claims it was sent a bad request

I have written a playbook to create credentials with custom credentials, below is the ansible playbook
---
- name: Trigger an Atower API
hosts: localhost
connection: local
tasks:
- name: Create a valid SCM credential from a private_key file
command: tower-cli credential create --organization "Default" --name "DevOps User" --credential-type "csa-test2" --inputs "{'user':'devops', 'stg01_ssh_key':\"$( sed -z 's/\n/\\n/g' test.pem )\" }"
no_log: false
I am getting this error related to quotaions
name", "DevOps User", "--credential-type", "csa-test2", "--inputs", "{'user':'devops', 'stg01_ssh_key':\"$( sed -z 's/\\n/\\n/g' test.pem )\" }"], "delta": "0:00:01.319114", "end": "2021-01-07 16:00:22.763388", "msg": "non-zero return code", "rc": 40, "start": "2021-01-07 16:00:21.444274", "stderr": "Error: The Tower server claims it was sent a bad request.\n\nPOST http://x.x.x.x:13080/api/v2/credentials/\nParams: None\nData: {\"inputs\": {\"stg01_ssh_key\": \"$( sed -z 's/\\n/\\n/g' test.pem )\", \"user\": \"devops\"}, \"credential_type\": 36, \"organization\": 1, \"name\": \"DevOps User\"}\n\nResponse: {\"inputs\":{\"stg01_ssh_key\":[\"Invalid certificate or key: $( sed -z 's/\\n/\\n/g' test.pem )...\"]}}", "stderr_lines": ["Error: The Tower server claims it was sent a bad request.", "", "POST http://x.x.x.x:13080/api/v2/credentials/", "Params: None", "Data: {\"inputs\": {\"stg01_ssh_key\": \"$( sed -z 's/\\n/\\n/g' test.pem )\", \"user\": \"devops\"}, \"credential_type\": 36, \"organization\": 1, \"name\": \"DevOps User\"}", "", "Response: {\"inputs\":{\"stg01_ssh_key\":[\"Invalid certificate or key: $( sed -z 's/\\n/\\n/g' test.pem )...\"]}}"], "stdout": "", "stdout_lines": []}
Also, when i try manually "tower-cli create" command, it is working fine. Can anyone help me in this. I dunno what is wrong here.
try to use shell instead of command, documentation says
The command(s) will not be processed through the shell, so variables like $HOSTNAME and operations like "*", "<", ">", "|", ";" and "&" will not work. Use the ansible.builtin.shell module if you need these features.
source: Ansible Documentation

shell script gives incorrect output when invoked using Ansible shell module

I have check.sh script that I wish to run on the target nodes:
cat check.sh
str=`echo $1 | sed -e 's#[\][\]n# #g'`
echo $str>check.row
It is suppose to replace \n with a single white space from the argument and save it in check.row file.
When I run it manually on the target server i get good output results as shown below:
bash -x ./check.sh '/fin/app/01/scripts\\n/fin/app/01/sql'
++ echo '/fin/app/01/scripts\\n/fin/app/01/sql'
++ sed -e 's#[\][\]n# #g'
+ str='/fin/app/01/scripts /fin/app/01/sql'
+ echo /fin/app/01/scripts /fin/app/01/sql
The check.row generated looks good as below:
[user1#remotehost1 ~]$ cat check.row
/fin/app/01/scripts /fin/app/01/sql
However, when i run the same using ansible shell or command module I do not get the expected results.
Below is my playbook:
tasks:
- copy:
src: "{{ playbook_dir }}/files/check.sh"
dest: "~/"
mode: 0754
- set_fact:
install_dir: "{{ hostvars[\'localhost\'][\'command_result\'].stdout.split('\t')[2] }}"
- shell: "bash -x ~/check.sh '{{ install_dir }}' > ~/check_rollback.log"
See ansible's debug output below:
changed: [10.8.44.55] => {
"changed": true,
"cmd": "bash -x ~/check.sh '/fin/app/01/scripts\\n/fin/app/01/sql' > ~/check_rollback.log",
"delta": "0:00:00.118943",
"end": "2019-09-04 10:50:16.503745",
"invocation": {
"module_args": {
"_raw_params": "bash -x ~/check.sh '/fin/app/01/scripts\\n/fin/app/01/sql' > ~/check_rollback.log",
"_uses_shell": true,
"argv": null,
"chdir": null,
"creates": null,
"executable": null,
"removes": null,
"stdin": null,
"stdin_add_newline": true,
"strip_empty_ends": true,
"warn": true
}
},
"rc": 0,
"start": "2019-09-04 10:50:16.384802",
"stderr": "++ echo '/fin/app/01/scripts\\n/fin/app/01/sql'\n++ sed -e 's#[\\][\\]n# #g'\n+ str='/fin/app/01/scripts\\n/fin/app/01/sql'\n+ echo '/fin/app/01/scripts\\n/fin/app/01/sql'",
"stderr_lines": [
"++ echo '/fin/app/01/scripts\\n/fin/app/01/sql'",
"++ sed -e 's#[\\][\\]n# #g'",
"+ str='/fin/app/01/scripts\\n/fin/app/01/sql'",
"+ echo '/fin/app/01/scripts\\n/fin/app/01/sql'"
],
"stdout": "",
"stdout_lines": [] }
And here is the check.row file output from ansible's run:
[user1#remotehost1 ~]$ cat check.row
/fin/app/01/scripts\\n/fin/app/01/sql
As you can instead of single whitespace it is now printing \n.
I am on the latest version of ansible.
One can replicate this issue easily. Can you please suggest why am I getting this issue and how to fix this?
First of all, you are using the shell module in which only the shell command is specified, you have incorrectly used bash in it.
shell: "bash -x ~/check.sh '{{ install_dir }}' > ~/check_rollback.log"
Secondly, as you can see your task has resulted in an error as seen in your attached output.
Stdout is empty and we can see an error in stderr.
Thirdly, If you want to use bash you can use command module, as shown below,
- command: "bash -x ~/check.sh '{{ install_dir }}' > ~/check_rollback.log"
I also suggest the following changes in your check.sh script,
#!/bin/bash
echo $1 # You can check the value that is passed to the script
str=$(echo "$1" | sed -e 's/\\n/ /g') # Use quotes around your variable
echo "$str" > check.row
And it is working fine.

Ansible fortios_config backups not working

I use Fortinet for firewall automation, but i get the error "Error reading running config" . I already followed this website: https://github.com/ansible/ansible/issues/33392
But do not find any solution. Please tell me what am I doing wrong ?
Ansible version: 2.7.0
Python version: 2.7.5
Fortinet: 60E
FortiOS version: 6.0.2
Here is what I am trying:
FortiOS.yml playbook:
---
- name: FortiOS Firewall Settings
hosts: fortiFW
connection: local
vars_files:
- /etc/ansible/vars/FortiOS_Settings_vars.yml
tasks:
- name: Backup current config
fortios_config:
host: 192.168.1.99
username: admin
password: Password#123
backup: yes
backup_path: /etc/ansible/forti_backup
Here is what I get as error:
ok: [192.168.1.99] META: ran handlers Read vars_file
'/etc/ansible/vars/FortiOS_Settings_vars.yml'
TASK [Backup current config]
**************************************************************************************************************************************************************************************************************** task path: /etc/ansible/FortiOS_Settings_test.yml:8 <192.168.1.99>
ESTABLISH LOCAL CONNECTION FOR USER: root <192.168.1.99> EXEC /bin/sh
-c 'echo ~root && sleep 0' <192.168.1.99> EXEC /bin/sh -c '( umask 77 && mkdir -p "echo
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226" && echo
ansible-tmp-1539674386.05-16470854685226="echo
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226" ) &&
sleep 0' Using module file
/usr/lib/python2.7/site-packages/ansible/modules/network/fortios/fortios_config.py
<192.168.1.99> PUT
/root/.ansible/tmp/ansible-local-6154Uq5Dmw/tmpt6JukB TO
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226/AnsiballZ_fortios_config.py
<192.168.1.99> EXEC /bin/sh -c 'chmod u+x
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226/
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226/AnsiballZ_fortios_config.py
&& sleep 0' <192.168.1.99> EXEC /bin/sh -c '/usr/bin/python
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226/AnsiballZ_fortios_config.py
&& sleep 0' <192.168.1.99> EXEC /bin/sh -c 'rm -f -r
/root/.ansible/tmp/ansible-tmp-1539674386.05-16470854685226/ >
/dev/null 2>&1 && sleep 0' The full traceback is: WARNING: The below
traceback may not be related to the actual failure. File
"/tmp/ansible_fortios_config_payload_b6IQmy/main.py", line 132, in
main
f.load_config(path=module.params['filter']) File "/usr/lib/python2.7/site-packages/pyFG/fortios.py", line 212, in
load_config
config_text = self.execute_command(command) File "/usr/lib/python2.7/site-packages/pyFG/fortios.py", line 154, in
execute_command
output = output + self._read_wrapper(o) File "/usr/lib/python2.7/site-packages/pyFG/fortios.py", line 120, in
_read_wrapper
return py23_compat.text_type(data)
fatal: [192.168.1.99]: FAILED! => {
"changed": false,
"invocation": {
"module_args": {
"backup": true,
"backup_filename": null,
"backup_path": "/etc/ansible/forti_backup",
"config_file": null,
"file_mode": false,
"filter": "",
"host": "192.168.1.99",
"password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
"src": null,
"timeout": 60,
"username": "admin",
"vdom": null
}
},
"msg": "Error reading running config" }
When working with this module, I had the same issue. I looked into the source code of the module, and found that this error occurs when filter is set to "" -> empty string. You can get facts about the device when changing filter to something like "firewall address". But then you will only get back the options from exactly that, like if you would've typed "show firewall address" on the CLI of the device.
I'm currently working on a solution to use Ansible for FortiGate automation, but it's not looking good. E.g. FortiGates additionally do not support Netconf, so you can't use Netconf to send commands to the device.
So therefore, you're not doing anything wrong, but the modules is either not optimized, or I guessed that maybe the full-configuration is too big to be read by the module, so that you have to use the filter option to shrink it.

How to pass multiple executable in ansible within a shell module?

I am trying to pass a prompt y in ansible when it executes command.
When i do manually on server it asks for a prompt.
The issue is for command to run i need to pass the executable /bin/bash
command: source /etc/profile.d/tableau_server.sh && tsm pending-changes apply for expect command to run i need to pass /usr/bin/expect .
My question, how can i pass 2 executable in ansible such that for command it uses /bin/bash and for expect prompt it should use /usr/bin/expect and the error is because i am using source, what is an alternative i can use?
Update: I dont know why but i am not able to pass --ignore-prompt , It gives an error
ubuntu#ip-xx-xxx-xx-xx:~$ tsm pending-changes apply --ignore-prompt
Unrecognized option: --ignore-prompt
Please help me with a solution!
ubuntu#ip-xx-xxx-xx-xx:~$ tsm pending-changes apply
This operation will perform a server restart. Are you sure you wish to continue?
(y/n):
My ansible script:
shell: |
source /etc/profile.d/tableau_server.sh && tsm pending-changes apply
expect "This operation will perform a server restart. Are you sure you wish to continue?\n(y/n):"
send "y\n"
exit 0
args:
executable: /usr/bin/expect
args:
executable: /bin/bash/expect
when: inventory_hostname == "xx.xxx.xx.xx"
ERROR:
changed: [xx.xxx.xxx.xx] => {
"changed": true,
"cmd": "source /etc/profile.d/tableau_server.sh && tsm pending-changes apply\n expect \"This operation will perform a server restart. Are you sure you wish to continue?\\n(y/n):\"\n send \"y\\n\"\n exit 0",
"delta": "0:00:00.034824",
"end": "2018-08-20 17:29:41.457700",
"invocation": {
"module_args": {
"_raw_params": "source /etc/profile.d/tableau_server.sh && tsm pending-changes apply\n expect \"This operation will perform a server restart. Are you sure you wish to continue?\\n(y/n):\"\n send \"y\\n\"\n exit 0",
"_uses_shell": true,
"argv": null,
"chdir": null,
"creates": null,
"executable": "/usr/bin/expect",
"removes": null,
"stdin": null,
"warn": true
}
},
"rc": 0,
"start": "2018-08-20 17:29:41.422876",
"stderr": "wrong # args: should be \"source ?-encoding name? fileName\"\n while executing\n\"source /etc/profile.d/tableau_server.sh && tsm pending-changes apply\"",
"stderr_lines": [
"wrong # args: should be \"source ?-encoding name? fileName\"",
" while executing",
"\"source /etc/profile.d/tableau_server.sh && tsm pending-changes apply\""
],
"stdout": "",
"stdout_lines": []
I would say you are doing far too much with bash commands and '&&' inside command, none of this feels idempotent.
Can I recommend going back to the drawing board with this. I would recommend creating the command using the 'creates' parameter so it can tell if it needs to run.
https://docs.ansible.com/ansible/2.6/modules/command_module.html
Or alternatively check before hand which will then see if the command needs running using register.
In this instance of your issue with the:
tsm pending-changes apply
should support as per https://onlinehelp.tableau.com/current/server-linux/en-us/cli_pending-changes.htm
tsm pending-changes apply --ignore-prompt
which will then not prompt for a yes and will not need the expect module.
I solved my issue by passing an -r option.
- name: Initialize and Start Tableau Server
shell: source /etc/profile.d/tableau_server.sh && tsm pending-changes apply -r -u ubuntu -p '{{ tableau_server_admin_password }}'
args:
executable: /bin/bash
when: inventory_hostname == "xx.xxx.xx.xx"

Go-Sublime-build configuration

Im having issues trying to set up go to run the current file from Sublime text 2.
Here's what I have in my go.sublime-build file
{
"cmd": [ "go", "run", "${file}" ]
}
When I try to run build on a go source file, I get the error
[Error 6] The handle is invalid
[cmd: [u'go run', u'C:\\Users\\gprasant\\Documents\\GitHub\\programming_pearls\\src\\go\\quicksort.go']]
[dir: C:\Users\gprasant\Documents\GitHub\programming_pearls\src\go]
Is there any way to get this fixed ? Or is there another plugin in Sublime text for Go development?
Installing GoSublime should get this working for you. After installing and restarting ST2: do ctrl-B, type "run" and hit enter.
I got by with
{
"cmd": "go run $file",
"shell" : true
}
In ST3: it is changed to be:
{
"shell_cmd": "go run ${file}"
}
On my mac, I needed the following code in:
/Users/your_user_name/Library/Application Support/Sublime Text 2/Packages/User/go.sublime-build
go.sublime-build
{
"cmd": ["go run '${file}'"],
"selector": "source.go",
"path": "/usr/local/go/bin",
"shell": true
}
"cmd" line quoting is to correctly handle file paths with spaces.
"shell" line is needed since commenting it out breaks it.
"path" line is needed because the basic shell, doesn't have access to my .zshrc file include the export GOPATH statement defining the go path.
After that any .go file should build and run with command+B, leaving the stdout message in a console built into sublime text 2.
what about:
{
"cmd": ["go", "run", "${file}"],
"path": "/user/local/go/bin"
}
I like GoSublime, just hate to type run each time when click Command + B
SublimeText 2
build-system for golang, making F4/shift-F4 work (next error/prev error)
1st, create a file: ~/gosublime_build.sh
GOPATH=~/go
export GOPATH
echo "GOPATH:$GOPATH"
if [ "$3." = "RUN." ]
then
EXENAME=${1##*/}
EXENAME=$GOPATH/bin/$EXENAME
echo $EXENAME
$($EXENAME)
echo "code: $?"
exit
fi
echo "go build $2"
cd /usr/local/go/bin
./go build -o ~/temp.go.compiled $2
if [ $? -eq 0 ]
then
cd $1
echo "Project: " $1
/usr/local/go/bin/go install
echo "go install exit code: $?"
else
echo "go build exit code: $?"
fi
2nd:
chmod 777 ~/gosublime_build.sh
3rd: create a new sublime2 build-system for "go" (Tools/Build System/New)
{
"cmd": ["~/gosublime_build.sh $file_path $file"]
,"shell": true
,"selector": "source.go"
,"file_regex": "([\\w/_-]+[.]{1}[\\w./_-]+?):([0-9]+):?([0-9]+)?(.*)?"
}
4th: select your new build-system (Tools/Build System)
5th: build with Ctrl-B, F4/Shift-F4: next/prev error
If anybody knows how to instruct the go compiler to inform FULL PATH of file and line for each error, this process can be simplified

Resources