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.
@@ -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
@@ -59,8 +59,10 @@ class Deployment
59
59
  private
60
60
 
61
61
  def load_sources
62
- @_sources = @config.setting(:sources).map do |(name, hash)|
63
- R10K::Deployment::Source.vivify(name, hash)
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
 
@@ -57,7 +57,7 @@ class Config
57
57
  def apply_config_settings
58
58
  cachedir = setting(:cachedir)
59
59
  if cachedir
60
- R10K::Git::Cache.cache_root = cachedir
60
+ R10K::Git::Cache.settings[:cache_root] = cachedir
61
61
  end
62
62
  end
63
63
 
@@ -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
- def initialize(ref, remote, basedir, dirname = nil)
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
- @dirname = sanitize_dirname(dirname || ref)
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 characers (letter, digit, underscore) in
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.new(@remote)
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
- R10K::Deployment::Environment.new(branch, @remote, @basedir)
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 = []
@@ -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
- class << self
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
- def cache_root
18
- @cache_root
19
- end
16
+ def_setting_attr :cache_root, File.expand_path('~/.r10k/git')
20
17
 
21
- # Memoize class instances and return existing instances.
22
- #
23
- # This allows objects to mark themselves as cached to prevent unnecessary
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
- def clear!
39
- @repos = {}
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
- @cache_root = self.class.cache_root || default_cache_root
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
- FileUtils.mkdir_p cache_root unless File.exist? @cache_root
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
@@ -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.new(@remote)
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 inheriting class for later generation
6
- def self.included(klass)
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
- attr_accessor :name, :basedir
34
-
35
- # @return [String] The full filesystem path to the module.
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'
@@ -0,0 +1,10 @@
1
+ require 'r10k/module'
2
+
3
+ class R10K::Module::Base
4
+ attr_accessor :name, :basedir
5
+
6
+ # @return [String] The full filesystem path to the module.
7
+ def full_path
8
+ File.join(@basedir, @name)
9
+ end
10
+ end
@@ -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
- module R10K
12
- module Module
13
- class Forge
10
+ class R10K::Module::Forge < R10K::Module::Base
14
11
 
15
- include R10K::Module
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
@@ -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
- module R10K
7
- module Module
8
- class Git
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
@@ -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,6 @@
1
+ module R10K
2
+ module Settings
3
+ require 'r10k/settings/container'
4
+ require 'r10k/settings/mixin'
5
+ end
6
+ 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
@@ -1,3 +1,3 @@
1
1
  module R10K
2
- VERSION = '1.0.0'
2
+ VERSION = '1.1.0rc1'
3
3
  end
@@ -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
+ }
@@ -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.expects(:systemu).never
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
- s = stub(:debug2 => nil, :debug1 => nil, :debug => nil, :info => nil)
12
- described_class.any_instance.stubs(:logger).returns s
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
- # "v80.0.0" ? Seriously? Where did the "v" come from?
58
- expected = %w{upgrade --version=v80.0.0 --ignore-dependencies branan/eight_hundred}
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 'v8.0.0' }
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=v7.0.0 --ignore-dependencies branan/eight_hundred}
73
- subject.expects(:pmt).with(expected)
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=v8.0.0 --ignore-dependencies branan/eight_hundred}
86
- subject.expects(:pmt).with(expected)
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.0.0
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-05-31 00:00:00.000000000 Z
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.3.0
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.3.0
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.10.0
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.10.0
110
- - !ruby/object:Gem::Dependency
111
- name: mocha
112
- requirement: !ruby/object:Gem::Requirement
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: '0'
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: Dynamic Puppet environments with Git
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:
@@ -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
@@ -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