Created
March 26, 2015 22:35
-
-
Save jmahowald/b5d96d53a1a40a3ebd72 to your computer and use it in GitHub Desktop.
thor actions to help with kitchen reloads
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'thor' | |
require 'fileutils' | |
require 'yaml' | |
## | |
# common commands used to manage berks in a way that makes sense for that | |
# Inspired by the fact that berks is a great idea that is painfully slow | |
# when using mercurial, and thus needs to work around the prescribed workflow | |
# | |
module GenesysChefWorkflow | |
module Cli | |
class Kitchen < Thor | |
include Thor::Actions | |
#So I'd prefer to set a class option to avoid the duplication, but | |
#because of this https://github.com/erikhuda/thor/issues/363 | |
#having a class_option that is required is broken | |
class_option :kitchen_dir, :default => "./", :aliases => "-d" | |
desc "provision", "Does a kitchen converge and verify" | |
option :instance_name, :aliases => "-i" | |
def provision() | |
#HACK my understanding of inside is that it should pop back, but | |
#that doesn't seem to be how it works. So I'll force the issue | |
#by keeping track myself | |
current_dir = File.expand_path(options[:kitchen_dir]) | |
resume_if_down() | |
inside(options[:kitchen_dir]) do | |
run_or_die("kitchen converge #{options[:kitchen_instance]}") | |
run_or_die("kitchen verify") | |
end | |
end | |
desc "resume",'starts the vagrant instance if you have halted it' | |
option :instance_name, :required => true, :aliases => "-i" | |
def resume() | |
vdir = vagrant_dir() | |
if(File.exist?(vdir)) | |
inside(vdir) do | |
reload_output = run_or_die("vagrant reload", true) | |
match = reload_output.match(/\s*default:\s+22\s+=>\s+(\d+)/m) | |
if(match) | |
vagrant_ssh_port = match[1] | |
say_status(:info, "Vagrant port is #{vagrant_ssh_port}, updating file") | |
kitchen_instance_yml = File.join(options[:kitchen_dir],".kitchen", "#{options[:instance_name]}.yml") | |
cnf = YAML::load_file(File.open(kitchen_instance_yml)) | |
if(cnf["port"] != vagrant_ssh_port) | |
say_status(:info, "updating port in #{kitchen_instance_yml}") | |
cnf["port"] = vagrant_ssh_port | |
File.open(kitchen_instance_yml,'w') do |h| | |
h.write cnf.to_yaml | |
end | |
end | |
else | |
error("Couldn't find oprt info in #{reload_output}") | |
end | |
end | |
else | |
status(:info,"No instance exists, starting one up") | |
end | |
end | |
desc "login",'does a vagrant ssh into the vm' | |
option :instance_name, :aliases => "-i" | |
def login() | |
#HACK my understanding of inside is that it should pop back, but | |
#that doesn't seem to be how it works. So I'll force the issue | |
#by keeping track myself | |
current_dir = File.expand_path(options[:kitchen_dir]) | |
resume_if_down() | |
inside(current_dir) do | |
run_or_die("kitchen login") | |
end | |
end | |
desc "suspend",'halts the vagrant instance' | |
option :instance_name, :aliases => "-i" | |
def suspend() | |
vdir = vagrant_dir | |
if(File.exist?(vdir)) | |
inside(vdir) do | |
run_or_die("vagrant suspend") | |
end | |
else | |
puts "No instance running, nothing to do" | |
end | |
end | |
desc "destroy", "Terminates an instance" | |
option :instance_name, :aliases => "-i" | |
def destroy() | |
inside(options[:kitchen_dir]) do | |
run_or_die("kitchen destroy #{options[:kitchen_instance]}") | |
end | |
end | |
desc "status", "Gives the status of a vagrant instance" | |
option :instance_name, :aliases => "-i" | |
def status() | |
dir = vagrant_dir | |
inside(dir) do | |
options[:capture] = true | |
status_output = run("vagrant status",options) | |
#All of the vagrant instances that come from kitchen | |
#have the name of default | |
#For Example the stauts would be | |
#Current machine states: | |
#default running (virtualbox) | |
#The VM is running. To stop this VM, you can run `vagrant halt` to | |
match = status_output.match(/default\s+(\w+)\s+\((\w+)/m) | |
if(match) | |
say_status(:info, "Vagrant state is #{match[1]}") | |
return match[1] | |
else | |
error("Couldn't determinte status:#{status_output}") | |
end | |
end | |
end | |
private | |
#Runs the command failing the thor request if the command wasn't succesful | |
#set capture to true if you want to get stdout back | |
#TODO Figure out how to share this best | |
def run_or_die(command,capture=false) | |
options[:capture] = capture | |
output = run(command,options) | |
raise("Error running #{command}") unless $? == 0 | |
output | |
end | |
#Returns the directory of the vagrant instance | |
def vagrant_dir | |
kitchen_dir = options[:kitchen_dir] | |
instance_name = options[:instance_name] || get_single_instance_name | |
vagrant_instance_path = File.join(kitchen_dir,'.kitchen','kitchen-vagrant',instance_name) | |
end | |
#a lot of times, we want to just get the default instance | |
def get_single_instance_name | |
inside(options[:kitchen_dir]) do | |
instance_output = run("kitchen list -b", capture: true) | |
say_status(:debug, "Instance list:#{instance_output}") | |
instances = instance_output.split("\n") | |
raise("No instances found: #{instance_output}") unless instances.length > 0 | |
if(instances.length > 1) | |
say_status(:warn, "More than one instance, picking the first. Please specify with -i:#{instance_output}") | |
else | |
options[:instance_name] = instances[0] | |
return instances[0] | |
end | |
end | |
end | |
def resume_if_down | |
vagrant_status = status() | |
#TODO find other states | |
if(vagrant_status == 'running') | |
say_status(:debug, "Machine is already running") | |
else | |
say_status(:info, "Machine is created but not on, bringing up") | |
resume() | |
end | |
end | |
#TODO create vagrant command with a block that takes the output | |
end | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment