Class: FogSite::Deployer

Inherits:
Object
  • Object
show all
Defined in:
lib/fog_site.rb

Overview

Used to actually execute a deploy. This object is not safe for reuse - the ‘@index` and `@updated_paths` stay dirty after a deploy to allow debugging and inspection by client scripts.

Defined Under Namespace

Classes: UsageError

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(site) ⇒ Deployer

Returns a new instance of Deployer.



46
47
48
49
50
# File 'lib/fog_site.rb', line 46

def initialize( site )
  @site = site
  @index = {}
  @updated_paths = []
end

Instance Attribute Details

#indexObject (readonly)

Returns the value of attribute index.



37
38
39
# File 'lib/fog_site.rb', line 37

def index
  @index
end

#updated_pathsObject (readonly)

Returns the value of attribute updated_paths.



37
38
39
# File 'lib/fog_site.rb', line 37

def updated_paths
  @updated_paths
end

Class Method Details

.run(site, options = {}) ⇒ Object

Run a single deploy. Creates a new ‘Deployer` and calls `run`.



41
42
43
44
# File 'lib/fog_site.rb', line 41

def self.run( site, options = {} )
  deployer = Deployer.new( site )
  deployer.run
end

Instance Method Details

#assert_not_nil(value, error) ⇒ Object

Raises:



158
159
160
# File 'lib/fog_site.rb', line 158

def assert_not_nil( value, error )
  raise UsageError.new( error ) unless value
end

#build_indexObject

Build an index of all the local files and their md5 sums. This will be used to decide what needs to be deployed.



88
89
90
91
92
93
94
# File 'lib/fog_site.rb', line 88

def build_index
  Dir["**/*"].each do |path|
    unless File.directory?( path )
      @index[path] = Digest::MD5.file(path).to_s
    end
  end
end

#cdnObject



142
143
144
# File 'lib/fog_site.rb', line 142

def cdn
  @cdn ||= Fog::CDN.new( credentials )
end

#connectionObject



146
147
148
# File 'lib/fog_site.rb', line 146

def connection
  @connection ||= Fog::Storage.new( credentials )
end

#credentialsObject



150
151
152
153
154
155
156
# File 'lib/fog_site.rb', line 150

def credentials
  {
    :provider              => 'AWS',
    :aws_access_key_id     => @site.access_key_id,
    :aws_secret_access_key => @site.secret_key
  }
end

#invalidate_cache(distribution_id) ⇒ Object

Compose and post a cache invalidation request to CloudFront. This will ensure that all CloudFront distributions get the latest content quickly.



136
137
138
139
140
# File 'lib/fog_site.rb', line 136

def invalidate_cache( distribution_id )
  unless @updated_paths.empty?
    cdn.post_invalidation distribution_id, @updated_paths
  end
end

#make_directoryObject

Creates an S3 bucket for web site serving, using ‘index.html` and `404.html` as our special pages.



74
75
76
77
78
79
80
81
82
83
84
# File 'lib/fog_site.rb', line 74

def make_directory
  domain = @site.domain_name
  puts "Using bucket: #{domain}".blue
  @directory = connection.directories.get domain
  unless @directory
    puts "Creating nw bucket.".red
    @directory = connection.directories.create :key => domain,
                                              :public => true
  end
  connection.put_bucket_website(domain, 'index.html', :key => "404.html")
end

#runObject

Validate our ‘Site`, create a and configure a bucket, build the index, sync the files and (finally) invalidate all paths which have been updated on the content distribution network.



55
56
57
58
59
60
61
62
63
64
65
# File 'lib/fog_site.rb', line 55

def run
  validate
  make_directory
  Dir.chdir @site.path do
    build_index
    sync_remote
    if( @site.distribution_id )
      invalidate_cache(@site.distribution_id)
    end
  end
end

#sync_remoteObject

Synchronize our local copy of the site with the remote one. This uses the index to detect what has been changed and upload only new/updated files. Helpful debugging information is emitted, and we’re left with a populated ‘updated_paths` instance variable which can be used to invalidate cached content.



101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/fog_site.rb', line 101

def sync_remote
  @directory.files.each do |remote_file|
    path = remote_file.key
    local_file_md5 = @index[path]

    if local_file_md5.nil? and @site.destroy_old_files
      puts "#{path}: deleted".red
      remote_file.destroy
      @updated_paths << ("/" + path)
    elsif local_file_md5 == remote_file.etag
      puts "#{path}: unchanged".white
      @index.delete( path )
    else
      puts "#{path}: updated".green
      write_file( path )
      @index.delete( path )
      @updated_paths << ("/" + path)
    end
  end

  @index.each do |path, md5|
    puts "#{path}: new".green
    write_file( path )
  end
end

#validateObject



67
68
69
70
# File 'lib/fog_site.rb', line 67

def validate
  assert_not_nil @site.access_key_id, "No AccessKeyId specified"
  assert_not_nil @site.secret_key, "No SecretKey specified"
end

#write_file(path) ⇒ Object

Push a single file out to S3.



128
129
130
131
132
# File 'lib/fog_site.rb', line 128

def write_file( path )
  @directory.files.create :key => path,
                          :body => File.open( path ),
                          :public => true
end