1- #!/usr/bin/ruby2.0
1+ #!/usr/bin/ruby
2+
3+ ##################################################################
4+ # This part of the code might be running on Ruby versions other
5+ # than 2.0. Testing on multiple Ruby versions is required for
6+ # changes to this part of the code.
7+ ##################################################################
28
39class Proxy
410 instance_methods . each do |m |
@@ -13,7 +19,7 @@ class Proxy
1319
1420 def method_missing ( name , *args , &block )
1521 @targets . map do |target |
16- target.public_send (name, *args, &block)
22+ target . __send__ ( name , *args , &block )
1723 end
1824 end
1925end
3642@log . level = Logger ::INFO
3743
3844begin
39- # use the gems bundled with the agent if present
40- Gem.use_paths(nil, Gem.path << "/opt/codedeploy-agent/vendor")
41-
4245 require 'fileutils'
4346 require 'openssl'
4447 require 'open-uri'
4548 require 'uri'
46- require 'json '
49+ require 'getoptlong '
4750
4851 def usage
4952 print <<EOF
5053
51- install <package-type>
54+ install [--sanity-check] <package-type>
55+ --sanity-check [optional]
5256 package-type: 'rpm', 'deb', or 'auto'
5357
5458Installs fetches the latest package version of the specified type and
@@ -64,9 +68,105 @@ are detected the automatic detection will abort
6468When using the automatic setup, if the system has apt-get but not gdebi,
6569the gdebi will be installed using apt-get first.
6670
71+ If --sanity-check is specified, the install script will wait for 3 minutes post installation
72+ to check for a running agent.
73+
74+ This install script needs Ruby version 2.0.x installed as a prerequisite.
75+ If you do not have Ruby version 2.0.x installed, please install it first.
76+
6777EOF
6878 end
6979
80+ # check ruby version, only version 2.0.x works
81+ def check_ruby_version_and_symlink
82+ @log . info ( "Starting Ruby version check." )
83+ actual_ruby_version = RUBY_VERSION . split ( '.' ) . map { |s |s . to_i }
84+ left_bound = '2.0.0' . split ( '.' ) . map { |s |s . to_i }
85+ right_bound = '2.1.0' . split ( '.' ) . map { |s |s . to_i }
86+ if !( File . exist? ( '/usr/bin/ruby2.0' ) )
87+ if ( File . symlink? ( '/usr/bin/ruby2.0' ) )
88+ @log . error ( "The symlink /usr/bin/ruby2.0 already exists, but it's linked to a non-existent directory or executable file." )
89+ exit ( 1 )
90+
91+ # The spaceship operator is a rarely used Ruby feature - particularly how it interacts with arrays.
92+ # Not all languages that have it handle that case the same way.
93+ elsif ( ( actual_ruby_version <=> left_bound ) < 0 || ( actual_ruby_version <=> right_bound ) >= 0 )
94+ @log . error ( "Current running Ruby version for " +ENV [ 'USER' ] +" is " +RUBY_VERSION +", but Ruby version 2.0.x needs to be installed." )
95+ @log . error ( 'If you have Ruby version 2.0.x installed for other users, please create a symlink to /usr/bin/ruby2.0.' )
96+ @log . error ( "Otherwise please install Ruby 2.0.x for " +ENV [ 'USER' ] +" user." )
97+ exit ( 1 )
98+ else
99+ ruby_interpreter_path = File . join ( RbConfig ::CONFIG [ "bindir" ] , RbConfig ::CONFIG [ "RUBY_INSTALL_NAME" ] + RbConfig ::CONFIG [ "EXEEXT" ] )
100+ File . symlink ( ruby_interpreter_path , '/usr/bin/ruby2.0' )
101+ end
102+ end
103+ end
104+
105+ def parse_args ( )
106+ if ( ARGV . length > 4 )
107+ usage
108+ @log . error ( 'Too many arguments.' )
109+ exit ( 1 )
110+ elsif ( ARGV . length < 1 )
111+ usage
112+ @log . error ( 'Expected package type as argument.' )
113+ exit ( 1 )
114+ end
115+
116+ @sanity_check = false
117+ @reexeced = false
118+
119+ @args = Array . new ( ARGV )
120+ opts = GetoptLong . new ( [ '--sanity-check' , GetoptLong ::NO_ARGUMENT ] , [ '--help' , GetoptLong ::NO_ARGUMENT ] , [ '--re-execed' , GetoptLong ::NO_ARGUMENT ] )
121+ opts . each do |opt , args |
122+ case opt
123+ when '--sanity-check'
124+ @sanity_check = true
125+ when '--help'
126+ usage
127+ when '--re-execed'
128+ @reexeced = true
129+ end
130+ end
131+ if ( ARGV . length < 1 )
132+ usage
133+ @log . error ( 'Expected package type as argument.' )
134+ exit ( 1 )
135+ end
136+ @type = ARGV . shift . downcase ;
137+ end
138+
139+ def force_ruby20 ( )
140+ # change interpreter when symlink /usr/bin/ruby2.0 exists, but running with lower ruby version
141+ actual_ruby_version = RUBY_VERSION . split ( '.' ) . map { |s |s . to_i }
142+ left_bound = '2.0.0' . split ( '.' ) . map { |s |s . to_i }
143+ right_bound = '2.1.0' . split ( '.' ) . map { |s |s . to_i }
144+ if ( actual_ruby_version <=> left_bound ) < 0
145+ if ( !@reexeced )
146+ @log . info ( "The current Ruby version is not 2.0.x! Restarting the installer with /usr/bin/ruby2.0" )
147+ exec ( '/usr/bin/ruby2.0' , __FILE__ , '--re-execed' , *@args )
148+ else
149+ @log . error ( 'The Ruby version in /usr/bin/ruby2.0 is ' +RUBY_VERSION +', but this must be Ruby version 2.0.x. Installation cannot continue.' )
150+ @log . error ( 'If you have Ruby version 2.0.x installed, please correct the symlink. Otherwise, please install Ruby 2.0' )
151+ exit ( 1 )
152+ end
153+ elsif ( actual_ruby_version <=> right_bound ) >= 0
154+ @log . warn ( 'The Ruby version in /usr/bin/ruby2.0 is ' +RUBY_VERSION +', but this must be Ruby version 2.0.x. Attempting to install anyway.' )
155+ @log . warn ( 'If you have Ruby version 2.0.x installed, please correct the symlink. Otherwise, please install Ruby 2.0' )
156+ end
157+ end
158+
159+ if ( Process . uid != 0 )
160+ @log . error ( 'Must run as root to install packages' )
161+ exit ( 1 )
162+ end
163+
164+ parse_args ( )
165+
166+ ########## Force running as Ruby 2.0 or fail here ##########
167+ check_ruby_version_and_symlink ( )
168+ force_ruby20 ( )
169+
70170 def run_command ( *args )
71171 exit_ok = system ( *args )
72172 $stdout. flush
77177
78178 def get_ec2_metadata_region
79179 begin
80- uri = URI.parse('http://169.254.169.254/latest/meta-data/placement/availability-zone')
81- az = uri.read(:read_timeout => 120)
82- az.strip
83- rescue OpenURI::HTTPError => e
180+ uri = URI . parse ( 'http://169.254.169.254/latest/meta-data/placement/availability-zone' )
181+ az = uri . read ( :read_timeout => 120 )
182+ az . strip
183+ rescue
84184 @log . warn ( "Could not get region from EC2 metadata service at '#{ uri . to_s } '" )
185+ return nil
85186 end
86187
87188 if ( az !~ /[a-z]{2}-[a-z]+-\d +[a-z]/ )
88189 @log . warn ( "Invalid availability zone name: '#{ az } '." )
89- nil
190+ return nil
90191 else
91- az.chop
192+ return az . chop
92193 end
93194 end
94195
137238 uri = get_s3_uri ( region , bucket , key )
138239
139240 begin
241+ require 'json'
242+
140243 version_string = uri . read ( :ssl_verify_mode => OpenSSL ::SSL ::VERIFY_PEER , :redirect => true , :read_timeout => 120 )
141244 JSON . parse ( version_string )
142245 rescue OpenURI ::HTTPError => e
@@ -166,34 +269,19 @@ EOF
166269 end
167270
168271 def do_sanity_check ( cmd )
169- @log.info("Waiting for a while before I check for a running agent")
170- sleep(3 * 60)
171- res = run_command(cmd, 'codedeploy-agent', 'status')
172- if (res.nil? || res == false)
173- @log.info("No codedeploy agent seems to be running. Starting the agent.")
174- run_command(cmd, 'codedeploy-agent', 'start-no-update')
272+ if @sanity_check
273+ @log . info ( "Waiting for 3 minutes before I check for a running agent" )
274+ sleep ( 3 * 60 )
275+ res = run_command ( cmd , 'codedeploy-agent' , 'status' )
276+ if ( res . nil? || res == false )
277+ @log . info ( "No codedeploy agent seems to be running. Starting the agent." )
278+ run_command ( cmd , 'codedeploy-agent' , 'start-no-update' )
279+ end
175280 end
176281 end
177282
178- if (Process.uid != 0)
179- @log.error('Must run as root to install packages')
180- exit(1)
181- end
182-
183283 @log . info ( "Starting update check." )
184284
185- if (ARGV.length > 1)
186- usage
187- @log.error('Too many arguments.')
188- exit(1)
189- elsif (ARGV.length < 1)
190- usage
191- @log.error('Expected package type as argument.')
192- exit(1)
193- end
194-
195- @type = ARGV[0].downcase;
196-
197285 if ( @type == 'auto' )
198286 @log . info ( 'Attempting to automatically detect supported package manager type for system...' )
199287
243331 when 'deb'
244332 #use -n for non-interactive mode
245333 #use -o to not overwrite config files unless they have not been changed
246- install_cmd = ['/usr/bin/gdebi', '-n', '-o', 'Dpkg::Options::=" --force-confdef" ', '-o', 'Dpg::Options::=" --force-conffold" ']
334+ install_cmd = [ '/usr/bin/gdebi' , '-n' , '-o' , 'Dpkg::Options::=--force-confdef' , '-o' , 'Dpg::Options::=--force-confold ' ]
247335 install_from_s3 ( region , bucket , version_file_key , @type , install_cmd )
248336 do_sanity_check ( '/usr/sbin/service' )
249337 when 'zypper'
0 commit comments