ale 0.0.3.pre3 → 0.0.3.pre4

Sign up to get free protection for your applications and to get access to all the features.
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