Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/ryotarai/infrataster
Infrastructure Behavior Testing Framework
https://github.com/ryotarai/infrataster
infrastructure rspec ruby
Last synced: 5 days ago
JSON representation
Infrastructure Behavior Testing Framework
- Host: GitHub
- URL: https://github.com/ryotarai/infrataster
- Owner: ryotarai
- License: mit
- Created: 2014-04-09T14:11:01.000Z (over 10 years ago)
- Default Branch: master
- Last Pushed: 2018-05-11T15:50:30.000Z (over 6 years ago)
- Last Synced: 2024-12-16T03:03:25.807Z (12 days ago)
- Topics: infrastructure, rspec, ruby
- Language: Ruby
- Homepage: http://infrataster.net
- Size: 269 KB
- Stars: 311
- Watchers: 35
- Forks: 36
- Open Issues: 17
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
Awesome Lists containing this project
README
# Infrataster
[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/ryotarai/infrataster?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)[![Gem Version](https://badge.fury.io/rb/infrataster.png)](http://badge.fury.io/rb/infrataster)
[![Code Climate](https://codeclimate.com/github/ryotarai/infrataster.png)](https://codeclimate.com/github/ryotarai/infrataster)Infrastructure Behavior Testing Framework.
## Basic Usage with Vagrant
First, create `Gemfile`:
```ruby
source 'https://rubygems.org'gem 'infrataster'
```Install gems:
```
$ bundle install
```Install Vagrant: [Official Docs](http://docs.vagrantup.com/v2/installation/index.html)
Create Vagrantfile:
```ruby
# Vagrantfile
Vagrant.configure("2") do |config|
config.vm.box = "hashicorp/precise64"config.vm.define :proxy do |c|
c.vm.network "private_network", ip: "192.168.33.10"
c.vm.network "private_network", ip: "172.16.33.10", virtualbox__intnet: "infrataster-example"
endconfig.vm.define :app do |c|
c.vm.network "private_network", ip: "172.16.33.11", virtualbox__intnet: "infrataster-example"
end
end
```Start VMs:
```
$ vagrant up
```Initialize rspec directory:
```
$ rspec --init
create spec/spec_helper.rb
create .rspec
````require 'infrataster/rspec'` and define target servers for testing in `spec/spec_helper.rb`:
```ruby
# spec/spec_helper.rb
require 'infrataster/rspec'Infrataster::Server.define(
:proxy, # name
'192.168.0.0/16', # ip address
vagrant: true # for vagrant VM
)
Infrataster::Server.define(
:app, # name
'172.16.0.0/16', # ip address
vagrant: true, # for vagrant VM
from: :proxy # access to this machine via SSH port forwarding from proxy
)# Code generated by `rspec --init` is following...
```
Or```ruby
# spec/spec_helper.rb
require 'infrataster/rspec'Infrataster::Server.define(:proxy) do |server|
server.address = '192.168.0.0/16'
server.vagrant = true
end
Infrataster::Server.define(:app) do |server|
server.address = '172.16.0.0/16'
server.vagrant = true
server.from = :proxy
end# Code generated by `rspec --init` is following...
```Then, you can write spec files:
```ruby
# spec/example_spec.rb
require 'spec_helper'describe server(:app) do
describe http('http://app') do
it "responds content including 'Hello Sinatra'" do
expect(response.body).to include('Hello Sinatra')
end
it "responds as 'text/html'" do
expect(response.headers['content-type']).to eq("text/html")
end
end
end
```Run tests:
```
$ bundle exec rspec
2 examples, 2 failures
```Currently, the tests failed because the VM doesn't respond to HTTP request.
It's time to write provisioning instruction like Chef's cookbooks or Puppet's manifests!
## Server
"Server" is a server you tests. This supports Vagrant, which is very useful to run servers for testing. Of course, you can test real servers.
You should define servers in `spec_helper.rb` like the following:
```ruby
Infrataster::Server.define(
# Name of the server, this will be used in the spec files.
:proxy,
# IP address of the server
'192.168.0.0/16',
# If the server is provided by vagrant and this option is true,
# SSH configuration to connect to this server is got from `vagrant ssh-config` command automatically.
vagrant: true,
)Infrataster::Server.define(
# Name of the server, this will be used in the spec files.
:app,
# IP address of the server
'172.16.0.0/16',
# If the server is provided by vagrant and this option is true,
# SSH configuration to connect to this server is got from `vagrant ssh-config` command automatically.
vagrant: true,
# Which gateway is used to connect to this server by SSH port forwarding?
from: :proxy,
# options for resources
mysql: {user: 'app', password: 'app'},
)
```You can specify SSH configuration manually too:
```ruby
Infrataster::Server.define(
# ...
ssh: {host_name: 'hostname', user: 'testuser', keys: ['/path/to/id_rsa']}
)
```### fuzzy IP address
Infrataster has "fuzzy IP address" feature. You can pass IP address which has netmask (= CIDR) to `Infrataster::Server#define`. This needs `vagrant` option or `ssh` option which has `host_name` because this fetches all IP address via SSH and find the matching one.
```ruby
Infrataster::Server.define(
:app,
# find IP address matching 172.16.0.0 ~ 172.16.255.255
'172.16.0.0/16',
)
```Of course, you can set fully-specified IP address too.
```ruby
Infrataster::Server.define(
:app,
'172.16.11.22',
# or
'172.16.11.22/32',
)
```### #ssh_exec
You can execute a command on the server like the following:
```ruby
describe server(:proxy) do
let(:time) { Time.now }
before do
current_server.ssh_exec "echo 'Hello' > /tmp/test-#{time.to_i}"
end
it "executes a command on the current server" do
result = current_server.ssh_exec("cat /tmp/test-#{time.to_i}")
expect(result.chomp).to eq('Hello')
end
end
```This is useful to test cases which depends on the status of the server.
## Resources
"Resource" is what you test by Infrataster. For instance, the following code describes `http` resource.
```ruby
describe server(:app) do
describe http('http://example.com') do
it "responds content including 'Hello Sinatra'" do
expect(response.body).to include('Hello Sinatra')
end
end
end
```### `http` resource
`http` resource tests HTTP response when sending HTTP request.
It accepts `method`, `params` and `header` as options.```ruby
describe server(:app) do
describe http(
'http://app.example.com',
method: :post,
params: {'foo' => 'bar'},
headers: {'USER' => 'VALUE'}
) do
it "responds with content including 'app'" do
expect(response.body).to include('app')# `response` is a instance of `Faraday::Response`
# See: https://github.com/lostisland/faraday/blob/master/lib/faraday/response.rb
end
end# Gzip support
describe http('http://app.example.com/gzipped') do
it "responds with content deflated by gzip" do
expect(response.headers['content-encoding']).to eq('gzip')
end
enddescribe http('http://app.example.com/gzipped', inflate_gzip: true) do
it "responds with content inflated automatically" do
expect(response.headers['content-encoding']).to be_nil
expect(response.body).to eq('plain text')
end
end# Redirects
describe http('http://app.example.com/redirect', follow_redirects: true) do
it "follows redirects" do
expect(response.status).to eq(200)
end
end# Custom Faraday middleware
describe http('http://app.example.com', faraday_middlewares: [
YourMiddleware,
[YourMiddleware, options]
]) do
it "uses the middlewares" do
expect(response.status).to eq(200)
end
end
end
```### `capybara` resource
`capybara` resource tests your web application by simulating real user's interaction.
```ruby
describe server(:app) do
describe capybara('http://app.example.com') do
it 'shows food list' do
visit '/'
click_link 'Foods'
expect(page).to have_content 'Yummy Soup'
end
end
end
```### `mysql_query` resource
`mysql_query` resource is now in [infrataster-plugin-mysql](https://github.com/ryotarai/infrataster-plugin-mysql).
### `pgsql_query` resource
`pgsql_query` resource sends a query to PostgreSQL server.
`pgsql_query` is provided by [infrataster-plugin-pgsql](https://github.com/SnehaM/infrataster-plugin-pgsql) by [@SnehaM](https://github.com/SnehaM).
### `dns` resource
`dns` resource sends a query to DNS server.
`dns` is provided by [infrataster-plugin-dns](https://github.com/otahi/infrataster-plugin-dns) by [@otahi](https://github.com/otahi).
### `memcached` resource
`memcached` resource sends a query to memcached server.
`memcached` is provided by [infrataster-plugin-memecached](https://github.com/rahulkhengare/infrataster-plugin-memcached) by [@rahulkhengare](https://github.com/rahulkhengare).
### `redis` resource
`redis` resource sends a query to redis server.
`redis` is provided by [infrataster-plugin-redis](https://github.com/rahulkhengare/infrataster-plugin-redis) by [@rahulkhengare](https://github.com/rahulkhengare).
### `firewall` resource
`firewall` resource tests your firewalls.
`firewall` is provided by [infrataster-plugin-firewall](https://github.com/otahi/infrataster-plugin-firewall) by [@otahi](https://github.com/otahi).
## Example
* [example](example)
* [spec/integration](spec/integration)## Tests
### Unit Tests
Unit tests are under `spec/unit` directory.
```
$ bundle exec rake spec:unit
```### Integration Tests
Integration tests are under `spec/integration` directory.
```
$ bundle exec rake spec:integration:prepare
$ bundle exec rake spec:integration
```## Presentations and Articles
* https://speakerdeck.com/ryotarai/introducing-infrataster
* https://speakerdeck.com/ryotarai/infrataster-infra-behavior-testing-framework-number-oedo04
* [Infratasterでリバースプロキシのテストをする](http://techlife.cookpad.com/entry/2014/11/19/151557)
* Google-Translated: [Testing reverse proxy with Infrataster](https://translate.google.com/translate?hl=ja&sl=ja&tl=en&u=http%3A%2F%2Ftechlife.cookpad.com%2Fentry%2F2014%2F11%2F19%2F151557)## Changelog
[Changelog](CHANGELOG.md)
## Contributing
1. Fork it ( http://github.com/ryotarai/infrataster/fork )
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request