pdqtest 1.4.1 → 1.9.9beta2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.travis.yml +9 -3
- data/doc/acceptance_tests.md +100 -22
- data/doc/caching.md +5 -1
- data/doc/development.md +16 -5
- data/doc/emoji.md +20 -9
- data/doc/enabling_testing.md +15 -3
- data/doc/examples.md +25 -6
- data/doc/hiera.md +30 -11
- data/doc/installation.md +59 -8
- data/doc/pdk.md +334 -0
- data/doc/puppet_facts.md +45 -3
- data/doc/puppet_module_dependencies.md +34 -16
- data/doc/running_tests.md +35 -15
- data/doc/test_generation.md +11 -19
- data/doc/tips_and_tricks.md +17 -8
- data/doc/troubleshooting.md +19 -8
- data/doc/upgrading.md +125 -6
- data/doc/windows.md +51 -0
- data/docker_images/centos/Dockerfile +4 -3
- data/docker_images/centos/Makefile +1 -1
- data/docker_images/ubuntu/Dockerfile +3 -3
- data/docker_images/windows/Dockerfile +26 -0
- data/docker_images/windows/make.ps1 +2 -0
- data/exe/pdqtest +73 -28
- data/lib/pdqtest/core.rb +1 -1
- data/lib/pdqtest/docker.rb +143 -51
- data/lib/pdqtest/emoji.rb +33 -7
- data/lib/pdqtest/fastcheck.rb +19 -0
- data/lib/pdqtest/instance.rb +16 -15
- data/lib/pdqtest/logger.rb +35 -0
- data/lib/pdqtest/pdk.rb +98 -0
- data/lib/pdqtest/pdqtest1x.rb +115 -0
- data/lib/pdqtest/puppet.rb +277 -134
- data/lib/pdqtest/skeleton.rb +119 -39
- data/lib/pdqtest/upgrade.rb +42 -42
- data/lib/pdqtest/util.rb +82 -2
- data/lib/pdqtest/version.rb +1 -2
- data/pdqtest.gemspec +8 -13
- data/res/{skeleton → acceptance}/init.bats +0 -0
- data/res/{skeleton → acceptance}/init__before.bats +0 -0
- data/res/{skeleton → acceptance}/init__setup.sh +0 -0
- data/res/skeleton/.puppet-lint.rc +5 -0
- data/res/skeleton/{dot_travis.yml → .travis.yml} +0 -0
- data/res/skeleton/Makefile +20 -5
- data/res/skeleton/make.ps1 +66 -0
- data/res/skeleton/spec/fixtures/hiera.yaml +13 -0
- data/res/skeleton/spec/fixtures/hieradata/test.yaml +11 -0
- data/res/templates/examples_init.pp.erb +1 -1
- metadata +47 -115
- data/lib/pdqtest/lint.rb +0 -31
- data/lib/pdqtest/rspec.rb +0 -69
- data/lib/pdqtest/syntax.rb +0 -20
- data/res/skeleton/Gemfile +0 -7
- data/res/skeleton/Rakefile +0 -3
- data/res/skeleton/dot_gitignore +0 -9
- data/res/skeleton/dot_rspec +0 -2
- data/res/skeleton/hiera.yaml +0 -7
- data/res/skeleton/spec_helper.rb +0 -4
- data/res/skeleton/test.yaml +0 -3
data/lib/pdqtest/docker.rb
CHANGED
@@ -6,23 +6,101 @@ module PDQTest
|
|
6
6
|
OUT = 0
|
7
7
|
ERR = 1
|
8
8
|
STATUS = 2
|
9
|
-
|
9
|
+
REAL_CMD = 3
|
10
10
|
IMAGES = {
|
11
|
-
:DEFAULT => 'declarativesystems/pdqtest-
|
12
|
-
:UBUNTU => 'declarativesystems/pdqtest-ubuntu:2018-
|
11
|
+
:DEFAULT => 'declarativesystems/pdqtest-centos:2018-09-15-0',
|
12
|
+
:UBUNTU => 'declarativesystems/pdqtest-ubuntu:2018-09-15-0',
|
13
|
+
:WINDOWS => 'declarativesystems/pdqtest-windows:2018-09-18-0',
|
13
14
|
}
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
|
16
|
+
# volume paths are different for windows containers
|
17
|
+
# https://superuser.com/questions/1051520/docker-windows-container-how-to-mount-a-host-folder-as-data-volume-on-windows
|
18
|
+
# path for common things *inside* the container
|
19
|
+
#
|
20
|
+
# Also... bind mounting _files_ is impossible on windows in docker right now:
|
21
|
+
# * https://github.com/docker/for-win/issues/376
|
22
|
+
# * https://github.com/moby/moby/issues/30555
|
23
|
+
# * https://github.com/opctl/opctl/issues/207
|
24
|
+
# * https://docs.docker.com/engine/reference/commandline/run/#capture-container-id---cidfile
|
25
|
+
CONTAINER_PATHS = {
|
26
|
+
:windows => {
|
27
|
+
:testcase => 'C:\\testcase',
|
28
|
+
},
|
29
|
+
:linux => {
|
30
|
+
:yum_cache => "/var/cache/yum",
|
31
|
+
:testcase => '/testcase',
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
# path for common things on the *host* computer running pdqtest (vm, laptop, etc)
|
36
|
+
HOST_PATHS = {
|
37
|
+
:windows => {
|
38
|
+
},
|
39
|
+
:linux => {
|
40
|
+
:yum_cache => "#{Util::app_dir_expanded}/cache/yum",
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
# convenience lookup for container testcase dir since its used all over the
|
45
|
+
# place
|
46
|
+
def self.test_dir
|
47
|
+
CONTAINER_PATHS[Util.host_platform][:testcase]
|
22
48
|
end
|
23
49
|
|
50
|
+
# Map the testcase and any OS specific volumes we would always want, eg
|
51
|
+
# yum cache, random crap for systemd, etc
|
52
|
+
def self.supporting_volumes
|
53
|
+
pwd = Dir.pwd
|
54
|
+
platform = Util.host_platform
|
55
|
+
if Util.is_windows
|
56
|
+
# normalise output for windows
|
57
|
+
pwd = pwd.gsub(/\//, '\\')
|
58
|
+
end
|
59
|
+
test_dir = CONTAINER_PATHS[platform][:testcase]
|
60
|
+
volumes = {test_dir => {pwd => 'rw'}}
|
61
|
+
|
62
|
+
if ! Util.is_windows
|
63
|
+
volumes['/sys/fs/cgroup'] = {'/sys/fs/cgroup' => 'ro'}
|
64
|
+
volumes[CONTAINER_PATHS[platform][:yum_cache]] = {HOST_PATHS[platform][:yum_cache] => 'rw'}
|
65
|
+
end
|
66
|
+
|
67
|
+
volumes
|
68
|
+
end
|
69
|
+
|
70
|
+
|
24
71
|
def self.exec(container, cmd)
|
25
|
-
|
72
|
+
status = 0
|
73
|
+
res = []
|
74
|
+
|
75
|
+
res[OUT]=[]
|
76
|
+
res[ERR]=[]
|
77
|
+
res[STATUS]=0
|
78
|
+
res[REAL_CMD]=[]
|
79
|
+
|
80
|
+
Array(cmd).each do |c|
|
81
|
+
real_c = Util.wrap_cmd(c)
|
82
|
+
res[REAL_CMD] << real_c
|
83
|
+
$logger.debug "Executing: #{real_c}"
|
84
|
+
_res = container.exec(real_c, tty: true)
|
85
|
+
|
86
|
+
if c =~ /robocopy/
|
87
|
+
# robocopy exit codes break the status check we do later on - we have
|
88
|
+
# to manually 'fix' them here
|
89
|
+
if _res[STATUS] < 4
|
90
|
+
_res[STATUS] = 0
|
91
|
+
end
|
92
|
+
end
|
93
|
+
res[STATUS] += _res[STATUS]
|
94
|
+
res[OUT] += _res[OUT]
|
95
|
+
res[ERR] += _res[ERR]
|
96
|
+
|
97
|
+
# non zero status from something thats not puppet apply is probably an error
|
98
|
+
if _res[STATUS] != 0 && !(c =~ /pupet apply|bats/)
|
99
|
+
$logger.warn "non-zero exit status: #{_res[STATUS]} from #{real_c}: #{_res[OUT]} #{_res[ERR]}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
res
|
26
104
|
end
|
27
105
|
|
28
106
|
# detect the image to use based on metadata.json
|
@@ -50,7 +128,7 @@ module PDQTest
|
|
50
128
|
when "ubuntu"
|
51
129
|
supported_images << IMAGES[:UBUNTU]
|
52
130
|
when "windows"
|
53
|
-
|
131
|
+
supported_images << IMAGES[:WINDOWS]
|
54
132
|
else
|
55
133
|
supported_images << IMAGES[:DEFAULT]
|
56
134
|
end
|
@@ -60,10 +138,15 @@ module PDQTest
|
|
60
138
|
supported_images.uniq
|
61
139
|
end
|
62
140
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
141
|
+
|
142
|
+
def self.new_container(image_name, privileged)
|
143
|
+
|
144
|
+
if Util.is_windows
|
145
|
+
::Docker.url = "tcp://127.0.0.1:2375"
|
146
|
+
# nasty hack for https://github.com/swipely/docker-api/issues/441
|
147
|
+
::Docker.send(:remove_const, 'API_VERSION')
|
148
|
+
::Docker.const_set('API_VERSION', '1.24')
|
149
|
+
end
|
67
150
|
|
68
151
|
# security options seem required on OSX to allow SYS_ADMIN capability to
|
69
152
|
# work - without this container starts fine with no errors but the CAP is
|
@@ -76,47 +159,56 @@ module PDQTest
|
|
76
159
|
[]
|
77
160
|
end
|
78
161
|
|
79
|
-
if !
|
80
|
-
|
162
|
+
if ! Util.is_windows
|
163
|
+
if ! Dir.exists?(HOST_PATHS[Util.host_platform][:yum_cache])
|
164
|
+
FileUtils.mkdir_p(HOST_PATHS[Util.host_platform][:yum_cache])
|
165
|
+
end
|
81
166
|
end
|
82
167
|
|
83
|
-
#
|
84
|
-
|
85
|
-
|
168
|
+
#
|
169
|
+
# volumes (container -> host)
|
170
|
+
#
|
171
|
+
volumes = supporting_volumes
|
172
|
+
|
173
|
+
#
|
174
|
+
# binds (host -> container)
|
175
|
+
#
|
176
|
+
binds = Util.volumes2binds(volumes)
|
177
|
+
|
178
|
+
#
|
179
|
+
# hostconfig->tmpfs (linux)
|
180
|
+
#
|
181
|
+
if Util.is_windows
|
182
|
+
start_body = {}
|
183
|
+
if privileged
|
184
|
+
$logger.error "--privileged has no effect on windows"
|
185
|
+
end
|
186
|
+
else
|
187
|
+
start_body = {
|
188
|
+
'HostConfig' => {
|
189
|
+
'Tmpfs': {
|
190
|
+
'/run' => '',
|
191
|
+
'/run/lock' => '',
|
192
|
+
},
|
193
|
+
CapAdd: [ 'SYS_ADMIN'],
|
194
|
+
Privileged: privileged,
|
195
|
+
}
|
196
|
+
}
|
86
197
|
end
|
198
|
+
|
199
|
+
#
|
200
|
+
# container
|
201
|
+
#
|
202
|
+
|
87
203
|
container = ::Docker::Container.create(
|
88
204
|
'Image' => image_name,
|
89
|
-
'Volumes' =>
|
90
|
-
test_dir => {pwd => 'rw'},
|
91
|
-
HIERA_YAML_CONTAINER => {hiera_yaml_host => 'rw'},
|
92
|
-
HIERA_DIR => {hiera_dir => 'rw'},
|
93
|
-
'/sys/fs/cgroup' => {'/sys/fs/cgroup' => 'ro'},
|
94
|
-
YUM_CACHE_CONTAINER => {YUM_CACHE_HOST => 'rw'},
|
95
|
-
},
|
205
|
+
'Volumes' => volumes,
|
96
206
|
'HostConfig' => {
|
97
207
|
"SecurityOpt" => security_opt,
|
98
|
-
"Binds":
|
99
|
-
"/sys/fs/cgroup:/sys/fs/cgroup:ro",
|
100
|
-
"#{pwd}:#{test_dir}:rw",
|
101
|
-
"#{hiera_yaml_host}:#{HIERA_YAML_CONTAINER}:rw",
|
102
|
-
"#{hiera_dir}:#{HIERA_DIR}:rw",
|
103
|
-
"#{YUM_CACHE_HOST}:#{YUM_CACHE_CONTAINER}:rw",
|
104
|
-
],
|
208
|
+
"Binds": binds,
|
105
209
|
},
|
106
210
|
)
|
107
|
-
container.start(
|
108
|
-
{
|
109
|
-
#'Binds' => [ pwd +':'+ test_dir,],
|
110
|
-
'HostConfig' => {
|
111
|
-
'Tmpfs': {
|
112
|
-
'/run' => '',
|
113
|
-
'/run/lock' => '',
|
114
|
-
},
|
115
|
-
CapAdd: [ 'SYS_ADMIN'],
|
116
|
-
Privileged: privileged,
|
117
|
-
},
|
118
|
-
}
|
119
|
-
)
|
211
|
+
container.start(start_body)
|
120
212
|
|
121
213
|
container
|
122
214
|
end
|
@@ -149,7 +241,7 @@ module PDQTest
|
|
149
241
|
exec_out(res).each { |l|
|
150
242
|
# Output comes back as an array and needs to be iterated or we lose our
|
151
243
|
# ansi formatting
|
152
|
-
|
244
|
+
$logger.info l.chomp
|
153
245
|
}
|
154
246
|
end
|
155
247
|
|
@@ -162,7 +254,7 @@ module PDQTest
|
|
162
254
|
exec_err(res).each { |l|
|
163
255
|
# Output comes back as an array and needs to be iterated or we lose our
|
164
256
|
# ansi formatting
|
165
|
-
|
257
|
+
$logger.error l.chomp
|
166
258
|
}
|
167
259
|
end
|
168
260
|
|
data/lib/pdqtest/emoji.rb
CHANGED
@@ -1,17 +1,43 @@
|
|
1
1
|
module PDQTest
|
2
2
|
module Emoji
|
3
|
+
|
4
|
+
# windows can only output emojii characters in powershell ISE *but* ISE
|
5
|
+
# causes PDK to crash, so we need special lame emoji's for our windows users
|
6
|
+
EMOJIS = {
|
7
|
+
:windows => {
|
8
|
+
:pass => ":-)",
|
9
|
+
:fail => "●~*",
|
10
|
+
:overall_pass => "=D",
|
11
|
+
:overall_fail => "><(((*>",
|
12
|
+
:slow => "(-_-)zzz",
|
13
|
+
:shame => "(-_-)",
|
14
|
+
},
|
15
|
+
:linux => {
|
16
|
+
:pass => "😬",
|
17
|
+
:fail => "💣",
|
18
|
+
:overall_pass => "😎",
|
19
|
+
:overall_fail => "💩",
|
20
|
+
:slow => "🐌",
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
|
3
25
|
@@disable = false
|
4
26
|
|
5
27
|
def self.disable(disable)
|
6
28
|
@@disable = disable
|
7
29
|
end
|
8
30
|
|
31
|
+
def self.emoji(key)
|
32
|
+
EMOJIS[Util.host_platform][key] || raise("missing emoji #{key}")
|
33
|
+
end
|
34
|
+
|
9
35
|
# Print a message prefixed with optional emoji to the STDOUT logger
|
10
|
-
def self.emoji_message(
|
36
|
+
def self.emoji_message(key, message, level=::Logger::INFO)
|
11
37
|
if ! @@disable
|
12
|
-
message = "#{message} #{emoji}"
|
38
|
+
message = "#{message} #{emoji(key)}"
|
13
39
|
end
|
14
|
-
|
40
|
+
$logger.add(level) { message }
|
15
41
|
end
|
16
42
|
|
17
43
|
# print cool emoji based on status
|
@@ -20,22 +46,22 @@ module PDQTest
|
|
20
46
|
if ! @@disable
|
21
47
|
if status
|
22
48
|
# cool bananas
|
23
|
-
|
49
|
+
$logger.info lable_string + emoji_pass
|
24
50
|
else
|
25
51
|
# boom! crappy code
|
26
|
-
|
52
|
+
$logger.error lable_string + emoji_fail
|
27
53
|
end
|
28
54
|
end
|
29
55
|
end
|
30
56
|
|
31
57
|
# partial status when lots to do
|
32
58
|
def self.partial_status(status, label)
|
33
|
-
emoji_status(status,
|
59
|
+
emoji_status(status, emoji(:pass), emoji(:fail), label)
|
34
60
|
end
|
35
61
|
|
36
62
|
# Overall program exit status
|
37
63
|
def self.final_status(status)
|
38
|
-
emoji_status(status,
|
64
|
+
emoji_status(status, emoji(:overall_pass), emoji(:overall_fail), 'Overall')
|
39
65
|
end
|
40
66
|
end
|
41
67
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'pdqtest/emoji'
|
2
|
+
module PDQTest
|
3
|
+
|
4
|
+
# Faster version of syntax and lint checks
|
5
|
+
module Fastcheck
|
6
|
+
|
7
|
+
def self.run
|
8
|
+
status = system("bundle exec puppet-lint manifests")
|
9
|
+
|
10
|
+
if status
|
11
|
+
status = system("bundle exec rake syntax")
|
12
|
+
end
|
13
|
+
|
14
|
+
PDQTest::Emoji.partial_status(status, "fastcheck (syntax+lint)")
|
15
|
+
status
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
data/lib/pdqtest/instance.rb
CHANGED
@@ -5,7 +5,6 @@ require 'escort'
|
|
5
5
|
|
6
6
|
module PDQTest
|
7
7
|
module Instance
|
8
|
-
TEST_DIR='/testcase'
|
9
8
|
@@keep_container = false
|
10
9
|
@@active_container = nil
|
11
10
|
@@image_name = false
|
@@ -50,29 +49,29 @@ module PDQTest
|
|
50
49
|
@@active_container = nil
|
51
50
|
|
52
51
|
if PDQTest::Puppet::find_examples().empty?
|
53
|
-
|
52
|
+
$logger.info "No acceptance tests found, annotate examples with #{PDQTest::Puppet.setting(:magic_marker)} to make some"
|
54
53
|
else
|
55
54
|
# process each supported OS
|
56
55
|
test_platforms = @@image_name || Docker::acceptance_test_images
|
57
|
-
|
56
|
+
$logger.info "Acceptance test on #{test_platforms}..."
|
58
57
|
test_platforms.each { |image_name|
|
59
|
-
|
60
|
-
@@active_container = PDQTest::Docker::new_container(
|
61
|
-
|
58
|
+
$logger.info "--- start test with #{image_name} ---"
|
59
|
+
@@active_container = PDQTest::Docker::new_container(image_name, @@privileged)
|
60
|
+
$logger.info "alive, running tests"
|
62
61
|
status &= PDQTest::Puppet.run(@@active_container, example)
|
63
62
|
|
64
63
|
if @@keep_container
|
65
|
-
|
66
|
-
|
64
|
+
$logger.info "finished build, container #{@@active_container.id} left on system"
|
65
|
+
$logger.info " docker exec -ti #{@@active_container.id} #{Util.shell} "
|
67
66
|
else
|
68
67
|
PDQTest::Docker.cleanup_container(@@active_container)
|
69
68
|
@@active_container = nil
|
70
69
|
end
|
71
70
|
|
72
|
-
|
71
|
+
$logger.info "--- end test with #{image_name} (status: #{status})---"
|
73
72
|
}
|
74
73
|
end
|
75
|
-
|
74
|
+
$logger.info "overall acceptance test status=#{status}"
|
76
75
|
status
|
77
76
|
end
|
78
77
|
|
@@ -80,8 +79,10 @@ module PDQTest
|
|
80
79
|
# pick the first test platform to test on as our shell - want to do a specific one
|
81
80
|
# just list it with --image-name
|
82
81
|
image_name = (@@image_name || Docker::acceptance_test_images).first
|
83
|
-
|
84
|
-
@@active_container = PDQTest::Docker::new_container(
|
82
|
+
$logger.info "Opening a shell in #{image_name}"
|
83
|
+
@@active_container = PDQTest::Docker::new_container(image_name, @@privileged)
|
84
|
+
|
85
|
+
PDQTest::Docker.exec(@@active_container, PDQTest::Puppet.setup)
|
85
86
|
|
86
87
|
# In theory I should be able to get something like the code below to
|
87
88
|
# redirect all input streams and give a makeshift interactive shell, howeve
|
@@ -93,10 +94,10 @@ module PDQTest
|
|
93
94
|
# puts out
|
94
95
|
# puts err
|
95
96
|
# }
|
96
|
-
system("docker exec -ti #{@@active_container.id}
|
97
|
+
system("docker exec -ti #{@@active_container.id} #{Util.shell}")
|
97
98
|
if @@keep_container
|
98
|
-
|
99
|
-
|
99
|
+
$logger.info "finished build, container #{@@active_container.id} left on system"
|
100
|
+
$logger.info " docker exec -ti #{@@active_container.id} #{Util.shell} "
|
100
101
|
else
|
101
102
|
PDQTest::Docker.cleanup_container(@@active_container)
|
102
103
|
@@active_container = nil
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'logging'
|
2
|
+
|
3
|
+
# Fixme - this should be in escort...
|
4
|
+
# credit: Dylan Ratcliffe
|
5
|
+
module PDQTest
|
6
|
+
module Logger
|
7
|
+
def self.logger
|
8
|
+
if ! $logger
|
9
|
+
# here we setup a color scheme called 'bright'
|
10
|
+
Logging.color_scheme('bright',
|
11
|
+
:lines => {
|
12
|
+
:debug => :blue,
|
13
|
+
:info => :white,
|
14
|
+
:warn => :yellow,
|
15
|
+
:error => :red,
|
16
|
+
:fatal => [:white, :on_red]
|
17
|
+
}
|
18
|
+
)
|
19
|
+
|
20
|
+
Logging.appenders.stdout(
|
21
|
+
'stdout',
|
22
|
+
:layout => Logging.layouts.pattern(
|
23
|
+
:pattern => '%m\n',
|
24
|
+
:color_scheme => 'bright'
|
25
|
+
)
|
26
|
+
)
|
27
|
+
|
28
|
+
$logger = Logging.logger['Colors']
|
29
|
+
$logger.add_appenders 'stdout'
|
30
|
+
$logger.level = :info
|
31
|
+
end
|
32
|
+
$logger
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/pdqtest/pdk.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'pdqtest/emoji'
|
2
|
+
require 'pdqtest/puppet'
|
3
|
+
require 'deep_merge'
|
4
|
+
|
5
|
+
module PDQTest
|
6
|
+
# the main purpose of this is to add emoji after running a PDK lifecycle..
|
7
|
+
# There is basically no other way to do this mega-hack. while `pdk` itself is
|
8
|
+
# a kind of selective wrapper around ruby, I couldn't get calling `pdk` from
|
9
|
+
# inside `pdk bundle` to work, nor could I figure out how to load the PDK
|
10
|
+
# libraries from the "inside"
|
11
|
+
module Pdk
|
12
|
+
SYNC_YML = '.sync.yaml'
|
13
|
+
|
14
|
+
# Copy these values from PDK generated metadata to module metadata
|
15
|
+
PDK_TAGS = [
|
16
|
+
"pdk-version",
|
17
|
+
"template-url",
|
18
|
+
"template-ref",
|
19
|
+
]
|
20
|
+
|
21
|
+
# Golden metadata key which proves PDK is already installed
|
22
|
+
PDK_VERSION_TAG = "pdk-version"
|
23
|
+
|
24
|
+
def self.run(subcommand)
|
25
|
+
if Util.is_windows
|
26
|
+
pdk = "powershell -command \"pdk #{subcommand}\" ; exit $LastExitCode"
|
27
|
+
else
|
28
|
+
pdk = "pdk #{subcommand}"
|
29
|
+
end
|
30
|
+
|
31
|
+
# write a .fixtures.yml for PDK test commands
|
32
|
+
if subcommand =~ /test/
|
33
|
+
PDQTest::Puppet.fixtures_yml
|
34
|
+
end
|
35
|
+
|
36
|
+
# on windows our environment is heavly contaminated by bundler - we have
|
37
|
+
# to remove it's environment or pdk command will flatout refuse to run
|
38
|
+
# probably doens't hurt to do this on linux too.
|
39
|
+
env = ENV.reject { |e|
|
40
|
+
[
|
41
|
+
"BUNDLER_ORIG_BUNDLER_ORIG_MANPATH",
|
42
|
+
"BUNDLER_ORIG_BUNDLER_VERSION",
|
43
|
+
"BUNDLER_ORIG_BUNDLE_BIN_PATH",
|
44
|
+
"BUNDLER_ORIG_BUNDLE_GEMFILE",
|
45
|
+
"BUNDLER_ORIG_GEM_HOME",
|
46
|
+
"BUNDLER_ORIG_GEM_PATH",
|
47
|
+
"BUNDLER_ORIG_MANPATH",
|
48
|
+
"BUNDLER_ORIG_PATH",
|
49
|
+
"BUNDLER_ORIG_RB_USER_INSTALL",
|
50
|
+
"BUNDLER_ORIG_RUBYLIB",
|
51
|
+
"BUNDLER_ORIG_RUBYOPT",
|
52
|
+
"BUNDLER_VERSION",
|
53
|
+
"BUNDLE_BIN_PATH",
|
54
|
+
"BUNDLE_GEMFILE",
|
55
|
+
"GEM_HOME",
|
56
|
+
"GEM_PATH",
|
57
|
+
"MANPATH",
|
58
|
+
"PROMPT",
|
59
|
+
"RUBYLIB",
|
60
|
+
"RUBYOPT",
|
61
|
+
].include? e
|
62
|
+
}
|
63
|
+
|
64
|
+
status = system(env, pdk, :unsetenv_others=>true)
|
65
|
+
|
66
|
+
PDQTest::Emoji.partial_status(status, subcommand)
|
67
|
+
status
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.enable_pdk(pdk_metadata)
|
71
|
+
if ! is_pdk_enabled
|
72
|
+
$logger.info("enabling PDK in metadata.json")
|
73
|
+
metadata = Puppet.module_metadata
|
74
|
+
|
75
|
+
PDK_TAGS.each do |pdk_tag|
|
76
|
+
metadata[pdk_tag] = pdk_metadata[pdk_tag]
|
77
|
+
end
|
78
|
+
PDQTest::Puppet.save_module_metadata(metadata)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def self.is_pdk_enabled
|
83
|
+
Puppet.module_metadata.include?(PDK_VERSION_TAG)
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.amend_sync_yml(data)
|
87
|
+
if File.exist? SYNC_YML
|
88
|
+
sync = YAML.load_file(SYNC_YML)
|
89
|
+
else
|
90
|
+
sync = {}
|
91
|
+
end
|
92
|
+
sync.deep_merge!(data)
|
93
|
+
$logger.info("Updated .sync.yml with #{data}")
|
94
|
+
|
95
|
+
File.open(SYNC_YML, 'w') { |f| YAML.dump(sync, f) }
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# Detection routines for PDQTest 1x files so that we can find and remove them
|
2
|
+
# as part of any PDQTest 2x/PDK upgrade
|
3
|
+
require 'digest/md5'
|
4
|
+
|
5
|
+
module PDQTest
|
6
|
+
module PDQTest1x
|
7
|
+
|
8
|
+
# Urgh... I wish I'd put my own magic marker in these files... then I would
|
9
|
+
# have been able to find them easily(!)
|
10
|
+
# This is a list of known PDQTest integrations and their MD5 sums.
|
11
|
+
# Thankfully I didn't make _too many_ upgrades
|
12
|
+
PDQTEST_FILES = {
|
13
|
+
"Rakefile" => [
|
14
|
+
"3c65c0650e68771854036fbe67fb0f5d",
|
15
|
+
"0254db5d3fc38c67a2c160d7296a24f8"
|
16
|
+
],
|
17
|
+
"spec/spec_helper.rb" => [
|
18
|
+
"8862eca30ed66bc71c1acc7a0da89305",
|
19
|
+
"0db89c9a486df193c0e40095422e19dc",
|
20
|
+
],
|
21
|
+
".rspec" => [
|
22
|
+
"c5f206a3f2387663a941cd9719e4bb00"
|
23
|
+
]
|
24
|
+
}
|
25
|
+
|
26
|
+
# These plus the `pdqtest` gem are the _only_ gems that PDQTest 1x ever used
|
27
|
+
# If we only see these gems and our own, then we are almost certainly safe
|
28
|
+
# to replace the file with the PDK version
|
29
|
+
# List was extracted with some awk-foo
|
30
|
+
# https://gist.github.com/GeoffWilliams/21de190c5f6285b68f777885d92dba72
|
31
|
+
PDQTEST_RUBYGEMS = [
|
32
|
+
/gem 'CFPropertyList'/,
|
33
|
+
/gem 'facter', '>= 1.7.0'/,
|
34
|
+
/gem 'facter', '2.4.6'/,
|
35
|
+
/gem 'facter', '2.5.1'/,
|
36
|
+
/gem 'metadata-json-lint'/,
|
37
|
+
/gem 'puppet'/,
|
38
|
+
/gem 'puppetlabs_spec_helper', '>= 1.0.0'/,
|
39
|
+
/gem 'puppet-lint', '>= 1.0.0'/,
|
40
|
+
/gem 'puppet', puppetversion/,
|
41
|
+
/gem 'puppet-strings'/,
|
42
|
+
/gem 'rake', '~> 10.0'/,
|
43
|
+
/gem 'rspec', '~> 2.0'/,
|
44
|
+
/gem 'rspec-puppet'/,
|
45
|
+
/gem 'rspec-puppet-facts', '1.7.0'/,
|
46
|
+
/gem 'rubocop'/,
|
47
|
+
/gem 'rubocop', '0.47.1'/,
|
48
|
+
/gem 'rubocop', '0.50.0'/,
|
49
|
+
]
|
50
|
+
|
51
|
+
PDQTEST_GEM = /^\s*gem 'pdqtest'/
|
52
|
+
|
53
|
+
# Did PDQTest ever manage this file?
|
54
|
+
def self.was_pdqtest_file(f)
|
55
|
+
[
|
56
|
+
".rspec",
|
57
|
+
"Gemfile",
|
58
|
+
"Rakefile",
|
59
|
+
"spec/fixtures",
|
60
|
+
].include? f
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.is_pdqtest_file(f)
|
64
|
+
detected = false
|
65
|
+
|
66
|
+
if PDQTEST_FILES.include?(f)
|
67
|
+
if File.exist? f
|
68
|
+
# check for known PDQTest files spanning all versions
|
69
|
+
project_md5 = Digest::MD5.file(f).hexdigest
|
70
|
+
if PDQTEST_FILES[f].include?(project_md5)
|
71
|
+
$logger.debug("File at #{f} matches a known PDQTest 1x file")
|
72
|
+
detected = true
|
73
|
+
end
|
74
|
+
else
|
75
|
+
$logger.debug "Missing PDQTest file #{f}"
|
76
|
+
detected = false
|
77
|
+
end
|
78
|
+
elsif f == "Gemfile"
|
79
|
+
if File.exist? f
|
80
|
+
# to detect if PDQTest is the Gemfile, just look for the gem itself
|
81
|
+
if File.readlines(f).grep(PDQTEST_GEM).any?
|
82
|
+
# this project previously used PDQTest, now check to see if there
|
83
|
+
# are any unknown gems in the file
|
84
|
+
$logger.debug("Detected PDQTest 1.x in your Gemfile")
|
85
|
+
detected = true
|
86
|
+
project_gems = File.readlines(f).grep(/^\s*gem /)
|
87
|
+
project_gems.reject { |line|
|
88
|
+
line =~ PDQTEST_GEM
|
89
|
+
}.each { |project_gem|
|
90
|
+
found = false
|
91
|
+
PDQTEST_RUBYGEMS.each { |pdqtest_gem|
|
92
|
+
if project_gem =~ pdqtest_gem
|
93
|
+
$logger.debug "known gem detected: #{project_gem.strip}"
|
94
|
+
found = true
|
95
|
+
end
|
96
|
+
}
|
97
|
+
if ! found
|
98
|
+
$logger.error("unknown gem line in your Gemfile: '#{project_gem.strip}'")
|
99
|
+
detected = false
|
100
|
+
end
|
101
|
+
}
|
102
|
+
end
|
103
|
+
else
|
104
|
+
$logger.debug("missing Gemfile: #{f}")
|
105
|
+
detected = false
|
106
|
+
end
|
107
|
+
else
|
108
|
+
raise("File #{f} was never managed by PDQTest, why are you testing it?")
|
109
|
+
end
|
110
|
+
|
111
|
+
detected
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
end
|