r10k 2.2.2 → 2.3.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.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.mkd +25 -0
  3. data/Gemfile +1 -1
  4. data/doc/dynamic-environments/configuration.mkd +36 -11
  5. data/integration/tests/basic_functionality/proxy_with_pe_only_module.rb +128 -0
  6. data/lib/r10k/errors.rb +18 -0
  7. data/lib/r10k/forge/module_release.rb +3 -3
  8. data/lib/r10k/git.rb +53 -0
  9. data/lib/r10k/git/rugged/bare_repository.rb +16 -7
  10. data/lib/r10k/git/rugged/base_repository.rb +16 -2
  11. data/lib/r10k/git/rugged/credentials.rb +9 -0
  12. data/lib/r10k/git/rugged/working_repository.rb +18 -5
  13. data/lib/r10k/git/shellgit/bare_repository.rb +12 -3
  14. data/lib/r10k/git/shellgit/base_repository.rb +19 -3
  15. data/lib/r10k/git/shellgit/working_repository.rb +13 -3
  16. data/lib/r10k/initializers.rb +1 -0
  17. data/lib/r10k/settings.rb +41 -22
  18. data/lib/r10k/settings/collection.rb +25 -21
  19. data/lib/r10k/settings/definition.rb +14 -2
  20. data/lib/r10k/settings/helpers.rb +38 -0
  21. data/lib/r10k/settings/list.rb +107 -0
  22. data/lib/r10k/util/symbolize_keys.rb +6 -2
  23. data/lib/r10k/version.rb +1 -1
  24. data/r10k.gemspec +1 -1
  25. data/r10k.yaml.example +38 -12
  26. data/spec/shared-examples/git/bare_repository.rb +62 -0
  27. data/spec/shared-examples/git/working_repository.rb +57 -11
  28. data/spec/shared-examples/settings/ancestry.rb +44 -0
  29. data/spec/unit/forge/module_release_spec.rb +1 -1
  30. data/spec/unit/git/rugged/credentials_spec.rb +6 -0
  31. data/spec/unit/settings/collection_spec.rb +2 -1
  32. data/spec/unit/settings/definition_spec.rb +6 -5
  33. data/spec/unit/settings/inheritance_spec.rb +38 -0
  34. data/spec/unit/settings/list_spec.rb +88 -0
  35. data/spec/unit/settings_spec.rb +52 -23
  36. data/spec/unit/util/attempt_spec.rb +1 -1
  37. data/spec/unit/util/symbolize_keys_spec.rb +25 -9
  38. metadata +11 -4
@@ -21,8 +21,12 @@ module R10K
21
21
  end
22
22
 
23
23
  value = hash[key]
24
- if recurse && value.is_a?(Hash)
25
- symbolize_keys!(value, true)
24
+ if recurse
25
+ if value.is_a?(Hash)
26
+ symbolize_keys!(value, true)
27
+ elsif value.is_a?(Array)
28
+ value.map { |item| symbolize_keys!(item, true) if item.is_a?(Hash) }
29
+ end
26
30
  end
27
31
  end
28
32
  end
@@ -1,3 +1,3 @@
1
1
  module R10K
2
- VERSION = '2.2.2'
2
+ VERSION = '2.3.0'
3
3
  end
@@ -28,7 +28,7 @@ Gem::Specification.new do |s|
28
28
  s.add_dependency 'log4r', '1.1.10'
29
29
  s.add_dependency 'multi_json', '~> 1.10'
30
30
 
31
- s.add_dependency 'puppet_forge', '~> 2.1.5'
31
+ s.add_dependency 'puppet_forge', '~> 2.2'
32
32
  s.add_dependency 'semantic_puppet', '~> 0.1.0'
33
33
  s.add_dependency 'minitar'
34
34
 
@@ -9,18 +9,25 @@
9
9
  # be updated.
10
10
  #
11
11
  # The default value is "~/.r10k"
12
- cachedir: '/var/cache/r10k'
12
+ #cachedir: '/var/cache/r10k'
13
+
14
+ # The 'proxy' setting configures an HTTP proxy to use for all HTTP/HTTPS
15
+ # operations performed by r10k. This includes requests to the Puppet Forge
16
+ # as well as any Git operations performed against an HTTP/HTTPS remote.
17
+ # You can also configure specific proxies for only Git or Forge operations
18
+ # using settings below. Authenticated proxies can be configured by providing
19
+ # credentials in the URL, e.g. 'https://username:password@proxy.example.com:8888'
20
+ #proxy: 'https://proxy.example.com:8888'
13
21
 
14
22
  # The 'sources' setting determines what repositories r10k will use when creating
15
23
  # Puppet environments.
16
24
  sources:
17
25
  # Each source should have a unique name, and preferrably should only use
18
26
  # alphanumeric characters and underscores.
19
- operations:
20
-
27
+ #operations:
21
28
  # The 'remote' setting determines the location of the VCS repository used
22
29
  # for creating environments.
23
- remote: 'git@github.com:my-org/org-operations-modules'
30
+ #remote: 'git@github.com:my-org/org-operations-modules'
24
31
 
25
32
  # The 'basedir' setting specifies where environments will be created for
26
33
  # this source. This setting should match the Puppet 'environmentpath'
@@ -28,19 +35,19 @@ sources:
28
35
  #
29
36
  # See http://docs.puppetlabs.com/references/latest/configuration.html#environmentpath
30
37
  # for more information about the Puppet 'environmentpath' setting.
31
- basedir: '/etc/puppetlabs/puppet/environments'
38
+ #basedir: '/etc/puppetlabs/puppet/environments'
32
39
 
33
40
  # One or more sources can be specified; each source is simple another entry
34
41
  # in the sources map.
35
- qa:
36
- remote: 'git@github.com:my-org/org-qa-modules'
42
+ #qa:
43
+ #remote: 'git@github.com:my-org/org-qa-modules'
37
44
 
38
45
  # Multiple sources can have the same 'basedir' setting, in case there is a
39
46
  # reason to push different sets of environments to the same Puppet master.
40
47
  # If two different sources have the same basedir care should be exercised
41
48
  # to make sure that two sources don't try create multiple environments with
42
49
  # the same name. See the 'prefix' setting for more information.
43
- basedir: '/etc/puppetlabs/puppet/environments'
50
+ #basedir: '/etc/puppetlabs/puppet/environments'
44
51
 
45
52
  # Sources can use the 'prefix' setting to avoid collisions between multiple
46
53
  # sources being created in the same directory. Setting prefix to true
@@ -49,7 +56,7 @@ sources:
49
56
  # branch.
50
57
  #
51
58
  # The default value is 'false'.
52
- prefix: true
59
+ #prefix: true
53
60
 
54
61
  # Additional configuration can be supplied to configure how r10k uses Git
55
62
  # and what version of Git it uses.
@@ -58,7 +65,7 @@ git:
58
65
  # As of 1.5.0 r10k can interact with Git repositories in two ways - by
59
66
  # shelling out to the 'git' executable, and by using libgit2 through the
60
67
  # 'rugged' library.
61
- provider: 'shellgit' # Either 'shellgit' or 'rugged', defaults to 'shellgit'
68
+ #provider: 'shellgit' # Either 'shellgit' or 'rugged', defaults to 'shellgit'
62
69
 
63
70
  # The 'private_key' setting sets the the SSH private key to use for remote
64
71
  # Git repositories accessed over SSH.
@@ -73,8 +80,27 @@ git:
73
80
  # The 'username' setting is only used by the 'rugged' Git provider.
74
81
  #username: 'git'
75
82
 
83
+ # The 'proxy' setting configures an HTTP proxy to use for all Git sources
84
+ # that have an HTTP/HTTPS remote URL. This can be overridden on a
85
+ # per-repository basis using the 'repositories' setting below.
86
+ #proxy: 'https://proxy.example.com:8888'
87
+
88
+ # The 'repositories' setting allows other git related settings to be
89
+ # configured for each remote repository individually. The value of
90
+ # this setting should be a list of repositories with a 'remote' key
91
+ # to identify the specific repository to be configured.
92
+ #repositories:
93
+ # - remote: "ssh://tessier-ashpool.freeside/protected-repo.git"
94
+ # private_key: "/etc/puppetlabs/r10k/ssh/id_rsa-protected-repo-deploy-key"
95
+ # proxy: 'https://proxy.example.com:8888'
96
+
76
97
  # Configuration options for downloading modules from the Puppet Forge
77
98
  forge:
78
99
  # The 'proxy' setting specifies an optional HTTP proxy to use when making
79
- # requests to the Puppet Forge.
80
- proxy: 'http://my.site.proxy:3128'
100
+ # requests to the Puppet Forge. This will override the top level 'proxy'
101
+ # option or any proxy related environment variables when configured.
102
+ #proxy: 'https://proxy.example.com:8888'
103
+
104
+ # The 'baseurl' setting indicates where Forge modules should be installed
105
+ # from. This defaults to 'https://forgeapi.puppetlabs.com'
106
+ #baseurl: 'https://forgemirror.example.com'
@@ -17,6 +17,37 @@ RSpec.shared_examples "a git bare repository" do
17
17
  config = File.read(File.join(basedir, dirname, 'config'))
18
18
  expect(config).to match(remote)
19
19
  end
20
+
21
+ context "without a proxy" do
22
+ before(:each) do
23
+ allow(R10K::Git).to receive(:get_proxy_for_remote).with(remote).and_return(nil)
24
+ end
25
+
26
+ it 'does not change proxy ENV' do
27
+ expect(ENV).to_not receive(:[]=)
28
+ expect(ENV).to_not receive(:update)
29
+
30
+ subject.clone(remote)
31
+ end
32
+ end
33
+
34
+ context "with a proxy" do
35
+ before(:each) do
36
+ allow(R10K::Git).to receive(:get_proxy_for_remote).with(remote).and_return('http://proxy.example.com:3128')
37
+ end
38
+
39
+ it "manages proxy-related ENV vars" do
40
+ # Sets proxy settings.
41
+ ['HTTPS_PROXY', 'https_proxy', 'HTTP_PROXY', 'http_proxy'].each do |var|
42
+ expect(ENV).to receive(:[]=).with(var, 'http://proxy.example.com:3128')
43
+ end
44
+
45
+ # Resets proxy settings when done.
46
+ expect(ENV).to receive(:update).with(hash_including('HTTPS_PROXY' => nil))
47
+
48
+ subject.clone(remote)
49
+ end
50
+ end
20
51
  end
21
52
 
22
53
  describe "updating the repo" do
@@ -34,6 +65,37 @@ RSpec.shared_examples "a git bare repository" do
34
65
  subject.fetch
35
66
  expect(subject.tags).to include('0.9.0')
36
67
  end
68
+
69
+ context "without a proxy" do
70
+ before(:each) do
71
+ allow(R10K::Git).to receive(:get_proxy_for_remote).with(remote).and_return(nil)
72
+ end
73
+
74
+ it 'does not change proxy ENV' do
75
+ expect(ENV).to_not receive(:[]=)
76
+ expect(ENV).to_not receive(:update)
77
+
78
+ subject.fetch
79
+ end
80
+ end
81
+
82
+ context "with a proxy" do
83
+ before(:each) do
84
+ allow(R10K::Git).to receive(:get_proxy_for_remote).with(remote).and_return('http://proxy.example.com:3128')
85
+ end
86
+
87
+ it "manages proxy-related ENV vars" do
88
+ # Sets proxy settings.
89
+ ['HTTPS_PROXY', 'https_proxy', 'HTTP_PROXY', 'http_proxy'].each do |var|
90
+ expect(ENV).to receive(:[]=).with(var, 'http://proxy.example.com:3128')
91
+ end
92
+
93
+ # Resets proxy settings when done.
94
+ expect(ENV).to receive(:update).with(hash_including('HTTPS_PROXY' => nil))
95
+
96
+ subject.fetch
97
+ end
98
+ end
37
99
  end
38
100
 
39
101
  describe "listing branches" do
@@ -57,21 +57,36 @@ RSpec.shared_examples "a git working repository" do
57
57
  expect(alternates[0]).to match_realpath File.join(remote, 'objects')
58
58
  end
59
59
  end
60
- end
61
60
 
62
- describe "updating the repo" do
63
- let(:tag_090) { subject.git_dir + 'refs' + 'tags' + '0.9.0' }
64
- let(:packed_refs) { subject.git_dir + 'packed-refs' }
61
+ context "without a proxy" do
62
+ before(:each) do
63
+ allow(R10K::Git).to receive(:get_proxy_for_remote).with(remote).and_return(nil)
64
+ end
65
65
 
66
- before do
67
- subject.clone(remote)
68
- tag_090.delete if tag_090.exist?
69
- packed_refs.delete if packed_refs.exist?
66
+ it 'does not change proxy ENV' do
67
+ expect(ENV).to_not receive(:[]=)
68
+ expect(ENV).to_not receive(:update)
69
+
70
+ subject.clone(remote)
71
+ end
70
72
  end
71
73
 
72
- it "fetches objects from the remote" do
73
- subject.fetch
74
- expect(subject.tags).to include('0.9.0')
74
+ context "with a proxy" do
75
+ before(:each) do
76
+ allow(R10K::Git).to receive(:get_proxy_for_remote).with(remote).and_return('http://proxy.example.com:3128')
77
+ end
78
+
79
+ it "manages proxy-related ENV vars" do
80
+ # Sets proxy settings.
81
+ ['HTTPS_PROXY', 'https_proxy', 'HTTP_PROXY', 'http_proxy'].each do |var|
82
+ expect(ENV).to receive(:[]=).with(var, 'http://proxy.example.com:3128')
83
+ end
84
+
85
+ # Resets proxy settings when done.
86
+ expect(ENV).to receive(:update).with(hash_including('HTTPS_PROXY' => nil))
87
+
88
+ subject.clone(remote)
89
+ end
75
90
  end
76
91
  end
77
92
 
@@ -90,6 +105,37 @@ RSpec.shared_examples "a git working repository" do
90
105
  subject.fetch
91
106
  expect(subject.tags).to include('0.9.0')
92
107
  end
108
+
109
+ context "without a proxy" do
110
+ before(:each) do
111
+ allow(R10K::Git).to receive(:get_proxy_for_remote).with(remote).and_return(nil)
112
+ end
113
+
114
+ it 'does not change proxy ENV' do
115
+ expect(ENV).to_not receive(:[]=)
116
+ expect(ENV).to_not receive(:update)
117
+
118
+ subject.fetch
119
+ end
120
+ end
121
+
122
+ context "with a proxy" do
123
+ before(:each) do
124
+ allow(R10K::Git).to receive(:get_proxy_for_remote).with(remote).and_return('http://proxy.example.com:3128')
125
+ end
126
+
127
+ it "manages proxy-related ENV vars" do
128
+ # Sets proxy settings.
129
+ ['HTTPS_PROXY', 'https_proxy', 'HTTP_PROXY', 'http_proxy'].each do |var|
130
+ expect(ENV).to receive(:[]=).with(var, 'http://proxy.example.com:3128')
131
+ end
132
+
133
+ # Resets proxy settings when done.
134
+ expect(ENV).to receive(:update).with(hash_including('HTTPS_PROXY' => nil))
135
+
136
+ subject.fetch
137
+ end
138
+ end
93
139
  end
94
140
 
95
141
  describe "listing branches" do
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ require 'r10k/settings/collection'
4
+ require 'r10k/settings/list'
5
+
6
+ shared_examples_for "a setting with ancestors" do
7
+ describe '#parent=' do
8
+ it "allows assignment to a collection" do
9
+ parent = R10K::Settings::Collection.new(:parent, [])
10
+
11
+ subject.parent = parent
12
+
13
+ expect(subject.parent).to eq parent
14
+ end
15
+
16
+ it "allows assignment to a list" do
17
+ parent = R10K::Settings::List.new(:parent, [])
18
+
19
+ subject.parent = parent
20
+
21
+ expect(subject.parent).to eq parent
22
+ end
23
+
24
+ it "rejects assignment when argument is not a settings collection or list" do
25
+ parent = Hash.new
26
+
27
+ expect { subject.parent = parent }.to raise_error do |error|
28
+ expect(error.message).to match /may only belong to a settings collection or list/i
29
+ end
30
+ end
31
+
32
+ it "rejects re-assignment" do
33
+ parent = R10K::Settings::Collection.new(:parent, [])
34
+ step_parent = R10K::Settings::Collection.new(:step_parent, [])
35
+
36
+ subject.parent = parent
37
+
38
+ expect { subject.parent = step_parent }.to raise_error do |error|
39
+ expect(error.message).to match /cannot be reassigned.*new parent/i
40
+ end
41
+ end
42
+ end
43
+ end
44
+
@@ -27,7 +27,7 @@ describe R10K::Forge::ModuleRelease do
27
27
 
28
28
  describe '#verify' do
29
29
  it "verifies the module checksum based on the Forge file checksum" do
30
- allow(subject.forge_release).to receive(:data).and_return('file_md5' => 'something')
30
+ allow(subject.forge_release).to receive(:file_md5).and_return('something')
31
31
  expect(subject.forge_release).to receive(:verify).with(download_path)
32
32
  subject.verify
33
33
  end
@@ -99,5 +99,11 @@ describe R10K::Git::Rugged::Credentials, :unless => R10K::Util::Platform.jruby?
99
99
  it "creates default credentials when no other types are allowed" do
100
100
  expect(subject.call("https://tessier-ashpool.freeside/repo.git", nil, [])).to be_a_kind_of(Rugged::Credentials::Default)
101
101
  end
102
+
103
+ it "refuses to generate credentials more than 50 times" do
104
+ (1..50).each { subject.call("https://tessier-ashpool.freeside/repo.git", nil, [:plaintext]) }
105
+
106
+ expect { subject.call("https://tessier-ashpool.freeside/repo.git", nil, [:plaintext]) }.to raise_error(R10K::Git::GitError, /authentication failed/i)
107
+ end
102
108
  end
103
109
  end
@@ -11,6 +11,8 @@ describe R10K::Settings::Collection do
11
11
  described_class.new(:collection, [symbol_defn, default_defn])
12
12
  end
13
13
 
14
+ it_behaves_like "a setting with ancestors"
15
+
14
16
  describe "#evaluate" do
15
17
  it "assigns values, validates them, and resolves a final value" do
16
18
  expect(subject).to receive(:assign).with({:default_defn => :squid})
@@ -20,7 +22,6 @@ describe R10K::Settings::Collection do
20
22
  end
21
23
  end
22
24
 
23
-
24
25
  describe '#assign' do
25
26
  it "assigns values to the appropriate setting" do
26
27
  subject.assign({:symbol_defn => :hello})
@@ -1,10 +1,15 @@
1
1
  require 'spec_helper'
2
2
  require 'r10k/settings/definition'
3
+ require 'r10k/settings/collection'
4
+ require 'r10k/settings/list'
3
5
 
4
6
  describe R10K::Settings::Definition do
7
+ subject { described_class.new(:setting) }
8
+
9
+ it_behaves_like "a setting with ancestors"
10
+
5
11
  describe "#evaluate" do
6
12
  it "assigns a value, validates it, and resolves a final value" do
7
- subject = described_class.new(:setting)
8
13
  expect(subject).to receive(:assign).with("myvalue")
9
14
  expect(subject).to receive(:validate)
10
15
  expect(subject).to receive(:resolve)
@@ -14,7 +19,6 @@ describe R10K::Settings::Definition do
14
19
 
15
20
  describe "#assign" do
16
21
  it 'stores the provided value' do
17
- subject = described_class.new(:setting)
18
22
  subject.assign("I'm the value")
19
23
  expect(subject.value).to eq "I'm the value"
20
24
  end
@@ -33,7 +37,6 @@ describe R10K::Settings::Definition do
33
37
  end
34
38
 
35
39
  it "does nothing if a validate hook has not been assigned" do
36
- subject = described_class.new(:setting)
37
40
  subject.assign("I'm the value")
38
41
  subject.validate
39
42
  end
@@ -55,7 +58,6 @@ describe R10K::Settings::Definition do
55
58
 
56
59
  describe "#resolve" do
57
60
  it "returns the value when the value has been given" do
58
- subject = described_class.new(:setting)
59
61
  subject.assign("Mun")
60
62
  expect(subject.resolve).to eq "Mun"
61
63
  end
@@ -71,7 +73,6 @@ describe R10K::Settings::Definition do
71
73
  end
72
74
 
73
75
  it "returns nil when there is no value nor default" do
74
- subject = described_class.new(:setting)
75
76
  expect(subject.resolve).to be_nil
76
77
  end
77
78
  end
@@ -0,0 +1,38 @@
1
+ require 'spec_helper'
2
+ require 'r10k/settings/collection'
3
+ require 'r10k/settings/definition'
4
+
5
+ RSpec.describe 'R10K::Settings inheritance' do
6
+ subject do
7
+ R10K::Settings::Collection.new(:parent_settings, [
8
+ R10K::Settings::Definition.new(:banana, {
9
+ :default => 'cavendish',
10
+ }),
11
+
12
+ R10K::Settings::Collection.new(:child_settings, [
13
+ R10K::Settings::Definition.new(:banana, {
14
+ :default => :inherit,
15
+ }),
16
+ ]),
17
+ ])
18
+ end
19
+
20
+ describe "child settings" do
21
+ let(:setting) { subject[:child_settings][:banana] }
22
+
23
+ context "when child value is not set" do
24
+ it "should resolve to default value from parent" do
25
+ expect(setting.value).to be_nil
26
+ expect(setting.resolve).to eq 'cavendish'
27
+ end
28
+ end
29
+
30
+ context "when child value is set" do
31
+ before(:each) { setting.assign('gros michel') }
32
+
33
+ it "should resolve to child value" do
34
+ expect(setting.resolve).to eq 'gros michel'
35
+ end
36
+ end
37
+ end
38
+ end