Skip to content

Instantly share code, notes, and snippets.

@jmahowald
Created March 26, 2015 22:35
Show Gist options
  • Save jmahowald/b5d96d53a1a40a3ebd72 to your computer and use it in GitHub Desktop.
Save jmahowald/b5d96d53a1a40a3ebd72 to your computer and use it in GitHub Desktop.
thor actions to help with kitchen reloads
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