r10k 1.0.0 → 1.1.0rc1
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.
- data/lib/r10k/cli/puppetfile.rb +27 -1
- data/lib/r10k/deployment.rb +4 -2
- data/lib/r10k/deployment/config.rb +1 -1
- data/lib/r10k/deployment/environment.rb +5 -3
- data/lib/r10k/deployment/source.rb +22 -5
- data/lib/r10k/git/cache.rb +16 -41
- data/lib/r10k/git/working_dir.rb +2 -1
- data/lib/r10k/module.rb +5 -12
- data/lib/r10k/module/base.rb +10 -0
- data/lib/r10k/module/forge.rb +11 -9
- data/lib/r10k/module/git.rb +3 -7
- data/lib/r10k/puppetfile.rb +9 -0
- data/lib/r10k/registry.rb +32 -0
- data/lib/r10k/settings.rb +6 -0
- data/lib/r10k/settings/container.rb +87 -0
- data/lib/r10k/settings/mixin.rb +45 -0
- data/lib/r10k/version.rb +1 -1
- data/spec/fixtures/module/forge/eight_hundred/Modulefile +8 -0
- data/spec/fixtures/module/forge/eight_hundred/metadata.json +19 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/unit/deployment/environment_spec.rb +5 -0
- data/spec/unit/deployment/source_spec.rb +24 -0
- data/spec/unit/git/working_dir_spec.rb +0 -4
- data/spec/unit/module/forge_spec.rb +10 -11
- data/spec/unit/registry_spec.rb +78 -0
- data/spec/unit/settings/container_spec.rb +68 -0
- metadata +28 -33
- data/lib/r10k/util/interp.rb +0 -25
- data/spec/unit/git/cache_spec.rb +0 -37
data/lib/r10k/cli/puppetfile.rb
CHANGED
@@ -49,7 +49,33 @@ Puppetfile (http://bombasticmonkey.com/librarian-puppet/).
|
|
49
49
|
end
|
50
50
|
end
|
51
51
|
self.command.add_command(Install.command)
|
52
|
-
|
52
|
+
module Check
|
53
|
+
def self.command
|
54
|
+
@cmd ||= Cri::Command.define do
|
55
|
+
name 'check'
|
56
|
+
usage 'check'
|
57
|
+
summary 'Try and load the Puppetfile to verify the syntax is correct.'
|
58
|
+
run do |opts,args,cmd|
|
59
|
+
puppetfile_root = Dir.getwd
|
60
|
+
puppetfile_path = ENV['PUPPETFILE_DIR']
|
61
|
+
puppetfile = ENV['PUPPETFILE']
|
62
|
+
|
63
|
+
puppetfile = R10K::Puppetfile.new(puppetfile_root, puppetfile_path, puppetfile)
|
64
|
+
begin
|
65
|
+
puppetfile.load
|
66
|
+
rescue LoadError => ex
|
67
|
+
$stderr.puts "ERROR: Puppetfile bad syntax"
|
68
|
+
ex.backtrace.each do |line|
|
69
|
+
puts line
|
70
|
+
end
|
71
|
+
exit 1
|
72
|
+
end
|
73
|
+
exit 0
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
self.command.add_command(Check.command)
|
53
79
|
module Purge
|
54
80
|
def self.command
|
55
81
|
@cmd ||= Cri::Command.define do
|
data/lib/r10k/deployment.rb
CHANGED
@@ -59,8 +59,10 @@ class Deployment
|
|
59
59
|
private
|
60
60
|
|
61
61
|
def load_sources
|
62
|
-
|
63
|
-
|
62
|
+
sources = @config.setting(:sources)
|
63
|
+
prefix = sources.length > 1
|
64
|
+
@_sources = sources.map do |(name, hash)|
|
65
|
+
R10K::Deployment::Source.vivify(name, hash, prefix)
|
64
66
|
end
|
65
67
|
end
|
66
68
|
|
@@ -27,11 +27,13 @@ class Environment
|
|
27
27
|
# @param [String] remote
|
28
28
|
# @param [String] basedir
|
29
29
|
# @param [String] dirname The directory to clone the root into, defaults to ref
|
30
|
-
|
30
|
+
# @param [String] source_name An additional string which may be used with ref to build dirname
|
31
|
+
def initialize(ref, remote, basedir, dirname = nil, source_name = "")
|
31
32
|
@ref = ref
|
32
33
|
@remote = remote
|
33
34
|
@basedir = basedir
|
34
|
-
|
35
|
+
alternate_name = source_name.empty? ? ref : source_name + "_" + ref
|
36
|
+
@dirname = sanitize_dirname(dirname || alternate_name)
|
35
37
|
|
36
38
|
@working_dir = R10K::Git::WorkingDir.new(@ref, @remote, @basedir, @dirname)
|
37
39
|
|
@@ -67,7 +69,7 @@ class Environment
|
|
67
69
|
|
68
70
|
# Strip out non-word characters in an environment directory name
|
69
71
|
#
|
70
|
-
# Puppet can only use word
|
72
|
+
# Puppet can only use word characters (letter, digit, underscore) in
|
71
73
|
# environment names; this cleans up environment names to avoid traversals
|
72
74
|
# and similar issues.
|
73
75
|
#
|
@@ -27,20 +27,23 @@ class Source
|
|
27
27
|
# @return [Array<R10K::Deployment::Environment>] All environments for this source
|
28
28
|
attr_reader :environments
|
29
29
|
|
30
|
-
def self.vivify(name, attrs)
|
30
|
+
def self.vivify(name, attrs, prefix = false)
|
31
31
|
remote = (attrs.delete(:remote) || attrs.delete('remote'))
|
32
32
|
basedir = (attrs.delete(:basedir) || attrs.delete('basedir'))
|
33
|
+
prefix_config = (attrs.delete(:prefix) || attrs.delete('prefix'))
|
34
|
+
prefix_outcome = prefix_config.nil? ? prefix : prefix_config
|
33
35
|
|
34
36
|
raise ArgumentError, "Unrecognized attributes for #{self.name}: #{attrs.inspect}" unless attrs.empty?
|
35
|
-
new(name, remote, basedir)
|
37
|
+
new(name, remote, basedir, prefix_outcome)
|
36
38
|
end
|
37
39
|
|
38
|
-
def initialize(name, remote, basedir)
|
40
|
+
def initialize(name, remote, basedir, prefix = nil)
|
39
41
|
@name = name
|
40
42
|
@remote = remote
|
41
43
|
@basedir = basedir
|
44
|
+
@prefix = prefix.nil? ? false : prefix
|
42
45
|
|
43
|
-
@cache = R10K::Git::Cache.
|
46
|
+
@cache = R10K::Git::Cache.generate(@remote)
|
44
47
|
|
45
48
|
load_environments
|
46
49
|
end
|
@@ -56,6 +59,16 @@ class Source
|
|
56
59
|
@basedir
|
57
60
|
end
|
58
61
|
|
62
|
+
def current_contents
|
63
|
+
dir = self.managed_directory
|
64
|
+
glob_part = @prefix ? @name.to_s() + '_*' : '*'
|
65
|
+
glob_exp = File.join(dir, glob_part)
|
66
|
+
|
67
|
+
Dir.glob(glob_exp).map do |fname|
|
68
|
+
File.basename fname
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
59
72
|
# List all environments that should exist in the basedir for this source
|
60
73
|
# @note This implements a required method for the Purgeable mixin
|
61
74
|
# @return [Array<String>]
|
@@ -68,7 +81,11 @@ class Source
|
|
68
81
|
def load_environments
|
69
82
|
if @cache.cached?
|
70
83
|
@environments = @cache.branches.map do |branch|
|
71
|
-
|
84
|
+
if @prefix
|
85
|
+
R10K::Deployment::Environment.new(branch, @remote, @basedir, nil, @name.to_s())
|
86
|
+
else
|
87
|
+
R10K::Deployment::Environment.new(branch, @remote, @basedir)
|
88
|
+
end
|
72
89
|
end
|
73
90
|
else
|
74
91
|
@environments = []
|
data/lib/r10k/git/cache.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'r10k/logging'
|
2
2
|
require 'r10k/git/repository'
|
3
3
|
|
4
|
+
require 'r10k/settings'
|
5
|
+
require 'r10k/registry'
|
6
|
+
|
4
7
|
module R10K
|
5
8
|
module Git
|
6
9
|
class Cache < R10K::Git::Repository
|
@@ -8,36 +11,16 @@ class Cache < R10K::Git::Repository
|
|
8
11
|
#
|
9
12
|
# @see man git-clone(1)
|
10
13
|
|
11
|
-
|
12
|
-
|
13
|
-
# @!attribute [r] cache_root
|
14
|
-
# @return [String] The directory to use as the cache.
|
15
|
-
attr_writer :cache_root
|
14
|
+
include R10K::Settings::Mixin
|
16
15
|
|
17
|
-
|
18
|
-
@cache_root
|
19
|
-
end
|
16
|
+
def_setting_attr :cache_root, File.expand_path('~/.r10k/git')
|
20
17
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
# cache refreshes.
|
25
|
-
#
|
26
|
-
# @param [String] remote A git remote URL
|
27
|
-
# @return [R10K::Synchro::Git]
|
28
|
-
def new(remote)
|
29
|
-
@repos ||= {}
|
30
|
-
unless @repos[remote]
|
31
|
-
obj = self.allocate
|
32
|
-
obj.send(:initialize, remote)
|
33
|
-
@repos[remote] = obj
|
34
|
-
end
|
35
|
-
@repos[remote]
|
36
|
-
end
|
18
|
+
def self.registry
|
19
|
+
@registry ||= R10K::Registry.new(self)
|
20
|
+
end
|
37
21
|
|
38
|
-
|
39
|
-
|
40
|
-
end
|
22
|
+
def self.generate(remote)
|
23
|
+
registry.generate(remote)
|
41
24
|
end
|
42
25
|
|
43
26
|
include R10K::Logging
|
@@ -46,12 +29,6 @@ class Cache < R10K::Git::Repository
|
|
46
29
|
# @return [String] The git repository remote
|
47
30
|
attr_reader :remote
|
48
31
|
|
49
|
-
# @!attribute [r] cache_root
|
50
|
-
# Where to keep the git object cache. Defaults to ~/.r10k/git if a class
|
51
|
-
# level value is not set.
|
52
|
-
# @return [String] The directory to use as the cache
|
53
|
-
attr_reader :cache_root
|
54
|
-
|
55
32
|
# @!attribute [r] path
|
56
33
|
# @return [String] The path to the git cache repository
|
57
34
|
attr_reader :path
|
@@ -61,9 +38,7 @@ class Cache < R10K::Git::Repository
|
|
61
38
|
def initialize(remote)
|
62
39
|
@remote = remote
|
63
40
|
|
64
|
-
@
|
65
|
-
|
66
|
-
@path = File.join(@cache_root, sanitized_dirname)
|
41
|
+
@path = File.join(settings[:cache_root], sanitized_dirname)
|
67
42
|
end
|
68
43
|
|
69
44
|
def sync
|
@@ -85,7 +60,11 @@ class Cache < R10K::Git::Repository
|
|
85
60
|
git "fetch --prune", :git_dir => @path
|
86
61
|
else
|
87
62
|
logger.debug "Creating new git cache for #{@remote.inspect}"
|
88
|
-
|
63
|
+
|
64
|
+
unless File.exist? settings[:cache_root]
|
65
|
+
FileUtils.mkdir_p settings[:cache_root]
|
66
|
+
end
|
67
|
+
|
89
68
|
git "clone --mirror #{@remote} #{@path}"
|
90
69
|
end
|
91
70
|
end
|
@@ -119,10 +98,6 @@ class Cache < R10K::Git::Repository
|
|
119
98
|
@remote.gsub(/[^@\w\.-]/, '-')
|
120
99
|
end
|
121
100
|
|
122
|
-
def default_cache_root
|
123
|
-
File.expand_path('~/.r10k/git')
|
124
|
-
end
|
125
|
-
|
126
101
|
def git_dir
|
127
102
|
@path
|
128
103
|
end
|
data/lib/r10k/git/working_dir.rb
CHANGED
@@ -37,7 +37,7 @@ class WorkingDir < R10K::Git::Repository
|
|
37
37
|
|
38
38
|
@full_path = File.join(@basedir, @dirname)
|
39
39
|
|
40
|
-
@cache = R10K::Git::Cache.
|
40
|
+
@cache = R10K::Git::Cache.generate(@remote)
|
41
41
|
end
|
42
42
|
|
43
43
|
# Synchronize the local git repository.
|
@@ -78,6 +78,7 @@ class WorkingDir < R10K::Git::Repository
|
|
78
78
|
# that doing a normal `git pull` on a directory will work.
|
79
79
|
git "clone --reference #{@cache.path} #{@remote} #{@full_path}"
|
80
80
|
git "remote add cache #{@cache.path}", :path => @full_path
|
81
|
+
git "checkout #{@ref}", :path => @full_path
|
81
82
|
end
|
82
83
|
|
83
84
|
def fetch
|
data/lib/r10k/module.rb
CHANGED
@@ -2,9 +2,8 @@ require 'r10k'
|
|
2
2
|
|
3
3
|
module R10K::Module
|
4
4
|
|
5
|
-
# Register an
|
6
|
-
def self.
|
7
|
-
klass.extend self
|
5
|
+
# Register an module implementation for later generation
|
6
|
+
def self.register(klass)
|
8
7
|
@klasses ||= []
|
9
8
|
@klasses << klass
|
10
9
|
end
|
@@ -30,13 +29,7 @@ module R10K::Module
|
|
30
29
|
end
|
31
30
|
end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
def full_path
|
37
|
-
File.join(@basedir, @name)
|
38
|
-
end
|
32
|
+
require 'r10k/module/base'
|
33
|
+
require 'r10k/module/git'
|
34
|
+
require 'r10k/module/forge'
|
39
35
|
end
|
40
|
-
|
41
|
-
require 'r10k/module/git'
|
42
|
-
require 'r10k/module/forge'
|
data/lib/r10k/module/forge.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'r10k'
|
2
1
|
require 'r10k/module'
|
3
2
|
require 'r10k/errors'
|
4
3
|
require 'r10k/logging'
|
@@ -8,11 +7,9 @@ require 'systemu'
|
|
8
7
|
require 'semver'
|
9
8
|
require 'json'
|
10
9
|
|
11
|
-
|
12
|
-
module Module
|
13
|
-
class Forge
|
10
|
+
class R10K::Module::Forge < R10K::Module::Base
|
14
11
|
|
15
|
-
|
12
|
+
R10K::Module.register(self)
|
16
13
|
|
17
14
|
def self.implement?(name, args)
|
18
15
|
!!(name.match %r[\w+/\w+])
|
@@ -40,9 +37,16 @@ class Forge
|
|
40
37
|
#logger.debug1 "Module #{@full_name} already matches version #{@version}"
|
41
38
|
elsif File.exist? metadata_path
|
42
39
|
#logger.debug "Module #{@full_name} is installed but doesn't match version #{@version}, upgrading"
|
40
|
+
|
41
|
+
# A Pulp based puppetforge http://www.pulpproject.org/ wont support
|
42
|
+
# `puppet module install abc/xyz --version=v1.5.9` but puppetlabs forge
|
43
|
+
# will support `puppet module install abc/xyz --version=1.5.9`
|
44
|
+
#
|
45
|
+
# Removing v from the semver for constructing the command ensures
|
46
|
+
# compatibility across both
|
43
47
|
cmd = []
|
44
48
|
cmd << 'upgrade'
|
45
|
-
cmd << "--version=#{@version}" if @version
|
49
|
+
cmd << "--version=#{@version.to_s.sub(/^v/,'')}" if @version
|
46
50
|
cmd << "--ignore-dependencies"
|
47
51
|
cmd << @full_name
|
48
52
|
pmt cmd
|
@@ -51,7 +55,7 @@ class Forge
|
|
51
55
|
#logger.debug "Module #{@full_name} is not installed"
|
52
56
|
cmd = []
|
53
57
|
cmd << 'install'
|
54
|
-
cmd << "--version=#{@version}" if @version
|
58
|
+
cmd << "--version=#{@version.to_s.sub(/^v/,'')}" if @version
|
55
59
|
cmd << "--ignore-dependencies"
|
56
60
|
cmd << @full_name
|
57
61
|
pmt cmd
|
@@ -101,5 +105,3 @@ class Forge
|
|
101
105
|
stdout
|
102
106
|
end
|
103
107
|
end
|
104
|
-
end
|
105
|
-
end
|
data/lib/r10k/module/git.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
|
-
require 'r10k'
|
2
1
|
require 'r10k/module'
|
3
2
|
require 'r10k/git/working_dir'
|
4
3
|
require 'forwardable'
|
5
4
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
include R10K::Module
|
5
|
+
class R10K::Module::Git < R10K::Module::Base
|
6
|
+
|
7
|
+
R10K::Module.register(self)
|
10
8
|
|
11
9
|
def self.implement?(name, args)
|
12
10
|
args.is_a? Hash and args.has_key?(:git)
|
@@ -30,5 +28,3 @@ class Git
|
|
30
28
|
@ref
|
31
29
|
end
|
32
30
|
end
|
33
|
-
end
|
34
|
-
end
|
data/lib/r10k/puppetfile.rb
CHANGED
@@ -57,6 +57,11 @@ class Puppetfile
|
|
57
57
|
@forge = forge
|
58
58
|
end
|
59
59
|
|
60
|
+
# @param [String] moduledir
|
61
|
+
def set_moduledir(moduledir)
|
62
|
+
@moduledir = moduledir
|
63
|
+
end
|
64
|
+
|
60
65
|
# @param [String] name
|
61
66
|
# @param [*Object] args
|
62
67
|
def add_module(name, args)
|
@@ -99,6 +104,10 @@ class Puppetfile
|
|
99
104
|
@librarian.set_forge(location)
|
100
105
|
end
|
101
106
|
|
107
|
+
def moduledir(location)
|
108
|
+
@librarian.set_moduledir(location)
|
109
|
+
end
|
110
|
+
|
102
111
|
def method_missing(method, *args)
|
103
112
|
raise NoMethodError, "unrecognized declaration '#{method}'"
|
104
113
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module R10K
|
2
|
+
|
3
|
+
# R10K::Registry implements a generic object memoization container. It caches
|
4
|
+
# new objects and returns cached objects based on the instantiation arguments.
|
5
|
+
class Registry
|
6
|
+
|
7
|
+
# Initialize a new registry with a given class
|
8
|
+
#
|
9
|
+
# @param klass [Class] The class to memoize
|
10
|
+
# @param method [Symbol] The method name to use when creating objects.
|
11
|
+
# Defaults to :new.
|
12
|
+
def initialize(klass, method = :new)
|
13
|
+
@klass = klass
|
14
|
+
@method = method
|
15
|
+
@instances = {}
|
16
|
+
end
|
17
|
+
|
18
|
+
# Create a new object, or return a memoized object.
|
19
|
+
#
|
20
|
+
# @param args [*Object] The arguments to pass to the initialize method
|
21
|
+
#
|
22
|
+
# @return [Object] A memoized instance of the registered class
|
23
|
+
def generate(*args)
|
24
|
+
@instances[args] ||= @klass.send(@method, *args)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Clear all memoized objects
|
28
|
+
def clear!
|
29
|
+
@instances = {}
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# Defines a collection for application settings
|
2
|
+
#
|
3
|
+
# This implements a hierarchical interface to application settings. Containers
|
4
|
+
# can define an optional parent container that will be used for default options
|
5
|
+
# if those options aren't set on the given container.
|
6
|
+
class R10K::Settings::Container
|
7
|
+
|
8
|
+
# @!attribute [r] valid_keys
|
9
|
+
# @return [Set<Symbol>] All valid keys defined on the container or parent container.
|
10
|
+
attr_accessor :valid_keys
|
11
|
+
|
12
|
+
# @param parent [R10K::Settings::Container] An optional parent container
|
13
|
+
def initialize(parent = nil)
|
14
|
+
@parent = parent
|
15
|
+
|
16
|
+
@valid_keys = Set.new
|
17
|
+
@settings = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
# Look up a value in the container. The lookup checks the current container,
|
21
|
+
# and then falls back to the parent container if it's given.
|
22
|
+
#
|
23
|
+
# @param key [Symbol] The lookup key
|
24
|
+
#
|
25
|
+
# @return [Object, nil] The retrieved value if present.
|
26
|
+
#
|
27
|
+
# @raise [R10K::Settings::Container::InvalidKey] If the looked up key isn't
|
28
|
+
# a valid key.
|
29
|
+
def [](key)
|
30
|
+
validate_key! key
|
31
|
+
|
32
|
+
if @settings[key]
|
33
|
+
@settings[key]
|
34
|
+
elsif @parent and (pkey = @parent[key])
|
35
|
+
@settings[key] = pkey
|
36
|
+
pkey
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Set a value on the container
|
41
|
+
#
|
42
|
+
# @param key [Symbol] The lookup key
|
43
|
+
# @param value [Object] The value to store in the container
|
44
|
+
#
|
45
|
+
# @raise [R10K::Settings::Container::InvalidKey] If the looked up key isn't
|
46
|
+
# a valid key.
|
47
|
+
def []=(key, value)
|
48
|
+
validate_key! key
|
49
|
+
|
50
|
+
@settings[key] = value
|
51
|
+
end
|
52
|
+
|
53
|
+
# Define a valid container key
|
54
|
+
#
|
55
|
+
# @note This should only be used by {#R10K::Settings::ClassSettings}
|
56
|
+
#
|
57
|
+
# @param key [Symbol]
|
58
|
+
# @return [void]
|
59
|
+
def add_valid_key(key)
|
60
|
+
@valid_keys.add(key)
|
61
|
+
end
|
62
|
+
|
63
|
+
# Determine if a key is a valid setting.
|
64
|
+
#
|
65
|
+
# @param key [Symbol]
|
66
|
+
#
|
67
|
+
# @return [true, false]
|
68
|
+
def valid_key?(key)
|
69
|
+
if @valid_keys.include?(key)
|
70
|
+
true
|
71
|
+
elsif @parent and @parent.valid_key?(key)
|
72
|
+
@valid_keys.add(key)
|
73
|
+
true
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def validate_key!(key)
|
80
|
+
unless valid_key?(key)
|
81
|
+
raise InvalidKey, "Key #{key} is not a valid key"
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# @api private
|
86
|
+
class InvalidKey < StandardError; end
|
87
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module R10K::Settings::Mixin
|
2
|
+
|
3
|
+
def self.included(klass)
|
4
|
+
klass.send(:include, InstanceMethods)
|
5
|
+
klass.send(:extend, ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module InstanceMethods
|
9
|
+
|
10
|
+
# @return [R10K::Settings::Container] A settings container for the given instance.
|
11
|
+
def settings
|
12
|
+
@settings ||= R10K::Settings::Container.new(self.class.settings)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module ClassMethods
|
17
|
+
|
18
|
+
# Define a setting and optional default on the extending class.
|
19
|
+
#
|
20
|
+
# @param key [Symbol]
|
21
|
+
# @param default [Object]
|
22
|
+
#
|
23
|
+
# @return [void]
|
24
|
+
def def_setting_attr(key, default = nil)
|
25
|
+
defaults.add_valid_key(key)
|
26
|
+
defaults[key] = default if default
|
27
|
+
end
|
28
|
+
|
29
|
+
# A singleton settings container for storing immutable default configuration
|
30
|
+
# on the extending class.
|
31
|
+
#
|
32
|
+
# @return [R10K::Settings::Container]
|
33
|
+
def defaults
|
34
|
+
@defaults ||= R10K::Settings::Container.new
|
35
|
+
end
|
36
|
+
|
37
|
+
# A singleton settings container for storing manual setting configurations
|
38
|
+
# on the extending class.
|
39
|
+
#
|
40
|
+
# @return [R10K::Settings::Container]
|
41
|
+
def settings
|
42
|
+
@settings ||= R10K::Settings::Container.new(defaults)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/r10k/version.rb
CHANGED
@@ -0,0 +1,8 @@
|
|
1
|
+
name 'branan-eight_hundred'
|
2
|
+
version '8.0.0'
|
3
|
+
source 'https://github.com/branan/puppet-module-eight_hundred'
|
4
|
+
author 'Branan Purvine-Riley'
|
5
|
+
license 'Apache License 2.0'
|
6
|
+
summary '800 modules! WOOOOOOO!'
|
7
|
+
description '800 modules! WOOOOOOOOOOOOOOOOOO!'
|
8
|
+
project_page 'https://github.com/branan/puppet-module-eight_hundred'
|
@@ -0,0 +1,19 @@
|
|
1
|
+
{
|
2
|
+
"checksums": {
|
3
|
+
"Modulefile": "1e780d794bcd6629dc3006129fc02edf"
|
4
|
+
},
|
5
|
+
"license": "Apache License 2.0",
|
6
|
+
"types": [
|
7
|
+
|
8
|
+
],
|
9
|
+
"version": "8.0.0",
|
10
|
+
"dependencies": [
|
11
|
+
|
12
|
+
],
|
13
|
+
"summary": "800 modules! WOOOOOOO!",
|
14
|
+
"source": "https://github.com/branan/puppet-module-eight_hundred",
|
15
|
+
"description": "800 modules! WOOOOOOOOOOOOOOOOOO!",
|
16
|
+
"author": "Branan Purvine-Riley",
|
17
|
+
"name": "branan-eight_hundred",
|
18
|
+
"project_page": "https://github.com/branan/puppet-module-eight_hundred"
|
19
|
+
}
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require 'r10k'
|
2
|
+
|
3
|
+
PROJECT_ROOT = File.expand_path('..', File.dirname(__FILE__))
|
4
|
+
|
5
|
+
RSpec.configure do |config|
|
6
|
+
# Filter out integration tests by default
|
7
|
+
#
|
8
|
+
# To run integration tests, run `rspec --tag integration`
|
9
|
+
config.filter_run_excluding :integration => true
|
10
|
+
end
|
@@ -11,6 +11,11 @@ describe R10K::Deployment::Environment do
|
|
11
11
|
subject.dirname.should == 'master'
|
12
12
|
end
|
13
13
|
|
14
|
+
it 'uses the ref and a provided source name in the default dirname' do
|
15
|
+
subject = described_class.new(ref, remote, '/tmp', nil, "the")
|
16
|
+
subject.dirname.should == 'the_master'
|
17
|
+
end
|
18
|
+
|
14
19
|
it 'allows a specific dirname to be set' do
|
15
20
|
subject = described_class.new(ref, remote, '/tmp', 'sourcename_master')
|
16
21
|
subject.dirname.should == 'sourcename_master'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'r10k/deployment/source'
|
3
|
+
|
4
|
+
describe R10K::Deployment::Source do
|
5
|
+
let(:name) { 'do_not_name_a_branch_this' }
|
6
|
+
let(:remote) { 'git://github.com/adrienthebo/r10k-fixture-repo' }
|
7
|
+
let(:basedir) { '/tmp' }
|
8
|
+
|
9
|
+
describe 'environments' do
|
10
|
+
it 'uses the name as a prefix when told' do
|
11
|
+
subject = described_class.new(name, remote, basedir, true)
|
12
|
+
subject.fetch_remote()
|
13
|
+
subject.environments.length.should > 0
|
14
|
+
subject.environments.first.dirname.should start_with name
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'avoids using the name as a prefix when told' do
|
18
|
+
subject = described_class.new(name, remote, basedir, false)
|
19
|
+
subject.fetch_remote()
|
20
|
+
subject.environments.length.should > 0
|
21
|
+
subject.environments.first.dirname.should_not start_with name
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -2,10 +2,6 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe R10K::Git::WorkingDir do
|
4
4
|
|
5
|
-
before do
|
6
|
-
R10K::Git::Cache.stubs(:cache_root).returns '/tmp'
|
7
|
-
end
|
8
|
-
|
9
5
|
describe "initializing" do
|
10
6
|
it "generates a new cache for the remote" do
|
11
7
|
wd = described_class.new('master', 'git://github.com/adrienthebo/r10k-fixture-repo', '/tmp')
|
@@ -4,12 +4,12 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
describe R10K::Module::Forge do
|
6
6
|
before :each do
|
7
|
-
Object.
|
7
|
+
allow_any_instance_of(Object).to receive(:systemu).and_raise "Tests should never invoke system calls"
|
8
8
|
end
|
9
9
|
|
10
10
|
before :each do
|
11
|
-
|
12
|
-
described_class.any_instance.
|
11
|
+
log = double('stub logger').as_null_object
|
12
|
+
described_class.any_instance.stub(:logger).and_return log
|
13
13
|
end
|
14
14
|
|
15
15
|
describe "implementing the Puppetfile spec" do
|
@@ -54,9 +54,8 @@ describe R10K::Module::Forge do
|
|
54
54
|
its(:version) { should eq 'v8.0.0' }
|
55
55
|
|
56
56
|
it "should try to upgrade the module" do
|
57
|
-
|
58
|
-
|
59
|
-
subject.expects(:pmt).with(expected)
|
57
|
+
expected = %w{upgrade --version=80.0.0 --ignore-dependencies branan/eight_hundred}
|
58
|
+
expect(subject).to receive(:pmt).with(expected)
|
60
59
|
subject.sync
|
61
60
|
end
|
62
61
|
end
|
@@ -65,12 +64,12 @@ describe R10K::Module::Forge do
|
|
65
64
|
subject { described_class.new('branan/eight_hundred', fixture_modulepath, '7.0.0') }
|
66
65
|
|
67
66
|
it { should_not be_insync }
|
68
|
-
its(:version) { should eq '
|
67
|
+
its(:version) { should eq '8.0.0' }
|
69
68
|
|
70
69
|
it "should try to downgrade the module" do
|
71
70
|
# Again with the magical "v" prefix to the version.
|
72
|
-
expected = %w{upgrade --version=
|
73
|
-
subject.
|
71
|
+
expected = %w{upgrade --version=7.0.0 --ignore-dependencies branan/eight_hundred}
|
72
|
+
expect(subject).to receive(:pmt).with(expected)
|
74
73
|
subject.sync
|
75
74
|
end
|
76
75
|
end
|
@@ -82,8 +81,8 @@ describe R10K::Module::Forge do
|
|
82
81
|
its(:version) { should eq SemVer::MIN }
|
83
82
|
|
84
83
|
it "should try to install the module" do
|
85
|
-
expected = %w{install --version=
|
86
|
-
subject.
|
84
|
+
expected = %w{install --version=8.0.0 --ignore-dependencies branan/eight_hundred}
|
85
|
+
expect(subject).to receive(:pmt).with(expected)
|
87
86
|
subject.sync
|
88
87
|
end
|
89
88
|
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'r10k/registry'
|
4
|
+
|
5
|
+
describe R10K::Registry do
|
6
|
+
|
7
|
+
describe "setting up a new registry" do
|
8
|
+
let(:klass) do
|
9
|
+
dubs = double('test class')
|
10
|
+
allow(dubs).to receive(:new) { |*args| args }
|
11
|
+
dubs
|
12
|
+
end
|
13
|
+
|
14
|
+
it "can create new objects" do
|
15
|
+
registry = described_class.new(klass)
|
16
|
+
expect(registry.generate).to eq []
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "defining object arity" do
|
20
|
+
|
21
|
+
it "handles unary objects" do
|
22
|
+
expect(klass).to receive(:new).with(:foo)
|
23
|
+
|
24
|
+
registry = described_class.new(klass)
|
25
|
+
expect(registry.generate(:foo)).to eq [:foo]
|
26
|
+
end
|
27
|
+
|
28
|
+
it "handles ternary objects" do
|
29
|
+
expect(klass).to receive(:new).with(:foo, :bar, :baz)
|
30
|
+
|
31
|
+
registry = described_class.new(klass)
|
32
|
+
expect(registry.generate(:foo, :bar, :baz)).to eq [:foo, :bar, :baz]
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'handles n-ary objects' do
|
36
|
+
args = %w[a bunch of arbitrary objects]
|
37
|
+
expect(klass).to receive(:new).with(*args)
|
38
|
+
|
39
|
+
registry = described_class.new(klass)
|
40
|
+
expect(registry.generate(*args)).to eq args
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'fails when the required arguments are not matched' do
|
44
|
+
expect(klass).to receive(:new).and_raise ArgumentError, "not enough args"
|
45
|
+
|
46
|
+
registry = described_class.new(klass)
|
47
|
+
expect { registry.generate('arity is hard') }.to raise_error ArgumentError, "not enough args"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it "can specify the constructor method" do
|
52
|
+
expect(klass).to receive(:from_json).and_return "this is json, right?"
|
53
|
+
|
54
|
+
registry = described_class.new(klass, :from_json)
|
55
|
+
expect(registry.generate).to eq "this is json, right?"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
it "returns a memoized object if it's been created before" do
|
61
|
+
registry = described_class.new(String)
|
62
|
+
first = registry.generate "bam!"
|
63
|
+
second = registry.generate "bam!"
|
64
|
+
|
65
|
+
expect(first.object_id).to eq second.object_id
|
66
|
+
end
|
67
|
+
|
68
|
+
it 'can clear registered objects' do
|
69
|
+
registry = described_class.new(String)
|
70
|
+
|
71
|
+
first = registry.generate "bam!"
|
72
|
+
registry.clear!
|
73
|
+
second = registry.generate "bam!"
|
74
|
+
|
75
|
+
expect(first.object_id).to_not eq second.object_id
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'r10k/settings'
|
4
|
+
|
5
|
+
describe R10K::Settings::Container do
|
6
|
+
|
7
|
+
describe 'validating keys' do
|
8
|
+
it 'can add new valid keys' do
|
9
|
+
subject.add_valid_key(:v)
|
10
|
+
subject[:v]
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'can check if a key is valid' do
|
14
|
+
subject.add_valid_key(:v)
|
15
|
+
expect(subject.valid_key?(:v)).to be_true
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'can list all valid keys' do
|
19
|
+
subject.add_valid_key(:v)
|
20
|
+
subject.add_valid_key(:w)
|
21
|
+
|
22
|
+
expect(subject.valid_keys).to include :v
|
23
|
+
expect(subject.valid_keys).to include :w
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
describe 'specifying settings' do
|
28
|
+
it 'fails if a setting application uses an invalid key' do
|
29
|
+
expect { subject[:invalid] = 'fail' }.to raise_error R10K::Settings::Container::InvalidKey
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'can look up values that it sets' do
|
33
|
+
subject.add_valid_key :v
|
34
|
+
subject[:v] = 'set'
|
35
|
+
expect(subject[:v]).to eq 'set'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe 'looking up settings' do
|
40
|
+
before do
|
41
|
+
subject.add_valid_key :v
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'fails if a setting lookup uses an invalid key' do
|
45
|
+
expect { subject[:invalid] }.to raise_error R10K::Settings::Container::InvalidKey
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'returns nil if a key is valid but no setting is present' do
|
49
|
+
expect(subject[:v]).to be_nil
|
50
|
+
end
|
51
|
+
|
52
|
+
describe 'with a parent container' do
|
53
|
+
let(:parent) { described_class.new.tap { |p| p.add_valid_key :v } }
|
54
|
+
subject { described_class.new(parent) }
|
55
|
+
|
56
|
+
it 'uses its setting over a parent value' do
|
57
|
+
subject[:v] = 'child'
|
58
|
+
parent[:v] = 'parent'
|
59
|
+
expect(subject[:v]).to eq 'child'
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'falls back to the parent value if it does not have a value' do
|
63
|
+
parent[:v] = 'parent'
|
64
|
+
expect(subject[:v]).to eq 'parent'
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: r10k
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
5
|
-
prerelease:
|
4
|
+
version: 1.1.0rc1
|
5
|
+
prerelease: 5
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Adrien Thebo
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-09-30 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: colored
|
@@ -34,7 +34,7 @@ dependencies:
|
|
34
34
|
requirements:
|
35
35
|
- - ~>
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version: 2.
|
37
|
+
version: 2.4.0
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -42,7 +42,7 @@ dependencies:
|
|
42
42
|
requirements:
|
43
43
|
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version: 2.
|
45
|
+
version: 2.4.0
|
46
46
|
- !ruby/object:Gem::Dependency
|
47
47
|
name: systemu
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -98,7 +98,7 @@ dependencies:
|
|
98
98
|
requirements:
|
99
99
|
- - ~>
|
100
100
|
- !ruby/object:Gem::Version
|
101
|
-
version: 2.
|
101
|
+
version: 2.14.0
|
102
102
|
type: :development
|
103
103
|
prerelease: false
|
104
104
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -106,27 +106,10 @@ dependencies:
|
|
106
106
|
requirements:
|
107
107
|
- - ~>
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
version: 2.
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
none: false
|
114
|
-
requirements:
|
115
|
-
- - ~>
|
116
|
-
- !ruby/object:Gem::Version
|
117
|
-
version: 0.10.5
|
118
|
-
type: :development
|
119
|
-
prerelease: false
|
120
|
-
version_requirements: !ruby/object:Gem::Requirement
|
121
|
-
none: false
|
122
|
-
requirements:
|
123
|
-
- - ~>
|
124
|
-
- !ruby/object:Gem::Version
|
125
|
-
version: 0.10.5
|
126
|
-
description: ! " R10K is an implementation of the Dynamic Puppet environments based
|
127
|
-
on git repositories\n as described in http://puppetlabs.com/blog/git-workflow-and-puppet-environments/.
|
128
|
-
It\n aggressively caches and tries to minimize network activity to ensure that
|
129
|
-
interactive\n deployment is as fast as possible.\n"
|
109
|
+
version: 2.14.0
|
110
|
+
description: ! " R10K provides a general purpose toolset for deploying Puppet environments
|
111
|
+
and modules.\n It implements the Puppetfile format and provides a native implementation
|
112
|
+
of Puppet\n dynamic environments.\n"
|
130
113
|
email: adrien@somethingsinistral.net
|
131
114
|
executables:
|
132
115
|
- r10k
|
@@ -137,7 +120,9 @@ files:
|
|
137
120
|
- lib/r10k.rb
|
138
121
|
- lib/r10k/errors.rb
|
139
122
|
- lib/r10k/logging.rb
|
123
|
+
- lib/r10k/registry.rb
|
140
124
|
- lib/r10k/deployment.rb
|
125
|
+
- lib/r10k/settings.rb
|
141
126
|
- lib/r10k/git/errors.rb
|
142
127
|
- lib/r10k/git/cache.rb
|
143
128
|
- lib/r10k/git/working_dir.rb
|
@@ -152,7 +137,6 @@ files:
|
|
152
137
|
- lib/r10k/deployment/config.rb
|
153
138
|
- lib/r10k/deployment/source.rb
|
154
139
|
- lib/r10k/util/purgeable.rb
|
155
|
-
- lib/r10k/util/interp.rb
|
156
140
|
- lib/r10k/cli/environment.rb
|
157
141
|
- lib/r10k/cli/environment/list.rb
|
158
142
|
- lib/r10k/cli/environment/deploy.rb
|
@@ -165,19 +149,27 @@ files:
|
|
165
149
|
- lib/r10k/cli/module/list.rb
|
166
150
|
- lib/r10k/cli/module/deploy.rb
|
167
151
|
- lib/r10k/cli/version.rb
|
152
|
+
- lib/r10k/settings/container.rb
|
153
|
+
- lib/r10k/settings/mixin.rb
|
168
154
|
- lib/r10k/task/environment.rb
|
169
155
|
- lib/r10k/task/deployment.rb
|
170
156
|
- lib/r10k/task/module.rb
|
171
157
|
- lib/r10k/task/puppetfile.rb
|
172
158
|
- lib/r10k/task.rb
|
159
|
+
- lib/r10k/module/base.rb
|
173
160
|
- lib/r10k/module/forge.rb
|
174
161
|
- lib/r10k/module/git.rb
|
175
162
|
- lib/r10k/version.rb
|
176
163
|
- lib/semver.rb
|
164
|
+
- spec/spec_helper.rb
|
165
|
+
- spec/fixtures/module/forge/eight_hundred/metadata.json
|
166
|
+
- spec/fixtures/module/forge/eight_hundred/Modulefile
|
167
|
+
- spec/unit/registry_spec.rb
|
177
168
|
- spec/unit/module_spec.rb
|
178
169
|
- spec/unit/git/working_dir_spec.rb
|
179
|
-
- spec/unit/git/cache_spec.rb
|
180
170
|
- spec/unit/deployment/environment_spec.rb
|
171
|
+
- spec/unit/deployment/source_spec.rb
|
172
|
+
- spec/unit/settings/container_spec.rb
|
181
173
|
- spec/unit/module/forge_spec.rb
|
182
174
|
homepage: http://github.com/adrienthebo/r10k
|
183
175
|
licenses: []
|
@@ -194,18 +186,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
194
186
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
195
187
|
none: false
|
196
188
|
requirements:
|
197
|
-
- - ! '
|
189
|
+
- - ! '>'
|
198
190
|
- !ruby/object:Gem::Version
|
199
|
-
version:
|
191
|
+
version: 1.3.1
|
200
192
|
requirements: []
|
201
193
|
rubyforge_project:
|
202
194
|
rubygems_version: 1.8.23
|
203
195
|
signing_key:
|
204
196
|
specification_version: 3
|
205
|
-
summary:
|
197
|
+
summary: Puppet environment and module deployment
|
206
198
|
test_files:
|
199
|
+
- spec/unit/registry_spec.rb
|
207
200
|
- spec/unit/module_spec.rb
|
208
201
|
- spec/unit/git/working_dir_spec.rb
|
209
|
-
- spec/unit/git/cache_spec.rb
|
210
202
|
- spec/unit/deployment/environment_spec.rb
|
203
|
+
- spec/unit/deployment/source_spec.rb
|
204
|
+
- spec/unit/settings/container_spec.rb
|
211
205
|
- spec/unit/module/forge_spec.rb
|
206
|
+
has_rdoc:
|
data/lib/r10k/util/interp.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
|
2
|
-
module R10K; end
|
3
|
-
module R10K::Util; end
|
4
|
-
|
5
|
-
module R10K::Util::Interp
|
6
|
-
|
7
|
-
# Interpolate a string with a given scope
|
8
|
-
#
|
9
|
-
# @param [String] string
|
10
|
-
# @param [Hash] scope
|
11
|
-
#
|
12
|
-
# @return [String]
|
13
|
-
def interpolate_string(string, scope)
|
14
|
-
|
15
|
-
interp = string.clone
|
16
|
-
|
17
|
-
while (matchdata = interp.match /%\{.+?\}/)
|
18
|
-
var_name = matchdata[1].intern
|
19
|
-
var_data = scope[var_name]
|
20
|
-
interp.gsub!(/%\{#{var_name}\}/, var_data)
|
21
|
-
end
|
22
|
-
|
23
|
-
interp
|
24
|
-
end
|
25
|
-
end
|
data/spec/unit/git/cache_spec.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe R10K::Git::Cache, 'memoizing objects' do
|
4
|
-
|
5
|
-
it "returns the same object when a remote is duplicated" do
|
6
|
-
first = described_class.new('foo')
|
7
|
-
second = described_class.new('foo')
|
8
|
-
|
9
|
-
first.should be second
|
10
|
-
end
|
11
|
-
|
12
|
-
it "wipes the memoized objects when .clear! is called" do
|
13
|
-
first = described_class.new('foo')
|
14
|
-
described_class.clear!
|
15
|
-
second = described_class.new('foo')
|
16
|
-
|
17
|
-
first.should_not be second
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
describe R10K::Git::Cache do
|
22
|
-
|
23
|
-
after do
|
24
|
-
described_class.clear!
|
25
|
-
end
|
26
|
-
|
27
|
-
describe 'setting the cache root' do
|
28
|
-
it 'defaults to ~/.r10k/git' do
|
29
|
-
described_class.new('foo').cache_root.should match %r[/\.r10k/git]
|
30
|
-
end
|
31
|
-
|
32
|
-
it 'uses the class cache root if set' do
|
33
|
-
described_class.stubs(:cache_root).returns '/var/spool/r10k'
|
34
|
-
described_class.new('foo').cache_root.should == '/var/spool/r10k'
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|