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