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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +9 -3
  3. data/doc/acceptance_tests.md +100 -22
  4. data/doc/caching.md +5 -1
  5. data/doc/development.md +16 -5
  6. data/doc/emoji.md +20 -9
  7. data/doc/enabling_testing.md +15 -3
  8. data/doc/examples.md +25 -6
  9. data/doc/hiera.md +30 -11
  10. data/doc/installation.md +59 -8
  11. data/doc/pdk.md +334 -0
  12. data/doc/puppet_facts.md +45 -3
  13. data/doc/puppet_module_dependencies.md +34 -16
  14. data/doc/running_tests.md +35 -15
  15. data/doc/test_generation.md +11 -19
  16. data/doc/tips_and_tricks.md +17 -8
  17. data/doc/troubleshooting.md +19 -8
  18. data/doc/upgrading.md +125 -6
  19. data/doc/windows.md +51 -0
  20. data/docker_images/centos/Dockerfile +4 -3
  21. data/docker_images/centos/Makefile +1 -1
  22. data/docker_images/ubuntu/Dockerfile +3 -3
  23. data/docker_images/windows/Dockerfile +26 -0
  24. data/docker_images/windows/make.ps1 +2 -0
  25. data/exe/pdqtest +73 -28
  26. data/lib/pdqtest/core.rb +1 -1
  27. data/lib/pdqtest/docker.rb +143 -51
  28. data/lib/pdqtest/emoji.rb +33 -7
  29. data/lib/pdqtest/fastcheck.rb +19 -0
  30. data/lib/pdqtest/instance.rb +16 -15
  31. data/lib/pdqtest/logger.rb +35 -0
  32. data/lib/pdqtest/pdk.rb +98 -0
  33. data/lib/pdqtest/pdqtest1x.rb +115 -0
  34. data/lib/pdqtest/puppet.rb +277 -134
  35. data/lib/pdqtest/skeleton.rb +119 -39
  36. data/lib/pdqtest/upgrade.rb +42 -42
  37. data/lib/pdqtest/util.rb +82 -2
  38. data/lib/pdqtest/version.rb +1 -2
  39. data/pdqtest.gemspec +8 -13
  40. data/res/{skeleton → acceptance}/init.bats +0 -0
  41. data/res/{skeleton → acceptance}/init__before.bats +0 -0
  42. data/res/{skeleton → acceptance}/init__setup.sh +0 -0
  43. data/res/skeleton/.puppet-lint.rc +5 -0
  44. data/res/skeleton/{dot_travis.yml → .travis.yml} +0 -0
  45. data/res/skeleton/Makefile +20 -5
  46. data/res/skeleton/make.ps1 +66 -0
  47. data/res/skeleton/spec/fixtures/hiera.yaml +13 -0
  48. data/res/skeleton/spec/fixtures/hieradata/test.yaml +11 -0
  49. data/res/templates/examples_init.pp.erb +1 -1
  50. metadata +47 -115
  51. data/lib/pdqtest/lint.rb +0 -31
  52. data/lib/pdqtest/rspec.rb +0 -69
  53. data/lib/pdqtest/syntax.rb +0 -20
  54. data/res/skeleton/Gemfile +0 -7
  55. data/res/skeleton/Rakefile +0 -3
  56. data/res/skeleton/dot_gitignore +0 -9
  57. data/res/skeleton/dot_rspec +0 -2
  58. data/res/skeleton/hiera.yaml +0 -7
  59. data/res/skeleton/spec_helper.rb +0 -4
  60. data/res/skeleton/test.yaml +0 -3
@@ -6,23 +6,101 @@ module PDQTest
6
6
  OUT = 0
7
7
  ERR = 1
8
8
  STATUS = 2
9
- ENV='export TERM=xterm LC_ALL=C PATH=/usr/local/bats/bin:/opt/puppetlabs/puppet/bin:$PATH;'
9
+ REAL_CMD = 3
10
10
  IMAGES = {
11
- :DEFAULT => 'declarativesystems/pdqtest-1x-centos:2019-04-01-0',
12
- :UBUNTU => 'declarativesystems/pdqtest-ubuntu:2018-08-29-0',
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
- HIERA_YAML_CONTAINER = '/etc/puppetlabs/puppet/hiera.yaml'
15
- HIERA_YAML_HOST = '/spec/fixtures/hiera.yaml'
16
- HIERA_DIR = '/spec/fixtures/hieradata'
17
- YUM_CACHE_CONTAINER = "/var/cache/yum"
18
- YUM_CACHE_HOST = "#{Util::app_dir_expanded}/cache/yum"
19
-
20
- def self.wrap_cmd(cmd)
21
- ['bash', '-c', "#{ENV} #{cmd}"]
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
- container.exec(wrap_cmd(cmd), tty: true)
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
- Escort::Logger.output.puts "Windows acceptance testing not supported yet... any ideas?"
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
- def self.new_container(test_dir, image_name, privileged)
64
- pwd = Dir.pwd
65
- hiera_yaml_host = File.join(pwd, HIERA_YAML_HOST)
66
- hiera_dir = File.join(pwd, HIERA_DIR)
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 ! Dir.exists?(YUM_CACHE_HOST)
80
- FileUtils.mkdir_p(YUM_CACHE_HOST)
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
- # hiera.yaml *must* exist on the host or we will get errors from Docker
84
- if ! File.exists?(hiera_yaml_host)
85
- File.write(hiera_yaml_host, '# hiera configuration for testing')
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
- Escort::Logger.output << l
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
- Escort::Logger.error << l
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(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
- Escort::Logger.output.puts message
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
- Escort::Logger.output.puts lable_string + emoji_pass
49
+ $logger.info lable_string + emoji_pass
24
50
  else
25
51
  # boom! crappy code
26
- Escort::Logger.error.error lable_string + emoji_fail
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, "😬", "💣", label)
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, "😎", "💩", 'Overall')
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
@@ -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
- Escort::Logger.output.puts "No acceptance tests found, annotate examples with #{PDQTest::Puppet::MAGIC_MARKER} to make some"
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
- Escort::Logger.output.puts "Acceptance test on #{test_platforms}..."
56
+ $logger.info "Acceptance test on #{test_platforms}..."
58
57
  test_platforms.each { |image_name|
59
- Escort::Logger.output.puts "--- start test with #{image_name} ---"
60
- @@active_container = PDQTest::Docker::new_container(TEST_DIR, image_name, @@privileged)
61
- Escort::Logger.output.puts "alive, running tests"
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
- Escort::Logger.output.puts "finished build, container #{@@active_container.id} left on system"
66
- Escort::Logger.output.puts " docker exec -ti #{@@active_container.id} bash "
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
- Escort::Logger.output.puts "--- end test with #{image_name} (status: #{status})---"
71
+ $logger.info "--- end test with #{image_name} (status: #{status})---"
73
72
  }
74
73
  end
75
- Escort::Logger.output.puts "overall acceptance test status=#{status}"
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
- Escort::Logger.output.puts "Opening a shell in #{image_name}"
84
- @@active_container = PDQTest::Docker::new_container(TEST_DIR, image_name, @@privileged)
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} bash")
97
+ system("docker exec -ti #{@@active_container.id} #{Util.shell}")
97
98
  if @@keep_container
98
- Escort::Logger.output.puts "finished build, container #{@@active_container.id} left on system"
99
- Escort::Logger.output.puts " docker exec -ti #{@@active_container.id} bash "
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
@@ -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