Ajimi
Ajimi is a tool to compare servers by their files to shows difference in their configurations. It is useful to achieve some kind of a regression test against a server by finding unexpected changes to its configuration file after running Chef, Ansible, or your own provisioning tool.
'Ajimi' means 'tasting' in Japanese. It was developed for originally replacing the existing server with the Chef's cookbook, but can be used for a general purpose of comparing two servers.
Installation
Add this line to your application's Gemfile:
gem 'ajimi'
And then execute:
$ bundle
Or install it yourself as:
$ gem install ajimi
Configuration
Generate a sample configuration file to current directory:
$ ajimi-init
And then edit Ajimifile:
$ (Your favorite editor) ./Ajimifile
A sample configuration looks like the following:
# Ajimi configuration file
# source setting
source "source.example.com", {
ssh_options: {
host: "192.168.0.1",
user: "ec2-user",
key: "~/.ssh/id_rsa"
},
enable_nice: true
}
# target setting
target "target.example.com", {
ssh_options: {
user: "ec2-user",
key: "~/.ssh/id_rsa"
},
enable_nice: false
}
# check setting
check_root_path "/"
pruned_paths [
"/dev",
"/proc",
]
ignored_paths [
*@config[:pruned_paths],
%r|^/lost\+found/?.*|,
%r|^/media/?.*|,
%r|^/mnt/?.*|,
%r|^/run/?.*|,
%r|^/sys/?.*|,
%r|^/tmp/?.*|
]
ignored_contents ({
"/root/.ssh/authorized_keys" => /Please login as the user \\"ec2-user\\" rather than the user \\"root\\"/
})
pending_paths [
"/etc/sudoers"
]
pending_contents ({
"/etc/hosts" => /127\.0\.0\.1/
})
The following arguments are supported in the Ajimifile:
source
- String (Required), Hash (Required): Source server's name and options. Options are as follows.ssh_options
- Hash (Required): SSH connection optionshost
- String (Optional): SSH hostname, FQDN or IP address. Default is name ofsource
.user
- String (Required): SSH username.key
- String (Required): Path to user's SSH secret key.
enable_nice
- Boolean (Optional): If true, the find process is wrapped by nice and ionice to lower load. Default is false.
target
- String (Required): Target server's name and options. Options are the same as source.check_root_path
- String (Required): Root path to check. If "/", Ajimi checks in the whole filesystem.pruned_paths
- Array[String|Regexp] (Optional): List of the path which should be excluded in the find process. Note thatpruned_paths
is better performance thanignored_paths
/pending_paths
.ignored_paths
- Array[String|Regexp] (Optional): List of the path which should be ignored as known difference.ignored_contents
- Hash=> String|Regexp (Optional): Hash of the path => pattern which should be ignored as known difference for each of the content.pending_paths
- Array[String|Regexp] (Optional): List of the path which should be resolved later but ignored temporarily as known difference.pending_contents
- Hash=> String|Regexp (Optional): Hash of the path => pattern which should be resolved later but ignored temporarily as known difference for each of the content.
Usage
Ajimi is a single command-line application: ajimi
.
It takes a subcommand such as dir
or exec
(Default subcommnad is check
).
To view a list of the available commands , just run ajimi help
with no arguments:
$ ajimi help
Commands:
ajimi [check] # (Default subcommand) Show differences between the source and the target server
ajimi dir <path> # Show differences between the source and the target server in the specified directory
ajimi exec source|target <command> # Execute an arbitrary command on the source or the target server
ajimi file <path> # Show differences between the source and the target server in the specified file
ajimi help [COMMAND] # Describe available commands or one specific command
Options:
[--ajimifile=AJIMIFILE] # Ajimifile path
# Default: ./Ajimifile
[--verbose], [--no-verbose]
# Default: true
After setting your Ajimifle, Run the following command in order to verify the SSH connection:
$ ajimi exec source hostname
$ ajimi exec target hostname
And then, run ajimi
command with -d
(or --find-max-depth
) option:
$ ajimi -d 3 > ajimi.log
Check the diffs report in ajimi.log, and add roughly unnecessary paths to pruned_paths
in Ajimifile.
Next, gradually increasing the depth 4, 5, ...
,
$ ajimi -d 4 > ajimi.log
Add known differences to ignored_paths
or pending_paths
.
After checking the difference of paths, then run ajimi
command with -c
(or --enable-check-contents
) option to check the contents of files where the difference has been reported:
$ ajimi -c > ajimi.log
Add known differences to ignored_contents
or pending_contents
,
and repeat until the number of lines of diffs report becomes human-readable.
Finally, resolve issues and remove pending_paths
or pending_contents
.
Command reference
$ ajimi help
Commands:
ajimi [check] # (Default subcommand) Show differences between the source and the target server
ajimi dir <path> # Show differences between the source and the target server in the specified directory
ajimi exec source|target <command> # Execute an arbitrary command on the source or the target server
ajimi file <path> # Show differences between the source and the target server in the specified file
ajimi help [COMMAND] # Describe available commands or one specific command
Options:
[--ajimifile=AJIMIFILE] # Ajimifile path
# Default: ./Ajimifile
[--verbose], [--no-verbose]
# Default: true
$ ajimi help check
Usage:
ajimi [check]
Options:
-r, [--check-root-path=CHECK_ROOT_PATH]
-d, [--find-max-depth=N]
-c, [--enable-check-contents], [--no-enable-check-contents]
[--limit-check-contents=N]
# Default: 0
[--ajimifile=AJIMIFILE] # Ajimifile path
# Default: ./Ajimifile
[--verbose], [--no-verbose]
# Default: true
(Default subcommand) Show differences between the source and the target server
$ ajimi help dir
Usage:
ajimi dir <path>
Options:
-d, [--find-max-depth=N]
# Default: 1
[--ignored-pattern=IGNORED_PATTERN]
[--ajimifile=AJIMIFILE] # Ajimifile path
# Default: ./Ajimifile
[--verbose], [--no-verbose]
# Default: true
Show differences between the source and the target server in the specified directory
$ ajimi help file
Usage:
ajimi file <path>
Options:
[--ignored-pattern=IGNORED_PATTERN]
[--ajimifile=AJIMIFILE] # Ajimifile path
# Default: ./Ajimifile
[--verbose], [--no-verbose]
# Default: true
Show differences between the source and the target server in the specified file
$ ajimi help exec
Usage:
ajimi exec source|target <command>
Options:
[--ajimifile=AJIMIFILE] # Ajimifile path
# Default: ./Ajimifile
[--verbose], [--no-verbose]
# Default: true
Execute an arbitrary command on the source or the target server
Development and Test
$ bundle install
$ bundle exec ajimi-init
(Implement some feature)
$ bundle exec rake spec
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request
License
The gem is available as open source under the terms of the MIT License.