From 7f2bdfa10374af0237cc3acc8c682c2f01032f6b Mon Sep 17 00:00:00 2001 From: elijah Date: Thu, 25 Sep 2014 00:54:09 -0700 Subject: add support for per-environment platform pinning. Support pins are platform.version, platform.branch, and platform.commit --- lib/leap/platform.rb | 3 ++ lib/leap_cli/commands/deploy.rb | 86 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+) diff --git a/lib/leap/platform.rb b/lib/leap/platform.rb index d97650b..89b1bc1 100644 --- a/lib/leap/platform.rb +++ b/lib/leap/platform.rb @@ -44,6 +44,9 @@ module Leap # return true if the platform version is within the specified range. # def version_in_range?(range) + if range.is_a? String + range = range.split('..') + end minimum_platform_version = Versionomy.parse(range.first) maximum_platform_version = Versionomy.parse(range.last) @version >= minimum_platform_version && @version <= maximum_platform_version diff --git a/lib/leap_cli/commands/deploy.rb b/lib/leap_cli/commands/deploy.rb index c214889..f68fe5d 100644 --- a/lib/leap_cli/commands/deploy.rb +++ b/lib/leap_cli/commands/deploy.rb @@ -44,6 +44,14 @@ module LeapCli end end + environments = nodes.field('environment').uniq + if environments.empty? + environments = [nil] + end + environments.each do |env| + check_platform_pinning(env) + end + quit! compile_hiera_files ssh_connect(nodes, connect_options(options)) do |ssh| @@ -70,6 +78,79 @@ module LeapCli 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) + bail!("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}.") + end + end + + # check branch + if provider.platform['branch'] + if !is_git_directory?(Path.platform) + bail!("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.") + end + unless provider.platform.branch == current_git_branch(Path.platform) + bail!("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}')") + end + end + + # check commit + if provider.platform['commit'] + if !is_git_directory?(Path.platform) + bail!("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.") + 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 + bail!("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.") + end + end + end + end + def sync_hiera_config(ssh) dest_dir = provider.hiera_sync_destination ssh.rsync.update do |server| @@ -119,7 +200,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" -- cgit v1.2.3