Skip to content

Instantly share code, notes, and snippets.

@gregsymons
Created November 30, 2016 20:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gregsymons/5ed5fa6da0372ecabad8a2904416dd4e to your computer and use it in GitHub Desktop.
Save gregsymons/5ed5fa6da0372ecabad8a2904416dd4e to your computer and use it in GitHub Desktop.
require 'artifactory'
require 'semantic'
RSpec::Matchers.define :be_latest_version_in_artifactory do
# If I define this method outside of this block then it is (unintuitively) not in scope within the block due
# to dynamic class voodoo. If I define it outside of the block, it is also unavailable to the outside world,
# so I can't call it in any control blocks.
def normalize_version_to_semver(version)
version.gsub(/~/, '-')
end
match do |package|
package_info = package.info
@actual_version = Semantic::Version.new(normalize_version_to_semver(package_info[:version]))
@expected_version = Artifactory::Resource::Artifact.search(options.merge(name: "#{package_info[:name]}*.deb"))
.map(&:properties)
.map { |p| p['deb.version'] }
.flatten
.map { |v| Semantic::Version.new(normalize_version_to_semver(v)) }
.max
@actual_version == @expected_version
end
chain :with_options do |options|
@options = options
end
description do
res = 'be the latest version'
res += " (expected '#{@expected_version}', found '#{@actual_version}')" unless @expected_version.nil?
res += " with options #{@options}" unless @options.nil?
res
end
def options
@options || {}
end
end
artifactory_endpoint = attribute('artifactory_endpoint',
default: 'https://artifactory.example.com/artifactory',
description: 'The base url to the Artifactory instance that packages will be installed from')
artifactory_username = attribute('artifactory_username', description: 'The user to log in to artifactory as')
artifactory_password = attribute('artifactory_key', description: 'The API key to log in to artifactory with')
backend_version = attribute('backend_version',
description: 'A backend version to install; by default the latest version available')
# This is another thing I'd prefer to do in something like a spec_helper, since it noises up what I'm actually testing here,
# but apparently inspec attributes are only available in spec files
Artifactory.configure do |c|
c.endpoint = artifactory_endpoint
c.username = artifactory_username
c.password = artifactory_password
end
control 'backend-002' do
impact 1.0
title 'Backend installation'
desc 'The backend service should be installed'
describe.one do
describe package('backend') do
it "By default, installs the latest version" do
expect(u2you_backend_version).to be_nil
end
it { is_expected.to be_installed }
# custom matcher works fine here, since it just queries the package that's
# passed to it.
it { is_expected.to be_latest_version_in_artifactory }
end
describe package('backend') do
# Since I can't declare this in global scope in libraries, I have to redefine it here. Note that this is the
# broadest scope I could get it to work in. Putting it in the describe.one block hid it, as did putting it in
# the control block, and in (what one would expect to be) global scope.
def normalize_version_to_semver(version)
version.gsub(/~/, '-')
end
it "If a version is specified, installs that version" do
expect(backend_version).to_not be_nil
end
it { is_expected.to be_installed }
it { expect(normalize_version_to_semver(subject.version)).to eq backend_version }
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment