chef-solo-wrapper 0.0.1

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 (2) hide show
  1. data/bin/cs +198 -0
  2. metadata +65 -0
data/bin/cs ADDED
@@ -0,0 +1,198 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # chef-solo-wrapper (cs)
4
+ #
5
+ # Copyright 2011, Chris Fordham
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You 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 implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ CHEF_SOLO_WRAPPER_VERSION = '0.0.1'
20
+
21
+ require 'rubygems'
22
+ require 'trollop'
23
+ require 'json'
24
+
25
+ opts = Trollop::options do
26
+ version 'chef-solo-wrapper '+CHEF_SOLO_WRAPPER_VERSION+' (c) 2011 Chris Fordham'
27
+ banner <<-EOS
28
+ A CLI wrapper for Chef Solo w/ RightScale integration.
29
+
30
+ Usage:
31
+ cs [options]
32
+ where [options] are:
33
+ EOS
34
+ opt :server, "Use attribute data from a RightScale server by nickname or ID.", :short => "-s", :type => String # flag --server, default false
35
+ opt :sandbox, "Use the Ruby environment in the local RightLink sandbox." # flag --sandbox, default false
36
+ opt :config, "Use alternate Chef Solo configuration (default used, ~/solo.rb.)", :short => "-c" # flag --config, default false
37
+ opt :json, "Use alternate Chef Solo JSON data (default used, ~/node.json.)", :short => "-j", :type => String # flag --json, default false
38
+ opt :dry, "Dry run only, don't run chef-solo.", :short => "-d" # flag --dry, default false
39
+ opt :run, "Use alernative run_list for chef-solo run.", :short => "-r", :type => String # flag --run, default false
40
+ opt :write, "Write back to local JSON file.", :short => "-w" # flag --write, default false
41
+ opt :loglevel, "The Chef log level to use: debug, info, warn, error, fatal", :short => "-l", :default => "info", :type => String # flag --loglevel, default info
42
+ opt :verbose, "Verbose mode.", :short => "-v" # flag --verbose, default false
43
+ opt :debug, "Debug mode." # flag --debug, default faulse
44
+ opt :help, "Print usage info and exit.", :short => "-h"
45
+ end
46
+ puts "options: #{opts.to_json}" unless !(opts.verbose || opts.debug and !opts.help)
47
+ puts 'chef-solo-wrapper '+CHEF_SOLO_WRAPPER_VERSION
48
+
49
+ solo = false
50
+ server = false
51
+
52
+ # ensure a solo.rb exists for run
53
+ if File.file?('/etc/chef/solo.rb')
54
+ solo = '/etc/chef/solo.rb'
55
+ else
56
+ puts ' DEBUG: /etc/chef/solo.rb: not found.' unless !opts.debug
57
+ end
58
+ if File.file?("#{ENV['HOME']}/solo.rb")
59
+ solo = "#{ENV['HOME']}/solo.rb"
60
+ else
61
+ puts ' DEBUG: ~/solo.rb: not found.' unless !opts.debug
62
+ end
63
+ unless solo
64
+ puts 'FATAL: No solo.rb file found (see http://wiki.opscode.com/display/chef/Chef+Solo), exiting.'
65
+ exit 1
66
+ else
67
+ puts "==> Using #{solo}." unless !opts.debug
68
+ if File.zero?(solo) then
69
+ puts "FATAL: #{solo} is empty, exiting."
70
+ exit 1
71
+ end
72
+ puts File.new(solo, 'r').read unless !opts.debug
73
+ end
74
+
75
+ # get json if available
76
+ if opts.json
77
+ attributes = File.new(opts.json, "r").read
78
+ else
79
+ if File.file?('/etc/chef/node.json')
80
+ node_file = '/etc/chef/node.json'
81
+ attributes = JSON.parse(File.new(node_file, "r").read)
82
+ elsif File.file?("#{File.expand_path('~')}/node.json")
83
+ node_file = "#{File.expand_path('~')}/node.json"
84
+ attributes = JSON.parse(File.new("#{File.expand_path('~')}/node.json", "r").read)
85
+ else
86
+ node_file = "#{File.expand_path('~')}/node.json"
87
+ attributes = JSON.parse("{\n}\n")
88
+ end
89
+ chef_json = " -j #{node_file}"
90
+ end
91
+
92
+ # when a rs server is specified
93
+ if opts.server
94
+
95
+ # import rest_connection
96
+ puts 'Importing RestConnection RubyGem.' unless !opts.verbose
97
+ require 'rest_connection'
98
+
99
+ # fetch server via rest_connection
100
+ if opts.server.to_i > 0
101
+ puts "Finding server: #{opts.server}."
102
+ server = Server.find(opts.server.to_i)
103
+ else
104
+ puts "Finding server: '%#{opts.server}%'"
105
+ server = Server.find(:first) { |s| s.nickname =~ /#{opts.server}/ }
106
+ end
107
+ puts "Found server, '#{server.nickname}'."
108
+ puts server.to_yaml unless !opts.verbose
109
+
110
+ # get current instance of server
111
+ server.reload_current
112
+ puts JSON.pretty_generate(server.settings) unless !opts.debug
113
+
114
+ # assign inputs from server params
115
+ inputs = server.parameters
116
+ puts " DEBUG: #{JSON.pretty_generate(inputs)}" unless !opts.debug
117
+ server_attributes = Hash.new
118
+ inputs.each { |input,v|
119
+ if inputs.to_s =~ /^[A-Z]+$/
120
+ puts " DEBUG: right_script input #{k} discarded." unless !opts.debug
121
+ else
122
+ puts " DEBUG: #{input} => #{v}" unless !opts.debug
123
+ keys = input.split("/")
124
+ if keys.count == 2
125
+ type = v.split(':')[0]
126
+ value = v.split(':')[1]
127
+ value = '' unless value != "$ignore"
128
+ if keys[0] != 'rightscale'
129
+ puts " DEBUG: node attribute #{keys[1]} detected for cookbook, #{keys[0]}." unless !opts.debug
130
+ puts " DEBUG: attribute:#{keys[0]}[\"#{keys[1]}\"] type:#{type} value:#{value}" unless !opts.debug
131
+ puts " DEBUG: [#{keys[0]}][#{keys[1]}] => type: #{type}" unless !opts.debug
132
+ puts " DEBUG: [#{keys[0]}][#{keys[1]}] => value: #{value}" unless !opts.debug
133
+ server_attributes["#{keys[0]}"] = {} unless server_attributes["#{keys[0]}"]
134
+ server_attributes["#{keys[0]}"]["#{keys[1]}"] = "#{value}"
135
+ end
136
+ end
137
+ end
138
+ }
139
+ puts " DEBUG:\n#{p server_attributes}" unless !opts.debug
140
+
141
+ end
142
+
143
+ if server_attributes
144
+ puts server_attributes.to_json
145
+ puts ' DEBUG: Merging attributes.' unless !opts.debug
146
+ attributes = server_attributes.merge(attributes)
147
+ else
148
+ puts ' DEBUG: No server attributes to merge.' unless !opts.debug
149
+ end
150
+
151
+ if opts.run
152
+ # override runlist
153
+ attributes['run_list'] = "#{opts.run}"
154
+ end
155
+
156
+ # write attributes back to local node.json
157
+ if opts.write and server_attributes
158
+ node_json = JSON.pretty_generate(attributes)
159
+ puts "Node Attributes: \n #{node_json}" unless !opts.debug
160
+ # open file for write back
161
+ fh = File.new(node_file, "w")
162
+ fh.write(node_json)
163
+ fh.close
164
+ end
165
+
166
+ # prepare options
167
+ chef_config = " -c #{opts.config}" unless !opts.config
168
+ chef_json = " -j #{opts.json}" unless !opts.json
169
+
170
+ # depict if sandbox chef-solo binary is used
171
+ if opts.sandbox
172
+ cs = '/opt/rightscale/sandbox/bin/chef-solo'
173
+ else
174
+ cs = 'chef-solo'
175
+ end
176
+
177
+ # build chef solo command
178
+ cmd = "#{cs}#{chef_config}#{chef_json} --log_level #{opts.loglevel} || ( echo 'Chef run failed!'; cat /var/chef-solo/chef-stacktrace.out; exit 1 )"
179
+ puts " DEBUG: running #{cmd}" unless !opts.debug
180
+
181
+ # import chef
182
+ puts 'Importing Chef RubyGem.' unless !opts.verbose
183
+ require 'chef'
184
+
185
+ # prepend sudo if not run as root
186
+ if Process.uid != 0
187
+ cmd.insert(0, 'sudo ')
188
+ puts " DEBUG: Non-root user, appending sudo (#{cmd})." unless !opts.debug
189
+ end
190
+
191
+ # finally, run chef-solo
192
+ puts 'Starting Chef Solo.' unless !(opts.verbose || opts.debug)
193
+ unless opts.dry
194
+ system(cmd)
195
+ else
196
+ puts 'Dry run only, exiting.'
197
+ exit
198
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chef-solo-wrapper
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Chris Fordham
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-05-29 00:00:00 Z
19
+ dependencies: []
20
+
21
+ description: A basic wrapper for chef-solo with RightScale integration.
22
+ email: chris@xhost.com.au
23
+ executables:
24
+ - cs
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - bin/cs
31
+ homepage: https://github.com/flaccid/chef-solo-wrapper
32
+ licenses: []
33
+
34
+ post_install_message:
35
+ rdoc_options: []
36
+
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ hash: 3
54
+ segments:
55
+ - 0
56
+ version: "0"
57
+ requirements: []
58
+
59
+ rubyforge_project:
60
+ rubygems_version: 1.8.10
61
+ signing_key:
62
+ specification_version: 3
63
+ summary: chef-solo-wrapper
64
+ test_files: []
65
+