Initial Commit of the cookbook-openstack-client

Thanks PaulCzar for making this happen, lets make this the best it can
be for people to both consume and operate openstack and chef.

Change-Id: Ied46d05b0a656c813e758fa8e7d7ba6570a5d8fc
This commit is contained in:
JJ Asghar 2014-10-06 12:20:39 -05:00
parent 2310a1f60e
commit 611e31c6e8
24 changed files with 784 additions and 0 deletions

21
.gitignore vendored Normal file
View File

@ -0,0 +1,21 @@
*~
*#
.#*
\#*#
.*.sw[a-z]
*.un~
pkg/
# Berkshelf
.vagrant
berks-cookbooks/*
Berksfile.lock
# Bundler
Gemfile.lock
bin/
.bundle/
.coverage/
.kitchen/
.kitchen.local.yml

17
.kitchen.yml Normal file
View File

@ -0,0 +1,17 @@
---
driver:
name: vagrant
provisioner:
name: chef_zero
platforms:
- name: ubuntu-14.04
- name: ubuntu-12.04
suites:
- name: default
run_list:
- recipe[openstack::default]
- recipe[openstack::_example_swift]
attributes:

29
.rubocop.yml Normal file
View File

@ -0,0 +1,29 @@
# Rubocop, we're buddies and all, but we're going to have to disagree on the following
AllCops:
Exclude:
- berks-cookbooks/**
- Guardfile
Encoding:
Exclude:
- Gemfile
WordArray:
MinSize: 3
Encoding:
Exclude:
- Gemfile
NumericLiterals:
Enabled: false
LineLength:
Enabled: false
WordArray:
MinSize: 3
MethodLength:
Max: 15

3
Berksfile Normal file
View File

@ -0,0 +1,3 @@
source 'https://supermarket.getchef.com'
metadata

13
CHANGELOG.md Normal file
View File

@ -0,0 +1,13 @@
openstack-client CHANGELOG
==========================
This file is used to list changes made in each version of the openstack-client cookbook.
10.0.1
-----
- [Paul Czarkowski](https://twitter.com/pczarkowski) - Initial release of openstack-client
- - -
Check the [Markdown Syntax Guide](http://daringfireball.net/projects/markdown/syntax) for help with Markdown.
The [Github Flavored Markdown page](http://github.github.com/github-flavored-markdown/) describes the differences between markdown on github and standard markdown.

13
Gemfile Normal file
View File

@ -0,0 +1,13 @@
source 'https://rubygems.org'
gem 'berkshelf', '~> 3.1.5'
gem 'chef', '~> 11.6'
gem 'rake', '~> 10.0'
gem 'rubocop', '~> 0.20'
gem 'foodcritic'
gem 'chefspec', '~> 4.0.0'
gem 'test-kitchen'
gem 'kitchen-vagrant'
gem 'guard', '>= 2.6'
gem 'guard-rubocop', '>= 1.1'
gem 'guard-foodcritic', '>= 1.0.2'

14
Guardfile Normal file
View File

@ -0,0 +1,14 @@
# Guardfile for testing your chef cookbooks.
guard :rubocop do
watch(%r{.+\.rb$})
watch(%r{(?:.+/)?\.rubocop\.yml$}) { |m| File.dirname(m[0]) }
end
guard :foodcritic, cookbook_paths: '.', cli: ['--epic-fail', 'any'] do
watch(%r{attributes/.+\.rb$})
watch(%r{providers/.+\.rb$})
watch(%r{recipes/.+\.rb$})
watch(%r{resources/.+\.rb$})
watch(%r{metadata\.rb$})
end

58
README.md Normal file
View File

@ -0,0 +1,58 @@
Openstack Cookbook
==================
This is a library cookbook to consume openstack cloud resources.
Requirements
------------
- TBD
Attributes
----------
Attributes are self documented in `attributes/*.rb`
Usage
-----
#### openstack::default
Installs [fog](http://fog.io) gem and enabled LWRPs
```json
{
"name":"my_node",
"run_list": [
"recipe[openstack]"
]
}
```
#### openstack::_example_swift
Example usage of swift LWRPs
```json
{
"name":"my_node",
"run_list": [
"recipe[openstack]",
"recipe[openstack::_example_swift]",
]
}
```
If you need a simple swift endpoint to test against, the following blog post will help you set up a [single node swift on rackspace cloud](http://blog.phymata.com/2013/02/18/swift-only-with-openstack-devstack-on-the-rackspace-cloud/).
Contributing
------------
Please use the typical Contrubution rules we have set up [here](https://wiki.openstack.org/wiki/Chef/GettingStarted#Contributing_to_the_OpenStack_Chef_Cookbooks),
if you have any questions about this book please go to `irc.freenode.net:#openstack-chef` or contact the [mailing-list](http://groups.google.com/group/opscode-chef-openstack).
License and Authors
-------------------
Apache 2
Paul Czarkowski, username.taken@gmail.com

77
Rakefile Normal file
View File

@ -0,0 +1,77 @@
# Encoding: utf-8
namespace :prepare do
desc 'Install ChefDK'
task :chefdk do
begin
gem 'chef-dk', '0.3.0'
rescue Gem::LoadError
puts 'ChefDK not found. Installing it for you...'
sh %(wget -O /tmp/chefdk.deb https://opscode-omnibus-packages.s3.amazonaws.com/ubuntu/12.04/x86_64/chefdk_0.3.0-1_amd64.deb)
sh %(sudo dpkg -i /tmp/chefdk.deb)
end
end
task :bundle do
if ENV['CI']
sh %(chef exec bundle install --path=.bundle --jobs 1 --retry 3 --verbose)
else
sh %(chef exec bundle install --path .bundle)
end
end
task :berks do
sh %(chef exec berks vendor)
end
end
desc 'Install required Gems and Cookbooks'
task prepare: ['prepare:bundle', 'prepare:berks']
namespace :style do
task :rubocop do
sh %(chef exec rubocop)
end
task :foodcritic do
sh %(chef exec foodcritic .)
end
end
desc 'Run all style checks'
task style: ['style:foodcritic', 'style:rubocop']
namespace :integration do
task :kitchen do
sh %(chef exec kitchen test)
end
end
task integration: ['integration:kitchen']
namespace :unit do
task :chefspec do
sh %(chef exec rspec test/unit/spec)
end
end
desc 'Run all unit tests'
task unit: ['unit:chefspec']
task spec: ['unit']
# Run all tests
desc 'Run all tests'
task test: ['style', 'unit', 'integration']
# The default rake task should just run it all
desc 'Install required Gems and Cookbook then run all tests'
task default: ['prepare', 'test']
begin
require 'kitchen/rake_tasks'
Kitchen::RakeTasks.new
rescue LoadError
puts '>>>>> Kitchen gem not loaded, omitting tasks' unless ENV['CI']
end

12
Thorfile Normal file
View File

@ -0,0 +1,12 @@
# encoding: utf-8
require 'bundler'
require 'bundler/setup'
require 'berkshelf/thor'
begin
require 'kitchen/thor_tasks'
Kitchen::ThorTasks.new
rescue LoadError
puts '>>>>> Kitchen gem not loaded, omitting tasks' unless ENV['CI']
end

19
Vagrantfile vendored Normal file
View File

@ -0,0 +1,19 @@
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure('2') do |config|
config.vm.hostname = 'openstack-client'
config.vm.box = 'ubuntu-12.04'
config.vm.box_url = "http://opscode-vm-bento.s3.amazonaws.com/vagrant/virtualbox/opscode_#{config.vm.box}_chef-provisionerless.box"
config.omnibus.chef_version = 'latest'
config.berkshelf.enabled = true
config.vm.provision :chef_solo do |chef|
chef.json = {
}
chef.run_list = [
'recipe[openstack-client::default]'
]
end
end

12
attributes/default.rb Normal file
View File

@ -0,0 +1,12 @@
# Encoding: utf-8
#
# Cookbook Name:: openstack-client
# Attributes:: default
#
# Copyright 2014, Paul Czarkowski
#
# Dependencies and versions
default['openstack-client']['fog_version'] = '~> 1.23.0'
default['openstack-client']['nokogiri_version'] = '~> 1.6.2.1'

94
chefignore Normal file
View File

@ -0,0 +1,94 @@
# Put files/directories that should be ignored in this file when uploading
# or sharing to the community site.
# Lines that start with '# ' are comments.
# OS generated files #
######################
.DS_Store
Icon?
nohup.out
ehthumbs.db
Thumbs.db
# SASS #
########
.sass-cache
# EDITORS #
###########
\#*
.#*
*~
*.sw[a-z]
*.bak
REVISION
TAGS*
tmtags
*_flymake.*
*_flymake
*.tmproj
.project
.settings
mkmf.log
## COMPILED ##
##############
a.out
*.o
*.pyc
*.so
*.com
*.class
*.dll
*.exe
*/rdoc/
# Testing #
###########
.watchr
.rspec
spec/*
spec/fixtures/*
test/*
features/*
Guardfile
Procfile
# SCM #
#######
.git
*/.git
.gitignore
.gitmodules
.gitconfig
.gitattributes
.svn
*/.bzr/*
*/.hg/*
*/.svn/*
# Berkshelf #
#############
cookbooks/*
tmp
# Cookbooks #
#############
CONTRIBUTING
CHANGELOG*
# Strainer #
############
Colanderfile
Strainerfile
.colander
.strainer
# Vagrant #
###########
.vagrant
Vagrantfile
# Travis #
##########
.travis.yml

31
libraries/client.rb Normal file
View File

@ -0,0 +1,31 @@
#
# Cookbook Name:: openstack-client
# Library:: openstack
# Author:: Paul Czarkowski
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
module Openstack
# The client module starts here
module Client
def initialize(name, run_context = nil)
super
begin
require 'fog'
rescue LoadError
Chef::Log.error("Missing gem 'fog'. Use the default openstack-client recipe to install it first.")
end
end
end
end

41
libraries/swift.rb Normal file
View File

@ -0,0 +1,41 @@
#
# Cookbook Name:: openstack-client
# Library:: storage
# Author:: Paul Czarkowski
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
module Openstack
module Client
# this is required to shut up rubocop
module Swift
include Openstack::Client
def swift # rubocop:disable all
@swift ||= Fog::Storage.new(provider: 'openstack',
openstack_username: new_resource.openstack_username,
openstack_api_key: new_resource.openstack_password,
openstack_auth_url: new_resource.openstack_auth_url,
openstack_tenant: new_resource.openstack_tenant,
openstack_region: new_resource.openstack_region,
openstack_temp_url_key: new_resource.openstack_temp_url_key,
openstack_persistent: new_resource.openstack_persistent,
openstack_service_name: new_resource.openstack_service_name,
openstack_service_type: new_resource.openstack_service_type,
openstack_endpoint_type: new_resource.openstack_endpoint_type
) # rubocop:disable all
end
end
end
end

13
metadata.rb Normal file
View File

@ -0,0 +1,13 @@
# Encoding: utf-8
name 'openstack-client'
maintainer 'openstack-chef'
maintainer_email 'opscode-chef-openstack@googlegroups.com'
license 'Apache2'
description 'Library cookbook to interact with Openstack Clouds'
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
version '10.0.1'
supports 'ubuntu', '>= 12.04'
%w(build-essential apt xml).each do |ckbk|
depends ckbk
end

127
providers/swift_object.rb Normal file
View File

@ -0,0 +1,127 @@
#
# Cookbook Name:: openstack-client
# Provider:: swift
# Author:: Paul Czarkowski
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
require 'tempfile'
require 'chef/digester'
include Openstack::Client::Swift
def whyrun_supported?
true
end
def load_current_resource
@current_resource = Chef::Resource::OpenstackSwiftObject.new(@new_resource.name)
@current_resource.file(@new_resource.file)
if ::File.exist?(@current_resource.file)
@current_resource.exists = true
@current_resource.checksum = Chef::Digester.checksum_for_file(@current_resource.file)
else
@current_resource.exists = false
new_resource.updated_by_last_action(true)
end
@current_resource
end
action :create do
f = Tempfile.new('download')
f.binmode if new_resource.binmode
directory = get_directory(new_resource.container)
directory.files.get(object(new_resource)) do |data, _remaining, _content_length|
f.syswrite data
end
new_resource.checksum = Chef::Digester.checksum_for_file(f.path)
if !current_resource.exists || (current_resource.checksum != new_resource.checksum)
converge_by("Moving new file with checksum to #{new_resource.file}") do
move_file(f.path, new_resource.file)
end
new_resource.updated_by_last_action(true)
else
f.unlink
end
end
action :create_if_missing do
unless current_resource.exists
action_create
new_resource.updated_by_last_action(true)
end
end
action :delete do
if current_resource.exists
# Use md5 checksums because CloudFiles etag is md5
new_resource.checksum = Chef::Digester.generate_md5_checksum_for_file(new_resource.file)
directory = get_directory(new_resource.container)
remote_file = directory.files.get(object(new_resource))
unless remote_file.nil?
converge_by("Destroying object #{object(new_resource)}") do
remote_file.destroy
end
new_resource.updated_by_last_action(true)
end
end
end
action :upload do
if current_resource.exists
# Use md5 checksums because CloudFiles etag is md5
new_resource.checksum = Chef::Digester.generate_md5_checksum_for_file(new_resource.file)
directory = get_directory(new_resource.container)
remote_file = directory.files.get(object(new_resource))
if remote_file.nil? || remote_file.etag != new_resource.checksum
converge_by("Uploading new file #{object(new_resource)} with
checksum #{new_resource.checksum} to #{new_resource.container} container") do
directory.files.create key: object(new_resource),
body: ::File.open(new_resource.file)
end
new_resource.updated_by_last_action(true)
end
end
end
private
def get_directory(n)
directory = swift.directories.get(n)
swift.directories.create key: n unless directory
directory
end
def object(resource)
if resource.object
resource.object
else
::File.basename(resource.file)
end
end
# Defining custom method to work around EACCESS errors on Windows when attempting to move across devices.
# Attrib to tknerr for workaround found in Berkshelf issue #140
def move_file(src, dest)
FileUtils.mv(src, dest, force: false)
rescue Errno::EACCES
FileUtils.cp_r(src, dest)
FileUtils.rm_rf(src)
end

62
recipes/_example_swift.rb Normal file
View File

@ -0,0 +1,62 @@
#
# Cookbook Name:: openstack-client
# Provider:: _example_swift
# Author:: Paul Czarkowski
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
file '/tmp/bacon' do
owner 'root'
group 'root'
mode '0755'
content 'bacon bacon bacon bacon'
action :create
end
openstack_swift_object 'upload_file' do
openstack_username 'admin'
openstack_password 'devstack'
openstack_tenant 'admin'
openstack_auth_url 'http://104.130.171.127:5000/v2.0/tokens'
container 'potato'
file '/tmp/bacon'
action :upload
end
file '/tmp/bacon' do
owner 'root'
group 'root'
mode '0755'
action :delete
end
openstack_swift_object 'download_file' do
openstack_username 'admin'
openstack_password 'devstack'
openstack_tenant 'admin'
openstack_auth_url 'http://104.130.171.127:5000/v2.0/tokens'
container 'potato'
file '/tmp/bacon'
action :create
end
openstack_swift_object 'delete_file' do
openstack_username 'admin'
openstack_password 'devstack'
openstack_tenant 'admin'
openstack_auth_url 'http://104.130.171.127:5000/v2.0/tokens'
container 'potato'
file '/tmp/bacon'
action :delete
end

33
recipes/default.rb Normal file
View File

@ -0,0 +1,33 @@
# Encoding: utf-8
#
# Cookbook Name:: openstack-client
# Recipe:: default
#
# Copyright 2014, Paul Czarkowski
#
# Required to install fog
if platform_family?('debian')
node.override['apt']['compile_time_update'] = true
include_recipe 'apt'
end
node.set['build-essential']['compile_time'] = true
include_recipe 'build-essential'
chef_gem 'nokogiri' do
version node['openstack-client']['nokogiri_version']
action :upgrade
end
include_recipe 'xml::ruby'
chef_gem 'fog' do
version node['openstack-client']['fog_version']
action :upgrade
end
# Load fog for the cloud_monitoring library
# https://sethvargo.com/using-gems-with-chef/
require 'fog'

41
resources/swift_object.rb Normal file
View File

@ -0,0 +1,41 @@
#
# Cookbook Name:: openstack-client
# Resource:: swift
# Author:: Paul Czarkowski
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
actions :create, :create_if_missing, :upload, :delete
default_action :create
BOOLEAN = [TrueClass, FalseClass]
attribute :openstack_username, kind_of: String, required: true
attribute :openstack_password, kind_of: String, required: true
attribute :openstack_tenant, kind_of: String, required: true
attribute :openstack_region, kind_of: String, default: 'RegionOne'
attribute :openstack_auth_url, kind_of: String, required: true
attribute :openstack_temp_url_key, kind_of: String
attribute :openstack_persistent, kind_of: BOOLEAN, default: false
attribute :openstack_service_name, kind_of: String
attribute :openstack_service_type, kind_of: String
attribute :openstack_endpoint_type, kind_of: String
attribute :file, kind_of: String, name_attribute: true
attribute :container, kind_of: String, required: true
attribute :object, kind_of: String
attribute :binmode, kind_of: BOOLEAN, default: false
attr_accessor :exists
attr_accessor :checksum

14
spec/default_spec.rb Normal file
View File

@ -0,0 +1,14 @@
# Encoding: utf-8
require_relative 'spec_helper'
describe 'openstack-client::default' do
describe 'ubuntu' do
let(:chef_run) { ChefSpec::Runner.new.converge(described_recipe) }
it 'writes some chefspec code' do
skip 'todo'
end
end
end

22
spec/spec_helper.rb Normal file
View File

@ -0,0 +1,22 @@
# Encoding: utf-8
require 'rspec/expectations'
require 'chefspec'
require 'chefspec/berkshelf'
require 'chef/application'
::LOG_LEVEL = :fatal
::UBUNTU_OPTS = {
platform: 'ubuntu',
version: '12.04',
log_level: ::LOG_LEVEL
}
REDHAT_OPTS = {
platform: 'redhat',
version: '6.5',
log_level: LOG_LEVEL
}
::CHEFSPEC_OPTS = {
log_level: ::LOG_LEVEL
}
at_exit { ChefSpec::Coverage.report! }

View File

@ -0,0 +1,7 @@
# Encoding: utf-8
require_relative 'spec_helper'
describe 'default' do
it { skip 'write some tests' }
end

View File

@ -0,0 +1,11 @@
# Encoding: utf-8
require 'serverspec'
# Required by serverspec
set :backend, :exec
RSpec.configure do |c|
c.before :all do
c.path = '/sbin:/usr/bin'
end
end