r10k 3.3.3 → 3.5.2
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 +5 -5
- data/.github/pull_request_template.md +1 -0
- data/.github/workflows/docker.yml +56 -0
- data/.github/workflows/release.yml +36 -0
- data/.travis.yml +23 -8
- data/CHANGELOG.mkd +57 -4
- data/CODEOWNERS +1 -0
- data/Gemfile +1 -1
- data/README.mkd +4 -3
- data/azure-pipelines.yml +2 -1
- data/bin/r10k +1 -1
- data/doc/dynamic-environments/configuration.mkd +160 -2
- data/doc/dynamic-environments/git-environments.mkd +1 -1
- data/doc/dynamic-environments/master-configuration.mkd +28 -58
- data/doc/faq.mkd +6 -1
- data/doc/puppetfile.mkd +2 -0
- data/docker/Makefile +39 -17
- data/docker/r10k/Dockerfile +36 -15
- data/docker/r10k/adduser.sh +13 -0
- data/docker/r10k/docker-entrypoint.d/10-analytics.sh +1 -1
- data/docker/r10k/release.Dockerfile +54 -0
- data/docker/spec/dockerfile_spec.rb +4 -3
- data/docker/spec/fixtures/Puppetfile +1 -1
- data/integration/Rakefile +2 -2
- data/lib/r10k/action/deploy/environment.rb +7 -3
- data/lib/r10k/action/deploy/module.rb +5 -1
- data/lib/r10k/action/runner.rb +4 -4
- data/lib/r10k/cli/deploy.rb +1 -1
- data/lib/r10k/environment.rb +30 -0
- data/lib/r10k/environment/bare.rb +16 -0
- data/lib/r10k/environment/git.rb +6 -5
- data/lib/r10k/environment/svn.rb +2 -0
- data/lib/r10k/environment/with_modules.rb +139 -0
- data/lib/r10k/forge/module_release.rb +2 -2
- data/lib/r10k/logging/terminaloutputter.rb +1 -1
- data/lib/r10k/module/base.rb +5 -0
- data/lib/r10k/module/forge.rb +5 -1
- data/lib/r10k/puppetfile.rb +6 -0
- data/lib/r10k/source.rb +4 -0
- data/lib/r10k/source/exec.rb +51 -0
- data/lib/r10k/source/hash.rb +182 -0
- data/lib/r10k/source/yaml.rb +20 -0
- data/lib/r10k/source/yamldir.rb +32 -0
- data/lib/r10k/util/attempt.rb +1 -1
- data/lib/r10k/version.rb +4 -1
- data/locales/r10k.pot +65 -22
- data/r10k.gemspec +6 -2
- data/spec/unit/action/deploy/environment_spec.rb +1 -0
- data/spec/unit/action/deploy/module_spec.rb +13 -0
- data/spec/unit/action/puppetfile/install_spec.rb +3 -1
- data/spec/unit/action/runner_spec.rb +2 -2
- data/spec/unit/forge/module_release_spec.rb +14 -10
- data/spec/unit/source/exec_spec.rb +81 -0
- data/spec/unit/source/hash_spec.rb +54 -0
- data/spec/unit/source/yaml_spec.rb +42 -0
- metadata +64 -22
- data/MAINTAINERS +0 -18
- data/docker/distelli-manifest.yml +0 -9
- data/integration/scripts/README.mkd +0 -86
- data/integration/scripts/setup_r10k_env_centos5.sh +0 -23
- data/integration/scripts/setup_r10k_env_centos6.sh +0 -23
- data/integration/scripts/setup_r10k_env_rhel7.sh +0 -23
- data/integration/scripts/setup_r10k_env_sles11.sh +0 -23
- data/integration/scripts/setup_r10k_env_sles12.sh +0 -23
- data/integration/scripts/setup_r10k_env_ubuntu1004.sh +0 -23
- data/integration/scripts/setup_r10k_env_ubuntu1204.sh +0 -23
- data/integration/scripts/setup_r10k_env_ubuntu1404.sh +0 -23
@@ -72,7 +72,11 @@ module R10K
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def allowed_initialize_opts
|
75
|
-
super.merge(environment: true,
|
75
|
+
super.merge(environment: true,
|
76
|
+
cachedir: :self,
|
77
|
+
'no-force': :self,
|
78
|
+
'generate-types': :self,
|
79
|
+
'puppet-path': :self)
|
76
80
|
end
|
77
81
|
end
|
78
82
|
end
|
data/lib/r10k/action/runner.rb
CHANGED
@@ -43,10 +43,10 @@ module R10K
|
|
43
43
|
config_settings = settings_from_config(@opts[:config])
|
44
44
|
|
45
45
|
overrides = {}
|
46
|
-
overrides[:cachedir] = @opts[:cachedir]
|
47
|
-
overrides[:deploy] = {} if @opts
|
48
|
-
overrides[:deploy][:puppet_path] = @opts[:'puppet-path']
|
49
|
-
overrides[:deploy][:generate_types] = @opts[:'generate-types']
|
46
|
+
overrides[:cachedir] = @opts[:cachedir] if @opts.key?(:cachedir)
|
47
|
+
overrides[:deploy] = {} if @opts.key?(:'puppet-path') || @opts.key?(:'generate-types')
|
48
|
+
overrides[:deploy][:puppet_path] = @opts[:'puppet-path'] if @opts.key?(:'puppet-path')
|
49
|
+
overrides[:deploy][:generate_types] = @opts[:'generate-types'] if @opts.key?(:'generate-types')
|
50
50
|
|
51
51
|
with_overrides = config_settings.merge(overrides) do |key, oldval, newval|
|
52
52
|
newval = oldval.merge(newval) if oldval.is_a? Hash
|
data/lib/r10k/cli/deploy.rb
CHANGED
@@ -18,7 +18,7 @@ module R10K::CLI
|
|
18
18
|
|
19
19
|
description <<-DESCRIPTION
|
20
20
|
`r10k deploy` implements the Git branch to Puppet environment workflow
|
21
|
-
(https://
|
21
|
+
(https://puppet.com/docs/puppet/latest/environments_about.html).
|
22
22
|
DESCRIPTION
|
23
23
|
|
24
24
|
required nil, :cachedir, 'Specify a cachedir, overriding the value in config'
|
data/lib/r10k/environment.rb
CHANGED
@@ -1,6 +1,36 @@
|
|
1
1
|
module R10K
|
2
2
|
module Environment
|
3
|
+
def self.factory
|
4
|
+
@factory ||= R10K::KeyedFactory.new
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.register(key, klass)
|
8
|
+
factory.register(key, klass)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.retrieve(key)
|
12
|
+
factory.retrieve(key)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.generate(type, name, basedir, dirname, options = {})
|
16
|
+
factory.generate(type, name, basedir, dirname, options)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.from_hash(name, hash)
|
20
|
+
R10K::Util::SymbolizeKeys.symbolize_keys!(hash)
|
21
|
+
|
22
|
+
basedir = hash.delete(:basedir)
|
23
|
+
dirname = hash.delete(:dirname) || name
|
24
|
+
|
25
|
+
type = hash.delete(:type)
|
26
|
+
type = type.is_a?(String) ? type.to_sym : type
|
27
|
+
|
28
|
+
generate(type, name, basedir, dirname, hash)
|
29
|
+
end
|
30
|
+
|
3
31
|
require 'r10k/environment/base'
|
32
|
+
require 'r10k/environment/with_modules'
|
33
|
+
require 'r10k/environment/bare'
|
4
34
|
require 'r10k/environment/git'
|
5
35
|
require 'r10k/environment/svn'
|
6
36
|
end
|
data/lib/r10k/environment/git.rb
CHANGED
@@ -6,10 +6,14 @@ require 'forwardable'
|
|
6
6
|
# This class implements an environment based on a Git branch.
|
7
7
|
#
|
8
8
|
# @since 1.3.0
|
9
|
-
class R10K::Environment::Git < R10K::Environment::
|
9
|
+
class R10K::Environment::Git < R10K::Environment::WithModules
|
10
10
|
|
11
11
|
include R10K::Logging
|
12
12
|
|
13
|
+
R10K::Environment.register(:git, self)
|
14
|
+
# Register git as the default environment type
|
15
|
+
R10K::Environment.register(nil, self)
|
16
|
+
|
13
17
|
# @!attribute [r] remote
|
14
18
|
# @return [String] The URL to the remote git repository
|
15
19
|
attr_reader :remote
|
@@ -66,15 +70,12 @@ class R10K::Environment::Git < R10K::Environment::Base
|
|
66
70
|
|
67
71
|
include R10K::Util::Purgeable
|
68
72
|
|
69
|
-
def managed_directories
|
70
|
-
[@full_path]
|
71
|
-
end
|
72
|
-
|
73
73
|
# Returns an array of the full paths to all the content being managed.
|
74
74
|
# @note This implements a required method for the Purgeable mixin
|
75
75
|
# @return [Array<String>]
|
76
76
|
def desired_contents
|
77
77
|
desired = [File.join(@full_path, '.git')]
|
78
78
|
desired += @repo.tracked_paths.map { |entry| File.join(@full_path, entry) }
|
79
|
+
desired += super
|
79
80
|
end
|
80
81
|
end
|
data/lib/r10k/environment/svn.rb
CHANGED
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'r10k/logging'
|
2
|
+
require 'r10k/util/purgeable'
|
3
|
+
|
4
|
+
# This abstract base class implements an environment that can include module
|
5
|
+
# content
|
6
|
+
#
|
7
|
+
# @since 3.4.0
|
8
|
+
class R10K::Environment::WithModules < R10K::Environment::Base
|
9
|
+
|
10
|
+
include R10K::Logging
|
11
|
+
|
12
|
+
# @!attribute [r] moduledir
|
13
|
+
# @return [String] The directory to install environment-defined modules
|
14
|
+
# into (default: #{basedir}/modules)
|
15
|
+
attr_reader :moduledir
|
16
|
+
|
17
|
+
# Initialize the given environment.
|
18
|
+
#
|
19
|
+
# @param name [String] The unique name describing this environment.
|
20
|
+
# @param basedir [String] The base directory where this environment will be created.
|
21
|
+
# @param dirname [String] The directory name for this environment.
|
22
|
+
# @param options [Hash] An additional set of options for this environment.
|
23
|
+
#
|
24
|
+
# @param options [String] :moduledir The path to install modules to
|
25
|
+
# @param options [Hash] :modules Modules to add to the environment
|
26
|
+
def initialize(name, basedir, dirname, options = {})
|
27
|
+
super(name, basedir, dirname, options)
|
28
|
+
|
29
|
+
@managed_content = {}
|
30
|
+
@modules = []
|
31
|
+
@moduledir = case options[:moduledir]
|
32
|
+
when nil
|
33
|
+
File.join(@basedir, @dirname, 'modules')
|
34
|
+
when File.absolute_path(options[:moduledir])
|
35
|
+
options.delete(:moduledir)
|
36
|
+
else
|
37
|
+
File.join(@basedir, @dirname, options.delete(:moduledir))
|
38
|
+
end
|
39
|
+
|
40
|
+
modhash = options.delete(:modules)
|
41
|
+
load_modules(modhash) unless modhash.nil?
|
42
|
+
end
|
43
|
+
|
44
|
+
# @return [Array<R10K::Module::Base>] All modules associated with this environment.
|
45
|
+
# Modules may originate from either:
|
46
|
+
# - The r10k environment object
|
47
|
+
# - A Puppetfile in the environment's content
|
48
|
+
def modules
|
49
|
+
return @modules if @puppetfile.nil?
|
50
|
+
|
51
|
+
@puppetfile.load unless @puppetfile.loaded?
|
52
|
+
@modules + @puppetfile.modules
|
53
|
+
end
|
54
|
+
|
55
|
+
def accept(visitor)
|
56
|
+
visitor.visit(:environment, self) do
|
57
|
+
@modules.each do |mod|
|
58
|
+
mod.accept(visitor)
|
59
|
+
end
|
60
|
+
|
61
|
+
puppetfile.accept(visitor)
|
62
|
+
validate_no_module_conflicts
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def load_modules(module_hash)
|
67
|
+
module_hash.each do |name, args|
|
68
|
+
add_module(name, args)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# @param [String] name
|
73
|
+
# @param [*Object] args
|
74
|
+
def add_module(name, args)
|
75
|
+
if args.is_a?(Hash)
|
76
|
+
# symbolize keys in the args hash
|
77
|
+
args = args.inject({}) { |memo,(k,v)| memo[k.to_sym] = v; memo }
|
78
|
+
end
|
79
|
+
|
80
|
+
if args.is_a?(Hash) && install_path = args.delete(:install_path)
|
81
|
+
install_path = resolve_install_path(install_path)
|
82
|
+
validate_install_path(install_path, name)
|
83
|
+
else
|
84
|
+
install_path = @moduledir
|
85
|
+
end
|
86
|
+
|
87
|
+
# Keep track of all the content this environment is managing to enable purging.
|
88
|
+
@managed_content[install_path] = Array.new unless @managed_content.has_key?(install_path)
|
89
|
+
|
90
|
+
mod = R10K::Module.new(name, install_path, args, self.name)
|
91
|
+
mod.origin = 'Environment'
|
92
|
+
|
93
|
+
@managed_content[install_path] << mod.name
|
94
|
+
@modules << mod
|
95
|
+
end
|
96
|
+
|
97
|
+
def validate_no_module_conflicts
|
98
|
+
@puppetfile.load unless @puppetfile.loaded?
|
99
|
+
conflicts = (@modules + @puppetfile.modules)
|
100
|
+
.group_by { |mod| mod.name }
|
101
|
+
.select { |_, v| v.size > 1 }
|
102
|
+
.map(&:first)
|
103
|
+
unless conflicts.empty?
|
104
|
+
msg = _('Puppetfile cannot contain module names defined by environment %{name}') % {name: self.name}
|
105
|
+
msg += ' '
|
106
|
+
msg += _("Remove the conflicting definitions of the following modules: %{conflicts}" % { conflicts: conflicts.join(' ') })
|
107
|
+
raise R10K::Error.new(msg)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
include R10K::Util::Purgeable
|
112
|
+
|
113
|
+
# Returns an array of the full paths that can be purged.
|
114
|
+
# @note This implements a required method for the Purgeable mixin
|
115
|
+
# @return [Array<String>]
|
116
|
+
def managed_directories
|
117
|
+
[@full_path]
|
118
|
+
end
|
119
|
+
|
120
|
+
# Returns an array of the full paths of filenames that should exist. Files
|
121
|
+
# inside managed_directories that are not listed in desired_contents will
|
122
|
+
# be purged.
|
123
|
+
# @note This implements a required method for the Purgeable mixin
|
124
|
+
# @return [Array<String>]
|
125
|
+
def desired_contents
|
126
|
+
list = @managed_content.keys
|
127
|
+
list += @managed_content.flat_map do |install_path, modnames|
|
128
|
+
modnames.collect { |name| File.join(install_path, name) }
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def purge_exclusions
|
133
|
+
super + @managed_content.flat_map do |install_path, modnames|
|
134
|
+
modnames.map do |name|
|
135
|
+
File.join(install_path, name, '**', '*')
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
@@ -212,14 +212,14 @@ module R10K
|
|
212
212
|
|
213
213
|
# Remove the temporary directory used for unpacking the module.
|
214
214
|
def cleanup_unpack_path
|
215
|
-
if unpack_path.exist?
|
215
|
+
if unpack_path.parent.exist?
|
216
216
|
unpack_path.parent.rmtree
|
217
217
|
end
|
218
218
|
end
|
219
219
|
|
220
220
|
# Remove the downloaded module release.
|
221
221
|
def cleanup_download_path
|
222
|
-
if download_path.exist?
|
222
|
+
if download_path.parent.exist?
|
223
223
|
download_path.parent.rmtree
|
224
224
|
end
|
225
225
|
end
|
data/lib/r10k/module/base.rb
CHANGED
@@ -31,6 +31,10 @@ class R10K::Module::Base
|
|
31
31
|
# @return [R10K::Environment, nil] The parent environment of the module
|
32
32
|
attr_reader :environment
|
33
33
|
|
34
|
+
# @!attribute [rw] origin
|
35
|
+
# @return [String] Where the module was sourced from. E.g., "Puppetfile"
|
36
|
+
attr_accessor :origin
|
37
|
+
|
34
38
|
# There's been some churn over `author` vs `owner` and `full_name` over
|
35
39
|
# `title`, so in the short run it's easier to support both and deprecate one
|
36
40
|
# later.
|
@@ -47,6 +51,7 @@ class R10K::Module::Base
|
|
47
51
|
@owner, @name = parse_title(@title)
|
48
52
|
@path = Pathname.new(File.join(@dirname, @name))
|
49
53
|
@environment = environment
|
54
|
+
@origin = 'external' # Expect Puppetfile or R10k::Environment to set this to a specific value
|
50
55
|
end
|
51
56
|
|
52
57
|
# @deprecated
|
data/lib/r10k/module/forge.rb
CHANGED
@@ -75,7 +75,11 @@ class R10K::Module::Forge < R10K::Module::Base
|
|
75
75
|
|
76
76
|
# @return [String] The version of the currently installed module
|
77
77
|
def current_version
|
78
|
-
|
78
|
+
if insync?
|
79
|
+
(@metadata ||= @metadata_file.read).nil? ? nil : @metadata.version
|
80
|
+
else
|
81
|
+
nil
|
82
|
+
end
|
79
83
|
end
|
80
84
|
|
81
85
|
alias version current_version
|
data/lib/r10k/puppetfile.rb
CHANGED
@@ -64,6 +64,7 @@ class Puppetfile
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def load(default_branch_override = nil)
|
67
|
+
return true if self.loaded?
|
67
68
|
if File.readable? @puppetfile_path
|
68
69
|
self.load!(default_branch_override)
|
69
70
|
else
|
@@ -83,6 +84,10 @@ class Puppetfile
|
|
83
84
|
raise R10K::Error.wrap(e, _("Failed to evaluate %{path}") % {path: @puppetfile_path})
|
84
85
|
end
|
85
86
|
|
87
|
+
def loaded?
|
88
|
+
@loaded
|
89
|
+
end
|
90
|
+
|
86
91
|
# @param [Array<String>] modules
|
87
92
|
def validate_no_duplicate_names(modules)
|
88
93
|
dupes = modules
|
@@ -129,6 +134,7 @@ class Puppetfile
|
|
129
134
|
@managed_content[install_path] = Array.new unless @managed_content.has_key?(install_path)
|
130
135
|
|
131
136
|
mod = R10K::Module.new(name, install_path, args, @environment)
|
137
|
+
mod.origin = 'Puppetfile'
|
132
138
|
|
133
139
|
@managed_content[install_path] << mod.name
|
134
140
|
@modules << mod
|
data/lib/r10k/source.rb
CHANGED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'r10k/util/subprocess'
|
2
|
+
require 'json'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
class R10K::Source::Exec < R10K::Source::Hash
|
6
|
+
R10K::Source.register(:exec, self)
|
7
|
+
|
8
|
+
def initialize(name, basedir, options = {})
|
9
|
+
unless @command = options[:command]
|
10
|
+
raise ConfigError, _('Environment source %{name} missing required parameter: command') % {name: name}
|
11
|
+
end
|
12
|
+
|
13
|
+
# We haven't set the environments option yet. We will do that by
|
14
|
+
# overloading the #environments method.
|
15
|
+
super(name, basedir, options)
|
16
|
+
end
|
17
|
+
|
18
|
+
def environments_hash
|
19
|
+
@environments_hash ||= set_environments_hash(run_environments_command)
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def run_environments_command
|
25
|
+
subproc = R10K::Util::Subprocess.new([@command])
|
26
|
+
subproc.raise_on_fail = true
|
27
|
+
subproc.logger = self.logger
|
28
|
+
procresult = subproc.execute
|
29
|
+
|
30
|
+
begin
|
31
|
+
environments = JSON.parse(procresult.stdout)
|
32
|
+
rescue JSON::ParserError => json_err
|
33
|
+
begin
|
34
|
+
environments = YAML.safe_load(procresult.stdout)
|
35
|
+
rescue Psych::SyntaxError => yaml_err
|
36
|
+
raise R10K::Error, _("Error parsing command output for exec source %{name}:\n" \
|
37
|
+
"Not valid JSON: %{j_msg}\n" \
|
38
|
+
"Not valid YAML: %{y_msg}\n" \
|
39
|
+
"Stdout:\n%{out}") % {name: name, j_msg: json_err.message, y_msg: yaml_err.message, out: procresult.stdout}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
unless R10K::Source::Hash.valid_environments_hash?(environments)
|
44
|
+
raise R10K::Error, _("Environment source %{name} command %{cmd} did not return valid environment data.\n" \
|
45
|
+
'Returned: %{data}') % {name: name, cmd: @command, data: environments}
|
46
|
+
end
|
47
|
+
|
48
|
+
# Return the resulting environments hash
|
49
|
+
environments
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
# This class implements an environment source based on recieving a hash of
|
2
|
+
# environments
|
3
|
+
#
|
4
|
+
# @since 3.4.0
|
5
|
+
#
|
6
|
+
# DESCRIPTION
|
7
|
+
#
|
8
|
+
# This class implements environments defined by a hash having the following
|
9
|
+
# schema:
|
10
|
+
#
|
11
|
+
# ---
|
12
|
+
# type: object
|
13
|
+
# additionalProperties:
|
14
|
+
# type: object
|
15
|
+
# properties:
|
16
|
+
# type:
|
17
|
+
# type: string
|
18
|
+
# basedir:
|
19
|
+
# type: string
|
20
|
+
# modules:
|
21
|
+
# type: object
|
22
|
+
# additionalProperties:
|
23
|
+
# type: object
|
24
|
+
# moduledir:
|
25
|
+
# type: string
|
26
|
+
# additionalProperties:
|
27
|
+
# type: string
|
28
|
+
#
|
29
|
+
# The top-level keys in the hash are environment names. Keys in individual
|
30
|
+
# environments should be the same as those which would be given to define a
|
31
|
+
# single source in r10k.yaml. Additionally, the "modules" key (and moduledir)
|
32
|
+
# can be used to designate module content for the environment, independent of
|
33
|
+
# the base source parameters.
|
34
|
+
#
|
35
|
+
# Example:
|
36
|
+
#
|
37
|
+
# ---
|
38
|
+
# production:
|
39
|
+
# type: git
|
40
|
+
# remote: 'https://github.com/reidmv/control-repo.git'
|
41
|
+
# ref: '1.0.0'
|
42
|
+
# modules:
|
43
|
+
# geoffwilliams-r_profile: '1.1.0'
|
44
|
+
# geoffwilliams-r_role: '2.0.0'
|
45
|
+
#
|
46
|
+
# development:
|
47
|
+
# type: git
|
48
|
+
# remote: 'https://github.com/reidmv/control-repo.git'
|
49
|
+
# ref: 'master'
|
50
|
+
# modules:
|
51
|
+
# geoffwilliams-r_profile: '1.1.0'
|
52
|
+
# geoffwilliams-r_role: '2.0.0'
|
53
|
+
#
|
54
|
+
# USAGE
|
55
|
+
#
|
56
|
+
# The following is an example implementation class showing how to use the
|
57
|
+
# R10K::Source::Hash abstract base class. Assume an r10k.yaml file such as:
|
58
|
+
#
|
59
|
+
# ---
|
60
|
+
# sources:
|
61
|
+
# proof-of-concept:
|
62
|
+
# type: demo
|
63
|
+
# basedir: '/etc/puppetlabs/code/environments'
|
64
|
+
#
|
65
|
+
# Class implementation:
|
66
|
+
#
|
67
|
+
# class R10K::Source::Demo < R10K::Source::Hash
|
68
|
+
# R10K::Source.register(:demo, self)
|
69
|
+
#
|
70
|
+
# def initialize(name, basedir, options = {})
|
71
|
+
# # This is just a demo class, so we hard-code an example :environments
|
72
|
+
# # hash here. In a real class, we might do something here such as
|
73
|
+
# # perform an API call to retrieve an :environments hash.
|
74
|
+
# options[:environments] = {
|
75
|
+
# 'production' => {
|
76
|
+
# 'remote' => 'https://git.example.com/puppet/control-repo.git',
|
77
|
+
# 'ref' => 'release-141',
|
78
|
+
# 'modules' => {
|
79
|
+
# 'puppetlabs-stdlib' => '6.1.0',
|
80
|
+
# 'puppetlabs-ntp' => '8.1.0',
|
81
|
+
# 'example-myapp1' => {
|
82
|
+
# 'git' => 'https://git.example.com/puppet/example-myapp1.git',
|
83
|
+
# 'ref' => 'v1.3.0',
|
84
|
+
# },
|
85
|
+
# },
|
86
|
+
# },
|
87
|
+
# 'development' => {
|
88
|
+
# 'remote' => 'https://git.example.com/puppet/control-repo.git',
|
89
|
+
# 'ref' => 'master',
|
90
|
+
# 'modules' => {
|
91
|
+
# 'puppetlabs-stdlib' => '6.1.0',
|
92
|
+
# 'puppetlabs-ntp' => '8.1.0',
|
93
|
+
# 'example-myapp1' => {
|
94
|
+
# 'git' => 'https://git.example.com/puppet/example-myapp1.git',
|
95
|
+
# 'ref' => 'v1.3.1',
|
96
|
+
# },
|
97
|
+
# },
|
98
|
+
# },
|
99
|
+
# }
|
100
|
+
#
|
101
|
+
# # All we need to do is supply options with the :environments hash.
|
102
|
+
# # The R10K::Source::Hash parent class takes care of the rest.
|
103
|
+
# super(name, basedir, options)
|
104
|
+
# end
|
105
|
+
# end
|
106
|
+
#
|
107
|
+
# Example output:
|
108
|
+
#
|
109
|
+
# [root@master:~] % r10k deploy environment production -pv
|
110
|
+
# INFO -> Using Puppetfile '/etc/puppetlabs/code/environments/production/Puppetfile'
|
111
|
+
# INFO -> Using Puppetfile '/etc/puppetlabs/code/environments/development/Puppetfile'
|
112
|
+
# INFO -> Deploying environment /etc/puppetlabs/code/environments/production
|
113
|
+
# INFO -> Environment production is now at 74ea2e05bba796918e4ff1803018c526337ef5f3
|
114
|
+
# INFO -> Deploying Environment content /etc/puppetlabs/code/environments/production/modules/stdlib
|
115
|
+
# INFO -> Deploying Environment content /etc/puppetlabs/code/environments/production/modules/ntp
|
116
|
+
# INFO -> Deploying Environment content /etc/puppetlabs/code/environments/production/modules/myapp1
|
117
|
+
# INFO -> Deploying Puppetfile content /etc/puppetlabs/code/environments/production/modules/ruby_task_helper
|
118
|
+
# INFO -> Deploying Puppetfile content /etc/puppetlabs/code/environments/production/modules/bolt_shim
|
119
|
+
# INFO -> Deploying Puppetfile content /etc/puppetlabs/code/environments/production/modules/apply_helpers
|
120
|
+
#
|
121
|
+
class R10K::Source::Hash < R10K::Source::Base
|
122
|
+
|
123
|
+
include R10K::Logging
|
124
|
+
|
125
|
+
# @param hash [Hash] A hash to validate.
|
126
|
+
# @return [Boolean] False if the hash is obviously invalid. A true return
|
127
|
+
# means _maybe_ it's valid.
|
128
|
+
def self.valid_environments_hash?(hash)
|
129
|
+
# TODO: more robust schema valiation
|
130
|
+
hash.is_a?(Hash)
|
131
|
+
end
|
132
|
+
|
133
|
+
# @param name [String] The identifier for this source.
|
134
|
+
# @param basedir [String] The base directory where the generated environments will be created.
|
135
|
+
# @param options [Hash] An additional set of options for this source. The
|
136
|
+
# semantics of this hash may depend on the source implementation.
|
137
|
+
#
|
138
|
+
# @option options [Boolean, String] :prefix If a String this becomes the prefix.
|
139
|
+
# If true, will use the source name as the prefix. All sources should respect this option.
|
140
|
+
# Defaults to false for no environment prefix.
|
141
|
+
# @option options [Hash] :environments The hash definition of environments
|
142
|
+
def initialize(name, basedir, options = {})
|
143
|
+
super(name, basedir, options)
|
144
|
+
end
|
145
|
+
|
146
|
+
# Set the environment hash for the source. The environment hash is what the
|
147
|
+
# source uses to generate enviroments.
|
148
|
+
# @param hash [Hash] The hash to sanitize and use as the source's environments.
|
149
|
+
# Should be formatted for use with R10K::Environment#from_hash.
|
150
|
+
def set_environments_hash(hash)
|
151
|
+
@environments_hash = hash.reduce({}) do |memo,(name,opts)|
|
152
|
+
R10K::Util::SymbolizeKeys.symbolize_keys!(opts)
|
153
|
+
memo.merge({
|
154
|
+
name => opts.merge({
|
155
|
+
:basedir => @basedir,
|
156
|
+
:dirname => R10K::Environment::Name.new(name, {prefix: @prefix, source: @name}).dirname
|
157
|
+
})
|
158
|
+
})
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# Return the sanitized environments hash for this source. The environments
|
163
|
+
# hash should contain objects formatted for use with R10K::Environment#from_hash.
|
164
|
+
# If the hash does not exist it will be built based on @options.
|
165
|
+
def environments_hash
|
166
|
+
@environments_hash ||= set_environments_hash(@options.fetch(:environments, {}))
|
167
|
+
end
|
168
|
+
|
169
|
+
def environments
|
170
|
+
@environments ||= environments_hash.map do |name, hash|
|
171
|
+
R10K::Environment.from_hash(name, hash)
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
# List all environments that should exist in the basedir for this source
|
176
|
+
# @note This is required by {R10K::Util::Basedir}
|
177
|
+
# @return [Array<String>]
|
178
|
+
def desired_contents
|
179
|
+
environments.map {|env| env.dirname }
|
180
|
+
end
|
181
|
+
|
182
|
+
end
|