right_scraper 1.0.26 → 3.0.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/Gemfile +16 -0
- data/README.rdoc +9 -28
- data/Rakefile +51 -39
- data/lib/right_scraper/builders/base.rb +64 -0
- data/lib/right_scraper/builders/filesystem.rb +96 -0
- data/lib/right_scraper/builders/union.rb +57 -0
- data/lib/right_scraper/logger.rb +102 -0
- data/lib/right_scraper/loggers/noisy.rb +85 -0
- data/lib/right_scraper/processes/ssh.rb +188 -0
- data/lib/right_scraper/repositories/base.rb +299 -0
- data/lib/right_scraper/repositories/download.rb +90 -0
- data/lib/right_scraper/repositories/git.rb +92 -0
- data/lib/right_scraper/repositories/mock.rb +70 -0
- data/lib/right_scraper/repositories/svn.rb +96 -0
- data/lib/right_scraper/resources/base.rb +70 -0
- data/{spec/scraper_base_spec.rb → lib/right_scraper/resources/cookbook.rb} +9 -23
- data/lib/right_scraper/resources/workflow.rb +55 -0
- data/lib/right_scraper/retrievers/base.rb +114 -0
- data/lib/right_scraper/retrievers/checkout.rb +79 -0
- data/lib/right_scraper/retrievers/download.rb +97 -0
- data/lib/right_scraper/retrievers/git.rb +140 -0
- data/lib/right_scraper/retrievers/svn.rb +87 -0
- data/lib/right_scraper/scanners/base.rb +111 -0
- data/lib/right_scraper/scanners/cookbook_manifest.rb +59 -0
- data/lib/right_scraper/scanners/cookbook_metadata.rb +69 -0
- data/lib/right_scraper/scanners/cookbook_s3_upload.rb +84 -0
- data/lib/right_scraper/scanners/union.rb +89 -0
- data/lib/right_scraper/scanners/workflow_manifest.rb +86 -0
- data/lib/right_scraper/scanners/workflow_metadata.rb +70 -0
- data/lib/right_scraper/scanners/workflow_s3_upload.rb +85 -0
- data/lib/right_scraper/scraper.rb +81 -57
- data/lib/right_scraper/scraper_logger.rb +61 -0
- data/lib/right_scraper/scrapers/base.rb +262 -0
- data/lib/right_scraper/scrapers/cookbook.rb +73 -0
- data/lib/right_scraper/scrapers/workflow.rb +88 -0
- data/lib/right_scraper/svn_client.rb +101 -0
- data/lib/right_scraper/version.rb +28 -0
- data/lib/right_scraper.rb +35 -11
- data/right_scraper.gemspec +26 -13
- data/right_scraper.rconf +13 -0
- data/spec/builder_spec.rb +50 -0
- data/spec/cookbook_helper.rb +73 -0
- data/spec/cookbook_manifest_spec.rb +55 -0
- data/spec/cookbook_s3_upload_spec.rb +152 -0
- data/spec/download/download_retriever_spec.rb +118 -0
- data/spec/download/download_retriever_spec_helper.rb +72 -0
- data/spec/download/download_spec.rb +130 -0
- data/spec/download/multi_dir_spec.rb +106 -0
- data/spec/download/multi_dir_spec_helper.rb +40 -0
- data/spec/git/cookbook_spec.rb +166 -0
- data/spec/git/demokey +27 -0
- data/spec/git/demokey.pub +1 -0
- data/spec/git/password_key +30 -0
- data/spec/git/password_key.pub +1 -0
- data/spec/git/repository_spec.rb +110 -0
- data/spec/git/retriever_spec.rb +505 -0
- data/spec/git/retriever_spec_helper.rb +112 -0
- data/spec/git/scraper_spec.rb +136 -0
- data/spec/git/ssh_spec.rb +170 -0
- data/spec/git/url_spec.rb +103 -0
- data/spec/logger_spec.rb +185 -0
- data/spec/repository_spec.rb +89 -23
- data/spec/{scraper_spec_helper_base.rb → retriever_spec_helper.rb} +41 -27
- data/spec/scanner_spec.rb +61 -0
- data/spec/scraper_helper.rb +96 -0
- data/spec/scraper_spec.rb +123 -45
- data/spec/spec_helper.rb +87 -14
- data/spec/svn/cookbook_spec.rb +97 -0
- data/spec/svn/multi_svn_spec.rb +64 -0
- data/spec/svn/multi_svn_spec_helper.rb +40 -0
- data/spec/svn/repository_spec.rb +72 -0
- data/spec/svn/retriever_spec.rb +261 -0
- data/spec/svn/scraper_spec.rb +90 -0
- data/spec/svn/{svn_scraper_spec_helper.rb → svn_retriever_spec_helper.rb} +46 -27
- data/spec/svn/url_spec.rb +47 -0
- data/spec/url_spec.rb +164 -0
- metadata +203 -31
- data/lib/right_scraper/linux/process_monitor.rb +0 -84
- data/lib/right_scraper/repository.rb +0 -78
- data/lib/right_scraper/scraper_base.rb +0 -175
- data/lib/right_scraper/scrapers/download_scraper.rb +0 -67
- data/lib/right_scraper/scrapers/git_scraper.rb +0 -283
- data/lib/right_scraper/scrapers/svn_scraper.rb +0 -119
- data/lib/right_scraper/watcher.rb +0 -158
- data/lib/right_scraper/win32/process_monitor.rb +0 -98
- data/spec/download/download_scraper_spec.rb +0 -94
- data/spec/git/git_scraper_spec.rb +0 -165
- data/spec/git/git_scraper_spec_helper.rb +0 -72
- data/spec/rcov.opts +0 -1
- data/spec/spec.opts +0 -2
- data/spec/svn/svn_scraper_spec.rb +0 -148
- data/spec/watcher_spec.rb +0 -74
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright: Copyright (c) 2010-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 NONINFRINGEMENT.
|
|
18
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
19
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
20
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
21
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
#++
|
|
23
|
+
|
|
24
|
+
module RightScraper
|
|
25
|
+
module Scrapers
|
|
26
|
+
|
|
27
|
+
# Base class for all scrapers. Subclasses should override
|
|
28
|
+
# #find_next which instantiates the resource from the file system.
|
|
29
|
+
class Base
|
|
30
|
+
|
|
31
|
+
# Scraped resources
|
|
32
|
+
attr_reader :resources
|
|
33
|
+
|
|
34
|
+
# Initialize scraper
|
|
35
|
+
#
|
|
36
|
+
# === Options
|
|
37
|
+
# <tt>:kind</tt>:: Scraper type, one of :cookbook or :workflow
|
|
38
|
+
# <tt>:repo_dir</tt>:: Required, path to directory containing files
|
|
39
|
+
# to be scraped
|
|
40
|
+
# <tt>:ignorable_paths</tt>:: List of directory names that should
|
|
41
|
+
# be ignored by scraper
|
|
42
|
+
# <tt>:scanners</tt>:: List of Scanner classes to use, optional
|
|
43
|
+
# <tt>:builders</tt>:: List of Builder classes to use, optional
|
|
44
|
+
#
|
|
45
|
+
# === Return
|
|
46
|
+
# scraper(Scrapers::Base):: Corresponding scraper instance
|
|
47
|
+
def self.scraper(options)
|
|
48
|
+
scraper_kind = options.delete(:kind)
|
|
49
|
+
scraper_class = @@types[scraper_kind]
|
|
50
|
+
raise "Can't understand how to build scraper #{scraper_kind}" if scraper_class.nil?
|
|
51
|
+
scraper = scraper_class.new(options)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Do the scrape!
|
|
55
|
+
# Extract all resources from directory
|
|
56
|
+
# Call this method or call 'next_resource' to retrieve
|
|
57
|
+
# resources one by one (you must then call 'close' yourself)
|
|
58
|
+
# Fill @resources
|
|
59
|
+
#
|
|
60
|
+
# === Return
|
|
61
|
+
# resources<Array>:: List of all scraped resources
|
|
62
|
+
def scrape
|
|
63
|
+
@resources = []
|
|
64
|
+
begin
|
|
65
|
+
resource = next_resource
|
|
66
|
+
until resource.nil?
|
|
67
|
+
@resources << resource
|
|
68
|
+
resource = next_resource
|
|
69
|
+
end
|
|
70
|
+
ensure
|
|
71
|
+
close
|
|
72
|
+
end
|
|
73
|
+
@resources
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Return the next resource in the filesystem, or nil if none. As
|
|
77
|
+
# a part of building the resources, invokes the builders.
|
|
78
|
+
# A resource can be a cookbook, a workflow, a RightScript etc.
|
|
79
|
+
#
|
|
80
|
+
# === Returns
|
|
81
|
+
# Object:: next resource in filesystem, or nil if none.
|
|
82
|
+
def next_resource
|
|
83
|
+
@logger.operation(:next) do
|
|
84
|
+
next nil if @next.nil?
|
|
85
|
+
|
|
86
|
+
value = @next
|
|
87
|
+
@next = search_dirs
|
|
88
|
+
while @next.nil? && !@queue.empty?
|
|
89
|
+
pop_queue
|
|
90
|
+
end
|
|
91
|
+
value
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Close any opened file descriptor
|
|
96
|
+
#
|
|
97
|
+
# === Return
|
|
98
|
+
# true:: Always return true
|
|
99
|
+
def close
|
|
100
|
+
@builder.finish
|
|
101
|
+
if @stack && !@stack.empty?
|
|
102
|
+
@stack.each {|s| s.close}
|
|
103
|
+
@stack = []
|
|
104
|
+
end
|
|
105
|
+
true
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
protected
|
|
109
|
+
|
|
110
|
+
# Directory containing files to be scraped
|
|
111
|
+
attr_reader :repo_dir
|
|
112
|
+
|
|
113
|
+
# (Hash) Lookup table from textual description of scraper type
|
|
114
|
+
# ('cookbook' or 'workflow' currently) to the class that
|
|
115
|
+
# represents that scraper.
|
|
116
|
+
@@types = {} unless class_variable_defined?(:@@types)
|
|
117
|
+
|
|
118
|
+
# Initialize scraper
|
|
119
|
+
#
|
|
120
|
+
# === Options
|
|
121
|
+
# <tt>:repository</tt>:: Required, original repository containing scraped
|
|
122
|
+
# files
|
|
123
|
+
# <tt>:repo_dir</tt>:: Required, path to directory containing files
|
|
124
|
+
# to be scraped
|
|
125
|
+
# <tt>:ignorable_paths</tt>:: List of directory names that should
|
|
126
|
+
# be ignored by scraper
|
|
127
|
+
# <tt>:scanners</tt>:: List of Scanner classes to use, defaulting
|
|
128
|
+
# to RightScraper::Scanners::ResourceManifest and
|
|
129
|
+
# RightScraper::Scanners::CookbookMetadata
|
|
130
|
+
# <tt>:builders</tt>:: List of Builder classes to use, defaulting to
|
|
131
|
+
# RightScaper::Builders::Filesystem
|
|
132
|
+
#
|
|
133
|
+
def initialize(options)
|
|
134
|
+
raise "Repository required when initializing a scraper" unless options[:repository]
|
|
135
|
+
raise "Repository directory required when initializing a scraper" unless options[:repo_dir]
|
|
136
|
+
@repository = options[:repository]
|
|
137
|
+
@logger = options[:logger] || ScraperLogger.new
|
|
138
|
+
@repo_dir = options[:repo_dir]
|
|
139
|
+
@ignorable_paths = options[:ignorable_paths]
|
|
140
|
+
@stack = []
|
|
141
|
+
@queue = (@repository.resources_path || [""]).reverse
|
|
142
|
+
@resources = []
|
|
143
|
+
scanners = options[:scanners] || default_scanners
|
|
144
|
+
@scanner = RightScraper::Scanners::Union.new(scanners, options)
|
|
145
|
+
builders = options[:builders] || default_builders
|
|
146
|
+
@builder = RightScraper::Builders::Union.new(builders, :ignorable_paths => @ignorable_paths,
|
|
147
|
+
:scanner => @scanner,
|
|
148
|
+
:logger => @logger,
|
|
149
|
+
:max_bytes => @max_bytes,
|
|
150
|
+
:max_seconds => @max_seconds)
|
|
151
|
+
pop_queue # Initialize @next
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# List of default scanners for this scaper
|
|
155
|
+
#
|
|
156
|
+
# === Return
|
|
157
|
+
# Array<Scanner>:: Default scanners
|
|
158
|
+
def default_scanners
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# List of default builders for this scaper
|
|
162
|
+
#
|
|
163
|
+
# === Return
|
|
164
|
+
# Array<Builder>:: Default builders
|
|
165
|
+
def default_brokers
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
# Find the interesting item in given directory
|
|
169
|
+
# Override in actual scraper implementation
|
|
170
|
+
#
|
|
171
|
+
# === Parameters
|
|
172
|
+
# dir(Dir):: directory to begin search in
|
|
173
|
+
def find_next(dir)
|
|
174
|
+
raise NotImplementedError
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
# Return the position of the scraper. Here, the position is the
|
|
178
|
+
# path relative from the top of the temporary directory. Akin to
|
|
179
|
+
# IO#pos or IO#tell.
|
|
180
|
+
def pos
|
|
181
|
+
strip_repo_dir(@stack.last.path)
|
|
182
|
+
end
|
|
183
|
+
alias_method :tell, :pos
|
|
184
|
+
|
|
185
|
+
# Turn path from an absolute filesystem location to a relative
|
|
186
|
+
# file location from #repo_dir.
|
|
187
|
+
#
|
|
188
|
+
# === Parameters
|
|
189
|
+
# path(String):: absolute path to relativize
|
|
190
|
+
#
|
|
191
|
+
# === Returns
|
|
192
|
+
# res(String):: relative pathname for path
|
|
193
|
+
def strip_repo_dir(path)
|
|
194
|
+
res = path[repo_dir.length+1..-1]
|
|
195
|
+
if res == nil || res == ""
|
|
196
|
+
"."
|
|
197
|
+
else
|
|
198
|
+
res
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
private :strip_repo_dir
|
|
202
|
+
|
|
203
|
+
# Test if the entry given is ignorable. By default just uses
|
|
204
|
+
# #ignorable_paths
|
|
205
|
+
#
|
|
206
|
+
# === Parameters
|
|
207
|
+
# entry(String):: file name to check
|
|
208
|
+
#
|
|
209
|
+
# === Returns
|
|
210
|
+
# Boolean:: true if the entry should be ignored
|
|
211
|
+
def ignorable?(entry)
|
|
212
|
+
@ignorable_paths.include?(entry)
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# Initialize @next with the next resource
|
|
216
|
+
#
|
|
217
|
+
# === Returns
|
|
218
|
+
# @next(Resources::Base):: Next resource
|
|
219
|
+
def pop_queue
|
|
220
|
+
until @queue.empty?
|
|
221
|
+
nextdir = @queue.pop
|
|
222
|
+
if File.directory?(File.join(repo_dir, nextdir))
|
|
223
|
+
@next = find_next(Dir.new(File.join(repo_dir, nextdir)))
|
|
224
|
+
return @next
|
|
225
|
+
else
|
|
226
|
+
@logger.warn("When processing in #{@repository}, no such path #{nextdir}")
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
@next = nil
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
# Search the directory stack looking for the next resource.
|
|
233
|
+
def search_dirs
|
|
234
|
+
@logger.operation(:searching) do
|
|
235
|
+
until @stack.empty?
|
|
236
|
+
dir = @stack.last
|
|
237
|
+
entry = dir.read
|
|
238
|
+
if entry == nil
|
|
239
|
+
dir.close
|
|
240
|
+
@stack.pop
|
|
241
|
+
next
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
next if entry == '.' || entry == '..'
|
|
245
|
+
next if ignorable?(entry)
|
|
246
|
+
|
|
247
|
+
fullpath = File.join(dir.path, entry)
|
|
248
|
+
|
|
249
|
+
if File.directory?(fullpath)
|
|
250
|
+
result = find_next(Dir.new(fullpath))
|
|
251
|
+
break
|
|
252
|
+
end
|
|
253
|
+
end
|
|
254
|
+
result
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
private :search_dirs
|
|
258
|
+
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright: Copyright (c) 2010-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 NONINFRINGEMENT.
|
|
18
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
19
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
20
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
21
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
#++
|
|
23
|
+
|
|
24
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'base'))
|
|
25
|
+
|
|
26
|
+
module RightScraper
|
|
27
|
+
module Scrapers
|
|
28
|
+
|
|
29
|
+
# Chef cookbook scraper
|
|
30
|
+
class Cookbook < Base
|
|
31
|
+
|
|
32
|
+
# Find the next cookbook, starting in dir.
|
|
33
|
+
#
|
|
34
|
+
# === Parameters
|
|
35
|
+
# dir(Dir):: directory to begin search in
|
|
36
|
+
def find_next(dir)
|
|
37
|
+
@logger.operation(:finding_next_cookbook, "in #{dir.path}") do
|
|
38
|
+
if File.exists?(File.join(dir.path, 'metadata.json'))
|
|
39
|
+
@logger.operation(:reading_cookbook, "from #{dir.path}") do
|
|
40
|
+
cookbook = RightScraper::Resources::Cookbook.new(@repository, strip_repo_dir(dir.path))
|
|
41
|
+
@builder.go(dir.path, cookbook)
|
|
42
|
+
cookbook
|
|
43
|
+
end
|
|
44
|
+
else
|
|
45
|
+
@stack << dir
|
|
46
|
+
search_dirs
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# List of default scanners for this scaper
|
|
52
|
+
#
|
|
53
|
+
# === Return
|
|
54
|
+
# Array<Scanner>:: Default scanners
|
|
55
|
+
def default_scanners
|
|
56
|
+
[RightScraper::Scanners::CookbookMetadata,
|
|
57
|
+
RightScraper::Scanners::CookbookManifest]
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# List of default builders for this scaper
|
|
61
|
+
#
|
|
62
|
+
# === Return
|
|
63
|
+
# Array<Builder>:: Default builders
|
|
64
|
+
def default_builders
|
|
65
|
+
[RightScraper::Builders::Filesystem]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Add this scraper to the list of available types.
|
|
69
|
+
@@types[:cookbook] = RightScraper::Scrapers::Cookbook
|
|
70
|
+
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright: Copyright (c) 2010-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 NONINFRINGEMENT.
|
|
18
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
19
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
20
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
21
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
#++
|
|
23
|
+
|
|
24
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'base'))
|
|
25
|
+
|
|
26
|
+
module RightScraper
|
|
27
|
+
module Scrapers
|
|
28
|
+
|
|
29
|
+
# Workflow scraper
|
|
30
|
+
class Workflow < Base
|
|
31
|
+
|
|
32
|
+
# Initialize list of known workflows on top of
|
|
33
|
+
def initialize(options)
|
|
34
|
+
@known_workflows = []
|
|
35
|
+
super(options)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Find the next workflows, starting in dir.
|
|
39
|
+
#
|
|
40
|
+
# === Parameters
|
|
41
|
+
# dir(Dir):: directory to begin search in
|
|
42
|
+
def find_next(dir)
|
|
43
|
+
@logger.operation(:finding_next_workflow, "in #{dir.path}") do
|
|
44
|
+
def_ext = RightScraper::Resources::Workflow::DEFINITION_EXT
|
|
45
|
+
meta_ext = RightScraper::Resources::Workflow::METADATA_EXT
|
|
46
|
+
potentials = Dir[File.join(dir.path, "*#{def_ext}")]
|
|
47
|
+
potentials.reject! { |wdef| !File.exists?(wdef.chomp(File.extname(wdef)) + meta_ext) }
|
|
48
|
+
potentials.reject! { |wdef| @known_workflows.include?(wdef) }
|
|
49
|
+
unless potentials.empty?
|
|
50
|
+
wdef = potentials.first
|
|
51
|
+
relative_def = strip_repo_dir(wdef)
|
|
52
|
+
@logger.operation(:reading_workflow, "#{relative_def}") do
|
|
53
|
+
workflow = RightScraper::Resources::Workflow.new(@repository, relative_def)
|
|
54
|
+
@builder.go(File.dirname(wdef), workflow)
|
|
55
|
+
@known_workflows << wdef
|
|
56
|
+
workflow
|
|
57
|
+
end
|
|
58
|
+
else
|
|
59
|
+
@stack << dir
|
|
60
|
+
search_dirs
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# List of default scanners for this scaper
|
|
66
|
+
#
|
|
67
|
+
# === Return
|
|
68
|
+
# Array<Scanner>:: Default scanners
|
|
69
|
+
def default_scanners
|
|
70
|
+
[RightScraper::Scanners::WorkflowMetadata,
|
|
71
|
+
RightScraper::Scanners::WorkflowManifest]
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# List of default builders for this scaper
|
|
75
|
+
#
|
|
76
|
+
# === Return
|
|
77
|
+
# Array<Builder>:: Default builders
|
|
78
|
+
def default_builders
|
|
79
|
+
[RightScraper::Builders::Filesystem]
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Add this scraper to the list of available types.
|
|
83
|
+
@@types[:workflow] = RightScraper::Scrapers::Workflow
|
|
84
|
+
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
#--
|
|
2
|
+
# Copyright: Copyright (c) 2010-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 NONINFRINGEMENT.
|
|
18
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
19
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
20
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
21
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
#++
|
|
23
|
+
require 'process_watcher'
|
|
24
|
+
|
|
25
|
+
module RightScraper
|
|
26
|
+
# Simplified interface to the process of creating SVN client
|
|
27
|
+
# contexts.
|
|
28
|
+
#
|
|
29
|
+
# SVN client contexts are needed for almost every nontrivial SVN
|
|
30
|
+
# operation, and the authentication procedure is truly baroque.
|
|
31
|
+
# Thus, when you need a client context, do something like this:
|
|
32
|
+
# client = SvnClient.new(repository)
|
|
33
|
+
# client.with_context do |ctx|
|
|
34
|
+
# ...
|
|
35
|
+
# end
|
|
36
|
+
module SvnClient
|
|
37
|
+
def calculate_version
|
|
38
|
+
unless @svn_version
|
|
39
|
+
out = ProcessWatcher.watch("svn", ["--version", "--quiet"],
|
|
40
|
+
repo_dir, @max_bytes || -1, @max_seconds || -1)
|
|
41
|
+
@svn_version = out.chomp.split(".").map {|e| e.to_i}
|
|
42
|
+
end
|
|
43
|
+
@svn_version
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def svn_arguments
|
|
47
|
+
version = calculate_version
|
|
48
|
+
case
|
|
49
|
+
when version[0] != 1
|
|
50
|
+
raise "SVN major revision is not 1, cannot be sure it will run properly."
|
|
51
|
+
when version[1] < 4
|
|
52
|
+
raise "SVN minor revision < 4; cannot be sure it will run properly."
|
|
53
|
+
when version[1] < 6
|
|
54
|
+
# --trust-server-cert is a 1.6ism
|
|
55
|
+
args = ["--no-auth-cache", "--non-interactive"]
|
|
56
|
+
else
|
|
57
|
+
args = ["--no-auth-cache", "--non-interactive", "--trust-server-cert"]
|
|
58
|
+
end
|
|
59
|
+
if repository.first_credential && repository.second_credential
|
|
60
|
+
args << "--username"
|
|
61
|
+
args << repository.first_credential
|
|
62
|
+
args << "--password"
|
|
63
|
+
args << repository.second_credential
|
|
64
|
+
end
|
|
65
|
+
args
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def get_tag_argument
|
|
69
|
+
if repository.tag
|
|
70
|
+
tag_cmd = ["-r", get_tag.to_s]
|
|
71
|
+
else
|
|
72
|
+
tag_cmd = ["-r", "HEAD"]
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def run_svn_no_chdir(*args)
|
|
77
|
+
ProcessWatcher.watch("svn", [args, svn_arguments].flatten,
|
|
78
|
+
repo_dir, @max_bytes || -1, @max_seconds || -1) do |phase, operation, exception|
|
|
79
|
+
#$stderr.puts "#{phase} #{operation} #{exception}"
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def run_svn(*args)
|
|
84
|
+
Dir.chdir(repo_dir) do
|
|
85
|
+
run_svn_no_chdir(*args)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Fetch the tag from the repository, or nil if one doesn't
|
|
90
|
+
# exist. This is a separate method because the repo tag should
|
|
91
|
+
# be a number but is a string in the database.
|
|
92
|
+
def get_tag
|
|
93
|
+
case repository.tag
|
|
94
|
+
when Fixnum then repository.tag
|
|
95
|
+
when /^\d+$/ then repository.tag.to_i
|
|
96
|
+
else
|
|
97
|
+
repository.tag
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
#-- -*- mode: ruby; encoding: utf-8 -*-
|
|
2
|
+
# Copyright: Copyright (c) 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 NONINFRINGEMENT.
|
|
18
|
+
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
19
|
+
# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
20
|
+
# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
21
|
+
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
|
+
#++
|
|
23
|
+
|
|
24
|
+
module RightScraper
|
|
25
|
+
# (Fixnum) protocol versioning scheme; prepended to hashes to
|
|
26
|
+
# prevent collisions.
|
|
27
|
+
PROTOCOL_VERSION = 1
|
|
28
|
+
end
|
data/lib/right_scraper.rb
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
#--
|
|
2
|
-
# Copyright: Copyright (c) 2010 RightScale, Inc.
|
|
2
|
+
# Copyright: Copyright (c) 2010-2011 RightScale, Inc.
|
|
3
3
|
#
|
|
4
4
|
# Permission is hereby granted, free of charge, to any person obtaining
|
|
5
5
|
# a copy of this software and associated documentation files (the
|
|
6
6
|
# 'Software'), to deal in the Software without restriction, including
|
|
7
7
|
# without limitation the rights to use, copy, modify, merge, publish,
|
|
8
|
-
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
|
9
9
|
# permit persons to whom the Software is furnished to do so, subject to
|
|
10
10
|
# the following conditions:
|
|
11
11
|
#
|
|
12
12
|
# The above copyright notice and this permission notice shall be
|
|
13
13
|
# included in all copies or substantial portions of the Software.
|
|
14
14
|
#
|
|
15
|
-
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
16
16
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
17
17
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
18
18
|
# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
@@ -21,12 +21,36 @@
|
|
|
21
21
|
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
22
22
|
#++
|
|
23
23
|
|
|
24
|
-
#
|
|
24
|
+
# Explicitly list required files to make IDEs happy
|
|
25
25
|
require 'fileutils'
|
|
26
|
-
require File.join(File.dirname(__FILE__), 'right_scraper', '
|
|
27
|
-
require File.join(File.dirname(__FILE__), 'right_scraper', '
|
|
28
|
-
require File.join(File.dirname(__FILE__), 'right_scraper', '
|
|
29
|
-
require File.join(File.dirname(__FILE__), 'right_scraper', '
|
|
30
|
-
require File.join(File.dirname(__FILE__), 'right_scraper', '
|
|
31
|
-
require File.join(File.dirname(__FILE__), 'right_scraper', '
|
|
32
|
-
require File.join(File.dirname(__FILE__), 'right_scraper', '
|
|
26
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'builders', 'base'))
|
|
27
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'builders', 'filesystem'))
|
|
28
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'builders', 'union'))
|
|
29
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'logger'))
|
|
30
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'processes', 'ssh'))
|
|
31
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'repositories', 'base'))
|
|
32
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'repositories', 'download'))
|
|
33
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'repositories', 'git'))
|
|
34
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'repositories', 'svn'))
|
|
35
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'resources', 'base'))
|
|
36
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'resources', 'cookbook'))
|
|
37
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'resources', 'workflow'))
|
|
38
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'retrievers', 'base'))
|
|
39
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'retrievers', 'checkout'))
|
|
40
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'retrievers', 'download'))
|
|
41
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'retrievers', 'git'))
|
|
42
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'retrievers', 'svn'))
|
|
43
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'scanners', 'base'))
|
|
44
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'scanners', 'cookbook_manifest'))
|
|
45
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'scanners', 'cookbook_metadata'))
|
|
46
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'scanners', 'cookbook_s3_upload'))
|
|
47
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'scanners', 'union'))
|
|
48
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'scanners', 'workflow_manifest'))
|
|
49
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'scanners', 'workflow_metadata'))
|
|
50
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'scraper'))
|
|
51
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'scraper_logger'))
|
|
52
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'scrapers', 'base'))
|
|
53
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'scrapers', 'cookbook'))
|
|
54
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'scrapers', 'workflow'))
|
|
55
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'svn_client'))
|
|
56
|
+
require File.expand_path(File.join(File.dirname(__FILE__), 'right_scraper', 'version'))
|