|
| 1 | +require 'rubygems' |
| 2 | +require 'aws' |
| 3 | +require 'net/ssh' |
| 4 | +require 'net/http' |
| 5 | +require 'logger' |
| 6 | + |
| 7 | +def message_lines |
| 8 | + 2.times do |x| |
| 9 | + puts "****************************************" |
| 10 | + end |
| 11 | +end |
| 12 | + |
| 13 | +logger = Logger.new(STDOUT) |
| 14 | + |
| 15 | + |
| 16 | +#load aws.yml -- This will allow you to login to aws |
| 17 | +aws_conf = YAML.load(File.read('aws.yml')) |
| 18 | + |
| 19 | +AWS.config(aws_conf) |
| 20 | + |
| 21 | +instance = key_pair = group = nil |
| 22 | + |
| 23 | +#create a new instance of the aws ec2 module |
| 24 | +ec2 = AWS::EC2.new |
| 25 | + |
| 26 | +#lookup the server ami. Is there a better way to do this? |
| 27 | +image = AWS.memoize do |
| 28 | + amazon_linux = ec2.images(). |
| 29 | + filter("root-device-type", "instance-store"). |
| 30 | + filter("name", "*ubuntu-images/ubuntu-natty-11.04-i386-server-20110426*") |
| 31 | + amazon_linux.to_a.sort_by(&:name).last |
| 32 | + end |
| 33 | + |
| 34 | +logger.debug("Using AMI: #{image.id} --- #{image.name}") |
| 35 | + |
| 36 | +#dynamically create a keypair for ec2 and save the private key to a file |
| 37 | +key_pair = ec2.key_pairs.create("chef-kp-#{Time.now.to_i}") |
| 38 | +logger.debug("Generated keypair #{key_pair.name}, fingerprint: #{key_pair.fingerprint}") |
| 39 | +logger.debug("Writing #{key_pair.name} to identity.pem") |
| 40 | +identity = File.new("identity.pem", "w") |
| 41 | +identity.write(key_pair.private_key) |
| 42 | +identity.close |
| 43 | +File.chmod(0600,"identity.pem") |
| 44 | + |
| 45 | +#create a security group for the chef server. Allow ssh and port 4000. |
| 46 | +group = ec2.security_groups.create("js-gp-#{Time.now.to_i}") |
| 47 | +group.authorize_ingress(:tcp, 22, "0.0.0.0/0") |
| 48 | + |
| 49 | +logger.debug("Using security group: #{group.name}") |
| 50 | + |
| 51 | +#start the Amazon ec2 instance |
| 52 | +instance = image.run_instance(:key_pair => key_pair, :security_groups => group) |
| 53 | +logger.info("Launched instance #{instance.id}, status: #{instance.status}") |
| 54 | +sleep 2 until instance.status != :pending |
| 55 | +logger.info("Launched instance #{instance.id}, status: #{instance.status}") |
| 56 | +exit 1 unless instance.status == :running |
| 57 | + |
| 58 | +#There is an race condition with port 22 being open, but no active SSHD. This sucks, but it's necessary. |
| 59 | +logger.debug("There seems to be a firewall rule lag here. Sleeping for 90 seconds.....") |
| 60 | +sleep 90 |
| 61 | + |
| 62 | +#login to the machine with ssh and get chefs pre-installation rolling. |
| 63 | +logger.debug("Logging into IP: #{instance.ip_address}") |
| 64 | + |
| 65 | +#Because of two interactive dialogs during the chef installation, I generate this script on the newly created server |
| 66 | +# log you in, then run the script with an active screen. There may be a better way, but I know if you override these |
| 67 | +# dialogues, many important pieces of the chef configuration will not get generated. |
| 68 | + |
| 69 | +begin |
| 70 | + Net::SSH.start(instance.ip_address, "ubuntu", :key_data => [key_pair.private_key]) do |ssh| |
| 71 | + puts ssh.exec!("echo \"deb http://apt.opscode.com/ `lsb_release -cs`-0.10 main\" | sudo tee /etc/apt/sources.list.d/opscode.list") |
| 72 | + puts ssh.exec!("cat /etc/apt/sources.list.d/opscode.list") |
| 73 | + puts ssh.exec!("sudo mkdir -p /etc/apt/trusted.gpg.d") |
| 74 | + logger.debug("Configuring Keys for the Chef Apt Repository") |
| 75 | + puts ssh.exec!("sudo gpg --keyserver keys.gnupg.net --recv-keys 83EF826A") |
| 76 | + puts ssh.exec!("sudo gpg --export packages@opscode.com | sudo tee /etc/apt/trusted.gpg.d/opscode-keyring.gpg > /dev/null") |
| 77 | + logger.debug("Updating all of the sources on the ubuntu machine") |
| 78 | + puts ssh.exec!("sudo apt-get update") |
| 79 | + logger.debug("Installing Opscode Keyring") |
| 80 | + puts ssh.exec!("sudo DEBIAN_FRONTEND='noninteractive' apt-get install opscode-keyring --assume-yes") |
| 81 | + logger.debug("Installing XML Libraries for Nokogiri") |
| 82 | + puts ssh.exec!("sudo apt-get install libxslt1-dev libxml2-dev --assume-yes") |
| 83 | + logger.debug("Installing RubyGems") |
| 84 | + puts ssh.exec!("sudo apt-get install rubygems1.8 --assume-yes") |
| 85 | + logger.debug("Installing Git") |
| 86 | + puts ssh.exec!("sudo apt-get install git --assume-yes") |
| 87 | + logger.debug("Installing Merb-Haml") |
| 88 | + puts ssh.exec!("sudo gem install merb-haml --no-ri --no-rdoc") |
| 89 | + puts ssh.exec!("echo \"sudo apt-get install chef chef-server-api chef-expander --assume-yes\" > setup_chef") |
| 90 | + puts ssh.exec!("echo \"sudo gem install knife-ec2 --no-ri --no-rdoc \" >> setup_chef") |
| 91 | + puts ssh.exec!("echo \"rm .profile\" >> setup_chef") |
| 92 | + puts ssh.exec!("echo \"./setup_chef\" > .profile") |
| 93 | + puts ssh.exec!("echo \"#{key_pair.private_key}\" > identity.pem") |
| 94 | + puts ssh.exec!("chmod 755 setup_chef create_server") |
| 95 | + puts ssh.exec!("chmod 600 identity.pem") |
| 96 | + end |
| 97 | +rescue SystemCallError, Timeout::Error => e |
| 98 | + logger.info("The ssh port may not be open, trying again") |
| 99 | + sleep 5 |
| 100 | + retry |
| 101 | +end |
| 102 | + |
| 103 | +login = File.new("login.sh", "w") |
| 104 | +login.write("ssh -i identity.pem ubuntu@#{instance.ip_address}") |
| 105 | +login.close |
| 106 | +File.chmod(0755,"login.sh") |
| 107 | + |
| 108 | +message_lines |
| 109 | +puts "Automatically logging you into the new chef server to finish installation" |
| 110 | +puts "Alternately you can use the command below:" |
| 111 | +puts "ssh -i #{Dir.pwd}/identity.pem ubuntu@#{instance.ip_address}" |
| 112 | +message_lines |
| 113 | +sleep 5 |
| 114 | + |
| 115 | + |
| 116 | + |
| 117 | + |
| 118 | + |
| 119 | + |
| 120 | + |
| 121 | + |
| 122 | + |
| 123 | + |
| 124 | + |
| 125 | + |
| 126 | + |
| 127 | + |
| 128 | + |
0 commit comments