clc-promote 0.9.8 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/clc-promote.gemspec +1 -0
- data/lib/promote.rb +2 -0
- data/lib/promote/environment_file.rb +6 -6
- data/lib/promote/node_shell.rb +17 -0
- data/lib/promote/node_shell/base_shell.rb +20 -0
- data/lib/promote/node_shell/ssh_shell.rb +40 -0
- data/lib/promote/node_shell/winrm_shell.rb +27 -0
- data/lib/promote/password_vault.rb +38 -0
- data/lib/promote/promoter.rb +53 -31
- data/lib/promote/rake_tasks.rb +9 -2
- data/lib/promote/version.rb +1 -1
- data/spec/unit/promote/cookbook_spec.rb +205 -79
- data/spec/unit/promote/environment_file_spec.rb +28 -0
- data/spec/unit/promote/node_shell/ssh_shell_spec.rb +39 -0
- data/spec/unit/promote/node_shell/winrm_shell_spec.rb +30 -0
- data/spec/unit/promote/node_shell_spec.rb +40 -0
- data/spec/unit/promote/password_vault_spec.rb +39 -0
- data/spec/unit/promote/promoter_spec.rb +152 -45
- data/spec/unit/promote/uploader_spec.rb +49 -33
- data/spec/unit/stubs/environments/env1.json +29 -0
- data/spec/unit/stubs/environments/env2.json +16 -0
- metadata +35 -2
| @@ -0,0 +1,28 @@ | |
| 1 | 
            +
            require 'promote'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Promote::EnvironmentFile do
         | 
| 4 | 
            +
              let(:here) { File.expand_path('../../', __FILE__) }
         | 
| 5 | 
            +
              let(:env_dir) { File.join(here, 'stubs', 'environments') }
         | 
| 6 | 
            +
              let(:config) { Promote::Config.new(environment_directory: env_dir) }
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              subject { Promote::EnvironmentFile.new(environment, config) }
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              describe 'overrides' do
         | 
| 11 | 
            +
                context 'there are overrides' do
         | 
| 12 | 
            +
                  let(:environment) { 'env1' }
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  it 'should return the override value' do
         | 
| 15 | 
            +
                    expect(subject.overrides['provisioner']['vault_bag']).to eq 'secrets_qa'
         | 
| 16 | 
            +
                  end
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                context 'there are no overrides' do
         | 
| 20 | 
            +
                  let(:environment) { 'env2' }
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  it 'should return an empty hash' do
         | 
| 23 | 
            +
                    expect(subject.overrides).to be_a(Hash)
         | 
| 24 | 
            +
                    expect(subject.overrides.keys.count).to be 0
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
            end
         | 
| @@ -0,0 +1,39 @@ | |
| 1 | 
            +
            require 'promote'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Promote::NodeShell::SshShell do
         | 
| 4 | 
            +
              let(:ip) { '1.1.1.1' }
         | 
| 5 | 
            +
              let(:node) { double('node', ipaddress: ip) }
         | 
| 6 | 
            +
              let(:connection) { double('connection', open_channel: nil, loop: nil) }
         | 
| 7 | 
            +
              let(:password) { 'pass' }
         | 
| 8 | 
            +
              let(:vault) { double('vault', root_password: password) }
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              before do
         | 
| 11 | 
            +
                allow(Promote::PasswordVault).to receive(:root_password)
         | 
| 12 | 
            +
                  .and_return(password)
         | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              subject { Promote::NodeShell::SshShell.new(node, vault) }
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              describe 'converge?' do
         | 
| 18 | 
            +
                it 'converges the correct endpoint' do
         | 
| 19 | 
            +
                  expect(Net::SSH).to receive(:start).with(ip, anything, anything)
         | 
| 20 | 
            +
                    .and_return(connection)
         | 
| 21 | 
            +
                  subject.converge?
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                it 'converges as root' do
         | 
| 25 | 
            +
                  expect(Net::SSH).to receive(:start).with(anything, 'root', anything)
         | 
| 26 | 
            +
                    .and_return(connection)
         | 
| 27 | 
            +
                  subject.converge?
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                it 'converges with the correct password' do
         | 
| 31 | 
            +
                  expect(Net::SSH).to receive(:start).with(
         | 
| 32 | 
            +
                    anything,
         | 
| 33 | 
            +
                    anything,
         | 
| 34 | 
            +
                    password: password
         | 
| 35 | 
            +
                  ).and_return(connection)
         | 
| 36 | 
            +
                  subject.converge?
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
            end
         | 
| @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            require 'promote'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Promote::NodeShell::WinrmShell do
         | 
| 4 | 
            +
              let(:ip) { '1.1.1.1' }
         | 
| 5 | 
            +
              let(:endpoint) { "http://#{ip}:5985/wsman" }
         | 
| 6 | 
            +
              let(:node) { double('node', ipaddress: ip) }
         | 
| 7 | 
            +
              let(:connection) { double('connection', run_cmd: { exitcode: 0 }, loop: nil) }
         | 
| 8 | 
            +
              let(:password) { 'pass' }
         | 
| 9 | 
            +
              let(:vault) { double('vault', admin_password: password) }
         | 
| 10 | 
            +
             | 
| 11 | 
            +
              before do
         | 
| 12 | 
            +
                allow(Promote::PasswordVault).to receive(:root_password)
         | 
| 13 | 
            +
                  .and_return(password)
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              subject { Promote::NodeShell::WinrmShell.new(node, vault) }
         | 
| 17 | 
            +
             | 
| 18 | 
            +
              describe 'converge?' do
         | 
| 19 | 
            +
                it 'converges with the correct authentication properties' do
         | 
| 20 | 
            +
                  expect(WinRM::WinRMWebService).to receive(:new).with(
         | 
| 21 | 
            +
                    endpoint,
         | 
| 22 | 
            +
                    :plaintext,
         | 
| 23 | 
            +
                    user: 'administrator',
         | 
| 24 | 
            +
                    pass: password,
         | 
| 25 | 
            +
                    basic_auth_only: true
         | 
| 26 | 
            +
                  ).and_return(connection)
         | 
| 27 | 
            +
                  subject.converge?
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
            end
         | 
| @@ -0,0 +1,40 @@ | |
| 1 | 
            +
            require 'promote'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Promote::NodeShell do
         | 
| 4 | 
            +
              let(:config) do
         | 
| 5 | 
            +
                Promote::Config.new(
         | 
| 6 | 
            +
                  node_name: 'user',
         | 
| 7 | 
            +
                  cookbook_directory: '/cookbooks',
         | 
| 8 | 
            +
                  client_key: 'key',
         | 
| 9 | 
            +
                  chef_server_url: 'https://some.chef.server'
         | 
| 10 | 
            +
                )
         | 
| 11 | 
            +
              end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              subject { Promote::NodeShell }
         | 
| 14 | 
            +
             | 
| 15 | 
            +
              describe 'for_node' do
         | 
| 16 | 
            +
                let(:node) { double('node', platform_family: 'family') }
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                it 'adds the correct vault to the shell' do
         | 
| 19 | 
            +
                  expect(subject.for_node(node, config).vault.node).to be node
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                context 'linux node' do
         | 
| 23 | 
            +
                  let(:node) { double('node', platform_family: 'ubuntu') }
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                  it 'returns a SshShell' do
         | 
| 26 | 
            +
                    expect(subject.for_node(node, config)).to(
         | 
| 27 | 
            +
                      be_instance_of Promote::NodeShell::SshShell)
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                context 'windows node' do
         | 
| 32 | 
            +
                  let(:node) { double('node', platform_family: 'windows') }
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  it 'returns a SshShell' do
         | 
| 35 | 
            +
                    expect(subject.for_node(node, config)).to(
         | 
| 36 | 
            +
                      be_instance_of Promote::NodeShell::WinrmShell)
         | 
| 37 | 
            +
                  end
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
            end
         | 
| @@ -0,0 +1,39 @@ | |
| 1 | 
            +
            require 'promote'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            describe Promote::PasswordVault do
         | 
| 4 | 
            +
              let(:node) do
         | 
| 5 | 
            +
                node = Chef::Node.new
         | 
| 6 | 
            +
                node.name 'node'
         | 
| 7 | 
            +
                node.override['provisioner']['vault_bag'] = bag
         | 
| 8 | 
            +
                node.override['clc_library']['win_fqdn'] = domain_item
         | 
| 9 | 
            +
                node
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
              let(:bag) { 'secrets_qa' }
         | 
| 12 | 
            +
              let(:domain_item) { 't3n' }
         | 
| 13 | 
            +
              let(:config) { Promote::Config.new }
         | 
| 14 | 
            +
              let(:vault) do
         | 
| 15 | 
            +
                {
         | 
| 16 | 
            +
                  'local_admin_password' => 'Pass@word1',
         | 
| 17 | 
            +
                  'local_root_password' => 'Password1'
         | 
| 18 | 
            +
                }
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              before do
         | 
| 22 | 
            +
                allow(ChefVault::Item).to receive(:load)
         | 
| 23 | 
            +
                  .with(bag, "#{domain_item}_domain").and_return(vault)
         | 
| 24 | 
            +
              end
         | 
| 25 | 
            +
              
         | 
| 26 | 
            +
              subject { Promote::PasswordVault.new(node, config) }
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              describe 'root_password' do
         | 
| 29 | 
            +
                it 'should return the correct password' do
         | 
| 30 | 
            +
                  expect(subject.root_password).to eq 'Password1'
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
             | 
| 34 | 
            +
              describe 'admin_password' do
         | 
| 35 | 
            +
                it 'should return the correct password' do
         | 
| 36 | 
            +
                  expect(subject.admin_password).to eq 'Pass@word1'
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
              end
         | 
| 39 | 
            +
            end
         | 
| @@ -72,21 +72,27 @@ describe Promote::Promoter do | |
| 72 72 | 
             
                let(:good_node) do
         | 
| 73 73 | 
             
                  node = Chef::Node.new
         | 
| 74 74 | 
             
                  node.name 'good_node'
         | 
| 75 | 
            -
                  node.default['ohai_time'] = Time.now.to_i  | 
| 75 | 
            +
                  node.default['ohai_time'] = Time.now.to_i - 1
         | 
| 76 76 | 
             
                  node
         | 
| 77 77 | 
             
                end
         | 
| 78 78 | 
             
                let(:bad_node) do
         | 
| 79 79 | 
             
                  node = Chef::Node.new
         | 
| 80 80 | 
             
                  node.name 'bad_node'
         | 
| 81 | 
            -
                  node.default['ohai_time'] = Time.now.to_i -  | 
| 81 | 
            +
                  node.default['ohai_time'] = Time.now.to_i - 1
         | 
| 82 82 | 
             
                  node
         | 
| 83 83 | 
             
                end
         | 
| 84 | 
            +
                let(:good_shell) { double('shell', converge?: true) }
         | 
| 85 | 
            +
                let(:bad_shell) { double('shell', converge?: false) }
         | 
| 84 86 | 
             
                let(:uploader) { double('uploader') }
         | 
| 85 87 | 
             
                let(:ui) { nil }
         | 
| 86 88 |  | 
| 87 89 | 
             
                before do
         | 
| 88 90 | 
             
                  allow(Promote::NodeFinder).to receive(:new).and_return(finder_good)
         | 
| 89 91 | 
             
                  allow(Promote::Uploader).to receive(:new).and_return(uploader)
         | 
| 92 | 
            +
                  allow(Promote::NodeShell).to receive(:for_node).with(good_node, config)
         | 
| 93 | 
            +
                    .and_return(good_shell)
         | 
| 94 | 
            +
                  allow(Promote::NodeShell).to receive(:for_node).with(bad_node, config)
         | 
| 95 | 
            +
                    .and_return(bad_shell)
         | 
| 90 96 | 
             
                end
         | 
| 91 97 |  | 
| 92 98 | 
             
                context 'all environments succeed' do
         | 
| @@ -98,9 +104,68 @@ describe Promote::Promoter do | |
| 98 104 | 
             
                    subject.monitor_promotion(
         | 
| 99 105 | 
             
                      'env1',
         | 
| 100 106 | 
             
                      %w(env2 env3 env4),
         | 
| 107 | 
            +
                      3,
         | 
| 108 | 
            +
                      0.25,
         | 
| 109 | 
            +
                      false,
         | 
| 110 | 
            +
                      ui
         | 
| 111 | 
            +
                    )
         | 
| 112 | 
            +
                  end
         | 
| 113 | 
            +
                end
         | 
| 114 | 
            +
             | 
| 115 | 
            +
                context 'converge windows first' do
         | 
| 116 | 
            +
                  let(:finder_ubu) { double('ubu_finder', search: [bad_node]) }
         | 
| 117 | 
            +
                  let(:finder_win) { double('win_finder', search: [good_node]) }
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                  before do
         | 
| 120 | 
            +
                    allow(Promote::NodeFinder).to(
         | 
| 121 | 
            +
                      receive(:new).with(
         | 
| 122 | 
            +
                        'chef_environment:env1 AND platform:ubuntu',
         | 
| 123 | 
            +
                        config
         | 
| 124 | 
            +
                      ).and_return(finder_ubu)
         | 
| 125 | 
            +
                    )
         | 
| 126 | 
            +
                    allow(Promote::NodeFinder).to(
         | 
| 127 | 
            +
                      receive(:new).with(
         | 
| 128 | 
            +
                        'chef_environment:env1 AND platform:windows',
         | 
| 129 | 
            +
                        config
         | 
| 130 | 
            +
                      ).and_return(finder_win)
         | 
| 131 | 
            +
                    )
         | 
| 132 | 
            +
                  end
         | 
| 133 | 
            +
             | 
| 134 | 
            +
                  it 'promotes windows before ubuntu fails' do
         | 
| 135 | 
            +
                    expect(good_shell).to receive(:converge?)
         | 
| 136 | 
            +
                    expect do
         | 
| 137 | 
            +
                      subject.monitor_promotion(
         | 
| 138 | 
            +
                        'env1',
         | 
| 139 | 
            +
                        %w(env2 env3 env4),
         | 
| 140 | 
            +
                        0.25,
         | 
| 141 | 
            +
                        3,
         | 
| 142 | 
            +
                        false,
         | 
| 143 | 
            +
                        ui
         | 
| 144 | 
            +
                      )
         | 
| 145 | 
            +
                    end.to raise_error(/env1/)
         | 
| 146 | 
            +
                  end
         | 
| 147 | 
            +
                end
         | 
| 148 | 
            +
             | 
| 149 | 
            +
                context 'dont converge if already converged' do
         | 
| 150 | 
            +
                  let(:good_node) do
         | 
| 151 | 
            +
                    node = Chef::Node.new
         | 
| 152 | 
            +
                    node.name 'converged'
         | 
| 153 | 
            +
                    node.default['ohai_time'] = Time.now.to_i + 3600
         | 
| 154 | 
            +
                    node
         | 
| 155 | 
            +
                  end
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                  it 'does not converge' do
         | 
| 158 | 
            +
                    %w(env2 env3 env4).each do |env|
         | 
| 159 | 
            +
                      expect(subject).to receive(:promote_to).with('env1', env, ui)
         | 
| 160 | 
            +
                      expect(uploader).to receive(:upload_environment).with(env, ui)
         | 
| 161 | 
            +
                    end
         | 
| 162 | 
            +
                    expect(good_shell).not_to receive(:converge?)
         | 
| 163 | 
            +
                    subject.monitor_promotion(
         | 
| 164 | 
            +
                      'env1',
         | 
| 165 | 
            +
                      %w(env2 env3 env4),
         | 
| 166 | 
            +
                      3,
         | 
| 101 167 | 
             
                      0.25,
         | 
| 102 168 | 
             
                      false,
         | 
| 103 | 
            -
                      1,
         | 
| 104 169 | 
             
                      ui
         | 
| 105 170 | 
             
                    )
         | 
| 106 171 | 
             
                  end
         | 
| @@ -110,77 +175,119 @@ describe Promote::Promoter do | |
| 110 175 | 
             
                  let(:self_node) do
         | 
| 111 176 | 
             
                    node = Chef::Node.new
         | 
| 112 177 | 
             
                    node.name config.node_name
         | 
| 113 | 
            -
                    node.default['ohai_time'] = Time.now.to_i -  | 
| 178 | 
            +
                    node.default['ohai_time'] = Time.now.to_i - 1
         | 
| 114 179 | 
             
                    node
         | 
| 115 180 | 
             
                  end
         | 
| 116 | 
            -
                  let(:finder_good) { double(' | 
| 117 | 
            -
                  
         | 
| 181 | 
            +
                  let(:finder_good) { double('finder', search: [self_node, good_node]) }
         | 
| 182 | 
            +
                  let(:self_shell) { double('shell') }
         | 
| 183 | 
            +
             | 
| 184 | 
            +
                  before do
         | 
| 185 | 
            +
                    allow(Promote::NodeShell).to receive(:for_node).with(self_node, config)
         | 
| 186 | 
            +
                      .and_return(self_shell)
         | 
| 187 | 
            +
                  end
         | 
| 188 | 
            +
             | 
| 118 189 | 
             
                  it 'promotes all nodes' do
         | 
| 119 190 | 
             
                    %w(env2 env3 env4).each do |env|
         | 
| 120 191 | 
             
                      expect(subject).to receive(:promote_to).with('env1', env, ui)
         | 
| 121 192 | 
             
                      expect(uploader).to receive(:upload_environment).with(env, ui)
         | 
| 122 193 | 
             
                    end
         | 
| 194 | 
            +
                    expect(self_shell).not_to receive(:converge?)
         | 
| 195 | 
            +
                    expect(good_shell).to receive(:converge?)
         | 
| 123 196 | 
             
                    subject.monitor_promotion(
         | 
| 124 197 | 
             
                      'env1',
         | 
| 125 198 | 
             
                      %w(env2 env3 env4),
         | 
| 199 | 
            +
                      3,
         | 
| 126 200 | 
             
                      0.25,
         | 
| 127 201 | 
             
                      false,
         | 
| 128 | 
            -
                      1,
         | 
| 129 202 | 
             
                      ui
         | 
| 130 203 | 
             
                    )
         | 
| 131 204 | 
             
                  end
         | 
| 132 205 | 
             
                end
         | 
| 133 206 |  | 
| 134 | 
            -
                context ' | 
| 135 | 
            -
                   | 
| 136 | 
            -
                     | 
| 137 | 
            -
             | 
| 138 | 
            -
             | 
| 139 | 
            -
                     | 
| 207 | 
            +
                context 'ignore provisioner' do
         | 
| 208 | 
            +
                  let(:prov) do
         | 
| 209 | 
            +
                    node = Chef::Node.new
         | 
| 210 | 
            +
                    node.name 'BA1PROVISIONER01'
         | 
| 211 | 
            +
                    node.default['ohai_time'] = Time.now.to_i - 1
         | 
| 212 | 
            +
                    node
         | 
| 140 213 | 
             
                  end
         | 
| 214 | 
            +
                  let(:finder_good) { double('finder', search: [prov, good_node]) }
         | 
| 215 | 
            +
                  let(:prov_shell) { double('shell') }
         | 
| 141 216 |  | 
| 142 | 
            -
                   | 
| 143 | 
            -
                     | 
| 144 | 
            -
             | 
| 217 | 
            +
                  before do
         | 
| 218 | 
            +
                    allow(Promote::NodeShell).to receive(:for_node).with(prov, config)
         | 
| 219 | 
            +
                      .and_return(prov_shell)
         | 
| 220 | 
            +
                  end
         | 
| 145 221 |  | 
| 146 | 
            -
             | 
| 147 | 
            -
             | 
| 148 | 
            -
             | 
| 149 | 
            -
             | 
| 150 | 
            -
             | 
| 151 | 
            -
             | 
| 152 | 
            -
             | 
| 153 | 
            -
             | 
| 154 | 
            -
                       | 
| 155 | 
            -
             | 
| 222 | 
            +
                  it 'promotes all nodes' do
         | 
| 223 | 
            +
                    %w(env2 env3 env4).each do |env|
         | 
| 224 | 
            +
                      expect(subject).to receive(:promote_to).with('env1', env, ui)
         | 
| 225 | 
            +
                      expect(uploader).to receive(:upload_environment).with(env, ui)
         | 
| 226 | 
            +
                    end
         | 
| 227 | 
            +
                    expect(prov_shell).not_to receive(:converge?)
         | 
| 228 | 
            +
                    expect(good_shell).to receive(:converge?)
         | 
| 229 | 
            +
                    subject.monitor_promotion(
         | 
| 230 | 
            +
                      'env1',
         | 
| 231 | 
            +
                      %w(env2 env3 env4),
         | 
| 232 | 
            +
                      3,
         | 
| 233 | 
            +
                      0.25,
         | 
| 234 | 
            +
                      false,
         | 
| 235 | 
            +
                      ui
         | 
| 236 | 
            +
                    )
         | 
| 156 237 | 
             
                  end
         | 
| 157 238 | 
             
                end
         | 
| 158 239 |  | 
| 159 | 
            -
                context ' | 
| 240 | 
            +
                context 'converge fails' do
         | 
| 160 241 | 
             
                  before do
         | 
| 161 242 | 
             
                    allow(Promote::NodeFinder).to(
         | 
| 162 | 
            -
                      receive(:new).with( | 
| 163 | 
            -
                         | 
| 243 | 
            +
                      receive(:new).with(
         | 
| 244 | 
            +
                        "chef_environment:#{env} AND platform:ubuntu",
         | 
| 245 | 
            +
                        config
         | 
| 246 | 
            +
                      ).and_return(finder_bad)
         | 
| 164 247 | 
             
                    )
         | 
| 165 248 | 
             
                  end
         | 
| 166 249 |  | 
| 167 | 
            -
                   | 
| 168 | 
            -
                     | 
| 169 | 
            -
             | 
| 170 | 
            -
             | 
| 250 | 
            +
                  context 'source environment does not fully converge' do
         | 
| 251 | 
            +
                    let(:env) { 'env1' }
         | 
| 252 | 
            +
             | 
| 253 | 
            +
                    it 'promotes no nodes' do
         | 
| 254 | 
            +
                      expect(subject).not_to receive(:promote_to)
         | 
| 255 | 
            +
                      expect(uploader).not_to receive(:upload_environment)
         | 
| 256 | 
            +
             | 
| 257 | 
            +
                      expect do
         | 
| 258 | 
            +
                        subject.monitor_promotion(
         | 
| 259 | 
            +
                          'env1',
         | 
| 260 | 
            +
                          %w(env2 env3 env4),
         | 
| 261 | 
            +
                          3,
         | 
| 262 | 
            +
                          0.25,
         | 
| 263 | 
            +
                          false,
         | 
| 264 | 
            +
                          ui
         | 
| 265 | 
            +
                        )
         | 
| 266 | 
            +
                      end.to raise_error(/env1/)
         | 
| 267 | 
            +
                    end
         | 
| 268 | 
            +
                  end
         | 
| 269 | 
            +
             | 
| 270 | 
            +
                  context 'stops promotion when promotion fails' do
         | 
| 271 | 
            +
                    let(:env) { 'env3' }
         | 
| 272 | 
            +
             | 
| 273 | 
            +
                    it 'stops on failure' do
         | 
| 274 | 
            +
                      %w(env2 env3).each do |env|
         | 
| 275 | 
            +
                        expect(subject).to receive(:promote_to).with('env1', env, ui)
         | 
| 276 | 
            +
                        expect(uploader).to receive(:upload_environment).with(env, ui)
         | 
| 277 | 
            +
                      end
         | 
| 278 | 
            +
                      expect(subject).not_to receive(:promote_to).with('env1', 'env4', ui)
         | 
| 279 | 
            +
                      expect(uploader).not_to receive(:upload_environment).with('env4')
         | 
| 280 | 
            +
                      expect do
         | 
| 281 | 
            +
                        subject.monitor_promotion(
         | 
| 282 | 
            +
                          'env1',
         | 
| 283 | 
            +
                          %w(env2 env3 env4),
         | 
| 284 | 
            +
                          3,
         | 
| 285 | 
            +
                          0.25,
         | 
| 286 | 
            +
                          false,
         | 
| 287 | 
            +
                          ui
         | 
| 288 | 
            +
                        )
         | 
| 289 | 
            +
                      end.to raise_error(/env3/)
         | 
| 171 290 | 
             
                    end
         | 
| 172 | 
            -
                    expect(subject).not_to receive(:promote_to).with('env1', 'env4', ui)
         | 
| 173 | 
            -
                    expect(uploader).not_to receive(:upload_environment).with('env4')
         | 
| 174 | 
            -
                    expect do
         | 
| 175 | 
            -
                      subject.monitor_promotion(
         | 
| 176 | 
            -
                        'env1',
         | 
| 177 | 
            -
                        %w(env2 env3 env4),
         | 
| 178 | 
            -
                        0.25,
         | 
| 179 | 
            -
                        false,
         | 
| 180 | 
            -
                        1,
         | 
| 181 | 
            -
                        ui
         | 
| 182 | 
            -
                      )
         | 
| 183 | 
            -
                    end.to raise_error(/env3$/)
         | 
| 184 291 | 
             
                  end
         | 
| 185 292 | 
             
                end
         | 
| 186 293 | 
             
              end
         | 
| @@ -187,8 +187,18 @@ describe Promote::Uploader do | |
| 187 187 | 
             
                  let(:env_name) { 'my_test' }
         | 
| 188 188 |  | 
| 189 189 | 
             
                  it 'uploads the environment' do
         | 
| 190 | 
            -
                    expect(Chef::ChefFS::FileSystem).to receive(:copy_to).with( | 
| 191 | 
            -
                       | 
| 190 | 
            +
                    expect(Chef::ChefFS::FileSystem).to receive(:copy_to).with(
         | 
| 191 | 
            +
                      an_instance_of(Chef::ChefFS::FilePattern),
         | 
| 192 | 
            +
                      anything,
         | 
| 193 | 
            +
                      anything,
         | 
| 194 | 
            +
                      anything,
         | 
| 195 | 
            +
                      anything,
         | 
| 196 | 
            +
                      anything,
         | 
| 197 | 
            +
                      anything
         | 
| 198 | 
            +
                    ) do |arg|
         | 
| 199 | 
            +
                      expect(arg.pattern).to eq(
         | 
| 200 | 
            +
                        File.join('/environments', "#{env_name}.json")
         | 
| 201 | 
            +
                      )
         | 
| 192 202 | 
             
                    end
         | 
| 193 203 | 
             
                    subject.upload_environment(env_name)
         | 
| 194 204 | 
             
                  end
         | 
| @@ -196,19 +206,20 @@ describe Promote::Uploader do | |
| 196 206 |  | 
| 197 207 | 
             
                context 'upload all environments' do
         | 
| 198 208 | 
             
                  it 'uploads the environment' do
         | 
| 199 | 
            -
                     | 
| 209 | 
            +
                    local = Chef::ChefFS::Config.new.local_fs.child_paths['environments']
         | 
| 200 210 |  | 
| 201 211 | 
             
                    expect(Chef::ChefFS::FileSystem).to receive(:copy_to).with(
         | 
| 202 212 | 
             
                      an_instance_of(Chef::ChefFS::FilePattern),
         | 
| 203 | 
            -
                      an_instance_of( | 
| 204 | 
            -
             | 
| 205 | 
            -
                      anything | 
| 206 | 
            -
                      anything | 
| 207 | 
            -
                      anything | 
| 208 | 
            -
                      anything | 
| 213 | 
            +
                      an_instance_of(
         | 
| 214 | 
            +
                        Chef::ChefFS::FileSystem::ChefRepositoryFileSystemRootDir),
         | 
| 215 | 
            +
                      anything,
         | 
| 216 | 
            +
                      anything,
         | 
| 217 | 
            +
                      anything,
         | 
| 218 | 
            +
                      anything,
         | 
| 219 | 
            +
                      anything
         | 
| 209 220 | 
             
                    ) do |file_pattern, source|
         | 
| 210 221 | 
             
                      expect(file_pattern.pattern).to eq(File.join('/environments/*.json'))
         | 
| 211 | 
            -
                      expect(source.child_paths['environments']).to eq( | 
| 222 | 
            +
                      expect(source.child_paths['environments']).to eq(local)
         | 
| 212 223 | 
             
                    end
         | 
| 213 224 | 
             
                    subject.upload_environments
         | 
| 214 225 | 
             
                  end
         | 
| @@ -219,13 +230,14 @@ describe Promote::Uploader do | |
| 219 230 | 
             
                    local_roles = Chef::ChefFS::Config.new.local_fs.child_paths['roles']
         | 
| 220 231 |  | 
| 221 232 | 
             
                    expect(Chef::ChefFS::FileSystem).to receive(:copy_to).with(
         | 
| 222 | 
            -
             | 
| 223 | 
            -
             | 
| 224 | 
            -
             | 
| 225 | 
            -
             | 
| 226 | 
            -
             | 
| 227 | 
            -
             | 
| 228 | 
            -
             | 
| 233 | 
            +
                      an_instance_of(Chef::ChefFS::FilePattern),
         | 
| 234 | 
            +
                      an_instance_of(
         | 
| 235 | 
            +
                        Chef::ChefFS::FileSystem::ChefRepositoryFileSystemRootDir),
         | 
| 236 | 
            +
                      anything,
         | 
| 237 | 
            +
                      anything,
         | 
| 238 | 
            +
                      anything,
         | 
| 239 | 
            +
                      anything,
         | 
| 240 | 
            +
                      anything
         | 
| 229 241 | 
             
                    ) do |file_pattern, source|
         | 
| 230 242 | 
             
                      expect(file_pattern.pattern).to eq(File.join('/roles/*.json'))
         | 
| 231 243 | 
             
                      expect(source.child_paths['roles']).to eq(local_roles)
         | 
| @@ -238,24 +250,27 @@ describe Promote::Uploader do | |
| 238 250 | 
             
                  let(:temp_data_bags) { File.join(config.temp_directory, 'data_bags') }
         | 
| 239 251 | 
             
                  let(:fake_bag_file) { File.join('bags', 'bag.json') }
         | 
| 240 252 | 
             
                  let(:secret_key_file) { File.join('bags', 'bag_secrets_keys.json') }
         | 
| 241 | 
            -
                  let(:config)  | 
| 242 | 
            -
                     | 
| 243 | 
            -
             | 
| 244 | 
            -
             | 
| 245 | 
            -
             | 
| 246 | 
            -
             | 
| 253 | 
            +
                  let(:config) do
         | 
| 254 | 
            +
                    Promote::Config.new(
         | 
| 255 | 
            +
                      temp_directory: '/tmp/promote_tests',
         | 
| 256 | 
            +
                      repo_root: '/tmp/promote_repo',
         | 
| 257 | 
            +
                      node_name: 'user',
         | 
| 258 | 
            +
                      client_key: 'key',
         | 
| 259 | 
            +
                      chef_server_url: 'https://some.chef.server'
         | 
| 260 | 
            +
                    )
         | 
| 261 | 
            +
                  end
         | 
| 247 262 |  | 
| 248 | 
            -
                  before  | 
| 263 | 
            +
                  before do
         | 
| 249 264 | 
             
                    fake_bag_path = File.join(config.data_bag_directory, fake_bag_file)
         | 
| 250 265 | 
             
                    FileUtils.mkdir_p(File.dirname(fake_bag_path))
         | 
| 251 266 | 
             
                    FileUtils.touch(fake_bag_path)
         | 
| 252 267 | 
             
                    FileUtils.touch(File.join(config.data_bag_directory, secret_key_file))
         | 
| 253 | 
            -
                   | 
| 268 | 
            +
                  end
         | 
| 254 269 |  | 
| 255 | 
            -
                  after  | 
| 270 | 
            +
                  after do
         | 
| 256 271 | 
             
                    FileUtils.rm_rf(config.temp_directory)
         | 
| 257 272 | 
             
                    FileUtils.rm_rf(config.repo_root)
         | 
| 258 | 
            -
                   | 
| 273 | 
            +
                  end
         | 
| 259 274 |  | 
| 260 275 | 
             
                  it 'copies the data_bags to a temp folder' do
         | 
| 261 276 | 
             
                    subject.upload_data_bags
         | 
| @@ -272,12 +287,13 @@ describe Promote::Uploader do | |
| 272 287 | 
             
                  it 'uploads the data_bags to chef' do
         | 
| 273 288 | 
             
                    expect(Chef::ChefFS::FileSystem).to receive(:copy_to).with(
         | 
| 274 289 | 
             
                      an_instance_of(Chef::ChefFS::FilePattern),
         | 
| 275 | 
            -
                      an_instance_of( | 
| 276 | 
            -
             | 
| 277 | 
            -
                      anything | 
| 278 | 
            -
                      anything | 
| 279 | 
            -
                      anything | 
| 280 | 
            -
                      anything | 
| 290 | 
            +
                      an_instance_of(
         | 
| 291 | 
            +
                        Chef::ChefFS::FileSystem::ChefRepositoryFileSystemRootDir),
         | 
| 292 | 
            +
                      anything,
         | 
| 293 | 
            +
                      anything,
         | 
| 294 | 
            +
                      anything,
         | 
| 295 | 
            +
                      anything,
         | 
| 296 | 
            +
                      anything
         | 
| 281 297 | 
             
                    ) do |file_pattern, source|
         | 
| 282 298 | 
             
                      expect(file_pattern.pattern).to eq('/data_bags/**/*.json')
         | 
| 283 299 | 
             
                      expect(source.child_paths['data_bags']).to eq([temp_data_bags])
         |