habitat_services

Use the habitat_service (singular) InSpec audit resource to perform in-depth auditing of a single service.

Use the habitat_services (plural) InSpec audit resource to list Habitat services, and perform bulk operations.

Availability

Status: EXPERIMENTAL

This resource, like all of the inspec-habitat resource pack, is in the early stages of research and development. Functionality may be defective, incomplete, or be withdrawn in the future. If you are interested in helping this project mature, please join the conversation or contribute code at the inspec-habitat project.

Connecting to Habitat

To configure inspec to be able to communicate with Chef Habitat, be sure to follow the instructions regarding configuring the connection options. This will prevent ‘unsupported platform’ errors.

Examples

Ensure there are 2 services, with the expected names

describe habitat_services do
  its('count') { should cmp 2 }
  its('names') { should include 'httpd' }
  its('names') { should include 'memcached' }
end

Ensure all running services were updated since January 1, 2018

describe habitat_services.where { release <= '20180101000000' } do
  it { should_not exist }
end

Ensure gcc is not a dependency of any service

# One way - list all services, insist none have a dependency on gcc
describe habitat_services do
  its('dependency_names') { should_not include 'core/gcc' }
end

# Another way - list all services with a dependency on gcc, insist there are none
describe habitat_services.where { dependency_names.include?('core/gcc') } do
  it { should_not exist }
end

Search for services, then examine them in detail using habitat_service

# Use the plural resource as a data lookup (not as a test)...
habitat_services.where { origin != 'core' }.habitat_service_params.each do |params|
  # ... then use the singular resource to do in-depth testing
  describe habitat_service(params) do
    its('release') { should_not be_standalone }
  end
end

Limitations

API versus CLI access

Habitat exposes certain data via the CLI, and other data via the HTTP Gateway API. To enjoy the full functionality of this resource, use a set of credentials that includes the API. Limited data is available by CLI. See the train-habitat documentation for more details.

If you use the CLI interface without the API, unavailable properties will return empty arrays or nil, and unavailable filter criteria will never match. See each property and filter criteria for details.

Availability

Installation

This resource is in the inspec-habitat resource pack. You can use the resource by setting an InSpec profile dependency on the resource pack. See inspec-habitat instructions.

Version

This resource was first available in version 0.1.0 of the resource pack.

Resource Parameters

Resource parameters are arguments passed to the resource in the control code.

This resource does not accept resource parameters, which is typical for plural resources.

Filter Criteria

Filter criteria are used to select which services you wish to examine. If no filter criteria are used, all services are selected.

dependency_names

An array of strings in the form origin/name. Each string is the qualified name of a dependency of a service that is being filtered.

Requires API connection; not available (never matches) via CLI.

describe habitat_services.where { dependency_names.include?('core/gcc') } do
  it { should_not exist }
end

name

String. The (unqualified) name of the service under consideration.

# No services named *ftp* permitted
describe habitat_services.where(name: /ftp/) do
  it { should_not exist }
end

origin

String. The name of the origin that created the package that backs the service under consideration.

# Examine only services released by Chef
describe habitat_services.where(origin: 'chef') do
  its('topologies') { should_not include 'standalone' }
end

release

String. A 14-digit timestamp, in the format YYYYMMDDHHMmmSS. The timestamp reflects the time at which the package backing the service was released. These strings are sortable and comparable.

# Examine packages older than Jan 1 2018
describe habitat_services.where { release < '20180101000000' } do
  its('update_strategies' ) { should_not include 'none' }
end

# Examine packages older than 1 year
describe habitat_services.where { Date.parse(release[0..7]) < Date.today - 365 } do
  its('update_strategies' ) { should_not include 'none' }
end

# Another way
describe habitat_services.where { release < (Date.today - 365).strftime('%Y%m%d000000') } do
  its('update_strategies' ) { should_not include 'none' }
end

topology

String reflecting the topology of the service. Values include standalone and leader (for leader-follower). See the Habitat docs for implications of these values.

# HA or the highway
describe habitat_services.where(topology: 'standalone') do
  it { should_not exist }
end

update_strategy

String reflecting how the software package backing the service should be updated. Values include none, rolling, and at-once. See the Habitat docs for implications of these values.

Requires API connection; not available (never matches) via CLI.

# No YOLO
describe habitat_services.where(update_strategy: 'at-once') do
  it { should_not exist }
end

Properties

Use properties to create tests that compare an expected to value to the actual value.

count

Number. The count of services that matched the filter criteria.

# Expect 12 total
describe habitat_services do
  its(count) { should cmp 12 }
end

describe habitat_services.where(update_strategy: 'at-once') do
  it { should_not exist }
  its(count) { should cmp 0 } # Same as `should_not exist`
end

dependency_names

Array of strings in the form origin/name. Each string is the qualified name of a dependency of a service that was selected by the filter criteria. This list is de-duplicated.

Requires API connection; not available (always an empty array) via CLI.

describe habitat_services do
  its('dependency_names') { should_not include 'core/gcc' }
end

habitatserviceparams

Hash. Returns a set of options that can be passed directly to habitat_service (singular) to load an individual service for in-depth analysis.

# Use the plural resource as a data lookup (not as a test)...
habitat_services.where { origin != 'core' }.habitat_service_params.each do |params|
  # ... then use the singular resource to do in-depth testing
  describe habitat_service(params) do
    its('release') { should_not be_standalone }
  end
end

names

Array of strings. The unqualified name of the service, such as ‘httpd’. This list is de-duplicated, though a name is almost always unique anyway.

describe habitat_services do
  its('names') { should include 'httpd' }
  its('names') { should include 'memcached' }
  its('names') { should_not include 'telnetd' }
end

origins

Array of strings. The names of the origins that created the packages that backs the services that were matched. This list is de-duplicated.

# Only allow core and mycorp-packaged services
describe habitat_services do
  its('origins') { should include 'core' }
  its('origins') { should include 'mycorp' }
  # Advanced usage - count an array-valued property
  its('origins', 'count') { should cmp 2 }
end

releases

Array of strings. Each string is a 14-digit timestamp, in the format YYYYMMDDHHMmmSS. The timestamp reflects the time at which the package backing the service was released. These strings are sortable and comparable. This list is de-duplicated.

# We had a bad Monday
describe habitat_services do
  its('releases') { should_not include '20180325000000' }
end

topologies

Array of strings reflecting the topology of the matched services. Values include standalone and leader (for leader-follower). See the Habitat docs for implications of these values. This list is de-duplicated.

describe habitat_services do
  its('topologies') { should_not include 'standalone' }
end

update_strategies

Array of strings reflecting how the software package backing the services that matched the filter should be updated. Values include none, rolling, and at-once. See the Habitat docs for implications of these values. This list is de-duplicated.

Requires API connection; not available (never matches) via CLI.

# No YOLO
describe habitat_services do
  its('update_strategies') { should_not include 'at-once' }
end

Matchers

Use matchers to create tests that test a true or false question.

InSpec includes a number of universal matchers.

This resource does not define any resource-specific matchers.