marionetta 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ coverage/*
6
+ spec/vagrant/.vagrant
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "http://rubygems.org"
2
+ gemspec
data/README.md ADDED
@@ -0,0 +1,89 @@
1
+ # Marionetta
2
+
3
+ A small ruby library for executing remote commands on a number
4
+ of servers. Comes with puppet mastery built in.
5
+
6
+ ## Defining a group of servers
7
+
8
+ Marionetta allows you to describe and manipulate a number of
9
+ servers in parallel via SSH. First you need to define a group
10
+ of servers:
11
+
12
+ ``` ruby
13
+ require 'marionetta'
14
+
15
+ servers = Marionetta::Group.new
16
+
17
+ servers.add_server do |s|
18
+ s[:hostname] = 'ubuntu@example.com'
19
+ end
20
+
21
+ servers.add_server do |s|
22
+ s[:hostname] = 'another@host.com'
23
+ s[:ssh][:flags] = ['-i', 'keys/private.key']
24
+ end
25
+ ```
26
+
27
+ ## Looping over a group
28
+
29
+ Continuing on from our example of defining a group of servers
30
+ above, we will now iterate over the servers:
31
+
32
+ ``` ruby
33
+ servers.each_server do |s|
34
+ # Run command on each server in parallel
35
+ Marionetta::SSH.new(s).run('whoami')
36
+ end
37
+ ```
38
+
39
+ ## Playing puppet master
40
+
41
+ Instead of running a puppet master server you can use
42
+ Marionetta to orchestrate a number instances puppet manifests.
43
+
44
+ ``` ruby
45
+ require 'marionetta'
46
+
47
+ servers = Marionetta::Group.new
48
+
49
+ servers.add_server |s|
50
+ s[:hostname] = 'ubuntu@example.com'
51
+ s[:puppet][:manifest] = 'puppet/manifest.pp'
52
+ s[:puppet][:modules] = 'puppet/modules'
53
+ end
54
+
55
+ # Install and update puppet on each server according to
56
+ # each servers puppet settings
57
+ servers.manipulate_each_server(:puppet, :update)
58
+ ```
59
+
60
+ ## Using Marionetta in your Rakefile
61
+
62
+ Marionetta provides an easy mechanism to generate rake tasks
63
+ for each of your groups.
64
+
65
+ In your Rakefile you can do something like so:
66
+
67
+ ``` ruby
68
+ require 'marionetta/rake_helper'
69
+
70
+ staging = Marionetta::Group.new(:staging)
71
+
72
+ staging.add_server |s|
73
+ s[:hostname] = 'staging.example.com'
74
+ s[:puppet][:manifest] = 'puppet/manifest.pp'
75
+ end
76
+
77
+ Marionetta::RakeHelper.new.install_group_tasks(staging)
78
+ ```
79
+
80
+ The tasks `staging:puppet:install` and `staging:puppet:update`
81
+ will be installed.
82
+
83
+ ## Author
84
+
85
+ Luke Morton a.k.a. DrPheltRight
86
+
87
+ ## License
88
+
89
+ MIT
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
@@ -0,0 +1,54 @@
1
+ module Marionetta
2
+ class Group
3
+ attr_reader :name, :groups
4
+
5
+ def initialize(name = nil)
6
+ @name = name
7
+ @groups = []
8
+ @servers = []
9
+ end
10
+
11
+ def add_group(group)
12
+ @groups << group
13
+ end
14
+
15
+ def add_server()
16
+ server = Marionetta.default_server
17
+ yield server
18
+ @servers << server
19
+ end
20
+
21
+ def add_servers(range)
22
+ range.each do |i|
23
+ server = Marionetta.default_server
24
+ yield server, i
25
+ @servers << server
26
+ end
27
+ end
28
+
29
+ def servers()
30
+ servers = @servers
31
+
32
+ groups.each do |g|
33
+ servers.concat(g.servers)
34
+ end
35
+
36
+ return servers
37
+ end
38
+
39
+ def each_server()
40
+ servers.each do |s|
41
+ UnitOfWork.new.async.work do
42
+ yield s
43
+ end
44
+ end
45
+ end
46
+
47
+ def manipulate_each_server(manipulator_name, method_name)
48
+ each_server do |s|
49
+ manipulator = Manipulators[manipulator_name].new(s)
50
+ manipulator.method(method_name).call()
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,103 @@
1
+ module Marionetta
2
+ module Manipulators
3
+ class PuppetManipulator
4
+ def self.tasks()
5
+ [:install, :update]
6
+ end
7
+
8
+ attr_reader :server
9
+
10
+ def initialize(server)
11
+ @server = server
12
+ end
13
+
14
+ def ssh()
15
+ @ssh ||= SSH.new(server)
16
+ end
17
+
18
+ def install_deb_repo()
19
+ deb_file = 'puppetlabs-release-stable.deb'
20
+
21
+ repo_install_cmd = [
22
+ "wget http://apt.puppetlabs.com/#{deb_file}",
23
+ "sudo dpkg -i #{deb_file}",
24
+ "rm #{deb_file}",
25
+ ].join(' && ')
26
+
27
+ repo_check_cmd = "test -f /etc/apt/sources.list.d/puppetlabs.list"
28
+
29
+ ssh.run("#{repo_check_cmd} || { #{repo_install_cmd}; }")
30
+ end
31
+
32
+ def install_deb()
33
+ install_cmd = [
34
+ 'sudo aptitude update',
35
+ 'sudo aptitude install -y puppet'
36
+ ].join(' && ')
37
+
38
+ ssh.run("which puppet || { #{install_cmd}; }")
39
+ end
40
+
41
+ def install()
42
+ install_deb_repo
43
+ install_deb
44
+ end
45
+
46
+ def installed?()
47
+ ssh.run('which puppet')
48
+ end
49
+
50
+ def archive_files()
51
+ cmds = [
52
+ 'rm -rf /tmp/puppet',
53
+ 'mkdir /tmp/puppet',
54
+ "cp #{server[:puppet][:manifest]} /tmp/puppet/manifest.pp",
55
+ ]
56
+
57
+ if server[:puppet].has_key?(:modules)
58
+ cmds << "cp -r #{server[:puppet][:modules]} /tmp/puppet/modules"
59
+ end
60
+
61
+ cmds << 'cd /tmp'
62
+ cmds << 'tar cvfz puppet.tar.gz puppet'
63
+
64
+ system(cmds.join(' && '))
65
+ end
66
+
67
+ def send_archive()
68
+ ssh.rsync('/tmp/puppet.tar.gz', "#{server[:hostname]}:/tmp")
69
+ end
70
+
71
+ def apply_archive()
72
+ cmds = [
73
+ 'cd /tmp',
74
+ 'tar xvfz puppet.tar.gz',
75
+ 'cd puppet',
76
+ ]
77
+
78
+ puppet_cmd = 'sudo puppet apply '
79
+
80
+ if server[:puppet].has_key?(:modules)
81
+ puppet_cmd += '--modulepath=/tmp/puppet/modules '
82
+ end
83
+
84
+ puppet_cmd += 'manifest.pp'
85
+
86
+ if server[:puppet].has_key?(:options)
87
+ puppet_cmd += " #{server[:puppet][:options]}"
88
+ end
89
+
90
+ cmds << puppet_cmd
91
+
92
+ ssh.run(cmds.join(' && '))
93
+ end
94
+
95
+ def update()
96
+ install unless installed?
97
+ archive_files
98
+ send_archive
99
+ apply_archive
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,15 @@
1
+ module Marionetta
2
+ module Manipulators
3
+ require_relative 'manipulators/puppet_manipulator'
4
+
5
+ def self.all()
6
+ {
7
+ :puppet => PuppetManipulator,
8
+ }
9
+ end
10
+
11
+ def self.[](key)
12
+ all[key]
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,30 @@
1
+ require 'marionetta'
2
+ require 'rake'
3
+
4
+ module Marionetta
5
+ class RakeHelper
6
+ include ::Rake::DSL if defined?(::Rake::DSL)
7
+
8
+ def install_group_tasks(group)
9
+ Manipulators.all.each do |manipulator_name, Manipulator|
10
+ Manipulator.tasks.each do |method_name|
11
+ task(task_name(group, manipulator_name, method_name)) do
12
+ group.manipulate_each_server(manipulator_name, method_name)
13
+ end
14
+ end
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def task_name(group, manipulator_name, method_name)
21
+ task_name_parts = [manipulator_name, method_name]
22
+
23
+ if group.name
24
+ task_name_parts.unshift(group.name)
25
+ end
26
+
27
+ return task_name_parts.join(':')
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,48 @@
1
+ module Marionetta
2
+ class SSH
3
+ attr_reader :server
4
+
5
+ def initialize(server)
6
+ @server = server
7
+ end
8
+
9
+ def get(local_dir, file)
10
+ rsync("#{server[:hostname]}", local_dir)
11
+ end
12
+
13
+ def put(remote_path, base_name = File.basename(remote_path))
14
+ require 'tempfile'
15
+
16
+ Tempfile.open(base_name) do |fp|
17
+ fp.puts yield
18
+ fp.flush
19
+ rsync(fp.path, "#{server[:hostname]}:#{remote_path}")
20
+ end
21
+ end
22
+
23
+ def rsync(from, to)
24
+ rsync_cmd = [server[:rsync][:command]]
25
+
26
+ if server[:rsync].has_key?(:flags)
27
+ rsync_cmd << server[:rsync][:flags]
28
+ end
29
+
30
+ rsync_cmd << [from, to]
31
+
32
+ system(*rsync_cmd.flatten)
33
+ end
34
+
35
+ def run(command)
36
+ ssh_cmd = [server[:ssh][:command]]
37
+
38
+ if server[:ssh].has_key?(:flags)
39
+ ssh_cmd << server[:ssh][:flags]
40
+ end
41
+
42
+ ssh_cmd << server[:hostname]
43
+ ssh_cmd << command
44
+
45
+ system(*ssh_cmd.flatten)
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,11 @@
1
+ require 'celluloid'
2
+
3
+ module Marionetta
4
+ class UnitOfWork
5
+ include Celluloid
6
+
7
+ def work()
8
+ yield
9
+ end
10
+ end
11
+ end
data/lib/marionetta.rb ADDED
@@ -0,0 +1,24 @@
1
+ module Marionetta
2
+ VERSION = '0.1.0'
3
+ DESCRIPTION = 'For lightweight puppet mastery. Organise
4
+ multiple machines via rsync and SSH rather
5
+ than using puppet master'
6
+
7
+ require_relative 'marionetta/ssh'
8
+ require_relative 'marionetta/manipulators'
9
+ require_relative 'marionetta/unit_of_work'
10
+ require_relative 'marionetta/group'
11
+
12
+ def self.default_server()
13
+ {
14
+ :ssh => {
15
+ :command => 'ssh',
16
+ :flags => [],
17
+ },
18
+ :rsync => {
19
+ :command => 'rsync',
20
+ :flags => ["-azP", "--delete"],
21
+ },
22
+ }
23
+ end
24
+ end
@@ -0,0 +1,23 @@
1
+ require File.dirname(__FILE__)+'/lib/marionetta'
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "marionetta"
5
+ s.version = Marionetta::VERSION
6
+ s.homepage = 'https://github.com/DrPheltRight/marionetta'
7
+ s.authors = ["Luke Morton"]
8
+ s.email = ["lukemorton.dev@gmail.com"]
9
+ s.summary = Marionetta::DESCRIPTION
10
+ s.description = Marionetta::DESCRIPTION
11
+
12
+ s.files = `git ls-files`.split("\n")
13
+ s.test_files = `git ls-files -- spec/*`.split("\n")
14
+ s.executables = `git ls-files -- bin/*`.split("\n").map {|f| File.basename(f)}
15
+
16
+ s.require_paths = ["lib"]
17
+
18
+ s.add_dependency('celluloid')
19
+
20
+ s.add_development_dependency('rake')
21
+ s.add_development_dependency('rspec')
22
+ s.add_development_dependency('vagrant')
23
+ end
@@ -0,0 +1,46 @@
1
+ require 'marionetta'
2
+ require 'marionetta/group'
3
+
4
+ describe Marionetta::Group do
5
+ it 'should add server map' do
6
+ vagrant = Marionetta::Group.new
7
+
8
+ vagrant.add_server do |s|
9
+ s[:hostname] = 'vagrant@192.168.33.11'
10
+ s[:puppet] = {:manifest => File.dirname(__FILE__)+'/puppet/manifest.pp'}
11
+ end
12
+ end
13
+
14
+ it 'should add multiple server maps at once' do
15
+ production = Marionetta::Group.new
16
+
17
+ production.add_servers (1..2) do |s, i|
18
+ s[:hostname] = "vagrant@192.168.33.11"
19
+ s[:puppet] = {:manifest => File.dirname(__FILE__)+'/puppet/manifest.pp'}
20
+ end
21
+
22
+ production.servers.count.should == 2
23
+ end
24
+
25
+ it 'should add sub groups' do
26
+ staging = Marionetta::Group.new
27
+
28
+ staging.add_server do |s|
29
+ s[:hostname] = 'vagrant@192.168.33.11'
30
+ s[:puppet] = {:manifest => File.dirname(__FILE__)+'/puppet/manifest.pp'}
31
+ end
32
+
33
+ all = Marionetta::Group.new
34
+ all.add_group(staging)
35
+ end
36
+
37
+ it 'should iterate over all servers' do
38
+ end
39
+
40
+ it 'should iterate over all servers including those of sub groups' do
41
+ end
42
+
43
+ it 'should manipulate each server' do
44
+ # vagrant.manipulate_each_server(:puppet, :update)
45
+ end
46
+ end
@@ -0,0 +1,7 @@
1
+ require 'marionetta/manipulators'
2
+
3
+ describe Marionetta::Manipulators do
4
+ it 'should maintain a list of manipulators' do
5
+ Marionetta::Manipulators.all
6
+ end
7
+ end
@@ -0,0 +1,17 @@
1
+ require 'marionetta/manipulators'
2
+
3
+ describe Marionetta::Manipulators::PuppetManipulator do
4
+ it 'should manipulate one server map' do
5
+ ssh_key_path = File.dirname(__FILE__)+'/vagrant/key'
6
+
7
+ server = Marionetta.default_server
8
+ server[:hostname] = 'vagrant@192.168.33.11'
9
+ server[:ssh][:flags] = ['-i', ssh_key_path]
10
+ server[:rsync][:flags] = ['-azP', '-e', "ssh -i #{ssh_key_path}", '--delete']
11
+ server[:puppet] = {
12
+ :manifest => File.dirname(__FILE__)+'/puppet/manifest.pp',
13
+ }
14
+
15
+ Marionetta::Manipulators::PuppetManipulator.new(server).update
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ require 'marionetta'
2
+ require 'vagrant'
3
+
4
+ env = Vagrant::Environment.new(:cwd => File.dirname(__FILE__)+'/vagrant')
5
+ env.cli('up')
6
+
7
+ describe Marionetta do
8
+ it 'should provide a default SSH map' do
9
+ Marionetta.default_server
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ file { '/etc/motd':
2
+ content => 'Hello sooty',
3
+ }
@@ -0,0 +1,6 @@
1
+ Vagrant::Config.run do |config|
2
+ config.vm.box = "precise64"
3
+ config.vm.box_url = "http://files.vagrantup.com/precise64.box"
4
+
5
+ config.vm.network(:hostonly, "192.168.33.11")
6
+ end
data/spec/vagrant/key ADDED
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEogIBAAKCAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzI
3
+ w+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoP
4
+ kcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2
5
+ hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NO
6
+ Td0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcW
7
+ yLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQIBIwKCAQEA4iqWPJXtzZA68mKd
8
+ ELs4jJsdyky+ewdZeNds5tjcnHU5zUYE25K+ffJED9qUWICcLZDc81TGWjHyAqD1
9
+ Bw7XpgUwFgeUJwUlzQurAv+/ySnxiwuaGJfhFM1CaQHzfXphgVml+fZUvnJUTvzf
10
+ TK2Lg6EdbUE9TarUlBf/xPfuEhMSlIE5keb/Zz3/LUlRg8yDqz5w+QWVJ4utnKnK
11
+ iqwZN0mwpwU7YSyJhlT4YV1F3n4YjLswM5wJs2oqm0jssQu/BT0tyEXNDYBLEF4A
12
+ sClaWuSJ2kjq7KhrrYXzagqhnSei9ODYFShJu8UWVec3Ihb5ZXlzO6vdNQ1J9Xsf
13
+ 4m+2ywKBgQD6qFxx/Rv9CNN96l/4rb14HKirC2o/orApiHmHDsURs5rUKDx0f9iP
14
+ cXN7S1uePXuJRK/5hsubaOCx3Owd2u9gD6Oq0CsMkE4CUSiJcYrMANtx54cGH7Rk
15
+ EjFZxK8xAv1ldELEyxrFqkbE4BKd8QOt414qjvTGyAK+OLD3M2QdCQKBgQDtx8pN
16
+ CAxR7yhHbIWT1AH66+XWN8bXq7l3RO/ukeaci98JfkbkxURZhtxV/HHuvUhnPLdX
17
+ 3TwygPBYZFNo4pzVEhzWoTtnEtrFueKxyc3+LjZpuo+mBlQ6ORtfgkr9gBVphXZG
18
+ YEzkCD3lVdl8L4cw9BVpKrJCs1c5taGjDgdInQKBgHm/fVvv96bJxc9x1tffXAcj
19
+ 3OVdUN0UgXNCSaf/3A/phbeBQe9xS+3mpc4r6qvx+iy69mNBeNZ0xOitIjpjBo2+
20
+ dBEjSBwLk5q5tJqHmy/jKMJL4n9ROlx93XS+njxgibTvU6Fp9w+NOFD/HvxB3Tcz
21
+ 6+jJF85D5BNAG3DBMKBjAoGBAOAxZvgsKN+JuENXsST7F89Tck2iTcQIT8g5rwWC
22
+ P9Vt74yboe2kDT531w8+egz7nAmRBKNM751U/95P9t88EDacDI/Z2OwnuFQHCPDF
23
+ llYOUI+SpLJ6/vURRbHSnnn8a/XG+nzedGH5JGqEJNQsz+xT2axM0/W/CRknmGaJ
24
+ kda/AoGANWrLCz708y7VYgAtW2Uf1DPOIYMdvo6fxIB5i9ZfISgcJ/bbCUkFrhoH
25
+ +vq/5CIWxCPp0f85R4qxxQ5ihxJ0YDQT9Jpx4TMss4PSavPaBH3RXow5Ohe+bYoQ
26
+ NE5OgEXk2wVfZczCZpigBKbKZHNYcelXtTt/nP3rsCuGcM4h53s=
27
+ -----END RSA PRIVATE KEY-----
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: marionetta
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Luke Morton
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-09-16 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: celluloid
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: vagrant
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: ! "For lightweight puppet mastery. Organise\n multiple
79
+ machines via rsync and SSH rather\n than using puppet master"
80
+ email:
81
+ - lukemorton.dev@gmail.com
82
+ executables: []
83
+ extensions: []
84
+ extra_rdoc_files: []
85
+ files:
86
+ - .gitignore
87
+ - Gemfile
88
+ - README.md
89
+ - Rakefile
90
+ - lib/marionetta.rb
91
+ - lib/marionetta/group.rb
92
+ - lib/marionetta/manipulators.rb
93
+ - lib/marionetta/manipulators/puppet_manipulator.rb
94
+ - lib/marionetta/rake_helper.rb
95
+ - lib/marionetta/ssh.rb
96
+ - lib/marionetta/unit_of_work.rb
97
+ - marionetta.gemspec
98
+ - spec/marionetta_group_spec.rb
99
+ - spec/marionetta_manipulators_spec.rb
100
+ - spec/marionetta_puppet_manipulator_spec.rb
101
+ - spec/marionetta_spec.rb
102
+ - spec/puppet/manifest.pp
103
+ - spec/vagrant/Vagrantfile
104
+ - spec/vagrant/key
105
+ homepage: https://github.com/DrPheltRight/marionetta
106
+ licenses: []
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ none: false
113
+ requirements:
114
+ - - ! '>='
115
+ - !ruby/object:Gem::Version
116
+ version: '0'
117
+ required_rubygems_version: !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ! '>='
121
+ - !ruby/object:Gem::Version
122
+ version: '0'
123
+ requirements: []
124
+ rubyforge_project:
125
+ rubygems_version: 1.8.23
126
+ signing_key:
127
+ specification_version: 3
128
+ summary: For lightweight puppet mastery. Organise multiple machines via rsync and
129
+ SSH rather than using puppet master
130
+ test_files:
131
+ - spec/marionetta_group_spec.rb
132
+ - spec/marionetta_manipulators_spec.rb
133
+ - spec/marionetta_puppet_manipulator_spec.rb
134
+ - spec/marionetta_spec.rb
135
+ - spec/puppet/manifest.pp
136
+ - spec/vagrant/Vagrantfile
137
+ - spec/vagrant/key