r10k 1.2.4 → 1.3.0rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/{CHANGELOG → CHANGELOG.mkd} +51 -41
- data/doc/dynamic-environments/configuration.mkd +1 -1
- data/doc/dynamic-environments/git-environments.markdown +19 -0
- data/doc/dynamic-environments/usage.mkd +6 -0
- data/lib/r10k/cli/deploy.rb +15 -0
- data/lib/r10k/cli/ext/logging.rb +0 -1
- data/lib/r10k/cli/module/deploy.rb +0 -1
- data/lib/r10k/cli/puppetfile.rb +2 -2
- data/lib/r10k/cli.rb +2 -16
- data/lib/r10k/deployment/environment.rb +9 -79
- data/lib/r10k/deployment/source.rb +15 -89
- data/lib/r10k/deployment.rb +13 -14
- data/lib/r10k/environment/base.rb +42 -0
- data/lib/r10k/environment/git.rb +79 -0
- data/lib/r10k/environment/svn.rb +73 -0
- data/lib/r10k/environment.rb +7 -0
- data/lib/r10k/execution.rb +0 -1
- data/lib/r10k/git/cache.rb +11 -5
- data/lib/r10k/git/repository.rb +1 -8
- data/lib/r10k/git/working_dir.rb +11 -34
- data/lib/r10k/git.rb +0 -1
- data/lib/r10k/instance_cache.rb +32 -0
- data/lib/r10k/keyed_factory.rb +39 -0
- data/lib/r10k/module/forge.rb +2 -3
- data/lib/r10k/module/svn.rb +0 -1
- data/lib/r10k/puppetfile.rb +0 -1
- data/lib/r10k/registry.rb +3 -31
- data/lib/r10k/source/base.rb +60 -0
- data/lib/r10k/source/git.rb +195 -0
- data/lib/r10k/source/svn.rb +140 -0
- data/lib/r10k/source.rb +39 -0
- data/lib/r10k/svn/remote.rb +48 -0
- data/lib/r10k/svn/working_dir.rb +0 -2
- data/lib/r10k/svn.rb +6 -0
- data/lib/r10k/task/deployment.rb +1 -2
- data/lib/r10k/task.rb +0 -2
- data/lib/r10k/task_runner.rb +0 -1
- data/lib/r10k/util/core_ext/hash_ext.rb +19 -0
- data/lib/r10k/util/subprocess.rb +0 -1
- data/lib/r10k/version.rb +1 -1
- data/lib/r10k.rb +1 -0
- data/spec/unit/deployment/environment_spec.rb +16 -15
- data/spec/unit/environment/git_spec.rb +81 -0
- data/spec/unit/environment/svn_spec.rb +76 -0
- data/spec/unit/git/repository_spec.rb +0 -10
- data/spec/unit/git/working_dir_spec.rb +1 -110
- data/spec/unit/{registry_spec.rb → instance_cache_spec.rb} +3 -3
- data/spec/unit/keyed_factory_spec.rb +51 -0
- data/spec/unit/source/git_spec.rb +274 -0
- data/spec/unit/source/svn_spec.rb +102 -0
- data/spec/unit/source_spec.rb +10 -0
- data/spec/unit/svn/remote_spec.rb +21 -0
- data/spec/unit/util/core_ext/hash_ext_spec.rb +63 -0
- metadata +36 -10
- data/lib/r10k/git/alternates.rb +0 -49
- data/spec/unit/git/alternates_spec.rb +0 -90
@@ -0,0 +1,195 @@
|
|
1
|
+
require 'r10k/git'
|
2
|
+
require 'r10k/environment'
|
3
|
+
require 'r10k/util/purgeable'
|
4
|
+
require 'r10k/util/core_ext/hash_ext'
|
5
|
+
|
6
|
+
# This class implements a source for Git environments.
|
7
|
+
#
|
8
|
+
# A Git source generates environments by locally caching the given Git
|
9
|
+
# repository and enumerating the branches for the Git repository. Branches
|
10
|
+
# are mapped to environments without modification.
|
11
|
+
#
|
12
|
+
# @since 1.3.0
|
13
|
+
class R10K::Source::Git < R10K::Source::Base
|
14
|
+
|
15
|
+
include R10K::Logging
|
16
|
+
|
17
|
+
R10K::Source.register(:git, self)
|
18
|
+
# Register git as the default source
|
19
|
+
R10K::Source.register(nil, self)
|
20
|
+
|
21
|
+
# @!attribute [r] remote
|
22
|
+
# @return [String] The URL to the remote git repository
|
23
|
+
attr_reader :remote
|
24
|
+
|
25
|
+
# @!attribute [r] cache
|
26
|
+
# @api private
|
27
|
+
# @return [R10K::Git::Cache] The git cache associated with this source
|
28
|
+
attr_reader :cache
|
29
|
+
|
30
|
+
# @!attribute [r] settings
|
31
|
+
# @return [Hash<Symbol, Object>] Additional settings that configure how
|
32
|
+
# the source should behave.
|
33
|
+
attr_reader :settings
|
34
|
+
|
35
|
+
# @!attribute [r] invalid_branches
|
36
|
+
# @return [String] How Git branch names that cannot be cleanly mapped to
|
37
|
+
# Puppet environments will be handled.
|
38
|
+
attr_reader :invalid_branches
|
39
|
+
|
40
|
+
# Initialize the given source.
|
41
|
+
#
|
42
|
+
# @param name [String] The identifier for this source.
|
43
|
+
# @param basedir [String] The base directory where the generated environments will be created.
|
44
|
+
# @param options [Hash] An additional set of options for this source.
|
45
|
+
#
|
46
|
+
# @option options [Boolean] :prefix Whether to prefix the source name to the
|
47
|
+
# environment directory names. Defaults to false.
|
48
|
+
# @option options [String] :remote The URL to the base directory of the SVN repository
|
49
|
+
# @option options [Hash] :remote Additional settings that configure how the
|
50
|
+
# source should behave.
|
51
|
+
def initialize(name, basedir, options = {})
|
52
|
+
super
|
53
|
+
|
54
|
+
@environments = []
|
55
|
+
|
56
|
+
@remote = options[:remote]
|
57
|
+
@invalid_branches = (options[:invalid_branches] || 'correct_and_warn')
|
58
|
+
|
59
|
+
@cache = R10K::Git::Cache.generate(@remote)
|
60
|
+
end
|
61
|
+
|
62
|
+
# Update the git cache for this git source to get the latest list of environments.
|
63
|
+
#
|
64
|
+
# @return [void]
|
65
|
+
def preload!
|
66
|
+
logger.info "Determining current branches for #{@remote.inspect}"
|
67
|
+
@cache.sync
|
68
|
+
end
|
69
|
+
alias fetch_remote preload!
|
70
|
+
|
71
|
+
# Load the git remote and create environments for each branch. If the cache
|
72
|
+
# has not been fetched, this will return an empty list.
|
73
|
+
#
|
74
|
+
# @return [Array<R10K::Environment::Git>]
|
75
|
+
def environments
|
76
|
+
if not @cache.cached?
|
77
|
+
[]
|
78
|
+
elsif not @environments.empty?
|
79
|
+
@environments
|
80
|
+
else
|
81
|
+
@environments = generate_environments()
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def generate_environments
|
86
|
+
envs = []
|
87
|
+
branch_names.each do |bn|
|
88
|
+
if bn.valid?
|
89
|
+
envs << R10K::Environment::Git.new(bn.name, @basedir, bn.dirname,
|
90
|
+
{:remote => remote, :ref => bn.name})
|
91
|
+
elsif bn.correct?
|
92
|
+
logger.warn "Environment #{bn.name.inspect} contained non-word characters, correcting name to #{bn.dirname}"
|
93
|
+
envs << R10K::Environment::Git.new(bn.name, @basedir, bn.dirname,
|
94
|
+
{:remote => remote, :ref => bn.name})
|
95
|
+
elsif bn.validate?
|
96
|
+
logger.error "Environment #{bn.name.inspect} contained non-word characters, ignoring it."
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
envs
|
101
|
+
end
|
102
|
+
|
103
|
+
include R10K::Util::Purgeable
|
104
|
+
|
105
|
+
def managed_directory
|
106
|
+
@basedir
|
107
|
+
end
|
108
|
+
|
109
|
+
def current_contents
|
110
|
+
dir = self.managed_directory
|
111
|
+
glob_part = @prefix ? @name.to_s() + '_*' : '*'
|
112
|
+
glob_exp = File.join(dir, glob_part)
|
113
|
+
|
114
|
+
Dir.glob(glob_exp).map do |fname|
|
115
|
+
File.basename fname
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# List all environments that should exist in the basedir for this source
|
120
|
+
# @note This implements a required method for the Purgeable mixin
|
121
|
+
# @return [Array<String>]
|
122
|
+
def desired_contents
|
123
|
+
@environments.map {|env| env.dirname }
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
def branch_names
|
129
|
+
@cache.branches.map do |branch|
|
130
|
+
BranchName.new(branch, {
|
131
|
+
:prefix => @prefix,
|
132
|
+
:sourcename => @name,
|
133
|
+
:invalid => @invalid_branches,
|
134
|
+
})
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# @api private
|
139
|
+
class BranchName
|
140
|
+
|
141
|
+
attr_reader :name
|
142
|
+
|
143
|
+
INVALID_CHARACTERS = %r[\W]
|
144
|
+
|
145
|
+
def initialize(name, opts)
|
146
|
+
@name = name
|
147
|
+
@opts = opts
|
148
|
+
|
149
|
+
@prefix = opts[:prefix]
|
150
|
+
@sourcename = opts[:sourcename]
|
151
|
+
@invalid = opts[:invalid]
|
152
|
+
|
153
|
+
case @invalid
|
154
|
+
when 'correct_and_warn'
|
155
|
+
@validate = true
|
156
|
+
@correct = true
|
157
|
+
when 'correct'
|
158
|
+
@validate = false
|
159
|
+
@correct = true
|
160
|
+
when 'error'
|
161
|
+
@validate = true
|
162
|
+
@correct = false
|
163
|
+
when NilClass
|
164
|
+
@validate = opts[:validate]
|
165
|
+
@correct = opts[:correct]
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
def correct?; @correct end
|
170
|
+
def validate?; @validate end
|
171
|
+
|
172
|
+
def valid?
|
173
|
+
if @validate
|
174
|
+
! @name.match(INVALID_CHARACTERS)
|
175
|
+
else
|
176
|
+
true
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
def dirname
|
181
|
+
dir = @name.dup
|
182
|
+
|
183
|
+
if @prefix
|
184
|
+
dir = "#{@sourcename}_#{dir}"
|
185
|
+
end
|
186
|
+
|
187
|
+
if @correct
|
188
|
+
dir.gsub!(INVALID_CHARACTERS, '_')
|
189
|
+
end
|
190
|
+
|
191
|
+
dir
|
192
|
+
end
|
193
|
+
|
194
|
+
end
|
195
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'r10k/svn'
|
2
|
+
require 'r10k/environment'
|
3
|
+
require 'r10k/util/purgeable'
|
4
|
+
require 'r10k/util/core_ext/hash_ext'
|
5
|
+
|
6
|
+
# This class implements a source for SVN environments.
|
7
|
+
#
|
8
|
+
# An SVN source generates environments by enumerating the branches and trunk
|
9
|
+
# for a given SVN remote. SVN repositories must conform to the conventional
|
10
|
+
# SVN repository structure with the directories trunk/, branches/, and
|
11
|
+
# optionally tags/ in the root of the repository. The trunk/ directory is
|
12
|
+
# specifically mapped to the production environment, branches are created
|
13
|
+
# as environments with the name of the given branch.
|
14
|
+
#
|
15
|
+
# @see http://svnbook.red-bean.com/en/1.7/svn.branchmerge.maint.html
|
16
|
+
# @since 1.3.0
|
17
|
+
class R10K::Source::SVN < R10K::Source::Base
|
18
|
+
|
19
|
+
R10K::Source.register(:svn, self)
|
20
|
+
|
21
|
+
# @!attribute [r] remote
|
22
|
+
# @return [String] The URL to the base directory of the SVN repository
|
23
|
+
attr_reader :remote
|
24
|
+
|
25
|
+
# @!attribute [r] svn_remote
|
26
|
+
# @api private
|
27
|
+
# @return [R10K::SVN::Remote]
|
28
|
+
attr_reader :svn_remote
|
29
|
+
|
30
|
+
# Initialize the given source.
|
31
|
+
#
|
32
|
+
# @param name [String] The identifier for this source.
|
33
|
+
# @param basedir [String] The base directory where the generated environments will be created.
|
34
|
+
# @param options [Hash] An additional set of options for this source.
|
35
|
+
#
|
36
|
+
# @option options [Boolean] :prefix Whether to prefix the source name to the
|
37
|
+
# environment directory names. Defaults to false.
|
38
|
+
# @option options [String] :remote The URL to the base directory of the SVN repository
|
39
|
+
def initialize(name, basedir, options = {})
|
40
|
+
super
|
41
|
+
|
42
|
+
@remote = options[:remote]
|
43
|
+
@environments = []
|
44
|
+
|
45
|
+
@svn_remote = R10K::SVN::Remote.new(@remote)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Enumerate the environments associated with this SVN source.
|
49
|
+
#
|
50
|
+
# @return [Array<R10K::Environment::SVN>] An array of environments created
|
51
|
+
# from this source.
|
52
|
+
def environments
|
53
|
+
if @environments.empty?
|
54
|
+
@environments = generate_environments()
|
55
|
+
end
|
56
|
+
|
57
|
+
@environments
|
58
|
+
end
|
59
|
+
|
60
|
+
# Generate a list of currently available SVN environments
|
61
|
+
#
|
62
|
+
# @todo respect environment name corrections
|
63
|
+
#
|
64
|
+
# @api protected
|
65
|
+
# @return [Array<R10K::Environment::SVN>] An array of environments created
|
66
|
+
# from this source.
|
67
|
+
def generate_environments
|
68
|
+
|
69
|
+
branch_names.map do |branch|
|
70
|
+
R10K::Environment::SVN.new(branch.name, @basedir, branch.dirname,
|
71
|
+
{ :remote => branch.remote })
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
include R10K::Util::Purgeable
|
76
|
+
|
77
|
+
def managed_directory
|
78
|
+
@basedir
|
79
|
+
end
|
80
|
+
|
81
|
+
def current_contents
|
82
|
+
Dir.glob(File.join(@basedir, '*')).map do |fname|
|
83
|
+
File.basename fname
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# List all environments that should exist in the basedir for this source
|
88
|
+
# @note This implements a required method for the Purgeable mixin
|
89
|
+
# @return [Array<String>]
|
90
|
+
def desired_contents
|
91
|
+
@environments.map {|env| env.dirname }
|
92
|
+
end
|
93
|
+
|
94
|
+
include R10K::Logging
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def branch_names
|
99
|
+
branches = []
|
100
|
+
|
101
|
+
branch_opts = {
|
102
|
+
:prefix => @prefix,
|
103
|
+
:sourcename => @name,
|
104
|
+
}
|
105
|
+
|
106
|
+
branches << BranchName.new('production', "#{@remote}/trunk", branch_opts)
|
107
|
+
@svn_remote.branches.each do |branch|
|
108
|
+
branches << BranchName.new(branch, "#{@remote}/branches/#{branch}", branch_opts)
|
109
|
+
end
|
110
|
+
|
111
|
+
branches
|
112
|
+
end
|
113
|
+
|
114
|
+
# @api private
|
115
|
+
# @todo respect environment name corrections
|
116
|
+
class BranchName
|
117
|
+
|
118
|
+
attr_reader :name
|
119
|
+
attr_reader :remote
|
120
|
+
|
121
|
+
def initialize(name, remote, opts)
|
122
|
+
@name = name
|
123
|
+
@remote = remote
|
124
|
+
@opts = opts
|
125
|
+
|
126
|
+
@prefix = opts[:prefix]
|
127
|
+
@sourcename = opts[:sourcename]
|
128
|
+
end
|
129
|
+
|
130
|
+
def dirname
|
131
|
+
dir = @name.dup
|
132
|
+
|
133
|
+
if @prefix
|
134
|
+
dir = "#{@sourcename}_#{dir}"
|
135
|
+
end
|
136
|
+
|
137
|
+
dir
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
data/lib/r10k/source.rb
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'r10k'
|
2
|
+
require 'r10k/keyed_factory'
|
3
|
+
require 'r10k/util/core_ext/hash_ext'
|
4
|
+
|
5
|
+
module R10K
|
6
|
+
module Source
|
7
|
+
def self.factory
|
8
|
+
@factory ||= R10K::KeyedFactory.new
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.register(key, klass)
|
12
|
+
factory.register(key, klass)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.retrieve(key)
|
16
|
+
factory.retrieve(key)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.generate(type, basedir, name, options = {})
|
20
|
+
factory.generate(type, basedir, name, options)
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.from_hash(name, hash)
|
24
|
+
hash.extend R10K::Util::CoreExt::HashExt::SymbolizeKeys
|
25
|
+
hash.symbolize_keys!
|
26
|
+
|
27
|
+
basedir = hash.delete(:basedir)
|
28
|
+
|
29
|
+
type = hash.delete(:type)
|
30
|
+
type = type.is_a?(String) ? type.to_sym : type
|
31
|
+
|
32
|
+
generate(type, name, basedir, hash)
|
33
|
+
end
|
34
|
+
|
35
|
+
require 'r10k/source/base'
|
36
|
+
require 'r10k/source/git'
|
37
|
+
require 'r10k/source/svn'
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'r10k/util/subprocess'
|
2
|
+
|
3
|
+
class R10K::SVN::Remote
|
4
|
+
|
5
|
+
def initialize(baseurl)
|
6
|
+
@baseurl = baseurl
|
7
|
+
end
|
8
|
+
|
9
|
+
# @todo validate that the path to trunk exists in the remote
|
10
|
+
def trunk
|
11
|
+
"#{@baseurl}/trunk"
|
12
|
+
end
|
13
|
+
|
14
|
+
# @todo gracefully handle cases where no branches exist
|
15
|
+
def branches
|
16
|
+
text = svn ['ls', "#{@baseurl}/branches"]
|
17
|
+
text.lines.map do |line|
|
18
|
+
line.chomp!
|
19
|
+
line.gsub!(%r[/$], '')
|
20
|
+
line
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
include R10K::Logging
|
27
|
+
|
28
|
+
# Wrap SVN commands
|
29
|
+
#
|
30
|
+
# @param argv [Array<String>]
|
31
|
+
# @param opts [Hash]
|
32
|
+
#
|
33
|
+
# @option opts [Pathname] :cwd The directory to run the command in
|
34
|
+
#
|
35
|
+
# @return [String] The stdout from the given command
|
36
|
+
def svn(argv, opts = {})
|
37
|
+
argv.unshift('svn')
|
38
|
+
|
39
|
+
subproc = R10K::Util::Subprocess.new(argv)
|
40
|
+
subproc.raise_on_fail = true
|
41
|
+
subproc.logger = self.logger
|
42
|
+
|
43
|
+
subproc.cwd = opts[:cwd]
|
44
|
+
result = subproc.execute
|
45
|
+
|
46
|
+
result.stdout
|
47
|
+
end
|
48
|
+
end
|
data/lib/r10k/svn/working_dir.rb
CHANGED
data/lib/r10k/svn.rb
ADDED
data/lib/r10k/task/deployment.rb
CHANGED
data/lib/r10k/task.rb
CHANGED
data/lib/r10k/task_runner.rb
CHANGED
@@ -0,0 +1,19 @@
|
|
1
|
+
module R10K
|
2
|
+
module Util
|
3
|
+
module CoreExt
|
4
|
+
module HashExt
|
5
|
+
module SymbolizeKeys
|
6
|
+
def symbolize_keys!
|
7
|
+
self.keys.each do |key|
|
8
|
+
next unless key.is_a? String
|
9
|
+
if self[key.to_sym]
|
10
|
+
raise TypeError, "An existing interned key for #{key} exists, cannot overwrite"
|
11
|
+
end
|
12
|
+
self[key.to_sym] = self.delete(key)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/lib/r10k/util/subprocess.rb
CHANGED
data/lib/r10k/version.rb
CHANGED
data/lib/r10k.rb
CHANGED
@@ -2,23 +2,24 @@ require 'spec_helper'
|
|
2
2
|
require 'r10k/deployment/environment'
|
3
3
|
|
4
4
|
describe R10K::Deployment::Environment do
|
5
|
-
let(:remote) { 'git://github.com/adrienthebo/r10k-fixture-repo' }
|
6
|
-
let(:ref) { 'master' }
|
7
5
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
6
|
+
it "creates R10K::Environment::Git instances" do
|
7
|
+
subject = described_class.new('gitref', 'git://git-server.local/git-remote.git', '/some/nonexistent/dir')
|
8
|
+
expect(subject).to be_a_kind_of R10K::Environment::Git
|
9
|
+
end
|
10
|
+
|
11
|
+
it "uses the ref as the dirname by default" do
|
12
|
+
subject = described_class.new('gitref', 'git://git-server.local/git-remote.git', '/some/nonexistent/dir')
|
13
|
+
expect(subject.dirname).to eq 'gitref'
|
14
|
+
end
|
13
15
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
it "can specify an explicit dirname" do
|
17
|
+
subject = described_class.new('gitref', 'git://git-server.local/git-remote.git', '/some/nonexistent/dir', 'explicit-dirname')
|
18
|
+
expect(subject.dirname).to eq 'explicit-dirname'
|
19
|
+
end
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
end
|
21
|
+
it "supports prefixing for backwards compatibility" do
|
22
|
+
subject = described_class.new('gitref', 'git://git-server.local/git-remote.git', '/some/nonexistent/dir', nil, 'source')
|
23
|
+
expect(subject.dirname).to eq 'source_gitref'
|
23
24
|
end
|
24
25
|
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'r10k/environment'
|
3
|
+
|
4
|
+
describe R10K::Environment::Git do
|
5
|
+
|
6
|
+
subject do
|
7
|
+
described_class.new(
|
8
|
+
'myenv',
|
9
|
+
'/some/nonexistent/environmentdir',
|
10
|
+
'gitref',
|
11
|
+
{
|
12
|
+
:remote => 'git://git-server.site/my-repo.git',
|
13
|
+
:ref => 'd026ea677116424d2968edb9cee8cbc24d09322b',
|
14
|
+
}
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
let(:working_dir) { subject.working_dir }
|
19
|
+
|
20
|
+
describe "storing attributes" do
|
21
|
+
it "can return the environment name" do
|
22
|
+
expect(subject.name).to eq 'myenv'
|
23
|
+
end
|
24
|
+
|
25
|
+
it "can return the environment basedir" do
|
26
|
+
expect(subject.basedir).to eq '/some/nonexistent/environmentdir'
|
27
|
+
end
|
28
|
+
|
29
|
+
it "can return the environment dirname" do
|
30
|
+
expect(subject.dirname).to eq 'gitref'
|
31
|
+
end
|
32
|
+
|
33
|
+
it "can return the environment remote" do
|
34
|
+
expect(subject.remote).to eq 'git://git-server.site/my-repo.git'
|
35
|
+
end
|
36
|
+
|
37
|
+
it "can return the environment ref" do
|
38
|
+
expect(subject.ref).to eq 'd026ea677116424d2968edb9cee8cbc24d09322b'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "synchronizing the environment" do
|
43
|
+
it "updates all modules when creating a new environment" do
|
44
|
+
allow(working_dir).to receive(:cloned?).and_return(false)
|
45
|
+
expect(working_dir).to receive(:sync)
|
46
|
+
expect(subject).to receive(:sync_modules)
|
47
|
+
subject.sync
|
48
|
+
end
|
49
|
+
|
50
|
+
it "does not update all modules when updating an existing environment" do
|
51
|
+
allow(working_dir).to receive(:cloned?).and_return(true)
|
52
|
+
expect(working_dir).to receive(:sync)
|
53
|
+
expect(subject).to_not receive(:sync_modules)
|
54
|
+
subject.sync
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "generating a puppetfile for the environment" do
|
59
|
+
let(:puppetfile) { subject.puppetfile }
|
60
|
+
|
61
|
+
it "creates a puppetfile at the full path to the environment" do
|
62
|
+
expect(puppetfile.basedir).to eq '/some/nonexistent/environmentdir/gitref'
|
63
|
+
end
|
64
|
+
|
65
|
+
it "sets the moduledir to 'modules' relative to the environment path" do
|
66
|
+
expect(puppetfile.moduledir).to eq '/some/nonexistent/environmentdir/gitref/modules'
|
67
|
+
end
|
68
|
+
|
69
|
+
it "sets the puppetfile path to 'Puppetfile' relative to the environment path" do
|
70
|
+
expect(puppetfile.puppetfile_path).to eq '/some/nonexistent/environmentdir/gitref/Puppetfile'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "enumerating modules" do
|
75
|
+
it "loads the Puppetfile and returns modules in that puppetfile" do
|
76
|
+
expect(subject.puppetfile).to receive(:load)
|
77
|
+
expect(subject.puppetfile).to receive(:modules).and_return [:modules]
|
78
|
+
expect(subject.modules).to eq([:modules])
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|