ventriloquist 0.3.2 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/CHANGELOG.md +47 -2
  4. data/Gemfile +2 -1
  5. data/Gemfile.lock +36 -28
  6. data/README.md +116 -41
  7. data/base_box/README.md +3 -0
  8. data/base_box/Vagrantfile +66 -0
  9. data/development/Vagrantfile +32 -11
  10. data/lib/ventriloquist/cap/platforms.rb +55 -0
  11. data/lib/ventriloquist/cap/{debian → platforms/debian}/elixir_install.rb +1 -0
  12. data/lib/ventriloquist/cap/{debian → platforms/debian}/erlang_install.rb +0 -0
  13. data/lib/ventriloquist/cap/{debian → platforms/debian}/go_install.rb +1 -1
  14. data/lib/ventriloquist/cap/{debian → platforms/debian}/phantomjs_install.rb +1 -1
  15. data/lib/ventriloquist/cap/{debian → platforms/debian}/python.rb +1 -0
  16. data/lib/ventriloquist/cap/{linux → platforms/linux}/nvm_install.rb +0 -0
  17. data/lib/ventriloquist/cap/{linux → platforms/linux}/nvm_install_nodejs.rb +0 -0
  18. data/lib/ventriloquist/cap/platforms/linux/rvm_install.rb +17 -0
  19. data/lib/ventriloquist/cap/{linux → platforms/linux}/rvm_install_ruby.rb +2 -3
  20. data/lib/ventriloquist/cap/services.rb +40 -0
  21. data/lib/ventriloquist/cap/{debian → services/debian}/mysql_install_client.rb +1 -1
  22. data/lib/ventriloquist/cap/{debian → services/debian}/mysql_install_headers.rb +1 -1
  23. data/lib/ventriloquist/cap/{debian → services/debian}/pg_install_client.rb +1 -1
  24. data/lib/ventriloquist/cap/{debian → services/debian}/pg_install_headers.rb +1 -1
  25. data/lib/ventriloquist/cap/{debian → services/debian}/ventriloquist_containers_upstart.rb +0 -0
  26. data/lib/ventriloquist/cap/{linux → services/linux}/mysql_configure_client.rb +0 -0
  27. data/lib/ventriloquist/cap/{linux → services/linux}/pg_export_pghost.rb +0 -0
  28. data/lib/ventriloquist/cap/utils.rb +40 -0
  29. data/lib/ventriloquist/cap/utils/debian/git_install.rb +13 -0
  30. data/lib/ventriloquist/cap/utils/debian/install_build_tools.rb +13 -0
  31. data/lib/ventriloquist/cap/utils/debian/install_packages.rb +47 -0
  32. data/lib/ventriloquist/cap/utils/debian/mercurial_install.rb +13 -0
  33. data/lib/ventriloquist/cap/utils/linux/download.rb +39 -0
  34. data/lib/ventriloquist/cap/{linux → utils/linux}/make.rb +0 -0
  35. data/lib/ventriloquist/cap/{linux → utils/linux}/untar.rb +0 -0
  36. data/lib/ventriloquist/config.rb +6 -3
  37. data/lib/ventriloquist/platforms/elixir.rb +1 -1
  38. data/lib/ventriloquist/platforms/go.rb +1 -1
  39. data/lib/ventriloquist/platforms/nodejs.rb +1 -0
  40. data/lib/ventriloquist/platforms/phantomjs.rb +1 -1
  41. data/lib/ventriloquist/platforms/ruby.rb +1 -0
  42. data/lib/ventriloquist/plugin.rb +3 -114
  43. data/lib/ventriloquist/provisioner.rb +12 -1
  44. data/lib/ventriloquist/service.rb +14 -7
  45. data/lib/ventriloquist/services/elastic_search.rb +12 -0
  46. data/lib/ventriloquist/services/mail_catcher.rb +12 -0
  47. data/lib/ventriloquist/services/memcached.rb +12 -0
  48. data/lib/ventriloquist/services/mysql.rb +5 -0
  49. data/lib/ventriloquist/services/postgresql.rb +5 -0
  50. data/lib/ventriloquist/services/redis.rb +12 -6
  51. data/lib/ventriloquist/services/rethink_db.rb +16 -0
  52. data/lib/ventriloquist/services_builder.rb +14 -5
  53. data/lib/ventriloquist/version.rb +1 -1
  54. data/locales/en.yml +6 -1
  55. data/services/base/Dockerfile +8 -7
  56. data/services/build-all.sh +6 -3
  57. data/services/elasticsearch/Dockerfile +6 -7
  58. data/services/mailcatcher/Dockerfile +3 -6
  59. data/services/memcached/Dockerfile +11 -12
  60. data/services/mysql/5.5/Dockerfile +17 -0
  61. data/services/mysql/{config → 5.5/config}/bin/add-mysql-user +0 -5
  62. data/services/mysql/5.6/Dockerfile +32 -0
  63. data/services/mysql/5.6/config/bin/add-mysql-user +15 -0
  64. data/services/mysql/5.6/config/etc/my.cnf +129 -0
  65. data/services/openjdk7/Dockerfile +1 -5
  66. data/services/postgresql/9.1/Dockerfile +5 -10
  67. data/services/postgresql/9.2/Dockerfile +7 -6
  68. data/services/postgresql/9.3/Dockerfile +16 -0
  69. data/services/postgresql/9.3/config/bin/prepare-postgres +25 -0
  70. data/services/postgresql/9.3/config/bin/start-postgres +6 -0
  71. data/services/postgresql/9.3/config/etc/postgresql/9.3/main/postgresql.conf +591 -0
  72. data/services/redis/Dockerfile +10 -6
  73. data/services/rethinkdb/Dockerfile +17 -0
  74. data/spec/unit/service_spec.rb +22 -12
  75. data/spec/unit/services_builder_spec.rb +26 -8
  76. data/ventriloquist.gemspec +1 -1
  77. metadata +46 -28
  78. data/lib/ventriloquist/cap/debian/git_install.rb +0 -18
  79. data/lib/ventriloquist/cap/debian/install_build_tools.rb +0 -18
  80. data/lib/ventriloquist/cap/debian/mercurial_install.rb +0 -18
  81. data/lib/ventriloquist/cap/linux/download.rb +0 -26
  82. data/lib/ventriloquist/cap/linux/rvm_install.rb +0 -17
  83. data/services/mysql/Dockerfile +0 -20
@@ -0,0 +1,3 @@
1
+ # Base box
2
+
3
+ Coming out soon...
@@ -0,0 +1,66 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ Vagrant.require_plugin 'vagrant-lxc'
5
+ Vagrant.require_plugin 'vagrant-cachier'
6
+ Vagrant.require_plugin 'vagrant-pristine'
7
+ Vagrant.require_plugin 'vocker'
8
+
9
+ Vagrant.configure("2") do |config|
10
+ config.vm.box = "raring64"
11
+ config.cache.auto_detect = true
12
+
13
+ config.vm.provider :virtualbox do |_, override|
14
+ override.vm.box_url = 'http://cloud-images.ubuntu.com/vagrant/raring/current/raring-server-cloudimg-amd64-vagrant-disk1.box'
15
+ end
16
+
17
+ config.vm.provider :lxc do |lxc, override|
18
+ # Required to boot nested containers
19
+ lxc.customize 'aa_profile', 'unconfined'
20
+ override.vm.box_url = 'http://bit.ly/vagrant-lxc-raring64-2013-10-23'
21
+ end
22
+
23
+ if ENV['LXC']
24
+ # Disable default lxc bridge
25
+ config.vm.provision :shell, inline: %[
26
+ cat <<STR > /etc/default/lxc
27
+ LXC_AUTO="false"
28
+ USE_LXC_BRIDGE="false"
29
+ STR
30
+ ]
31
+ end
32
+
33
+ config.vm.provision :docker do |docker|
34
+ docker.pull_images 'fgrehm/ventriloquist-base'
35
+ end
36
+
37
+ if ENV['LXC']
38
+ # Remove docker dependency on lxc-net
39
+ config.vm.provision :shell, inline: %[
40
+ if $(grep -q 'and started' /etc/init/docker.conf); then
41
+ sed -i.bkp 's/and started.*//' /etc/init/docker.conf
42
+ fi
43
+ ]
44
+ end
45
+
46
+ # Required packages
47
+ config.vm.provision :shell, inline: %[
48
+ apt-get update
49
+ apt-get install -y git curl build-essential libreadline-dev libssl-dev libsqlite3-dev libbz2-dev
50
+ ]
51
+
52
+ config.vm.provision :shell, privileged: false, inline: %[
53
+ # RVM
54
+ \\curl -L https://get.rvm.io | sudo bash -s stable --autolibs=enabled
55
+ sudo usermod -a -G rvm $USER
56
+
57
+ # NVM
58
+ \\curl https://raw.github.com/creationix/nvm/master/install.sh | sh
59
+
60
+ # pyenv
61
+ git clone git://github.com/yyuu/pyenv.git $HOME/.pyenv
62
+ echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.profile
63
+ echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.profile
64
+ echo 'eval "$(pyenv init -)"' >> ~/.profile
65
+ ]
66
+ end
@@ -12,7 +12,6 @@ Vagrant.configure("2") do |config|
12
12
  config.vm.synced_folder "../", "/vagrant", id: 'vagrant-root'
13
13
 
14
14
  config.vm.network :private_network, ip: "192.168.123.123"
15
- config.vm.network :forwarded_port, guest: 8080, host: 8080
16
15
 
17
16
  config.cache.auto_detect = true
18
17
 
@@ -23,28 +22,50 @@ Vagrant.configure("2") do |config|
23
22
  config.vm.provider :lxc do |lxc, override|
24
23
  # Required to boot nested containers
25
24
  lxc.customize 'aa_profile', 'unconfined'
26
- override.vm.box_url = 'http://bit.ly/vagrant-lxc-raring64-2013-07-12'
25
+ override.vm.box_url = 'http://bit.ly/vagrant-lxc-raring64-2013-10-23'
27
26
  end
28
27
 
29
28
  # Required to boot nested containers
29
+ # Disable default lxc bridge
30
30
  config.vm.provision :shell, inline: %[
31
- if ! [ -f /etc/default/lxc ]; then
32
- cat <<STR > /etc/default/lxc
31
+ cat <<STR > /etc/default/lxc
33
32
  LXC_AUTO="false"
34
33
  USE_LXC_BRIDGE="false"
35
34
  STR
36
- fi
37
35
  ]
38
36
 
39
37
  config.vm.provision :ventriloquist do |env|
38
+ # Basic examples
39
+ env.services << %w( redis memcached pg mailcatcher mysql rethinkdb )
40
+ env.platforms << %w( nodejs phantomjs go erlang elixir python:2.7.5 )
41
+
42
+ # Test custom ports and tagging
40
43
  env.services << {
41
- redis: { image: 'fgrehm/ventriloquist-redis', tag: 'latest' },
42
- memcached: { image: 'fgrehm/ventriloquist-memcached', tag: 'latest' },
43
- elasticsearch: { image: 'fgrehm/ventriloquist-elasticsearch', tag: 'latest' }
44
- }
45
- env.services << ['pg:9.1', 'mysql']
44
+ 'es' => {
45
+ image: 'fgrehm/ventriloquist-elasticsearch',
46
+ # Check if container will get the built in elasticsearch configs
47
+ type: 'elasticsearch',
48
+ },
49
+ 'pg-9.1' => {
50
+ image: 'fgrehm/ventriloquist-pg',
51
+ tag: '9.1' },
52
+ 'es-2' => {
53
+ image: 'fgrehm/ventriloquist-elasticsearch',
54
+ tag: '0.90.3',
55
+ ports: [':9200']
56
+ } }
46
57
 
58
+ # Test hash usage
47
59
  env.platforms << { ruby: { version: '2.0.0' } }
48
- env.platforms << %w( nodejs phantomjs go:1.1.2 erlang elixir)
60
+
61
+ # Test packages installation
62
+ env.packages << %w( htop sqlite3 curl wget )
49
63
  end
64
+
65
+ # Remove docker dependency on lxc-net
66
+ config.vm.provision :shell, inline: %[
67
+ if $(grep -q 'and started' /etc/init/docker.conf); then
68
+ sed -i.bkp 's/and started.*//' /etc/init/docker.conf
69
+ fi
70
+ ]
50
71
  end
@@ -0,0 +1,55 @@
1
+ module VagrantPlugins
2
+ module Ventriloquist
3
+ class Plugin < Vagrant.plugin("2")
4
+ guest_capability("linux", "nvm_install") do
5
+ require_relative "platforms/linux/nvm_install"
6
+ Cap::Linux::NvmInstall
7
+ end
8
+
9
+ guest_capability("linux", "nvm_install_nodejs") do
10
+ require_relative "platforms/linux/nvm_install_nodejs"
11
+ Cap::Linux::NvmInstallNodeJS
12
+ end
13
+
14
+ guest_capability("linux", "rvm_install") do
15
+ require_relative "platforms/linux/rvm_install"
16
+ Cap::Linux::RvmInstall
17
+ end
18
+
19
+ guest_capability("linux", "rvm_install_ruby") do
20
+ require_relative "platforms/linux/rvm_install_ruby"
21
+ Cap::Linux::RvmInstallRuby
22
+ end
23
+
24
+ guest_capability("debian", "phantomjs_install") do
25
+ require_relative "platforms/debian/phantomjs_install"
26
+ Cap::Debian::PhantomjsInstall
27
+ end
28
+
29
+ guest_capability("debian", "go_install") do
30
+ require_relative "platforms/debian/go_install"
31
+ Cap::Debian::GoInstall
32
+ end
33
+
34
+ guest_capability("debian", "erlang_install") do
35
+ require_relative "platforms/debian/erlang_install"
36
+ Cap::Debian::ErlangInstall
37
+ end
38
+
39
+ guest_capability("debian", "elixir_install") do
40
+ require_relative "platforms/debian/elixir_install"
41
+ Cap::Debian::ElixirInstall
42
+ end
43
+
44
+ guest_capability("debian", "pyenv_install") do
45
+ require_relative "platforms/debian/python"
46
+ Cap::Debian::Python
47
+ end
48
+
49
+ guest_capability("debian", "pyenv_install_python") do
50
+ require_relative "platforms/debian/python"
51
+ Cap::Debian::Python
52
+ end
53
+ end
54
+ end
55
+ end
@@ -21,6 +21,7 @@ module VagrantPlugins
21
21
  machine.guest.capability(:download, ELIXIR_PRECOMPILED, path)
22
22
  end
23
23
 
24
+ # TODO: Create unzip capability
24
25
  comm.sudo('apt-get install -y unzip')
25
26
  comm.sudo("unzip -o #{path} -d /usr/local/elixir")
26
27
 
@@ -13,7 +13,7 @@ module VagrantPlugins
13
13
  machine.env.ui.info("Installing go #{version}")
14
14
  machine.communicate.tap do |comm|
15
15
  comm.sudo('apt-get install curl -y -q')
16
- # TODO: Use download + untar capability
16
+ # TODO: Use download + untar capability and leverage vagrant-cachier
17
17
  comm.execute("cd /usr/local && curl #{src} | sudo tar xzfv -")
18
18
 
19
19
  if ! comm.test("grep -q '#{bin_path}' /etc/profile.d/ventriloquist.sh 2>/dev/null")
@@ -12,7 +12,7 @@ module VagrantPlugins
12
12
  machine.env.ui.info("Installing phantomjs #{version}")
13
13
  machine.communicate.tap do |comm|
14
14
  comm.sudo('apt-get install -y fontconfig libfreetype6 curl -y -q')
15
- # TODO: Use download + untar capability
15
+ # TODO: Use download + untar capability and leverage vagrant-cachier
16
16
  comm.execute("cd /usr/local/share && curl #{src} | sudo tar xjfv -")
17
17
  comm.sudo("ln -s #{executable} /usr/local/bin/phantomjs")
18
18
  end
@@ -7,6 +7,7 @@ module VagrantPlugins
7
7
  machine.communicate.tap do |comm|
8
8
  if ! comm.test('test -d $HOME/.pyenv')
9
9
  machine.env.ui.info('Installing pyenv dependencies')
10
+ # TODO: Use capability
10
11
  comm.sudo('sudo apt-get install -y build-essential libreadline-dev libssl-dev libsqlite3-dev libbz2-dev')
11
12
 
12
13
  machine.env.ui.info('Installing pyenv')
@@ -0,0 +1,17 @@
1
+ module VagrantPlugins
2
+ module Ventriloquist
3
+ module Cap
4
+ module Linux
5
+ module RvmInstall
6
+ def self.rvm_install(machine)
7
+ if ! machine.communicate.test('test -d /usr/local/rvm')
8
+ machine.env.ui.info('Installing RVM')
9
+ machine.communicate.sudo('\curl -L https://get.rvm.io | bash -s stable --autolibs=enabled')
10
+ machine.communicate.sudo("usermod -a -G rvm #{machine.config.ssh.username || 'vagrant'}")
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -6,9 +6,8 @@ module VagrantPlugins
6
6
  def self.rvm_install_ruby(machine, version)
7
7
  if ! machine.communicate.test("rvm list | grep #{version}")
8
8
  machine.env.ui.info("Installing Ruby #{version}")
9
- machine.communicate.execute("rvm install #{version}")
10
- # FIXME: THIS IS DEBIAN SPECIFIC
11
- machine.communicate.sudo("apt-get install -y libxslt1-dev")
9
+ machine.communicate.sudo("rvm install #{version}")
10
+ machine.guest.capability(:install_packages, 'libxslt1-dev', silent: true)
12
11
  end
13
12
  end
14
13
  end
@@ -0,0 +1,40 @@
1
+ module VagrantPlugins
2
+ module Ventriloquist
3
+ class Plugin < Vagrant.plugin("2")
4
+ guest_capability("debian", "ventriloquist_containers_upstart") do
5
+ require_relative "services/debian/ventriloquist_containers_upstart"
6
+ Cap::Debian::VentriloquistContainersUpstart
7
+ end
8
+
9
+ guest_capability("debian", "pg_install_client") do
10
+ require_relative "services/debian/pg_install_client"
11
+ Cap::Debian::PgInstallClient
12
+ end
13
+
14
+ guest_capability("debian", "pg_install_headers") do
15
+ require_relative "services/debian/pg_install_headers"
16
+ Cap::Debian::PgInstallHeaders
17
+ end
18
+
19
+ guest_capability("linux", "pg_export_pghost") do
20
+ require_relative "services/linux/pg_export_pghost"
21
+ Cap::Linux::PgExportPghost
22
+ end
23
+
24
+ guest_capability("debian", "mysql_install_client") do
25
+ require_relative "services/debian/mysql_install_client"
26
+ Cap::Debian::MySqlInstallClient
27
+ end
28
+
29
+ guest_capability("debian", "mysql_install_headers") do
30
+ require_relative "services/debian/mysql_install_headers"
31
+ Cap::Debian::MySqlInstallHeaders
32
+ end
33
+
34
+ guest_capability("linux", "mysql_configure_client") do
35
+ require_relative "services/linux/mysql_configure_client"
36
+ Cap::Linux::MySqlConfigureClient
37
+ end
38
+ end
39
+ end
40
+ end
@@ -7,7 +7,7 @@ module VagrantPlugins
7
7
  machine.communicate.tap do |comm|
8
8
  if ! comm.test('which mysql > /dev/null')
9
9
  machine.env.ui.info('Installing MySQL client')
10
- comm.sudo('apt-get install -y mysql-client')
10
+ machine.guest.capability(:install_packages, 'mysql-client', silent: true)
11
11
  end
12
12
  end
13
13
  end
@@ -7,7 +7,7 @@ module VagrantPlugins
7
7
  machine.communicate.tap do |comm|
8
8
  if ! comm.test('dpkg -l | grep libmysqlclient-dev')
9
9
  machine.env.ui.info('Installing MySQL headers')
10
- comm.sudo('apt-get install -y libmysqlclient-dev')
10
+ machine.guest.capability(:install_packages, 'libmysqlclient-dev', silent: true)
11
11
  end
12
12
  end
13
13
  end
@@ -7,7 +7,7 @@ module VagrantPlugins
7
7
  machine.communicate.tap do |comm|
8
8
  if ! comm.test('which psql > /dev/null')
9
9
  machine.env.ui.info('Installing PostgreSQL client')
10
- comm.sudo('apt-get install -y postgresql-client')
10
+ machine.guest.capability(:install_packages, 'postgresql-client', silent: true)
11
11
  end
12
12
  end
13
13
  end
@@ -7,7 +7,7 @@ module VagrantPlugins
7
7
  machine.communicate.tap do |comm|
8
8
  if ! comm.test('dpkg -l | grep libpq-dev')
9
9
  machine.env.ui.info('Installing PostgreSQL headers')
10
- comm.sudo('apt-get install -y libpq-dev')
10
+ machine.guest.capability(:install_packages, 'libpq-dev', silent: true)
11
11
  end
12
12
  end
13
13
  end
@@ -0,0 +1,40 @@
1
+ module VagrantPlugins
2
+ module Ventriloquist
3
+ class Plugin < Vagrant.plugin("2")
4
+ guest_capability("debian", "git_install") do
5
+ require_relative "utils/debian/git_install"
6
+ Cap::Debian::GitInstall
7
+ end
8
+
9
+ guest_capability("debian", "mercurial_install") do
10
+ require_relative "utils/debian/mercurial_install"
11
+ Cap::Debian::MercurialInstall
12
+ end
13
+
14
+ guest_capability("linux", "make") do
15
+ require_relative "utils/linux/make"
16
+ Cap::Linux::Make
17
+ end
18
+
19
+ guest_capability("debian", "install_build_tools") do
20
+ require_relative "utils/debian/install_build_tools"
21
+ Cap::Debian::InstallBuildTools
22
+ end
23
+
24
+ guest_capability("linux", "download") do
25
+ require_relative "utils/linux/download"
26
+ Cap::Linux::Download
27
+ end
28
+
29
+ guest_capability("linux", "untar") do
30
+ require_relative "utils/linux/untar"
31
+ Cap::Linux::Untar
32
+ end
33
+
34
+ guest_capability("debian", "install_packages") do
35
+ require_relative "utils/debian/install_packages"
36
+ Cap::Debian::InstallPackages
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,13 @@
1
+ module VagrantPlugins
2
+ module Ventriloquist
3
+ module Cap
4
+ module Debian
5
+ module GitInstall
6
+ def self.git_install(machine)
7
+ machine.guest.capability(:install_packages, 'git')
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module VagrantPlugins
2
+ module Ventriloquist
3
+ module Cap
4
+ module Debian
5
+ module InstallBuildTools
6
+ def self.install_build_tools(machine)
7
+ machine.guest.capability(:install_packages, 'build-essential')
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,47 @@
1
+ module VagrantPlugins
2
+ module Ventriloquist
3
+ module Cap
4
+ module Debian
5
+ module InstallPackages
6
+ def self.install_packages(machine, packages, opts = {})
7
+ packages = Array(packages).flatten
8
+ machine.communicate.tap do |comm|
9
+ # Based on http://askubuntu.com/a/17829
10
+ packages_to_install = packages - installed_packages(machine)
11
+ return if packages_to_install.empty?
12
+
13
+ unless opts[:silent]
14
+ machine.env.ui.info("Installing #{packages_to_install}")
15
+ end
16
+
17
+ if requires_update?(machine)
18
+ comm.sudo("apt-get update -q")
19
+ end
20
+ comm.sudo("apt-get install #{packages_to_install.join(' ')} -y --force-yes -q -o Dpkg::Options::='--force-confdef' -o Dpkg::Options::='--force-confold'")
21
+ end
22
+ end
23
+
24
+ def self.installed_packages(machine)
25
+ pkgs = ""
26
+ cmd = "dpkg --get-selections | grep -v deinstall | awk '{ print $1 }'"
27
+ machine.communicate.execute cmd do |buffer, output|
28
+ if buffer == :stdout
29
+ pkgs << output.chomp
30
+ end
31
+ end
32
+ pkgs.split("\n")
33
+ end
34
+
35
+ def self.requires_update?(machine)
36
+ @@_updated_machines ||= {}
37
+
38
+ required = !@@_updated_machines[machine]
39
+ @@_updated_machines[machine] = true
40
+
41
+ return required
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end