RAKE TEST: Fix rake task for docs:cli (#6437)

Signed-off-by: Sonu Saha <sonu.saha@progress.com>
Co-authored-by: Sonu Saha <sonu.saha@progress.com>
This commit is contained in:
Vasundhara Jagdale 2023-02-27 11:48:08 +05:30 committed by GitHub
parent 3f4af15de5
commit acf97be56e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 71 additions and 66 deletions

View file

@ -34,7 +34,6 @@ group :test do
gem "pry-byebug" gem "pry-byebug"
gem "pry", "~> 0.10" gem "pry", "~> 0.10"
gem "rake", ">= 10" gem "rake", ">= 10"
gem "ruby-progressbar", "~> 1.8"
gem "simplecov", "~> 0.21" gem "simplecov", "~> 0.21"
gem "simplecov_json_formatter" gem "simplecov_json_formatter"
gem "webmock", "~> 3.0" gem "webmock", "~> 3.0"

View file

@ -5,21 +5,11 @@ require "bundler/gem_helper"
require "rake/testtask" require "rake/testtask"
require "train" require "train"
require "fileutils" require "fileutils"
require_relative "tasks/docs"
Bundler::GemHelper.install_tasks name: "inspec-core" Bundler::GemHelper.install_tasks name: "inspec-core"
Bundler::GemHelper.install_tasks name: "inspec" Bundler::GemHelper.install_tasks name: "inspec"
# The docs tasks rely on ruby-progressbar. If we can't load it, then don't
# load the docs tasks. This is necessary to allow this Rakefile to work
# when the "tests" gem group in the Gemfile has been excluded, such as
# during an appbundle-updater run.
begin
require "ruby-progressbar"
require_relative "tasks/docs"
rescue LoadError
puts "docs tasks are unavailable because the ruby-progressbar gem is not available."
end
task :install do task :install do
inspec_bin_path = ::File.join(::File.dirname(__FILE__), "inspec-bin") inspec_bin_path = ::File.join(::File.dirname(__FILE__), "inspec-bin")
Dir.chdir(inspec_bin_path) Dir.chdir(inspec_bin_path)

View file

@ -100,11 +100,11 @@ module Inspec
option :ssl, type: :boolean, option :ssl, type: :boolean,
desc: "Use SSL for transport layer encryption (WinRM)." desc: "Use SSL for transport layer encryption (WinRM)."
option :ssl_peer_fingerprint, type: :string, option :ssl_peer_fingerprint, type: :string,
desc: "Specify peer fingerprint for SSL authentication, used in lieu of certificates" desc: "Specify SSL peer fingerprint in place of certificates for SSL authentication (WinRM)."
option :self_signed, type: :boolean, option :self_signed, type: :boolean,
desc: "Allow remote scans with self-signed certificates (WinRM)." desc: "Allow remote scans with self-signed certificates (WinRM)."
option :ca_trust_file, type: :string, option :ca_trust_file, type: :string,
desc: "Specify CA trust file for SSL authentication" desc: "Specify CA certificate required for SSL authentication (WinRM)."
option :client_cert, type: :string, option :client_cert, type: :string,
desc: "Specify client certificate for SSL authentication" desc: "Specify client certificate for SSL authentication"
option :client_key, type: :string, option :client_key, type: :string,
@ -121,32 +121,32 @@ module Inspec
desc: "Read configuration from JSON file (`-` reads from stdin)." desc: "Read configuration from JSON file (`-` reads from stdin)."
option :json_config, type: :string, hide: true option :json_config, type: :string, hide: true
option :proxy_command, type: :string, option :proxy_command, type: :string,
desc: "Specifies the command to use to connect to the server" desc: "Specifies the command to use to connect to the server."
option :bastion_host, type: :string, option :bastion_host, type: :string,
desc: "Specifies the bastion host if applicable" desc: "Specifies the bastion host if applicable."
option :bastion_user, type: :string, option :bastion_user, type: :string,
desc: "Specifies the bastion user if applicable" desc: "Specifies the bastion user if applicable."
option :bastion_port, type: :string, option :bastion_port, type: :string,
desc: "Specifies the bastion port if applicable" desc: "Specifies the bastion port if applicable."
option :insecure, type: :boolean, default: false, option :insecure, type: :boolean, default: false,
desc: "Disable SSL verification on select targets" desc: "Disable SSL verification on select targets."
option :target_id, type: :string, option :target_id, type: :string,
desc: "Provide a ID which will be included on reports - deprecated" desc: "Provide an ID which will be included on reports - deprecated"
option :winrm_shell_type, type: :string, default: "powershell", option :winrm_shell_type, type: :string, default: "powershell",
desc: "Specify a shell type for winrm (eg. 'elevated' or 'powershell')" desc: "Specify which shell type to use (powershell, elevated, or cmd), which defaults to powershell (WinRM)."
option :docker_url, type: :string, option :docker_url, type: :string,
desc: "Provides path to Docker API endpoint (Docker)" desc: "Provides path to Docker API endpoint (Docker). Defaults to unix:///var/run/docker.sock on Unix systems and tcp://localhost:2375 on Windows."
option :ssh_config_file, type: :array, option :ssh_config_file, type: :array,
desc: "A list of paths to the ssh config file, e.g ~/.ssh/config or /etc/ssh/ssh_config" desc: "A list of paths to the ssh config file, e.g ~/.ssh/config or /etc/ssh/ssh_config."
option :podman_url, type: :string, option :podman_url, type: :string,
desc: "Provides path to Podman API endpoint" desc: "Provides the path to the Podman API endpoint. Defaults to unix:///run/user/$UID/podman/podman.sock for rootless container, unix:///run/podman/podman.sock for rootful container (for this you need to execute inspec as root user)."
end end
def self.profile_options def self.profile_options
option :profiles_path, type: :string, option :profiles_path, type: :string,
desc: "Folder which contains referenced profiles." desc: "Folder which contains referenced profiles."
option :vendor_cache, type: :string, option :vendor_cache, type: :string,
desc: "Use the given path for caching dependencies. (default: ~/.inspec/cache)" desc: "Use the given path for caching dependencies, (default: ~/.inspec/cache)."
option :auto_install_gems, type: :boolean, default: false, option :auto_install_gems, type: :boolean, default: false,
desc: "Auto installs gem dependencies of the profile or resource pack." desc: "Auto installs gem dependencies of the profile or resource pack."
end end
@ -174,7 +174,7 @@ module Inspec
option :input, type: :array, banner: "name1=value1 name2=value2", option :input, type: :array, banner: "name1=value1 name2=value2",
desc: "Specify one or more inputs directly on the command line, as --input NAME=VALUE. Accepts single-quoted YAML and JSON structures." desc: "Specify one or more inputs directly on the command line, as --input NAME=VALUE. Accepts single-quoted YAML and JSON structures."
option :input_file, type: :array, option :input_file, type: :array,
desc: "Load one or more input files, a YAML file with values for the profile to use" desc: "Load one or more input files, a YAML file with values for the profile to use."
option :waiver_file, type: :array, option :waiver_file, type: :array,
desc: "Load one or more waiver files." desc: "Load one or more waiver files."
option :attestation_file, type: :array, option :attestation_file, type: :array,
@ -184,14 +184,14 @@ module Inspec
option :create_lockfile, type: :boolean, option :create_lockfile, type: :boolean,
desc: "Write out a lockfile based on this execution (unless one already exists)" desc: "Write out a lockfile based on this execution (unless one already exists)"
option :backend_cache, type: :boolean, option :backend_cache, type: :boolean,
desc: "Allow caching for backend command output. (default: true)" desc: "Allow caching for backend command output. (default: true)."
option :show_progress, type: :boolean, option :show_progress, type: :boolean,
desc: "Show progress while executing tests." desc: "Show progress while executing tests."
option :distinct_exit, type: :boolean, default: true, option :distinct_exit, type: :boolean, default: true,
desc: "Exit with code 101 if any tests fail, and 100 if any are skipped (default). If disabled, exit 0 on skips and 1 for failures." desc: "Exit with code 101 if any tests fail, and 100 if any are skipped (default). If disabled, exit 0 on skips and 1 for failures."
option :silence_deprecations, type: :array, option :silence_deprecations, type: :array,
banner: "[all]|[GROUP GROUP...]", banner: "[all]|[GROUP GROUP...]",
desc: "Suppress deprecation warnings. See install_dir/etc/deprecations.json for list of GROUPs or use 'all'." desc: "Suppress deprecation warnings. See install_dir/etc/deprecations.json for a list of GROUPs or use 'all'."
option :diff, type: :boolean, default: true, option :diff, type: :boolean, default: true,
desc: "Use --no-diff to suppress 'diff' output of failed textual test results." desc: "Use --no-diff to suppress 'diff' output of failed textual test results."
option :sort_results_by, type: :string, default: "file", banner: "--sort-results-by=none|control|file|random", option :sort_results_by, type: :string, default: "file", banner: "--sort-results-by=none|control|file|random",
@ -199,7 +199,7 @@ module Inspec
option :filter_empty_profiles, type: :boolean, default: false, option :filter_empty_profiles, type: :boolean, default: false,
desc: "Filter empty profiles (profiles without controls) from the report." desc: "Filter empty profiles (profiles without controls) from the report."
option :filter_waived_controls, type: :boolean, option :filter_waived_controls, type: :boolean,
desc: "Do not execute waived controls in InSpec at all. Must use with --waiver-file. Ignores `run` setting of waiver file." desc: "Do not execute waived controls in InSpec at all. Must use with --waiver-file. Ignores the `run` setting of the waiver file."
option :retain_waiver_data, type: :boolean, option :retain_waiver_data, type: :boolean,
desc: "EXPERIMENTAL: Only works in conjunction with --filter-waived-controls, retains waiver data about controls that were skipped" desc: "EXPERIMENTAL: Only works in conjunction with --filter-waived-controls, retains waiver data about controls that were skipped"
option :command_timeout, type: :numeric, option :command_timeout, type: :numeric,

View file

@ -62,9 +62,9 @@ class Inspec::InspecCLI < Inspec::BaseCLI
require "license_acceptance/cli_flags/thor" require "license_acceptance/cli_flags/thor"
include LicenseAcceptance::CLIFlags::Thor include LicenseAcceptance::CLIFlags::Thor
desc "json PATH", "read all tests in PATH and generate a JSON summary" desc "json PATH", "read all tests in the PATH and generate a JSON summary."
option :output, aliases: :o, type: :string, option :output, aliases: :o, type: :string,
desc: "Save the created profile to a path" desc: "Save the created profile to a path."
option :controls, type: :array, option :controls, type: :array,
desc: "A list of controls to include. Ignore all other tests." desc: "A list of controls to include. Ignore all other tests."
option :tags, type: :array, option :tags, type: :array,
@ -84,7 +84,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
option :format, type: :string, option :format, type: :string,
desc: "The output format to use: json, raw, yaml. If valid format is not provided then it will use the default for the given 'what'." desc: "The output format to use: json, raw, yaml. If valid format is not provided then it will use the default for the given 'what'."
option :output, aliases: :o, type: :string, option :output, aliases: :o, type: :string,
desc: "Save the created output to a path" desc: "Save the created output to a path."
option :controls, type: :array, option :controls, type: :array,
desc: "For --what=profile, a list of controls to include. Ignore all other tests." desc: "For --what=profile, a list of controls to include. Ignore all other tests."
option :tags, type: :array, option :tags, type: :array,
@ -152,9 +152,11 @@ class Inspec::InspecCLI < Inspec::BaseCLI
} }
end end
desc "check PATH", "verify all tests at the specified PATH" desc "check PATH", "Verify the metadata in the `inspec.yml` file,\
verify that control blocks have the correct fields (title, description, impact),\
and define that all controls have visible tests and the controls are not using deprecated InSpec DSL code"
option :format, type: :string, option :format, type: :string,
desc: "The output format to use doc (default), json. If valid format is not provided then it will use the default." desc: "The output format to use. Valid values: `json` and `doc`. Default value: `doc`."
option :with_cookstyle, type: :boolean, option :with_cookstyle, type: :boolean,
desc: "Enable or disable cookstyle checks.", default: false desc: "Enable or disable cookstyle checks.", default: false
profile_options profile_options
@ -240,10 +242,10 @@ class Inspec::InspecCLI < Inspec::BaseCLI
} }
end end
desc "archive PATH", "archive a profile to tar.gz (default) or zip" desc "archive PATH", "Archive a profile to a tar file (default) or zip file."
profile_options profile_options
option :output, aliases: :o, type: :string, option :output, aliases: :o, type: :string,
desc: "Save the archive to a path" desc: "Save the archive to a path."
option :zip, type: :boolean, default: false, option :zip, type: :boolean, default: false,
desc: "Generates a zip archive." desc: "Generates a zip archive."
option :tar, type: :boolean, default: false, option :tar, type: :boolean, default: false,
@ -291,14 +293,10 @@ class Inspec::InspecCLI < Inspec::BaseCLI
} }
end end
desc "exec LOCATIONS", "Run all tests at LOCATIONS." desc "exec LOCATIONS", "Run all test files at the specified locations."
long_desc <<~EOT long_desc <<~EOT
Run all test files at the specified LOCATIONS. The subcommand loads the given profiles, fetches their dependencies if needed, then connects to the target and executes any controls in the profiles.
One or more reporters are used to generate the output.
Loads the given profile(s) and fetches their dependencies if needed. Then
connects to the target and executes any controls contained in the profiles.
One or more reporters are used to generate output.
``` ```
Exit codes: Exit codes:
0 Normal exit, all tests passed 0 Normal exit, all tests passed
@ -312,7 +310,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
Below are some examples of using `exec` with different test LOCATIONS: Below are some examples of using `exec` with different test LOCATIONS:
Automate: Chef Automate:
``` ```
#{Inspec::Dist::EXEC_NAME} automate login #{Inspec::Dist::EXEC_NAME} automate login
#{Inspec::Dist::EXEC_NAME} exec compliance://username/linux-baseline #{Inspec::Dist::EXEC_NAME} exec compliance://username/linux-baseline
@ -322,7 +320,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
#{Inspec::Dist::EXEC_NAME} compliance login #{Inspec::Dist::EXEC_NAME} compliance login
``` ```
Supermarket: Chef Supermarket:
``` ```
#{Inspec::Dist::EXEC_NAME} exec supermarket://username/linux-baseline #{Inspec::Dist::EXEC_NAME} exec supermarket://username/linux-baseline
``` ```
@ -359,12 +357,12 @@ class Inspec::InspecCLI < Inspec::BaseCLI
#{Inspec::Dist::EXEC_NAME} exec https://github.com/dev-sec/linux-baseline.git #{Inspec::Dist::EXEC_NAME} exec https://github.com/dev-sec/linux-baseline.git
``` ```
Web hosted fileshare (also supports .zip): Web hosted file (also supports .zip):
``` ```
#{Inspec::Dist::EXEC_NAME} exec https://webserver/linux-baseline.tar.gz #{Inspec::Dist::EXEC_NAME} exec https://webserver/linux-baseline.tar.gz
``` ```
Web hosted fileshare with basic authentication (supports .zip): Web hosted file with basic authentication (supports .zip):
``` ```
#{Inspec::Dist::EXEC_NAME} exec https://username:password@webserver/linux-baseline.tar.gz #{Inspec::Dist::EXEC_NAME} exec https://username:password@webserver/linux-baseline.tar.gz
``` ```
@ -391,7 +389,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
} }
end end
desc "detect", "detect the target OS" desc "detect", "detects the target OS."
target_options target_options
option :format, type: :string option :format, type: :string
def detect def detect
@ -420,7 +418,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
} }
end end
desc "shell", "open an interactive debugging shell" desc "shell", "open an interactive debugging shell."
target_options target_options
option :command, aliases: :c, option :command, aliases: :c,
desc: "A single command string to run instead of launching the shell" desc: "A single command string to run instead of launching the shell"
@ -483,7 +481,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
} }
end end
desc "env", "Output shell-appropriate completion configuration" desc "env", "Outputs shell-appropriate completion configuration."
def env(shell = nil) def env(shell = nil)
Inspec.with_feature("inspec-cli-env") { Inspec.with_feature("inspec-cli-env") {
begin begin
@ -519,7 +517,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
} }
end end
desc "version", "prints the version of this tool" desc "version", "prints the version of this tool."
option :format, type: :string option :format, type: :string
def version def version
Inspec.with_feature("inspec-cli-version") { Inspec.with_feature("inspec-cli-version") {
@ -535,7 +533,7 @@ class Inspec::InspecCLI < Inspec::BaseCLI
desc "clear_cache", "clears the InSpec cache. Useful for debugging." desc "clear_cache", "clears the InSpec cache. Useful for debugging."
option :vendor_cache, type: :string, option :vendor_cache, type: :string,
desc: "Use the given path for caching dependencies. (default: ~/.inspec/cache)" desc: "Use the given path for caching dependencies, (default: `~/.inspec/cache`)."
def clear_cache def clear_cache
Inspec.with_feature("inspec-cli-clear-cache") { Inspec.with_feature("inspec-cli-clear-cache") {
o = config o = config

View file

@ -19,7 +19,23 @@ require "fileutils"
require "yaml" require "yaml"
require "git" require "git"
DOCS_DIR = "../docs".freeze DOCS_DIR = "docs-chef-io/content/inspec".freeze
MENU_MD = <<~MENU.freeze
+++
title = "InSpec CLI"
draft = false
gh_repo = "inspec"
[menu]
[menu.inspec]
title = "InSpec Executable"
identifier = "inspec/reference/cli.md InSpec Executable"
parent = "inspec/reference"
weight = 10
+++
MENU
class Markdown class Markdown
class << self class << self
@ -45,6 +61,10 @@ class Markdown
"* #{msg.gsub("\n", "\n ")}\n" "* #{msg.gsub("\n", "\n ")}\n"
end end
def dl(msg)
"#{msg.gsub("\n", "\n ")}\n"
end
def ul(msg) def ul(msg)
msg + "\n" msg + "\n"
end end
@ -64,7 +84,7 @@ class Markdown
def meta(opts) def meta(opts)
o = opts.map { |k, v| "#{k}: #{v}" }.join("\n") o = opts.map { |k, v| "#{k}: #{v}" }.join("\n")
"---\n#{o}\n---\n\n" "+++\n#{o}\n+++\n\n"
end end
end end
end end
@ -127,9 +147,9 @@ namespace :docs do # rubocop:disable Metrics/BlockLength
# list of subcommands we ignore; these are e.g. plugins # list of subcommands we ignore; these are e.g. plugins
skip_commands = %w{scap} skip_commands = %w{scap}
res = f.meta(title: "About the InSpec CLI") res = ""
res << f.h1("InSpec CLI") res << MENU_MD
res << f.p("Use the InSpec CLI to run tests and audits against targets "\ res << f.p("<!-- markdownlint-disable MD024 -->\n\nUse the InSpec Command Line Interface (CLI) to run tests and audits against targets "\
"using local, SSH, WinRM, or Docker connections.") "using local, SSH, WinRM, or Docker connections.")
require "inspec/cli" require "inspec/cli"
@ -147,11 +167,11 @@ namespace :docs do # rubocop:disable Metrics/BlockLength
res << f.h3("Syntax") res << f.h3("Syntax")
res << f.p("This subcommand has the following syntax:") res << f.p("This subcommand has the following syntax:")
res << f.code("$ inspec #{cmd.usage}", "bash") res << f.code("inspec #{cmd.usage}", "bash")
opts = cmd.options.reject { |_, o| o.hide } opts = cmd.options.reject { |_, o| o.hide }
unless opts.empty? unless opts.empty?
res << f.h3("Options") + f.p("This subcommand has additional options:") res << f.h3("Options") + f.p("This subcommand has the following additional options:")
list = "" list = ""
opts.keys.sort.each do |option| opts.keys.sort.each do |option|
@ -160,8 +180,10 @@ namespace :docs do # rubocop:disable Metrics/BlockLength
usage = opt.usage.split(", ") usage = opt.usage.split(", ")
.map { |x| x.tr("[]", "") } .map { |x| x.tr("[]", "") }
.map { |x| x.start_with?("-") ? x : "-" + x } .map { |x| x.start_with?("-") ? x : "-" + x }
.map { |x| "``" + x + "``" } .map { |x| "`" + x + "`" }
list << f.li("#{usage.join(", ")} \n#{opt.description}") msg = "#{usage.join(", ")}\n"
msg << ": #{opt.description}\n" if opt.description && !opt.description.empty?
list << f.dl(msg)
end.join end.join
res << f.ul(list) res << f.ul(list)
end end
@ -170,11 +192,7 @@ namespace :docs do # rubocop:disable Metrics/BlockLength
res << "\n\n" if f == RST res << "\n\n" if f == RST
end end
# TODO: The directory is broken, so we need to fix it dst = File.join(pwd, DOCS_DIR , "cli#{f.suffix}")
# Use the docs-chef-io directory to fix the cli doc build
# doc_directory = File.join(pwd, "docs-chef-io/content/inspec")
# dst = File.join(doc_directory , "cli#{f.suffix}")
dst = File.join(DOCS_DIR, "cli#{f.suffix}")
File.write(dst, res) File.write(dst, res)
puts "Documentation generated in #{dst.inspect}" puts "Documentation generated in #{dst.inspect}"
end end