marionetta 0.1.11 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
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