inspec-resource-pack 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 526cf6f51d3c1b1e7f940524e97ad3290c145cbf96e1a6a97f54836acfef07f1
4
+ data.tar.gz: 1ebb3618679cf8b8120e48b6d343db68030f38cb5c841c1c1f4ff5330add82b8
5
+ SHA512:
6
+ metadata.gz: 8d9b8f1ad84c4d0d86f0809848a5dcdcc0bb207af641716031068b695229567be3d7ed2a58b9b065124691ec3dd0f60e0c309b18da7235149293f4ed7455de71
7
+ data.tar.gz: 45362a4ae99b34e6dd6c927aba57e4829366077a5387a0c5815216f75d67a55ee073e371e666b81135c2ae007e8d771bf29fd1a5f07dd2c8a9c431202e670f43
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # encoding: utf-8
2
+ source 'https://rubygems.org'
3
+
4
+ gemspec
5
+
6
+ group :development do
7
+ gem 'bundler'
8
+ gem 'byebug'
9
+ gem 'minitest'
10
+ gem 'rake'
11
+ gem 'rubocop', '= 0.49.1' # Need to keep in sync with main InSpec project, so config files will work
12
+ end
data/README.md ADDED
@@ -0,0 +1,28 @@
1
+ # ResourcePack Plugin
2
+
3
+ This plugin was generated by `inspec init plugin`, and apparently the author, 'Lynn Frank', did not update the README.
4
+
5
+ ## To Install This Plugin
6
+
7
+ Assuming it has been published to RubyGems, you can install this gem using:
8
+
9
+ ```
10
+ you@machine $ inspec plugin install inspec-resource-pack
11
+ ```
12
+
13
+ ## What This Plugin Does
14
+
15
+ No idea.
16
+
17
+ ## Developing This Plugin
18
+
19
+ The generated plugin contains everything a real-world, industrial grade plugin would have, including:
20
+
21
+ * an (possibly incomplete) implementation of one or more InSpec Plugin Types
22
+ * documentation (you are reading it now)
23
+ * tests, at the unit and functional level
24
+ * a .gemspec, for packaging and publishing it as a gem
25
+ * a Gemfile, for managing its dependencies
26
+ * a Rakefile, for running development tasks
27
+ * Rubocop linting support for using the base InSpec project rubocop.yml (See Rakefile)
28
+
@@ -0,0 +1,45 @@
1
+ # coding: utf-8
2
+
3
+ # As plugins are usually packaged and distributed as a RubyGem,
4
+ # we have to provide a .gemspec file, which controls the gembuild
5
+ # and publish process. This is a fairly generic gemspec.
6
+
7
+ # It is traditional in a gemspec to dynamically load the current version
8
+ # from a file in the source tree. The next three lines make that happen.
9
+ lib = File.expand_path('../lib', __FILE__)
10
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
11
+ require 'inspec-resource-pack/version'
12
+
13
+ Gem::Specification.new do |spec|
14
+ # Importantly, all InSpec plugins must be prefixed with `inspec-` (most
15
+ # plugins) or `train-` (plugins which add new connectivity features).
16
+ spec.name = 'inspec-resource-pack'
17
+
18
+ # It is polite to namespace your plugin under InspecPlugins::YourPluginInCamelCase
19
+ spec.version = InspecPlugins::ResourcePack::VERSION
20
+ spec.authors = ['Lynn Frank']
21
+ spec.email = ['franklin.webber@gmail.com']
22
+ spec.summary = 'Test resources defined in a profile'
23
+ spec.description = '["Adds some testing helper files to be able to unit test"]'
24
+ spec.homepage = 'https://github.com/burtlo/inspec-resource-pack'
25
+ spec.license = 'Apache-2.0'
26
+
27
+ # Though complicated-looking, this is pretty standard for a gemspec.
28
+ # It just filters what will actually be packaged in the gem (leaving
29
+ # out tests, etc)
30
+ spec.files = %w{
31
+ README.md inspec-resource-pack.gemspec Gemfile
32
+ } + Dir.glob(
33
+ 'lib/**/*', File::FNM_DOTMATCH
34
+ ).reject { |f| File.directory?(f) }
35
+ spec.require_paths = ['lib']
36
+
37
+ # If you rely on any other gems, list them here with any constraints.
38
+ # This is how `inspec plugin install` is able to manage your dependencies.
39
+ # For example, perhaps you are writing a thing that talks to AWS, and you
40
+ # want to ensure you have `aws-sdk` in a certain version.
41
+
42
+ # All plugins should mention inspec, > 2.2.78
43
+ # 2.2.78 included the v2 Plugin API
44
+ spec.add_dependency 'inspec', '>=2.2.78', '<4.0.0'
45
+ end
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+
3
+ require 'inspec/resource'
4
+ require 'plugins/inspec-init/lib/inspec-init/renderer'
5
+
6
+ module InspecPlugins
7
+ module ResourcePack
8
+ class GenerateCLI < Inspec.plugin(2, :cli_command)
9
+ subcommand_desc 'generate resource_pack', 'Create an InSpec profile that is resource pack'
10
+
11
+ # The usual rhythm for a Thor CLI file is description, options, command method.
12
+ # Thor just has you call DSL methods in sequence prior to each command.
13
+
14
+ # Let's make a command, 'do_something'. This will then be available
15
+ # as `inspec my-command do-something
16
+ # (Change this method name to be something sensible for your plugin.)
17
+
18
+ # First, provide a usage / description. This will appear
19
+ # in `inspec help my-command`.
20
+ # As this is a usage message, you should write the command as it should appear
21
+ # to the user (if you want it to have dashes, use dashes)
22
+ desc 'resource_pack NAME', 'Create a custom resource pack'
23
+
24
+ option :overwrite, type: :boolean, default: false,
25
+ desc: 'Overwrites existing directory'
26
+
27
+ def resource_pack(new_resource_pack_name)
28
+ base_templates_path = File.absolute_path(File.join(__FILE__,'..','..','templates'))
29
+ resource_pack_template = 'resource_pack'
30
+
31
+ render_opts = {
32
+ templates_path: base_templates_path,
33
+ overwrite: options[:overwrite]
34
+ }
35
+ renderer = InspecPlugins::Init::Renderer.new(ui, render_opts)
36
+
37
+ vars = { name: new_resource_pack_name }
38
+
39
+ renderer.render_with_values(resource_pack_template, 'resource pack', vars)
40
+
41
+ # ui.exit(:success) # or :usage_error
42
+ ui.exit
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,38 @@
1
+ # encoding: UTF-8
2
+
3
+ # Plugin Definition file
4
+ # The purpose of this file is to declare to InSpec what plugin_types (capabilities)
5
+ # are included in this plugin, and provide hooks that will load them as needed.
6
+
7
+ # It is important that this file load successfully and *quickly*.
8
+ # Your plugin's functionality may never be used on this InSpec run; so we keep things
9
+ # fast and light by only loading heavy things when they are needed.
10
+
11
+ # Presumably this is light
12
+ require 'inspec-resource-pack/version'
13
+
14
+ # The InspecPlugins namespace is where all plugins should declare themselves.
15
+ # The 'Inspec' capitalization is used throughout the InSpec source code; yes, it's
16
+ # strange.
17
+ module InspecPlugins
18
+ # Pick a reasonable namespace here for your plugin. A reasonable choice
19
+ # would be the CamelCase version of your plugin gem name.
20
+ # inspec-resource-pack => ResourcePack
21
+ module ResourcePack
22
+ # This simple class handles the plugin definition, so calling it simply Plugin is OK.
23
+ # Inspec.plugin returns various Classes, intended to be superclasses for various
24
+ # plugin components. Here, the one-arg form gives you the Plugin Definition superclass,
25
+ # which mainly gives you access to the hook / plugin_type DSL.
26
+ # The number '2' says you are asking for version 2 of the plugin API. If there are
27
+ # future versions, InSpec promises plugin API v2 will work for at least two more InSpec
28
+ # major versions.
29
+ class Plugin < ::Inspec.plugin(2)
30
+ plugin_name :'inspec-resource-pack'
31
+
32
+ cli_command :generate do
33
+ require 'inspec-resource-pack/cli_command'
34
+ InspecPlugins::ResourcePack::GenerateCLI
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,10 @@
1
+ # encoding: UTF-8
2
+
3
+ # This file simply makes it easier for CI engines to update
4
+ # the version stamp, and provide a clean way for the gemspec
5
+ # to learn the current version.
6
+ module InspecPlugins
7
+ module ResourcePack
8
+ VERSION = '0.1.0'.freeze
9
+ end
10
+ end
@@ -0,0 +1,16 @@
1
+ # encoding: utf-8
2
+
3
+ # This file is known as the "entry point."
4
+ # This is the file InSpec will try to load if it
5
+ # thinks your plugin is installed.
6
+
7
+ # The *only* thing this file should do is setup the
8
+ # load path, then load the plugin definition file.
9
+
10
+ # Next two lines simply add the path of the gem to the load path.
11
+ # This is not needed when being loaded as a gem; but when doing
12
+ # plugin development, you may need it. Either way, it's harmless.
13
+ libdir = File.dirname(__FILE__)
14
+ $LOAD_PATH.unshift(libdir) unless $LOAD_PATH.include?(libdir)
15
+
16
+ require 'inspec-resource-pack/plugin'
@@ -0,0 +1,10 @@
1
+ name: <%= name %>
2
+ title: InSpec Resource Pack
3
+ maintainer: The Authors
4
+ copyright: The Authors
5
+ copyright_email: you@example.com
6
+ license: Apache-2.0
7
+ summary: An InSpec Resource Pack
8
+ version: 0.1.0
9
+ supports:
10
+ platform: os
@@ -0,0 +1,22 @@
1
+ class ExampleResource < Inspec.resource(1)
2
+ name 'example'
3
+
4
+ def initialize(alternate_path = nil)
5
+ @path = alternate_path || default_path
6
+ end
7
+
8
+ def default_path
9
+ if inspec.os.windows?
10
+ 'C:\example\bin\example.bat'
11
+ else
12
+ '/usr/bin/example'
13
+ end
14
+ end
15
+
16
+ attr_reader :path
17
+
18
+ def version
19
+ raw_result = inspec.command("#{path} --version").stdout
20
+ raw_result.split.first
21
+ end
22
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+ require 'libraries/example'
3
+
4
+ describe_inspec_resource 'example' do
5
+ context 'on windows' do
6
+ # This helper method here is the equivalent to the first line within the environment
7
+ # that defines an os that returns a true when the names align.
8
+ # let(:platform) { 'windows' }
9
+
10
+ environment do
11
+ os.returns(windows?: true, linux?: false)
12
+ command('C:\example\bin\example.bat --version').returns(stdout: '0.1.0 (windows-build)')
13
+ end
14
+
15
+ its(:version) { should eq('0.1.0') }
16
+ end
17
+
18
+ context 'on linux' do
19
+ let(:platform) { 'linux' }
20
+
21
+ environment do
22
+ command('/usr/bin/example --version').returns(stdout: '0.1.0 (GNULinux-build)')
23
+ end
24
+
25
+ its(:version) { should eq('0.1.0') }
26
+ end
27
+ end
@@ -0,0 +1,173 @@
1
+ require 'inspec'
2
+ require 'rspec/its'
3
+
4
+ # To test each of your resources, they will need to be required
5
+ # to have the InSpec registry know about it.
6
+ #
7
+ # require './libraries/ohai.rb'
8
+
9
+ RSpec.configure do |config|
10
+ #
11
+ # Add a convienent name for the example group to the RSpec
12
+ # lexicon. This enables a user to write:
13
+ # describe_inspec_resource 'ohai'
14
+ #
15
+ # As opposed to appending a type to the declaration of the spec:
16
+ # describe 'ohai', type: :inspec_resource'
17
+ #
18
+ config.alias_example_group_to :describe_inspec_resource, type: :inspec_resource
19
+ end
20
+
21
+ shared_context 'InSpec Resource', type: :inspec_resource do
22
+ # The name of the resource which is the string in the
23
+ # top-level description should be the name field of
24
+ # the InSpec resource as it would appears in the registry.
25
+ let(:resource_name) { self.class.top_level_description }
26
+
27
+ # Find the resource in the registry based on the resource_name.
28
+ # The resource classes stored here are not exactly instances
29
+ # of the Resource class (e.g. OhaiResource). They are
30
+ # instead wrapped with the backend transport mechanism which
31
+ # they will be executed against.
32
+ let(:resource_class) { Inspec::Resource.registry[resource_name] }
33
+
34
+ #
35
+ def self.environment_builder(builder = nil)
36
+ if builder
37
+ @environment_builder = builder
38
+ else
39
+ @environment_builder
40
+ end
41
+ end
42
+
43
+ def self.environment(&block)
44
+ environment_builder(DoubleBuilder.new(&block))
45
+
46
+ # Create a backend helper which will generate a backend double
47
+ # based on the definitions that have been building up in
48
+ # all the environment builders in th current context and their
49
+ # parent contexts.
50
+ let(:backend) do
51
+ # For all the possible platforms assign a false result unless the platform name matches
52
+ possible_platforms = %w{aix redhat debian suse bsd solaris linux unix windows hpux darwin}
53
+ os_platform_mock_results = possible_platforms.inject({}) { |acc, elem| acc["#{elem}?"] = (elem == platform.to_s) ; acc }
54
+ platform_builder = DoubleBuilder.new { os.returns(os_platform_mock_results) }
55
+
56
+ env_builders = [ platform_builder ] + self.class.parent_groups.map(&:environment_builder).compact
57
+ starting_double = RSpec::Mocks::Double.new('backend')
58
+ env_builders.inject(starting_double) { |acc, elem| elem.evaluate(self, acc) }
59
+ end
60
+ end
61
+
62
+ # Create an instance of the resource with the mock backend and the resource name
63
+ def resource(*args)
64
+ resource_class.new(backend, resource_name, *args)
65
+ end
66
+
67
+ # Provide an alias of the resource to subject. By setting the subject
68
+ # creates an implicit subject to work with the `rspec-its`.
69
+ let(:subject) { resource }
70
+
71
+ # Provide a helper to help define the environment where the plugin is run in the unit tests
72
+ let(:platform) do
73
+ "spec"
74
+ end
75
+
76
+ # This is a no-op backend that should be overridden.
77
+ # Below is a helper method #environment which provides some
78
+ # shortcuts for hiding some of the RSpec mocking/stubbing double language.
79
+ def backend
80
+ double(
81
+ <<~BACKEND
82
+ A mocked underlying backend has not been defined. This can be done through the environment
83
+ helper method. Which enables you to specify how the mock envrionment will behave to all requests.
84
+
85
+ environment do
86
+ command('which ohai').returns(stdout: '/path/to/ohai')
87
+ command('/path/to/ohai').returns(stdout: '{ "os": "mac_os_x" }')
88
+ end
89
+ BACKEND
90
+ )
91
+ end
92
+ end
93
+
94
+ # This class serves only to create a context to enable a new domain-specific-language (DSL)
95
+ # for defining a backend in a simple way. The DoubleBuilder is constructed with the current
96
+ # test context which it later defines the #backend method that returns the test double that
97
+ # is built with this DSL.
98
+ class DoubleBuilder
99
+ def initialize(&block)
100
+ @content_block = block
101
+ end
102
+
103
+ def evaluate(test_context, backend)
104
+ # Evaluate the block provided to queue up a bunch of backend double definitions.
105
+ instance_exec(&@content_block)
106
+
107
+ backend_doubles = self.backend_doubles
108
+ test_context.instance_exec do
109
+ # With all the backend double definitions defined,
110
+ # create a backend to append all these doubles
111
+ backend_doubles.each do |backend_double|
112
+ if backend_double.has_inputs?
113
+ allow(backend).to receive(backend_double.name).with(*backend_double.inputs).and_return(backend_double.outputs)
114
+ else
115
+ allow(backend).to receive(backend_double.name).with(no_args).and_return(backend_double.outputs)
116
+ end
117
+ end
118
+ end
119
+
120
+ backend
121
+ end
122
+
123
+ # Store all the doubling specified in the initial part of #evaluate
124
+ def backend_doubles
125
+ @backend_doubles ||= []
126
+ end
127
+
128
+ def method_missing(backend_method_name, *args, &_block)
129
+ backend_double = BackendDouble.new(backend_method_name)
130
+ backend_double.inputs = args unless args.empty?
131
+ backend_doubles.push backend_double
132
+ # NOTE: The block is ignored.
133
+ self
134
+ end
135
+
136
+ class InSpecResouceMash < Hashie::Mash
137
+ disable_warnings
138
+ end
139
+
140
+ # When defining a new aspect of the environment (e.g. command, file)
141
+ # you will often want a result from that detail. Because of the fluent
142
+ # interface this double builder provides this is a way to grab the last
143
+ # build double and append a mock of a return object.
144
+ #
145
+ # @TODO this shouldn't be used without a double being created, an
146
+ # error will be generated with that last_double coming back as a nil.
147
+ # There may be some interesting behavior that could be undertaken
148
+ # here when no aspect is provided. It may also be better to throw a
149
+ # useful exception that describes use.
150
+ def returns(method_signature_as_hash)
151
+ return_result = InSpecResouceMash.new(method_signature_as_hash)
152
+ last_double = backend_doubles.last
153
+ results_double_name = "#{last_double.name}_#{last_double.inputs}_RESULTS"
154
+ last_double.outputs = RSpec::Mocks::Double.new(results_double_name, return_result)
155
+ self
156
+ end
157
+
158
+ # Create a object to hold the backend doubling information
159
+ class BackendDouble
160
+ class NoInputsSpecifed; end
161
+
162
+ def initialize(name)
163
+ @name = name
164
+ @inputs = NoInputsSpecifed
165
+ end
166
+
167
+ def has_inputs?
168
+ inputs != NoInputsSpecifed
169
+ end
170
+
171
+ attr_accessor :name, :inputs, :outputs
172
+ end
173
+ end
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: inspec-resource-pack
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Lynn Frank
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-05-31 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: inspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 2.2.78
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: 4.0.0
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 2.2.78
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: 4.0.0
33
+ description: '["Adds some testing helper files to be able to unit test"]'
34
+ email:
35
+ - franklin.webber@gmail.com
36
+ executables: []
37
+ extensions: []
38
+ extra_rdoc_files: []
39
+ files:
40
+ - Gemfile
41
+ - README.md
42
+ - inspec-resource-pack.gemspec
43
+ - lib/inspec-resource-pack.rb
44
+ - lib/inspec-resource-pack/cli_command.rb
45
+ - lib/inspec-resource-pack/plugin.rb
46
+ - lib/inspec-resource-pack/version.rb
47
+ - lib/templates/resource_pack/inspec.yml
48
+ - lib/templates/resource_pack/libraries/example.rb
49
+ - lib/templates/resource_pack/spec/example_spec.rb
50
+ - lib/templates/resource_pack/spec/spec_helper.rb
51
+ homepage: https://github.com/burtlo/inspec-resource-pack
52
+ licenses:
53
+ - Apache-2.0
54
+ metadata: {}
55
+ post_install_message:
56
+ rdoc_options: []
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubygems_version: 3.0.3
71
+ signing_key:
72
+ specification_version: 4
73
+ summary: Test resources defined in a profile
74
+ test_files: []