sous_chef 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -2,5 +2,99 @@
2
2
 
3
3
  Chef's prep-cook
4
4
 
5
+ == Description
6
+
5
7
  Create bash scripts with chef-like syntax
6
8
 
9
+ == Example
10
+
11
+ Given this code:
12
+
13
+ config = {:dir => '/home'}
14
+
15
+ SousChef.prep(:verbose, :shebang) do
16
+ halt_on_failed_command
17
+
18
+ log do
19
+ stdout "/root/stdout.log"
20
+ stderr "/root/stderr.log"
21
+ end
22
+
23
+ file "/etc/config.yml" do
24
+ content config.to_yaml
25
+ mode 0600
26
+ end
27
+
28
+ execute 'rvm' do
29
+ creates "/usr/local/rvm/scripts/rvm"
30
+ command "gem install rvm && rvm-install"
31
+ end
32
+
33
+ execute "source rvm" do
34
+ command <<-EOS
35
+ RUBYOPT=""
36
+ source /usr/local/rvm/scripts/rvm
37
+ EOS
38
+ end
39
+
40
+ gemfile config[:dir] do
41
+ source "http://gemcutter.org/"
42
+
43
+ gem 'chef'
44
+ gem 'dbi', '0.4.3'
45
+ gem 'dbd-mysql', '0.4.3'
46
+ gem 'open4', '0.9.6'
47
+ end
48
+
49
+ execute 'install bundler' do
50
+ command "gem install bundler --no-ri --no-rdoc"
51
+ end
52
+
53
+ execute 'bundle gems' do
54
+ cwd config[:dir]
55
+ command "gem bundle"
56
+ end
57
+ end
58
+
59
+ the return value will be:
60
+
61
+ #!/bin/bash
62
+
63
+ # halt on failed command
64
+ set -e
65
+
66
+ exec 1>/root/stdout.log 2>/root/stderr.log
67
+
68
+ # /etc/config.yml
69
+ if ! test -e /etc/config.yml; then
70
+ echo '---
71
+ :dir: /home
72
+ ' > /etc/config.yml
73
+ fi
74
+ chmod 0600 /etc/config.yml
75
+
76
+ # rvm
77
+ if ! test -e /usr/local/rvm/scripts/rvm; then
78
+ gem install rvm && rvm-install
79
+ fi
80
+
81
+ # source rvm
82
+ RUBYOPT=""
83
+ source /usr/local/rvm/scripts/rvm
84
+
85
+ # /home
86
+ if ! test -e /home/Gemfile; then
87
+ echo 'source "http://gemcutter.org/"
88
+
89
+ gem "chef"
90
+ gem "dbd-mysql", "0.4.3"
91
+ gem "dbi", "0.4.3"
92
+ gem "open4", "0.9.6"' > /home/Gemfile
93
+ fi
94
+
95
+ # install bundler
96
+ gem install bundler --no-ri --no-rdoc
97
+
98
+ # bundle gems
99
+ cd /home
100
+ gem bundle
data/VERSION.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- :major: 0
3
2
  :minor: 0
4
- :patch: 1
5
-
3
+ :build:
4
+ :patch: 2
5
+ :major: 0
@@ -32,7 +32,8 @@ module SousChef
32
32
  script << %{# #{resource.name}\n} if verbose? && resource.name
33
33
  script << resource.to_script
34
34
  end
35
- lines.join("\n\n")
35
+ # add a trailing newline for consistency and vim-friendliness
36
+ lines.join("\n\n") << "\n"
36
37
  end
37
38
  end
38
39
 
@@ -98,9 +99,12 @@ module SousChef
98
99
  end
99
100
 
100
101
  def escape_string(string)
101
- # many slashes because single-quote has some sort of
102
- # special meaning in regexp replacement strings
103
- string && string.gsub(/'/, %q{\\\\'})
102
+ # bash is completely insane
103
+ # this stops the quote, immediately starts another one using
104
+ # double quotes to insert the single quote, then resumes the
105
+ # single quote again until the terminating single quote
106
+ return if string.nil?
107
+ string.gsub("'", %q{'"'"'})
104
108
  end
105
109
 
106
110
  def method_missing(meth, *args, &block)
@@ -9,6 +9,7 @@ module SousChef
9
9
 
10
10
  def to_script
11
11
  @script ||= begin
12
+ setup
12
13
  prepend %{cd #{escape_path(@cwd)}} if @cwd
13
14
  @commands = @commands.inject([]) do |result, line|
14
15
  result + line.split("\n")
@@ -7,7 +7,7 @@ module SousChef
7
7
 
8
8
  protected
9
9
  def escaped_content
10
- escape_string(content)
10
+ content#.gsub('$', '\$')
11
11
  end
12
12
 
13
13
  def create
@@ -24,9 +24,21 @@ module SousChef
24
24
  %{test -e #{escape_path(path)}}
25
25
  end
26
26
 
27
+ def heredoc
28
+ @heredoc ||= begin
29
+ candidate = "SousChefHeredoc"
30
+ candidate += "1" while content.include?(candidate)
31
+ candidate
32
+ end
33
+ end
34
+
27
35
  def create_file_command
28
36
  if content
29
- %{echo '#{escaped_content}' > #{escape_path(path)}}
37
+ lines = []
38
+ lines << "cat <<'#{heredoc}' > #{escape_path(path)}"
39
+ lines << escaped_content
40
+ lines << heredoc
41
+ lines.join("\n")
30
42
  else
31
43
  %{touch #{escape_path(path)}}
32
44
  end
@@ -7,9 +7,11 @@ if test -e /root/report.log; then
7
7
  fi
8
8
 
9
9
  if ! test -e /etc/config.yml; then
10
- echo '--- {}
10
+ cat <<'SousChefHeredoc' > /etc/config.yml
11
+ --- {}
11
12
 
12
- ' > /etc/config.yml
13
+
14
+ SousChefHeredoc
13
15
  fi
14
16
  chmod 0600 /etc/config.yml
15
17
 
@@ -23,10 +25,12 @@ source /usr/local/rvm/scripts/rvm
23
25
 
24
26
  if ! test -e /etc/profile.d/rvm.sh; then
25
27
  echo 'Setting up rvm source'
26
- echo '# rvm configuration
28
+ cat <<'SousChefHeredoc' > /etc/profile.d/rvm.sh
29
+ # rvm configuration
27
30
  RUBYOPT=""
28
31
  if [[ -s /usr/local/rvm/scripts/rvm ]] ; then source /usr/local/rvm/scripts/rvm ; fi
29
- ' > /etc/profile.d/rvm.sh
32
+
33
+ SousChefHeredoc
30
34
  fi
31
35
 
32
36
  echo 'installing ruby'
@@ -49,12 +53,14 @@ mkdir -p /home/sous_chef
49
53
  chmod 0755 /home/sous_chef
50
54
 
51
55
  if ! test -e /home/sous_chef/Gemfile; then
52
- echo 'source "http://gemcutter.org/"
56
+ cat <<'SousChefHeredoc' > /home/sous_chef/Gemfile
57
+ source "http://gemcutter.org/"
53
58
 
54
59
  gem "chef"
55
60
  gem "dbd-mysql", "0.4.3"
56
61
  gem "dbi", "0.4.3"
57
- gem "open4", "0.9.6"' > /home/sous_chef/Gemfile
62
+ gem "open4", "0.9.6"
63
+ SousChefHeredoc
58
64
  fi
59
65
 
60
66
  gem install bundler --no-ri --no-rdoc
@@ -64,9 +70,11 @@ gem bundle
64
70
 
65
71
  if ! test -e /etc/profile.d/bin-path.sh; then
66
72
  echo 'Setting up bin-path'
67
- echo '# bundled gem bin path configuration
73
+ cat <<'SousChefHeredoc' > /etc/profile.d/bin-path.sh
74
+ # bundled gem bin path configuration
68
75
  export PATH=/home/sous_chef/bin:$PATH
69
- ' > /etc/profile.d/bin-path.sh
76
+
77
+ SousChefHeredoc
70
78
  fi
71
79
 
72
80
  nohup /home/sous_chef/bin/chef --main &
data/spec/recipe_spec.rb CHANGED
@@ -16,7 +16,7 @@ describe SousChef::Recipe do
16
16
  end
17
17
 
18
18
  it "includes comments" do
19
- @recipe.to_script.should == "# run ls\nls"
19
+ @recipe.to_script.should == "# run ls\nls\n"
20
20
  end
21
21
  end
22
22
 
@@ -34,7 +34,7 @@ describe SousChef::Recipe do
34
34
  end
35
35
 
36
36
  it "includes a shebang line" do
37
- @recipe.to_script.should == "#!/bin/bash\n\nls"
37
+ @recipe.to_script.should == "#!/bin/bash\n\nls\n"
38
38
  end
39
39
  end
40
40
  end
@@ -56,7 +56,7 @@ describe SousChef::Recipe do
56
56
  end
57
57
 
58
58
  it "loads a recipe from a file" do
59
- @recipe.to_script.should == File.read(File.dirname(__FILE__) + '/fixtures/deploy_command_expected.sh').strip
59
+ @recipe.to_script.should == File.read(File.dirname(__FILE__) + '/fixtures/deploy_command_expected.sh')
60
60
  end
61
61
  end
62
62
  end
@@ -1,37 +1,21 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
3
  describe SousChef::Resource::Execute do
4
- before do
5
- @execute = SousChef::Resource::Execute.new(nil, "install bundler") do
6
- command "gem install bundler"
4
+ it "formats multiline commands that are wrapped in not_if" do
5
+ execute = resource("clone sous_chef") do
6
+ command <<-EOS
7
+ git clone git://github.com/engineyard/sous_chef.git
8
+ cd sous_chef
9
+ gem bundle
10
+ EOS
11
+ not_if 'test -d sous_chef'
7
12
  end
8
- end
9
-
10
- it "has a name" do
11
- @execute.name.should == "install bundler"
12
- end
13
-
14
- it "responds to a method its context responds to" do
15
- @context = stub(:foobar => 5)
16
- @execute = SousChef::Resource::Execute.new(@context, "install bundler") do
17
- command "gem install bundler"
18
- end
19
- @execute.should respond_to(:foobar)
20
- end
21
-
22
- it "delegates missing methods to its context when it responds" do
23
- @context = stub(:foobar => 5)
24
- @execute = SousChef::Resource::Execute.new(@context, "install bundler") do
25
- command "gem install bundler"
26
- end
27
- @execute.foobar.should == 5
28
- end
29
-
30
- it "does not resource_respond_to? a method its context responds to" do
31
- @context = stub(:foobar => 5)
32
- @execute = SousChef::Resource::Execute.new(@context, "install bundler") do
33
- command "gem install bundler"
34
- end
35
- @execute.should_not be_resource_respond_to(:foobar)
13
+ execute.to_script.should == %{
14
+ if ! test -d sous_chef; then
15
+ git clone git://github.com/engineyard/sous_chef.git
16
+ cd sous_chef
17
+ gem bundle
18
+ fi
19
+ }.strip
36
20
  end
37
21
  end
@@ -35,10 +35,12 @@ describe SousChef::Resource::File do
35
35
  @file.content.should == nil
36
36
  end
37
37
 
38
- it "echos content to file" do
38
+ it "cats content to file" do
39
39
  @file.to_script.should == %{
40
40
  if ! test -e note.txt; then
41
- echo 'this is a note' > note.txt
41
+ cat <<'SousChefHeredoc' > note.txt
42
+ this is a note
43
+ SousChefHeredoc
42
44
  fi
43
45
  }.strip
44
46
  end
@@ -49,7 +51,9 @@ fi
49
51
  end
50
52
  @file.to_script.should == %q{
51
53
  if ! test -e note.txt; then
52
- echo 'this is a \'note\'' > note.txt
54
+ cat <<'SousChefHeredoc' > note.txt
55
+ this is a 'note'
56
+ SousChefHeredoc
53
57
  fi
54
58
  }.strip
55
59
  end
@@ -58,11 +62,26 @@ fi
58
62
  @file = resource("note.txt") do
59
63
  content %{export PATH=/my/bin:$PATH}
60
64
  end
61
- @file.to_script.should == %q{
65
+ @file.to_script.should == <<-EOSH.chomp
62
66
  if ! test -e note.txt; then
63
- echo 'export PATH=/my/bin:$PATH' > note.txt
67
+ cat <<'SousChefHeredoc' > note.txt
68
+ export PATH=/my/bin:$PATH
69
+ SousChefHeredoc
64
70
  fi
65
- }.strip
71
+ EOSH
72
+ end
73
+
74
+ it "changes it's heredoc if the content of the file contains the heredoc" do
75
+ @file = resource("note.txt") do
76
+ content %{SousChefHeredoc}
77
+ end
78
+ @file.to_script.should == <<-EOSH.chomp
79
+ if ! test -e note.txt; then
80
+ cat <<'SousChefHeredoc1' > note.txt
81
+ SousChefHeredoc
82
+ SousChefHeredoc1
83
+ fi
84
+ EOSH
66
85
  end
67
86
 
68
87
  it "handles newlines in the content" do
@@ -75,16 +94,18 @@ a
75
94
  NOTE
76
95
  EOS
77
96
  end
78
- @file.to_script.should == %q{
97
+ @file.to_script.should == <<-EOSH.chomp
79
98
  if ! test -e note.txt; then
80
- echo 'This
99
+ cat <<'SousChefHeredoc' > note.txt
100
+ This
81
101
  is
82
102
 
83
103
  a
84
104
  NOTE
85
- ' > note.txt
105
+
106
+ SousChefHeredoc
86
107
  fi
87
- }.strip
108
+ EOSH
88
109
  end
89
110
 
90
111
  it "outputs the path instead of the name if it exists" do
@@ -94,7 +115,9 @@ fi
94
115
  end
95
116
  @file.to_script.should == %q{
96
117
  if ! test -e /home/user/note.txt; then
97
- echo 'this is a note' > /home/user/note.txt
118
+ cat <<'SousChefHeredoc' > /home/user/note.txt
119
+ this is a note
120
+ SousChefHeredoc
98
121
  fi
99
122
  }.strip
100
123
  end
data/spec/sous_spec.rb CHANGED
@@ -8,7 +8,7 @@ describe SousChef do
8
8
  command "ls"
9
9
  end
10
10
  end
11
- script.should == "ls"
11
+ script.should == "ls\n"
12
12
  end
13
13
 
14
14
  it "concatenates multiple commands" do
@@ -18,7 +18,7 @@ describe SousChef do
18
18
  command "tar xvfz file.tgz"
19
19
  end
20
20
  end
21
- script.should == "curl -O http://www.example.com/file.tgz\ntar xvfz file.tgz"
21
+ script.should == "curl -O http://www.example.com/file.tgz\ntar xvfz file.tgz\n"
22
22
  end
23
23
 
24
24
  it "respects multiline commands" do
@@ -30,7 +30,7 @@ tar xvfz file.tgz
30
30
  CODE
31
31
  end
32
32
  end
33
- script.should == "curl -O http://www.example.com/file.tgz\ntar xvfz file.tgz"
33
+ script.should == "curl -O http://www.example.com/file.tgz\ntar xvfz file.tgz\n"
34
34
  end
35
35
 
36
36
  it "changes current working directory on cwd" do
@@ -39,7 +39,7 @@ tar xvfz file.tgz
39
39
  cwd "/home/user"
40
40
  end
41
41
  end
42
- script.should == %{cd /home/user}
42
+ script.should == "cd /home/user\n"
43
43
  end
44
44
 
45
45
  it "changes the current working directory before any commands" do
@@ -49,7 +49,7 @@ tar xvfz file.tgz
49
49
  cwd "/home/user"
50
50
  end
51
51
  end
52
- script.should == %{cd /home/user\ncp foo bar}
52
+ script.should == "cd /home/user\ncp foo bar\n"
53
53
  end
54
54
 
55
55
  it "can use a method defined within the prep block" do
@@ -62,7 +62,7 @@ tar xvfz file.tgz
62
62
  report "`date`"
63
63
  end
64
64
  end
65
- script.should == %{echo `date`}
65
+ script.should == "echo `date`\n"
66
66
  end
67
67
 
68
68
  it "scopes cwd to the correct execute block" do
@@ -76,7 +76,7 @@ tar xvfz file.tgz
76
76
  command "gem bundle"
77
77
  end
78
78
  end
79
- script.should == %{gem install bundler\n\ncd /data/projects/foo\ngem bundle}
79
+ script.should == "gem install bundler\n\ncd /data/projects/foo\ngem bundle\n"
80
80
  end
81
81
 
82
82
  it "wraps commands in an if block on not_if" do
@@ -87,12 +87,12 @@ tar xvfz file.tgz
87
87
  not_if "test -d /data/projects/foo/vendor"
88
88
  end
89
89
  end
90
- script.should == %{
90
+ script.should == <<-EOSH
91
91
  if ! test -d /data/projects/foo/vendor; then
92
92
  cd /data/projects/foo
93
93
  gem bundle
94
94
  fi
95
- }.strip
95
+ EOSH
96
96
  end
97
97
 
98
98
  it "wraps commands in an if block with test -e on creates" do
@@ -103,12 +103,12 @@ fi
103
103
  command "gem bundle"
104
104
  end
105
105
  end
106
- script.should == %{
106
+ script.should == <<-EOSH
107
107
  if ! test -e /data/projects/foo/vendor; then
108
108
  cd /data/projects/foo
109
109
  gem bundle
110
110
  fi
111
- }.strip
111
+ EOSH
112
112
  end
113
113
  end
114
114
 
@@ -120,11 +120,13 @@ fi
120
120
  content "export PATH=~/bin:$PATH"
121
121
  end
122
122
  end
123
- script.should == %{
123
+ script.should == <<-EOSH
124
124
  if ! test -e ~/.bash_profile; then
125
- echo 'export PATH=~/bin:$PATH' > ~/.bash_profile
125
+ cat <<'SousChefHeredoc' > ~/.bash_profile
126
+ export PATH=~/bin:\$PATH
127
+ SousChefHeredoc
126
128
  fi
127
- }.strip
129
+ EOSH
128
130
  end
129
131
  end
130
132
 
@@ -133,7 +135,7 @@ fi
133
135
  script = SousChef.prep do
134
136
  directory "/usr/local/bin"
135
137
  end
136
- script.should == %{mkdir -p /usr/local/bin}
138
+ script.should == "mkdir -p /usr/local/bin\n"
137
139
  end
138
140
  end
139
141
 
@@ -142,7 +144,7 @@ fi
142
144
  script = SousChef.prep do
143
145
  log "~/script.log"
144
146
  end
145
- script.should == %{exec 1>~/script.log 2>&1}
147
+ script.should == "exec 1>~/script.log 2>&1\n"
146
148
  end
147
149
 
148
150
  it "allows logging stdout only" do
@@ -151,7 +153,7 @@ fi
151
153
  stdout "stdout.log"
152
154
  end
153
155
  end
154
- script.should == %{exec 1>stdout.log}
156
+ script.should == "exec 1>stdout.log\n"
155
157
  end
156
158
 
157
159
  it "allows logging stdout and stderr" do
@@ -161,7 +163,7 @@ fi
161
163
  stderr "stderr.log"
162
164
  end
163
165
  end
164
- script.should == %{exec 1>stdout.log 2>stderr.log}
166
+ script.should == "exec 1>stdout.log 2>stderr.log\n"
165
167
  end
166
168
  end
167
169
 
@@ -170,7 +172,7 @@ fi
170
172
  script = SousChef.prep do
171
173
  halt_on_failed_command
172
174
  end
173
- script.should == %{set -e}
175
+ script.should == "set -e\n"
174
176
  end
175
177
  end
176
178
 
@@ -179,7 +181,7 @@ fi
179
181
  script = SousChef.prep do
180
182
  echo "I'm in bash!"
181
183
  end
182
- script.should == %q{echo 'I\'m in bash!'}
184
+ script.should == %{echo 'I'"'"'m in bash!'\n}
183
185
  end
184
186
 
185
187
  it "echoes from anywhere" do
@@ -189,12 +191,14 @@ fi
189
191
  content "something"
190
192
  end
191
193
  end
192
- script.should == %q{
194
+ script.should == <<-EOSH
193
195
  if ! test -e newfile.txt; then
194
- echo 'I\'m in bash!'
195
- echo 'something' > newfile.txt
196
+ echo 'I'"'"'m in bash!'
197
+ cat <<'SousChefHeredoc' > newfile.txt
198
+ something
199
+ SousChefHeredoc
196
200
  fi
197
- }.strip
201
+ EOSH
198
202
  end
199
203
  end
200
204
 
@@ -206,12 +210,14 @@ fi
206
210
  gem "rack", "1.0.0"
207
211
  end
208
212
  end
209
- script.should == %q{
213
+ script.should == <<-EOSH
210
214
  if ! test -e /data/projects/foo/Gemfile; then
211
- echo 'gem "rack", "1.0.0"
212
- gem "rails", "2.3.2"' > /data/projects/foo/Gemfile
215
+ cat <<'SousChefHeredoc' > /data/projects/foo/Gemfile
216
+ gem "rack", "1.0.0"
217
+ gem "rails", "2.3.2"
218
+ SousChefHeredoc
213
219
  fi
214
- }.strip
220
+ EOSH
215
221
  end
216
222
 
217
223
  it "can have sources" do
@@ -221,13 +227,15 @@ fi
221
227
  source 'http://gems.engineyard.com/'
222
228
  end
223
229
  end
224
- script.should == %q{
230
+ script.should == <<-EOSH
225
231
  if ! test -e /data/projects/foo/Gemfile; then
226
- echo 'source "http://gems.engineyard.com/"
232
+ cat <<'SousChefHeredoc' > /data/projects/foo/Gemfile
233
+ source "http://gems.engineyard.com/"
227
234
 
228
- gem "rails"' > /data/projects/foo/Gemfile
235
+ gem "rails"
236
+ SousChefHeredoc
229
237
  fi
230
- }.strip
238
+ EOSH
231
239
  end
232
240
  end
233
241
 
@@ -239,7 +247,7 @@ fi
239
247
  end
240
248
  end
241
249
  recipe.node = { :dir => '/home' }
242
- recipe.to_script.should == "ls /home"
250
+ recipe.to_script.should == "ls /home\n"
243
251
  end
244
252
  end
245
253
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sous_chef
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Emde