r10k 3.7.0 → 3.9.3

Sign up to get free protection for your applications and to get access to all the features.
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