microstatic 0.3.0 → 0.4.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.
- data/README.md +3 -0
- data/bin/microstatic +3 -12
- data/lib/microstatic.rb +2 -0
- data/lib/microstatic/cli.rb +72 -0
- data/lib/microstatic/config.rb +28 -0
- data/lib/microstatic/rake.rb +1 -1
- data/lib/microstatic/route53_dns.rb +42 -0
- data/lib/microstatic/s3_bucket_creator.rb +6 -3
- data/lib/microstatic/s3_deployer.rb +8 -2
- data/lib/microstatic/uses_fog.rb +10 -0
- data/lib/microstatic/version.rb +1 -1
- data/microstatic.gemspec +2 -0
- data/spec/integration/spec_helper.rb +7 -0
- metadata +39 -4
data/README.md
CHANGED
data/bin/microstatic
CHANGED
@@ -1,17 +1,8 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
require 'microstatic'
|
4
|
+
require 'microstatic/cli'
|
4
5
|
|
5
|
-
if
|
6
|
-
puts 'please specify a bucket name'
|
7
|
-
exit 1
|
8
|
-
end
|
6
|
+
require 'pry' if ENV.has_key? 'PRY_PLEASE'
|
9
7
|
|
10
|
-
|
11
|
-
|
12
|
-
bucket_creator = Microstatic::S3BucketCreator.new( Microstatic.aws_creds_from_env )
|
13
|
-
|
14
|
-
puts "creating bucket #{bucket_name} ..."
|
15
|
-
bucket_creator.create( bucket_name )
|
16
|
-
|
17
|
-
puts "done"
|
8
|
+
Microstatic::CLI.start(ARGV)
|
data/lib/microstatic.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
require "microstatic/version"
|
2
2
|
|
3
|
+
require 'microstatic/config'
|
3
4
|
require 'microstatic/uses_fog'
|
4
5
|
|
5
6
|
require "microstatic/s3_deployer"
|
6
7
|
require "microstatic/s3_bucket_creator"
|
8
|
+
require "microstatic/route53_dns"
|
7
9
|
|
8
10
|
module Microstatic
|
9
11
|
def self.aws_creds_from_env
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'rainbow'
|
3
|
+
|
4
|
+
module Microstatic
|
5
|
+
class CLI < Thor
|
6
|
+
desc "setup <APP_NAME>", "do the needful to get started hosting your static site. S3, Route 53, whatever it takes."
|
7
|
+
def setup( app_name = false )
|
8
|
+
app_name ||= inferred_app_name
|
9
|
+
bucket_name = subdomain_for(app_name)
|
10
|
+
|
11
|
+
bucket = bucket( bucket_name )
|
12
|
+
# TODO: pass bucket through to dns setup so we don't have to look it up again
|
13
|
+
dns( app_name )
|
14
|
+
|
15
|
+
# TODO: add Rakefile, Gemfile, etc for doing a rake deploy using this gem
|
16
|
+
end
|
17
|
+
|
18
|
+
desc "bucket <BUCKET_NAME>", "create an S3 bucket which can host your static site"
|
19
|
+
def bucket( bucket_name = false )
|
20
|
+
bucket_name ||= guess_bucket_name
|
21
|
+
# TODO: check it doesn't already exist for you
|
22
|
+
# TODO: check bucket_name looks like a site name (e.g. foo.thepete.net, not just foo)
|
23
|
+
# TODO: handle the bucket name already being taken by someone else
|
24
|
+
# TODO: fail gracefully if aws creds not available
|
25
|
+
|
26
|
+
describe_operation( "create S3 bucket '#{bucket_name}'" ) do
|
27
|
+
S3BucketCreator.new( config.aws_creds ).create( bucket_name )
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "dns <APP_NAME>", "create a Route 53 entry pointing to the S3 bucket containing your static site"
|
32
|
+
def dns( app_name = false )
|
33
|
+
app_name ||= inferred_app_name
|
34
|
+
bucket_name = subdomain_for(app_name)
|
35
|
+
|
36
|
+
describe_operation( "create Route 53 entry '#{bucket_name}'" ) do
|
37
|
+
Route53Dns.new( config.aws_creds ).add_s3_record_for_bucket( bucket_name )
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def guess_bucket_name
|
44
|
+
subdomain_for( inferred_app_name )
|
45
|
+
end
|
46
|
+
|
47
|
+
def subdomain_for( app_name )
|
48
|
+
"#{app_name}.#{config.site_name}"
|
49
|
+
end
|
50
|
+
|
51
|
+
def inferred_app_name
|
52
|
+
File.basename(Dir.pwd)
|
53
|
+
end
|
54
|
+
|
55
|
+
def config
|
56
|
+
Config.automagic
|
57
|
+
end
|
58
|
+
|
59
|
+
def describe_operation( operation_desc )
|
60
|
+
STDOUT.print " #{operation_desc} ..."
|
61
|
+
yield
|
62
|
+
STDOUT.puts "\r- #{operation_desc} "+CHECKMARK
|
63
|
+
rescue
|
64
|
+
STDOUT.puts "\r- #{operation_desc} "+SADMARK
|
65
|
+
raise
|
66
|
+
end
|
67
|
+
|
68
|
+
CHECKMARK="\u2713".color(:green)
|
69
|
+
SADMARK="\u2718".color(:red)
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Microstatic
|
2
|
+
class Config
|
3
|
+
def self.automagic
|
4
|
+
#in the future this'll try to create a config based on
|
5
|
+
#various diff. files, in priority order?
|
6
|
+
self.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def site_name
|
10
|
+
ENV.fetch('MICROSTATIC_SITE_NAME')
|
11
|
+
end
|
12
|
+
|
13
|
+
def aws_creds
|
14
|
+
{
|
15
|
+
:access_key_id => aws_access_key_id,
|
16
|
+
:secret_access_key => aws_secret_access_key
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
def aws_access_key_id
|
21
|
+
ENV.fetch('AWS_ACCESS_KEY_ID')
|
22
|
+
end
|
23
|
+
|
24
|
+
def aws_secret_access_key
|
25
|
+
ENV.fetch('AWS_SECRET_ACCESS_KEY')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/lib/microstatic/rake.rb
CHANGED
@@ -0,0 +1,42 @@
|
|
1
|
+
module Microstatic
|
2
|
+
|
3
|
+
class Route53Dns
|
4
|
+
include UsesFog
|
5
|
+
|
6
|
+
def initialize( aws_creds )
|
7
|
+
check_and_store_aws_creds(aws_creds)
|
8
|
+
end
|
9
|
+
|
10
|
+
def add_s3_record_for_bucket( bucket_name, hostname = false )
|
11
|
+
subdomain ||= bucket_name
|
12
|
+
|
13
|
+
zone = parent_zone_for_subdomain( subdomain )
|
14
|
+
cname_value = website_endpoint_for_bucket_named( bucket_name )
|
15
|
+
|
16
|
+
record = zone.records.create(
|
17
|
+
:name => subdomain,
|
18
|
+
:value => cname_value,
|
19
|
+
:type => 'CNAME',
|
20
|
+
:ttl => 86400
|
21
|
+
)
|
22
|
+
record
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def website_endpoint_for_bucket_named( bucket_name )
|
28
|
+
bucket = connection.directories.get(bucket_name)
|
29
|
+
|
30
|
+
# per http://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteEndpoints.html
|
31
|
+
#TODO: get endpoint from API, or get this logic merged into fog
|
32
|
+
bucket_website_endpoint = "#{bucket.key}.s3-website-#{bucket.location}.amazonaws.com"
|
33
|
+
end
|
34
|
+
|
35
|
+
def parent_zone_for_subdomain( subdomain )
|
36
|
+
zone_name = subdomain.split(".")[1..-1].push("").join(".")
|
37
|
+
dns.zones.find{ |x| x.domain == zone_name }
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -8,9 +8,12 @@ class S3BucketCreator
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def create( bucket_name )
|
11
|
-
|
12
|
-
connection.
|
13
|
-
|
11
|
+
# TODO: can we create a new directory without eagerly fetch the list of all dirs?
|
12
|
+
directory = connection.directories.create( :key => bucket_name, :public => true )
|
13
|
+
# TODO: can I do this by calling a method on directory?
|
14
|
+
connection.put_bucket_website( directory.key, 'index.html', :key => '404.html' )
|
15
|
+
|
16
|
+
directory
|
14
17
|
end
|
15
18
|
end
|
16
19
|
|
@@ -31,7 +31,7 @@ class S3Deployer
|
|
31
31
|
|
32
32
|
if !s3_object
|
33
33
|
log_action('CREATE', s3_key)
|
34
|
-
|
34
|
+
put_file( s3_key, file )
|
35
35
|
else
|
36
36
|
s3_md5 = s3_object.headers['ETag'].sub(/"(.*)"/,'\1')
|
37
37
|
local_md5 = Digest::MD5.hexdigest( file.read )
|
@@ -40,11 +40,17 @@ class S3Deployer
|
|
40
40
|
log_action('NO CHANGE', s3_key)
|
41
41
|
else
|
42
42
|
log_action('UPDATE', s3_key)
|
43
|
-
|
43
|
+
put_file( s3_key, file )
|
44
44
|
end
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
+
private
|
49
|
+
|
50
|
+
def put_file( s3_key, file )
|
51
|
+
connection.put_object( @bucket, s3_key, file.open, 'x-amz-acl' => 'public-read', 'x-amz-storage-class' => 'REDUCED_REDUNDANCY' )
|
52
|
+
end
|
53
|
+
|
48
54
|
def log_action(action,file)
|
49
55
|
message = action.to_s.rjust(10) + " " + file
|
50
56
|
puts message
|
data/lib/microstatic/uses_fog.rb
CHANGED
@@ -10,8 +10,18 @@ module Microstatic
|
|
10
10
|
@aws_creds = aws_creds
|
11
11
|
end
|
12
12
|
|
13
|
+
# TODO: rename connection to storage
|
13
14
|
def connection
|
14
15
|
@_connection ||= Fog::Storage.new({
|
16
|
+
:provider => 'AWS',
|
17
|
+
:aws_access_key_id => @aws_creds.fetch(:access_key_id),
|
18
|
+
:aws_secret_access_key => @aws_creds.fetch(:secret_access_key),
|
19
|
+
:path_style => true
|
20
|
+
})
|
21
|
+
end
|
22
|
+
|
23
|
+
def dns
|
24
|
+
@_dns ||= Fog::DNS.new({
|
15
25
|
:provider => 'AWS',
|
16
26
|
:aws_access_key_id => @aws_creds.fetch(:access_key_id),
|
17
27
|
:aws_secret_access_key => @aws_creds.fetch(:secret_access_key)
|
data/lib/microstatic/version.rb
CHANGED
data/microstatic.gemspec
CHANGED
@@ -16,6 +16,8 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.version = Microstatic::VERSION
|
17
17
|
|
18
18
|
gem.add_runtime_dependency "fog", ">=1"
|
19
|
+
gem.add_runtime_dependency "thor", ">=0.15" # 0.15 is an arbitrary guess at what might be API-compatible
|
20
|
+
gem.add_runtime_dependency "rainbow", ">= 1.1"
|
19
21
|
|
20
22
|
gem.add_development_dependency "rake"
|
21
23
|
gem.add_development_dependency "bundler"
|
@@ -1,3 +1,10 @@
|
|
1
1
|
require_relative '../../lib/microstatic'
|
2
|
+
# require_relative '../../lib/microstatic/uses_fog'
|
2
3
|
|
4
|
+
if ENV['FOG_MOCK']
|
5
|
+
Fog.mock!
|
6
|
+
include Microstatic::UsesFog
|
7
|
+
check_and_store_aws_creds(Microstatic.aws_creds_from_env)
|
8
|
+
connection.directories.create(:key => 'microstatic-test-bucket')
|
9
|
+
end
|
3
10
|
require 'pry'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: microstatic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-12-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: fog
|
@@ -27,6 +27,38 @@ dependencies:
|
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '1'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: thor
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0.15'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0.15'
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: rainbow
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ! '>='
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.1'
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.1'
|
30
62
|
- !ruby/object:Gem::Dependency
|
31
63
|
name: rake
|
32
64
|
requirement: !ruby/object:Gem::Requirement
|
@@ -109,7 +141,10 @@ files:
|
|
109
141
|
- Rakefile
|
110
142
|
- bin/microstatic
|
111
143
|
- lib/microstatic.rb
|
144
|
+
- lib/microstatic/cli.rb
|
145
|
+
- lib/microstatic/config.rb
|
112
146
|
- lib/microstatic/rake.rb
|
147
|
+
- lib/microstatic/route53_dns.rb
|
113
148
|
- lib/microstatic/s3_bucket_creator.rb
|
114
149
|
- lib/microstatic/s3_deployer.rb
|
115
150
|
- lib/microstatic/uses_fog.rb
|
@@ -135,7 +170,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
135
170
|
version: '0'
|
136
171
|
segments:
|
137
172
|
- 0
|
138
|
-
hash:
|
173
|
+
hash: 3071074031925254256
|
139
174
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
140
175
|
none: false
|
141
176
|
requirements:
|
@@ -144,7 +179,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
144
179
|
version: '0'
|
145
180
|
segments:
|
146
181
|
- 0
|
147
|
-
hash:
|
182
|
+
hash: 3071074031925254256
|
148
183
|
requirements: []
|
149
184
|
rubyforge_project:
|
150
185
|
rubygems_version: 1.8.25
|