right_link 5.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (199) hide show
  1. data/actors/agent_manager.rb +88 -0
  2. data/actors/instance_scheduler.rb +321 -0
  3. data/actors/instance_services.rb +64 -0
  4. data/actors/instance_setup.rb +567 -0
  5. data/bin/cloud +25 -0
  6. data/bin/cook_runner +44 -0
  7. data/bin/deploy +120 -0
  8. data/bin/enroll +385 -0
  9. data/bin/rad +32 -0
  10. data/bin/rchk +29 -0
  11. data/bin/rnac +39 -0
  12. data/bin/rs_connect +33 -0
  13. data/bin/rs_log_level +31 -0
  14. data/bin/rs_ohai +28 -0
  15. data/bin/rs_reenroll +31 -0
  16. data/bin/rs_run_recipe +34 -0
  17. data/bin/rs_run_right_script +34 -0
  18. data/bin/rs_shutdown +33 -0
  19. data/bin/rs_tag +33 -0
  20. data/bin/rs_thunk +33 -0
  21. data/bin/rstat +31 -0
  22. data/bin/system +16 -0
  23. data/ext/Rakefile +18 -0
  24. data/init/config.yml +5 -0
  25. data/init/init.rb +79 -0
  26. data/lib/chef/ohai_setup.rb +51 -0
  27. data/lib/chef/plugins/cloud.rb +91 -0
  28. data/lib/chef/plugins/cloudstack.rb +23 -0
  29. data/lib/chef/plugins/ec2.rb +23 -0
  30. data/lib/chef/plugins/linux/block_device2.rb +24 -0
  31. data/lib/chef/plugins/rackspace.rb +23 -0
  32. data/lib/chef/plugins/rightscale.rb +125 -0
  33. data/lib/chef/plugins/windows/network.rb +114 -0
  34. data/lib/chef/plugins.rb +74 -0
  35. data/lib/chef/providers/dns_dnsmadeeasy_provider.rb +81 -0
  36. data/lib/chef/providers/dns_resource.rb +100 -0
  37. data/lib/chef/providers/executable_schedule_provider.rb +70 -0
  38. data/lib/chef/providers/executable_schedule_resource.rb +144 -0
  39. data/lib/chef/providers/remote_recipe_provider.rb +86 -0
  40. data/lib/chef/providers/remote_recipe_resource.rb +101 -0
  41. data/lib/chef/providers/right_link_tag_provider.rb +73 -0
  42. data/lib/chef/providers/right_link_tag_resource.rb +59 -0
  43. data/lib/chef/providers/right_script_provider.rb +190 -0
  44. data/lib/chef/providers/right_script_resource.rb +113 -0
  45. data/lib/chef/providers/rs_shutdown_provider.rb +75 -0
  46. data/lib/chef/providers/rs_shutdown_resource.rb +55 -0
  47. data/lib/chef/providers/server_collection_provider.rb +66 -0
  48. data/lib/chef/providers/server_collection_resource.rb +93 -0
  49. data/lib/chef/providers/windows/powershell_provider.rb +151 -0
  50. data/lib/chef/providers/windows/powershell_resource.rb +111 -0
  51. data/lib/chef/providers/windows/unsupported_provider.rb +51 -0
  52. data/lib/chef/right_providers.rb +55 -0
  53. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.csproj +104 -0
  54. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.dll-Help.xml +141 -0
  55. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Exceptions.cs +182 -0
  56. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeCommand.cs +58 -0
  57. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeRequest.cs +46 -0
  58. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeResponse.cs +45 -0
  59. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceCommand.cs +58 -0
  60. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceRequest.cs +46 -0
  61. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceResponse.cs +45 -0
  62. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceCommand.cs +58 -0
  63. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceRequest.cs +46 -0
  64. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceResponse.cs +45 -0
  65. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionCommand.cs +178 -0
  66. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionRequest.cs +67 -0
  67. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionResponse.cs +58 -0
  68. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueCommandBase.cs +142 -0
  69. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueRequestBase.cs +64 -0
  70. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueResponseBase.cs +69 -0
  71. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/JsonTransport.cs +110 -0
  72. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeClient.cs +158 -0
  73. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeServer.cs +142 -0
  74. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
  75. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolConstants.cs +55 -0
  76. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolUtilities.cs +77 -0
  77. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ReadMe.txt +53 -0
  78. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeCommand.cs +59 -0
  79. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeRequest.cs +46 -0
  80. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeResponse.cs +58 -0
  81. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceCommand.cs +59 -0
  82. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceRequest.cs +46 -0
  83. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceResponse.cs +40 -0
  84. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceCommand.cs +59 -0
  85. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceRequest.cs +46 -0
  86. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceResponse.cs +40 -0
  87. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueCommandBase.cs +293 -0
  88. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueRequestBase.cs +75 -0
  89. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueResponseBase.cs +45 -0
  90. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Transport.cs +91 -0
  91. data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet.sln +35 -0
  92. data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Program.cs +374 -0
  93. data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
  94. data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/TestChefNodeCmdlet.csproj +65 -0
  95. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Program.cs +136 -0
  96. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Properties/AssemblyInfo.cs +36 -0
  97. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/ReadMe.txt +46 -0
  98. data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/TestNextActionCmdlet.csproj +68 -0
  99. data/lib/chef/windows/bin/Newtonsoft.Json.dll +0 -0
  100. data/lib/chef/windows/chef_node_server.rb +463 -0
  101. data/lib/chef/windows/dynamic_powershell_provider.rb +296 -0
  102. data/lib/chef/windows/pipe_server.rb +283 -0
  103. data/lib/chef/windows/powershell_host.rb +285 -0
  104. data/lib/chef/windows/powershell_pipe_server.rb +136 -0
  105. data/lib/chef/windows/powershell_provider_base.rb +92 -0
  106. data/lib/chef/windows/scripts/run_loop.ps1 +105 -0
  107. data/lib/clouds/cloud.rb +557 -0
  108. data/lib/clouds/cloud_factory.rb +250 -0
  109. data/lib/clouds/cloud_utilities.rb +244 -0
  110. data/lib/clouds/clouds/azure.rb +106 -0
  111. data/lib/clouds/clouds/cloudstack.rb +114 -0
  112. data/lib/clouds/clouds/ec2.rb +113 -0
  113. data/lib/clouds/clouds/eucalyptus.rb +46 -0
  114. data/lib/clouds/clouds/google.rb +102 -0
  115. data/lib/clouds/clouds/none.rb +76 -0
  116. data/lib/clouds/clouds/openstack.rb +30 -0
  117. data/lib/clouds/clouds/rackspace-ng.rb +54 -0
  118. data/lib/clouds/clouds/rackspace.rb +78 -0
  119. data/lib/clouds/clouds/softlayer.rb +91 -0
  120. data/lib/clouds/metadata_formatter.rb +108 -0
  121. data/lib/clouds/metadata_provider.rb +128 -0
  122. data/lib/clouds/metadata_source.rb +87 -0
  123. data/lib/clouds/metadata_sources/certificate_metadata_source.rb +207 -0
  124. data/lib/clouds/metadata_sources/config_drive_metadata_source.rb +129 -0
  125. data/lib/clouds/metadata_sources/file_metadata_source.rb +74 -0
  126. data/lib/clouds/metadata_sources/http_metadata_source.rb +277 -0
  127. data/lib/clouds/metadata_sources/selective_metadata_source.rb +122 -0
  128. data/lib/clouds/metadata_tree_climber.rb +144 -0
  129. data/lib/clouds/metadata_writer.rb +155 -0
  130. data/lib/clouds/metadata_writers/dictionary_metadata_writer.rb +72 -0
  131. data/lib/clouds/metadata_writers/ruby_metadata_writer.rb +76 -0
  132. data/lib/clouds/metadata_writers/shell_metadata_writer.rb +121 -0
  133. data/lib/clouds/register_clouds.rb +34 -0
  134. data/lib/clouds.rb +32 -0
  135. data/lib/gem_dependencies.rb +83 -0
  136. data/lib/git_hooks/commit-msg.rb +7 -0
  137. data/lib/instance/agent_config.rb +168 -0
  138. data/lib/instance/agent_watcher.rb +233 -0
  139. data/lib/instance/audit_cook_stub.rb +104 -0
  140. data/lib/instance/audit_proxy.rb +247 -0
  141. data/lib/instance/bundle_queue.rb +104 -0
  142. data/lib/instance/cook/agent_connection.rb +109 -0
  143. data/lib/instance/cook/audit_logger.rb +165 -0
  144. data/lib/instance/cook/audit_stub.rb +142 -0
  145. data/lib/instance/cook/ca-bundle.crt +2794 -0
  146. data/lib/instance/cook/chef_state.rb +211 -0
  147. data/lib/instance/cook/cook.rb +306 -0
  148. data/lib/instance/cook/cook_state.rb +298 -0
  149. data/lib/instance/cook/cookbook_path_mapping.rb +66 -0
  150. data/lib/instance/cook/cookbook_repo_retriever.rb +190 -0
  151. data/lib/instance/cook/executable_sequence.rb +765 -0
  152. data/lib/instance/cook/external_parameter_gatherer.rb +190 -0
  153. data/lib/instance/cook/repose_downloader.rb +349 -0
  154. data/lib/instance/cook/shutdown_request_proxy.rb +121 -0
  155. data/lib/instance/cook.rb +41 -0
  156. data/lib/instance/downloader.rb +208 -0
  157. data/lib/instance/duplicable.rb +67 -0
  158. data/lib/instance/exceptions.rb +49 -0
  159. data/lib/instance/executable_sequence_proxy.rb +278 -0
  160. data/lib/instance/instance_commands.rb +577 -0
  161. data/lib/instance/instance_state.rb +633 -0
  162. data/lib/instance/json_utilities.rb +102 -0
  163. data/lib/instance/login_manager.rb +533 -0
  164. data/lib/instance/login_user_manager.rb +522 -0
  165. data/lib/instance/message_encoder.rb +118 -0
  166. data/lib/instance/multi_thread_bundle_queue.rb +232 -0
  167. data/lib/instance/operation_context.rb +60 -0
  168. data/lib/instance/options_bag.rb +65 -0
  169. data/lib/instance/payload_formatter.rb +46 -0
  170. data/lib/instance/policy.rb +53 -0
  171. data/lib/instance/policy_audit.rb +100 -0
  172. data/lib/instance/policy_manager.rb +146 -0
  173. data/lib/instance/reenroll_manager.rb +104 -0
  174. data/lib/instance/right_scripts_cookbook.rb +181 -0
  175. data/lib/instance/shutdown_request.rb +221 -0
  176. data/lib/instance/single_thread_bundle_queue.rb +189 -0
  177. data/lib/instance/volume_management.rb +450 -0
  178. data/lib/instance.rb +50 -0
  179. data/lib/repo_conf_generators/apt_conf_generators.rb +106 -0
  180. data/lib/repo_conf_generators/gem_conf_generators.rb +80 -0
  181. data/lib/repo_conf_generators/rightscale_conf_generators.rb +254 -0
  182. data/lib/repo_conf_generators/rightscale_key.pub +17 -0
  183. data/lib/repo_conf_generators/yum_conf_generators.rb +225 -0
  184. data/lib/repo_conf_generators.rb +30 -0
  185. data/lib/run_shell.rb +28 -0
  186. data/scripts/agent_checker.rb +571 -0
  187. data/scripts/agent_controller.rb +247 -0
  188. data/scripts/agent_deployer.rb +148 -0
  189. data/scripts/bundle_runner.rb +336 -0
  190. data/scripts/cloud_controller.rb +176 -0
  191. data/scripts/log_level_manager.rb +142 -0
  192. data/scripts/ohai_runner.rb +33 -0
  193. data/scripts/reenroller.rb +193 -0
  194. data/scripts/server_importer.rb +293 -0
  195. data/scripts/shutdown_client.rb +183 -0
  196. data/scripts/system_configurator.rb +367 -0
  197. data/scripts/tagger.rb +381 -0
  198. data/scripts/thunker.rb +356 -0
  199. metadata +418 -0
@@ -0,0 +1,298 @@
1
+ #
2
+ # Copyright (c) 2009-2011 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ module RightScale
24
+
25
+ # Manages and persists cook process state
26
+ class CookState
27
+ # Dev tags namespace
28
+ DEV_TAG_NAMESPACE = 'rs_agent_dev:'
29
+
30
+ # Cookbook path dev tag namespace and prefix
31
+ COOKBOOK_PATH_TAG = "#{DEV_TAG_NAMESPACE}cookbooks_path"
32
+
33
+ # Breakpoint dev tag namespace and prefix
34
+ BREAKPOINT_TAG = "#{DEV_TAG_NAMESPACE}break_point"
35
+
36
+ # Download once dev tag namespace and prefix
37
+ DOWNLOAD_ONCE_TAG = "#{DEV_TAG_NAMESPACE}download_cookbooks_once"
38
+
39
+ # Log level dev tag namespace and prefix
40
+ LOG_LEVEL_TAG = "#{DEV_TAG_NAMESPACE}log_level"
41
+
42
+ # Path to JSON file where dev state is serialized
43
+ STATE_DIR = RightScale::AgentConfig.agent_state_dir
44
+ STATE_FILE = File.join(STATE_DIR, 'cook_state.js')
45
+
46
+ class << self
47
+ # Reset class state and load persisted state if any
48
+ #
49
+ # === Return
50
+ # true:: Always return true
51
+ def init(reset=false)
52
+ if @state.nil? || reset
53
+ @state = CookState.new
54
+ end
55
+ true
56
+ end
57
+
58
+ private
59
+ # not sure if method_missing is the best way to go to expose
60
+ # our state interface as class methods. If this is not the best
61
+ # approach, then we should look for another...
62
+ def method_missing(method, *args, &block)
63
+ # ensure the state is initialized before calling any methods
64
+ init unless initialized?
65
+ if @state.respond_to?(method)
66
+ @state.send(method, *args, &block)
67
+ else
68
+ super
69
+ end
70
+ end
71
+
72
+ # Was cook state initialized?
73
+ #
74
+ # === Return
75
+ # true:: if logger has been initialized
76
+ # false:: Otherwise
77
+ def initialized?
78
+ defined?(@state) && @state
79
+ end
80
+ end
81
+
82
+ # Reset class state and load persisted state if any
83
+ #
84
+ # === Return
85
+ # true:: Always return true
86
+ def initialize
87
+ # set some defaults
88
+ @has_downloaded_cookbooks = false
89
+ @reboot = false
90
+ @startup_tags = []
91
+ @log_level = Logger::INFO
92
+ @log_file = nil
93
+
94
+ # replace defaults with state on disk
95
+ load_state
96
+
97
+ true
98
+ end
99
+
100
+ attr_reader :log_level, :log_file, :startup_tags
101
+ attr_writer :has_downloaded_cookbooks
102
+
103
+ def has_downloaded_cookbooks?
104
+ !!@has_downloaded_cookbooks
105
+ end
106
+
107
+ # Are we rebooting? (needed for RightScripts)
108
+ #
109
+ # === Return
110
+ # res(Boolean):: Whether this instance was rebooted
111
+ def reboot?
112
+ !!@reboot
113
+ end
114
+
115
+ # Is the instance running in dev mode?
116
+ # dev mode tweaks the behavior of the RightLink agent to help
117
+ # the development of Chef recipes.
118
+ # In dev mode, the log level is always debug.
119
+ #
120
+ # === Return
121
+ # true:: If dev tags are defined on this instance
122
+ # false:: Otherwise
123
+ def dev_mode_enabled?
124
+ !!tag_value(DEV_TAG_NAMESPACE)
125
+ end
126
+
127
+ # Determines the developer log level, if any, which forces and supercedes
128
+ # all other log level configurations.
129
+ #
130
+ # === Return
131
+ # level(Token):: developer log level or nil
132
+ def dev_log_level
133
+ if value = tag_value(LOG_LEVEL_TAG)
134
+ value = value.downcase.to_sym
135
+ value = nil unless [:debug, :info, :warn, :error, :fatal].include?(value)
136
+ end
137
+ value
138
+ end
139
+
140
+ # Path to cookbooks repos directory. Cookbooks are downloaded to
141
+ # this location if and only if it doesn't exist.
142
+ #
143
+ # === Return
144
+ # path(Array):: Dev cookbooks repositories path
145
+ # nil:: Use default cookbook download algorithm
146
+ def cookbooks_path
147
+ path = tag_value(COOKBOOK_PATH_TAG)
148
+ path.split(/, */) if path
149
+ end
150
+
151
+ # Name of first recipe in run list that should not be run
152
+ #
153
+ # === Return
154
+ # recipe(String):: Name of recipe to break execution of sequence on
155
+ def breakpoint
156
+ recipe = tag_value(BREAKPOINT_TAG)
157
+ end
158
+
159
+ # Whether dev cookbooks path should be used instead of standard
160
+ # cookbooks repositories location
161
+ # True if in dev mode and all dev cookbooks repos directories are not empty
162
+ #
163
+ # === Return
164
+ # true:: If dev cookbooks repositories path should be used
165
+ # false:: Otherwise
166
+ def use_cookbooks_path?
167
+ res = !!(paths = cookbooks_path)
168
+ return false unless res
169
+ paths.each do |path|
170
+ res = path && File.directory?(path) && Dir.entries(path) != ['.', '..']
171
+ break unless res
172
+ end
173
+ res
174
+ end
175
+
176
+ # Whether cookbooks should be downloaded
177
+ # False if either a dev cookbooks path is used or the download once
178
+ # flag is set and cookbooks have already been downloaded
179
+ # Note: we know a cookbook is downloaded when this method is called.
180
+ # Make sure this stays true.
181
+ #
182
+ # === Return
183
+ # true:: If cookbooks should be downloaded
184
+ # false:: Otherwise
185
+ def download_cookbooks?
186
+ # always download unless machine is tagged with a valid cookbooks path or
187
+ # machine is tagged with download once and cookbooks have already been downloaded.
188
+ res = !(use_cookbooks_path? || (has_downloaded_cookbooks? && download_once?))
189
+ end
190
+
191
+ # Whether cookbooks should be downloaded only once
192
+ #
193
+ # === Return
194
+ # true:: If cookbooks should be downloaded only once for this instance
195
+ # false:: Otherwise
196
+ def download_once?
197
+ tag_value(DOWNLOAD_ONCE_TAG) == 'true'
198
+ end
199
+
200
+ # Current logger severity
201
+ #
202
+ # === Return
203
+ # level(Integer):: one of Logger::INFO ... Logger::FATAL
204
+ def log_level
205
+ @log_level
206
+ end
207
+
208
+ # Re-initialize then merge given state
209
+ #
210
+ # === Parameters
211
+ # state_to_merge(RightScale::InstanceState):: InstanceState to be passed on to Cook
212
+ # overrides(Hash):: Hash keyed by state name that will override state_to_merge
213
+ #
214
+ # === Return
215
+ # true:: Always
216
+ def update(state_to_merge, overrides = {})
217
+ # only merge state if state to be merged has values
218
+ @startup_tags = state_to_merge.startup_tags if state_to_merge.respond_to?(:startup_tags)
219
+ @reboot = state_to_merge.reboot? if state_to_merge.respond_to?(:reboot?)
220
+ @log_level = state_to_merge.log_level if state_to_merge.respond_to?(:log_level)
221
+ if state_to_merge.respond_to?(:log_file) && state_to_merge.respond_to?(:value)
222
+ @log_file = state_to_merge.log_file(state_to_merge.value)
223
+ end
224
+
225
+ @startup_tags = overrides[:startup_tags] if overrides.has_key?(:startup_tags)
226
+ @reboot = overrides[:reboot] if overrides.has_key?(:reboot)
227
+ @log_file = overrides[:log_file] if overrides.has_key?(:log_file)
228
+
229
+ # check the log level again after the startup_tags have been updated or
230
+ # overridden.
231
+ if overrides.has_key?(:log_level)
232
+ @log_level = overrides[:log_level]
233
+ elsif tagged_log_level = dev_log_level
234
+ @log_level = tagged_log_level
235
+ end
236
+
237
+ save_state
238
+
239
+ true
240
+ end
241
+
242
+ protected
243
+
244
+ # Extract tag value for tag with given namespace and prefix
245
+ #
246
+ # === Parameters
247
+ # prefix(String):: Tag namespace and prefix
248
+ #
249
+ # === Return
250
+ # value(String):: Corresponding tag value
251
+ def tag_value(prefix)
252
+ tag = @startup_tags.detect { |t| t =~ /^#{prefix}/ }
253
+ value = tag[prefix.size + 1..-1] if tag
254
+ end
255
+
256
+ # Save dev state to file
257
+ #
258
+ # === Return
259
+ # true:: Always return true
260
+ def save_state
261
+ # start will al state to be saved
262
+ state_to_save = { 'startup_tags' => startup_tags,
263
+ 'reboot' => reboot?,
264
+ 'log_level' => log_level }
265
+
266
+ # only save a log file one is defined
267
+ if log_file
268
+ state_to_save['log_file'] = log_file
269
+ end
270
+
271
+ # only save persist the fact we downloaded cookbooks if we are in dev mode
272
+ if download_once?
273
+ state_to_save['has_downloaded_cookbooks'] = has_downloaded_cookbooks?
274
+ end
275
+
276
+ RightScale::JsonUtilities::write_json(RightScale::CookState::STATE_FILE, state_to_save)
277
+ true
278
+ end
279
+
280
+ # load dev state from disk
281
+ #
282
+ # === Return
283
+ # true:: Always return true
284
+ def load_state
285
+ if File.file?(STATE_FILE)
286
+ state = RightScale::JsonUtilities::read_json(STATE_FILE)
287
+ @log_level = state['log_level'] || Logger::INFO
288
+ Log.info("Initializing CookState from #{STATE_FILE} with #{state.inspect}") if @log_level == Logger::DEBUG
289
+
290
+ @has_downloaded_cookbooks = state['has_downloaded_cookbooks']
291
+ @startup_tags = state['startup_tags'] || []
292
+ @reboot = state['reboot']
293
+ @log_file = state['log_file'] # nil if not in state loaded from disk
294
+ end
295
+ true
296
+ end
297
+ end
298
+ end
@@ -0,0 +1,66 @@
1
+ #
2
+ # Copyright (c) 2009-2011 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ module RightScale
24
+ # helpers for constructing various paths related to coookbooks
25
+ class CookbookPathMapping
26
+ # Constructs a repose download path for a given cookbook
27
+ #
28
+ # === Parameters
29
+ # repose_root (String):: the root for all cookbooks downloaded with repose
30
+ # repo_sha (String):: unique identifier for the repo containig the cookbook
31
+ # position (String):: the relative path of the cookbook within the repo
32
+ #
33
+ # === Return
34
+ # (String):: full path to the repose download location for the given cookbook
35
+ def self.repose_path(repose_root, repo_sha, position)
36
+ build_path(repose_root, repo_sha, position)
37
+ end
38
+
39
+ # Constructs a cookbook checkout path for a given cookbook
40
+ #
41
+ # === Parameters
42
+ # checkout_root (String):: the root of all checked out cookbooks
43
+ # repo_dir (String):: root directory for all cookbooks in a the repo
44
+ # position (String):: the relative path of the cookbook within the repo
45
+ #
46
+ # === Return
47
+ # (String):: full path to the checked out location for the given cookbook
48
+ def self.checkout_path(repo_dir, position)
49
+ build_path(repo_dir, position)
50
+ end
51
+
52
+ private
53
+ # Combines the given path segments removing un needed separators and missing intermediate
54
+ #
55
+ # === Parameters
56
+ # root (String):: the root of the path
57
+ # sub (String):: middle section of the path
58
+ # leaf (String):: end of the path
59
+ #
60
+ # === Return
61
+ # (String):: cleaned path, empty string is all params are nil
62
+ def self.build_path(root="", sub="", leaf="")
63
+ File.join(*([root || ""] + "#{sub || ""}".split('/') + "#{leaf || ""}".split('/')))
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,190 @@
1
+ #
2
+ # Copyright (c) 2009-2013 RightScale Inc
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+
23
+ require 'right_scraper'
24
+
25
+ module RightScale
26
+ #
27
+ class CookbookRepoRetriever
28
+ attr_reader :checkout_root
29
+
30
+ # Maps the given DevRepository to a has that can be consumed by the RightScraper gem
31
+ # TODO: May make sense for this to a member of the DevRepository class as an instance method.
32
+ # Also, may want to take a version as a parameter in the future (or not...).
33
+ #
34
+ # === Parameters
35
+ # dev_repo (DevRepository):: core representation of a resource repository
36
+ #
37
+ # === Returns
38
+ # (Hash)::
39
+ # :repo_type (Symbol):: Type of repository: one of :git, :svn, :download or :local
40
+ # * :git denotes a 'git' repository that should be retrieved via 'git clone'
41
+ # * :svn denotes a 'svn' repository that should be retrieved via 'svn checkout'
42
+ # * :download denotes a tar ball that should be retrieved via HTTP GET (HTTPS if uri starts with https://)
43
+ # * :local denotes cookbook that is already local and doesn't need to be retrieved
44
+ # :url (String):: URL to repository (e.g. git://github.com/opscode/chef-repo.git)
45
+ # :tag (String):: git commit or svn branch that should be used to retrieve repository
46
+ # Optional, use 'master' for git and 'trunk' for svn if tag is nil.
47
+ # Not used for raw repositories.
48
+ # :cookbooks_path (Array):: Path to cookbooks inside repostory
49
+ # Optional (use location of repository as cookbook path if nil)
50
+ # :first_credential (String):: Either the Private SSH key used to retrieve git repositories, or the Username used to retrieve svn and raw repositories
51
+ # :second_credential (String):: Password used to retrieve svn and raw repositories
52
+ def self.to_scraper_hash(dev_repo)
53
+ repo = {}
54
+ repo[:repo_type] = dev_repo.repo_type.to_sym unless dev_repo.repo_type.nil?
55
+ repo[:url] = dev_repo.url
56
+ repo[:tag] = dev_repo.tag
57
+ repo[:resources_path] = dev_repo.cookbooks_path
58
+ if !dev_repo.ssh_key.nil?
59
+ repo[:first_credential] = dev_repo.ssh_key
60
+ elsif !(dev_repo.username.nil? && dev_repo.password.nil?)
61
+ repo[:first_credential] = dev_repo.username
62
+ repo[:second_credential] = dev_repo.password
63
+ end
64
+
65
+ repo
66
+ end
67
+
68
+ # Initialize...
69
+ #
70
+ # === Parameters
71
+ # repose_root (String):: root of all repose downloaded cookbooks
72
+ # dev_cookbooks (Hash):: collection of repos to be checked out see RightScale::DevRepositories for hash content
73
+ def initialize(repose_root, dev_cookbooks)
74
+ @checkout_root = AgentConfig.dev_cookbook_checkout_dir
75
+ @repose_root = repose_root
76
+ @dev_cookbooks = (dev_cookbooks.nil? || dev_cookbooks.repositories.nil?) ? {} : dev_cookbooks.repositories
77
+ @scraper = RightScraper::Scraper.new(:kind => :cookbook, :basedir => @checkout_root)
78
+ @registered_checkouts = {}
79
+ end
80
+
81
+ # Are there any cookbooks to be checked out?
82
+ #
83
+ # === Returns
84
+ # true if there are cookbooks to be checked out, false otherwise
85
+ def has_cookbooks?
86
+ !@dev_cookbooks.empty?
87
+ end
88
+
89
+ # Should there be a link created for this cookbook?
90
+ #
91
+ # === Parameters
92
+ # repo_sha (String) :: unique identifier of the cookbook repository
93
+ # position (String) :: repo relative ppath of the cookbook
94
+ #
95
+ # === Returns
96
+ # true if there is a cookbook in the given repo that should be checekd out
97
+ def should_be_linked?(repo_sha, position)
98
+ @dev_cookbooks.has_key?(repo_sha) &&
99
+ @dev_cookbooks[repo_sha].positions &&
100
+ @dev_cookbooks[repo_sha].positions.detect { |dev_position| dev_position.position == position }
101
+ end
102
+
103
+ # Was the cookbook checked out?
104
+ #
105
+ # === Parameters
106
+ # repo_sha (String) :: unique identifier of the cookbook repository
107
+ #
108
+ # === Returns
109
+ # true if the given repo is checekd out
110
+ def is_checked_out?(repo_sha)
111
+ !!repo_dir_for(repo_sha)
112
+ end
113
+
114
+ # Checkout directory for given repository hash.
115
+ #
116
+ # === Parameters
117
+ # @param [String] repo_sha for lookup
118
+ #
119
+ # === Return
120
+ # @return [String] checked-out directory or nil
121
+ def repo_dir_for(repo_sha)
122
+ @registered_checkouts[repo_sha]
123
+ end
124
+
125
+ # Checkout the given repo and link each dev cookbook to it's matching repose path
126
+ #
127
+ # === Parameters
128
+ # callback (Proc) :: to be called for each repo checked out see RightScraper::Scraper.scrape for details
129
+ #
130
+ # === Return
131
+ # true
132
+ def checkout_cookbook_repos(&callback)
133
+ @dev_cookbooks.each_pair do |repo_sha, dev_repo|
134
+ repo = self.class.to_scraper_hash(dev_repo)
135
+
136
+ # get the root dir this repo should be, or was, checked out to
137
+ repo_dir = @scraper.repo_dir(repo)
138
+
139
+ if File.directory?(repo_dir)
140
+ # repo was already checked out on this machine; leave it alone
141
+ # synthesize a scraper callback so our progress listener knows what's up
142
+ if callback
143
+ callback.call(:commit, :initialize, "Skipping checkout -- repository already exists in #{repo_dir}", nil)
144
+ end
145
+ @registered_checkouts[repo_sha] = repo_dir
146
+ else
147
+ # repo wasn't checked out successfully yet; check it out now
148
+ success = false
149
+ begin
150
+ success = @scraper.scrape(repo, &callback)
151
+ ensure
152
+ if success
153
+ @registered_checkouts[repo_sha] = repo_dir
154
+ else
155
+ # nuke the repo dir if checkout fails, so we try again next time
156
+ FileUtils.rm_rf(repo_dir) unless success
157
+
158
+ # scraper logger is an odd duck, so just transfer any errors to
159
+ # the normal logger.
160
+ @scraper.errors.each { |e| ::RightScale::Log.error(e) }
161
+ ::RightScale::Log.error("Failed to checkout from #{repo[:url].inspect}")
162
+ end
163
+ end
164
+ end
165
+ end
166
+ true
167
+ end
168
+
169
+ # Creates a symlink from the checked out cookbook to the expected repose download location
170
+ #
171
+ # === Parameters
172
+ # repo_sha (String) :: unique identifier of the cookbook repository
173
+ # position (String) :: repo relative ppath of the cookbook
174
+ #
175
+ # === Returns
176
+ # true if link was created, false otherwise
177
+ def link(repo_sha, position)
178
+ # symlink to the checked out cookbook only if it was actually checked out
179
+ if repo_dir = @registered_checkouts[repo_sha]
180
+ checkout_path = CookbookPathMapping.checkout_path(repo_dir, position)
181
+ raise ArgumentError.new("Missing directory cannot be linked: #{checkout_path}") unless File.directory?(checkout_path)
182
+ repose_path = CookbookPathMapping.repose_path(@repose_root, repo_sha, position)
183
+ FileUtils.mkdir_p(File.dirname(repose_path))
184
+ Platform.filesystem.create_symlink(checkout_path, repose_path)
185
+ return true
186
+ end
187
+ false
188
+ end
189
+ end
190
+ end