inspec 1.47.0 → 1.48.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
2
  SHA1:
3
- metadata.gz: 73d4de764766d6ce02f52597d9cdd3d3c5f962bf
4
- data.tar.gz: 0aaec0745ed380804d6bd333711054eab7c505ea
3
+ metadata.gz: '012308b85533b4379b4dae9b2d6bb956e4716dea'
4
+ data.tar.gz: a621d9a79814290988494ec07da9bad51057f33b
5
5
  SHA512:
6
- metadata.gz: 93d630d3408a4c34b13504dbdc6cb07e0de5a672525db739bb7e54eff8d0971b09838ae5c14169362d3a98b58ae27af1feffb0e443733e5e92ce948786494f95
7
- data.tar.gz: 49a27fd5dbe847483d31fa7d5ec357c91008596f47042d531c81c290b332b542d7caf90e56a9ae04c572b9d39cc913dda87565ec82a405aeef92e7c3d87df425
6
+ metadata.gz: 93b4c27033acdb1e4559c48940d0c73b1d94b3b20e109ed6a3b2ecf57908143b8c133717790ff273253aa580d893ee3ecd9a75e1129d9125bbc64f2c7c2d8397
7
+ data.tar.gz: 8eb7fe1e83c0bba17b5ef763015c83be4952c622e80a80af68a702d829d78bed389864157cdee86352f4ae166213ddc17b4fd5fbd5455719c89c8efc3de77a30
@@ -1,29 +1,47 @@
1
1
  # Change Log
2
2
  <!-- usage documentation: http://expeditor-docs.es.chef.io/configuration/changelog/ -->
3
- <!-- latest_release 1.47.0 -->
4
- ## [v1.47.0](https://github.com/chef/inspec/tree/v1.47.0) (2017-12-04)
3
+ <!-- latest_release 1.48.0 -->
4
+ ## [v1.48.0](https://github.com/chef/inspec/tree/v1.48.0) (2017-12-07)
5
5
 
6
- #### New Features
7
- - Enable caching for backend calls [#2309](https://github.com/chef/inspec/pull/2309) ([jquick](https://github.com/jquick))
6
+ #### Merged Pull Requests
7
+ - Fix changelog categories, bump minor version for release [#2381](https://github.com/chef/inspec/pull/2381) ([adamleff](https://github.com/adamleff))
8
8
  <!-- latest_release -->
9
9
 
10
- <!-- release_rollup since=1.46.2 -->
11
- ### Changes since 1.46.2 release
10
+ <!-- release_rollup since=1.47.0 -->
11
+ ### Changes since 1.47.0 release
12
12
 
13
- #### New Features
14
- - Enable caching for backend calls [#2309](https://github.com/chef/inspec/pull/2309) ([jquick](https://github.com/jquick)) <!-- 1.47.0 -->
13
+ #### Enhancements
14
+ - Allow crontab resource to read crontab at user specified paths. [#2328](https://github.com/chef/inspec/pull/2328) ([miah](https://github.com/miah)) <!-- 1.47.7 -->
15
+ - Update default cli options to be uniq per command type [#2378](https://github.com/chef/inspec/pull/2378) ([jquick](https://github.com/jquick)) <!-- 1.47.6 -->
16
+
17
+ #### Bug Fixes
18
+ - Allow `inspec check` to ignore `only_if` [#2250](https://github.com/chef/inspec/pull/2250) ([jerryaldrichiii](https://github.com/jerryaldrichiii)) <!-- 1.47.2 -->
19
+ - Remove rainbow dependency, fix duplicate rake gem [#2374](https://github.com/chef/inspec/pull/2374) ([adamleff](https://github.com/adamleff)) <!-- 1.47.8 -->
20
+ - Resolve merge issue with json-config vs thor defaults [#2377](https://github.com/chef/inspec/pull/2377) ([jquick](https://github.com/jquick)) <!-- 1.47.5 -->
21
+ - Update rspec cli control summary to not uniq fails/skips [#2362](https://github.com/chef/inspec/pull/2362) ([jquick](https://github.com/jquick)) <!-- 1.47.1 -->
15
22
 
16
23
  #### Merged Pull Requests
17
- - docker_image resource: properly handle registries in image strings [#2356](https://github.com/chef/inspec/pull/2356) ([adamleff](https://github.com/adamleff)) <!-- 1.46.5 -->
24
+ - Fix changelog categories, bump minor version for release [#2381](https://github.com/chef/inspec/pull/2381) ([adamleff](https://github.com/adamleff)) <!-- 1.48.0 -->
25
+ - Fix inspec appveyor test with the new local train transport [#2376](https://github.com/chef/inspec/pull/2376) ([jquick](https://github.com/jquick)) <!-- 1.47.4 -->
26
+ - Update command resource to check for mock backend [#2353](https://github.com/chef/inspec/pull/2353) ([jquick](https://github.com/jquick)) <!-- 1.47.3 -->
27
+ <!-- release_rollup -->
28
+
29
+ <!-- latest_stable_release -->
30
+ ## [v1.47.0](https://github.com/chef/inspec/tree/v1.47.0) (2017-12-04)
31
+
32
+ #### New Features
33
+ - Enable caching for backend calls [#2309](https://github.com/chef/inspec/pull/2309) ([jquick](https://github.com/jquick))
18
34
 
19
35
  #### Bug Fixes
20
- - security_policy resource: use PID for filename instead of random [#2368](https://github.com/chef/inspec/pull/2368) ([jquick](https://github.com/jquick)) <!-- 1.46.7 -->
21
- - key_rsa resource: fix inline shell documentation help, wrong resource name used in examples [#2364](https://github.com/chef/inspec/pull/2364) ([eramoto](https://github.com/eramoto)) <!-- 1.46.6 -->
22
- - json resource: ensure params is not nil in event of read/parse failure [#2354](https://github.com/chef/inspec/pull/2354) ([adamleff](https://github.com/adamleff)) <!-- 1.46.4 -->
23
- - Unique export file for security policy resource [#2350](https://github.com/chef/inspec/pull/2350) ([jquick](https://github.com/jquick)) <!-- 1.46.3 -->
24
- <!-- release_rollup -->
36
+ - Unique export file for security policy resource [#2350](https://github.com/chef/inspec/pull/2350) ([jquick](https://github.com/jquick))
37
+ - json resource: ensure params is not nil in event of read/parse failure [#2354](https://github.com/chef/inspec/pull/2354) ([adamleff](https://github.com/adamleff))
38
+ - key_rsa resource: fix inline shell documentation help, wrong resource name used in examples [#2364](https://github.com/chef/inspec/pull/2364) ([eramoto](https://github.com/eramoto))
39
+ - security_policy resource: use PID for filename instead of random [#2368](https://github.com/chef/inspec/pull/2368) ([jquick](https://github.com/jquick))
25
40
 
41
+ #### Merged Pull Requests
42
+ - docker_image resource: properly handle registries in image strings [#2356](https://github.com/chef/inspec/pull/2356) ([adamleff](https://github.com/adamleff))
26
43
  <!-- latest_stable_release -->
44
+
27
45
  ## [v1.46.2](https://github.com/chef/inspec/tree/v1.46.2) (2017-11-29)
28
46
 
29
47
  #### Enhancements
@@ -36,7 +54,6 @@
36
54
  - file resource: fix NilClass error when using advanced windows permissions [#2344](https://github.com/chef/inspec/pull/2344) ([TheLonelyGhost](https://github.com/TheLonelyGhost))
37
55
  - wmi resource: properly escape quotes in WMI query [#2342](https://github.com/chef/inspec/pull/2342) ([TheLonelyGhost](https://github.com/TheLonelyGhost))
38
56
  - Allow skipping/failing resources in FilterTable [#2349](https://github.com/chef/inspec/pull/2349) ([jerryaldrichiii](https://github.com/jerryaldrichiii))
39
- <!-- latest_stable_release -->
40
57
 
41
58
  ## [v1.45.13](https://github.com/chef/inspec/tree/v1.45.13) (2017-11-21)
42
59
 
data/Gemfile CHANGED
@@ -12,7 +12,7 @@ gem 'ffi', '>= 1.9.14'
12
12
  group :test do
13
13
  gem 'bundler', '~> 1.5'
14
14
  gem 'minitest', '~> 5.5'
15
- gem 'rake', '~> 10'
15
+ gem 'rake', '>= 10'
16
16
  gem 'rubocop', '= 0.49.1'
17
17
  gem 'simplecov', '~> 0.10'
18
18
  gem 'concurrent-ruby', '~> 0.9'
@@ -26,10 +26,9 @@ Gem::Specification.new do |spec|
26
26
 
27
27
  spec.required_ruby_version = '>= 2.3'
28
28
 
29
- spec.add_dependency 'train', '~> 0.30'
29
+ spec.add_dependency 'train', '~> 0.31', '>= 0.31.1'
30
30
  spec.add_dependency 'thor', '~> 0.19'
31
31
  spec.add_dependency 'json', '>= 1.8', '< 3.0'
32
- spec.add_dependency 'rainbow', '~> 2'
33
32
  spec.add_dependency 'method_source', '~> 0.8'
34
33
  spec.add_dependency 'rubyzip', '~> 1.1'
35
34
  spec.add_dependency 'rspec', '~> 3'
@@ -40,7 +40,7 @@ module Inspec
40
40
  #
41
41
  # @param [Hash] config for the transport backend
42
42
  # @return [TransportBackend] enriched transport instance
43
- def self.create(config)
43
+ def self.create(config) # rubocop:disable Metrics/AbcSize
44
44
  conf = Train.target_config(config)
45
45
  name = Train.validate_backend(conf)
46
46
  transport = Train.create(name, conf)
@@ -56,12 +56,15 @@ module Inspec
56
56
  # Set caching settings. We always want to enable caching for
57
57
  # the Mock transport for testing.
58
58
  if config[:backend_cache] || config[:backend] == :mock
59
+ Inspec::Log.debug 'Option backend_cache is enabled'
59
60
  connection.enable_cache(:file)
60
61
  connection.enable_cache(:command)
61
62
  elsif config[:debug_shell]
63
+ Inspec::Log.debug 'Option backend_cache is disabled'
62
64
  connection.disable_cache(:file)
63
65
  connection.disable_cache(:command)
64
66
  else
67
+ Inspec::Log.debug 'Option backend_cache is disabled'
65
68
  connection.disable_cache(:command)
66
69
  end
67
70
 
@@ -59,18 +59,28 @@ module Inspec
59
59
  desc: 'A list of controls to run. Ignore all other tests.'
60
60
  option :format, type: :string,
61
61
  desc: 'Which formatter to use: cli, progress, documentation, json, json-min, junit'
62
- option :color, type: :boolean, default: true,
62
+ option :color, type: :boolean,
63
63
  desc: 'Use colors in output.'
64
64
  option :attrs, type: :array,
65
65
  desc: 'Load attributes file (experimental)'
66
66
  option :cache, type: :string,
67
67
  desc: 'Use the given path for caching dependencies. (default: ~/.inspec/cache)'
68
- option :create_lockfile, type: :boolean, default: true,
68
+ option :create_lockfile, type: :boolean,
69
69
  desc: 'Write out a lockfile based on this execution (unless one already exists)'
70
- option :backend_cache, type: :boolean, default: false,
70
+ option :backend_cache, type: :boolean,
71
71
  desc: 'Allow caching for backend command output.'
72
72
  end
73
73
 
74
+ def self.default_options
75
+ {
76
+ exec: {
77
+ 'color' => true,
78
+ 'create_lockfile' => true,
79
+ 'backend_cache' => false,
80
+ },
81
+ }
82
+ end
83
+
74
84
  private
75
85
 
76
86
  # helper method to run tests
@@ -101,8 +111,8 @@ module Inspec
101
111
  puts
102
112
  end
103
113
 
104
- def opts
105
- o = merged_opts
114
+ def opts(type = nil)
115
+ o = merged_opts(type)
106
116
 
107
117
  # Due to limitations in Thor it is not possible to set an argument to be
108
118
  # both optional and its value to be mandatory. E.g. the user supplying
@@ -118,9 +128,18 @@ module Inspec
118
128
  o
119
129
  end
120
130
 
121
- def merged_opts
122
- # argv overrides json
123
- Thor::CoreExt::HashWithIndifferentAccess.new(options_json.merge(options))
131
+ def merged_opts(type = nil)
132
+ opts = {}
133
+
134
+ # start with default options if we have any
135
+ opts = BaseCLI.default_options[type] unless type.nil?
136
+
137
+ # merge in any options from json-config
138
+ opts.merge!(options_json)
139
+
140
+ # merge in any options defined via thor
141
+ opts.merge!(options)
142
+ Thor::CoreExt::HashWithIndifferentAccess.new(opts)
124
143
  end
125
144
 
126
145
  def options_json
@@ -62,6 +62,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
62
62
  o = opts.dup
63
63
  o[:ignore_supports] = true # we check for integrity only
64
64
  o[:backend] = Inspec::Backend.create(target: 'mock://')
65
+ o[:check_mode] = true
65
66
 
66
67
  # run check
67
68
  profile = Inspec::Profile.for_target(path, o)
@@ -151,8 +152,8 @@ class Inspec::InspecCLI < Inspec::BaseCLI # rubocop:disable Metrics/ClassLength
151
152
  exec_options
152
153
  def exec(*targets)
153
154
  diagnose
154
- configure_logger(opts)
155
- o = opts.dup
155
+ o = opts(:exec).dup
156
+ configure_logger(o)
156
157
 
157
158
  # run tests
158
159
  run_tests(targets, o)
@@ -13,7 +13,7 @@ module Inspec
13
13
  # as the basic DSL of the control files (describe, control, title,
14
14
  # etc).
15
15
  #
16
- class ControlEvalContext
16
+ class ControlEvalContext # rubocop:disable Metrics/ClassLength
17
17
  # Create the context for controls. This includes all components of the DSL,
18
18
  # including matchers and resources.
19
19
  #
@@ -47,12 +47,13 @@ module Inspec
47
47
 
48
48
  attr_accessor :skip_file
49
49
 
50
- def initialize(backend, conf, dependencies, require_loader)
50
+ def initialize(backend, conf, dependencies, require_loader, skip_only_if_eval)
51
51
  @backend = backend
52
52
  @conf = conf
53
53
  @dependencies = dependencies
54
54
  @require_loader = require_loader
55
55
  @skip_file = false
56
+ @skip_only_if_eval = skip_only_if_eval
56
57
  end
57
58
 
58
59
  define_method :title do |arg|
@@ -70,6 +71,7 @@ module Inspec
70
71
  define_method :control do |*args, &block|
71
72
  id = args[0]
72
73
  opts = args[1] || {}
74
+ opts[:skip_only_if_eval] = @skip_only_if_eval
73
75
  register_control(rule_class.new(id, profile_id, opts, &block))
74
76
  end
75
77
 
@@ -133,7 +135,10 @@ module Inspec
133
135
 
134
136
  define_method :only_if do |&block|
135
137
  return unless block
136
- return if @skip_file == true || block.yield == true
138
+ return if @skip_file == true
139
+ return if @skip_only_if_eval == true
140
+
141
+ return if block.yield == true
137
142
 
138
143
  # Apply `set_skip_rule` for other rules in the same file
139
144
  profile_context_owner.rules.values.each do |r|
@@ -78,7 +78,7 @@ module Inspec
78
78
  for_fetcher(fetcher, opts)
79
79
  end
80
80
 
81
- attr_reader :source_reader, :backend, :runner_context
81
+ attr_reader :source_reader, :backend, :runner_context, :check_mode
82
82
  def_delegator :@source_reader, :tests
83
83
  def_delegator :@source_reader, :libraries
84
84
  def_delegator :@source_reader, :metadata
@@ -96,6 +96,7 @@ module Inspec
96
96
  @attr_values = options[:attributes]
97
97
  @tests_collected = false
98
98
  @libraries_loaded = false
99
+ @check_mode = options[:check_mode] || false
99
100
  Metadata.finalize(@source_reader.metadata, @profile_id, options)
100
101
 
101
102
  # if a backend has already been created, clone it so each profile has its own unique backend object
@@ -14,7 +14,8 @@ module Inspec
14
14
  class ProfileContext # rubocop:disable Metrics/ClassLength
15
15
  def self.for_profile(profile, backend, attributes)
16
16
  new(profile.name, backend, { 'profile' => profile,
17
- 'attributes' => attributes })
17
+ 'attributes' => attributes,
18
+ 'check_mode' => profile.check_mode })
18
19
  end
19
20
 
20
21
  attr_reader :attributes, :profile_id, :resource_registry, :backend
@@ -27,6 +28,7 @@ module Inspec
27
28
  @profile_id = profile_id
28
29
  @backend = backend
29
30
  @conf = conf.dup
31
+ @skip_only_if_eval = @conf['check_mode']
30
32
  @rules = {}
31
33
  @control_subcontexts = []
32
34
  @lib_subcontexts = []
@@ -53,7 +55,7 @@ module Inspec
53
55
  def control_eval_context
54
56
  @control_eval_context ||= begin
55
57
  ctx = Inspec::ControlEvalContext.create(self, to_resources_dsl)
56
- ctx.new(@backend, @conf, dependencies, @require_loader)
58
+ ctx.new(@backend, @conf, dependencies, @require_loader, @skip_only_if_eval)
57
59
  end
58
60
  end
59
61
 
@@ -776,8 +776,8 @@ class InspecRspecCli < InspecRspecJson # rubocop:disable Metrics/ClassLength
776
776
  examples[0][:message].to_s
777
777
  else
778
778
  [
779
- !fails.empty? ? "#{fails.uniq.length} failed" : nil,
780
- !skips.empty? ? "#{skips.uniq.length} skipped" : nil,
779
+ !fails.empty? ? "#{fails.length} failed" : nil,
780
+ !skips.empty? ? "#{skips.length} skipped" : nil,
781
781
  ].compact.join(' ')
782
782
  end
783
783
 
@@ -29,7 +29,7 @@ module Inspec
29
29
  @resource_dsl
30
30
  end
31
31
 
32
- def initialize(id, profile_id, _opts, &block)
32
+ def initialize(id, profile_id, opts, &block)
33
33
  @impact = nil
34
34
  @title = nil
35
35
  @desc = nil
@@ -44,6 +44,7 @@ module Inspec
44
44
  @__checks = []
45
45
  @__skip_rule = nil
46
46
  @__merge_count = 0
47
+ @__skip_only_if_eval = opts[:skip_only_if_eval]
47
48
 
48
49
  # evaluate the given definition
49
50
  instance_eval(&block) if block_given?
@@ -104,6 +105,8 @@ module Inspec
104
105
  # @return [nil]
105
106
  def only_if
106
107
  return unless block_given?
108
+ return if @__skip_only_if_eval == true
109
+
107
110
  @__skip_rule ||= !yield
108
111
  end
109
112
 
@@ -4,5 +4,5 @@
4
4
  # author: Christoph Hartmann
5
5
 
6
6
  module Inspec
7
- VERSION = '1.47.0'
7
+ VERSION = '1.48.0'
8
8
  end
@@ -45,9 +45,9 @@ module Inspec::Resources
45
45
  result.exit_status.to_i
46
46
  end
47
47
 
48
- def exist?
48
+ def exist? # rubocop:disable Metrics/AbcSize
49
49
  # silent for mock resources
50
- return false if inspec.os.name.nil?
50
+ return false if inspec.os.name.nil? || inspec.os.name == 'mock'
51
51
 
52
52
  if inspec.os.linux?
53
53
  res = inspec.backend.run_command("bash -c 'type \"#{@command}\"'")
@@ -56,7 +56,7 @@ module Inspec::Resources
56
56
  elsif inspec.os.unix?
57
57
  res = inspec.backend.run_command("type \"#{@command}\"")
58
58
  else
59
- warn "`command(#{@command}).exist?` is not suported on your OS: #{inspec.os[:name]}"
59
+ warn "`command(#{@command}).exist?` is not supported on your OS: #{inspec.os[:name]}"
60
60
  return false
61
61
  end
62
62
  res.exit_status.to_i == 0
@@ -1,15 +1,14 @@
1
1
  # encoding: utf-8
2
- # author: Adam Leff
3
2
 
4
3
  require 'utils/parser'
5
4
  require 'utils/filter'
6
5
 
7
6
  module Inspec::Resources
8
- class Crontab < Inspec.resource(1)
7
+ class Crontab < Inspec.resource(1) # rubocop:disable Metrics/ClassLength
9
8
  name 'crontab'
10
9
  desc 'Use the crontab InSpec audit resource to test the contents of the crontab for a given user which contains information about scheduled tasks owned by that user.'
11
10
  example "
12
- describe crontab('root') do
11
+ describe crontab(user: 'root') do
13
12
  its('commands') { should include '/path/to/some/script' }
14
13
  end
15
14
 
@@ -25,51 +24,40 @@ module Inspec::Resources
25
24
  describe crontab.where { command =~ /a partial command string/ } do
26
25
  its('entries.length') { should cmp 1 }
27
26
  end
27
+
28
+ describe crontab(path: '/etc/cron.d/some_crontab') do
29
+ its('commands') { should include '/path/to/some/script' }
30
+ end
28
31
  "
29
32
 
30
33
  attr_reader :params
31
34
 
32
35
  include CommentParser
33
36
 
34
- def initialize(user = nil)
35
- @user = user
37
+ def initialize(opts = nil)
38
+ if opts.respond_to?(:fetch)
39
+ Hash[opts.map { |k, v| [k.to_sym, v] }]
40
+ @user = opts.fetch(:user, nil)
41
+ @path = opts.fetch(:path, nil)
42
+ raise Inspec::Exceptions::ResourceFailed, 'A user or path must be supplied.' if @user.nil? && @path.nil?
43
+ else
44
+ @user = opts
45
+ @path = nil
46
+ end
47
+ raise Inspec::Exceptions::ResourceSkipped, 'The `crontab` resource is not supported on your OS.' unless inspec.os.unix?
36
48
  @params = read_crontab
37
-
38
- return skip_resource 'The `crontab` resource is not supported on your OS.' unless inspec.os.unix?
39
49
  end
40
50
 
41
51
  def read_crontab
42
- inspec.command(crontab_cmd).stdout.lines.map { |l| parse_crontab_line(l) }.compact
52
+ ct = is_system_crontab? ? inspec.file(@path).content : inspec.command(crontab_cmd).stdout
53
+ ct.lines.map { |l| parse_crontab_line(l) }.compact
43
54
  end
44
55
 
45
56
  def parse_crontab_line(l)
46
57
  data, = parse_comment_line(l, comment_char: '#', standalone_comments: false)
47
58
  return nil if data.nil? || data.empty?
48
59
 
49
- case data
50
- when /@hourly .*/
51
- { 'minute' => '0', 'hour' => '*', 'day' => '*', 'month' => '*', 'weekday' => '*', 'command' => data.split(/\s+/, 2).at(1) }
52
- when /@(midnight|daily) .*/
53
- { 'minute' => '0', 'hour' => '0', 'day' => '*', 'month' => '*', 'weekday' => '*', 'command' => data.split(/\s+/, 2).at(1) }
54
- when /@weekly .*/
55
- { 'minute' => '0', 'hour' => '0', 'day' => '*', 'month' => '*', 'weekday' => '0', 'command' => data.split(/\s+/, 2).at(1) }
56
- when /@monthly ./
57
- { 'minute' => '0', 'hour' => '0', 'day' => '1', 'month' => '*', 'weekday' => '*', 'command' => data.split(/\s+/, 2).at(1) }
58
- when /@(annually|yearly) .*/
59
- { 'minute' => '0', 'hour' => '0', 'day' => '1', 'month' => '1', 'weekday' => '*', 'command' => data.split(/\s+/, 2).at(1) }
60
- when /@reboot .*/
61
- { 'minute' => '-1', 'hour' => '-1', 'day' => '-1', 'month' => '-1', 'weekday' => '-1', 'command' => data.split(/\s+/, 2).at(1) }
62
- else
63
- elements = data.split(/\s+/, 6)
64
- {
65
- 'minute' => elements.at(0),
66
- 'hour' => elements.at(1),
67
- 'day' => elements.at(2),
68
- 'month' => elements.at(3),
69
- 'weekday' => elements.at(4),
70
- 'command' => elements.at(5),
71
- }
72
- end
60
+ is_system_crontab? ? parse_system_crontab(data) : parse_user_crontab(data)
73
61
  end
74
62
 
75
63
  def crontab_cmd
@@ -84,19 +72,98 @@ module Inspec::Resources
84
72
  .add(:days, field: 'day')
85
73
  .add(:months, field: 'month')
86
74
  .add(:weekdays, field: 'weekday')
75
+ .add(:user, field: 'user')
87
76
  .add(:commands, field: 'command')
88
77
 
89
78
  # rebuild the crontab line from raw content
90
79
  filter.add(:content) { |t, _|
91
80
  t.entries.map do |e|
92
- [e.minute, e.hour, e.day, e.month, e.weekday, e.command].join(' ')
81
+ [e.minute, e.hour, e.day, e.month, e.weekday, e.user, e.command].compact.join(' ')
93
82
  end.join("\n")
94
83
  }
95
84
 
96
85
  filter.connect(self, :params)
97
86
 
98
87
  def to_s
99
- @user.nil? ? 'crontab for current user' : "crontab for user #{@user}"
88
+ if is_system_crontab?
89
+ "crontab for path #{@path}"
90
+ elsif is_user_crontab?
91
+ "crontab for user #{@user}"
92
+ else
93
+ 'crontab for current user'
94
+ end
95
+ end
96
+
97
+ private
98
+
99
+ def is_system_crontab?
100
+ !@path.nil?
101
+ end
102
+
103
+ def is_user_crontab?
104
+ !@user.nil?
105
+ end
106
+
107
+ def parse_system_crontab(data)
108
+ case data
109
+ when /@hourly .*/
110
+ elements = data.split(/\s+/, 3)
111
+ { 'minute' => '0', 'hour' => '*', 'day' => '*', 'month' => '*', 'weekday' => '*', 'user' => elements.at(1), 'command' => elements.at(2) }
112
+ when /@(midnight|daily) .*/
113
+ elements = data.split(/\s+/, 3)
114
+ { 'minute' => '0', 'hour' => '0', 'day' => '*', 'month' => '*', 'weekday' => '*', 'user' => elements.at(1), 'command' => elements.at(2) }
115
+ when /@weekly .*/
116
+ elements = data.split(/\s+/, 3)
117
+ { 'minute' => '0', 'hour' => '0', 'day' => '*', 'month' => '*', 'weekday' => '0', 'user' => elements.at(1), 'command' => elements.at(2) }
118
+ when /@monthly ./
119
+ elements = data.split(/\s+/, 3)
120
+ { 'minute' => '0', 'hour' => '0', 'day' => '1', 'month' => '*', 'weekday' => '*', 'user' => elements.at(1), 'command' => elements.at(2) }
121
+ when /@(annually|yearly) .*/
122
+ elements = data.split(/\s+/, 3)
123
+ { 'minute' => '0', 'hour' => '0', 'day' => '1', 'month' => '1', 'weekday' => '*', 'user' => elements.at(1), 'command' => elements.at(2) }
124
+ when /@reboot .*/
125
+ elements = data.split(/\s+/, 3)
126
+ { 'minute' => '-1', 'hour' => '-1', 'day' => '-1', 'month' => '-1', 'weekday' => '-1', 'user' => elements.at(1), 'command' => elements.at(2) }
127
+ else
128
+ elements = data.split(/\s+/, 7)
129
+ {
130
+ 'minute' => elements.at(0),
131
+ 'hour' => elements.at(1),
132
+ 'day' => elements.at(2),
133
+ 'month' => elements.at(3),
134
+ 'weekday' => elements.at(4),
135
+ 'user' => elements.at(5),
136
+ 'command' => elements.at(6),
137
+ }
138
+ end
139
+ end
140
+
141
+ def parse_user_crontab(data)
142
+ case data
143
+ when /@hourly .*/
144
+ { 'minute' => '0', 'hour' => '*', 'day' => '*', 'month' => '*', 'weekday' => '*', 'user' => @user, 'command' => data.split(/\s+/, 2).at(1) }
145
+ when /@(midnight|daily) .*/
146
+ { 'minute' => '0', 'hour' => '0', 'day' => '*', 'month' => '*', 'weekday' => '*', 'user' => @user, 'command' => data.split(/\s+/, 2).at(1) }
147
+ when /@weekly .*/
148
+ { 'minute' => '0', 'hour' => '0', 'day' => '*', 'month' => '*', 'weekday' => '0', 'user' => @user, 'command' => data.split(/\s+/, 2).at(1) }
149
+ when /@monthly ./
150
+ { 'minute' => '0', 'hour' => '0', 'day' => '1', 'month' => '*', 'weekday' => '*', 'user' => @user, 'command' => data.split(/\s+/, 2).at(1) }
151
+ when /@(annually|yearly) .*/
152
+ { 'minute' => '0', 'hour' => '0', 'day' => '1', 'month' => '1', 'weekday' => '*', 'user' => @user, 'command' => data.split(/\s+/, 2).at(1) }
153
+ when /@reboot .*/
154
+ { 'minute' => '-1', 'hour' => '-1', 'day' => '-1', 'month' => '-1', 'weekday' => '-1', 'user' => @user, 'command' => data.split(/\s+/, 2).at(1) }
155
+ else
156
+ elements = data.split(/\s+/, 6)
157
+ {
158
+ 'minute' => elements.at(0),
159
+ 'hour' => elements.at(1),
160
+ 'day' => elements.at(2),
161
+ 'month' => elements.at(3),
162
+ 'weekday' => elements.at(4),
163
+ 'user' => @user,
164
+ 'command' => elements.at(5),
165
+ }
166
+ end
100
167
  end
101
168
  end
102
169
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: inspec
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.47.0
4
+ version: 1.48.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dominik Richter
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-12-04 00:00:00.000000000 Z
11
+ date: 2017-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: train
@@ -16,14 +16,20 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0.30'
19
+ version: '0.31'
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.31.1
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
27
  - - "~>"
25
28
  - !ruby/object:Gem::Version
26
- version: '0.30'
29
+ version: '0.31'
30
+ - - ">="
31
+ - !ruby/object:Gem::Version
32
+ version: 0.31.1
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: thor
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -58,20 +64,6 @@ dependencies:
58
64
  - - "<"
59
65
  - !ruby/object:Gem::Version
60
66
  version: '3.0'
61
- - !ruby/object:Gem::Dependency
62
- name: rainbow
63
- requirement: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - "~>"
66
- - !ruby/object:Gem::Version
67
- version: '2'
68
- type: :runtime
69
- prerelease: false
70
- version_requirements: !ruby/object:Gem::Requirement
71
- requirements:
72
- - - "~>"
73
- - !ruby/object:Gem::Version
74
- version: '2'
75
67
  - !ruby/object:Gem::Dependency
76
68
  name: method_source
77
69
  requirement: !ruby/object:Gem::Requirement