marionetta 0.1.11 → 0.2.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 CHANGED
@@ -3,4 +3,5 @@
3
3
  Gemfile.lock
4
4
  pkg/*
5
5
  coverage/*
6
- spec/vagrant/.vagrant
6
+ spec/vagrant/.vagrant
7
+ *.deb
data/README.md CHANGED
@@ -14,7 +14,7 @@ servers in parallel via SSH. First you need to define a group
14
14
  of servers:
15
15
 
16
16
  ``` ruby
17
- require 'marionetta'
17
+ require 'marionetta/group'
18
18
 
19
19
  servers = Marionetta::Group.new
20
20
 
@@ -34,9 +34,18 @@ Continuing on from our example of defining a group of servers
34
34
  above, we will now iterate over the servers:
35
35
 
36
36
  ``` ruby
37
+ # Each block executes in it's own asynchronous thread
37
38
  servers.each_server do |s|
38
- # Run command on each server in parallel
39
- Marionetta::SSH.new(s).ssh('whoami')
39
+ cmd = Marionetta::CommandRunner.new(s)
40
+
41
+ # Send a command via SSH
42
+ cmd.ssh('whoami')
43
+
44
+ # Get a file
45
+ cmd.get('/var/backups/database')
46
+
47
+ # Put a file
48
+ cmd.put('/etc/motd')
40
49
  end
41
50
  ```
42
51
 
@@ -46,7 +55,7 @@ Instead of running a puppet master server you can use
46
55
  Marionetta to orchestrate a number instances.
47
56
 
48
57
  ``` ruby
49
- require 'marionetta'
58
+ require 'marionetta/group'
50
59
 
51
60
  servers = Marionetta::Group.new
52
61
 
@@ -69,7 +78,7 @@ for each of your groups.
69
78
  In your Rakefile you can do something like so:
70
79
 
71
80
  ``` ruby
72
- require 'marionetta'
81
+ require 'marionetta/group'
73
82
  require 'marionetta/rake_helper'
74
83
 
75
84
  staging = Marionetta::Group.new(:staging)
@@ -87,6 +96,25 @@ will now be available in your Rakefile.
87
96
 
88
97
  **Groups must have names if you want to generate rake tasks.**
89
98
 
99
+ ## Using the debloyer
100
+
101
+ Also included is a .deb deploying manipulator. You can use
102
+ this to deploy your application over SSH as a .deb.
103
+
104
+ ``` ruby
105
+ require 'marionetta/group'
106
+
107
+ staging = Marionetta::Group.new(:staging)
108
+
109
+ staging.add_server do |s|
110
+ s[:hostname] = 'staging.example.com'
111
+ s[:debloyer][:from] = '/my-app'
112
+ s[:debloyer][:to] = '/home/staging/www'
113
+ end
114
+
115
+ staging.manipulate_each_server(:debployer, :deploy)
116
+ ```
117
+
90
118
  ## Author
91
119
 
92
120
  Luke Morton a.k.a. DrPheltRight
data/Rakefile CHANGED
@@ -35,5 +35,5 @@ task(:publish => :gem) do
35
35
  end
36
36
 
37
37
  task(:clean) do
38
- system('rm -rf *.gem')
38
+ system('rm *.gem')
39
39
  end
@@ -1,5 +1,5 @@
1
1
  module Marionetta
2
- VERSION = '0.1.11'
2
+ VERSION = '0.2.0'
3
3
  DESCRIPTION = 'For lightweight puppet mastery. Organise
4
4
  multiple machines via rsync and SSH rather
5
5
  than using puppet master'
@@ -15,6 +15,17 @@ module Marionetta
15
15
  :flags => ["-azP", "--delete"],
16
16
  },
17
17
  :logger => Logger.new($stdout),
18
+
19
+ :debloyer => {
20
+ :name => 'debloyer',
21
+ :fpm => {
22
+ :command => 'fpm',
23
+ :flags => [
24
+ '-s', 'dir',
25
+ '-t', 'deb',
26
+ ],
27
+ },
28
+ },
18
29
  }
19
30
  end
20
31
  end
@@ -10,26 +10,14 @@ module Marionetta
10
10
 
11
11
  def system(*args)
12
12
  status = Open4::popen4(*args) do |pid, stdin, stdout, stderr|
13
+ yield stdout, stderr if block_given?
14
+
13
15
  server[:logger].info(args.join(' '))
14
16
  server[:logger].debug(stdout.read)
15
17
  server[:logger].debug(stderr.read)
16
18
  end
17
19
 
18
- return status.exitstatus
19
- end
20
-
21
- def get(local_dir, file)
22
- rsync("#{server[:hostname]}", local_dir)
23
- end
24
-
25
- def put(remote_path, base_name = File.basename(remote_path))
26
- require 'tempfile'
27
-
28
- Tempfile.open(base_name) do |fp|
29
- fp.puts yield
30
- fp.flush
31
- rsync(fp.path, "#{server[:hostname]}:#{remote_path}")
32
- end
20
+ return status.exitstatus == 0
33
21
  end
34
22
 
35
23
  def rsync(from, to)
@@ -44,7 +32,15 @@ module Marionetta
44
32
  system(*rsync_cmd.flatten)
45
33
  end
46
34
 
47
- def ssh(command)
35
+ def get(file_path, save_to = File.dirname(file_path))
36
+ rsync("#{server[:hostname]}:#{file_path}", save_to)
37
+ end
38
+
39
+ def put(file_path, save_to = File.dirname(file_path))
40
+ rsync(file_path, "#{server[:hostname]}:#{save_to}")
41
+ end
42
+
43
+ def ssh(command, &block)
48
44
  ssh_cmd = [server[:ssh][:command]]
49
45
 
50
46
  if server[:ssh].has_key?(:flags)
@@ -54,7 +50,7 @@ module Marionetta
54
50
  ssh_cmd << server[:hostname]
55
51
  ssh_cmd << command
56
52
 
57
- system(*ssh_cmd.flatten)
53
+ system(*ssh_cmd.flatten, &block)
58
54
  end
59
55
  end
60
56
  end
@@ -1,10 +1,12 @@
1
1
  module Marionetta
2
2
  module Manipulators
3
+ require_relative 'manipulators/debloyer'
3
4
  require_relative 'manipulators/puppet_manipulator'
4
5
 
5
6
  def self.all()
6
7
  {
7
- :puppet => PuppetManipulator,
8
+ :debployer => Debloyer,
9
+ :puppet => PuppetManipulator,
8
10
  }
9
11
  end
10
12
 
@@ -0,0 +1,75 @@
1
+ require 'marionetta/command_runner'
2
+
3
+ module Marionetta
4
+ module Manipulators
5
+ class Debloyer
6
+ def self.tasks()
7
+ [:deploy]
8
+ end
9
+
10
+ attr_writer :cmd
11
+
12
+ def initialize(server)
13
+ @server = server
14
+ end
15
+
16
+ def deploy()
17
+ deb_path = create_deb_path
18
+ build_deb(deb_path)
19
+ send_deb(deb_path)
20
+ apply_deb(deb_path)
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :server
26
+
27
+ def cmd()
28
+ @cmd ||= CommandRunner.new(server)
29
+ end
30
+
31
+ def from_dir()
32
+ server[:debloyer][:from]
33
+ end
34
+
35
+ def to_dir()
36
+ server[:debloyer][:to]
37
+ end
38
+
39
+ def timestamp()
40
+ Time.new.strftime('%F_%T')
41
+ end
42
+
43
+ def create_deb_path()
44
+ "/tmp/#{server[:debloyer][:name]}_#{timestamp}.deb"
45
+ end
46
+
47
+ def build_cmd()
48
+ server[:debloyer][:fpm][:command]
49
+ end
50
+
51
+ def build_options(deb_path)
52
+ options = server[:debloyer][:fpm][:flags]
53
+
54
+ options << ['-n', server[:debloyer][:name]]
55
+ options << ['-p', deb_path]
56
+ options << ['-C', from_dir]
57
+ options << ['--prefix', to_dir]
58
+
59
+ options
60
+ end
61
+
62
+ def build_deb(deb_path)
63
+ cmd.system(*[build_cmd, build_options(deb_path), '.'].flatten)
64
+ end
65
+
66
+ def send_deb(deb_path)
67
+ cmd.put(deb_path, '/tmp')
68
+ end
69
+
70
+ def apply_deb(deb_path)
71
+ cmd.ssh("sudo dpkg -i #{deb_path}")
72
+ end
73
+ end
74
+ end
75
+ end
@@ -1,14 +1,13 @@
1
- require 'marionetta'
2
1
  require 'marionetta/command_runner'
3
2
 
4
3
  module Marionetta
5
4
  module Manipulators
6
5
  class PuppetManipulator
7
- attr_writer :cmd
8
-
9
6
  def self.tasks()
10
7
  [:install, :update]
11
8
  end
9
+
10
+ attr_writer :cmd
12
11
 
13
12
  def initialize(server)
14
13
  @server = server
@@ -79,7 +78,7 @@ module Marionetta
79
78
  end
80
79
 
81
80
  def send_archive()
82
- cmd.rsync('/tmp/puppet.tar.gz', "#{server[:hostname]}:/tmp")
81
+ cmd.put('/tmp/puppet.tar.gz')
83
82
  end
84
83
 
85
84
  def apply_archive()
@@ -0,0 +1,11 @@
1
+ def a(*args)
2
+ yield args if block_given?
3
+ end
4
+
5
+ def b(*args, &block)
6
+ a(*args, &block)
7
+ end
8
+
9
+ b do |str|
10
+ puts str, 'cool'
11
+ end
@@ -17,6 +17,7 @@ Gem::Specification.new do |s|
17
17
 
18
18
  s.add_dependency('open4')
19
19
  s.add_dependency('celluloid')
20
+ s.add_dependency('fpm')
20
21
 
21
22
  s.add_development_dependency('rake')
22
23
  s.add_development_dependency('rspec')
@@ -0,0 +1,5 @@
1
+ def app()
2
+ puts 'hello world'
3
+ end
4
+
5
+ app
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+ require "marionetta"
3
+ require "marionetta/manipulators/debloyer"
4
+
5
+ describe Marionetta::Manipulators::Debloyer do
6
+ it 'should deploy a deb' do
7
+ Marionetta::Manipulators::Debloyer.new(server).deploy
8
+ end
9
+ end
@@ -83,15 +83,7 @@ describe Marionetta::Group do
83
83
 
84
84
  it 'should manipulate each server' do
85
85
  vagrant = Marionetta::Group.new
86
-
87
- vagrant.add_server do |s|
88
- s[:hostname] = 'vagrant@192.168.33.11'
89
- ssh_key_path = File.dirname(__FILE__)+'/vagrant/key'
90
- s[:ssh][:flags] = ['-i', ssh_key_path]
91
- s[:rsync][:flags] = ['-azP', '-e', "ssh -i #{ssh_key_path}", '--delete']
92
- s[:puppet] = {:manifest => File.dirname(__FILE__)+'/puppet/manifest.pp'}
93
- end
94
-
86
+ vagrant.add_server(server)
95
87
  vagrant.manipulate_each_server(:puppet, :update)
96
88
  end
97
89
  end
@@ -3,16 +3,6 @@ require 'marionetta/manipulators/puppet_manipulator'
3
3
 
4
4
  describe Marionetta::Manipulators::PuppetManipulator do
5
5
  it 'should manipulate one server map' do
6
- ssh_key_path = File.dirname(__FILE__)+'/vagrant/key'
7
-
8
- server = Marionetta.default_server
9
- server[:hostname] = 'vagrant@192.168.33.11'
10
- server[:ssh][:flags] = ['-i', ssh_key_path]
11
- server[:rsync][:flags] = ['-azP', '-e', "ssh -i #{ssh_key_path}", '--delete']
12
- server[:puppet] = {
13
- :manifest => File.dirname(__FILE__)+'/puppet/manifest.pp',
14
- }
15
-
16
6
  Marionetta::Manipulators::PuppetManipulator.new(server).update
17
7
  end
18
8
  end
@@ -4,14 +4,7 @@ require 'marionetta/rake_helper'
4
4
  describe Marionetta::RakeHelper do
5
5
  it 'should install rake tasks' do
6
6
  vagrant = Marionetta::Group.new(:vagrant)
7
-
8
- vagrant.add_server do |s|
9
- s[:hostname] = 'vagrant@192.168.33.11'
10
- ssh_key_path = File.dirname(__FILE__)+'/vagrant/key'
11
- s[:ssh][:flags] = ['-i', ssh_key_path]
12
- s[:rsync][:flags] = ['-azP', '-e', "ssh -i #{ssh_key_path}", '--delete']
13
- s[:puppet] = {:manifest => File.dirname(__FILE__)+'/puppet/manifest.pp'}
14
- end
7
+ vagrant.add_server(server)
15
8
 
16
9
  Marionetta::RakeHelper.new(vagrant).install_group_tasks
17
10
  Rake::Task.tasks.count.should > 0
@@ -0,0 +1,30 @@
1
+ require 'spec_helper'
2
+ require 'marionetta/command_runner'
3
+
4
+ def cmd()
5
+ Marionetta::CommandRunner.new(server)
6
+ end
7
+
8
+ describe Marionetta::CommandRunner do
9
+ it 'should get file' do
10
+ cmd.get('/etc/hostname', '/tmp/hosting')
11
+ File.open('/tmp/hosting', 'rb').read.should == "precise64\n"
12
+ end
13
+
14
+ it 'should put file' do
15
+ file_path = "#{LIB}/marionetta.rb"
16
+ cmd.put(file_path, '/tmp')
17
+ local = File.open(file_path, 'rb').read
18
+
19
+ tmp_path = '/tmp/marionetta.rb'
20
+ cmd.get(tmp_path)
21
+ remote = File.open(tmp_path, 'rb').read
22
+ remote.should == local
23
+ end
24
+
25
+ it 'should run commands' do
26
+ cmd.ssh('whoami') do |stdout, stderr|
27
+ stdout.read.should == "vagrant\n"
28
+ end
29
+ end
30
+ end
@@ -1,7 +1,27 @@
1
1
  require 'vagrant'
2
2
  require 'celluloid'
3
+ require 'marionetta'
4
+
5
+ LIB = File.dirname(__FILE__)+'/../lib'
3
6
 
4
7
  env = Vagrant::Environment.new(:cwd => File.dirname(__FILE__)+'/vagrant')
5
8
  env.cli('up')
6
9
 
7
- Celluloid.logger.level = Logger::WARN
10
+ def server()
11
+ s = Marionetta.default_server
12
+
13
+ s[:hostname] = 'vagrant@192.168.33.11'
14
+ ssh_key_path = File.dirname(__FILE__)+'/vagrant/key'
15
+ s[:ssh][:flags] = ['-i', ssh_key_path]
16
+ s[:rsync][:flags] = ['-azP', '-e', "ssh -i #{ssh_key_path}", '--delete']
17
+
18
+ s[:debloyer][:from] = File.dirname(__FILE__)+'/app'
19
+ s[:debloyer][:to] = '/home/vagrant'
20
+ s[:debloyer][:name] = 'test'
21
+
22
+ s[:puppet] = {
23
+ :manifest => File.dirname(__FILE__)+'/puppet/manifest.pp',
24
+ }
25
+
26
+ return s
27
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: marionetta
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.11
4
+ version: 0.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -43,6 +43,22 @@ dependencies:
43
43
  - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
45
  version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: fpm
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
46
62
  - !ruby/object:Gem::Dependency
47
63
  name: rake
48
64
  requirement: !ruby/object:Gem::Requirement
@@ -107,14 +123,19 @@ files:
107
123
  - lib/marionetta/command_runner.rb
108
124
  - lib/marionetta/group.rb
109
125
  - lib/marionetta/manipulators.rb
126
+ - lib/marionetta/manipulators/debloyer.rb
110
127
  - lib/marionetta/manipulators/puppet_manipulator.rb
111
128
  - lib/marionetta/rake_helper.rb
129
+ - lib/test.rb
112
130
  - marionetta.gemspec
131
+ - spec/app/app.rb
132
+ - spec/marionetta_debloyer_spec.rb
113
133
  - spec/marionetta_group_spec.rb
114
134
  - spec/marionetta_manipulators_spec.rb
115
135
  - spec/marionetta_puppet_manipulator_spec.rb
116
136
  - spec/marionetta_rake_helper_spec.rb
117
137
  - spec/marionetta_spec.rb
138
+ - spec/marionetta_ssh_spec.rb
118
139
  - spec/puppet/manifest.pp
119
140
  - spec/spec_helper.rb
120
141
  - spec/vagrant/Vagrantfile
@@ -145,11 +166,14 @@ specification_version: 3
145
166
  summary: For lightweight puppet mastery. Organise multiple machines via rsync and
146
167
  SSH rather than using puppet master
147
168
  test_files:
169
+ - spec/app/app.rb
170
+ - spec/marionetta_debloyer_spec.rb
148
171
  - spec/marionetta_group_spec.rb
149
172
  - spec/marionetta_manipulators_spec.rb
150
173
  - spec/marionetta_puppet_manipulator_spec.rb
151
174
  - spec/marionetta_rake_helper_spec.rb
152
175
  - spec/marionetta_spec.rb
176
+ - spec/marionetta_ssh_spec.rb
153
177
  - spec/puppet/manifest.pp
154
178
  - spec/spec_helper.rb
155
179
  - spec/vagrant/Vagrantfile