itamae-spec 0.0.2

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.
Files changed (77) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/Gemfile +7 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +42 -0
  7. data/Rakefile +47 -0
  8. data/bin/itamae-spec +4 -0
  9. data/itamae-spec.gemspec +36 -0
  10. data/lib/itamae-spec.rb +10 -0
  11. data/lib/itamae-spec/cli.rb +19 -0
  12. data/lib/itamae-spec/generators.rb +20 -0
  13. data/lib/itamae-spec/generators/cookbook.rb +10 -0
  14. data/lib/itamae-spec/generators/project.rb +10 -0
  15. data/lib/itamae-spec/generators/templates/cookbook/attributes/.keep +0 -0
  16. data/lib/itamae-spec/generators/templates/cookbook/recipes/default.rb +0 -0
  17. data/lib/itamae-spec/generators/templates/cookbook/recipes/files/.keep +0 -0
  18. data/lib/itamae-spec/generators/templates/cookbook/recipes/templates/.keep +0 -0
  19. data/lib/itamae-spec/generators/templates/cookbook/spec/default_spec.rb +0 -0
  20. data/lib/itamae-spec/generators/templates/project/.rspec +2 -0
  21. data/lib/itamae-spec/generators/templates/project/Gemfile +3 -0
  22. data/lib/itamae-spec/generators/templates/project/Project.json +1 -0
  23. data/lib/itamae-spec/generators/templates/project/Rakefile +9 -0
  24. data/lib/itamae-spec/generators/templates/project/cookbooks/sample/attributes/.keep +0 -0
  25. data/lib/itamae-spec/generators/templates/project/cookbooks/sample/attributes/default.json +5 -0
  26. data/lib/itamae-spec/generators/templates/project/cookbooks/sample/recipes/default.rb +7 -0
  27. data/lib/itamae-spec/generators/templates/project/cookbooks/sample/recipes/files/.keep +0 -0
  28. data/lib/itamae-spec/generators/templates/project/cookbooks/sample/recipes/templates/.keep +0 -0
  29. data/lib/itamae-spec/generators/templates/project/cookbooks/sample/spec/default_spec.rb +9 -0
  30. data/lib/itamae-spec/generators/templates/project/environments/.keep +0 -0
  31. data/lib/itamae-spec/generators/templates/project/environments/sample.json +7 -0
  32. data/lib/itamae-spec/generators/templates/project/keys/.keep +0 -0
  33. data/lib/itamae-spec/generators/templates/project/nodes/.keep +0 -0
  34. data/lib/itamae-spec/generators/templates/project/nodes/sample.json +10 -0
  35. data/lib/itamae-spec/generators/templates/project/roles/.keep +0 -0
  36. data/lib/itamae-spec/generators/templates/project/roles/sample.json +5 -0
  37. data/lib/itamae-spec/generators/templates/project/spec/spec_helper.rb +41 -0
  38. data/lib/itamae-spec/generators/templates/project/tmp-nodes/.keep +0 -0
  39. data/lib/itamae-spec/logger.rb +76 -0
  40. data/lib/itamae-spec/resource.rb +2 -0
  41. data/lib/itamae-spec/resource/http_request.rb +71 -0
  42. data/lib/itamae-spec/resource/s3_file.rb +31 -0
  43. data/lib/itamae-spec/task/base.rb +90 -0
  44. data/lib/itamae-spec/task/base_task.rb +148 -0
  45. data/lib/itamae-spec/task/itamae_task.rb +112 -0
  46. data/lib/itamae-spec/task/local_itamae_task.rb +84 -0
  47. data/lib/itamae-spec/task/local_serverspec_task.rb +125 -0
  48. data/lib/itamae-spec/task/serverspec_task.rb +111 -0
  49. data/lib/itamae-spec/version.rb +3 -0
  50. data/lib/itamae-spec/version.txt +1 -0
  51. data/spec/integration/Vagrantfile +35 -0
  52. data/spec/integration/default_spec.rb +226 -0
  53. data/spec/integration/recipes/default.rb +423 -0
  54. data/spec/integration/recipes/default2.rb +6 -0
  55. data/spec/integration/recipes/define/default.rb +6 -0
  56. data/spec/integration/recipes/define/files/remote_file_in_definition +1 -0
  57. data/spec/integration/recipes/dry_run.rb +6 -0
  58. data/spec/integration/recipes/files/remote_file_auto +1 -0
  59. data/spec/integration/recipes/hello.erb +6 -0
  60. data/spec/integration/recipes/hello.txt +1 -0
  61. data/spec/integration/recipes/included.rb +9 -0
  62. data/spec/integration/recipes/node.json +3 -0
  63. data/spec/integration/recipes/redefine.rb +20 -0
  64. data/spec/integration/recipes/templates/template_auto.erb +6 -0
  65. data/spec/integration/spec_helper.rb +42 -0
  66. data/spec/unit/lib/itamae/backend_spec.rb +95 -0
  67. data/spec/unit/lib/itamae/handler/base_spec.rb +34 -0
  68. data/spec/unit/lib/itamae/handler/fluentd_spec.rb +19 -0
  69. data/spec/unit/lib/itamae/handler_proxy_spec.rb +38 -0
  70. data/spec/unit/lib/itamae/handler_spec.rb +11 -0
  71. data/spec/unit/lib/itamae/node_spec.rb +14 -0
  72. data/spec/unit/lib/itamae/recipe_spec.rb +6 -0
  73. data/spec/unit/lib/itamae/resource/base_spec.rb +127 -0
  74. data/spec/unit/lib/itamae/resource_spec.rb +23 -0
  75. data/spec/unit/lib/itamae/runner_spec.rb +32 -0
  76. data/spec/unit/spec_helper.rb +23 -0
  77. metadata +315 -0
@@ -0,0 +1,84 @@
1
+ require 'itamae-spec/task/base_task'
2
+
3
+ module ItamaeSpec
4
+ module Task
5
+ class LocalItamaeTask < BaseTask
6
+ def create_itamae_command(node_name, hash)
7
+ command = 'bundle exec itamae-spec local'
8
+ command << " -j tmp-nodes/#{node_name}.json"
9
+
10
+ hash[:environments][:shell] = ENV['shell'] if ENV['shell']
11
+ command << if hash[:environments][:shell]
12
+ " --shell=#{hash[:environments][:shell]}"
13
+ else
14
+ ' --shell=bash'
15
+ end
16
+
17
+ command << ' --dry-run' if ENV['dry-run'] == 'true'
18
+ command << ' --log-level=debug' if ENV['debug'] == 'true'
19
+ command
20
+ end
21
+
22
+ Itamae.logger.formatter.colored = true
23
+ task = LocalItamaeTask.new
24
+
25
+ namespace :local_itamae do
26
+ all = []
27
+
28
+ Dir.glob('nodes/**/*.json').each do |node_file|
29
+ begin
30
+ node_name = File.basename(node_file, '.json')
31
+ node = task.load_node_attributes(node_file)
32
+ node_short = node[:environments][:hostname].split('.')[0]
33
+ rescue => e
34
+ Itamae.logger.error e.inspect
35
+ Itamae.logger.info "From node file: #{node_file}"
36
+ exit 2
37
+ end
38
+
39
+ all << node_short
40
+ desc 'Itamae local to all nodes'
41
+ task 'all' => all
42
+
43
+ desc "Itamae local to #{node_name}"
44
+ task node_short do
45
+ Itamae.logger.color(:cyan) do
46
+ Itamae.logger.info "Start local_itamae_task to #{node[:environments][:hostname]}"
47
+ end
48
+
49
+ begin
50
+ run_list = task.load_run_list(node_file)
51
+ environments = task.load_environments(node)
52
+ recipe_attributes_list = task.load_recipe_attributes(run_list)
53
+
54
+ merged_recipe = task.merge_attributes(recipe_attributes_list)
55
+ merged_environments = task.merge_attributes(merged_recipe, environments)
56
+ attributes = task.merge_attributes(merged_environments, node)
57
+ task.create_tmp_nodes(node_name, attributes)
58
+
59
+ command = task.create_itamae_command(node_name, attributes)
60
+ command_recipe = task.list_recipe_filepath(run_list)
61
+ command_recipe.sort_by! {|item| File.dirname(item) }
62
+ command << command_recipe.join
63
+
64
+ task.runner_display(attributes[:run_list], run_list, command)
65
+ st = system command
66
+ if st
67
+ Itamae.logger.color(:green) do
68
+ Itamae.logger.info 'local_itamae_task is completed.'
69
+ end
70
+ else
71
+ Itamae.logger.error 'local_itamae_task is failed.'
72
+ exit 1
73
+ end
74
+ rescue => e
75
+ Itamae.logger.error e.inspect
76
+ Itamae.logger.info "From node file: #{node_file}"
77
+ exit 2
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,125 @@
1
+ require 'itamae-spec/task/base_task'
2
+
3
+ module ItamaeSpec
4
+ module Task
5
+ class LocalServerspecTask < BaseTask
6
+ ChangeTargetError = Class.new(StandardError)
7
+ LoadSpecError = Class.new(StandardError)
8
+
9
+ def create_spec_command(node_name, hash)
10
+ ENV['TARGET_HOST'] = if hash[:environments][:local_ipv4].nil?
11
+ hash[:environments][:hostname]
12
+ else
13
+ hash[:environments][:local_ipv4]
14
+ end
15
+
16
+ ENV['NODE_FILE'] = "tmp-nodes/#{node_name}.json"
17
+ ENV['SUDO_PASSWORD'] = hash[:environments][:sudo_password]
18
+ ENV['LOCAL_MODE'] = 'enable local mode'
19
+
20
+ command = 'bundle exec rspec'
21
+ end
22
+
23
+ def list_recipe_filepath(run_list)
24
+ recipes = []
25
+ run_list.each do |recipe|
26
+ target_list = Dir.glob("cookbooks/#{recipe.keys.join}/spec/#{recipe.values.join}_spec.rb")
27
+
28
+ raise LoadSpecError, "#{recipe.to_a.join('::')} cookbook or spec does not exist." if target_list.empty?
29
+
30
+ target_list.each do |target|
31
+ recipes << " #{target}"
32
+ end
33
+ end
34
+
35
+ recipes
36
+ end
37
+
38
+ Itamae.logger.formatter.colored = true
39
+ task = LocalServerspecTask.new
40
+
41
+ namespace :local_spec do
42
+ all = []
43
+
44
+ begin
45
+ project = { project: ARGV[1] }
46
+
47
+ if (ARGV[0] == '-T' || ARGV[0] == '--tasks') && !project[:project].nil?
48
+ unless Dir.exist?("nodes/#{project[:project]}")
49
+ raise ChangeTargetError, "'#{project[:project]}' project is not exist."
50
+ end
51
+
52
+ File.open 'Project.json', 'w' do |f|
53
+ f.flock File::LOCK_EX
54
+ f.puts project.to_json
55
+ f.flock File::LOCK_UN
56
+ end
57
+
58
+ Itamae.logger.color(:green) do
59
+ Itamae.logger.info "Changed target mode '#{project[:project]}'"
60
+ end
61
+ end
62
+
63
+ resp = JSON.parse(File.read('Project.json'))
64
+ target = resp['project'] << '/**'
65
+ rescue => e
66
+ Itamae.logger.error e.inspect
67
+ exit 2
68
+ end
69
+
70
+ Dir.glob("nodes/#{target}/*.json").each do |node_file|
71
+ begin
72
+ node_name = File.basename(node_file, '.json')
73
+ node = task.load_node_attributes(node_file)
74
+ node_short = node[:environments][:hostname].split('.')[0]
75
+ rescue => e
76
+ Itamae.logger.error e.inspect
77
+ Itamae.logger.info "From node file: #{node_file}"
78
+ exit 2
79
+ end
80
+
81
+ all << node_short
82
+ desc 'Serverspec to all nodes'
83
+ task 'all' => all
84
+
85
+ desc "Serverspec to #{node_name}"
86
+ task node_short do
87
+ Itamae.logger.color(:cyan) do
88
+ Itamae.logger.info "Start local_serverspec_task to #{node[:environments][:hostname]}"
89
+ end
90
+
91
+ begin
92
+ run_list = task.load_run_list(node_file)
93
+ environments = task.load_environments(node)
94
+ recipe_attributes_list = task.load_recipe_attributes(run_list)
95
+
96
+ merged_recipe = task.merge_attributes(recipe_attributes_list)
97
+ merged_environments = task.merge_attributes(merged_recipe, environments)
98
+ attributes = task.merge_attributes(merged_environments, node)
99
+ task.create_tmp_nodes(node_name, attributes)
100
+
101
+ command = task.create_spec_command(node_name, attributes)
102
+ command_recipe = task.list_recipe_filepath(run_list)
103
+ command << command_recipe.join
104
+
105
+ task.runner_display(attributes[:run_list], run_list, command)
106
+ st = system command
107
+ if st
108
+ Itamae.logger.color(:green) do
109
+ Itamae.logger.info 'local_serverspec_task is completed.'
110
+ end
111
+ else
112
+ Itamae.logger.error 'local_serverspec_task is failed.'
113
+ exit 1
114
+ end
115
+ rescue => e
116
+ Itamae.logger.error e.inspect
117
+ Itamae.logger.info "From node file: #{node_file}"
118
+ exit 2
119
+ end
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,111 @@
1
+ require 'itamae-spec/task/base_task'
2
+
3
+ module ItamaeSpec
4
+ module Task
5
+ class ServerspecTask < BaseTask
6
+ ChangeTargetError = Class.new(StandardError)
7
+ LoadSpecError = Class.new(StandardError)
8
+
9
+ def list_recipe_filepath(run_list)
10
+ recipes = []
11
+ run_list.each do |recipe|
12
+ target_list = Dir.glob("cookbooks/#{recipe.keys.join}/spec/#{recipe.values.join}_spec.rb")
13
+
14
+ raise LoadSpecError, "#{recipe.to_a.join('::')} cookbook or spec does not exist." if target_list.empty?
15
+
16
+ target_list.each do |target|
17
+ recipes << " #{target}"
18
+ end
19
+ end
20
+
21
+ recipes
22
+ end
23
+
24
+ Itamae.logger.formatter.colored = true
25
+ task = ServerspecTask.new
26
+
27
+ namespace :spec do
28
+ all = []
29
+
30
+ begin
31
+ project = { project: ARGV[1] }
32
+
33
+ if (ARGV[0] == '-T' || ARGV[0] == '--tasks') && !project[:project].nil?
34
+ unless Dir.exist?("nodes/#{project[:project]}")
35
+ raise ChangeTargetError, "'#{project[:project]}' project is not exist."
36
+ end
37
+
38
+ File.open 'Project.json', 'w' do |f|
39
+ f.flock File::LOCK_EX
40
+ f.puts project.to_json
41
+ f.flock File::LOCK_UN
42
+ end
43
+
44
+ Itamae.logger.color(:green) do
45
+ Itamae.logger.info "Changed target mode '#{project[:project]}'"
46
+ end
47
+ end
48
+
49
+ resp = JSON.parse(File.read('Project.json'))
50
+ target = resp['project'] << '/**'
51
+ rescue => e
52
+ Itamae.logger.error e.inspect
53
+ exit 2
54
+ end
55
+
56
+ Dir.glob("nodes/#{target}/*.json").each do |node_file|
57
+ begin
58
+ node_name = File.basename(node_file, '.json')
59
+ node = task.load_node_attributes(node_file)
60
+ node_short = node[:environments][:hostname].split('.')[0]
61
+ rescue => e
62
+ Itamae.logger.error e.inspect
63
+ Itamae.logger.info "From node file: #{node_file}"
64
+ exit 2
65
+ end
66
+
67
+ all << node_short
68
+ desc 'Serverspec to all nodes'
69
+ task 'all' => all
70
+
71
+ desc "Serverspec to #{node_name}"
72
+ task node_short do
73
+ Itamae.logger.color(:cyan) do
74
+ Itamae.logger.info "Start serverspec_task to #{node[:environments][:hostname]}"
75
+ end
76
+
77
+ begin
78
+ run_list = task.load_run_list(node_file)
79
+ environments = task.load_environments(node)
80
+ recipe_attributes_list = task.load_recipe_attributes(run_list)
81
+
82
+ merged_recipe = task.merge_attributes(recipe_attributes_list)
83
+ merged_environments = task.merge_attributes(merged_recipe, environments)
84
+ attributes = task.merge_attributes(merged_environments, node)
85
+ task.create_tmp_nodes(node_name, attributes)
86
+
87
+ command = task.create_spec_command(node_name, attributes)
88
+ command_recipe = task.list_recipe_filepath(run_list)
89
+ command << command_recipe.join
90
+
91
+ task.runner_display(attributes[:run_list], run_list, command)
92
+ st = system command
93
+ if st
94
+ Itamae.logger.color(:green) do
95
+ Itamae.logger.info 'serverspec_task is completed.'
96
+ end
97
+ else
98
+ Itamae.logger.error 'serverspec_task is failed.'
99
+ exit 1
100
+ end
101
+ rescue => e
102
+ Itamae.logger.error e.inspect
103
+ Itamae.logger.info "From node file: #{node_file}"
104
+ exit 2
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,3 @@
1
+ module ItamaeSpec
2
+ VERSION = File.read(File.expand_path("../version.txt", __FILE__)).strip
3
+ end
@@ -0,0 +1 @@
1
+ 0.0.2
@@ -0,0 +1,35 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+ require 'vagrant-digitalocean'
4
+
5
+ # Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
6
+ VAGRANTFILE_API_VERSION = "2"
7
+
8
+ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
9
+ config.vm.define :trusty do |c|
10
+ c.vm.hostname = 'itamae-trusty'
11
+ c.vm.hostname += "-#{ENV['WERCKER_BUILD_ID']}" if ENV['WERCKER_BUILD_ID']
12
+ c.vm.provider :virtualbox do |provider, override|
13
+ override.vm.box = "ubuntu/trusty64"
14
+ override.vm.provision :shell, inline: <<-EOC
15
+ cat /etc/apt/sources.list | sed -e 's|http://[^ ]*|mirror://mirrors.ubuntu.com/mirrors.txt|g' > /tmp/sources.list
16
+ if !(diff -q /etc/apt/sources.list /tmp/sources.list); then
17
+ mv /tmp/sources.list /etc/apt/sources.list
18
+ apt-get update
19
+ fi
20
+ EOC
21
+ end
22
+
23
+ c.vm.provider :digital_ocean do |provider, override|
24
+ override.ssh.private_key_path = '~/.ssh/id_rsa.vagrant'
25
+ override.vm.box = 'digital_ocean'
26
+ override.vm.box_url = "https://github.com/smdahlen/vagrant-digitalocean/raw/master/box/digital_ocean.box"
27
+
28
+ provider.ssh_key_name = ENV['WERCKER'] ? 'vagrant/wercker/itamae' : 'Vagrant'
29
+ provider.token = ENV['DIGITALOCEAN_TOKEN']
30
+ provider.image = 'ubuntu-14-04-x64' # ubuntu
31
+ provider.region = 'nyc3'
32
+ provider.size = '512mb'
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,226 @@
1
+ require 'spec_helper'
2
+
3
+ describe user("itamae") do
4
+ it { should exist }
5
+ it { should have_uid 1234 }
6
+ it { should have_home_directory '/home/itamae' }
7
+ it { should have_login_shell '/bin/dash' }
8
+ end
9
+
10
+ describe file('/tmp/included_recipe') do
11
+ it { should be_file }
12
+ end
13
+
14
+ describe package('dstat') do
15
+ it { should be_installed }
16
+ end
17
+
18
+ describe package('sl') do
19
+ it { should be_installed }
20
+ end
21
+
22
+ describe package('resolvconf') do
23
+ it { should_not be_installed }
24
+ end
25
+
26
+ %w!/tmp/remote_file /tmp/remote_file_auto!.each do |f|
27
+ describe file(f) do
28
+ it { should be_file }
29
+ its(:content) { should match(/Hello Itamae/) }
30
+ end
31
+ end
32
+
33
+ describe file('/tmp/directory') do
34
+ it { should be_directory }
35
+ it { should be_mode 700 }
36
+ it { should be_owned_by "itamae" }
37
+ it { should be_grouped_into "itamae" }
38
+ end
39
+
40
+ describe file('/tmp/directory_never_exist1') do
41
+ it { should_not be_directory }
42
+ end
43
+
44
+ %w!/tmp/template /tmp/template_auto!.each do |f|
45
+ describe file(f) do
46
+ it { should be_file }
47
+ its(:content) { should match(/Hello/) }
48
+ its(:content) { should match(/Good bye/) }
49
+ its(:content) { should match(/^total memory: \d+kB$/) }
50
+ its(:content) { should match(/^uninitialized node key: $/) }
51
+ end
52
+ end
53
+
54
+ describe file('/tmp/file') do
55
+ it { should be_file }
56
+ its(:content) { should match(/Hello World/) }
57
+ it { should be_mode 777 }
58
+ end
59
+
60
+ describe file('/tmp/execute') do
61
+ it { should be_file }
62
+ its(:content) { should match(/Hello Execute/) }
63
+ end
64
+
65
+ describe file('/tmp/never_exist1') do
66
+ it { should_not be_file }
67
+ end
68
+
69
+ describe file('/tmp/never_exist2') do
70
+ it { should_not be_file }
71
+ end
72
+
73
+ describe file('/tmp/http_request.html') do
74
+ it { should be_file }
75
+ its(:content) { should match(/"from": "itamae"/) }
76
+ end
77
+
78
+ describe file('/tmp/http_request_delete.html') do
79
+ it { should be_file }
80
+ its(:content) { should match(/"from": "itamae"/) }
81
+ end
82
+
83
+ describe file('/tmp/http_request_post.html') do
84
+ it { should be_file }
85
+ its(:content) do
86
+ should match(/"from": "itamae"/)
87
+ should match(/"love": "sushi"/)
88
+ end
89
+ end
90
+
91
+ describe file('/tmp/http_request_put.html') do
92
+ it { should be_file }
93
+ its(:content) do
94
+ should match(/"from": "itamae"/)
95
+ should match(/"love": "sushi"/)
96
+ end
97
+ end
98
+
99
+ describe file('/tmp/http_request_headers.html') do
100
+ it { should be_file }
101
+ its(:content) { should match(/"User-Agent": "Itamae"/) }
102
+ end
103
+
104
+ describe file('/tmp/http_request_redirect.html') do
105
+ it { should be_file }
106
+ its(:content) { should match(/"from": "itamae"/) }
107
+ end
108
+
109
+ describe file('/tmp/notifies') do
110
+ it { should be_file }
111
+ its(:content) { should eq("2431") }
112
+ end
113
+
114
+ describe file('/tmp/subscribes') do
115
+ it { should be_file }
116
+ its(:content) { should eq("2431") }
117
+ end
118
+
119
+ describe file('/tmp/cron_stopped') do
120
+ it { should be_file }
121
+ its(:content) do
122
+ expect(subject.content.lines.size).to eq 1
123
+ end
124
+ end
125
+
126
+ describe file('/tmp/cron_running') do
127
+ it { should be_file }
128
+ its(:content) do
129
+ expect(subject.content.lines.size).to eq 2
130
+ end
131
+ end
132
+
133
+ describe file('/tmp-link') do
134
+ it { should be_linked_to '/tmp' }
135
+ its(:content) do
136
+ expect(subject.content.lines.size).to eq 0
137
+ end
138
+ end
139
+
140
+ describe file('/tmp-link-force') do
141
+ it { should be_linked_to '/tmp' }
142
+ end
143
+
144
+ describe command('cd /tmp/git_repo && git rev-parse HEAD') do
145
+ its(:stdout) { should match(/3116e170b89dc0f7315b69c1c1e1fd7fab23ac0d/) }
146
+ end
147
+
148
+ describe command('cd /tmp/git_repo_submodule/empty_repo && cat README.md') do
149
+ its(:stdout) { should match(/Empty Repo/) }
150
+ end
151
+
152
+ describe file('/tmp/created_by_itamae_user') do
153
+ it { should be_file }
154
+ it { should be_owned_by 'itamae' }
155
+ its(:content) { should eq("/home/itamae\n/home/itamae") }
156
+ end
157
+
158
+ describe file('/tmp/created_in_default2') do
159
+ it { should be_file }
160
+ end
161
+
162
+ describe file('/tmp/never_exist3') do
163
+ it { should_not be_file }
164
+ end
165
+
166
+ describe file('/tmp/never_exist4') do
167
+ it { should_not be_file }
168
+ end
169
+
170
+ describe file('/tmp/created_in_redefine') do
171
+ it { should be_file }
172
+ its(:content) { should match(/first/) }
173
+ end
174
+
175
+ describe command('gem list') do
176
+ its(:stdout) { should include('tzinfo (1.2.2, 1.1.0)') }
177
+ end
178
+
179
+ describe command('ri Bundler') do
180
+ its(:stderr) { should eq("Nothing known about Bundler\n") }
181
+ end
182
+
183
+ describe file('/tmp/created_by_definition') do
184
+ it { should be_file }
185
+ its(:content) { should eq("name:name,key:value,message:Hello, Itamae\n") }
186
+ end
187
+
188
+ describe file('/tmp/remote_file_in_definition') do
189
+ it { should be_file }
190
+ its(:content) { should eq("definition_example\n") }
191
+ end
192
+
193
+ describe file('/tmp/multi_delayed_notifies') do
194
+ it { should be_file }
195
+ its(:content) { should eq("1\n2\n3\n4\n") }
196
+ end
197
+
198
+ describe file('/tmp/multi_immediately_notifies') do
199
+ it { should be_file }
200
+ its(:content) { should eq("1\n2\n3\n4\n") }
201
+ end
202
+
203
+ describe file('/tmp/file_edit_sample') do
204
+ it { should be_file }
205
+ its(:content) { should eq("Hello, Itamae") }
206
+ it { should be_mode 400 }
207
+ it { should be_owned_by "itamae2" }
208
+ it { should be_grouped_into "itamae2" }
209
+ end
210
+
211
+ describe file('/home/itamae2') do
212
+ it { should be_directory }
213
+ it { should be_owned_by "itamae2" }
214
+ it { should be_grouped_into "itamae2" }
215
+ end
216
+
217
+ describe file('/tmp/file_create_without_content') do
218
+ its(:content) { should eq("Hello, World") }
219
+ it { should be_mode 600 }
220
+ it { should be_owned_by "itamae" }
221
+ it { should be_grouped_into "itamae" }
222
+ end
223
+
224
+ describe file('/tmp/file_edit_notifies') do
225
+ its(:content) { should eq("1") }
226
+ end