aboutsummaryrefslogtreecommitdiff
path: root/lib/leap_cli/commands/deploy.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/leap_cli/commands/deploy.rb')
-rw-r--r--lib/leap_cli/commands/deploy.rb163
1 files changed, 135 insertions, 28 deletions
diff --git a/lib/leap_cli/commands/deploy.rb b/lib/leap_cli/commands/deploy.rb
index 814407f..6589837 100644
--- a/lib/leap_cli/commands/deploy.rb
+++ b/lib/leap_cli/commands/deploy.rb
@@ -17,9 +17,12 @@ module LeapCli
# --force
c.switch :force, :desc => 'Deploy even if there is a lockfile.', :negatable => false
+ # --dev
+ c.switch :dev, :desc => "Development mode: don't run 'git submodule update' before deploy.", :negatable => false
+
# --tags
c.flag :tags, :desc => 'Specify tags to pass through to puppet (overriding the default).',
- :default_value => DEFAULT_TAGS.join(','), :arg_name => 'TAG[,TAG]'
+ :arg_name => 'TAG[,TAG]'
c.flag :port, :desc => 'Override the default SSH port.',
:arg_name => 'PORT'
@@ -28,9 +31,12 @@ module LeapCli
:arg_name => 'IPADDRESS'
c.action do |global,options,args|
- init_submodules
- nodes = filter_deploy_nodes(args)
+ if options[:dev] != true
+ init_submodules
+ end
+
+ nodes = manager.filter!(args)
if nodes.size > 1
say "Deploying to these nodes: #{nodes.keys.join(', ')}"
if !global[:yes] && !agree("Continue? ")
@@ -38,7 +44,16 @@ module LeapCli
end
end
- compile_hiera_files
+ environments = nodes.field('environment').uniq
+ if environments.empty?
+ environments = [nil]
+ end
+ environments.each do |env|
+ check_platform_pinning(env)
+ end
+ # compile hiera files for all the nodes in every environment that is
+ # being deployed and only those environments.
+ compile_hiera_files(manager.filter(environments))
ssh_connect(nodes, connect_options(options)) do |ssh|
ssh.leap.log :checking, 'node' do
@@ -58,39 +73,128 @@ module LeapCli
end
end
end
+
end
end
private
+ #
+ # The currently activated provider.json could have loaded some pinning
+ # information for the platform. If this is the case, refuse to deploy
+ # if there is a mismatch.
+ #
+ # For example:
+ #
+ # "platform": {
+ # "branch": "develop"
+ # "version": "1.0..99"
+ # "commit": "e1d6280e0a8c565b7fb1a4ed3969ea6fea31a5e2..HEAD"
+ # }
+ #
+ def check_platform_pinning(environment)
+ provider = manager.env(environment).provider
+ return unless provider['platform']
+
+ if environment.nil? || environment == 'default'
+ provider_json = 'provider.json'
+ else
+ provider_json = 'provider.' + environment + '.json'
+ end
+
+ # can we have json schema verification already?
+ unless provider.platform.is_a? Hash
+ bail!('`platform` attribute in #{provider_json} must be a hash (was %s).' % provider.platform.inspect)
+ end
+
+ # check version
+ if provider.platform['version']
+ if !Leap::Platform.version_in_range?(provider.platform.version)
+ say("The platform is pinned to a version range of '#{provider.platform.version}' "+
+ "by the `platform.version` property in #{provider_json}, but the platform "+
+ "(#{Path.platform}) has version #{Leap::Platform.version}.")
+ quit!("OK. Bye.") unless agree("Do you really want to deploy from the wrong version? ")
+ end
+ end
+
+ # check branch
+ if provider.platform['branch']
+ if !is_git_directory?(Path.platform)
+ say("The platform is pinned to a particular branch by the `platform.branch` property "+
+ "in #{provider_json}, but the platform directory (#{Path.platform}) is not a git repository.")
+ quit!("OK. Bye.") unless agree("Do you really want to deploy anyway? ")
+ end
+ unless provider.platform.branch == current_git_branch(Path.platform)
+ say("The platform is pinned to branch '#{provider.platform.branch}' by the `platform.branch` property "+
+ "in #{provider_json}, but the current branch is '#{current_git_branch(Path.platform)}' " +
+ "(for directory '#{Path.platform}')")
+ quit!("OK. Bye.") unless agree("Do you really want to deploy from the wrong branch? ")
+ end
+ end
+
+ # check commit
+ if provider.platform['commit']
+ if !is_git_directory?(Path.platform)
+ say("The platform is pinned to a particular commit range by the `platform.commit` property "+
+ "in #{provider_json}, but the platform directory (#{Path.platform}) is not a git repository.")
+ quit!("OK. Bye.") unless agree("Do you really want to deploy anyway? ")
+ end
+ current_commit = current_git_commit(Path.platform)
+ Dir.chdir(Path.platform) do
+ commit_range = assert_run!("git log --pretty='format:%H' '#{provider.platform.commit}'",
+ "The platform is pinned to a particular commit range by the `platform.commit` property "+
+ "in #{provider_json}, but git was not able to find commits in the range specified "+
+ "(#{provider.platform.commit}).")
+ commit_range = commit_range.split("\n")
+ if !commit_range.include?(current_commit) &&
+ provider.platform.commit.split('..').first != current_commit
+ say("The platform is pinned via the `platform.commit` property in #{provider_json} " +
+ "to a commit in the range #{provider.platform.commit}, but the current HEAD " +
+ "(#{current_commit}) is not in that range.")
+ quit!("OK. Bye.") unless agree("Do you really want to deploy from the wrong commit? ")
+ end
+ end
+ end
+ end
+
def sync_hiera_config(ssh)
- dest_dir = provider.hiera_sync_destination
ssh.rsync.update do |server|
node = manager.node(server.host)
hiera_file = Path.relative_path([:hiera, node.name])
- ssh.leap.log hiera_file + ' -> ' + node.name + ':' + dest_dir + '/hiera.yaml'
+ ssh.leap.log hiera_file + ' -> ' + node.name + ':' + Leap::Platform.hiera_path
{
:source => hiera_file,
- :dest => dest_dir + '/hiera.yaml',
+ :dest => Leap::Platform.hiera_path,
:flags => "-rltp --chmod=u+rX,go-rwx"
}
end
end
+ #
+ # sync various support files.
+ #
def sync_support_files(ssh)
- dest_dir = provider.hiera_sync_destination
+ dest_dir = Leap::Platform.files_dir
+ source_files = []
+ if Path.defined?(:custom_puppet_dir) && file_exists?(:custom_puppet_dir)
+ source_files += [:custom_puppet_dir, :custom_puppet_modules_dir, :custom_puppet_manifests_dir].collect{|path|
+ Path.relative_path(path, Path.provider) + '/' # rsync needs trailing slash
+ }
+ ensure_dir :custom_puppet_modules_dir
+ end
ssh.rsync.update do |server|
node = manager.node(server.host)
files_to_sync = node.file_paths.collect {|path| Path.relative_path(path, Path.provider) }
+ files_to_sync += source_files
if files_to_sync.any?
ssh.leap.log(files_to_sync.join(', ') + ' -> ' + node.name + ':' + dest_dir)
{
- :chdir => Path.provider,
+ :chdir => Path.named_path(:files_dir),
:source => ".",
:dest => dest_dir,
:excludes => "*",
- :includes => calculate_includes_from_files(files_to_sync),
- :flags => "-rltp --chmod=u+rX,go-rwx --relative --delete --delete-excluded --filter='protect hiera.yaml' --copy-links"
+ :includes => calculate_includes_from_files(files_to_sync, '/files'),
+ :flags => "-rltp --chmod=u+rX,go-rwx --relative --delete --delete-excluded --copy-links"
}
else
nil
@@ -100,9 +204,9 @@ module LeapCli
def sync_puppet_files(ssh)
ssh.rsync.update do |server|
- ssh.leap.log(Path.platform + '/[bin,tests,puppet] -> ' + server.host + ':' + LeapCli::PUPPET_DESTINATION)
+ ssh.leap.log(Path.platform + '/[bin,tests,puppet] -> ' + server.host + ':' + Leap::Platform.leap_dir)
{
- :dest => LeapCli::PUPPET_DESTINATION,
+ :dest => Leap::Platform.leap_dir,
:source => '.',
:chdir => Path.platform,
:excludes => '*',
@@ -112,7 +216,12 @@ module LeapCli
end
end
+ #
+ # ensure submodules are up to date, if the platform is a git
+ # repository.
+ #
def init_submodules
+ return unless is_git_directory?(Path.platform)
Dir.chdir Path.platform do
assert_run! "git submodule sync"
statuses = assert_run! "git submodule status"
@@ -126,11 +235,17 @@ module LeapCli
end
end
- def calculate_includes_from_files(files)
+ #
+ # converts an array of file paths into an array
+ # suitable for --include of rsync
+ #
+ # if set, `prefix` is stripped off.
+ #
+ def calculate_includes_from_files(files, prefix=nil)
return nil unless files and files.any?
# prepend '/' (kind of like ^ for rsync)
- includes = files.collect {|file| '/' + file}
+ includes = files.collect {|file| file =~ /^\// ? file : '/' + file }
# include all sub files of specified directories
includes.size.times do |i|
@@ -148,6 +263,10 @@ module LeapCli
end
end
+ if prefix
+ includes.map! {|path| path.sub(/^#{Regexp.escape(prefix)}\//, '/')}
+ end
+
return includes
end
@@ -155,23 +274,11 @@ module LeapCli
if options[:tags]
tags = options[:tags].split(',')
else
- tags = LeapCli::DEFAULT_TAGS.dup
+ tags = Leap::Platform.default_puppet_tags.dup
end
tags << 'leap_slow' unless options[:fast]
tags.join(',')
end
- #
- # for safety, we allow production deploys to be turned off in the Leapfile.
- #
- def filter_deploy_nodes(filter)
- nodes = manager.filter!(filter)
- if !leapfile.allow_production_deploy
- nodes = nodes[:environment => "!production"]
- assert! nodes.any?, "Skipping deploy because @allow_production_deploy is disabled."
- end
- nodes
- end
-
end
end