ponyhost 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/README.md +8 -0
  2. data/bin/ponyhost +60 -0
  3. data/lib/ponyhost.rb +138 -0
  4. metadata +69 -0
data/README.md ADDED
@@ -0,0 +1,8 @@
1
+ ponyHost is a super simple way to use the Amazon AWS S3 Website feature.
2
+
3
+ $ cd your-website
4
+ $ gem install ponyhost
5
+ $ ponyhost create foobar
6
+ $ ponyhost push foobar
7
+ $ open http://foobar.ponyho.st
8
+
data/bin/ponyhost ADDED
@@ -0,0 +1,60 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'ponyhost'
4
+
5
+ command = ARGV.shift
6
+ bucketname = ARGV.shift
7
+ bucketname = PonyHost.normalize_bucketname(bucketname) if bucketname
8
+
9
+ if command == "server"
10
+ server()
11
+ elsif command == "list" || (["create", "push", "destroy", "show", "version"].include?(command) && bucketname != nil)
12
+ credentials = PonyHost.obtain_credentials
13
+
14
+ AWS::S3::Base.establish_connection!({
15
+ :access_key_id => credentials[:access_key_id],
16
+ :secret_access_key => credentials[:access_key_secret]
17
+ })
18
+
19
+ if(command == "create")
20
+ PonyHost.create(bucketname)
21
+ elsif(command == "push")
22
+ PonyHost.push(bucketname, ".")
23
+ elsif(command == "autopush")
24
+ # TODO
25
+ # monitor cwd and push automatically?
26
+ elsif(command == "destroy")
27
+ print "Do you really wanna destroy '#{bucketname}' (type 'YES'):"
28
+ PonyHost.destroy(bucketname) if STDIN.gets.chop == "YES"
29
+ elsif(command == "list")
30
+ puts "Your sites:"
31
+ PonyHost.list.each do |name|
32
+ puts "http://#{name}"
33
+ end
34
+ elsif(command == "show")
35
+ # deprecated?
36
+ PonyHost.show(bucketname)
37
+ elsif(command == "version")
38
+ puts "ponyhost version #{PonyHost::VERSION}"
39
+ puts "created by Johannes Wagener http://johannes.wagener.cc"
40
+ end
41
+ else
42
+ puts "usage: ponyhost <command> [<sitename>]"
43
+ puts " "
44
+ puts "available commands:"
45
+ puts " list Lists all sites/buckets from your S3 account"
46
+ puts " create [sitename] Creates a new bucket for your site"
47
+ puts " push [sitename] Pushes the current directory to the specified bucket/site"
48
+ puts " destroy [sitename] Removes all files and destroys the bucket"
49
+ puts " server Runs a local HTTP server for the current directory"
50
+ # puts " version Print version information"
51
+ puts " "
52
+ puts "Notes: if the sitename contains no '.' it will be suffixed with the default domain #{PonyHost::DEFAULT_DOMAIN}"
53
+ puts "To use your own domainname you have to set up the DNS correctly:"
54
+ puts "For a site under a subdomain like www.foobar.com you have to create a CNAME record for www.foobar.com to s3-website-us-east-1.amazonaws.com"
55
+ puts "For a site under a domain like foobar.com you have to create an A record pointing to 72.21.214.197"
56
+ puts "Once thats done you just have to create the site with the correct name:"
57
+ puts "$ ponyhost create www.foobar.com"
58
+ puts " "
59
+
60
+ end
data/lib/ponyhost.rb ADDED
@@ -0,0 +1,138 @@
1
+ require 'yaml'
2
+ require 'aws/s3'
3
+ require 'socket'
4
+ require 'digest/md5'
5
+
6
+ # monkey patch to add website to extract significant parameter
7
+ class AWS::S3::Authentication::CanonicalString
8
+ def extract_significant_parameter
9
+ request.path[/[&?](acl|torrent|logging|website)(?:&|=|$)/, 1]
10
+ end
11
+ end
12
+
13
+
14
+ class PonyHost
15
+ S3_CREDENTIAL_FILES = ["~/.ponyhost.yml"]
16
+ DEFAULT_DOMAIN = "lolcat.biz"
17
+ VERSION = "0.1"
18
+ class << self
19
+
20
+
21
+ def obtain_credentials
22
+ credential_file = File.expand_path(S3_CREDENTIAL_FILES.first)
23
+ if File.exists?(credential_file)
24
+ return YAML.load_file(credential_file)
25
+ else
26
+ puts "AWS Credentials file '#{credential_file}' missing. We'll create one."
27
+ puts "You'll find your Amazon AWS credentials here:"
28
+ puts "https://aws-portal.amazon.com/gp/aws/developer/account/index.html?ie=UTF8&action=access-key"
29
+ #http://aws.amazon.com/account/
30
+ credentials = {}
31
+ print "Your AWS Access Key ID: "
32
+ credentials[:access_key_id] = STDIN.gets.chop
33
+ print "Your AWS Access Key Secret: "
34
+ credentials[:access_key_secret] = STDIN.gets.chop
35
+ File.open(credential_file, "w") {|file| file.puts(credentials.to_yaml) }
36
+ return credentials
37
+ end
38
+ end
39
+
40
+ def create(bucketname)
41
+ bucket = AWS::S3::Bucket.create(bucketname, :access => :public_read)
42
+
43
+ body = '<?xml version="1.0" encoding="UTF-8"?>
44
+ <WebsiteConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
45
+ <IndexDocument><Suffix>index.html</Suffix></IndexDocument>
46
+ <ErrorDocument><Key>404.html</Key></ErrorDocument>
47
+ </WebsiteConfiguration>'
48
+
49
+ res = AWS::S3::Base.request(:put, "/#{bucketname}?website", {}, body)
50
+
51
+ puts "Site created: http://#{bucketname}"
52
+ puts "Push your files with: ponyhost push #{bucketname}"
53
+ end
54
+
55
+ def push(bucketname, directory = ".")
56
+ bucket = AWS::S3::Bucket.find(bucketname)
57
+ file_names = flat_list_directory(Dir.new(directory))
58
+
59
+ file_names.each do |file_name|
60
+ local_md5 = md5sum(file_name).chomp
61
+ remote_md5 = bucket[file_name] && bucket[file_name].about["etag"].gsub('"', '').chomp
62
+ if local_md5.to_s == remote_md5.to_s
63
+ puts "Skipping \t#{file_name}"
64
+ else
65
+ puts "Pushing \t#{file_name}"
66
+ AWS::S3::S3Object.store(file_name, open(file_name), bucketname, :access => :public_read)
67
+ end
68
+ end
69
+ end
70
+
71
+ def list
72
+ AWS::S3::Service.buckets.map(&:name)
73
+ end
74
+
75
+ def destroy(bucketname)
76
+ AWS::S3::Bucket.delete(bucketname, :force => true)
77
+ puts "'#{bucketname} is destroyed"
78
+ end
79
+
80
+ def show(bucketname)
81
+ res = AWS::S3::Base.request(:get, "/#{bucketname}?website") rescue res = $!
82
+ puts res
83
+ end
84
+
85
+ def server(port=9090)
86
+ s=TCPServer.new(port);
87
+ puts "Server running on http://localhost:#{port}"
88
+ loop do
89
+ _ = s.accept
90
+ requested_filename = _.gets.split[1]
91
+ requested_filename = "/index.html" if requested_filename == "/"
92
+ begin
93
+ data = File.read(".#{requested_filename}")
94
+ status = 200
95
+ rescue
96
+ status = 404
97
+ if File.exists?("404.html")
98
+ data = File.read("404.html")
99
+ else
100
+ data = "#{requested_filename} not found and no 404.html error page either."
101
+ end
102
+ end
103
+ status_msg = status == 200 ? "OK" : "NOT FOUND"
104
+ _ << "HTTP/1.0 #{status} #{status_msg}\r\n\r\n#{data}";
105
+
106
+ puts %Q{[#{Time.now}] "GET #{requested_filename}" #{status}}
107
+ _.close
108
+ end
109
+ end
110
+
111
+ def md5sum(file_name)
112
+ Digest::MD5.hexdigest(File.read(file_name))
113
+ end
114
+
115
+ def flat_list_directory(dir, path = "")
116
+ list = []
117
+ dir.each do |entry|
118
+ unless [".", ".."].include?(entry)
119
+ full_entry_path = path == "" ? entry : [path, entry].join("/")
120
+ if File.directory?(full_entry_path)
121
+ list += flat_list_directory(Dir.new(full_entry_path), full_entry_path)
122
+ else
123
+ list << full_entry_path
124
+ end
125
+ end
126
+ end
127
+ list
128
+ end
129
+
130
+ def normalize_bucketname(bucketname)
131
+ if bucketname.include?(".")
132
+ bucketname
133
+ else
134
+ "#{bucketname}.#{DEFAULT_DOMAIN}"
135
+ end
136
+ end
137
+ end
138
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ponyhost
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: "0.1"
6
+ platform: ruby
7
+ authors:
8
+ - Johannes Wagener
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-06-13 00:00:00 +02:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: aws-s3
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
20
+ none: false
21
+ requirements:
22
+ - - ">="
23
+ - !ruby/object:Gem::Version
24
+ version: "0"
25
+ type: :runtime
26
+ version_requirements: *id001
27
+ description: ponyHost allows you to easily create S3 website buckets with a nice hostname and push files to it
28
+ email:
29
+ - johannes@wagener.cc
30
+ executables:
31
+ - ponyhost
32
+ extensions: []
33
+
34
+ extra_rdoc_files: []
35
+
36
+ files:
37
+ - lib/ponyhost.rb
38
+ - README.md
39
+ - bin/ponyhost
40
+ has_rdoc: true
41
+ homepage: http://ponyho.st
42
+ licenses: []
43
+
44
+ post_install_message:
45
+ rdoc_options: []
46
+
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: "0"
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: 1.3.6
61
+ requirements: []
62
+
63
+ rubyforge_project: ponyhost
64
+ rubygems_version: 1.6.2
65
+ signing_key:
66
+ specification_version: 3
67
+ summary: Create super simple S3 powered websites
68
+ test_files: []
69
+