|
| 1 | +#!/usr/bin/env ruby |
| 2 | +require 'optparse' |
| 3 | +require 'ostruct' |
| 4 | +require_relative '../lib/restacker' |
| 5 | +require_relative '../lib/restacker_config' |
| 6 | +require_relative '../lib/aws_cli' |
| 7 | + |
| 8 | +ACTIONS = { |
| 9 | + list: 'Lists current stack names', |
| 10 | + describe: 'Describes a stack parameters and template', |
| 11 | + restack: 'Restacks a given deployment', |
| 12 | + deploy: 'Deploys a new stack', |
| 13 | + migrate: 'Migrates from green to blue stack', |
| 14 | + remove: 'Removes the given deployment', |
| 15 | + dump: 'Dumps the default configuration for a given template or module', |
| 16 | + console: 'Opens the AWS Console' |
| 17 | +} |
| 18 | +ACTIONS_HELP = "ACTIONS\n\n" + ACTIONS.to_yaml.sub("---\n", '').gsub(': ', "\t").gsub(':', " ") |
| 19 | +NOTES = "Notes: |
| 20 | + - If no template file path is provided when restacking #{File.basename($0)} will use the same |
| 21 | + template as if currently deployed. |
| 22 | + - Deployed stack name will be in the form of NAME-DATE using today's date" |
| 23 | + |
| 24 | +class Parser |
| 25 | + def self.parse(options) |
| 26 | + opts = OpenStruct.new |
| 27 | + |
| 28 | + opt_parser = OptionParser.new do |o| |
| 29 | + o.banner = "Usage: #{File.basename($0)} [ACTION] [OPTONS]\n\n#{ACTIONS_HELP}\n\nOPTIONS\n\n" |
| 30 | + |
| 31 | + o.on('-c PROFILE', '--credentials=PROFILE', 'Specify the AWS profile credential (~/.aws/config) to use') do |profile| |
| 32 | + opts[:profile] = profile |
| 33 | + end |
| 34 | + |
| 35 | + o.on('-d', '--debug', 'Show stack traces') do |debug| |
| 36 | + opts[:debug] = debug |
| 37 | + end |
| 38 | + |
| 39 | + o.on('-e PARAMS', '--environment-params=PARAMS', 'Parameters to add to the instance environment (/etc/profile.d) in the form of', 'k1=v1,k2=v2. E.g., -p SCORING_URL=https://scoring...') do |params| |
| 40 | + opts[:env_params] = params |
| 41 | + end |
| 42 | + |
| 43 | + o.on("-h", "--help", "Prints these wonderful lines...") do |
| 44 | + puts o |
| 45 | + puts "\n#{NOTES}" |
| 46 | + exit |
| 47 | + end |
| 48 | + |
| 49 | + o.on('-l LOCATION', '--location=LOCATION', 'Where to deploy, ksp, kvp, kcp...') do |location| |
| 50 | + opts[:location] = location |
| 51 | + end |
| 52 | + |
| 53 | + o.on('-m MODULE', '--migrate-module=MODULE', 'Migration module to execute') do |_module| |
| 54 | + opts[:module] = _module |
| 55 | + end |
| 56 | + |
| 57 | + o.on('-n NAME', '--name=NAME', 'Stack prefix stack name (alphanumeric with dashes)') do |name| |
| 58 | + opts[:name] = name |
| 59 | + end |
| 60 | + |
| 61 | + o.on('-o OPTIONS', '--migrate-options=OPTIONS', 'Options required by migration module to migrate from green to', 'blue stack in the form of k1=v1,k2=v2. E.g., -p EIP=1.2.3.4') do |options| |
| 62 | + opts[:options] = options |
| 63 | + end |
| 64 | + |
| 65 | + o.on('-p PARAMS', '--params=PARAMS', 'Parameters to override current stack parameters in the form of', 'k1=v1,k2=v2. E.g., -p AmiId=ami-a4jd7928') do |params| |
| 66 | + opts[:params] = params |
| 67 | + end |
| 68 | + |
| 69 | + o.on('-P FILE', '--parameters-file=FILE', 'YAML formated parameters file (as generated by the dump command) containing parameters to override stack parameters') do |file| |
| 70 | + opts[:params_file] = file |
| 71 | + end |
| 72 | + |
| 73 | + o.on('-r REGION', '--region=REGION', "The region where the stack to be restacked exists") do |region| |
| 74 | + opts[:region] = region |
| 75 | + end |
| 76 | + |
| 77 | + o.on('-t PATH', '--template=PATH', 'Template file path to override current stack template') do |template| |
| 78 | + opts[:template] = template |
| 79 | + end |
| 80 | + |
| 81 | + o.on('-u USERNAME', '--username=USERNAME', 'Your username, defaults to $USER') do |username| |
| 82 | + opts[:username] = username |
| 83 | + end |
| 84 | + |
| 85 | + o.on('-v', '--verbose', 'Show more output') do |verbose| |
| 86 | + opts[:verbose] = verbose |
| 87 | + end |
| 88 | + |
| 89 | + o.on('-V', '--version', 'Display the version') do |version| |
| 90 | + opts[:version] = version |
| 91 | + end |
| 92 | + end |
| 93 | + |
| 94 | + begin |
| 95 | + return opts, opt_parser.parse!(options) |
| 96 | + rescue OptionParser::InvalidOption => e |
| 97 | + puts e.message |
| 98 | + exit(1) |
| 99 | + end |
| 100 | + end |
| 101 | +end |
| 102 | + |
| 103 | +def usage(msg) |
| 104 | + puts msg, "\n" |
| 105 | + Parser.parse %w[--help] |
| 106 | +end |
| 107 | + |
| 108 | +# parse options |
| 109 | +options, unparsed = Parser.parse(ARGV) |
| 110 | + |
| 111 | +# set the username to $USER if not specified |
| 112 | +options[:username] = ENV['USER'] if options[:username].nil? |
| 113 | + |
| 114 | +begin |
| 115 | + action = unparsed.pop |
| 116 | + puts(VERSION) || exit(0) if options[:version] |
| 117 | + usage("Please specify an ACTION") && exit(0) if action.nil? |
| 118 | + |
| 119 | + if ACTIONS.keys.push(:aws).include?(action.to_sym) |
| 120 | + restacker = Restacker.new(options.to_h) unless ['dump'].include?(action) |
| 121 | + case action |
| 122 | + when 'list' |
| 123 | + puts "Listing stacks" |
| 124 | + restacker.list_stacks |
| 125 | + when 'desc', 'describe' |
| 126 | + if options[:name] |
| 127 | + puts "Describing #{options[:name]}" |
| 128 | + restacker.describe_stack(options[:name]) |
| 129 | + else |
| 130 | + usage "Please specify a stack name (-n) to describe" |
| 131 | + end |
| 132 | + when 'restack' |
| 133 | + if options[:name] |
| 134 | + puts "Restacking #{options[:name]}" |
| 135 | + restacker.restack_by_name(options[:name]) |
| 136 | + puts "Now run migrate followed by remove" |
| 137 | + else |
| 138 | + usage "Please specify a stack name (-n) to restack" |
| 139 | + end |
| 140 | + when 'deploy' |
| 141 | + if options[:template] && options[:name] |
| 142 | + restacker.deploy_stack(options[:template], options[:name]) |
| 143 | + else |
| 144 | + usage "Please specify stack name (-n) and template (-t) to deploy" |
| 145 | + end |
| 146 | + when 'migrate' |
| 147 | + if options[:name] && options[:options] && options[:module] |
| 148 | + puts "Migrating #{options[:name]}, #{options[:options]}, #{options[:module]}" |
| 149 | + # restacker = Restacker.new(options.to_h) |
| 150 | + # restacker.restack_by_name(stack_name) |
| 151 | + else |
| 152 | + usage "Please specify a stack name (-n), options (-o) and module (-m) to migrate" |
| 153 | + end |
| 154 | + when 'remove' |
| 155 | + if options[:name] |
| 156 | + puts "Removing stack" |
| 157 | + restacker.delete_stack(options[:name]) |
| 158 | + else |
| 159 | + usage "Please specify a stack name (-n) to remove" |
| 160 | + end |
| 161 | + when 'dump' |
| 162 | + if options[:template] |
| 163 | + # puts "Dumping stack parameters" |
| 164 | + Restacker.dump_stack_params(options) |
| 165 | + else |
| 166 | + usage "Please specify a stack template (-t) or module (-m)" |
| 167 | + end |
| 168 | + when 'console' |
| 169 | + AwsCli.new(options).console(options) |
| 170 | + when 'aws' |
| 171 | + AwsCli.new(options).cmd(options[:params], options[:debug]) |
| 172 | + end |
| 173 | + else |
| 174 | + usage "Unknown ACTION: #{action}" |
| 175 | + end |
| 176 | +rescue => e |
| 177 | + puts options[:debug] |
| 178 | + if options[:debug] |
| 179 | + puts e.class |
| 180 | + puts e.message |
| 181 | + usage $@ |
| 182 | + else |
| 183 | + usage e.message |
| 184 | + end |
| 185 | +end |
0 commit comments