Skip to content

Commit

Permalink
Merge pull request #1 from swalberg/master
Browse files Browse the repository at this point in the history
Fast-forward to swalberg
  • Loading branch information
chrisUsick authored Jul 24, 2018
2 parents 02d8ff3 + 6d19776 commit 6d22bea
Show file tree
Hide file tree
Showing 60 changed files with 3,081 additions and 311 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,10 @@ bin/*

.kitchen/
.kitchen.local.yml
.idea
helper.rb
test/integration/data_bags/

# build output
metadata.json
tmp/
31 changes: 29 additions & 2 deletions .kitchen.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,39 @@ driver:

provisioner:
name: chef_solo
deprecations_as_errors: true

platforms:
- name: ubuntu-12.04
- name: centos-6.4
- name: amazon-linux
driver_config:
box: mvbcoding/awslinux
- name: centos-6.9
- name: centos-7.3
- name: debian-7.11
- name: debian-8.8
- name: debian-9.0
- name: fedora-25
- name: opensuse-leap-42.2
- name: ubuntu-14.04
- name: ubuntu-16.04
- name: windows-2012-r2
driver_config:
box: mwrock/Windows2012R2
- name: windows-2016
driver_config:
box: mwrock/Windows2016

suites:
- name: default
run_list:
- recipe[f5_test::test_create_pool]
- recipe[f5_test::test_create_vip]
attributes:
fqdn: local.kitchen.node
ipaddress: 127.0.0.1
f5:
credentials:
default:
username: <%= ENV['F5_USERNAME'] %>
password: <%= ENV['F5_PASSWORD'] %>
host: <%= ENV['F5_HOST'] %>
10 changes: 10 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
Lint/ParenthesesAsGroupedExpression:
Exclude:
- 'spec/**/*'

Lint/UselessAssignment:
Exclude:
- 'libraries/chef_f5.rb'

Metrics/ParameterLists:
Max: 6
6 changes: 6 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
sudo: false
language: ruby
rvm:
- 2.3.3
script:
- bundle exec rake test
6 changes: 3 additions & 3 deletions Berksfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
source "https://supermarket.getchef.com"
source 'https://supermarket.chef.io'

metadata

#group :integration do
group :integration do
cookbook 'f5_test', path: 'test/fixtures/cookbooks/f5_test'
#end
end
14 changes: 10 additions & 4 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -1,16 +1,22 @@
source 'https://rubygems.org'

group :development do
gem "berkshelf", github: "berkshelf/berkshelf"
gem "vagrant", github: "mitchellh/vagrant", tag: "v1.6.3"
gem 'berkshelf', github: 'berkshelf/berkshelf'
end

group :plugins do
gem "vagrant-berkshelf", github: "berkshelf/vagrant-berkshelf"
gem "vagrant-omnibus", github: "schisamo/vagrant-omnibus"
end

gem 'test-kitchen'
gem 'kitchen-vagrant'
gem 'chefspec'
gem 'foodcritic'
gem 'rubocop'
gem 'listen', '2.10.1' # fixed for guard
gem 'rb-readline'
gem 'guard'
gem 'guard-shell'
gem 'guard-rspec', require: false
gem 'vagrant-wrapper'

gem 'f5-icontrol', '>= 0.2.7'
45 changes: 45 additions & 0 deletions Guardfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# A sample Guardfile
# More info at https://github.com/guard/guard#readme

## Uncomment and set this to only include directories you want to watch
directories %w(. libraries resources test spec) \
.select { |d| Dir.exist?(d) ? d : UI.warning("Directory #{d} does not exist") }

## Note: if you are using the `directories` clause above and you are not
## watching the project directory ('.'), then you will want to move
## the Guardfile to a watched dir and symlink it back, e.g.
#
# $ mkdir config
# $ mv Guardfile config/
# $ ln -s config/Guardfile .
#
# and, you'll have to watch "config/Guardfile" instead of "Guardfile"

# Note: The cmd option is now required due to the increasing number of ways
# rspec may be run, below are examples of the most common uses.
# * bundler: 'bundle exec rspec'
# * bundler binstubs: 'bin/rspec'
# * spring: 'bin/rspec' (This will use spring if running and you have
# installed the spring binstubs per the docs)
# * zeus: 'zeus rspec' (requires the server to be started separately)
# * 'just' rspec: 'rspec'

guard :rspec, cmd: 'bundle exec rspec --format documentation' do
require 'guard/rspec/dsl'
dsl = Guard::RSpec::Dsl.new(self)

# Feel free to open issues for suggestions and improvements

# RSpec files
rspec = dsl.rspec
watch(rspec.spec_helper) { rspec.spec_dir }
watch(rspec.spec_support) { rspec.spec_dir }
watch(rspec.spec_files)
watch(%r{^libraries/(.+).rb$}) { |m| Dir["spec/unit/recipes/*_spec.rb"] }
watch(%r{^resources/(.+).rb$}) { |m| Dir["spec/unit/recipes/*_spec.rb"] }
watch(%r{^test/fixtures/cookbooks/f5_test/recipes/(.+)\.rb$}) { |m| "spec/unit/recipes/#{m[1]}_spec.rb" }

# Ruby files
ruby = dsl.ruby
dsl.watch_spec_files_for(ruby.lib_files)
end
4 changes: 0 additions & 4 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,7 +1,3 @@
Copyright (C) 2014 YOUR_NAME

All rights reserved - Do Not Redistribute
=======
The MIT License (MIT)

Copyright (c) 2014 Sean Walberg
Expand Down
173 changes: 139 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,37 @@
# f5-cookbook

A LWRP to manage F5 VIPs and Pools. Currently a WIP, but it will create VIPs and pools, and add nodes to pools
A set of resources for managing F5 load balancers. Currently a WIP, but it will create VIPs and pools, and add nodes to pools

## Supported Platforms
## Requirements

TBA
### Platforms

## Attributes

<table>
<tr>
<th>Key</th>
<th>Type</th>
<th>Description</th>
<th>Default</th>
</tr>
</table>
- RHEL/Fedora and derivatives
- Debian/Ubuntu and derivatives
- Windows [2012.R2, 2016]

## Usage
### Chef

### f5::default
- Chef 12.7+

Not needed at the moment
### Cookbooks

Include `f5` in your node's `run_list`:
- none

```json
{
"run_list": [
"recipe[f5::default]"
]
}
```
## Attributes

Or if you are using a wrapper cookbook,
- `node['f5']['gem_version']` - Sets the version of the gem that will be installed via the resource
- `node['f5']['enabled_status']` - Can take one of three values:
- `:manual` - the default, the `f5_pool` resource does not touch the node's enabled status on load balancer, allowing it to be managed manually on the load balancer
- `:disabled` - if a node does not exist or does exist but is enabled, the load balancer will be asked to disable the node
- `:enabled` - if a node does not exist or does exist but is disabled, the load balancer will be asked to enable the node

```
include_recipe "f5::default"
```
## Usage

Your node will also need access to the credentials for the load balancer either in the attributes or a data bag:

If you're using a data bag, call it `f5` and the default item is called `default`.

```
$ knife data bag show f5 default
Unencrypted data bag detected, ignoring any provided secret options.
Expand All @@ -52,18 +42,20 @@ username: chef-api
```

Or, if no data bag is found, attributes are used

```
default[:f5][:credentials][:default] = {
host: "lb1.example.com",
username: "chef-api",
password: "TopSecret"
}
```
### LWRP

### Resources

In an application's recipe:

```Ruby
```ruby
# Creates the pool if missing and adds this node to the pool
# (currently using node.ipaddress and node.fqdn for the node)
f5_pool 'mypool' do
Expand All @@ -74,19 +66,132 @@ end

# Creates the VIP if missing
f5_vip 'myvip' do
address 'vipaddress'
address 'vipaddress' # IPv4 or FQDN, see below
port 'vipport'
protocol 'protocol' # TCP default
pool 'mypool'

# this is optional; defaults to :manual so won't touch your setting
# unless you specify one of the valid options.
snat_pool :automap

# this is optional; defaults to :manual so won't touch your setting
# unless you specify one of the valid options.
# :none disables the firewall_policy,
# anything else is a named firewall_policy
enforced_firewall_policy

# this is optional; defaults to :manual so won't touch your setting
# unless you specify one of the valid options.
# :none disables the firewall_policy,
# anything else is a named firewall_policy
staged_firewall_policy
end
```

See the documentation for [LocalLB::LBMethod](https://devcentral.f5.com/wiki/iControl.LocalLB__LBMethod.ashx) and [protocol](https://devcentral.f5.com/wiki/iControl.Common__ProtocolType.ashx).

## Testing
#### Using DNS for the name

This is an **experimental feature**. Some of the corner cases might not work :)

If you pass a FQDN to the VIP's address, this resource will attempt to resolve the name through DNS. If a match is found, the first address returned is used for the VIP. If no match is found, the resource will not be processed.


#### Manging node enabled status through node attributes

The `f5_pool` resource exposes an `enabled_status` property which allows you to explicitly take control of a node's enabled/disabled status within a pool via chef recipes and attributes.

```ruby
f5_pool 'mypool' do
host 'value'
port 'value'
enabled_status :disabled
end
```

Though more commonly this is delegated to an attribute, which is the default behavior when this property is not specified explicitly:

```ruby
f5_pool 'mypool' do
host 'value'
port 'value'
end
```

is equivalent to

```ruby
f5_pool 'mypool' do
host 'value'
port 'value'
enabled_status node['f5']['enabled_status']
end
```

and `node['f5']['enabled_status']` defaults to `:manual` so it won't touch the enabled status of your node in the pool unless you explicitly ask it to.

#### Managing virtual server client and server ssl profiles

The `f5_vip` resource exposes a pair or properties which allow you to add client and server SSL profiles to a virtual server.

```ruby
f5_vip 'myvip' do
address 'vipaddress'
port 'vipport'
protocol 'protocol' # TCP default
pool 'mypool'
client_ssl_profile 'client.cert'
server_ssl_profile 'server.cert'
end
```

These two properties are optional and only take effect if they are specified.

They will converge to ensure that profile is applied to the given vip, but there is currently no option to remove an SSL profile.

### Writing specs for vip and pool resources

This coobkook provides custom chefspec matchers so you can write specs like this:

```ruby
require 'chefspec'

describe 'example::default' do
let(:chef_run) { ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '16.04').converge(described_recipe) }

it 'creates the example_com pool (if needed) and adds this node to it' do
expect(chef_run).to create_f5_pool('example_com').with(
ip: '10.0.0.2',
host: 'examplenode01.internaldomain.com',
port: 80,
monitor: 'test-monitor'
)
end

it 'creates the example.com vip' do
expect(chef_run).to create_f5_vip('example.com').with(
address: '86.75.30.9',
port: '80',
protocol: 'PROTOCOL_TCP',
pool: 'reallybasic'
)
end
end
```

NOTE: these matches verify only the presence (or absence via `expect(chef_run).to_not`) of a resource and the configuration of its properties according to hash passed to the optional `with` method.

The matchers cannot be used to validate whether convergence of an `f5_pool` or `f5_vip` resource took place.

## Testing this cookbook

Run `bundle exec rake test` to run the chefspec tests.

`bundle exec rake guard` starts a [`guard`](https://github.com/guard/guard) listener which watches files and auto-runs rspec to provide faster feedback

Run `rspec` to run the chefspec tests.
`bundle exec rake lint` will run rubocop

## License and Authors

Author:: Sean Walberg (<[email protected]>)
Author:: Sean Walberg ([[email protected]](mailto:[email protected]))
2 changes: 1 addition & 1 deletion Thorfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ begin
require 'kitchen/thor_tasks'
Kitchen::ThorTasks.new
rescue LoadError
puts ">>>>> Kitchen gem not loaded, omitting tasks" unless ENV['CI']
puts '>>>>> Kitchen gem not loaded, omitting tasks' unless ENV['CI']
end
Loading

0 comments on commit 6d22bea

Please sign in to comment.