right_link 5.9.0

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 (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