DevOps is a two way street
§ Operations should benefit from years of
best practices surrounding software
development
− Infrastructure as code
− Branching/merging
− testing, testing, testing
> unit tests
> functional tests
> Test Driven Development
> Behavior Driven Development
The faster your write/test/fix loop is,
the happier you are.
Workflows
new software development workflow
§ Write code alongside unit tests
− ensures correctness of new code
− avoids breaking old code
§ Perform integration/acceptance tests in pre-production environments
− Ensures your software plays well with others
Workflows
New cookbook workflow
• Write cookbook
• Write ChefSpec tests alongside
• Use rspec for libraries in cookbooks
• Test cookbook locally
• test-kitchen
• Vagrant
• Test cookbook remotely
• test-kitchen with OpenStack
• Test cookbook in a particular environment
• ServerSpec
Code Correctness
Rubocop - http://batsov.com/rubocop/ Foodcritic - http://acrmp.github.io/foodcritic/
Rubocop example
$ cd cookbooks/gapMetrics/!
$ rubocop!
warning: parser/current is loading parser/ruby21, which recognizes!
warning: 2.1.7-compliant syntax, but you are running 2.1.5.!
Inspecting 20 files!
CCCCCCWWCCCCCCW.WCCC!
!
Offenses:!
!
Berksfile:1:1: C: Missing space after #.!
#site :opscode!
^^^^^^^^^^^^^^!
...!
recipes/xpolog.rb:11:3: C: Inconsistent indentation detected.!
authorized_keys_for 'xpolog'!
^^^^^^^^^^^^^^^^^^^^^^^^^^^^!
recipes/xpolog.rb:11:31: C: Final newline missing.!
authorized_keys_for 'xpolog'!
!!
20 files inspected, 384 offenses detected!
Rubocop resources
§ Marks your code against the style guide
− https://github.com/bbatsov/ruby-style-guide
§ Can automatically fix some errors
§ You can choose rules to ignore, create new ones
or override defaults in .rubocop.yml
https://docs.chef.io/rubocop.html
Foodcritic example
$ foodcritic .!
FC001: Use strings in preference to symbols to access node attributes: ./attributes/
graphite.rb:28!
FC002: Avoid string interpolation where not required: ./recipes/relay.rb:78!
FC007: Ensure recipe dependencies are reflected in cookbook metadata: ./recipes/
_pre_setup.rb:34!
$ !
$ foodcritic -h!
foodcritic [cookbook_paths]!
-t, --tags TAGS Check against (or exclude ~) rules with the specified
tags.!
-f, --epic-fail TAGS Fail the build based on tags. Use 'any' to fail on
all warnings.!
-c, --chef-version VERSION Only check against rules valid for this version of
Chef.!
-B, --cookbook-path PATH Cookbook path(s) to check.!
-C, --[no-]context Show lines matched against rather than the default
summary.!
-E, --environment-path PATH Environment path(s) to check.!
-I, --include PATH Additional rule file path(s) to load.!
-G, --search-gems Search rubygems for rule files with the path
foodcritic/rules/**/*.rb!
-R, --role-path PATH Role path(s) to check.!
-S, --search-grammar PATH Specify grammar to use when validating search syntax.!
-V, --version Display the foodcritic version.!
-X, --exclude PATH Exclude path(s) from being linted.!
Foodcritic resources
http://acrmp.github.io/foodcritic/
Also, look for great production-related catches from Etsy:
https://github.com/etsy/foodcritic-rules
§ Catch packages with an :upgrade action and no specific version
§ Notice dev resources being called from prod
§ Find execute resources with no metaparameters or action :ignore
Unit tests – ChefSpec (an extension of rspec)
ChefSpec simulates the convergence of resources on a node
$ chef exec rspec getValues_spec.rb --format doc!
!
Knifemanage::GetValues#get_changes!
can get a change set from jenkins!
!
Finished in 0.00964 seconds (files took 6.96 seconds to load)!
1 example, 0 failures!
Unit tests – ChefSpec (an extension of rspec)
rspec in general can mock objects or stub apis
ChefSpec and rspec resources
§ https://docs.chef.io/chefspec.html
§ http://betterspecs.org/
More on day 3 under testing.
Functional testing
§ Identify the function or purpose of the cookbook
§ Create input data
§ Expect output
§ Create and execute tests
§ Verify output
Remember, we were talking about test-kitchen?
Test-Kitchen components
Kitchen is made up of pluggable parts
§ pluggable testing framework
§ ships with ChefDK
§ rapidly create/configure/test sandboxes
$ chef --version
Chef Development Kit Version: 0.6.2
chef-client version: 12.3.0
berks version: 3.2.4
kitchen version: 1.4.0
$ vagrant -v
Vagrant 1.6.3
Test-Kitchen sandbox creation
Could be anywhere
§ Target specified by a driver
− use vagrant to run locally, e.g. your laptop
− use OpenStack driver to create sandboxes in an
OpenStack tenant
> You should all have a personal developer tenant in OpenStack
> The watchmen pipelines can do this for your project
§ It’s quite useful to understand how that works behind the scenes
§ No, seriously.
Test-Kitchen sandbox configuration
Configuration done by the provisioner
− Could be a real chef client and server
− Could be chef-solo
− Could be chef-zero
Test-Kitchen sandbox configuration
Configuration done by the provisioner
− Just use chef-zero
Test-Kitchen sandbox testing
Testing is performed via the busser
− Lots of choices
> ChefSpec
> ServerSpec
§ You can also interactively poke at the box
− most useful for our beginner case
Problem: we want to test our mysite
cookbook locally
§ Problem: We’d like a faster test cycle than constantly uploading the
cookbook
§ Solution: test kitchen!
Install Vagrant and VirtualBox
§ Vagrant wraps VirtualBox
https://www.vagrantup.com/downloads.html https://www.virtualbox.org/wiki/Downloads
Test Kitchen
§ Test Kitchen is a tool for testing cookbooks
§ Each config is specific to a given cookbook
§ Perform all commands in the cookbook under test’s directory.
− Gives developer space to safely interact with distributed systems.
Update default .kitchen.yml to use our
vagrant boxes
(mysite/.kitchen.yml)
---!
driver:!
name: vagrant!
!
provisioner:!
name: chef_zero!
!
platforms:!
- name: rhel66!
driver_config:!
box: packer-rhel66!
box_url: http://repo1.phx.gapinc.dev/gapSoftware/vagrant-boxes/packer-rhel66.box!
!
suites:!
- name: mysite!
run_list:!
- recipe[mysite::default]!
attributes:!
A Brief Understanding of YAML
§ No tabs, only spaces
§ Indentation sets hierarchy
§ 2 spaces per indentation
§ use a real editor
§ http://yaml.org/refcard.html
Test-Kitchen - check your configuration
kitchen diagnose!
---!
timestamp: 2015-08-17 03:43:16 UTC!
kitchen_version: 1.4.0!
instances:!
default-rhel66:!
platform:!
os_type: unix!
shell_type: bourne!
state_file: {}!
driver:!
box: packer-rhel66!
box_check_update:!
box_url: http://repo1.phx.gapinc.dev/gapSoftware/vagrant-boxes/packer-rhel66.box!
box_version:!
customize: {}!
gui:!
kitchen_root: "/Users/lamont/tmp/mysite"!
log_level: :info!
Test-Kitchen – kitchen help
$ kitchen help
Commands:!
kitchen console # Kitchen Console!!
kitchen converge [INSTANCE|REGEXP|all] # Change instance state to converge. Use a provisioner to configure
one or more instances!
kitchen create [INSTANCE|REGEXP|all] # Change instance state to create. Start one or more instances!
kitchen destroy [INSTANCE|REGEXP|all] # Change instance state to destroy. Delete all information for one or
more instances!
kitchen diagnose [INSTANCE|REGEXP|all] # Show computed diagnostic configuration!
kitchen driver # Driver subcommands!
kitchen driver create [NAME] # Create a new Kitchen Driver gem project!
kitchen driver discover # Discover Test Kitchen drivers published on RubyGems!
kitchen driver help [COMMAND] # Describe subcommands or one specific subcommand!
kitchen exec INSTANCE|REGEXP -c REMOTE_COMMAND # Execute command on one or more instance!
kitchen help [COMMAND] # Describe available commands or one specific command!
kitchen init # Adds some configuration to your cookbook so Kitchen can rock!
kitchen list [INSTANCE|REGEXP|all] # Lists one or more instances!
kitchen login INSTANCE|REGEXP # Log in to one instance!
kitchen setup [INSTANCE|REGEXP|all] # Change instance state to setup. Prepare to run automated tests.
Install busser and related gems on one or ...!
kitchen test [INSTANCE|REGEXP|all] # Test (destroy, create, converge, setup, verify and destroy) one or
more instances!
kitchen verify [INSTANCE|REGEXP|all] # Change instance state to verify. Run automated tests on one or more
instances!
kitchen version # Print Kitchen's version information!
Test-Kitchen – kitchen list
kitchen list!
IInstance Driver Provisioner Verifier Transport Last Action!
default-rhel66 Vagrant ChefZero Busser Ssh <Not Created>!
Test-Kitchen – kitchen create
kitchen create!
-----> Starting Kitchen (v1.4.0)!
-----> Creating <default-rhel66>...!
Bringing machine 'default' up with 'virtualbox' provider...!
==> default: Box 'packer-rhel66' could not be found. Attempting to find and install...!
default: Box Provider: virtualbox!
default: Box Version: >= 0!
==> default: Adding box 'packer-rhel66' (v0) for provider: virtualbox!
default: Downloading: http://repo1.phx.gapinc.dev/gapSoftware/vagrant-boxes/packer-rhel66.box!
==> default: Successfully added box 'packer-rhel66' (v0) for 'virtualbox'!!
==> default: Importing base box 'packer-rhel66'...!
==> default: Matching MAC address for NAT networking...!
==> default: Setting the name of the VM: kitchen-mysite-default-rhel66_default_1439784531236_96800!
Skipping Berkshelf with --no-provision!
==> default: Clearing any previously set network interfaces...!
==> default: Preparing network interfaces based on configuration...!
default: Adapter 1: nat!
==> default: Forwarding ports...!
default: 22 => 2222 (adapter 1)!
==> default: Booting VM...!
==> default: Waiting for machine to boot. This may take a few minutes...!
default: SSH address: 127.0.0.1:2222!
default: SSH username: vagrant!
...!
---> Kitchen is finished. (13m32.61s)!
Test-Kitchen – kitchen list, again
$
kitchen list!
Instance Driver Provisioner Verifier Transport Last Action!
default-rhel66 Vagrant ChefZero Busser Ssh Created!
Test-Kitchen – kitchen login
kitchen login!
Last login: Sun Aug 16 21:09:20 2015 from 10.0.2.2!
Welcome to your Vagrant-built virtual machine.!
[vagrant@default-rhel66 ~]$!
Test-Kitchen – kitchen destroy
kitchen destroy!
-----> Starting Kitchen (v1.4.0)!
-----> Destroying <default-rhel66>...!
==> default: Forcing shutdown of VM...!
==> default: Destroying VM and associated drives...!
Vagrant instance <default-rhel66> destroyed.!
Finished destroying <default-rhel66> (0m4.13s).!
-----> Kitchen is finished. (0m5.00s)!
Test-Kitchen – kitchen converge
kkitchen converge!
...!
* cookbook_file[/var/www/html/index.html] action create!
!
- update content in file /var/www/html/index.html from none to 7e1f17!
--- /var/www/html/index.html !2015-08-16 21:29:13.978725350 -0700!
+++ /var/www/html/.index.html20150816-6007-t8s9c1 !2015-08-16 21:29:13.977725849 -0700!
@@ -1 +1,10 @@!
+<html>!
+<title>Better Homepage for Gap,Inc</title>!
+<body>!
+<h1>It is SALE time at Gap!</h1>!
+<h2>Time for back to school.</h2>!
+<p>We configured this in the recipe</p>!
+</body>!
+</html>!
+!
- change mode from '' to '0644'!
- change owner from '' to 'nobody'!
!!
Running handlers:!
Running handlers complete!
Chef Client finished, 4/4 resources updated in 133.595728961 seconds!
Finished converging <default-rhel66> (2m18.42s).!
-----> Kitchen is finished. (3m10.41s)!
!
Test Kitchen – What just happened?
§ Test Kitchen automatically includes prerequisite commands
− create
− converge <- converge implies create
− setup
− verify
− destroy
− test <- test implies create, converge, setup, verify, destroy
No comments:
Post a Comment