chef-umami 0.0.6 → 0.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 20229674bc6c78285cdb0e431520c7586128e9a5
4
- data.tar.gz: 67e17a4cd7045f7105f7ab83aecdc858e02fcfec
2
+ SHA256:
3
+ metadata.gz: c4b494656c612150234d8aadf2f2b9522ce278bf2a279d7de9c187a2afc63ec5
4
+ data.tar.gz: 790ea90397d73c0defa6c600246d66faa7c4618fd2ec337e091dd37a4779d2d1
5
5
  SHA512:
6
- metadata.gz: 93f9eaf93b7b68f378793c8745c6dda3235240a568093e0d7d82da4873d51a9e24eb08d34e8f3aaaf383c0a9f779c95c6b247c6e911319f22a462f99b91f96d2
7
- data.tar.gz: aec07f530e3fd0bbb618046315845f30927eb3cd8b37e9026202ebf62891f19128d9579f66debd12f5966331a886e07b613b80d96676640b259fe86aea9fd7bd
6
+ metadata.gz: ca092e6173b6b1d8827cf5191145b271341e159e4cb9ecff7ddaa4cf8e795f0ed3d551b49694e8f9ad7c4c4b4c5c2bde5742e571b918b6e3a75115afed39104a
7
+ data.tar.gz: aa896dd76d1e333b8e28144ad837d345228c751551d1ec0681f3f79d6ca36c65c8a1cfd2d677b9fccf74ff9fbd0ea57627c4b0bdd98b8a2a04e506a803ad37b3
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.1.0]
4
+
5
+ Updates to support modern Chef.
6
+
7
+ - Specifically Chef 14.x and ChefDK 3.4.x.
8
+ - Replaces the export/upload mechanism with the push mechanism as it does all that work anyhow.
9
+ - Honestly, the only thing being used by the previous export functionality was the Chef client config. The rest was waste.
10
+ - Updates `Umami::Client` to manage creating and ingesting the config we need.
11
+ - Adds `Umami::Policyfile::PolicyfileLock` as a convenience.
12
+ - Minor updates to address changes in Chef/ChefDK support and methods.
13
+ - Fixes up Rubocop support within Umami as well as that used for testing Umami itself.
14
+
3
15
  ## [0.0.6]
4
16
  - Adds tests.
5
17
  - Updates gem dependencies to use newer versions of Chef and ChefDK.
@@ -13,17 +13,96 @@
13
13
  # limitations under the License.
14
14
 
15
15
  require 'chef'
16
+ require 'chef-umami/policyfile/policyfile_lock'
17
+ require 'tmpdir' # Extends Dir
18
+
19
+ # NOTE: Lifts some code from https://github.com/chef/chef-dk/blob/master/lib/chef-dk/policyfile_services/export_repo.rb
16
20
 
17
21
  module Umami
18
22
  class Client
19
- def initialize
20
- @client = client
23
+ attr_reader :config_path
24
+ attr_reader :policyfile
25
+ attr_reader :staging_dir # Where Umami will stage files.
26
+ def initialize(policyfile = nil)
27
+ @client = client
28
+ @policy_name = nil
29
+ @policyfile = policyfile
30
+ @staging_dir = Dir.mktmpdir('umami-')
31
+ @config_path = client_rb_staging_path
32
+ end
33
+
34
+ def policy_name
35
+ @policy_name ||= Umami::Policyfile::PolicyfileLock.new(policyfile).name
21
36
  end
22
37
 
23
38
  def client
24
39
  @client ||= Chef::Client.new
25
40
  end
26
41
 
42
+ def fake_client_key
43
+ File.join(staging_dir, 'umami.pem')
44
+ end
45
+
46
+ def cp_fake_client_key
47
+ # Create a fake client cert based on a dummy cert we have laying around.
48
+ fake_client_key_src = File.join(File.dirname(__FILE__), %w(.. .. support umami.pem))
49
+ FileUtils.cp(fake_client_key_src, fake_client_key)
50
+ end
51
+
52
+ def dot_chef_staging_dir
53
+ dot_dir = File.join(staging_dir, '.chef')
54
+ FileUtils.mkdir_p(dot_dir)
55
+ dot_dir
56
+ end
57
+
58
+ def client_rb_staging_path
59
+ File.join(dot_chef_staging_dir, 'config.rb')
60
+ end
61
+
62
+ def create_client_rb
63
+ File.open(client_rb_staging_path, 'wb+') do |f|
64
+ f.print(<<~CONFIG)
65
+ ### Chef Client Configuration ###
66
+ # The settings in this file will configure chef to apply the exported policy in
67
+ # this directory. To use it, run:
68
+ #
69
+ # chef-client -z
70
+ #
71
+ policy_name '#{policy_name}'
72
+ policy_group 'local'
73
+ use_policyfile true
74
+ policy_document_native_api true
75
+ chef_server_url 'http://127.0.0.1:8889'
76
+ node_name 'umami-node'
77
+ client_key '#{fake_client_key}'
78
+ # In order to use this repo, you need a version of Chef Client and Chef Zero
79
+ # that supports policyfile "native mode" APIs:
80
+ current_version = Gem::Version.new(Chef::VERSION)
81
+ unless Gem::Requirement.new(">= 12.7").satisfied_by?(current_version)
82
+ puts("!" * 80)
83
+ puts(<<-MESSAGE)
84
+ This Chef Repo requires features introduced in Chef 12.7, but you are using
85
+ Chef \#{Chef::VERSION}. Please upgrade to Chef 12.7 or later.
86
+ MESSAGE
87
+ puts("!" * 80)
88
+ exit!(1)
89
+ end
90
+ CONFIG
91
+ end
92
+ end
93
+
94
+ def build_config
95
+ create_client_rb
96
+ cp_fake_client_key
97
+ end
98
+
99
+ def apply_config!
100
+ build_config
101
+ Chef::Config.from_file(config_path)
102
+ # Define Chef::Config['config_file'] lest Ohai complain.
103
+ Chef::Config['config_file'] = config_path
104
+ end
105
+
27
106
  # Perform the steps required prior to compiling resources, including
28
107
  # running Ohai and building up the node object.
29
108
  def prep
@@ -32,7 +32,7 @@ module Umami
32
32
  r = RuboCop::CLI.new
33
33
  # Don't output to STDOUT.
34
34
  args = [
35
- '--only', 'Style/IndentationWidth,Style/IndentationConsistency',
35
+ '--only', 'Layout/IndentationWidth,Layout/IndentationConsistency',
36
36
  '--auto-correct',
37
37
  '--out', '/dev/null',
38
38
  path
@@ -12,35 +12,35 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- require 'chef-dk/authenticated_http'
16
15
  require 'chef-dk/policyfile/storage_config'
17
- require 'chef-dk/policyfile/uploader'
18
16
  require 'chef-dk/policyfile_lock'
19
17
  require 'chef-dk/ui'
20
18
 
21
19
  module Umami
22
20
  class Policyfile
23
- class Uploader
24
- attr_reader :policyfile_lock_file
25
- def initialize(policyfile_lock_file = nil)
26
- @http_client = http_client
27
- @policyfile_lock_file = policyfile_lock_file
28
- @policyfile_lock = policyfile_lock
29
- @policyfile_uploader = policyfile_uploader
30
- @storage_config = storage_config
31
- @ui = ui
21
+ class PolicyfileLock
22
+ attr_reader :policyfile
23
+ def initialize(policyfile = nil)
24
+ @policyfile = policyfile
25
+ @policyfile_lock = nil
26
+ @storage_config = storage_config
27
+ @ui = ui
32
28
  end
33
29
 
34
30
  def storage_config
35
- @storage_config ||= ChefDK::Policyfile::StorageConfig.new.use_policyfile(policyfile_lock_file)
31
+ @storage_config ||= ChefDK::Policyfile::StorageConfig.new.use_policyfile(policyfile)
36
32
  end
37
33
 
38
34
  def ui
39
35
  @ui ||= ChefDK::UI.new
40
36
  end
41
37
 
38
+ def policyfile_lock_path
39
+ policyfile.gsub(/\.rb$/, '.lock.json')
40
+ end
41
+
42
42
  def policyfile_lock_content
43
- IO.read(policyfile_lock_file)
43
+ IO.read(policyfile_lock_path)
44
44
  end
45
45
 
46
46
  def lock_data
@@ -54,31 +54,8 @@ module Umami
54
54
  ).build_from_lock_data(lock_data)
55
55
  end
56
56
 
57
- def http_client
58
- @http_client ||= ChefDK::AuthenticatedHTTP.new(Chef::Config['chef_server_url'])
59
- end
60
-
61
- def policy_group
62
- Chef::Config['policy_group']
63
- end
64
-
65
- def policy_document_native_api
66
- true
67
- end
68
-
69
- def policyfile_uploader
70
- @policyfile_uploader ||= ChefDK::Policyfile::Uploader.new(
71
- policyfile_lock,
72
- policy_group,
73
- ui: ui,
74
- http_client: http_client,
75
- policy_document_native_api: policy_document_native_api
76
- )
77
- end
78
-
79
- # Push the policy, including all dependent cookbooks.
80
- def upload
81
- policyfile_uploader.upload
57
+ def name
58
+ policyfile_lock.name
82
59
  end
83
60
  end
84
61
  end
@@ -0,0 +1,46 @@
1
+ # Copyright 2017 Bloomberg Finance, L.P.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ require 'chef-dk/policyfile_services/push'
16
+
17
+ module Umami
18
+ class PolicyfileServices
19
+ class Push < ChefDK::PolicyfileServices::Push
20
+ def initialize(policyfile: nil, ui: nil, policy_group: nil, config: nil, root_dir: nil)
21
+ super(policyfile: policyfile, ui: ui, policy_group: policy_group,
22
+ config: config, root_dir: root_dir)
23
+ end
24
+
25
+ # Keep up with the times and force use of the newer API.
26
+ def api_version
27
+ '2'
28
+ end
29
+
30
+ # We'll override the #http_client method to ensure we set the appropriate
31
+ # API version we expect to be used. Chef::Authenticator#request_version
32
+ # will use this to set the appropriate header that Chef Server (Zero)
33
+ # uses to determine how to generate cookbook manifests. Without this, we
34
+ # see issues during the Umami::Client#compile phase where Chef cannot
35
+ # locate recipes within a cookbook and `umami` fails miserably.
36
+ # I spent a week debugging this when trying to update `umami` to support
37
+ # newer Chef libraries. That, too, was miserable.
38
+ def http_client
39
+ @http_client ||= Chef::ServerAPI.new(config.chef_server_url,
40
+ signing_key_filename: config.client_key,
41
+ client_name: config.node_name,
42
+ api_version: api_version)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -18,10 +18,10 @@ require 'chef-umami/client'
18
18
  require 'chef-umami/logger'
19
19
  require 'chef-umami/options'
20
20
  require 'chef-umami/server'
21
- require 'chef-umami/policyfile/exporter'
22
- require 'chef-umami/policyfile/uploader'
21
+ require 'chef-umami/policyfile_services/push'
23
22
  require 'chef-umami/test/unit'
24
23
  require 'chef-umami/test/integration'
24
+ require 'chef-dk/ui'
25
25
 
26
26
  module Umami
27
27
  class Runner
@@ -30,24 +30,36 @@ module Umami
30
30
 
31
31
  attr_reader :cookbook_dir
32
32
  def initialize
33
- @config = config
33
+ @umami_config = umami_config
34
34
  @cookbook_dir = Dir.pwd
35
- @exporter = exporter
36
- @chef_zero_server = chef_zero_server
37
- # If we load the uploader or client now, they won't see the updated
38
- # Chef config!
39
- @uploader = nil
35
+ ## If we load the pusher or client now, they won't see the updated
36
+ ## Chef config!
37
+ @push = nil
40
38
  @chef_client = nil
39
+ @ui = ui
41
40
  end
42
41
 
43
- # A hash of values describing the config. Comprised of command line
42
+ # A hash of values describing the Umami config. Comprised of command line
44
43
  # options. May (in the future) contain options read from a config file.
45
- def config
46
- @config ||= parse_options
44
+ def umami_config
45
+ @umami_config ||= parse_options
46
+ end
47
+
48
+ # Convenience to return the Chef::Config singleton.
49
+ def chef_config
50
+ Chef::Config
51
+ end
52
+
53
+ def ui
54
+ @ui ||= ChefDK::UI.new
47
55
  end
48
56
 
49
57
  def policyfile
50
- config[:policyfile]
58
+ umami_config[:policyfile]
59
+ end
60
+
61
+ def policy_group
62
+ chef_config['policy_group']
51
63
  end
52
64
 
53
65
  # Return the computed policyfile lock name.
@@ -65,12 +77,14 @@ module Umami
65
77
  end
66
78
  end
67
79
 
68
- def exporter
69
- @exporter ||= Umami::Policyfile::Exporter.new(policyfile_lock_file, cookbook_dir, policyfile)
70
- end
71
-
72
- def uploader
73
- @uploader ||= Umami::Policyfile::Uploader.new(policyfile_lock_file)
80
+ def push
81
+ # rubocop:disable Layout/AlignHash
82
+ @push ||= Umami::PolicyfileServices::Push.new(policyfile: policyfile,
83
+ ui: ui,
84
+ policy_group: policy_group,
85
+ config: chef_config,
86
+ root_dir: cookbook_dir)
87
+ # rubocop:enable Layout/AlignHash
74
88
  end
75
89
 
76
90
  def chef_zero_server
@@ -78,31 +92,27 @@ module Umami
78
92
  end
79
93
 
80
94
  def chef_client
81
- @chef_client ||= Umami::Client.new
95
+ @chef_client ||= Umami::Client.new(policyfile)
82
96
  end
83
97
 
84
98
  def run
85
99
  validate_lock_file!
86
- puts "\nExporting the policy, related cookbooks, and a valid client configuration..."
87
- exporter.export
88
- Chef::Config.from_file(exporter.chef_config_file)
100
+ chef_client.apply_config!
89
101
  chef_zero_server.start
90
102
  puts "\nUploading the policy and related cookbooks..."
91
- uploader.upload
103
+ push.run
92
104
  puts "\nExecuting chef-client compile phase..."
93
- # Define Chef::Config['config_file'] lest Ohai complain.
94
- Chef::Config['config_file'] = exporter.chef_config_file
95
105
  chef_client.compile
96
106
  # Build a hash of all the recipes' resources, keyed by the canonical
97
107
  # name of the recipe (i.e. ohai::default).
98
108
  recipe_resources = {}
99
109
  chef_client.resource_collection.each do |resource|
100
110
  canonical_recipe = "#{resource.cookbook_name}::#{resource.recipe_name}"
101
- unless config[:recipes].empty?
111
+ unless umami_config[:recipes].nil? || umami_config[:recipes].empty?
102
112
  # The user has explicitly requested that one or more recipes have
103
113
  # tests written, to the exclusion of others.
104
114
  # ONLY include the recipe if it matches the list.
105
- next unless config[:recipes].include?(canonical_recipe)
115
+ next unless umami_config[:recipes].include?(canonical_recipe)
106
116
  end
107
117
  if recipe_resources.key?(canonical_recipe)
108
118
  recipe_resources[canonical_recipe] << resource
@@ -114,17 +124,17 @@ module Umami
114
124
  # Remove the temporary directory using a naive guard to ensure we're
115
125
  # deleting what we expect.
116
126
  re_export_path = Regexp.new('/tmp/umami')
117
- FileUtils.rm_rf(exporter.export_root) if exporter.export_root.match(re_export_path)
127
+ FileUtils.rm_rf(chef_client.staging_dir) if chef_client.staging_dir.match(re_export_path)
118
128
 
119
- if config[:unit_tests]
129
+ if umami_config[:unit_tests]
120
130
  puts "\nGenerating a set of unit tests..."
121
- unit_tester = Umami::Test::Unit.new(config[:test_root])
131
+ unit_tester = Umami::Test::Unit.new(umami_config[:test_root])
122
132
  unit_tester.generate(recipe_resources)
123
133
  end
124
134
 
125
- if config[:integration_tests]
135
+ if umami_config[:integration_tests]
126
136
  puts "\nGenerating a set of integration tests..."
127
- integration_tester = Umami::Test::Integration.new(config[:test_root])
137
+ integration_tester = Umami::Test::Integration.new(umami_config[:test_root])
128
138
  integration_tester.generate(recipe_resources)
129
139
  end
130
140
  end
@@ -49,6 +49,7 @@ module Umami
49
49
  return if resource.action.include?(:delete)
50
50
  end
51
51
  return if resource.action == :delete
52
+
52
53
  "\n" + send("test_#{resource.declared_type}", resource)
53
54
  end
54
55
 
@@ -60,8 +60,9 @@ module Umami
60
60
 
61
61
  def write_test(resource = nil)
62
62
  state_attrs = [] # Attribute hash to be used with #with()
63
- resource.state.each do |attr, value|
63
+ resource.state_for_resource_reporter.each do |attr, value|
64
64
  next if value.nil? || (value.respond_to?(:empty) && value.empty?)
65
+
65
66
  if value.is_a? String
66
67
  value = value.gsub("'", "\\\\'") # Escape any single quotes in the value.
67
68
  end
@@ -90,6 +91,7 @@ module Umami
90
91
  (cookbook, recipe) = canonical_recipe.split('::')
91
92
  # Only write unit tests for the cookbook we're in.
92
93
  next unless cookbook == tested_cookbook
94
+
93
95
  content = [preamble(cookbook, recipe)]
94
96
  resources.each do |resource|
95
97
  content << write_test(resource)
@@ -13,5 +13,5 @@
13
13
  # limitations under the License.
14
14
 
15
15
  module Umami
16
- VERSION = '0.0.6'.freeze
16
+ VERSION = '0.1.0'.freeze
17
17
  end
@@ -18,17 +18,16 @@ RSpec.describe Umami::Runner do
18
18
  it 'initiates a Umami::Runner object' do
19
19
  runner = Umami::Runner.new
20
20
  expect(runner).to be_an_instance_of(Umami::Runner)
21
- expect(runner.exporter).to be_an_instance_of(Umami::Policyfile::Exporter)
22
21
  expect(runner.chef_zero_server).to be_an_instance_of(Umami::Server)
23
22
  end
24
23
 
25
24
  context 'with no options provided' do
26
25
  it 'sets proper defaults' do
27
26
  runner = Umami::Runner.new
28
- expect(runner.config[:integration_tests]).to be true
27
+ expect(runner.umami_config[:integration_tests]).to be true
29
28
  expect(runner.policyfile).to eq("Policyfile.rb")
30
- expect(runner.config[:test_root]).to eq("spec")
31
- expect(runner.config[:unit_tests]).to be true
29
+ expect(runner.umami_config[:test_root]).to eq("spec")
30
+ expect(runner.umami_config[:unit_tests]).to be true
32
31
  end
33
32
  end
34
33
 
@@ -41,10 +40,10 @@ RSpec.describe Umami::Runner do
41
40
  my_argv.flatten!
42
41
  stub_const("ARGV", my_argv)
43
42
  runner = Umami::Runner.new
44
- expect(runner.config[:integration_tests]).to be false
43
+ expect(runner.umami_config[:integration_tests]).to be false
45
44
  expect(runner.policyfile).to eq("test_policy.rb")
46
- expect(runner.config[:test_root]).to eq("dust_spec")
47
- expect(runner.config[:unit_tests]).to be false
45
+ expect(runner.umami_config[:test_root]).to eq("dust_spec")
46
+ expect(runner.umami_config[:unit_tests]).to be false
48
47
  end
49
48
  end
50
49
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chef-umami
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Frantz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-26 00:00:00.000000000 Z
11
+ date: 2019-05-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef
@@ -16,42 +16,42 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '13.0'
19
+ version: '14'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '13.0'
26
+ version: '14'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: chef-dk
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '2.5'
33
+ version: '3'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '2.5'
40
+ version: '3'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rubocop
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0.47'
47
+ version: '0.69'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '0.47'
54
+ version: '0.69'
55
55
  description: A tool to generate unit/integration tests for Chef cookbooks and policy
56
56
  files.
57
57
  email:
@@ -76,8 +76,8 @@ files:
76
76
  - lib/chef-umami/logger.rb
77
77
  - lib/chef-umami/options.rb
78
78
  - lib/chef-umami/policyfile.rb
79
- - lib/chef-umami/policyfile/exporter.rb
80
- - lib/chef-umami/policyfile/uploader.rb
79
+ - lib/chef-umami/policyfile/policyfile_lock.rb
80
+ - lib/chef-umami/policyfile_services/push.rb
81
81
  - lib/chef-umami/runner.rb
82
82
  - lib/chef-umami/server.rb
83
83
  - lib/chef-umami/test.rb
@@ -107,7 +107,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
107
107
  version: '0'
108
108
  requirements: []
109
109
  rubyforge_project:
110
- rubygems_version: 2.6.11
110
+ rubygems_version: 2.7.9
111
111
  signing_key:
112
112
  specification_version: 4
113
113
  summary: A tool to generate unit/integration tests for Chef cookbooks and policy files.
@@ -1,101 +0,0 @@
1
- # Copyright 2017 Bloomberg Finance, L.P.
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
-
15
- require 'chef-dk/policyfile_services/install'
16
- require 'chef-dk/policyfile_services/export_repo'
17
- require 'chef-dk/ui'
18
- require 'tmpdir' # Extends Dir
19
-
20
- module Umami
21
- class Policyfile
22
- class Exporter
23
- attr_reader :chef_config_file
24
- attr_reader :cookbook_dir
25
- attr_reader :export_root
26
- attr_reader :export_path
27
- attr_reader :policyfile
28
- attr_accessor :policyfile_lock_file
29
-
30
- def initialize(policyfile_lock_file = nil, cookbook_dir = nil, policyfile = nil)
31
- @policyfile = policyfile
32
- @export_root = Dir.mktmpdir('umami-')
33
- # We need the target dir named the same as the source dir so that `chef` commands
34
- # work as happily programatically as they would via the command line.
35
- # This is because the commands assume they're being run from within a cookbook
36
- # directory.
37
- @export_path = File.join(export_root, cookbook_dir)
38
- @chef_config_file = "#{export_path}/.chef/config.rb"
39
- end
40
-
41
- def ui
42
- @ui ||= ChefDK::UI.new
43
- end
44
-
45
- # Execute `chef install` to ensure we get a fresh, clean Policyfile lock
46
- # file on each run.
47
- def install_policy
48
- puts "Generating a new Policyfile from '#{policyfile}'..."
49
- install_service = ChefDK::PolicyfileServices::Install.new(
50
- policyfile: policyfile,
51
- ui: ui
52
- )
53
- @policyfile_lock_file = install_service.storage_config.policyfile_lock_filename
54
- install_service.run
55
- end
56
-
57
- def fake_client_key
58
- "#{export_path}/umami.pem"
59
- end
60
-
61
- def cp_fake_client_key
62
- # Create a fake client cert based on a dummy cert we have laying around.
63
- fake_client_key_src = File.join(File.dirname(__FILE__), %w(.. .. .. support umami.pem))
64
- FileUtils.cp(fake_client_key_src, fake_client_key)
65
- end
66
-
67
- def update_chef_config
68
- File.open(chef_config_file, 'a') do |f|
69
- f.puts "chef_server_url 'http://127.0.0.1:8889'"
70
- f.puts "cookbook_path ['#{export_path}/cookbook_artifacts']"
71
- f.puts "client_key '#{fake_client_key}'"
72
- f.puts "node_name 'umami-node'"
73
- end
74
- end
75
-
76
- # Export the cookbook and prepare a chef-zero-compatible directory.
77
- # We'll use this as a temporary launch pad for things, as needed, akin
78
- # to test-kitchen's sandbox.
79
- def export
80
- install_policy
81
- export_service = ChefDK::PolicyfileServices::ExportRepo.new(
82
- policyfile: policyfile_lock_file,
83
- export_dir: export_path
84
- )
85
- begin
86
- export_service.run
87
- rescue ChefDK::PolicyfileExportRepoError => e
88
- puts "\nFAILED TO EXPORT POLICYFILE: #{e.message} (#{e.class})"
89
- puts "CAUSE: #{e.cause}"
90
- puts 'BACKTRACE:'
91
- e.backtrace.each do |line|
92
- puts "\t#{line}"
93
- end
94
- exit(1)
95
- end
96
- cp_fake_client_key
97
- update_chef_config
98
- end
99
- end
100
- end
101
- end