ale 0.0.3.pre3 → 0.0.3.pre4

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/README.md CHANGED
@@ -10,15 +10,6 @@ Installation
10
10
 
11
11
  gem install ale
12
12
 
13
- Setting Up a Website
14
- --------------------
13
+ Getting Started
14
+ ---------------
15
15
 
16
- Getting a S3 bucket set up for websites takes a little bit of work up front,
17
- but it is something you only have to do once and then it is smooth saling.
18
- Starting by logging into (S3 console)[http://console.aws.amazon.com/] and
19
- creating a bucket with the same name as the URL for you website. Make sure
20
- that the bucket includes a subdomain (like 'www', for example). Once you've
21
- created your bucket, click on *Properties* nears the top and then on the
22
- tab named *Website*. Check the box labeled *Enabled* and then fill in
23
- the text box for *Index Document* (something like `index.html` works well).
24
- That's it for S3.
@@ -18,6 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.files = `git ls-files`.split("\n")
19
19
  s.require_paths = ['lib']
20
20
 
21
- s.add_dependency('aws-sdk', '~> 1.1.3')
22
- s.add_dependency('thor', '~> 0.14.6')
21
+ s.add_dependency('crack', '~> 0.3.1')
22
+ s.add_dependency('net-http-persistent', '~> 2.1')
23
+ s.add_dependency('thor', '~> 0.14.6')
23
24
  end
data/lib/ale.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  module Ale
2
+ autoload :Bucket, 'ale/bucket'
2
3
  autoload :CLI, 'ale/cli'
3
4
  autoload :Config, 'ale/config'
4
5
  autoload :Site, 'ale/site'
@@ -0,0 +1,130 @@
1
+ require 'base64'
2
+ require 'crack'
3
+ require 'mime/types'
4
+ require 'net/http/persistent'
5
+ require 'time'
6
+
7
+ module Ale
8
+ class Bucket
9
+ attr_reader :name
10
+
11
+ class << self
12
+ def create(name)
13
+ self.new(name).tap {|bucket| bucket.create }
14
+ end
15
+ end
16
+
17
+ def initialize(name)
18
+ @name = name
19
+ end
20
+
21
+ # Creates the bucket on S3. It does not throw an error if the bucket
22
+ # already exsists.
23
+ #
24
+ def create
25
+ request = Net::HTTP::Put.new(uri.request_uri)
26
+ request.add_field('x-amz-acl', 'private')
27
+ send(uri, request)
28
+ end
29
+
30
+ # Allows the bucket to be used to host websites.
31
+ #
32
+ def enable_website
33
+ uri = uri(query: 'website')
34
+ request = Net::HTTP::Put.new(uri.request_uri)
35
+ request.body = File.read(File.expand_path('../../templates/website_configuration.xml', __FILE__))
36
+ send(uri, request)
37
+ end
38
+
39
+ # Returns true of the bucket exsists on S3.
40
+ #
41
+ def exists?
42
+ request = Net::HTTP::Head.new(uri.request_uri)
43
+ send(uri, request) do |response|
44
+ return response.class == Net::HTTPOK
45
+ end
46
+ end
47
+
48
+ # Returns an array of all of the objects in the bucket.
49
+ #
50
+ def objects
51
+ uri = uri(prefix: 'prefix=/')
52
+ request = Net::HTTP::Get.new(uri.request_uri)
53
+ send(uri, request) do |response|
54
+ list = Crack::XML.parse(response.body)
55
+ # Make sure we're returning an Array.
56
+ return [list['ListBucketResult']['Contents']].flatten.compact
57
+ end
58
+ end
59
+
60
+ # Removes an object form the bucket.
61
+ #
62
+ def remove(key)
63
+ uri = uri(key)
64
+ request = Net::HTTP::Delete.new(uri.request_uri)
65
+ send(uri, request)
66
+ end
67
+
68
+ # Uploads a file to the specified key on S3.
69
+ #
70
+ def upload(file, key, permissions = 'private')
71
+ uri = uri(key)
72
+ file = File.open(file, 'rb')
73
+ request = Net::HTTP::Put.new(uri.request_uri)
74
+ request.add_field('Content-Length', file.size)
75
+ request.add_field('Content-Type', MIME::Types.of(file.path))
76
+ request.add_field('x-amz-acl', permissions)
77
+ request.body_stream = file
78
+ send(uri, request)
79
+ end
80
+
81
+ private
82
+
83
+ # Creates an authorization string for the request.
84
+ # http://s3.amazonaws.com/doc/s3-developer-guide/RESTAuthentication.html
85
+ #
86
+ def authorization(uri, request)
87
+ string_to_sign = "#{request.class::METHOD}\n"
88
+ string_to_sign << "\n"
89
+ string_to_sign << "#{request['Content-Type']}\n"
90
+ string_to_sign << "#{request['Date']}\n"
91
+
92
+ amz_headers = request.to_hash.collect {|h,v| "#{h}:#{v.join(',')}" if h =~ /x-amz-/ }.compact.sort
93
+ string_to_sign << amz_headers.join("\n") << "\n" unless amz_headers.empty?
94
+
95
+ string_to_sign << uri.request_uri
96
+
97
+ digest = OpenSSL::HMAC.digest(OpenSSL::Digest::Digest.new('sha1'), Ale::Config.amazon_secret_access_key, string_to_sign)
98
+ signature = Base64.encode64(digest).chomp
99
+
100
+ "AWS #{Ale::Config.amazon_access_key_id}:#{signature}"
101
+ end
102
+
103
+ # Helps construct URIs for interacting the S3's REST API.
104
+ #
105
+ def uri(options_or_path = {}, options = {})
106
+ if options_or_path.is_a?(Hash)
107
+ options, path = options_or_path, '/'
108
+ else
109
+ path = options_or_path
110
+ end
111
+ path = URI.escape(path.sub(/^\//, ''))
112
+ URI::HTTP.build(options.merge(host: 's3.amazonaws.com', path: "/#{name}/#{path}"))
113
+ end
114
+
115
+ def connection
116
+ @_connection ||= Net::HTTP::Persistent.new("ale/#{name}")
117
+ end
118
+
119
+ # Send a request object to the URI passed in.
120
+ #
121
+ def send(uri, request, &block)
122
+ unless request.to_hash.key?('Content-Type')
123
+ request.add_field('Content-Type', 'application/x-www-form-urlencoded')
124
+ end
125
+ request.add_field('Date', Time.now.utc.rfc822)
126
+ request.add_field('Authorization', authorization(uri, request))
127
+ connection.request(uri, request, &block)
128
+ end
129
+ end
130
+ end
@@ -33,6 +33,21 @@ module Ale
33
33
  end
34
34
  end
35
35
 
36
+ desc 'setup', 'Creates the bucket on S3 and enabled it for websites'
37
+ def setup
38
+ opts = options.dup
39
+
40
+ Ale.alefile = opts[:alefile]
41
+ Ale::Config.load(Ale.alefile)
42
+
43
+ say("Setting up website for bucket: #{Ale::Config.bucket}")
44
+ uploader.setup!
45
+ rescue AlefileNotFound
46
+ say('Count not locale Alefile', :red)
47
+ rescue BucketNotSpecified
48
+ say('No bucket specificed in Alefile', :red)
49
+ end
50
+
36
51
  desc 'upload', 'Uploads the built site to S3'
37
52
  method_option 'alefile', :type => :string, :banner =>
38
53
  'Use the specified alefile instead of Alefile'
@@ -42,9 +57,8 @@ module Ale
42
57
  Ale.alefile = opts[:alefile]
43
58
  Ale::Config.load(Ale.alefile)
44
59
 
45
- uploader.upload!
46
-
47
60
  say("Uploading site in #{uploader.site.directory}")
61
+ uploader.upload!
48
62
  rescue AlefileNotFound
49
63
  say('Count not locale Alefile', :red)
50
64
  rescue BucketNotFound
@@ -1,9 +1,12 @@
1
- require 'aws-sdk'
2
-
3
1
  module Ale
4
2
  class Uploader
5
3
  attr_reader :site
6
4
 
5
+ def setup!
6
+ Ale::Bucket.create(Ale::Config.bucket)
7
+ bucket.enable_website
8
+ end
9
+
7
10
  def initialize(site)
8
11
  @site = site
9
12
  end
@@ -18,7 +21,7 @@ module Ale
18
21
  def bucket
19
22
  return @bucket unless @bucket.nil?
20
23
  raise Ale::BucketNotSpecified if Ale::Config.bucket.empty?
21
- @bucket = AWS::S3.new.buckets[Ale::Config.bucket]
24
+ @bucket = Ale::Bucket.new(Ale::Config.bucket)
22
25
  raise Ale::BucketNotFound unless @bucket.exists?
23
26
  @bucket
24
27
  end
@@ -45,7 +48,7 @@ module Ale
45
48
  end
46
49
 
47
50
  def permissions(file)
48
- private_files.include?(file) ? :private : :public_read
51
+ private_files.include?(file) ? 'private' : 'public-read'
49
52
  end
50
53
 
51
54
  def private_files
@@ -58,9 +61,9 @@ module Ale
58
61
 
59
62
  def remove_stale_files_from_s3
60
63
  bucket.objects.each do |object|
61
- unless files.include?("#{site.directory}/#{object.key}")
62
- puts "Deleting old file #{object.key}"
63
- object.delete
64
+ unless files.include?("#{site.directory}/#{object['Key']}")
65
+ puts "Deleting old file #{object['Key']}"
66
+ bucket.remove(object['Key'])
64
67
  end
65
68
  end
66
69
  end
@@ -69,17 +72,21 @@ module Ale
69
72
  files.each do |file|
70
73
  unless File.directory?(file)
71
74
  key = key_name(file)
72
- object = bucket.objects[key]
73
- if object.exists?
74
- if object.last_modified < File.mtime(file)
75
+ keys_on_s3 = bucket.objects.map {|object| object['Key']}
76
+
77
+ if keys_on_s3.include?(key)
78
+ object = bucket.objects.find {|obj| obj['Key'] == key }
79
+ last_modified = Time.parse(object['LastModified'])
80
+
81
+ if last_modified < File.mtime(file)
75
82
  puts "Updating file #{key}"
76
- object.write(:file => file, :acl => permissions(file))
83
+ bucket.upload(file, key, permissions(file))
77
84
  else
78
85
  puts "File #{key} is already on S3"
79
86
  end
80
87
  else
81
- puts "Uploading filed #{key}"
82
- object.write(:file => file, :acl => permissions(file))
88
+ puts "Uploading file #{key}"
89
+ bucket.upload(file, key, permissions(file))
83
90
  end
84
91
  end
85
92
  end
@@ -1,3 +1,3 @@
1
1
  module Ale
2
- VERSION = '0.0.3.pre3'
2
+ VERSION = '0.0.3.pre4'
3
3
  end
@@ -0,0 +1,8 @@
1
+ <WebsiteConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
2
+ <IndexDocument>
3
+ <Suffix>index.html</Suffix>
4
+ </IndexDocument>
5
+ <ErrorDocument>
6
+ <Key>404.html</Key>
7
+ </ErrorDocument>
8
+ </WebsiteConfiguration>
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ale
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3.pre3
4
+ version: 0.0.3.pre4
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,33 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-10-06 00:00:00.000000000Z
12
+ date: 2011-10-09 00:00:00.000000000Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: aws-sdk
16
- requirement: &70174158803320 !ruby/object:Gem::Requirement
15
+ name: crack
16
+ requirement: &70280802231900 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: 1.1.3
21
+ version: 0.3.1
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70174158803320
24
+ version_requirements: *70280802231900
25
+ - !ruby/object:Gem::Dependency
26
+ name: net-http-persistent
27
+ requirement: &70280802230400 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ~>
31
+ - !ruby/object:Gem::Version
32
+ version: '2.1'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70280802230400
25
36
  - !ruby/object:Gem::Dependency
26
37
  name: thor
27
- requirement: &70174158802060 !ruby/object:Gem::Requirement
38
+ requirement: &70280802227160 !ruby/object:Gem::Requirement
28
39
  none: false
29
40
  requirements:
30
41
  - - ~>
@@ -32,7 +43,7 @@ dependencies:
32
43
  version: 0.14.6
33
44
  type: :runtime
34
45
  prerelease: false
35
- version_requirements: *70174158802060
46
+ version_requirements: *70280802227160
36
47
  description: Takes a static site and uploads it to Amazon's S3.
37
48
  email: jeremy@jeremyboles.com
38
49
  executables:
@@ -47,12 +58,14 @@ files:
47
58
  - ale.gemspec
48
59
  - bin/ale
49
60
  - lib/ale.rb
61
+ - lib/ale/bucket.rb
50
62
  - lib/ale/cli.rb
51
63
  - lib/ale/config.rb
52
64
  - lib/ale/site.rb
53
65
  - lib/ale/uploader.rb
54
66
  - lib/ale/version.rb
55
67
  - lib/templates/Alefile
68
+ - lib/templates/website_configuration.xml
56
69
  - test/ale_defaults_test.rb
57
70
  - test/test_helper.rb
58
71
  homepage: https://github.com/jeremyboles/ale