New test_patch helper script

This tool allows a single patch to be tested against the chef repo.
It will to do job of cloning the repo, merging in the patch(s),
setting up the test and running it, basic queries and tempest.

Also enhanced the Berksfile to allow for easy local development.

Usage: chef exec ruby test_patch.rb help test

Change-Id: I32ba57c29f2f5caee0391ea791ffe10fe06caceb
This commit is contained in:
Mark Vanderwiel 2015-03-16 17:03:16 -05:00
parent 0390aa9200
commit b99b94a852
4 changed files with 223 additions and 1 deletions

View File

@ -4,7 +4,11 @@ source 'https://supermarket.chef.io'
dashboard database data-processing identity image
integration-test network object-storage ops-database
ops-messaging orchestration telemetry}.each do |cookbook|
cookbook "openstack-#{cookbook}", github: "stackforge/cookbook-openstack-#{cookbook}", branch: 'master'
if ENV['REPO_DEV'] && Dir.exist?("../cookbook-openstack-#{cookbook}")
cookbook "openstack-#{cookbook}", path: "../cookbook-openstack-#{cookbook}"
else
cookbook "openstack-#{cookbook}", github: "stackforge/cookbook-openstack-#{cookbook}", branch: 'master'
end
end
cookbook "openstack_client", github: "stackforge/cookbook-openstack-client", branch: 'master'

View File

@ -67,6 +67,7 @@ $ sudo su -
```bash
# Access the controller as noted above
$ source openrc
$ nova-manage version
$ nova service-list && nova hypervisor-list
$ glance image-list
$ keystone user-list
@ -161,6 +162,10 @@ To cleanup everything, use the following rake command.
$ chef exec rake clean
```
## Tools
See the doc/tools.md for more information.
## Databags
Some basic information about the use of databags within this repo.

25
doc/tools.md Normal file
View File

@ -0,0 +1,25 @@
# Tools
## Using the test_patch tool
The tools/test_patch.rb tool will do most of the heavy lifting of testing out one or more patches.
It will basically create a clean environment with a copy of the repo and the patched cookbook, and then run
one of the test environments.
To see the various options and help:
```shell
$ chef exec ruby tools\test_patch.rb help test
```
## Cookbook Patch Development
The Berksfile in this repo has been enhanced to look for local working cookbook development directories and use them
to when running the test suite. Simply set REPO_DEV=True and create a directory tree as follows:
* base_dev_dir\
** openstack-chef-repo
** cookbook-openstack-***
When doing the 'chef exec rake berks_vendor', the Berks file will pick up cookbooks changes from the
cookbook-openstack-*** directories.

188
tools/test_patch.rb Normal file
View File

@ -0,0 +1,188 @@
# Test Patches
#
# Test patches against the testing repo
#
# Author: Mark Vanderwiel (<vanderwl@us.ibm.com>)
# Copyright (c) 2015, IBM, Corp.
require 'fileutils'
require 'English'
require 'chef/mixin/shell_out'
require 'open3'
require 'thor'
def version
'0.1.0'
end
# rubocop:disable LineLength
def run(command, verbose = true) # rubocop:disable Metrics/MethodLength
puts "## Running command: [#{Dir.pwd}] $ #{command}"
live_stream = STDOUT
live_stream = nil unless verbose
runner = Mixlib::ShellOut.new(command, live_stream: live_stream, timeout: 1800).run_command
runner.error!
runner.stdout
end
def check_dependencies
puts '## Checking dependencies'
run('chef --version')
run('vagrant --version')
end
def get_gerrit_user(user)
return user unless user.to_s.empty?
puts '## Using git config to find gitreview.username'
git_config = run('git config -l', false)
/^gitreview.username=(?<user>.*)$/i =~ git_config
abort 'Error! Gerrit user could not be found, please use --username' if user.to_s.empty?
user
end
def get_patch_info(user, patch) # rubocop:disable Metrics/MethodLength
puts "## Gathering information for patch: #{patch} with user: #{user}"
patch_info = run("ssh -p 29418 #{user}@review.openstack.org gerrit query --current-patch-set #{patch}", false)
/^\s*project: stackforge\/(?<patch_project>.*)$/i =~ patch_info
/^\s*ref: (?<patch_ref>.*)$/i =~ patch_info
abort "Error! Patch: #{patch} not valid" if patch_project.nil?
patch_cookbook = patch_project.gsub('cookbook-', '')
puts "## Patch project: #{patch_project}"
puts "## Patch cookbook: #{patch_cookbook}"
puts "## Patch ref: #{patch_ref}"
abort "Error! Only cookbook-openstack-* patches allowed, not from project: #{patch_project}" unless patch_project[/cookbook-openstack-.*/]
{ patch: patch, project: patch_project, cookbook: patch_cookbook, ref: patch_ref }
end
def add_patch(patch_info)
puts "## Adding patch: #{patch_info[:patch]} to cookbook: #{patch_info[:cookbook]}"
run("git clone git@github.com:stackforge/#{patch_info[:project]}.git")
Dir.chdir(patch_info[:project]) do
run("git fetch https://review.openstack.org/stackforge/#{patch_info[:project]} #{patch_info[:ref]}")
run('git checkout FETCH_HEAD')
end
end
def run_tempest
puts '## Starting tempest tests'
Dir.chdir('vms') do
run("vagrant ssh -c \"sudo bash -c 'cd /opt/tempest && ./run_tests.sh -V'\" controller")
end
end
def run_basic_queries # rubocop:disable Metrics/MethodLength
puts '## Starting basic query tests'
{
'nova-manage' => ['version', 'db version'],
'nova' => %w(--version service-list hypervisor-list net-list image-list),
'glance-manage' => %w(db_version),
'glance' => %w(--version image-list),
'keystone-manage' => %w(db_version),
'keystone' => %w(--version user-list endpoint-list role-list service-list tenant-list),
'cinder-manage' => ['version list', 'db version'],
'cinder' => %w(--version list),
'rabbitmqctl' => %w(cluster_status)
}.each do |cli, commands|
commands.each do |command|
Dir.chdir('vms') do
run("vagrant ssh -c \"sudo bash -c 'source /root/openrc && #{cli} #{command}'\" controller")
end
end
end
puts '## Finished basic query tests'
end
def get_test_dir(env, os, patches)
patch = 'master'
patch = patches.gsub(' ', '-') unless patches.to_s.empty?
dir_name = "test-#{env}-#{os}-#{patch}"
puts "## Repo dir: #{dir_name}"
dir_name
end
# Class to run the CLI
class MyCLI < Thor
desc 'test', 'Spin up test repo with optional patches'
long_desc <<-LONGDESC
This will run the test suite. There are options to include one or more patches using the gerrit review number.
The test will run in a new directory called test-<env>-<os>-<patch>, where aio_nova is the default environment,
ubuntu14 is the default os platform and master (no patches) is the default for patch.
For patches, the tool will try to find your gerrit review name using the "git config -l". If the tool
cannot automatically find your gerrit review name, use the -u option to specify it.\n
Examples:
"$ chef exec ruby test_patch test"\n
This will run the aio_nova against the master branch.
"$ chef exec ruby test_patch test -t"\n
This will run the aio_nova against the master branch and run the tempest suite.
"$ chef exec ruby test_patch test -p 161495 -u kramvan"\n
This will run the aio_nova against the master branch including the 161495 patch set.
"$ chef exec ruby test_patch test -p 161495,123456 -u kramvan"\n
This will run the aio_nova against the master branch including patches 161495 and 123456.
"$ chef exec ruby test_patch test -p 161495 -i"\n
This will run the aio_nova against the master branch including the 161495 patch set and
run the converge a second time to help check for idempotentcy. Also, in this case the
gerrit username was automatically found.
"$ chef exec ruby test_patch test -k -s"\n
This is a developer run. The -s will skip the setup steps and just run the converge and tests
again. This allows a developer to tweak and debug a node and then try converge again.
LONGDESC
option :patches, aliases: :p, default: nil, banner: ' Gerrit patch numbers: xxx,zzz, defaults to no patches just use master branch.'
option :env, aliases: :e, default: 'aio_nova', banner: ' Test environment to run.'
option :os, aliases: :o, default: 'ubuntu14', banner: ' OS to use, ubuntu14 or centos7.'
option :idempotent, aliases: :i, default: false, type: :boolean, banner: ' Run converge a second time to help check for idempotentcy.'
option :query, aliases: :q, default: true, type: :boolean, banner: ' Run basic test queries after converge completes.'
option :tempest, aliases: :t, default: false, type: :boolean, banner: ' Run Tempest suite.'
option :keep, aliases: :k, default: false, type: :boolean, banner: ' Keep the environment, do not run \"rake destroy_machines\".'
option :username, aliases: :u, banner: ' Gerrit user name used to fetch a patch if tool cannot automatically find it in git config.'
option :skip, aliases: :s, banner: ' Skip all source changes, just run converge and tests again. For development after manually tweaking a node.'
def test # rubocop:disable Metrics/MethodLength, Metrics/AbcSize, CyclomaticComplexity, Metrics/PerceivedComplexity
puts "## Starting repo test version: #{version} environment: #{options[:env]} on os: #{options[:os]}"
ENV['REPO_OS'] = options[:os]
# TODO: Allow more flexibility with dependencies
check_dependencies
dir_name = get_test_dir(options[:env], options[:os], options[:patches])
Dir.mkdir(dir_name) unless Dir.exist?(dir_name)
Dir.chdir(dir_name) do
if options[:patches] && !options[:skip]
user = get_gerrit_user(options[:username])
options[:patches].split(' ').each do |patch|
patch_info = get_patch_info(user, patch)
add_patch(patch_info)
end
end
run('git clone git@github.com:stackforge/openstack-chef-repo.git') unless options[:skip]
Dir.chdir('openstack-chef-repo') do
ENV['REPO_DEV'] = options[:patches]
run('chef exec rake berks_vendor') unless options[:skip]
(1..(options[:idempotent] ? 2 : 1)).each do |pass|
puts "## Starting Converge pass: #{pass}"
run("chef exec rake #{options[:env]}")
run_basic_queries if options[:query]
run_tempest if options[:tempest]
puts "## Finished Converge pass: #{pass}"
end
run('chef exec rake destroy_machines') unless options[:keep]
end
end
FileUtils.rm_rf(dir_name) unless options[:keep]
puts "## Finished repo test version: #{version} environment: #{options[:env]} on os: #{options[:os]}"
end
end
MyCLI.start(ARGV)