-
Notifications
You must be signed in to change notification settings - Fork 194
Expand file tree
/
Copy pathinstaller.rb
More file actions
166 lines (143 loc) · 6.63 KB
/
installer.rb
File metadata and controls
166 lines (143 loc) · 6.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
require 'instance_agent/plugins/codedeploy/install_instruction'
module InstanceAgent
module Plugins
module CodeDeployPlugin
# Manages install and cleanup files. Also generates and executes
# install instructions based on the files section of the
# application specification file.
class Installer
attr_reader :deployment_archive_dir
attr_reader :deployment_instructions_dir
attr_accessor :file_exists_behavior
def initialize(opts = {})
raise "the deployment_archive_dir option is required" if
opts[:deployment_archive_dir].nil?
raise "the deployment_instructions_dir option is required" if
opts[:deployment_instructions_dir].nil?
raise "the file_exists_behavior option is required" if
opts[:file_exists_behavior].nil?
@deployment_archive_dir = opts[:deployment_archive_dir]
@deployment_instructions_dir = opts[:deployment_instructions_dir]
@file_exists_behavior = opts[:file_exists_behavior]
end
def install(deployment_group_id, application_specification)
cleanup_file = File.join(deployment_instructions_dir, "#{deployment_group_id}-cleanup")
if File.exists?(cleanup_file)
commands = InstanceAgent::Plugins::CodeDeployPlugin::InstallInstruction.parse_remove_commands(File.read(cleanup_file))
commands.each do |cmd|
cmd.execute
end
commands.clear
FileUtils.rm(cleanup_file)
end
instructions = generate_instructions(application_specification)
install_file = File.join(deployment_instructions_dir, "#{deployment_group_id}-install.json")
File.open(install_file, "w") do |f|
f.write(instructions.to_json)
end
File.open(cleanup_file, "w") do |f|
instructions.command_array.each do |cmd|
cmd.execute(f)
end
end
#Unlink references to the CommandBuilder instance that was yielded to the Proc object(code block) in generate_instructions()
instructions.cleanup
instructions = nil
end
private
def generate_instructions(application_specification)
InstanceAgent::Plugins::CodeDeployPlugin::InstallInstruction.generate_instructions() do |i|
application_specification.files.each do |fi|
absolute_source_path = File.join(deployment_archive_dir,
fi.source)
log(:debug, "generating instructions for copying #{fi.source} to #{fi.destination}")
if File.directory?(absolute_source_path) && !File.symlink?(absolute_source_path)
fill_in_missing_ancestors(i, fi.destination)
generate_directory_copy(i, absolute_source_path, fi.destination)
else
file_destination = File.join(fi.destination, File.basename(absolute_source_path))
fill_in_missing_ancestors(i, file_destination)
generate_normal_copy(i, absolute_source_path, file_destination)
end
end
(application_specification.permissions || []).each do |permission|
object = permission.object
log(:debug, "generating instructions for setting permissions on object #{object}")
log(:debug, "it is an existing directory - #{File.directory?(object)}")
if i.copying_file?(object)
if permission.type.include?("file")
log(:debug, "found matching file #{object} to set permissions on")
permission.validate_file_permission
permission.validate_file_acl(object)
i.set_permissions(object, permission)
end
elsif (i.making_directory?(object) || File.directory?(object))
log(:debug, "found matching directory #{object} to search for objects to set permissions on")
i.find_matches(permission).each do|match|
log(:debug, "found matching object #{match} to set permissions on")
i.set_permissions(match, permission)
end
end
end
end
end
private
def generate_directory_copy(i, absolute_source_path, destination)
unless File.directory?(destination)
i.mkdir(destination)
end
(Dir.entries(absolute_source_path) - [".", ".."]).each do |entry|
entry = entry.force_encoding("UTF-8");
absolute_source_path = absolute_source_path.force_encoding("UTF-8");
absolute_entry_path = File.join(absolute_source_path, entry)
entry_destination = File.join(destination, entry)
if File.directory?(absolute_entry_path) && !File.symlink?(absolute_entry_path)
generate_directory_copy(i, absolute_entry_path, entry_destination)
else
generate_normal_copy(i, absolute_entry_path, entry_destination)
end
end
end
private
def generate_normal_copy(i, absolute_source_path, destination)
if File.exists?(destination)
case @file_exists_behavior
when "DISALLOW"
raise "The deployment failed because a specified file already exists at this location: #{destination}"
when "OVERWRITE"
i.copy(absolute_source_path, destination)
when "RETAIN"
# neither generate copy command or fail the deployment
else
raise "The deployment failed because an invalid option was specified for fileExistsBehavior: #{@file_exists_behavior}. Valid options include OVERWRITE, RETAIN, and DISALLOW."
end
else
i.copy(absolute_source_path, destination)
end
end
private
def fill_in_missing_ancestors(i, destination)
missing_ancestors = []
parent_dir = File.dirname(destination)
while !File.exists?(parent_dir) &&
parent_dir != "." && parent_dir != "/"
missing_ancestors.unshift(parent_dir)
parent_dir = File.dirname(parent_dir)
end
missing_ancestors.each do |dir|
i.mkdir(dir)
end
end
private
def description
self.class.to_s
end
private
def log(severity, message)
raise ArgumentError, "Unknown severity #{severity.inspect}" unless InstanceAgent::Log::SEVERITIES.include?(severity.to_s)
InstanceAgent::Log.send(severity.to_sym, "#{description}: #{message}")
end
end
end
end
end