{"id":13905482,"url":"https://github.com/ryotarai/infrataster","last_synced_at":"2025-05-16T17:07:42.064Z","repository":{"id":15859293,"uuid":"18599666","full_name":"ryotarai/infrataster","owner":"ryotarai","description":"Infrastructure Behavior Testing Framework","archived":false,"fork":false,"pushed_at":"2018-05-11T15:50:30.000Z","size":275,"stargazers_count":310,"open_issues_count":17,"forks_count":33,"subscribers_count":34,"default_branch":"master","last_synced_at":"2025-05-15T08:24:11.959Z","etag":null,"topics":["infrastructure","rspec","ruby"],"latest_commit_sha":null,"homepage":"http://infrataster.net","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ryotarai.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-04-09T14:11:01.000Z","updated_at":"2025-05-02T00:47:27.000Z","dependencies_parsed_at":"2022-09-07T15:50:27.576Z","dependency_job_id":null,"html_url":"https://github.com/ryotarai/infrataster","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryotarai%2Finfrataster","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryotarai%2Finfrataster/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryotarai%2Finfrataster/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ryotarai%2Finfrataster/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ryotarai","download_url":"https://codeload.github.com/ryotarai/infrataster/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254573588,"owners_count":22093731,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["infrastructure","rspec","ruby"],"created_at":"2024-08-06T23:01:16.722Z","updated_at":"2025-05-16T17:07:42.037Z","avatar_url":"https://github.com/ryotarai.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"# Infrataster\n[![Gitter](https://badges.gitter.im/Join Chat.svg)](https://gitter.im/ryotarai/infrataster?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n\n[![Gem Version](https://badge.fury.io/rb/infrataster.png)](http://badge.fury.io/rb/infrataster)\n[![Code Climate](https://codeclimate.com/github/ryotarai/infrataster.png)](https://codeclimate.com/github/ryotarai/infrataster)\n\nInfrastructure Behavior Testing Framework.\n\n\n## Basic Usage with Vagrant\n\nFirst, create `Gemfile`:\n\n```ruby\nsource 'https://rubygems.org'\n\ngem 'infrataster'\n```\n\nInstall gems:\n\n```\n$ bundle install\n```\n\nInstall Vagrant: [Official Docs](http://docs.vagrantup.com/v2/installation/index.html)\n\nCreate Vagrantfile:\n\n```ruby\n# Vagrantfile\nVagrant.configure(\"2\") do |config|\n  config.vm.box = \"hashicorp/precise64\"\n\n  config.vm.define :proxy do |c|\n    c.vm.network \"private_network\", ip: \"192.168.33.10\"\n    c.vm.network \"private_network\", ip: \"172.16.33.10\", virtualbox__intnet: \"infrataster-example\"\n  end\n\n  config.vm.define :app do |c|\n    c.vm.network \"private_network\", ip: \"172.16.33.11\", virtualbox__intnet: \"infrataster-example\"\n  end\nend\n```\n\nStart VMs:\n\n```\n$ vagrant up\n```\n\nInitialize rspec directory:\n\n```\n$ rspec --init\n  create   spec/spec_helper.rb\n  create   .rspec\n```\n\n`require 'infrataster/rspec'` and define target servers for testing in `spec/spec_helper.rb`:\n\n```ruby\n# spec/spec_helper.rb\nrequire 'infrataster/rspec'\n\nInfrataster::Server.define(\n  :proxy,           # name\n  '192.168.0.0/16', # ip address\n  vagrant: true     # for vagrant VM\n)\nInfrataster::Server.define(\n  :app,             # name\n  '172.16.0.0/16',  # ip address\n  vagrant: true,    # for vagrant VM\n  from: :proxy      # access to this machine via SSH port forwarding from proxy\n)\n\n# Code generated by `rspec --init` is following...\n```\nOr\n\n```ruby\n# spec/spec_helper.rb\nrequire 'infrataster/rspec'\n\nInfrataster::Server.define(:proxy) do |server|\n    server.address = '192.168.0.0/16'\n    server.vagrant = true\nend\nInfrataster::Server.define(:app) do |server|\n    server.address = '172.16.0.0/16'\n    server.vagrant = true\n    server.from = :proxy\nend\n\n# Code generated by `rspec --init` is following...\n```\n\nThen, you can write spec files:\n\n```ruby\n# spec/example_spec.rb\nrequire 'spec_helper'\n\ndescribe server(:app) do\n  describe http('http://app') do\n    it \"responds content including 'Hello Sinatra'\" do\n      expect(response.body).to include('Hello Sinatra')\n    end\n    it \"responds as 'text/html'\" do\n      expect(response.headers['content-type']).to eq(\"text/html\")\n    end\n  end\nend\n```\n\nRun tests:\n\n```\n$ bundle exec rspec\n2 examples, 2 failures\n```\n\nCurrently, the tests failed because the VM doesn't respond to HTTP request.\n\nIt's time to write provisioning instruction like Chef's cookbooks or Puppet's manifests!\n\n## Server\n\n\"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.\n\nYou should define servers in `spec_helper.rb` like the following:\n\n```ruby\nInfrataster::Server.define(\n  # Name of the server, this will be used in the spec files.\n  :proxy,\n  # IP address of the server\n  '192.168.0.0/16',\n  # If the server is provided by vagrant and this option is true,\n  # SSH configuration to connect to this server is got from `vagrant ssh-config` command automatically.\n  vagrant: true,\n)\n\nInfrataster::Server.define(\n  # Name of the server, this will be used in the spec files.\n  :app,\n  # IP address of the server\n  '172.16.0.0/16',\n  # If the server is provided by vagrant and this option is true,\n  # SSH configuration to connect to this server is got from `vagrant ssh-config` command automatically.\n  vagrant: true,\n  # Which gateway is used to connect to this server by SSH port forwarding?\n  from: :proxy,\n  # options for resources\n  mysql: {user: 'app', password: 'app'},\n)\n```\n\nYou can specify SSH configuration manually too:\n\n```ruby\nInfrataster::Server.define(\n  # ...\n  ssh: {host_name: 'hostname', user: 'testuser', keys: ['/path/to/id_rsa']}\n)\n```\n\n### fuzzy IP address\n\nInfrataster 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.\n\n```ruby\nInfrataster::Server.define(\n  :app,\n  # find IP address matching 172.16.0.0 ~ 172.16.255.255\n  '172.16.0.0/16',\n)\n```\n\nOf course, you can set fully-specified IP address too.\n\n```ruby\nInfrataster::Server.define(\n  :app,\n  '172.16.11.22',\n  # or\n  '172.16.11.22/32',\n)\n```\n\n### #ssh_exec\n\nYou can execute a command on the server like the following:\n\n```ruby\ndescribe server(:proxy) do\n  let(:time) { Time.now }\n  before do\n    current_server.ssh_exec \"echo 'Hello' \u003e /tmp/test-#{time.to_i}\"\n  end\n  it \"executes a command on the current server\" do\n    result = current_server.ssh_exec(\"cat /tmp/test-#{time.to_i}\")\n    expect(result.chomp).to eq('Hello')\n  end\nend\n```\n\nThis is useful to test cases which depends on the status of the server.\n\n## Resources\n\n\"Resource\" is what you test by Infrataster. For instance, the following code describes `http` resource.\n\n```ruby\ndescribe server(:app) do\n  describe http('http://example.com') do\n    it \"responds content including 'Hello Sinatra'\" do\n      expect(response.body).to include('Hello Sinatra')\n    end\n  end\nend\n```\n\n### `http` resource\n\n`http` resource tests HTTP response when sending HTTP request.\nIt accepts `method`, `params` and `header` as options.\n\n```ruby\ndescribe server(:app) do\n  describe http(\n    'http://app.example.com',\n    method: :post,\n    params: {'foo' =\u003e 'bar'},\n    headers: {'USER' =\u003e 'VALUE'}\n  ) do\n    it \"responds with content including 'app'\" do\n      expect(response.body).to include('app')\n\n      # `response` is a instance of `Faraday::Response`\n      # See: https://github.com/lostisland/faraday/blob/master/lib/faraday/response.rb\n    end\n  end\n\n  # Gzip support\n  describe http('http://app.example.com/gzipped') do\n    it \"responds with content deflated by gzip\" do\n      expect(response.headers['content-encoding']).to eq('gzip')\n    end\n  end\n\n  describe http('http://app.example.com/gzipped', inflate_gzip: true) do\n    it \"responds with content inflated automatically\" do\n      expect(response.headers['content-encoding']).to be_nil\n      expect(response.body).to eq('plain text')\n    end\n  end\n\n  # Redirects\n  describe http('http://app.example.com/redirect', follow_redirects: true) do\n    it \"follows redirects\" do\n      expect(response.status).to eq(200)\n    end\n  end\n\n  # Custom Faraday middleware\n  describe http('http://app.example.com', faraday_middlewares: [\n    YourMiddleware,\n    [YourMiddleware, options]\n  ]) do\n    it \"uses the middlewares\" do\n      expect(response.status).to eq(200)\n    end\n  end\nend\n```\n\n### `capybara` resource\n\n`capybara` resource tests your web application by simulating real user's interaction.\n\n```ruby\ndescribe server(:app) do\n  describe capybara('http://app.example.com') do\n    it 'shows food list' do\n      visit '/'\n      click_link 'Foods'\n      expect(page).to have_content 'Yummy Soup'\n    end\n  end\nend\n```\n\n### `mysql_query` resource\n\n`mysql_query` resource is now in [infrataster-plugin-mysql](https://github.com/ryotarai/infrataster-plugin-mysql).\n\n### `pgsql_query` resource\n\n`pgsql_query` resource sends a query to PostgreSQL server.\n\n`pgsql_query` is provided by [infrataster-plugin-pgsql](https://github.com/SnehaM/infrataster-plugin-pgsql) by [@SnehaM](https://github.com/SnehaM).\n\n### `dns` resource\n\n`dns` resource sends a query to DNS server.\n\n`dns` is provided by [infrataster-plugin-dns](https://github.com/otahi/infrataster-plugin-dns) by [@otahi](https://github.com/otahi).\n\n### `memcached` resource\n\n`memcached` resource sends a query to memcached server.\n\n`memcached` is provided by [infrataster-plugin-memecached](https://github.com/rahulkhengare/infrataster-plugin-memcached) by [@rahulkhengare](https://github.com/rahulkhengare).\n\n### `redis` resource\n\n`redis` resource sends a query to redis server.\n\n`redis` is provided by [infrataster-plugin-redis](https://github.com/rahulkhengare/infrataster-plugin-redis) by [@rahulkhengare](https://github.com/rahulkhengare).\n\n### `firewall` resource\n\n`firewall` resource tests your firewalls.\n\n`firewall` is provided by [infrataster-plugin-firewall](https://github.com/otahi/infrataster-plugin-firewall) by [@otahi](https://github.com/otahi).\n\n## Example\n\n* [example](example)\n* [spec/integration](spec/integration)\n\n## Tests\n\n### Unit Tests\n\nUnit tests are under `spec/unit` directory.\n\n```\n$ bundle exec rake spec:unit\n```\n\n### Integration Tests\n\nIntegration tests are under `spec/integration` directory.\n\n```\n$ bundle exec rake spec:integration:prepare\n$ bundle exec rake spec:integration\n```\n\n## Presentations and Articles\n\n* https://speakerdeck.com/ryotarai/introducing-infrataster\n\n\u003ca href=\"https://speakerdeck.com/ryotarai/introducing-infrataster\"\u003e\n\u003cimg src=\"http://i.gyazo.com/305b8b041acd3569268ece4e07e2517a.png\" alt=\"Introducing Infrataster\" width=\"300px\"\u003e\n\u003c/a\u003e\n\n* https://speakerdeck.com/ryotarai/infrataster-infra-behavior-testing-framework-number-oedo04\n* [Infratasterでリバースプロキシのテストをする](http://techlife.cookpad.com/entry/2014/11/19/151557)\n  * Google-Translated: [Testing reverse proxy with Infrataster](https://translate.google.com/translate?hl=ja\u0026sl=ja\u0026tl=en\u0026u=http%3A%2F%2Ftechlife.cookpad.com%2Fentry%2F2014%2F11%2F19%2F151557)\n\n## Changelog\n\n[Changelog](CHANGELOG.md)\n\n## Contributing\n\n1. Fork it ( http://github.com/ryotarai/infrataster/fork )\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create new Pull Request\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryotarai%2Finfrataster","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fryotarai%2Finfrataster","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fryotarai%2Finfrataster/lists"}