r10k 3.7.0 → 3.9.3

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 (85) hide show
  1. checksums.yaml +4 -4
  2. data/.github/pull_request_template.md +1 -1
  3. data/.github/workflows/docker.yml +4 -1
  4. data/.github/workflows/release.yml +3 -2
  5. data/.github/workflows/rspec_tests.yml +1 -1
  6. data/.github/workflows/stale.yml +19 -0
  7. data/.travis.yml +8 -1
  8. data/CHANGELOG.mkd +32 -0
  9. data/CODEOWNERS +2 -2
  10. data/doc/common-patterns.mkd +1 -0
  11. data/doc/dynamic-environments/configuration.mkd +114 -42
  12. data/doc/dynamic-environments/usage.mkd +12 -11
  13. data/doc/puppetfile.mkd +23 -3
  14. data/docker/Gemfile +1 -1
  15. data/docker/Makefile +4 -3
  16. data/docker/docker-compose.yml +18 -0
  17. data/docker/r10k/Dockerfile +1 -1
  18. data/docker/r10k/docker-entrypoint.sh +0 -1
  19. data/docker/r10k/release.Dockerfile +1 -1
  20. data/docker/spec/dockerfile_spec.rb +26 -32
  21. data/integration/tests/git_source/git_source_repeated_remote.rb +2 -2
  22. data/integration/tests/user_scenario/basic_workflow/multi_env_custom_forge_git_module.rb +2 -1
  23. data/integration/tests/user_scenario/basic_workflow/multi_env_custom_forge_git_module_static.rb +2 -1
  24. data/integration/tests/user_scenario/basic_workflow/multi_source_custom_forge_git_module.rb +1 -1
  25. data/integration/tests/user_scenario/basic_workflow/single_env_custom_forge_git_module.rb +2 -1
  26. data/lib/r10k/action/base.rb +10 -0
  27. data/lib/r10k/action/deploy/display.rb +49 -10
  28. data/lib/r10k/action/deploy/environment.rb +101 -51
  29. data/lib/r10k/action/deploy/module.rb +54 -30
  30. data/lib/r10k/action/puppetfile/check.rb +3 -1
  31. data/lib/r10k/action/puppetfile/install.rb +20 -23
  32. data/lib/r10k/action/puppetfile/purge.rb +8 -2
  33. data/lib/r10k/action/runner.rb +33 -0
  34. data/lib/r10k/cli/deploy.rb +13 -7
  35. data/lib/r10k/cli/puppetfile.rb +5 -5
  36. data/lib/r10k/content_synchronizer.rb +83 -0
  37. data/lib/r10k/deployment.rb +1 -1
  38. data/lib/r10k/environment/base.rb +29 -2
  39. data/lib/r10k/environment/git.rb +17 -5
  40. data/lib/r10k/environment/name.rb +22 -4
  41. data/lib/r10k/environment/svn.rb +11 -4
  42. data/lib/r10k/environment/with_modules.rb +46 -30
  43. data/lib/r10k/git.rb +1 -0
  44. data/lib/r10k/git/rugged/credentials.rb +39 -2
  45. data/lib/r10k/initializers.rb +1 -0
  46. data/lib/r10k/module.rb +1 -1
  47. data/lib/r10k/module/base.rb +17 -1
  48. data/lib/r10k/module/forge.rb +29 -11
  49. data/lib/r10k/module/git.rb +50 -27
  50. data/lib/r10k/module/local.rb +2 -1
  51. data/lib/r10k/module/svn.rb +24 -18
  52. data/lib/r10k/puppetfile.rb +66 -83
  53. data/lib/r10k/settings.rb +18 -2
  54. data/lib/r10k/source/base.rb +9 -0
  55. data/lib/r10k/source/git.rb +18 -7
  56. data/lib/r10k/source/hash.rb +5 -5
  57. data/lib/r10k/source/svn.rb +5 -3
  58. data/lib/r10k/util/cleaner.rb +21 -0
  59. data/lib/r10k/util/setopts.rb +33 -12
  60. data/lib/r10k/version.rb +1 -1
  61. data/locales/r10k.pot +98 -82
  62. data/r10k.gemspec +1 -1
  63. data/spec/fixtures/unit/action/r10k_creds.yaml +9 -0
  64. data/spec/r10k-mocks/mock_source.rb +1 -1
  65. data/spec/shared-examples/puppetfile-action.rb +7 -7
  66. data/spec/unit/action/deploy/display_spec.rb +35 -5
  67. data/spec/unit/action/deploy/environment_spec.rb +199 -38
  68. data/spec/unit/action/deploy/module_spec.rb +162 -28
  69. data/spec/unit/action/puppetfile/check_spec.rb +2 -2
  70. data/spec/unit/action/puppetfile/install_spec.rb +31 -10
  71. data/spec/unit/action/puppetfile/purge_spec.rb +25 -5
  72. data/spec/unit/action/runner_spec.rb +48 -1
  73. data/spec/unit/environment/git_spec.rb +19 -2
  74. data/spec/unit/environment/name_spec.rb +28 -0
  75. data/spec/unit/environment/svn_spec.rb +12 -0
  76. data/spec/unit/environment/with_modules_spec.rb +74 -0
  77. data/spec/unit/git/rugged/credentials_spec.rb +78 -1
  78. data/spec/unit/module/forge_spec.rb +21 -13
  79. data/spec/unit/module/git_spec.rb +63 -8
  80. data/spec/unit/module_spec.rb +77 -10
  81. data/spec/unit/puppetfile_spec.rb +63 -60
  82. data/spec/unit/util/purgeable_spec.rb +2 -8
  83. data/spec/unit/util/setopts_spec.rb +25 -1
  84. metadata +11 -12
  85. data/azure-pipelines.yml +0 -87
data/doc/puppetfile.mkd CHANGED
@@ -109,11 +109,19 @@ latest version available.
109
109
 
110
110
  mod 'puppetlabs/apache', :latest
111
111
 
112
+ An explicit type and/or version can be specified using the standard interface,
113
+ `:type` and `:version`. The `:source` parameter is not supported for individual
114
+ forge modules and will be ignored.
115
+
116
+ mod 'puppetlabs/apache',
117
+ type: 'forge',
118
+ version: '6.0.0'
119
+
112
120
  ### Git
113
121
 
114
122
  Git repositories that contain a Puppet module can be cloned and used as modules.
115
123
  When Git is used, the module version can be specified by using `:ref`, `:tag`,
116
- `:commit`, and `:branch`.
124
+ `:commit`, `:branch`, or the standard interface parameter `:version`.
117
125
 
118
126
  When a module is installed using `:ref`, r10k uses some simple heuristics to
119
127
  determine the type of Git object that should be checked out. This can be used
@@ -153,6 +161,13 @@ mod 'apache',
153
161
  mod 'apache',
154
162
  :git => 'https://github.com/puppetlabs/puppetlabs-apache',
155
163
  :branch => 'docs_experiment'
164
+
165
+ # Install puppetlabs/apache and use standard interface parameters pinned to the
166
+ # '2098a17' commit.
167
+ mod 'puppetlabs-apache',
168
+ type: 'git',
169
+ source: 'https://github.com/puppetlabs/puppetlabs-apache',
170
+ version: '2098a17'
156
171
  ```
157
172
 
158
173
  #### Control Repo Branch Tracking
@@ -195,8 +210,8 @@ the latest version available in the main SVN repository.
195
210
  mod 'apache',
196
211
  :svn => 'https://github.com/puppetlabs/puppetlabs-apache/trunk'
197
212
 
198
- If an SVN revision number is specified with `:rev` (or `:revision`), that
199
- SVN revision will be kept checked out.
213
+ If an SVN revision number is specified with `:rev`, `:revision`, or `:version`,
214
+ that SVN revision will be kept checked out.
200
215
 
201
216
  mod 'apache',
202
217
  :svn => 'https://github.com/puppetlabs/puppetlabs-apache/trunk',
@@ -206,6 +221,11 @@ SVN revision will be kept checked out.
206
221
  :svn => 'https://github.com/puppetlabs/puppetlabs-apache/trunk',
207
222
  :revision => '154'
208
223
 
224
+ mod 'apache',
225
+ type: 'svn',
226
+ source: 'https://github.com/puppetlabs/puppetlabs-apache/trunk',
227
+ version: '154'
228
+
209
229
  If the SVN repository requires credentials, you can supply the `:username` and
210
230
  `:password` options.
211
231
 
data/docker/Gemfile CHANGED
@@ -2,7 +2,7 @@ source "https://rubygems.org"
2
2
 
3
3
  gem 'pupperware',
4
4
  :git => 'https://github.com/puppetlabs/pupperware.git',
5
- :branch => 'master',
5
+ :branch => 'main',
6
6
  :glob => 'gem/*.gemspec'
7
7
 
8
8
  group :test do
data/docker/Makefile CHANGED
@@ -5,12 +5,12 @@ vcs_ref := $(shell git rev-parse HEAD)
5
5
  build_date := $(shell date -u +%FT%T)
6
6
  hadolint_available := $(shell hadolint --help > /dev/null 2>&1; echo $$?)
7
7
  hadolint_command := hadolint
8
- hadolint_container := hadolint/hadolint:latest
8
+ hadolint_container := ghcr.io/hadolint/hadolint:latest
9
9
  alpine_version := 3.9
10
10
  export BUNDLE_PATH = $(PWD)/.bundle/gems
11
11
  export BUNDLE_BIN = $(PWD)/.bundle/bin
12
12
  export GEMFILE = $(PWD)/Gemfile
13
- export DOCKER_BUILDKIT = 1
13
+ export DOCKER_BUILDKIT ?= 1
14
14
 
15
15
  ifeq ($(IS_RELEASE),true)
16
16
  VERSION ?= $(shell echo $(git_describe) | sed 's/-.*//')
@@ -50,8 +50,9 @@ endif
50
50
 
51
51
  build: prep
52
52
  docker pull alpine:$(alpine_version)
53
- docker build \
53
+ docker buildx build \
54
54
  ${DOCKER_BUILD_FLAGS} \
55
+ --load \
55
56
  --build-arg alpine_version=$(alpine_version) \
56
57
  --build-arg vcs_ref=$(vcs_ref) \
57
58
  --build-arg build_date=$(build_date) \
@@ -0,0 +1,18 @@
1
+ version: '3.7'
2
+
3
+ services:
4
+ r10k_check:
5
+ image: ${R10K_IMAGE:-puppet/r10k}
6
+ environment:
7
+ - PUPPERWARE_ANALYTICS_ENABLED=${PUPPERWARE_ANALYTICS_ENABLED:-false}
8
+ command: 'puppetfile check --verbose --trace --puppetfile test/Puppetfile'
9
+ volumes:
10
+ - ${SPEC_DIRECTORY}/fixtures:/home/puppet/test
11
+
12
+ r10k_install:
13
+ image: ${R10K_IMAGE:-puppet/r10k}
14
+ environment:
15
+ - PUPPERWARE_ANALYTICS_ENABLED=${PUPPERWARE_ANALYTICS_ENABLED:-false}
16
+ command: 'puppetfile install --verbose --trace --puppetfile test/Puppetfile'
17
+ volumes:
18
+ - ${SPEC_DIRECTORY}/fixtures:/home/puppet/test
@@ -49,7 +49,7 @@ COPY --from=build /workspace/r10k.gem /
49
49
  SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
50
50
  # ignore apk and gem pinning
51
51
  # hadolint ignore=DL3018,DL3028
52
- RUN chmod a+x /adduser.sh /docker-entrypoint.sh && \
52
+ RUN chmod a+x /adduser.sh /docker-entrypoint.sh /docker-entrypoint.d/*.sh && \
53
53
  # Add a puppet user to run r10k as for consistency with puppetserver
54
54
  /adduser.sh && \
55
55
  chown -R puppet: /docker-entrypoint.d /docker-entrypoint.sh && \
@@ -4,7 +4,6 @@ set -e
4
4
 
5
5
  for f in /docker-entrypoint.d/*.sh; do
6
6
  # Don't print out any messages here since this is a CLI container
7
- chmod +x "$f"
8
7
  "$f"
9
8
  done
10
9
 
@@ -38,7 +38,7 @@ LABEL org.label-schema.version="$version" \
38
38
  SHELL ["/bin/ash", "-eo", "pipefail", "-c"]
39
39
  # ignore apk and gem pinning
40
40
  # hadolint ignore=DL3018,DL3028
41
- RUN chmod a+x /adduser.sh /docker-entrypoint.sh && \
41
+ RUN chmod a+x /adduser.sh /docker-entrypoint.sh /docker-entrypoint.d/*.sh && \
42
42
  /adduser.sh && \
43
43
  chown -R puppet: /docker-entrypoint.d /docker-entrypoint.sh && \
44
44
  apk add --no-cache ruby openssh-client git ruby-rugged curl ruby-dev make gcc musl-dev && \
@@ -1,43 +1,37 @@
1
1
  require 'rspec/core'
2
2
  require 'fileutils'
3
3
  require 'open3'
4
+ include Pupperware::SpecHelpers
4
5
 
5
- SPEC_DIRECTORY = File.dirname(__FILE__)
6
+ ENV['SPEC_DIRECTORY'] = File.dirname(__FILE__)
7
+ # unifies volume naming
8
+ ENV['COMPOSE_PROJECT_NAME'] ||= 'r10k'
6
9
 
7
- describe 'r10k container' do
8
- include Pupperware::SpecHelpers
9
- def run_r10k(command)
10
- run_command("docker run --detach \
11
- --volume #{File.join(SPEC_DIRECTORY, 'fixtures')}:/home/puppet/test \
12
- #{@image} #{command} \
13
- --verbose \
14
- --trace \
15
- --puppetfile test/Puppetfile")
16
- end
17
-
18
- before(:all) do
19
- @image = require_test_image
10
+ RSpec.configure do |c|
11
+ c.before(:suite) do
12
+ ENV['R10K_IMAGE'] = require_test_image
13
+ pull_images(['r10k_check','r10k_install'])
14
+ teardown_cluster()
15
+ # no certs to preload, but if the suite adds puppetserver, be explicit
16
+ docker_compose_up(preload_certs: true)
20
17
  end
21
18
 
22
- after(:all) do
23
- FileUtils.rm_rf(File.join(SPEC_DIRECTORY, 'fixtures', 'modules'))
24
- end
25
-
26
- it 'should validate the Puppetfile' do
27
- result = run_r10k('puppetfile check')
28
- container = result[:stdout].chomp
29
- wait_on_container_exit(container)
30
- expect(get_container_exit_code(container)).to eq(0)
31
- emit_log(container)
32
- teardown_container(container)
19
+ c.after(:suite) do
20
+ teardown_cluster()
21
+ FileUtils.rm_rf(File.join(ENV['SPEC_DIRECTORY'], 'fixtures', 'modules'))
33
22
  end
23
+ end
34
24
 
35
- it 'should install the Puppetfile' do
36
- result = run_r10k('puppetfile install')
37
- container = result[:stdout].chomp
38
- wait_on_container_exit(container)
39
- expect(get_container_exit_code(container)).to eq(0)
40
- emit_log(container)
41
- teardown_container(container)
25
+ describe 'r10k container' do
26
+ {
27
+ 'r10k_check': 'validate',
28
+ 'r10k_install': 'install',
29
+ }.each do |container, op|
30
+ it "should #{op} the Puppetfile" do
31
+ container = get_service_container(container)
32
+ wait_on_container_exit(container)
33
+ expect(get_container_exit_code(container)).to eq(0)
34
+ emit_log(container)
35
+ end
42
36
  end
43
37
  end
@@ -30,11 +30,11 @@ CONF
30
30
  puppetfile = <<-EOS
31
31
  mod 'prod_apache',
32
32
  :git => 'git://github.com/puppetlabs/puppetlabs-apache.git',
33
- :branch => 'master'
33
+ :tag => 'v6.0.0'
34
34
 
35
35
  mod 'test_apache',
36
36
  :git => 'git://github.com/puppetlabs/puppetlabs-apache.git',
37
- :branch => 'master'
37
+ :tag => 'v6.0.0'
38
38
  EOS
39
39
 
40
40
  teardown do
@@ -27,7 +27,8 @@ stdlib_notify_message_regex = /The test message is:.*one.*=>.*1.*two.*=>.*bats.*
27
27
  puppet_file = <<-PUPPETFILE
28
28
  mod "puppetlabs/motd"
29
29
  mod 'puppetlabs/stdlib',
30
- :git => 'git://github.com/puppetlabs/puppetlabs-stdlib.git'
30
+ :git => 'git://github.com/puppetlabs/puppetlabs-stdlib.git',
31
+ :tag => 'v7.0.1'
31
32
  PUPPETFILE
32
33
 
33
34
  puppet_file_path = File.join(git_environments_path, 'Puppetfile')
@@ -31,7 +31,8 @@ puppet_file = <<-PUPPETFILE
31
31
  moduledir '#{@module_path}'
32
32
  mod "puppetlabs/motd"
33
33
  mod 'puppetlabs/stdlib',
34
- :git => 'git://github.com/puppetlabs/puppetlabs-stdlib.git'
34
+ :git => 'git://github.com/puppetlabs/puppetlabs-stdlib.git',
35
+ :tag => 'v7.0.1'
35
36
  PUPPETFILE
36
37
 
37
38
  puppet_file_path = File.join(git_environments_path, 'Puppetfile')
@@ -65,7 +65,7 @@ env_structs = {:production => GitEnv.new('/git_repos',
65
65
  '/git_repos_alt/environments_alt.git',
66
66
  '/root/environments_alt',
67
67
  '/root/environments_alt/Puppetfile',
68
- 'mod "puppetlabs/stdlib", :git => "git://github.com/puppetlabs/puppetlabs-stdlib.git"',
68
+ 'mod "puppetlabs/stdlib", :git => "git://github.com/puppetlabs/puppetlabs-stdlib.git", :tag => "v7.0.1"',
69
69
  '/root/environments_alt/manifests/site.pp',
70
70
  create_site_pp(master_certname, stage_env_manifest)
71
71
  ),
@@ -28,7 +28,8 @@ notify_message_regex = /I am in the production environment/
28
28
  puppet_file = <<-PUPPETFILE
29
29
  mod "puppetlabs/motd"
30
30
  mod 'puppetlabs/inifile',
31
- :git => 'git://github.com/puppetlabs/puppetlabs-inifile'
31
+ :git => 'git://github.com/puppetlabs/puppetlabs-inifile',
32
+ :tag => 'v5.0.1'
32
33
  PUPPETFILE
33
34
 
34
35
  puppet_file_path = File.join(git_environments_path, 'Puppetfile')
@@ -10,6 +10,16 @@ module R10K
10
10
 
11
11
  attr_accessor :settings
12
12
 
13
+ # @param opts [Hash] A hash of options defined in #allowed_initialized_opts
14
+ # and managed by the SetOps mixin within the Action::Base class.
15
+ # Corresponds to the CLI flags and options.
16
+ # @param argv [Enumerable] Typically CRI::ArgumentList or Array. A list-like
17
+ # collection of the remaining arguments to the CLI invocation (after
18
+ # removing flags and options).
19
+ # @param settings [Hash] A hash of configuration loaded from the relevant
20
+ # config (r10k.yaml).
21
+ #
22
+ # @note All arguments will be required in the next major version
13
23
  def initialize(opts, argv, settings = {})
14
24
  @opts = opts
15
25
  @argv = argv
@@ -9,17 +9,48 @@ module R10K
9
9
 
10
10
  include R10K::Action::Deploy::DeployHelpers
11
11
 
12
+ # @param opts [Hash] A hash of options defined in #allowed_initialized_opts
13
+ # and managed by the SetOps mixin within the Action::Base class.
14
+ # Corresponds to the CLI flags and options.
15
+ # @param argv [Enumerable] Typically CRI::ArgumentList or Array. A list-like
16
+ # collection of the remaining arguments to the CLI invocation (after
17
+ # removing flags and options).
18
+ # @param settings [Hash] A hash of configuration loaded from the relevant
19
+ # config (r10k.yaml).
20
+ #
21
+ # @note All arguments will be required in the next major version
22
+ def initialize(opts, argv, settings = {})
23
+ super
24
+
25
+ @settings = @settings.merge({
26
+ overrides: {
27
+ environments: {
28
+ preload_environments: @fetch,
29
+ requested_environments: @argv.map { |arg| arg.gsub(/\W/, '_') }
30
+ },
31
+ modules: {},
32
+ output: {
33
+ format: @format,
34
+ trace: @trace,
35
+ detail: @detail
36
+ },
37
+ purging: {}
38
+ }
39
+ })
40
+ end
41
+
12
42
  def call
13
43
  expect_config!
14
44
  deployment = R10K::Deployment.new(@settings)
15
45
 
16
- if @fetch
46
+ if @settings.dig(:overrides, :environments, :preload_environments)
17
47
  deployment.preload!
48
+ deployment.validate!
18
49
  end
19
50
 
20
- output = { :sources => deployment.sources.map { |source| source_info(source, @argv) } }
51
+ output = { :sources => deployment.sources.map { |source| source_info(source, @settings.dig(:overrides, :environments, :requested_environments)) } }
21
52
 
22
- case @format
53
+ case @settings.dig(:overrides, :output, :format)
23
54
  when 'json' then json_format(output)
24
55
  else yaml_format(output)
25
56
  end
@@ -27,7 +58,7 @@ module R10K
27
58
  # exit 0
28
59
  true
29
60
  rescue => e
30
- logger.error R10K::Errors::Formatting.format_exception(e, @trace)
61
+ logger.error R10K::Errors::Formatting.format_exception(e, @settings.dig(:overrides, :output, :trace))
31
62
  false
32
63
  end
33
64
 
@@ -43,7 +74,7 @@ module R10K
43
74
  puts output.to_yaml
44
75
  end
45
76
 
46
- def source_info(source, argv=[])
77
+ def source_info(source, requested_environments = [])
47
78
  source_info = {
48
79
  :name => source.name,
49
80
  :basedir => source.basedir,
@@ -52,28 +83,30 @@ module R10K
52
83
  source_info[:prefix] = source.prefix if source.prefix
53
84
  source_info[:remote] = source.remote if source.respond_to?(:remote)
54
85
 
55
- env_list = source.environments.select { |env| argv.empty? || argv.include?(env.name) }
86
+ select_all_envs = requested_environments.empty?
87
+ env_list = source.environments.select { |env| select_all_envs || requested_environments.include?(env.name) }
56
88
  source_info[:environments] = env_list.map { |env| environment_info(env) }
57
89
 
58
90
  source_info
59
91
  end
60
92
 
61
93
  def environment_info(env)
62
- if !@puppetfile && !@detail
94
+ modules = @settings.dig(:overrides, :environments, :deploy_modules)
95
+ if !modules && !@settings.dig(:overrides, :output, :detail)
63
96
  env.dirname
64
97
  else
65
98
  env_info = env.info.merge({
66
99
  :status => (env.status rescue nil),
67
100
  })
68
101
 
69
- env_info[:modules] = env.modules.map { |mod| module_info(mod) } if @puppetfile
102
+ env_info[:modules] = env.modules.map { |mod| module_info(mod) } if modules
70
103
 
71
104
  env_info
72
105
  end
73
106
  end
74
107
 
75
108
  def module_info(mod)
76
- if @detail
109
+ if @settings.dig(:overrides, :output, :detail)
77
110
  { :name => mod.title, :properties => mod.properties }
78
111
  else
79
112
  mod.title
@@ -81,7 +114,13 @@ module R10K
81
114
  end
82
115
 
83
116
  def allowed_initialize_opts
84
- super.merge(puppetfile: :self, detail: :self, format: :self, fetch: :self)
117
+ super.merge({
118
+ puppetfile: :modules,
119
+ modules: :self,
120
+ detail: :self,
121
+ format: :self,
122
+ fetch: :self
123
+ })
85
124
  end
86
125
  end
87
126
  end
@@ -1,4 +1,5 @@
1
1
  require 'r10k/util/setopts'
2
+ require 'r10k/util/cleaner'
2
3
  require 'r10k/deployment'
3
4
  require 'r10k/logging'
4
5
  require 'r10k/action/visitor'
@@ -13,29 +14,64 @@ module R10K
13
14
 
14
15
  include R10K::Action::Deploy::DeployHelpers
15
16
 
17
+ # Deprecated
16
18
  attr_reader :force
17
19
 
18
- def initialize(opts, argv, settings = nil)
19
- settings ||= {}
20
- @purge_levels = settings.fetch(:deploy, {}).fetch(:purge_levels, [])
21
- @user_purge_whitelist = settings.fetch(:deploy, {}).fetch(:purge_whitelist, [])
22
- @generate_types = settings.fetch(:deploy, {}).fetch(:generate_types, false)
23
-
20
+ attr_reader :settings
21
+
22
+ # @param opts [Hash] A hash of options defined in #allowed_initialized_opts
23
+ # and managed by the SetOps mixin within the Action::Base class.
24
+ # Corresponds to the CLI flags and options.
25
+ # @param argv [Enumerable] Typically CRI::ArgumentList or Array. A list-like
26
+ # collection of the remaining arguments to the CLI invocation (after
27
+ # removing flags and options).
28
+ # @param settings [Hash] A hash of configuration loaded from the relevant
29
+ # config (r10k.yaml).
30
+ #
31
+ # @note All arguments will be required in the next major version
32
+ def initialize(opts, argv, settings = {})
24
33
  super
25
34
 
26
- # @force here is used to make it easier to reason about
27
- @force = !@no_force
28
- @argv = @argv.map { |arg| arg.gsub(/\W/,'_') }
35
+ # instance variables below are set by the super class based on the
36
+ # spec of #allowed_initialize_opts and any command line flags. This
37
+ # gives a preference order of cli flags > config files > defaults.
38
+ @settings = @settings.merge({
39
+ overrides: {
40
+ environments: {
41
+ requested_environments: @argv.map { |arg| arg.gsub(/\W/,'_') },
42
+ default_branch_override: @default_branch_override,
43
+ generate_types: @generate_types || settings.dig(:deploy, :generate_types) || false,
44
+ preload_environments: true
45
+ },
46
+ modules: {
47
+ requested_modules: [],
48
+ deploy_modules: @modules,
49
+ force: !@no_force, # force here is used to make it easier to reason about
50
+ },
51
+ purging: {
52
+ purge_levels: settings.dig(:deploy, :purge_levels) || [],
53
+ purge_allowlist: read_purge_allowlist(settings.dig(:deploy, :purge_whitelist) || [],
54
+ settings.dig(:deploy, :purge_allowlist) || [])
55
+ },
56
+ output: {}
57
+ }
58
+ })
29
59
  end
30
60
 
31
61
  def call
32
62
  @visit_ok = true
33
63
 
34
- expect_config!
35
- deployment = R10K::Deployment.new(@settings)
36
- check_write_lock!(@settings)
64
+ begin
65
+ expect_config!
66
+ deployment = R10K::Deployment.new(@settings)
67
+ check_write_lock!(@settings)
68
+
69
+ deployment.accept(self)
70
+ rescue => e
71
+ @visit_ok = false
72
+ logger.error R10K::Errors::Formatting.format_exception(e, @trace)
73
+ end
37
74
 
38
- deployment.accept(self)
39
75
  @visit_ok
40
76
  end
41
77
 
@@ -43,15 +79,34 @@ module R10K
43
79
 
44
80
  private
45
81
 
82
+ def read_purge_allowlist (whitelist, allowlist)
83
+ whitelist_has_content = !whitelist.empty?
84
+ allowlist_has_content = !allowlist.empty?
85
+ case
86
+ when whitelist_has_content == false && allowlist_has_content == false
87
+ []
88
+ when whitelist_has_content && allowlist_has_content
89
+ raise R10K::Error.new "Values found for both purge_whitelist and purge_allowlist. Setting " <<
90
+ "purge_whitelist is deprecated, please only use purge_allowlist."
91
+ when allowlist_has_content
92
+ allowlist
93
+ else
94
+ logger.warn "Setting purge_whitelist is deprecated; please use purge_allowlist instead."
95
+ whitelist
96
+ end
97
+ end
98
+
46
99
  def visit_deployment(deployment)
47
100
  # Ensure that everything can be preloaded. If we cannot preload all
48
101
  # sources then we can't fully enumerate all environments which
49
102
  # could be dangerous. If this fails then an exception will be raised
50
103
  # and execution will be halted.
51
- deployment.preload!
52
- deployment.validate!
104
+ if @settings.dig(:overrides, :environments, :preload_environments)
105
+ deployment.preload!
106
+ deployment.validate!
107
+ end
53
108
 
54
- undeployable = undeployable_environment_names(deployment.environments, @argv)
109
+ undeployable = undeployable_environment_names(deployment.environments, @settings.dig(:overrides, :environments, :requested_environments))
55
110
  if !undeployable.empty?
56
111
  @visit_ok = false
57
112
  logger.error _("Environment(s) \'%{environments}\' cannot be found in any source and will not be deployed.") % {environments: undeployable.join(", ")}
@@ -59,7 +114,7 @@ module R10K
59
114
 
60
115
  yield
61
116
 
62
- if @purge_levels.include?(:deployment)
117
+ if @settings.dig(:overrides, :purging, :purge_levels).include?(:deployment)
63
118
  logger.debug("Purging unmanaged environments for deployment...")
64
119
  deployment.purge!
65
120
  end
@@ -67,7 +122,8 @@ module R10K
67
122
  if (postcmd = @settings[:postrun])
68
123
  if postcmd.grep('$modifiedenvs').any?
69
124
  envs = deployment.environments.map { |e| e.dirname }
70
- envs.reject! { |e| !@argv.include?(e) } if @argv.any?
125
+ requested_envs = @settings.dig(:overrides, :environments, :requested_environments)
126
+ envs.reject! { |e| !requested_envs.include?(e) } if requested_envs.any?
71
127
  postcmd = postcmd.map { |e| e.gsub('$modifiedenvs', envs.join(' ')) }
72
128
  end
73
129
  subproc = R10K::Util::Subprocess.new(postcmd)
@@ -81,7 +137,8 @@ module R10K
81
137
  end
82
138
 
83
139
  def visit_environment(environment)
84
- if !(@argv.empty? || @argv.any? { |name| environment.dirname == name })
140
+ requested_envs = @settings.dig(:overrides, :environments, :requested_environments)
141
+ if !(requested_envs.empty? || requested_envs.any? { |name| environment.dirname == name })
85
142
  logger.debug1(_("Environment %{env_dir} does not match environment name filter, skipping") % {env_dir: environment.dirname})
86
143
  return
87
144
  end
@@ -95,28 +152,31 @@ module R10K
95
152
  environment.sync
96
153
  logger.info _("Environment %{env_dir} is now at %{env_signature}") % {env_dir: environment.dirname, env_signature: environment.signature}
97
154
 
98
- if status == :absent || @puppetfile
155
+ if status == :absent || @settings.dig(:overrides, :modules, :deploy_modules)
99
156
  if status == :absent
100
157
  logger.debug(_("Environment %{env_dir} is new, updating all modules") % {env_dir: environment.dirname})
101
158
  end
102
159
 
103
160
  previous_ok = @visit_ok
104
161
  @visit_ok = true
105
- yield
162
+
163
+ environment.deploy
164
+
106
165
  @environment_ok = @visit_ok
107
166
  @visit_ok &&= previous_ok
108
167
  end
109
168
 
110
- if @purge_levels.include?(:environment)
169
+
170
+ if @settings.dig(:overrides, :purging, :purge_levels).include?(:environment)
111
171
  if @visit_ok
112
172
  logger.debug("Purging unmanaged content for environment '#{environment.dirname}'...")
113
- environment.purge!(:recurse => true, :whitelist => environment.whitelist(@user_purge_whitelist))
173
+ environment.purge!(:recurse => true, :whitelist => environment.whitelist(@settings.dig(:overrides, :purging, :purge_allowlist)))
114
174
  else
115
175
  logger.debug("Not purging unmanaged content for environment '#{environment.dirname}' due to prior deploy failures.")
116
176
  end
117
177
  end
118
178
 
119
- if @generate_types
179
+ if @settings.dig(:overrides, :environments, :generate_types)
120
180
  if @environment_ok
121
181
  logger.debug("Generating puppet types for environment '#{environment.dirname}'...")
122
182
  environment.generate_types!
@@ -128,34 +188,21 @@ module R10K
128
188
  write_environment_info!(environment, started_at, @visit_ok)
129
189
  end
130
190
 
131
- def visit_puppetfile(puppetfile)
132
- puppetfile.load(@opts[:'default-branch-override'])
133
-
134
- yield
135
-
136
- if @purge_levels.include?(:puppetfile)
137
- logger.debug("Purging unmanaged Puppetfile content for environment '#{puppetfile.environment.dirname}'...")
138
- puppetfile.purge!
139
- end
140
- end
141
-
142
- def visit_module(mod)
143
- logger.info _("Deploying %{origin} content %{path}") % {origin: mod.origin, path: mod.path}
144
- mod.sync(force: @force)
145
- end
146
-
147
191
  def write_environment_info!(environment, started_at, success)
148
- module_deploys = []
149
- begin
150
- environment.modules.each do |mod|
151
- name = mod.name
152
- version = mod.version
153
- sha = mod.repo.head rescue nil
154
- module_deploys.push({:name => name, :version => version, :sha => sha})
192
+ module_deploys =
193
+ begin
194
+ environment.modules.map do |mod|
195
+ props = mod.properties
196
+ {
197
+ name: mod.name,
198
+ version: props[:expected],
199
+ sha: props[:type] == :git ? props[:actual] : nil
200
+ }
201
+ end
202
+ rescue
203
+ logger.debug("Unable to get environment module deploy data for .r10k-deploy.json at #{environment.path}")
204
+ []
155
205
  end
156
- rescue
157
- logger.debug("Unable to get environment module deploy data for .r10k-deploy.json at #{environment.path}")
158
- end
159
206
 
160
207
  # make this file write as atomic as possible in pure ruby
161
208
  final = "#{environment.path}/.r10k-deploy.json"
@@ -183,12 +230,15 @@ module R10K
183
230
  end
184
231
 
185
232
  def allowed_initialize_opts
186
- super.merge(puppetfile: :self,
233
+ super.merge(puppetfile: :modules,
234
+ modules: :self,
187
235
  cachedir: :self,
188
236
  'no-force': :self,
189
237
  'generate-types': :self,
190
238
  'puppet-path': :self,
191
239
  'puppet-conf': :self,
240
+ 'private-key': :self,
241
+ 'oauth-token': :self,
192
242
  'default-branch-override': :self)
193
243
  end
194
244
  end