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