syncwrap 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,75 @@
1
+ #--
2
+ # Copyright (c) 2011-2012 David Kellum
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you
5
+ # may not use this file except in compliance with the License. You may
6
+ # obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
+ # implied. See the License for the specific language governing
14
+ # permissions and limitations under the License.
15
+ #++
16
+
17
+ require 'syncwrap/distro'
18
+
19
+ # Provisions for install and configuration of PostgreSQL
20
+ module SyncWrap::PostgreSQL
21
+ include SyncWrap::Distro
22
+
23
+ def initialize
24
+ super
25
+ end
26
+
27
+ # Update PostgreSQL config files from local etc
28
+ def pg_configure
29
+ rput( 'etc/postgresql/9.1/main/', :user => 'postgres' )
30
+ end
31
+
32
+ def pg_install
33
+ dist_install 'postgresql'
34
+ end
35
+
36
+ def pg_start
37
+ dist_service( 'postgresql', 'start' )
38
+ end
39
+
40
+ def pg_stop
41
+ dist_service( 'postgresql', 'stop' )
42
+ end
43
+
44
+ def pg_adjust_sysctl
45
+ rput( 'etc/sysctl.d/61-postgresql-shm.conf', :user => 'root' )
46
+ sudo "sysctl -p /etc/sysctl.d/61-postgresql-shm.conf"
47
+ end
48
+
49
+ module Ubuntu
50
+ include SyncWrap::PostgreSQL
51
+
52
+ def initialize
53
+ super
54
+ end
55
+
56
+ end
57
+
58
+ module EC2
59
+ include SyncWrap::PostgreSQL
60
+
61
+ def initialize
62
+ super
63
+ end
64
+
65
+ def pg_relocate
66
+ # FIXME: Different default location on RHEL?
67
+ sudo <<-SH
68
+ mkdir -p /mnt/var/postgresql/
69
+ mv /var/lib/postgresql/9.1 /mnt/var/postgresql/
70
+ SH
71
+ end
72
+
73
+ end
74
+
75
+ end
@@ -0,0 +1,116 @@
1
+ #--
2
+ # Copyright (c) 2011-2012 David Kellum
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you
5
+ # may not use this file except in compliance with the License. You may
6
+ # obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
+ # implied. See the License for the specific language governing
14
+ # permissions and limitations under the License.
15
+ #++
16
+
17
+ require 'rake/remote_task'
18
+
19
+ require 'syncwrap/base'
20
+ require 'syncwrap/common'
21
+
22
+ # Implements common remoting methods in terms of rake/remote_task (and
23
+ # thus Vlad compatible)
24
+ module SyncWrap::RemoteTask
25
+ include SyncWrap::Common
26
+ include Rake::DSL
27
+
28
+ def initialize
29
+ super
30
+
31
+ # Defaults:
32
+ set( :sudo_flags, %w[ -H ] )
33
+ set( :rsync_flags, %w[ -rlpcb -ii ] )
34
+ end
35
+
36
+ # Implements SyncWrap::Common#run
37
+ def run( *args )
38
+ opts = args.last.is_a?( Hash ) && args.pop || {}
39
+
40
+ exit_multi = opts[ :error ].nil? || opts[ :error ] == :exit
41
+
42
+ args = cleanup_arg_lines( args, exit_multi )
43
+
44
+ #FIXME: Should cleanup multi-line commands
45
+ remote_task_current.run( *args )
46
+ end
47
+
48
+ # Implements SyncWrap::Common#sudo
49
+ def sudo( *args )
50
+ opts = args.last.is_a?( Hash ) && args.pop || {}
51
+
52
+ flags = opts[ :flags ] || []
53
+ if opts[ :user ]
54
+ flags += [ '-u', opts[ :user ] ]
55
+ end
56
+
57
+ unless opts[ :shell ] == false
58
+ exit_multi = opts[ :error ].nil? || opts[ :error ] == :exit
59
+ cmd = cleanup_arg_lines( args, exit_multi )
60
+ cmd = cmd.join( ' ' ).gsub( /"/, '\"' )
61
+ cmd = "sh -c \"#{cmd}\""
62
+ else
63
+ cmd = cleanup_arg_lines( args, false )
64
+ end
65
+
66
+ remote_task_current.sudo( [ flags, cmd ] )
67
+ end
68
+
69
+ # Implements SyncWrap::Common#rsync
70
+ def rsync( *args )
71
+ remote_task_current.rsync( *args )
72
+ end
73
+
74
+ def target_host
75
+ remote_task_current.target_host
76
+ end
77
+
78
+ # Implements Common#exec_conditional
79
+ def exec_conditional
80
+ yield
81
+ 0
82
+ rescue Rake::CommandFailedError => e
83
+ e.status
84
+ end
85
+
86
+ # Remove extra whitespace from multi-line and single arguments
87
+ def cleanup_arg_lines( args, exit_error_on_multi )
88
+ args.flatten.compact.map do |arg|
89
+ alines = arg.split( $/ )
90
+ if alines.length > 1 && exit_error_on_multi
91
+ alines.unshift( "set -e" )
92
+ end
93
+ alines.map { |f| f.strip }.join( $/ )
94
+ end
95
+ end
96
+
97
+ def remote_task( name, *args, &block )
98
+ Rake::RemoteTask.remote_task( name, *args, &block )
99
+ end
100
+
101
+ def set( *args )
102
+ Rake::RemoteTask.set( *args )
103
+ end
104
+
105
+ def host( host_name, *roles )
106
+ Rake::RemoteTask.host( host_name, *roles )
107
+ end
108
+
109
+ def role( role_name, host = nil, args = {} )
110
+ Rake::RemoteTask.role( role_name, host, args )
111
+ end
112
+
113
+ def remote_task_current
114
+ Thread.current[ :task ] or raise "Not running from a RemoteTask"
115
+ end
116
+ end
@@ -0,0 +1,55 @@
1
+ #--
2
+ # Copyright (c) 2011-2012 David Kellum
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you
5
+ # may not use this file except in compliance with the License. You may
6
+ # obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
+ # implied. See the License for the specific language governing
14
+ # permissions and limitations under the License.
15
+ #++
16
+
17
+ require 'syncwrap/distro'
18
+
19
+ # Customizations for RedHat Enterprise Linux and derivatives like
20
+ # CentOS and Amazon Linux. Specific distros/versions may further
21
+ # override these.
22
+ module SyncWrap::RHEL
23
+ include SyncWrap::Distro
24
+
25
+ def initialize
26
+ super
27
+
28
+ packages_map.merge!( 'emacs' => 'emacs-nox',
29
+ 'postgresql' => 'postgresql-server' )
30
+ end
31
+
32
+ # FIXME
33
+ # rpm -Uvh \
34
+ # http://linux.mirrors.es.net/fedora-epel/6/x86_64/ \
35
+ # epel-release-6-7.noarch.rpm
36
+
37
+ def dist_install( *pkgs )
38
+ pkgs = dist_map_packages( pkgs )
39
+ sudo "yum install -qy #{pkgs.join( ' ' )}"
40
+ end
41
+
42
+ def dist_uninstall( *pkgs )
43
+ pkgs = dist_map_packages( pkgs )
44
+ sudo "yum remove -qy #{pkgs.join( ' ' )}"
45
+ end
46
+
47
+ def dist_install_init_service( name )
48
+ sudo "/sbin/chkconfig --add #{name}"
49
+ end
50
+
51
+ def dist_service( *args )
52
+ sudo( [ '/sbin/service' ] + args )
53
+ end
54
+
55
+ end
@@ -0,0 +1,49 @@
1
+ #--
2
+ # Copyright (c) 2011-2012 David Kellum
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you
5
+ # may not use this file except in compliance with the License. You may
6
+ # obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
+ # implied. See the License for the specific language governing
14
+ # permissions and limitations under the License.
15
+ #++
16
+
17
+ require 'syncwrap/distro'
18
+
19
+ # Customizations for Ubuntu and possibly other Debian/apt packaged
20
+ # derivatives. Specific distros/versions may further specialize.
21
+ module SyncWrap::Ubuntu
22
+ include SyncWrap::Distro
23
+
24
+ def initialize
25
+ super
26
+
27
+ packages_map.merge!( 'apr' => 'libapr1',
28
+ 'apr-devel' => 'libapr1-dev' )
29
+ end
30
+
31
+ def dist_install( *pkgs )
32
+ pkgs = dist_map_packages( pkgs )
33
+ sudo "apt-get -yq install #{pkgs.join( ' ' )}"
34
+ end
35
+
36
+ def dist_uninstall( *pkgs )
37
+ pkgs = dist_map_packages( pkgs )
38
+ sudo "aptitude -yq purge #{pkgs.join( ' ' )}"
39
+ end
40
+
41
+ def dist_install_init_service( name )
42
+ sudo "/usr/sbin/update-rc.d #{name} defaults"
43
+ end
44
+
45
+ def dist_service( *args )
46
+ sudo( [ '/usr/sbin/service' ] + args )
47
+ end
48
+
49
+ end
@@ -0,0 +1,102 @@
1
+ #--
2
+ # Copyright (c) 2011-2012 David Kellum
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you
5
+ # may not use this file except in compliance with the License. You may
6
+ # obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
+ # implied. See the License for the specific language governing
14
+ # permissions and limitations under the License.
15
+ #++
16
+
17
+ require 'syncwrap/common'
18
+
19
+ # Provisions for a (daemon) run user and var directory. Utilities for
20
+ # working with the same.
21
+ module SyncWrap::UserRun
22
+ include SyncWrap::Common
23
+
24
+ # A user for running deployed daemons, jobs (default: 'runr')
25
+ attr_accessor :user_run
26
+
27
+ # A group for running (default: 'runr')
28
+ attr_accessor :user_run_group
29
+
30
+ # Directory for persistent data, logs. (default: /var/local/runr)
31
+ attr_accessor :user_run_dir
32
+
33
+ def initialize
34
+ super
35
+
36
+ @user_run = 'runr'
37
+ @user_run_group = 'runr'
38
+
39
+ @user_run_dir = '/var/local/runr'
40
+ end
41
+
42
+ # Create and set owner/permission of run_dir, such that user_run may
43
+ # create new directories there.
44
+ def user_run_dir_setup
45
+ user_create
46
+ sudo <<-SH
47
+ mkdir -p #{user_run_dir}
48
+ chown #{user_run}:#{user_run_group} #{user_run_dir}
49
+ chmod 775 #{user_run_dir}
50
+ SH
51
+ end
52
+
53
+ # Create and set owner/permission of a named service directory under
54
+ # user_run_dir.
55
+ def user_run_service_dir_setup( sname, instance = nil )
56
+ sdir = user_run_service_dir( sname, instance )
57
+
58
+ sudo <<-SH
59
+ mkdir -p #{sdir}
60
+ chown #{user_run}:#{user_run_group} #{sdir}
61
+ chmod 775 #{sdir}
62
+ SH
63
+ end
64
+
65
+ def user_run_service_dir( sname, instance = nil )
66
+ "#{user_run_dir}/" + [ sname, instance ].compact.join( '-' )
67
+ end
68
+
69
+ # As per SyncWrap::Common#rput with :user => user_run
70
+ def user_run_rput( *args )
71
+ opts = args.last.is_a?( Hash ) && args.pop || {}
72
+ opts[ :user ] = user_run
73
+ args.push( opts )
74
+ rput( *args )
75
+ end
76
+
77
+ # Chown to user_run where args may be flags and files/directories.
78
+ def user_run_chown( *args )
79
+ flags, paths = args.partition { |a| a =~ /^-/ }
80
+ sudo( 'chown', flags, "#{user_run}:#{user_run_group}", paths )
81
+ end
82
+
83
+ def user_exist?
84
+ exec_conditional { run "id #{user_run}" } == 0
85
+ end
86
+
87
+ def user_create
88
+ user_create! unless user_exist?
89
+ end
90
+
91
+ def user_create!
92
+ if user_run_group == user_run
93
+ sudo "useradd #{user_run}"
94
+ else
95
+ sudo <<-SH
96
+ groupadd #{user_run_group}
97
+ useradd -g #{user_run_group} #{user_run}
98
+ SH
99
+ end
100
+ end
101
+
102
+ end
data/lib/syncwrap.rb ADDED
@@ -0,0 +1,17 @@
1
+ #--
2
+ # Copyright (c) 2011-2012 David Kellum
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you
5
+ # may not use this file except in compliance with the License. You may
6
+ # obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
13
+ # implied. See the License for the specific language governing
14
+ # permissions and limitations under the License.
15
+ #++
16
+
17
+ require 'syncwrap/base'
@@ -0,0 +1,202 @@
1
+ #!/usr/bin/env jruby
2
+ #.hashdot.profile += jruby-shortlived
3
+
4
+ #--
5
+ # Copyright (c) 2011-2012 David Kellum
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License"); you
8
+ # may not use this file except in compliance with the License. You
9
+ # may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
16
+ # implied. See the License for the specific language governing
17
+ # permissions and limitations under the License.
18
+ #++
19
+
20
+ require 'rubygems'
21
+ require 'bundler/setup'
22
+
23
+ require 'minitest/unit'
24
+ require 'minitest/autorun'
25
+
26
+ require 'syncwrap/java'
27
+ require 'syncwrap/hashdot'
28
+ require 'syncwrap/jruby'
29
+ require 'syncwrap/iyyov'
30
+ require 'syncwrap/ec2'
31
+ require 'syncwrap/ubuntu'
32
+ require 'syncwrap/rhel'
33
+ require 'syncwrap/postgresql'
34
+ require 'syncwrap/remote_task'
35
+
36
+ class TestSyncWrap < MiniTest::Unit::TestCase
37
+
38
+ class EveryWrapper
39
+ include SyncWrap::Java
40
+ include SyncWrap::Hashdot
41
+ include SyncWrap::JRuby
42
+ include SyncWrap::Iyyov
43
+
44
+ include SyncWrap::RHEL
45
+ include SyncWrap::Ubuntu # Not a recomendated combo
46
+
47
+ include SyncWrap::EC2
48
+ include SyncWrap::PostgreSQL::Ubuntu
49
+ include SyncWrap::PostgreSQL::EC2
50
+ end
51
+
52
+ def test_init
53
+ w = EveryWrapper.new
54
+ assert_equal( '/usr/local', w.common_prefix,
55
+ 'Common#initialize should run for defaults' )
56
+ assert_equal( 'runr', w.user_run,
57
+ 'UserRun#initialize should run for defaults' )
58
+ assert_equal( '1.1.3', w.iyyov_version,
59
+ 'Iyyov#initialize should run for defaults' )
60
+ end
61
+
62
+ def test_no_remoting_module
63
+ w = EveryWrapper.new
64
+ assert_raises( RuntimeError, <<-MSG ) { w.run( 'ls' ) }
65
+ Should raise when no remoting module is included.
66
+ MSG
67
+ end
68
+
69
+ class CommonWrapper
70
+ include SyncWrap::Common
71
+
72
+ attr_reader :last_args
73
+
74
+ def rsync( *args )
75
+ @last_args = args
76
+ end
77
+
78
+ def target_host
79
+ 'testhost'
80
+ end
81
+
82
+ end
83
+
84
+ def test_rput
85
+ w = CommonWrapper.new
86
+
87
+ w.rput( 'other/lang.sh', '/etc/' )
88
+
89
+ assert_equal( [ 'other/lang.sh',
90
+ 'testhost:/etc/' ],
91
+ w.last_args )
92
+
93
+ w.rput( 'etc/profile.d/lang.sh' )
94
+
95
+ assert_equal( [ 'etc/profile.d/lang.sh',
96
+ 'testhost:/etc/profile.d/' ],
97
+ w.last_args )
98
+
99
+ w.rput( 'etc/profile.d/' )
100
+
101
+ assert_equal( [ 'etc/profile.d/',
102
+ 'testhost:/etc/profile.d/' ],
103
+ w.last_args )
104
+
105
+ w.rput( 'etc/profile.d' )
106
+
107
+ assert_equal( [ 'etc/profile.d',
108
+ 'testhost:/etc/' ],
109
+ w.last_args )
110
+
111
+ w.rput( 'etc/profile.d/lang.sh', :user => 'root' )
112
+
113
+ assert_equal( [ '--rsync-path=sudo rsync',
114
+ 'etc/profile.d/lang.sh',
115
+ 'testhost:/etc/profile.d/'],
116
+ w.last_args )
117
+
118
+ w.rput( 'etc/profile.d/lang.sh', :user => 'runr' )
119
+
120
+ assert_equal( [ '--rsync-path=sudo -u runr rsync',
121
+ 'etc/profile.d/lang.sh',
122
+ 'testhost:/etc/profile.d/'],
123
+ w.last_args )
124
+
125
+ w.rput( 'etc/profile.d/lang.sh', :excludes => :dev )
126
+
127
+ assert_equal( [ '--cvs-exclude',
128
+ 'etc/profile.d/lang.sh',
129
+ 'testhost:/etc/profile.d/' ],
130
+ w.last_args )
131
+ end
132
+
133
+ class RemoteTaskWrapper
134
+ include SyncWrap::RemoteTask
135
+ end
136
+
137
+ class TestTask
138
+ attr_accessor :last_args
139
+
140
+ def with
141
+ Thread.current[ :task ] = self
142
+ yield self
143
+ ensure
144
+ Thread.current[ :task ] = nil
145
+ end
146
+
147
+ def run( *args )
148
+ @last_args = args
149
+ end
150
+
151
+ alias sudo run
152
+ end
153
+
154
+ def test_remote_not_in_task
155
+ w = RemoteTaskWrapper.new
156
+ assert_raises( RuntimeError ) { w.run( 'foo' ) }
157
+ end
158
+
159
+ def test_run
160
+ w = RemoteTaskWrapper.new
161
+ TestTask.new.with do |t|
162
+ w.run( 'foo' )
163
+ assert_equal( [ 'foo' ], t.last_args )
164
+
165
+ w.run( 'foo', 'bar', :opt => :bar )
166
+ assert_equal( [ 'foo', 'bar' ], t.last_args )
167
+
168
+ w.run <<-SH
169
+ mkdir -p foo
170
+ touch foo/goo
171
+ SH
172
+ assert_equal( [ [ 'set -e',
173
+ 'mkdir -p foo',
174
+ 'touch foo/goo' ].join( $/ ) ],
175
+ t.last_args )
176
+ end
177
+ end
178
+
179
+ def test_sudo
180
+ w = RemoteTaskWrapper.new
181
+ TestTask.new.with do |t|
182
+ w.sudo( 'foo' )
183
+ assert_equal( [ 'sh -c "foo"' ], t.last_args.flatten.compact )
184
+
185
+ w.sudo( 'foo', :shell => false )
186
+ assert_equal( [ 'foo' ], t.last_args.flatten.compact )
187
+
188
+ w.sudo( 'foo', 'bar', :user => 'postgres' )
189
+ assert_equal( [ '-u', 'postgres', 'sh -c "foo bar"' ],
190
+ t.last_args.flatten.compact )
191
+
192
+ w.sudo <<-SH
193
+ mkdir -p foo
194
+ touch foo/goo
195
+ SH
196
+
197
+ assert_equal( [ "sh -c \"set -e\nmkdir -p foo\ntouch foo/goo\"" ],
198
+ t.last_args.flatten.compact )
199
+ end
200
+ end
201
+
202
+ end
@@ -0,0 +1,25 @@
1
+ #!/usr/local/bin/jruby
2
+ #.hashdot.profile = jruby-shortlived
3
+ #--
4
+ # Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
5
+ # All rights reserved.
6
+ # See LICENSE.txt for permissions.
7
+ #++
8
+
9
+ require 'rubygems'
10
+ require 'rubygems/gem_runner'
11
+ require 'rubygems/exceptions'
12
+
13
+ required_version = Gem::Requirement.new ">= 1.8.7"
14
+
15
+ unless required_version.satisfied_by? Gem.ruby_version then
16
+ abort "Expected Ruby Version #{required_version}, is #{Gem.ruby_version}"
17
+ end
18
+
19
+ args = ARGV.clone
20
+
21
+ begin
22
+ Gem::GemRunner.new.run args
23
+ rescue Gem::SystemExitException => e
24
+ exit e.exit_code
25
+ end