Skip to content

Commit

Permalink
Introduce user provider and resource
Browse files Browse the repository at this point in the history
- Fixes #269, adds an `elasticsearch_user` resource with provider that creates a user, group, and removes the automatic homedir

- Pins chef to 11.16.4 since chef 12 and many libraries like poise aren't compatible yet, explicit depends on rspec

- Adds a unit test with chefspec matcher under `libraries/matchers.rb` for testing chef resources were created with correct data and actions

- Adds an `elasticsearch_test` kitchenCI suite that tests edge cases, so the default test suite can test the expected way people use the cookbook

- Tweak rubocop rules to avoid style complaints about methods that are too complex (controversial rule) and compact class styles (also controversial at the moment)

- Updated `README.md` with an example of how to use the `elasticsearch_user` resource
  • Loading branch information
martinb3 committed Jan 5, 2015
1 parent 84f7b2d commit 04d010a
Show file tree
Hide file tree
Showing 16 changed files with 185 additions and 33 deletions.
7 changes: 6 additions & 1 deletion .kitchen.yml
Expand Up @@ -9,7 +9,7 @@ driver:
name: vagrant # provide a default test-kitchen driver, vagrant

driver_config:
require_chef_omnibus: latest
require_chef_omnibus: 11.16.4

provisioner:
name: chef_zero
Expand Down Expand Up @@ -39,3 +39,8 @@ suites:
run_list: recipe[elasticsearch]
attributes:
foo: 'bar'

- name: elasticsearch_test
run_list: recipe[elasticsearch_test]
attributes:
foo: 'bar'
8 changes: 8 additions & 0 deletions .rubocop.yml
@@ -1,5 +1,13 @@
# Rubocop, we're buddies and all, but we're going to have to disagree on the following -

# Allow compact class definitions
Style/ClassAndModuleChildren:
Enabled: false

# Allow more complex ruby methods
Metrics/AbcSize:
Max: 50

# Disable requirement of "encoding" headers on files
Encoding:
Enabled: false
Expand Down
2 changes: 2 additions & 0 deletions Gemfile
Expand Up @@ -7,8 +7,10 @@ end

group :unit do
gem 'berkshelf', '~> 3'
gem 'chef', '>= 11.16'
gem 'chefspec'
gem 'chef-sugar'
gem 'rspec'
end

group :kitchen_common do
Expand Down
30 changes: 29 additions & 1 deletion README.md
@@ -1,6 +1,34 @@
# Elasticsearch Chef Cookbook

This branch contains the next version of the cookbook.
This branch contains the next version of the cookbook. This cookbook has been
converted into a library cookbook.

## Recipes

### default

The default recipe creates an elasticsearch user and group with the default
options.

## Resources

### elasticsearch_user

Creates a user and group on the system for use by elasticsearch. Here is an
example with many of the default options and default values (all options except
a resource name may be omitted):

```ruby
elasticsearch_user 'elasticsearch' do
username 'elasticsearch'
groupname 'elasticsearch'
homedir '/usr/local/elasticsearch'
shell '/bin/bash'
comment 'Elasticsearch User'

action :create
end
```

## Testing

Expand Down
9 changes: 9 additions & 0 deletions libraries/matchers.rb
@@ -0,0 +1,9 @@
# encoding: UTF-8
if defined?(ChefSpec)
def create_elasticsearch_user(resource_name)
ChefSpec::Matchers::ResourceMatcher.new(
:elasticsearch_user,
:create,
resource_name)
end
end
70 changes: 70 additions & 0 deletions libraries/user.rb
@@ -0,0 +1,70 @@
class Chef
# Chef Resource for declaring a user and group for Elasticsearch
class Resource::ElasticsearchUser < Resource
include Poise

actions(:create, :remove)

attribute(:username, kind_of: String, default: lazy { name }) # default to resource name
attribute(:uid, kind_of: Integer)
attribute(:shell, kind_of: String, default: '/bin/bash')
attribute(:comment, kind_of: String, default: 'Elasticsearch User')

attribute(:homedir_name, kind_of: String, default: lazy { username }) # default to username
attribute(:homedir_parent, kind_of: String, default: '/usr/local') # windows requires override
attribute(:homedir, kind_of: String, default: lazy { ::File.join(homedir_parent, homedir_name) }) # combination of next two

attribute(:groupname, kind_of: String, default: lazy { username }) # default to username
attribute(:gid, kind_of: Integer)
end

# Chef Provider for creating a user and group for Elasticsearch
class Provider::ElasticsearchUser < Provider
include Poise

def action_create
converge_by("create elasticsearch_user resource #{new_resource.name}") do
notifying_block do
group new_resource.groupname do
gid new_resource.gid
action :create
system true
end

user new_resource.username do
comment new_resource.comment
home new_resource.homedir
shell new_resource.shell
uid new_resource.uid
gid new_resource.groupname
supports manage_home: false
action :create
system true
end

bash 'remove the elasticsearch user home' do
user 'root'
code "rm -rf #{new_resource.homedir}"
not_if { ::File.symlink?("#{new_resource.homedir}") }
only_if { ::File.directory?("#{new_resource.homedir}") }
end
end
end
end

def action_remove
converge_by("remove elasticsearch_user resource #{new_resource.name}") do
notifying_block do
# delete user before deleting the group
user new_resource.username do
action :remove
end

group new_resource.groupname do
action :remove
end
end
end
end
end
end
1 change: 1 addition & 0 deletions metadata.rb
Expand Up @@ -11,3 +11,4 @@
depends 'yum'
depends 'chef-sugar'
depends 'curl'
depends 'poise'
7 changes: 1 addition & 6 deletions recipes/default.rb
Expand Up @@ -7,9 +7,4 @@
include_recipe 'chef-sugar'
include_recipe 'curl'

ruby_block 'dummy_block for test coverage' do
block do
# some Ruby code
end
action :run
end
elasticsearch_user 'elasticsearch'
1 change: 1 addition & 0 deletions test/fixtures/cookbooks/elasticsearch_test/metadata.rb
Expand Up @@ -10,3 +10,4 @@
depends 'apt'
depends 'yum'
depends 'chef-sugar'
depends 'elasticsearch'
4 changes: 2 additions & 2 deletions test/fixtures/cookbooks/elasticsearch_test/recipes/default.rb
@@ -1,4 +1,4 @@
# this is a test fixture used to test that the elasticsearch cookbook's
# provided LWRPs and recipes can be used correctly from a wrapper
# resources, providers, and recipes can be used correctly from a wrapper

include_recipe 'chef-sugar' # placeholder while we're writing recipes still
include_recipe 'elasticsearch_test::user'
15 changes: 15 additions & 0 deletions test/fixtures/cookbooks/elasticsearch_test/recipes/user.rb
@@ -0,0 +1,15 @@
# create user with all non-default overriden options
elasticsearch_user 'foo bar baz' do
groupname 'bar'
username 'foo'
uid 1111
gid 2222
shell '/bin/sh'
homedir '/usr/local/myhomedir'
end

elasticsearch_user 'deleteme'

elasticsearch_user 'deleteme' do
action :remove
end
8 changes: 0 additions & 8 deletions test/integration/default/serverspec/default_spec.rb

This file was deleted.

11 changes: 11 additions & 0 deletions test/integration/default/serverspec/user_spec.rb
@@ -0,0 +1,11 @@
# normal user with defaults
describe group('elasticsearch') do
it { should exist }
end

describe user('elasticsearch') do
it { should exist }
it { should have_home_directory '/usr/local/elasticsearch' }
it { should have_login_shell '/bin/bash' }
it { should belong_to_group 'elasticsearch' }
end
5 changes: 5 additions & 0 deletions test/integration/elasticsearch_test/serverspec/spec_helper.rb
@@ -0,0 +1,5 @@
# Encoding: utf-8
require 'serverspec'

set :backend, :exec
set :path, '/sbin:/usr/local/sbin:$PATH'
23 changes: 23 additions & 0 deletions test/integration/elasticsearch_test/serverspec/user_spec.rb
@@ -0,0 +1,23 @@
require_relative 'spec_helper'

# extra user to test all non-defaults
describe group('bar') do
it { should exist }
it { should have_gid(2222) }
end

describe user('foo') do
it { should exist }
it { should have_uid(1111) }
it { should have_home_directory '/usr/local/myhomedir' }
it { should have_login_shell '/bin/sh' }
it { should belong_to_group 'bar' }
end

describe group('deleteme') do
it { should_not exist }
end

describe user('deleteme') do
it { should_not exist }
end
17 changes: 2 additions & 15 deletions test/unit/spec/default_spec.rb
Expand Up @@ -17,22 +17,9 @@
# any platform specific data you want available to your test can be loaded here
property = load_platform_properties(platform: platform, platform_version: version)

# added as an example, but this probably isn't a great one, since we shouldn't be
# testing resources that are not created/executed by our cookbook.
it 'upgrades curl' do

# example of using a platform specific property to override a package name
curl_package_name = property['curl_package'] || 'curl'

# ensure package is installed (action is :upgrade)
expect(chef_run).to upgrade_package(curl_package_name)

it 'creates elasticsearch_user' do
expect(chef_run).to create_elasticsearch_user('elasticsearch')
end

it 'creates a dummy ruby block for test coverage' do
expect(chef_run).to run_ruby_block('dummy_block for test coverage')
end

end
end
end
Expand Down

0 comments on commit 04d010a

Please sign in to comment.