```Ansibledoes not have a
rpm`` module.
That's right, because there is yum
.
Since it is a configuration management tool, rpm
that can be called --force
is deprecated in `ʻAnsible``.
However, there are some sites that have been developing past systems by splicing them together, and there are times when you really want to put a 32-bit rpm
in a 64-bit machine. When I implement this with yum
, it says "I will not put it in because there is a 64-bit package".
The ideal form is development with configuration management in mind, This is a deprecated module. </ font>
I'm not going to do it so difficult
--The rpm
file has already been placed on the node with copy
etc.
--I want to be able to place files with a built-in equivalent to copy
someday.
--Receive the option of the rpm
command and use it as it is
――I want to manage the flag someday
--Confirm that the specified rpm
file exists
--Confirm that the specified rpm
is not installed
--Install the specified rpm
together with the specified options
Is it about this?
See past articles.
-Ansible self-made module creation-Part 1: Life you want to receive arguments-
rpm.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
from ansible.module_utils.basic import AnsibleModule
#Main processing
#-----------------------------------------------------------
def main():
#AnsibleModule class:Create module
module = AnsibleModule(
#Argument reception
argument_spec=dict(
#Write the argument receiving process here
),
#Argument check enabled
supports_check_mode=True
)
#Check for the existence of the specified file
#Judgment of necessity of change
changed = False
#rpm installation
#End processing
if __name__ == '__main__':
main()
I wonder if this is the place
The arguments accepted this time are as follows
Argument name | Mandatory | Default value | Argument meaning |
---|---|---|---|
pkgs | ○ | - | List of packages |
opts | -Uvh | Options given to the rpm command | |
chdir | / | Package storage directory |
By the way, I didn't know how to receive the `` list'', so I posted it to a certain Q & A, but the next day I solved it myself. Reference: To use the array passed in Ansible with_list for a loop in a module
rpm.py
:#(abridgement)
#Argument reception
argument_spec=dict(
#Package list(Mandatory,list type)
pkgs = dict(required = True, type = list),
#option(str type,[-Uvh])
opts = dict(required = False, type = str, default = '-Uvh'),
#Package storage directory(str type)
chdir = dict(required = False, type = str, default = '/'),
),
#Argument check enabled
supports_check_mode=True
:#(abridgement)
In addition, indentation at the beginning of the line is deleted when excerpting partially as described above. Because it will be long sideways.
Last time, when I created a module to mkfifo
, I used the stat
command and the test
command without thinking about anything, but I thought that there would be so many modules.
Reference: Check the existence of the file with python
rpm.py
:#(abridgement)
from ansible.module_utils.basic import AnsibleModule
import os
:#(abridgement)
#Since it becomes redundant, re-enter variables
pkgs = module.params['pkgs']
chdir = module.params['chdir']
#Loop for each package list
for pkg in pkgs:
#Check for the existence of the specified file
if (os.path.isfile(chdir + '/' + pkg)):
#File is not placed
module.fail_json(msg = chdir + '/' + pkg + ' is not found.')
:#(abridgement)
I'm worried, so let's check the operation here. I haven't placed rpm
in / tmp /
yet.
test.yml
- name: ntp install
rpm:
pkgs: '{{ item }}'
opts: '-ivh'
chdir: '/tmp'
with_list:
- [ 'ntp-4.2.6p5-15.el6.centos.x86_64.rpm','ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm' ]
Operation check
$ ansible-playbook -i test_grp -l test_srv -u root test.yml -vvv
:#(abridgement)
ok: [192.168.56.104] => (item=[u'ntp-4.2.6p5-15.el6.centos.x86_64.rpm', u'ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm']) => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"ansible_loop_var": "item",
"changed": false,
"invocation": {
"module_args": {
"chdir": "/tmp",
"opts": "-ivh",
"pkgs": [
"ntp-4.2.6p5-15.el6.centos.x86_64.rpm",
"ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm"
]
}
},
"item": [
"ntp-4.2.6p5-15.el6.centos.x86_64.rpm",
"ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm"
]
}
That ... a little debug.
rpm.py
#Since it becomes redundant, re-enter variables
pkgs = module.params['pkgs']
chdir = module.params['chdir']
num = 0
hog = 0
#Loop for each package list
for pkg in pkgs:
num += 1
#Check for the existence of the specified file
if (os.path.isfile(chdir + '/' + pkg)):
hog += 1
#File is not placed
module.fail_json(msg = chdir + '/' + pkg + ' is not found.')
:#(abridgement)
module.exit_json(num = num, hog = hog)
Execution result
ok: [192.168.56.104] => (item=[u'ntp-4.2.6p5-15.el6.centos.x86_64.rpm', u'ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm']) => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"ansible_loop_var": "item",
"changed": false,
"hog": 0, ★
"invocation": {
"module_args": {
"chdir": "/tmp",
"opts": "-ivh",
"pkgs": [
"ntp-4.2.6p5-15.el6.centos.x86_64.rpm",
"ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm"
]
}
},
"item": [
"ntp-4.2.6p5-15.el6.centos.x86_64.rpm",
"ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm"
],
"num": 2 ★
}
Hmmm ʻif (os.path.isfile (chdir +'/' + pkg)): I wonder if `` is wrong. As a result of various trials, it worked as
ʻif os.path.isfile (chdir +'/' + pkg) == False: ``. Hmm, why?
rpm.py
:#(abridgement)
from ansible.module_utils.basic import AnsibleModule
import os
:#(abridgement)
#Since it becomes redundant, re-enter variables
pkgs = module.params['pkgs']
chdir = module.params['chdir']
#Loop for each package list
for pkg in pkgs:
#Check for the existence of the specified file
if os.path.isfile(chdir + '/' + pkg) == False:
#File is not placed
module.fail_json(msg = chdir + '/' + pkg + ' is not found.')
:#(abridgement)
You don't need to change it, that is, if you already have all the pkg
installed. You can tell if the rpm
package is installed with the following command.
$ rpm -q ntp-4.2.6p5-15.el6.centos.x86_64
ntp-4.2.6p5-15.el6.centos.x86_64
$ echo $?
0
$ rpm -q hoge
Package hoge is not installed.
$ echo $?
1
However, the rpm
file is not always the package name without the .rpm
at the end of the file name.
$ ls -1 jdk-8u192-linux-x64.rpm
jdk-8u192-linux-x64.rpm
$ rpm -q jdk-8u192-linux-x64
Package jdk-8u192-linux-x64 is not installed.
$ rpm -qa | grep jdk
jdk1.8-1.8.0_192-fcs.x86_64
In the above example, the file name is jdk-8u192-linux-x64.rpm
, but the package name is jdk1.8-1.8.0_192-fcs.x86_64
.
To determine this, you need to look up the package name with rpm -qp rpm filename
.
$ rpm -qp jdk-8u192-linux-x64.rpm
warning: jdk-8u192-linux-x64.rpm:Header V3 RSA/SHA256 Signature, key ID ec551f03: NOKEY
jdk1.8-1.8.0_192-fcs.x86_64
The package name is obtained from the above standard output.
Incorporate this process into the module
rpm.py
:#(abridgement)
#Since it becomes redundant, re-enter variables
pkgs = module.params['pkgs']
chdir = module.params['chdir']
#Judgment of necessity of change
changed = False
#List of rpm files to be installed
rpms = []
#Loop for each package list
for pkg in pkgs:
#Create full path of file
fpath = chdir + '/' + pkg
#Check for the existence of the specified file
if os.path.exists(fpath) == False:
#File is not placed
module.fail_json(msg = fpath + ' is not found.')
#Get the package name from the rpm file
rc, pkg_name, stderr = module.run_command('rpm -qp ' + fpath)
#Check the installation status of the package
rc, stdout, stderr = module.run_command('rpm -q ' + pkg_name)
#Is it installed
if rc != 0:
#Not installed, so change required
changed = True
#Add to installation target
rpms.append(fpath)
:#(abridgement)
If the rpm list rpms
to be installed is empty, it will end ... It will be left to chagned! = True
.
rpm.py
:#(abridgement)
#Judgment of necessity of rpm installation
if changed != True:
#Not to be installed
module.exit_json()
#rpm list creation
rpm_line = ' '.join(rpms)
#rpm installation
rc, stdout, stderr = module.run_command('rpm ' + module.params['opts'] + ' ' + rpm_line)
#rpm installation result judgment
if rc != 0:
#Installation failure
module.fail_json(stdout = stdout, stderr = stderr)
#End processing
module.exit_json(changed = changed)
:#(abridgement)
test.yml
- name: ntp install
rpm:
pkgs: '{{ item }}'
opts: '-ivh'
chdir: '/tmp'
with_list:
- [ 'ntp-4.2.6p5-15.el6.centos.x86_64.rpm','ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm' ]
#Make sure the package file is in place
$ ssh [email protected] "ls -l /tmp/*rpm"
-rw-rw-r--.1 root root 614364 May 11 17:01 2020 /tmp/ntp-4.2.6p5-15.el6.centos.x86_64.rpm
-rw-rw-r--.1 root root 80836 May 11 17:00 2020 /tmp/ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm
#Make sure the package file is not installed
$ ssh [email protected] "rpm -qa | grep ntp"
$
#Run!
$ ansible-playbook -i test_grp -l test_srv -u root test.yml -vvv
:#(abridgement)
changed: [192.168.56.104] => (item=[u'ntp-4.2.6p5-15.el6.centos.x86_64.rpm', u'ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm']) => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"ansible_loop_var": "item",
"changed": true,
"invocation": {
"module_args": {
"chdir": "/tmp",
"opts": "-ivh",
"pkgs": [
"ntp-4.2.6p5-15.el6.centos.x86_64.rpm",
"ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm"
]
}
},
"item": [
"ntp-4.2.6p5-15.el6.centos.x86_64.rpm",
"ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm"
],
"msg": "/tmp/ntp-4.2.6p5-15.el6.centos.x86_64.rpm /tmp/ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm"
}
#Run again to check idempotence!
$ ansible-playbook -i test_grp -l test_srv -u root test.yml -vvv
ok: [192.168.56.104] => (item=[u'ntp-4.2.6p5-15.el6.centos.x86_64.rpm', u'ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm']) => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"ansible_loop_var": "item",
"changed": false,
"invocation": {
"module_args": {
"chdir": "/tmp",
"opts": "-ivh",
"pkgs": [
"ntp-4.2.6p5-15.el6.centos.x86_64.rpm",
"ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm"
]
}
},
"item": [
"ntp-4.2.6p5-15.el6.centos.x86_64.rpm",
"ntpdate-4.2.6p5-15.el6.centos.x86_64.rpm"
]
}
Isn't it okay?
rpm.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
from ansible.module_utils.basic import AnsibleModule
import os
#Main processing
#-----------------------------------------------------------
def main():
#AnsibleModule class:Create module
module = AnsibleModule(
#Argument reception
argument_spec=dict(
#Package list(Mandatory,list type)
pkgs = dict(required = True, type = list),
#option(str type,[-Uvh])
opts = dict(required = False, type = str, default = '-Uvh'),
#Package storage directory(str type)
chdir = dict(required = False, type = str, default = '/'),
),
#Argument check enabled
supports_check_mode=True
)
#Since it becomes redundant, re-enter variables
pkgs = module.params['pkgs']
chdir = module.params['chdir']
#Judgment of necessity of change
changed = False
#List of rpm files to be installed
rpms = []
#Loop for each package list
for pkg in pkgs:
#Create full path of file
fpath = chdir + '/' + pkg
#Check for the existence of the specified file
if os.path.exists(fpath) == False:
#File is not placed
module.fail_json(msg = fpath + ' is not found.')
#Get the package name from the rpm file
rc, pkg_name, stderr = module.run_command('rpm -qp ' + fpath)
#Check the installation status of the package
rc, stdout, stderr = module.run_command('rpm -q ' + pkg_name)
#Is it installed
if rc != 0:
#Not installed, so change required
changed = True
#Add to installation target
rpms.append(fpath)
#Judgment of necessity of rpm installation
if changed != True:
#Not to be installed
module.exit_json()
#rpm list creation
rpm_line = ' '.join(rpms)
#rpm installation
rc, stdout, stderr = module.run_command('rpm ' + module.params['opts'] + ' ' + rpm_line)
#rpm installation result judgment
if rc != 0:
#Installation failure
module.fail_json(stdout = stdout, stderr = stderr)
#End processing
module.exit_json(changed = changed)
if __name__ == '__main__':
main()