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.
Files changed (92) hide show
  1. data/Gemfile +16 -0
  2. data/README.rdoc +9 -28
  3. data/Rakefile +51 -39
  4. data/lib/right_scraper/builders/base.rb +64 -0
  5. data/lib/right_scraper/builders/filesystem.rb +96 -0
  6. data/lib/right_scraper/builders/union.rb +57 -0
  7. data/lib/right_scraper/logger.rb +102 -0
  8. data/lib/right_scraper/loggers/noisy.rb +85 -0
  9. data/lib/right_scraper/processes/ssh.rb +188 -0
  10. data/lib/right_scraper/repositories/base.rb +299 -0
  11. data/lib/right_scraper/repositories/download.rb +90 -0
  12. data/lib/right_scraper/repositories/git.rb +92 -0
  13. data/lib/right_scraper/repositories/mock.rb +70 -0
  14. data/lib/right_scraper/repositories/svn.rb +96 -0
  15. data/lib/right_scraper/resources/base.rb +70 -0
  16. data/{spec/scraper_base_spec.rb → lib/right_scraper/resources/cookbook.rb} +9 -23
  17. data/lib/right_scraper/resources/workflow.rb +55 -0
  18. data/lib/right_scraper/retrievers/base.rb +114 -0
  19. data/lib/right_scraper/retrievers/checkout.rb +79 -0
  20. data/lib/right_scraper/retrievers/download.rb +97 -0
  21. data/lib/right_scraper/retrievers/git.rb +140 -0
  22. data/lib/right_scraper/retrievers/svn.rb +87 -0
  23. data/lib/right_scraper/scanners/base.rb +111 -0
  24. data/lib/right_scraper/scanners/cookbook_manifest.rb +59 -0
  25. data/lib/right_scraper/scanners/cookbook_metadata.rb +69 -0
  26. data/lib/right_scraper/scanners/cookbook_s3_upload.rb +84 -0
  27. data/lib/right_scraper/scanners/union.rb +89 -0
  28. data/lib/right_scraper/scanners/workflow_manifest.rb +86 -0
  29. data/lib/right_scraper/scanners/workflow_metadata.rb +70 -0
  30. data/lib/right_scraper/scanners/workflow_s3_upload.rb +85 -0
  31. data/lib/right_scraper/scraper.rb +81 -57
  32. data/lib/right_scraper/scraper_logger.rb +61 -0
  33. data/lib/right_scraper/scrapers/base.rb +262 -0
  34. data/lib/right_scraper/scrapers/cookbook.rb +73 -0
  35. data/lib/right_scraper/scrapers/workflow.rb +88 -0
  36. data/lib/right_scraper/svn_client.rb +101 -0
  37. data/lib/right_scraper/version.rb +28 -0
  38. data/lib/right_scraper.rb +35 -11
  39. data/right_scraper.gemspec +26 -13
  40. data/right_scraper.rconf +13 -0
  41. data/spec/builder_spec.rb +50 -0
  42. data/spec/cookbook_helper.rb +73 -0
  43. data/spec/cookbook_manifest_spec.rb +55 -0
  44. data/spec/cookbook_s3_upload_spec.rb +152 -0
  45. data/spec/download/download_retriever_spec.rb +118 -0
  46. data/spec/download/download_retriever_spec_helper.rb +72 -0
  47. data/spec/download/download_spec.rb +130 -0
  48. data/spec/download/multi_dir_spec.rb +106 -0
  49. data/spec/download/multi_dir_spec_helper.rb +40 -0
  50. data/spec/git/cookbook_spec.rb +166 -0
  51. data/spec/git/demokey +27 -0
  52. data/spec/git/demokey.pub +1 -0
  53. data/spec/git/password_key +30 -0
  54. data/spec/git/password_key.pub +1 -0
  55. data/spec/git/repository_spec.rb +110 -0
  56. data/spec/git/retriever_spec.rb +505 -0
  57. data/spec/git/retriever_spec_helper.rb +112 -0
  58. data/spec/git/scraper_spec.rb +136 -0
  59. data/spec/git/ssh_spec.rb +170 -0
  60. data/spec/git/url_spec.rb +103 -0
  61. data/spec/logger_spec.rb +185 -0
  62. data/spec/repository_spec.rb +89 -23
  63. data/spec/{scraper_spec_helper_base.rb → retriever_spec_helper.rb} +41 -27
  64. data/spec/scanner_spec.rb +61 -0
  65. data/spec/scraper_helper.rb +96 -0
  66. data/spec/scraper_spec.rb +123 -45
  67. data/spec/spec_helper.rb +87 -14
  68. data/spec/svn/cookbook_spec.rb +97 -0
  69. data/spec/svn/multi_svn_spec.rb +64 -0
  70. data/spec/svn/multi_svn_spec_helper.rb +40 -0
  71. data/spec/svn/repository_spec.rb +72 -0
  72. data/spec/svn/retriever_spec.rb +261 -0
  73. data/spec/svn/scraper_spec.rb +90 -0
  74. data/spec/svn/{svn_scraper_spec_helper.rb → svn_retriever_spec_helper.rb} +46 -27
  75. data/spec/svn/url_spec.rb +47 -0
  76. data/spec/url_spec.rb +164 -0
  77. metadata +203 -31
  78. data/lib/right_scraper/linux/process_monitor.rb +0 -84
  79. data/lib/right_scraper/repository.rb +0 -78
  80. data/lib/right_scraper/scraper_base.rb +0 -175
  81. data/lib/right_scraper/scrapers/download_scraper.rb +0 -67
  82. data/lib/right_scraper/scrapers/git_scraper.rb +0 -283
  83. data/lib/right_scraper/scrapers/svn_scraper.rb +0 -119
  84. data/lib/right_scraper/watcher.rb +0 -158
  85. data/lib/right_scraper/win32/process_monitor.rb +0 -98
  86. data/spec/download/download_scraper_spec.rb +0 -94
  87. data/spec/git/git_scraper_spec.rb +0 -165
  88. data/spec/git/git_scraper_spec_helper.rb +0 -72
  89. data/spec/rcov.opts +0 -1
  90. data/spec/spec.opts +0 -2
  91. data/spec/svn/svn_scraper_spec.rb +0 -148
  92. data/spec/watcher_spec.rb +0 -74
@@ -0,0 +1,140 @@
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 'git'
24
+
25
+ module RightScraper
26
+ module Retrievers
27
+ # Retriever for resources stored in a git repository.
28
+ class Git < CheckoutBasedRetriever
29
+ # In addition to normal retriever initialization, if the
30
+ # underlying repository has a credential we need to initialize a
31
+ # fresh SSHAgent and add the credential to it.
32
+ def retrieve
33
+ RightScraper::Processes::SSHAgent.with do |agent|
34
+ agent.add_key(@repository.first_credential) unless
35
+ @repository.first_credential.nil?
36
+ super
37
+ end
38
+ end
39
+
40
+ # Return true if a checkout exists. Currently tests for .git in
41
+ # the checkout.
42
+ #
43
+ # === Returns ===
44
+ # Boolean:: true if the checkout already exists (and thus
45
+ # incremental updating can occur).
46
+ def exists?
47
+ File.exists?(File.join(@repo_dir, '.git'))
48
+ end
49
+
50
+ def do_fetch(git)
51
+ @logger.operation(:fetch) do
52
+ git.tags.each {|tag| git.lib.tag(['-d', tag.name])}
53
+ git.fetch(['--all', '--prune', '--tags'])
54
+ end
55
+ end
56
+
57
+ # Incrementally update the checkout. The operations are as follows:
58
+ # * checkout #tag
59
+ # * if #tag is the head of a branch:
60
+ # * find that branch's remote
61
+ # * fetch it
62
+ # * merge changes
63
+ # * update @repository#tag
64
+ # Note that if #tag is a SHA revision or a tag that exists in the
65
+ # current repository, no fetching is done.
66
+ def do_update
67
+ git = ::Git.open(@repo_dir)
68
+ do_fetch(git)
69
+ git.reset_hard
70
+ do_checkout_revision(git)
71
+ do_update_tag(git)
72
+ end
73
+
74
+ def do_update_tag(git)
75
+ @repository = @repository.clone
76
+ @repository.tag = git.gtree("HEAD").sha
77
+ end
78
+
79
+ # Clone the remote repository. The operations are as follows:
80
+ # * clone repository to @repo_dir
81
+ # * checkout #tag
82
+ # * update @repository#tag
83
+ def do_checkout
84
+ super
85
+ git = @logger.operation(:cloning, "to #{@repo_dir}") do
86
+ ::Git.clone(@repository.url, @repo_dir)
87
+ end
88
+ do_fetch(git)
89
+ do_checkout_revision(git)
90
+ do_update_tag git
91
+ end
92
+
93
+ def do_checkout_revision(git)
94
+ @logger.operation(:checkout_revision) do
95
+ case
96
+ when tag?(git, repo_tag) && branch?(git, repo_tag) then
97
+ raise "Ambiguous reference: '#{repo_tag}' denotes both a branch and a tag"
98
+ when branch = find_remote_branch(git, repo_tag) then
99
+ branch.checkout
100
+ when branch = find_local_branch(git, repo_tag) then
101
+ branch.checkout
102
+ else
103
+ git.checkout(repo_tag)
104
+ end
105
+ end if repo_tag
106
+ end
107
+
108
+ def tag?(git, name)
109
+ git.tags.find {|t| t.name == name}
110
+ end
111
+
112
+ def branch?(git, name)
113
+ git.branches.find {|t| t.name == name}
114
+ end
115
+
116
+ def repo_tag
117
+ name = (@repository.tag || "master").chomp
118
+ name = "master" if name.empty?
119
+ name
120
+ end
121
+
122
+ def find_branch(git, tag)
123
+ find_local_branch(git, tag) || find_remote_branch(git, tag)
124
+ end
125
+
126
+ def find_local_branch(git, name)
127
+ git.branches.local.find {|b| b.name == name}
128
+ end
129
+
130
+ def find_remote_branch(git, name)
131
+ git.branches.remote.find {|b| b.name == name}
132
+ end
133
+
134
+ # Ignore .git directories.
135
+ def ignorable_paths
136
+ ['.git']
137
+ end
138
+ end
139
+ end
140
+ end
@@ -0,0 +1,87 @@
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 File.join(File.dirname(__FILE__), '..', 'svn_client')
24
+
25
+ require 'process_watcher'
26
+
27
+ module RightScraper
28
+ module Retrievers
29
+ # Retriever for svn repositories
30
+ class Svn < CheckoutBasedRetriever
31
+
32
+ include RightScraper::SvnClient
33
+
34
+ # Return true if a checkout exists. Currently tests for .svn in
35
+ # the checkout.
36
+ #
37
+ # === Returns
38
+ # Boolean:: true if the checkout already exists (and thus
39
+ # incremental updating can occur).
40
+ def exists?
41
+ File.exists?(File.join(@repo_dir, '.svn'))
42
+ end
43
+
44
+ # Incrementally update the checkout. The operations are as follows:
45
+ # * update to #tag
46
+ # In theory if #tag is a revision number that already exists no
47
+ # update is necessary. It's not clear if the SVN client libraries
48
+ # are bright enough to notice this.
49
+ def do_update
50
+ @logger.operation(:update) do
51
+ run_svn("update", get_tag_argument)
52
+ end
53
+ do_update_tag
54
+ end
55
+
56
+ # Update our idea of what the head of the repository is. We
57
+ # would like to use svn info, but that doesn't do the right
58
+ # thing all the time; the right thing to do is to run log and
59
+ # pick out the first tag.
60
+ def do_update_tag
61
+ @repository = @repository.clone
62
+ log = run_svn("log", "-r", 'HEAD')
63
+ log.split(/\n/).each do |line|
64
+ if line =~ /^r(\d+)/
65
+ @repository.tag = $1
66
+ break
67
+ end
68
+ end
69
+ end
70
+
71
+ # Check out the remote repository. The operations are as follows:
72
+ # * checkout repository at #tag to @repo_dir
73
+ def do_checkout
74
+ super
75
+ @logger.operation(:checkout_revision) do
76
+ run_svn_no_chdir("checkout", @repository.url, @repo_dir, get_tag_argument)
77
+ end
78
+ do_update_tag
79
+ end
80
+
81
+ # Ignore .svn directories.
82
+ def ignorable_paths
83
+ ['.svn']
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,111 @@
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 Scanners
26
+ # Base class for scanning filesystems. Subclasses should override
27
+ # #notice and may override #new, #begin, #end and
28
+ # #notice_dir.
29
+ #
30
+ # Overriding #new is useful for getting
31
+ # additional arguments. Overriding #begin allows you to do
32
+ # processing before the scan of a given resource begins;
33
+ # overriding #end allows you to do processing after it completes.
34
+ #
35
+ # Most processing will occur in #notice, which notifies you that a
36
+ # file has been detected, and in #notice_dir. In #notice you are
37
+ # handed the relative position of the file from the start of the
38
+ # resource; so if you were scanning <tt>/a/resource</tt> and
39
+ # noticed a file <tt>b/c</tt>, #notice would be called with
40
+ # <tt>"b/c"</tt>, even though the full pathname is
41
+ # <tt>/a/resource/b/c</tt>. If you decide you need the actual
42
+ # data, #notice takes a block which will return that data to you
43
+ # if you +yield+.
44
+ #
45
+ # In #notice_dir you are handed the relative position of a
46
+ # directory. The return value determines whether you find the
47
+ # directory worth recursing into, or not--as an example, when
48
+ # looking for the <tt>metadata.json</tt> file it is never
49
+ # necessary to descend past the topmost directory of the resource,
50
+ # but the same is not true when building a manifest.
51
+ class Base
52
+ # Create a new Scanner. Recognizes options as given. Some
53
+ # options may be required, others optional. This class recognizes
54
+ # only _:logger_.
55
+ #
56
+ # === Options ===
57
+ # _:logger_:: Optional. Logger currently being used
58
+ #
59
+ # === Parameters ===
60
+ # options(Hash):: scanner options
61
+ def initialize(options={})
62
+ @logger = options.fetch(:logger, RightScraper::Logger.new)
63
+ end
64
+
65
+ # Notification that all scans for this repository have
66
+ # completed.
67
+ def finish
68
+ end
69
+
70
+ # Begin a scan for the given resource.
71
+ #
72
+ # === Parameters ===
73
+ # resource(RightScraper::Resource::Base):: resource to scan
74
+ def begin(resource)
75
+ end
76
+
77
+ # Finish a scan for the given resource.
78
+ #
79
+ # === Parameters ===
80
+ # resource(RightScraper::Resource::Base):: resource that just finished
81
+ # scanning
82
+ def end(resource)
83
+ end
84
+
85
+ # Notice a file during scanning.
86
+ #
87
+ # === Block ===
88
+ # Return the data for this file. We use a block because it may
89
+ # not always be necessary to read the data.
90
+ #
91
+ # === Parameters ===
92
+ # relative_position(String):: relative pathname for _pathname_
93
+ # from root of resource
94
+ def notice(relative_position)
95
+ end
96
+
97
+ # Notice a directory during scanning. Returns true if the scanner
98
+ # should recurse into the directory (the default behavior)
99
+ #
100
+ # === Parameters ===
101
+ # relative_position(String):: relative pathname for the directory
102
+ # from root of resource
103
+ #
104
+ # === Returns ===
105
+ # Boolean:: should the scanning recurse into the directory
106
+ def notice_dir(relative_position)
107
+ true
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,59 @@
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
+ require 'digest/sha1'
26
+
27
+ module RightScraper
28
+ module Scanners
29
+ # Build manifests from a filesystem.
30
+ class CookbookManifest < Base
31
+ # Create a new manifest scanner. Does not accept any new arguments.
32
+ def initialize(*args)
33
+ super
34
+ @manifest = {}
35
+ end
36
+
37
+ # Complete a scan for the given resource.
38
+ #
39
+ # === Parameters ===
40
+ # resource(RightScraper::Resources::Base):: resource to scan
41
+ def end(resource)
42
+ resource.manifest = @manifest
43
+ @manifest = {}
44
+ end
45
+
46
+ # Notice a file during scanning.
47
+ #
48
+ # === Block ===
49
+ # Return the data for this file. We use a block because it may
50
+ # not always be necessary to read the data.
51
+ #
52
+ # === Parameters ===
53
+ # relative_position(String):: relative pathname for file from root of resource
54
+ def notice(relative_position)
55
+ @manifest[relative_position] = Digest::SHA1.hexdigest(yield)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,69 @@
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 'json'
25
+
26
+ module RightScraper
27
+ module Scanners
28
+ # Load cookbook metadata from a filesystem.
29
+ class CookbookMetadata < Base
30
+ # Begin a scan for the given cookbook.
31
+ #
32
+ # === Parameters
33
+ # cookbook(RightScraper::Resources::Cookbook):: cookbook to scan
34
+ def begin(cookbook)
35
+ @cookbook = cookbook
36
+ end
37
+
38
+ # Notice a file during scanning.
39
+ #
40
+ # === Block
41
+ # Return the data for this file. We use a block because it may
42
+ # not always be necessary to read the data.
43
+ #
44
+ # === Parameters
45
+ # relative_position(String):: relative pathname for the file from root of cookbook
46
+ def notice(relative_position)
47
+ if relative_position == "metadata.json"
48
+ @logger.operation(:metadata_parsing) do
49
+ @cookbook.metadata = JSON.parse(yield)
50
+ end
51
+ end
52
+ end
53
+
54
+ # Notice a directory during scanning. Since metadata.json is by
55
+ # definition only in the root directory we don't need to recurse,
56
+ # but we do need to go into the first directory (identified by
57
+ # +relative_position+ being +nil+).
58
+ #
59
+ # === Parameters
60
+ # relative_position(String):: relative pathname for the directory from root of cookbook
61
+ #
62
+ # === Returns
63
+ # Boolean:: should the scanning recurse into the directory
64
+ def notice_dir(relative_position)
65
+ relative_position == nil
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,84 @@
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 'right_aws'
24
+ require 'json'
25
+
26
+ module RightScraper
27
+ module Scanners
28
+ # Upload scanned files to an S3 bucket.
29
+ class CookbookS3Upload < Base
30
+ # Create a new S3Upload. In addition to the options recognized
31
+ # by Scanner, this class recognizes <tt>:s3_key</tt>,
32
+ # <tt>:s3_secret</tt>, and <tt>:s3_bucket</tt> and requires all
33
+ # of those.
34
+ #
35
+ # === Options
36
+ # <tt>:s3_key</tt>:: Required. S3 access key.
37
+ # <tt>:s3_secret</tt>:: Required. S3 secret key.
38
+ # <tt>:s3_bucket</tt>:: Required. Bucket to upload cookbooks to.
39
+ #
40
+ # === Parameters
41
+ # options(Hash):: scanner options
42
+ def initialize(options={})
43
+ super
44
+ s3_key = options.fetch(:s3_key)
45
+ s3_secret = options.fetch(:s3_secret)
46
+ s3 = RightAws::S3.new(aws_access_key_id=s3_key,
47
+ aws_secret_access_key=s3_secret,
48
+ :logger => Logger.new)
49
+ @bucket = s3.bucket(options.fetch(:s3_bucket))
50
+ raise "Need an actual, existing S3 bucket!" if @bucket.nil?
51
+ end
52
+
53
+ # Upon ending a scan for a cookbook, upload the cookbook
54
+ # contents to S3.
55
+ #
56
+ # === Parameters
57
+ # cookbook(RightScraper::Cookbook):: cookbook to scan
58
+ def end(cookbook)
59
+ @bucket.put(File.join('Cooks', cookbook.resource_hash),
60
+ {
61
+ :metadata => cookbook.metadata,
62
+ :manifest => cookbook.manifest
63
+ }.to_json)
64
+ end
65
+
66
+ # Upload a file during scanning.
67
+ #
68
+ # === Block
69
+ # Return the data for this file. We use a block because it may
70
+ # not always be necessary to read the data.
71
+ #
72
+ # === Parameters
73
+ # relative_position(String):: relative pathname for file from root of cookbook
74
+ def notice(relative_position)
75
+ contents = yield
76
+ name = Digest::SHA1.hexdigest(contents)
77
+ path = File.join('Files', name)
78
+ unless @bucket.key(path).exists?
79
+ @bucket.put(path, contents)
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,89 @@
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 Scanners
26
+ # Union scanner, to permit running multiple scanners while only
27
+ # walking the fs once.
28
+ class Union
29
+ # Create a new union scanner. Recognizes no new options.
30
+ #
31
+ # === Parameters
32
+ # classes(List):: List of Scanner classes to run
33
+ # options(Hash):: scanner options
34
+ def initialize(classes, options={})
35
+ @subscanners = classes.map {|klass| klass.new(options)}
36
+ end
37
+
38
+ # Notify subscanners that all scans have completed.
39
+ def finish
40
+ @subscanners.each {|scanner| scanner.finish}
41
+ end
42
+
43
+ # Begin a scan for the given resource.
44
+ #
45
+ # === Parameters
46
+ # resource(RightScraper::Resource::Base):: resource to scan
47
+ def begin(resource)
48
+ @subscanners.each {|scanner| scanner.begin(resource)}
49
+ end
50
+
51
+ # Finish a scan for the given resource.
52
+ #
53
+ # === Parameters
54
+ # resource(RightScraper::Resource::Base):: resource that just finished scanning
55
+ def end(resource)
56
+ @subscanners.each {|scanner| scanner.end(resource)}
57
+ end
58
+
59
+ # Notice a file during scanning.
60
+ #
61
+ # === Block
62
+ # Return the data for this file. We use a block because it may
63
+ # not always be necessary to read the data.
64
+ #
65
+ # === Parameters
66
+ # relative_position(String):: relative pathname for the file from the root of resource
67
+ def notice(relative_position)
68
+ data = nil
69
+ @subscanners.each {|scanner| scanner.notice(relative_position) {
70
+ data = yield if data.nil?
71
+ data
72
+ }
73
+ }
74
+ end
75
+
76
+ # Notice a directory during scanning. Returns true if any of the
77
+ # subscanners report that they should recurse into the directory.
78
+ #
79
+ # === Parameters
80
+ # relative_position(String):: relative pathname for directory from root of resource
81
+ #
82
+ # === Returns
83
+ # Boolean:: should the scanning recurse into the directory
84
+ def notice_dir(relative_position)
85
+ @subscanners.any? {|scanner| scanner.notice_dir(relative_position)}
86
+ end
87
+ end
88
+ end
89
+ end