lib/engineyard/cli/recipes.rb
require 'tempfile'
module EY
class CLI
class Recipes < EY::Thor
desc "apply [--environment ENVIRONMENT]",
"Run chef recipes uploaded by '#{banner_base} recipes upload' on the specified environment."
long_desc <<-DESC
This is similar to '#{banner_base} rebuild' except Engine Yard's main
configuration step is skipped.
The cookbook uploaded by the '#{banner_base} recipes upload' command will be run when
you run '#{banner_base} recipes apply'.
DESC
method_option :environment, type: :string, aliases: %w(-e),
required: true, default: '',
desc: "Environment in which to apply recipes"
method_option :account, type: :string, aliases: %w(-c),
required: true, default: '',
desc: "Name of the account in which the environment can be found"
def apply
environment = fetch_environment(options[:environment], options[:account])
apply_recipes(environment)
end
desc "upload [--environment ENVIRONMENT]",
"Upload custom chef recipes to specified environment so they can be applied."
long_desc <<-DESC
Make an archive of the "cookbooks/" subdirectory in your current working
directory and upload it to Engine Yard Cloud's recipe storage.
Alternatively, specify a .tgz of a cookbooks/ directory yourself as follows:
$ #{banner_base} recipes upload -f path/to/recipes.tgz
The uploaded cookbooks will be run when executing '#{banner_base} recipes apply'
and also automatically each time you update/rebuild your instances.
DESC
method_option :environment, type: :string, aliases: %w(-e),
required: true, default: '',
desc: "Environment that will receive the recipes"
method_option :account, type: :string, aliases: %w(-c),
required: true, default: '',
desc: "Name of the account in which the environment can be found"
method_option :apply, type: :boolean,
desc: "Apply the recipes immediately after they are uploaded"
method_option :file, type: :string, aliases: %w(-f),
required: true, default: '',
desc: "Specify a gzipped tar file (.tgz) for upload instead of cookbooks/ directory"
def upload
environment = fetch_environment(options[:environment], options[:account])
upload_recipes(environment, options[:file])
if options[:apply]
apply_recipes(environment)
end
end
no_tasks do
def apply_recipes(environment)
environment.run_custom_recipes
ui.info "Uploaded recipes started for #{environment.name}"
end
def upload_recipes(environment, filename)
if filename && filename != ''
environment.upload_recipes_at_path(filename)
ui.info "Recipes file #{filename} uploaded successfully for #{environment.name}"
else
path = cookbooks_dir_archive_path
environment.upload_recipes_at_path(path)
ui.info "Recipes in cookbooks/ uploaded successfully for #{environment.name}"
end
end
def cookbooks_dir_archive_path
unless FileTest.exist?("cookbooks")
raise EY::Error, "Could not find chef recipes. Please run from the root of your recipes repo."
end
recipes_file = Tempfile.new("recipes")
cmd = "tar czf '#{recipes_file.path}' cookbooks/"
if FileTest.exist?("data_bags")
cmd = cmd + " data_bags/"
end
unless system(cmd)
raise EY::Error, "Could not archive recipes.\nCommand `#{cmd}` exited with an error."
end
recipes_file.path
end
end
desc "download [--environment ENVIRONMENT]",
"Download a copy of the custom chef recipes from this environment into the current directory."
long_desc <<-DESC
The recipes will be unpacked into a directory called "cookbooks" in the
current directory. This is the opposite of 'recipes upload'.
If the cookbooks directory already exists, an error will be raised.
DESC
method_option :environment, type: :string, aliases: %w(-e),
required: true, default: '',
desc: "Environment for which to download the recipes"
method_option :account, type: :string, aliases: %w(-c),
required: true, default: '',
desc: "Name of the account in which the environment can be found"
def download
if File.exist?('cookbooks')
raise EY::Error, "Cannot download recipes, cookbooks directory already exists."
end
environment = fetch_environment(options[:environment], options[:account])
recipes = environment.download_recipes
cmd = "tar xzf '#{recipes.path}' cookbooks"
if system(cmd)
ui.info "Recipes downloaded successfully for #{environment.name}"
else
raise EY::Error, "Could not unarchive recipes.\nCommand `#{cmd}` exited with an error."
end
end
end
end
end