ponyhost 0.1
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 +8 -0
- data/bin/ponyhost +60 -0
- data/lib/ponyhost.rb +138 -0
- metadata +69 -0
data/README.md
ADDED
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
|
+
|