right_link 5.9.0
Sign up to get free protection for your applications and to get access to all the features.
- data/actors/agent_manager.rb +88 -0
- data/actors/instance_scheduler.rb +321 -0
- data/actors/instance_services.rb +64 -0
- data/actors/instance_setup.rb +567 -0
- data/bin/cloud +25 -0
- data/bin/cook_runner +44 -0
- data/bin/deploy +120 -0
- data/bin/enroll +385 -0
- data/bin/rad +32 -0
- data/bin/rchk +29 -0
- data/bin/rnac +39 -0
- data/bin/rs_connect +33 -0
- data/bin/rs_log_level +31 -0
- data/bin/rs_ohai +28 -0
- data/bin/rs_reenroll +31 -0
- data/bin/rs_run_recipe +34 -0
- data/bin/rs_run_right_script +34 -0
- data/bin/rs_shutdown +33 -0
- data/bin/rs_tag +33 -0
- data/bin/rs_thunk +33 -0
- data/bin/rstat +31 -0
- data/bin/system +16 -0
- data/ext/Rakefile +18 -0
- data/init/config.yml +5 -0
- data/init/init.rb +79 -0
- data/lib/chef/ohai_setup.rb +51 -0
- data/lib/chef/plugins/cloud.rb +91 -0
- data/lib/chef/plugins/cloudstack.rb +23 -0
- data/lib/chef/plugins/ec2.rb +23 -0
- data/lib/chef/plugins/linux/block_device2.rb +24 -0
- data/lib/chef/plugins/rackspace.rb +23 -0
- data/lib/chef/plugins/rightscale.rb +125 -0
- data/lib/chef/plugins/windows/network.rb +114 -0
- data/lib/chef/plugins.rb +74 -0
- data/lib/chef/providers/dns_dnsmadeeasy_provider.rb +81 -0
- data/lib/chef/providers/dns_resource.rb +100 -0
- data/lib/chef/providers/executable_schedule_provider.rb +70 -0
- data/lib/chef/providers/executable_schedule_resource.rb +144 -0
- data/lib/chef/providers/remote_recipe_provider.rb +86 -0
- data/lib/chef/providers/remote_recipe_resource.rb +101 -0
- data/lib/chef/providers/right_link_tag_provider.rb +73 -0
- data/lib/chef/providers/right_link_tag_resource.rb +59 -0
- data/lib/chef/providers/right_script_provider.rb +190 -0
- data/lib/chef/providers/right_script_resource.rb +113 -0
- data/lib/chef/providers/rs_shutdown_provider.rb +75 -0
- data/lib/chef/providers/rs_shutdown_resource.rb +55 -0
- data/lib/chef/providers/server_collection_provider.rb +66 -0
- data/lib/chef/providers/server_collection_resource.rb +93 -0
- data/lib/chef/providers/windows/powershell_provider.rb +151 -0
- data/lib/chef/providers/windows/powershell_resource.rb +111 -0
- data/lib/chef/providers/windows/unsupported_provider.rb +51 -0
- data/lib/chef/right_providers.rb +55 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.csproj +104 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ChefNodeCmdlet.dll-Help.xml +141 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Exceptions.cs +182 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeCommand.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetChefNodeResponse.cs +45 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceCommand.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetCurrentResourceResponse.cs +45 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceCommand.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNewResourceResponse.cs +45 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionCommand.cs +178 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionRequest.cs +67 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNextActionResponse.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueCommandBase.cs +142 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueRequestBase.cs +64 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/GetNodeValueResponseBase.cs +69 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/JsonTransport.cs +110 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeClient.cs +158 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/PipeServer.cs +142 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolConstants.cs +55 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ProtocolUtilities.cs +77 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/ReadMe.txt +53 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeCommand.cs +59 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetChefNodeResponse.cs +58 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceCommand.cs +59 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetCurrentResourceResponse.cs +40 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceCommand.cs +59 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceRequest.cs +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNewResourceResponse.cs +40 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueCommandBase.cs +293 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueRequestBase.cs +75 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/SetNodeValueResponseBase.cs +45 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet/Transport.cs +91 -0
- data/lib/chef/windows/ChefNodeCmdlet/ChefNodeCmdlet.sln +35 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Program.cs +374 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/Properties/AssemblyInfo.cs +16 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestChefNodeCmdlet/TestChefNodeCmdlet.csproj +65 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Program.cs +136 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/Properties/AssemblyInfo.cs +36 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/ReadMe.txt +46 -0
- data/lib/chef/windows/ChefNodeCmdlet/TestNextActionCmdlet/TestNextActionCmdlet.csproj +68 -0
- data/lib/chef/windows/bin/Newtonsoft.Json.dll +0 -0
- data/lib/chef/windows/chef_node_server.rb +463 -0
- data/lib/chef/windows/dynamic_powershell_provider.rb +296 -0
- data/lib/chef/windows/pipe_server.rb +283 -0
- data/lib/chef/windows/powershell_host.rb +285 -0
- data/lib/chef/windows/powershell_pipe_server.rb +136 -0
- data/lib/chef/windows/powershell_provider_base.rb +92 -0
- data/lib/chef/windows/scripts/run_loop.ps1 +105 -0
- data/lib/clouds/cloud.rb +557 -0
- data/lib/clouds/cloud_factory.rb +250 -0
- data/lib/clouds/cloud_utilities.rb +244 -0
- data/lib/clouds/clouds/azure.rb +106 -0
- data/lib/clouds/clouds/cloudstack.rb +114 -0
- data/lib/clouds/clouds/ec2.rb +113 -0
- data/lib/clouds/clouds/eucalyptus.rb +46 -0
- data/lib/clouds/clouds/google.rb +102 -0
- data/lib/clouds/clouds/none.rb +76 -0
- data/lib/clouds/clouds/openstack.rb +30 -0
- data/lib/clouds/clouds/rackspace-ng.rb +54 -0
- data/lib/clouds/clouds/rackspace.rb +78 -0
- data/lib/clouds/clouds/softlayer.rb +91 -0
- data/lib/clouds/metadata_formatter.rb +108 -0
- data/lib/clouds/metadata_provider.rb +128 -0
- data/lib/clouds/metadata_source.rb +87 -0
- data/lib/clouds/metadata_sources/certificate_metadata_source.rb +207 -0
- data/lib/clouds/metadata_sources/config_drive_metadata_source.rb +129 -0
- data/lib/clouds/metadata_sources/file_metadata_source.rb +74 -0
- data/lib/clouds/metadata_sources/http_metadata_source.rb +277 -0
- data/lib/clouds/metadata_sources/selective_metadata_source.rb +122 -0
- data/lib/clouds/metadata_tree_climber.rb +144 -0
- data/lib/clouds/metadata_writer.rb +155 -0
- data/lib/clouds/metadata_writers/dictionary_metadata_writer.rb +72 -0
- data/lib/clouds/metadata_writers/ruby_metadata_writer.rb +76 -0
- data/lib/clouds/metadata_writers/shell_metadata_writer.rb +121 -0
- data/lib/clouds/register_clouds.rb +34 -0
- data/lib/clouds.rb +32 -0
- data/lib/gem_dependencies.rb +83 -0
- data/lib/git_hooks/commit-msg.rb +7 -0
- data/lib/instance/agent_config.rb +168 -0
- data/lib/instance/agent_watcher.rb +233 -0
- data/lib/instance/audit_cook_stub.rb +104 -0
- data/lib/instance/audit_proxy.rb +247 -0
- data/lib/instance/bundle_queue.rb +104 -0
- data/lib/instance/cook/agent_connection.rb +109 -0
- data/lib/instance/cook/audit_logger.rb +165 -0
- data/lib/instance/cook/audit_stub.rb +142 -0
- data/lib/instance/cook/ca-bundle.crt +2794 -0
- data/lib/instance/cook/chef_state.rb +211 -0
- data/lib/instance/cook/cook.rb +306 -0
- data/lib/instance/cook/cook_state.rb +298 -0
- data/lib/instance/cook/cookbook_path_mapping.rb +66 -0
- data/lib/instance/cook/cookbook_repo_retriever.rb +190 -0
- data/lib/instance/cook/executable_sequence.rb +765 -0
- data/lib/instance/cook/external_parameter_gatherer.rb +190 -0
- data/lib/instance/cook/repose_downloader.rb +349 -0
- data/lib/instance/cook/shutdown_request_proxy.rb +121 -0
- data/lib/instance/cook.rb +41 -0
- data/lib/instance/downloader.rb +208 -0
- data/lib/instance/duplicable.rb +67 -0
- data/lib/instance/exceptions.rb +49 -0
- data/lib/instance/executable_sequence_proxy.rb +278 -0
- data/lib/instance/instance_commands.rb +577 -0
- data/lib/instance/instance_state.rb +633 -0
- data/lib/instance/json_utilities.rb +102 -0
- data/lib/instance/login_manager.rb +533 -0
- data/lib/instance/login_user_manager.rb +522 -0
- data/lib/instance/message_encoder.rb +118 -0
- data/lib/instance/multi_thread_bundle_queue.rb +232 -0
- data/lib/instance/operation_context.rb +60 -0
- data/lib/instance/options_bag.rb +65 -0
- data/lib/instance/payload_formatter.rb +46 -0
- data/lib/instance/policy.rb +53 -0
- data/lib/instance/policy_audit.rb +100 -0
- data/lib/instance/policy_manager.rb +146 -0
- data/lib/instance/reenroll_manager.rb +104 -0
- data/lib/instance/right_scripts_cookbook.rb +181 -0
- data/lib/instance/shutdown_request.rb +221 -0
- data/lib/instance/single_thread_bundle_queue.rb +189 -0
- data/lib/instance/volume_management.rb +450 -0
- data/lib/instance.rb +50 -0
- data/lib/repo_conf_generators/apt_conf_generators.rb +106 -0
- data/lib/repo_conf_generators/gem_conf_generators.rb +80 -0
- data/lib/repo_conf_generators/rightscale_conf_generators.rb +254 -0
- data/lib/repo_conf_generators/rightscale_key.pub +17 -0
- data/lib/repo_conf_generators/yum_conf_generators.rb +225 -0
- data/lib/repo_conf_generators.rb +30 -0
- data/lib/run_shell.rb +28 -0
- data/scripts/agent_checker.rb +571 -0
- data/scripts/agent_controller.rb +247 -0
- data/scripts/agent_deployer.rb +148 -0
- data/scripts/bundle_runner.rb +336 -0
- data/scripts/cloud_controller.rb +176 -0
- data/scripts/log_level_manager.rb +142 -0
- data/scripts/ohai_runner.rb +33 -0
- data/scripts/reenroller.rb +193 -0
- data/scripts/server_importer.rb +293 -0
- data/scripts/shutdown_client.rb +183 -0
- data/scripts/system_configurator.rb +367 -0
- data/scripts/tagger.rb +381 -0
- data/scripts/thunker.rb +356 -0
- 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
|