Puppet - how can I add host entry dynamically reading from linux $hostname - amazon-ec2

I am using puppet for provisioning to AWS cloud. I am a newbie to this.
My requirement is to add entry into /etc/hosts file of amazon ec2 instance. However at the time of writing puppet, I do not know the actual hostname.
How can I use $HOSTNAME variable in .pp file?
Something like this -
host { '$HOSTNAME':
ip => 'echo $HOSTNAME | tr "-" "." | sed 's/ip.//'',
host_aliases => 'mywebsite',
}

Something like this :
host { $fqdn :
ip => $ipaddress,
host_aliases => 'mywebsite',
}
$fqdn provides fully qualified domain name and $ipaddress provides IP address for the machine. These variables are available if you have facter installed in your system. facter is available at the puppetlab repo. You can install it the same way you installed puppet in your system.
As in the comment, you can also use $hostname to get the short-hostname in place of $fqdn.

Since I wanted the hosts file to be updated before startup script's start gets executed, I did this and it worked for me.
Added this in /etc/init.d/
setup_hostname() {
IPADDR=`echo $HOSTNAME | tr "-" "." | sed 's/ip.//'`
echo "${IPADDR} ${HOSTNAME}" >> /etc/hosts
}
Called setup_hostname from start
case "$1" in
start)
clean
setup_hostname
start
;;

Related

How to get the output of execute shell script in lua api

I am newbie in luci and lua api. Now I have problem about remove firewall rule from luci webgui in opnewrt. I know delete the rule is using the uci command : uci delete firewall.#rule[index]
But I don't know the index exectly. So I use blow shell script name index.sh to find the index by key word.
uci show firewall | grep $1 | grep -oE '\[.*?\]' | sed 's/[][]//g' | head -n 1
Here $1 is the mac address.
My process is get the mac address from luci web and remove the firewall rule of block the
network access from the mac address I set before. To recover the network access of the mac address.
But I use the lua api of luci.sys.exec and luci.util.exec to get the output of firewall rule index that are all wrong.
My example code:
1.Get the mac address from luci
local del_mac = protocol.urldecode(luci.http.formvalue("deleteMac"))
2.Execute the the shell script to get the index
local ruleindex = ut.trim(tostring(luci.sys.exec("index.sh '" .. del_mac .."'"))
local uci_delete_rule = "uci delete firewall.#rule['" .. ruleindex .. "]'"
luci.sys.exec(uci_delete_rule)
or
local index = "index.sh %s" %{list_del_mac}
local rule_index = ut.trim(tostring(luci.util.exe(index)))
local uci_delete_rule = "uci delete firewall.#rule['" .. rule_index .. "]'"
luci.sys.exec(uci_delete_rule)
3.Reload the firewall rule
luci.sys.exec("uci commit firewall")
luci.sys.exec("fw3 reload")
Can anyone help me to reslove the problem?
Thank you for your help
This doesn't look right to me: "index.sh %s" %{list_del_mac} Unless it's short for string.format in luci, that's not proper Lua. Concatenate your command string, or actually use string.format
"index.sh " ..list_del_mac
or
string.format( "index.sh %s", list_del_mac )
also, to get the return value after execution, you need to send it to a variable
return_value = luci.sys.exec(uci_delete_rule)
print( return_value )

Ssh not working when host is taken using grep

When I'm hardcoding i. e.
server1=ip-10.237.40.10-aws-n-myhost
ssh - i /home/<passwordfile> akhil#$server1
It is working,but when I'm greping the host from other file its not working
Eg:
server2=$(grep - e host /home/akhil/configuration. File | awk FS, '{print $2} ' )
echo $server2
ssh - i /home/<passwordfile> akhil#$server2
While printing server 2 is fine, but when it is used in ssh I'm getting a error saying : not known host name.
I want to automate the script with a configuration file so that when ever the cluster changes I could simply change the ip address in configfile instead of changing in all my scripts.
I need help in this.
Thanks

Shell / Korn script - set variable depending on hostname in list

I need to write a korn script that depending on the host the script is running on, will set a deployment directory (so say 5 hosts deploy the software to directory one and five other hosts deploy to directory two).
How could I do this - I wanted to avoid an if condition for every host like below
IF [hostname = host1] then $INSTALL_DIR=Dir1
ELSE IF [hostname = host2] then $INSTALL_DIR=Dir1
and would prefer to have a list of say Directory1Hosts and Directory2Hosts which contains all the hosts valid for each directory, and then I would just check if the host the script is running on is in my Directory1Hosts or Directory2Hosts (so only two IF conditions instead of 10).
Thanks for your help - have been struggling to find how to do effectively a contains clause.
Use a case statement:
case $hostname in
host1) INSTALL_DIR=DIR1 ;;
host2) INSTALL_DIR=DIR2 ;;
esac
or use an associative array
install_dirs=([host1]=DIR1 [host2]=DIR2)
...
INSTALL_DIR=${install_dirs[$hostname]}
When you want to have configuration and code apart, you can make a config directory: one file with hosts for each install dir.
# cat installdirs/Dir1
host1
host2
With these files your code can be
INSTALL_DIR=$(grep -Flx "${hostname}" installdirs/* | cut -d"/" -f2)

Is there any option to list groups in Ansible?

As far as i know, ansible has an option named --list-hosts for listing hosts. Is there any option for listing host groups? Or any other way to come through?
You can simply inspect the groups variable using the debug module:
ansible localhost -m debug -a 'var=groups.keys()'
The above is using groups.keys() to get just the list of groups. You could drop the .keys() part to see group membership as well:
ansible localhost -m debug -a 'var=groups'
Listing groups
Using tools built-in to Ansible + jq, this gives you something reasonably close:
ansible-inventory --list | jq "keys"
An advantage of this approach vs manually parsing inventory files is that it fully utilizes your ansible.cfg files (which can point to one or multiple inventory files, a directory of inventory files, etc...).
Example output on my machine (local_redis_all is a locally defined Ansible group):
[
"_meta",
"all",
"local_redis_all",
]
If you prefer it in plain-text form, use an approach like ansible-inventory --list | jq -r "keys | .[]". It will give you an output like this:
_meta
all
local_redis_all
Listing hosts
This was not part of the original question, but including it here anyway since it might be useful to some of my readers. Use the following command for JSON output (note: the command actually outputs a JSON array for each group, I haven't yet figured out a way to flatten these with jq - suggestions are welcome):
ansible-inventory --list | jq ".[].hosts | map(.)?
This gives you an output similar to this:
[
"redis-01",
"redis-02",
"redis-03"
]
Likewise, in raw text format (one host per line): ansible-inventory --list | jq -r ".[].hosts | .[]?"
This gives you an output like this:
redis-01
redis-02
redis-03
Note:- For New Ansible Users
Ansible has some special internal variables which are also known as Magic Variables.
From this link you will get full list of magic variables Magic Variables
There is magic variable called "groups" which hold the inventory group information.
we can access the value of any variable ( both user defined and Internal ) using an ansible module called debug .
I am Using Separate Inventory File
$
$ ansible -i inventory.ini all -m debug -a "var=groups"
$
centos-client.ansible.lab | SUCCESS => {
"groups": {
"all": [
"centos-client.ansible.lab",
"ubuntu-client.ansible.lab"
],
"centos": [
"centos-client.ansible.lab"
],
"ubuntu": [
"ubuntu-client.ansible.lab"
],
"ungrouped": []
}
}
ubuntu-client.ansible.lab | SUCCESS => {
"groups": {
"all": [
"centos-client.ansible.lab",
"ubuntu-client.ansible.lab"
],
"centos": [
"centos-client.ansible.lab"
],
"ubuntu": [
"ubuntu-client.ansible.lab"
],
"ungrouped": []
}
}
Method #1 - Using Ansible
If you just want a list of the groups within a given inventory file you can use the magic variables as mentioned in a couple of the other answers.
In this case you can use the groups magic variable and specifically just show the keys() in this hash (keys + values). The keys are all the names of the groups.
NOTE: By targeting the localhost we force this command to just run against a single host when processing the inventory file.
$ ansible -i inventory/rhvh localhost -m debug -a 'var=groups.keys()'
localhost | SUCCESS => {
"groups.keys()": "dict_keys(['all', 'ungrouped', 'dc1-rhvh', 'dc2-rhvh', 'dc3-rhvh', 'dc4-rhvh', 'dc5-rhvh', 'rhvh', 'dc1', 'dc2', 'dc3', 'dc4', 'dc5', 'production'])"
}
Method #2 - using grep & sed
You could of course just grep the contents of your inventory file too:
$ grep -E '^\[' inventory/rhvh
[dc1-rhvh]
[dc2-rhvh]
[dc3-rhvh]
[dc4-rhvh]
[dc5-rhvh]
[rhvh:children]
[dc1:children]
[dc2:children]
[dc3:children]
[dc4:children]
[dc5:children]
[production:children]
You're on the hook though for teasing out of the 2nd method's output or you can use sed to do it:
$ grep -E '^\[' inventory/rhvh | sed 's/:children//'
[dc1-rhvh]
[dc2-rhvh]
[dc3-rhvh]
[dc4-rhvh]
[dc5-rhvh]
[rhvh]
[dc1]
[dc2]
[dc3]
[dc4]
[dc5]
If you're not sure if the host will actually be in the inventory you can use:
ansible -i hosts/ localhost -m debug -a 'var=groups'
-i where your inventory files are kept
-m enable module debug.
-a module arguments.
It will output the group / hosts just once and not for every host in your inventory.
Same goes for just getting the list of groups in the inventory:
ansible -i hosts/ localhost -m debug -a 'var=groups.keys()'
another way to see your hosts is just to press tab after the ansible keyword.
Something like that?
cat ~/inventory/* | grep "\[.*\]"

Output the file in way we wanted

I have ssh config file which contains so many servers from google,aws and some remote servers.I wanted to have a bash function that will output only the Host and the HostName of the server so I dont have to remember there public DNS to check my webapps.
Sample Server Config in my ssh config looks like this
Host aws_server
User rand
HostName 65.2.25.152
Port 8000
IdentityFile PEM PATH
ServerAliveInterval 120
ServerAliveCountMax 30
I want the output like
aws_server 65.2.25.152
for all the servers
Using sed
sed '/^Host/{s/[^ ]* //;:1;N;s/\n.*HostName */\t/;t2;b1;:2;p};d' file
aws_server 65.2.25.152
Modified version that's more robust for multiple hosts,missing HostNames
sed ':1;s/\(.*\n\|^\)Host *//;N;s/\n.*HostName */\t/;t2;$!{b1;:2;p};d' file
using awk
awk '{if($1=="Host")k=$2;if($1=="HostName")printf("%s\t%s\n",k,$2)}' file
I would use awk for this:
awk '
# Save the host when we see it.
/^Host/ {
host=$2
next
}
# If we have a host and are on a HostName line
host && $1 == "HostName" {
# Print the Host and HostName values
printf "%s"OFS"%s\n", host, $2
host=""
next
}
# If we have a HostName without a Host clear the host (should not happen but just to be safe)
$1 == "HostName" {
host=""
}
' .ssh/config

Resources