commit e86f258f5a3a5c69e8d56748c2e138cc1ea77c98 Author: Jan Klare Date: Tue Aug 30 07:45:16 2016 +0200 initial commit * working Rakefile to run lint, style and unit tests * providers for domain, endpoint, project, role, service and user * some initial README info diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..de2fb39 --- /dev/null +++ b/.gitignore @@ -0,0 +1,7 @@ +Berksfile.lock +*~ +*# +.#* +\#*# +.*.sw[a-z] +*.un~ diff --git a/.rubocop.yml b/.rubocop.yml new file mode 100644 index 0000000..cc32da4 --- /dev/null +++ b/.rubocop.yml @@ -0,0 +1 @@ +inherit_from: .rubocop_todo.yml diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml new file mode 100644 index 0000000..11d2dd1 --- /dev/null +++ b/.rubocop_todo.yml @@ -0,0 +1,20 @@ +# This configuration was generated by +# `rubocop --auto-gen-config` +# on 2016-08-29 21:29:34 +0200 using RuboCop version 0.39.0. +# The point is for the user to remove these configuration records +# one by one as the offenses are removed from the code base. +# Note that changes in the inspected code, or installation of new +# versions of RuboCop, may require this file to be generated again. + +# Offense count: 7 +Style/Documentation: + Exclude: + - 'spec/**/*' + - 'test/**/*' + - 'libraries/openstack_base.rb' + - 'libraries/openstack_domain.rb' + - 'libraries/openstack_endpoint.rb' + - 'libraries/openstack_project.rb' + - 'libraries/openstack_role.rb' + - 'libraries/openstack_service.rb' + - 'libraries/openstack_user.rb' diff --git a/Berksfile b/Berksfile new file mode 100644 index 0000000..155e0bf --- /dev/null +++ b/Berksfile @@ -0,0 +1,23 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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. + +source 'https://supermarket.chef.io' + +metadata + +# cookbook for testing LWRPs: +cookbook 'openstackclient_test', + path: 'spec/cookbooks/openstackclient_test' diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..d9a10c0 --- /dev/null +++ b/LICENSE @@ -0,0 +1,176 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS diff --git a/README.md b/README.md new file mode 100644 index 0000000..0d6a857 --- /dev/null +++ b/README.md @@ -0,0 +1,49 @@ +# Description + +Installs the fog-openstack gem and offers Resources to use it. + +# Requirements + +- gem 'fog-openstack' + +# Resources + +## openstack_domain +- creates or deletes an openstack domain +- example recipe can be found + [here](spec/cookbooks/openstackclient_test/recipes/domain.rb) + +## openstack_endpoint +- creates or deletes an openstack endpoint +- example recipe can be found + [here](spec/cookbooks/openstackclient_test/recipes/endpoint.rb) + +## openstack_project +- creates or deletes an openstack project +- example recipe can be found + [here](spec/cookbooks/openstackclient_test/recipes/project.rb) + +## openstack_role +- creates or deletes an openstack role +- example recipe can be found + [here](spec/cookbooks/openstackclient_test/recipes/role.rb) + +## openstack_service +- creates or deletes an openstack service +- example recipe can be found + [here](spec/cookbooks/openstackclient_test/recipes/service.rb) + +## openstack_user +- creates or deletes an openstack user +- grants or revokes role to user in project +- grants or revokes domain to user +- example recipe can be found + [here](spec/cookbooks/openstackclient_test/recipes/user.rb) + +# License and Maintainer + +Maintainer:: cloudbau GmbH () +Source:: https://github.com/cloudbau/cookbook-openstackclient +Issues:: https://github.com/cloudbau/cookbook-openstackclient/issues + +License:: Apache v2.0 diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..289568a --- /dev/null +++ b/Rakefile @@ -0,0 +1,34 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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. + +task default: ['test'] + +task test: [:lint, :style, :unit] + +desc 'Run FoodCritic (lint) tests' +task :lint do + sh %(chef exec foodcritic --epic-fail any .) +end + +desc 'Run RuboCop (style) tests' +task :style do + sh %(chef exec rubocop) +end + +desc 'Run RSpec (unit) tests' +task :unit do + sh %(chef exec rspec --format documentation) +end diff --git a/libraries/matchers.rb b/libraries/matchers.rb new file mode 100644 index 0000000..074f86b --- /dev/null +++ b/libraries/matchers.rb @@ -0,0 +1,97 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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. + +if defined?(ChefSpec) + def create_openstack_project(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:openstack_project, :create, resource_name) + end + + def delete_openstack_project(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:openstack_project, :delete, resource_name) + end + + def create_openstack_service(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:openstack_service, :create, resource_name) + end + + def delete_openstack_service(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:openstack_service, :delete, resource_name) + end + + def create_openstack_endpoint(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:openstack_endpoint, :create, resource_name) + end + + def delete_openstack_endpoint(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:openstack_endpoint, :delete, resource_name) + end + + def create_openstack_role(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:openstack_role, :create, resource_name) + end + + def delete_openstack_role(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:openstack_role, :delete, resource_name) + end + + def create_openstack_user(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:openstack_user, :create, resource_name) + end + + def delete_openstack_user(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:openstack_user, :delete, resource_name) + end + + def grant_role_openstack_user(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:openstack_user, :grant_role, resource_name) + end + + def revoke_role_openstack_user(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:openstack_user, :revoke_role, resource_name) + end + + def grant_domain_openstack_user(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:openstack_user, :grant_domain, resource_name) + end + + def revoke_domain_openstack_user(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:openstack_user, :revoke_domain, resource_name) + end + + def create_openstack_domain(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:openstack_domain, :create, resource_name) + end + + def delete_openstack_domain(resource_name) + ChefSpec::Matchers::ResourceMatcher + .new(:openstack_domain, :delete, resource_name) + end +end diff --git a/libraries/openstack_base.rb b/libraries/openstack_base.rb new file mode 100644 index 0000000..569ebd9 --- /dev/null +++ b/libraries/openstack_base.rb @@ -0,0 +1,25 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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 OpenstackclientCookbook + class OpenstackBase < Chef::Resource + require 'fog/openstack' + def connection + @connection_cache ||= Fog::Identity::OpenStack + .new(new_resource.connection_params) + end + end +end diff --git a/libraries/openstack_domain.rb b/libraries/openstack_domain.rb new file mode 100644 index 0000000..acef8e2 --- /dev/null +++ b/libraries/openstack_domain.rb @@ -0,0 +1,48 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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_relative 'openstack_base' +module OpenstackclientCookbook + class OpenstackDomain < OpenstackBase + resource_name :openstack_domain + + property :domain_name, String, name_property: true + property :connection_params, Hash, required: true + + default_action :create + + action :create do + domain = connection.domains.find { |u| u.id == domain_name } || + connection.domains.find { |u| u.name == domain_name } + if domain + log "Domain with name: \"#{domain_name}\" already exists" + else + connection.domains.create( + name: domain_name + ) + end + end + + action :delete do + domain = connection.domains.find { |u| u.name == domain_name } + if domain + domain.destroy + else + log "Domain with name: \"#{domain_name}\" doesn't exist" + end + end + end +end diff --git a/libraries/openstack_endpoint.rb b/libraries/openstack_endpoint.rb new file mode 100644 index 0000000..8c27db3 --- /dev/null +++ b/libraries/openstack_endpoint.rb @@ -0,0 +1,62 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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_relative 'openstack_base' +module OpenstackclientCookbook + class OpenstackEndpoint < OpenstackBase + resource_name :openstack_endpoint + + property :endpoint_name, String, name_property: true + property :service_name, String, required: true + property :interface, String, required: true + property :url, String, required: true + property :region, String + property :connection_params, Hash, required: true + + default_action :create + + action :create do + service = connection.services.find { |s| s.name == service_name } + endpoint = connection.endpoints.find do |e| + e.service_id == service.id && e.interface == interface + end + + if endpoint + log "#{interface}_endpoint for \"#{service_name}\" already exists" + else + connection.endpoints.create( + interface: interface, + url: url, + service_id: service.id, + name: endpoint_name, + region: region + ) + end + end + + action :delete do + service = connection.services.find { |s| s.name == service_name } + endpoint = connection.endpoints.find do |e| + e.service_id == service.id && e.interface == interface + end + if endpoint + connection.endpoints.destroy(endpoint.id) + else + log "#{interface}_endpoint for \"#{service_name}\" doesn't exist" + end + end + end +end diff --git a/libraries/openstack_project.rb b/libraries/openstack_project.rb new file mode 100644 index 0000000..731bdc8 --- /dev/null +++ b/libraries/openstack_project.rb @@ -0,0 +1,45 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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_relative 'openstack_base' +module OpenstackclientCookbook + class OpenstackProject < OpenstackBase + resource_name :openstack_project + + property :project_name, String, name_property: true + property :connection_params, Hash, required: true + + default_action :create + + action :create do + project = connection.projects.find { |p| p.name == project_name } + if project + log "Project with name: \"#{project_name}\" already exists" + else + connection.projects.create name: project_name + end + end + + action :delete do + project = connection.projects.find { |p| p.name == project_name } + if project + project.destroy + else + log "Project with name: \"#{project_name}\" doesn't exist" + end + end + end +end diff --git a/libraries/openstack_role.rb b/libraries/openstack_role.rb new file mode 100644 index 0000000..79fa88b --- /dev/null +++ b/libraries/openstack_role.rb @@ -0,0 +1,45 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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_relative 'openstack_base' +module OpenstackclientCookbook + class OpenstackRole < OpenstackBase + resource_name :openstack_role + + property :role_name, String, name_property: true + property :connection_params, Hash, required: true + + default_action :create + + action :create do + role = connection.roles.find { |r| r.name == role_name } + if role + log "Role with name: \"#{role_name}\" already exists" + else + connection.roles.create name: role_name + end + end + + action :delete do + role = connection.roles.find { |r| r.name == role_name } + if role + role.destroy + else + log "Role with name: \"#{role_name}\" doesn't exist" + end + end + end +end diff --git a/libraries/openstack_service.rb b/libraries/openstack_service.rb new file mode 100644 index 0000000..76e035d --- /dev/null +++ b/libraries/openstack_service.rb @@ -0,0 +1,49 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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_relative 'openstack_base' +module OpenstackclientCookbook + class OpenstackService < OpenstackBase + resource_name :openstack_service + + property :service_name, String, name_property: true + property :type, String, required: true + property :connection_params, Hash, required: true + + default_action :create + + action :create do + service = connection.services.find { |s| s.name == service_name } + if service + log "Service with name: \"#{service_name}\" already exists" + else + connection.services.create( + name: service_name, + type: type + ) + end + end + + action :delete do + service = connection.services.find { |s| s.name == service_name } + if service + service.destroy + else + log "Service with name: \"#{service_name}\" doesn't exist" + end + end + end +end diff --git a/libraries/openstack_user.rb b/libraries/openstack_user.rb new file mode 100644 index 0000000..524d01f --- /dev/null +++ b/libraries/openstack_user.rb @@ -0,0 +1,82 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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_relative 'openstack_base' +module OpenstackclientCookbook + class OpenstackUser < OpenstackBase + resource_name :openstack_user + + property :user_name, String, name_property: true + property :email, String, default: 'defaultmail' + property :password, String, default: 'defaultpass' + property :role_name, String + property :project_name, String + property :domain_name, String + property :connection_params, Hash, required: true + + default_action :create + + action :create do + user = connection.users.find { |u| u.name == user_name } + if user + log "User with name: \"#{user_name}\" already exists" + else + connection.users.create( + name: user_name, + email: email, + password: password + ) + end + end + + action :delete do + user = connection.users.find { |u| u.name == user_name } + if user + user.destroy + else + log "User with name: \"#{user_name}\" doesn't exist" + end + end + + action :grant_role do + user = connection.users.find { |u| u.name == user_name } + project = connection.projects.find { |p| p.name == project_name } + role = connection.roles.find { |r| r.name == role_name } + project.grant_role_to_user role.id, user.id if role && project && user + end + + action :revoke_role do + user = connection.users.find { |u| u.name == user_name } + project = connection.projects.find { |p| p.name == project_name } + role = connection.roles.find { |r| r.name == role_name } + project.revoke_role_from_user role.id, user.id if role && project && user + end + + action :grant_domain do + user = connection.users.find { |u| u.name == user_name } + domain = connection.domains.find { |p| p.name == domain_name } + role = connection.roles.find { |r| r.name == role_name } + domain.grant_domain_user_role user.id, role.id if role && domain && user + end + + action :revoke_domain do + user = connection.users.find { |u| u.name == user_name } + domain = connection.domains.find { |p| p.name == domain_name } + role = connection.roles.find { |r| r.name == role_name } + domain.revoke_domain_user_role user.id, role.id if role && domain && user + end + end +end diff --git a/metadata.rb b/metadata.rb new file mode 100644 index 0000000..7e4b961 --- /dev/null +++ b/metadata.rb @@ -0,0 +1,26 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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. + +name 'openstackclient' +maintainer 'cloudbau GmbH' +maintainer_email 'j.klare@cloudbau.de' +license 'Apache v2.0' +description 'Installs the fog-openstack gem and offers LWRPs to use it' +issues_url 'https://github.com/cloudbau/cookbook-openstackclient/issues' +source_url 'https://github.com/cloudbau/cookbook-openstackclient' +version '0.1.0' + +gem 'fog-openstack' diff --git a/spec/cookbooks/openstackclient_test/metadata.rb b/spec/cookbooks/openstackclient_test/metadata.rb new file mode 100644 index 0000000..1b3e3c8 --- /dev/null +++ b/spec/cookbooks/openstackclient_test/metadata.rb @@ -0,0 +1,20 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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. + +name 'openstackclient_test' +version '0.0.1' + +depends 'openstackclient' diff --git a/spec/cookbooks/openstackclient_test/recipes/domain.rb b/spec/cookbooks/openstackclient_test/recipes/domain.rb new file mode 100644 index 0000000..96e9c27 --- /dev/null +++ b/spec/cookbooks/openstackclient_test/recipes/domain.rb @@ -0,0 +1,32 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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. + +connection_params = { + openstack_auth_url: 'http://devstack.test:5000/v3/auth/tokens', + openstack_username: 'admin', + openstack_api_key: 'password', + openstack_project_name: 'admin', + openstack_domain_id: 'default' +} + +openstack_domain 'mydomain' do + connection_params connection_params +end + +openstack_domain 'mydomain' do + connection_params connection_params + action :delete +end diff --git a/spec/cookbooks/openstackclient_test/recipes/endpoint.rb b/spec/cookbooks/openstackclient_test/recipes/endpoint.rb new file mode 100644 index 0000000..87e01e7 --- /dev/null +++ b/spec/cookbooks/openstackclient_test/recipes/endpoint.rb @@ -0,0 +1,40 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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. + +connection_params = { + openstack_auth_url: 'http://devstack.test:5000/v3/auth/tokens', + openstack_username: 'admin', + openstack_api_key: 'password', + openstack_project_name: 'admin', + openstack_domain_id: 'default' +} + +%w(public internal admin).each do |interface| + openstack_endpoint "myendpoint_#{interface}" do + service_name 'myservice' + interface interface + url "http://localhost:80/#{interface}" + connection_params connection_params + end + + openstack_endpoint "myendpoint_#{interface}" do + service_name 'myservice' + interface interface + url "http://localhost:80/#{interface}" + connection_params connection_params + action :delete + end +end diff --git a/spec/cookbooks/openstackclient_test/recipes/project.rb b/spec/cookbooks/openstackclient_test/recipes/project.rb new file mode 100644 index 0000000..ab96087 --- /dev/null +++ b/spec/cookbooks/openstackclient_test/recipes/project.rb @@ -0,0 +1,32 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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. + +connection_params = { + openstack_auth_url: 'http://devstack.test:5000/v3/auth/tokens', + openstack_username: 'admin', + openstack_api_key: 'password', + openstack_project_name: 'admin', + openstack_domain_id: 'default' +} + +openstack_project 'myproject' do + connection_params connection_params +end + +openstack_project 'myproject' do + connection_params connection_params + action :delete +end diff --git a/spec/cookbooks/openstackclient_test/recipes/role.rb b/spec/cookbooks/openstackclient_test/recipes/role.rb new file mode 100644 index 0000000..3071aa7 --- /dev/null +++ b/spec/cookbooks/openstackclient_test/recipes/role.rb @@ -0,0 +1,32 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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. + +connection_params = { + openstack_auth_url: 'http://devstack.test:5000/v3/auth/tokens', + openstack_username: 'admin', + openstack_api_key: 'password', + openstack_project_name: 'admin', + openstack_domain_id: 'default' +} + +openstack_role 'myrole' do + connection_params connection_params +end + +openstack_role 'myrole' do + connection_params connection_params + action :delete +end diff --git a/spec/cookbooks/openstackclient_test/recipes/service.rb b/spec/cookbooks/openstackclient_test/recipes/service.rb new file mode 100644 index 0000000..aedfe59 --- /dev/null +++ b/spec/cookbooks/openstackclient_test/recipes/service.rb @@ -0,0 +1,34 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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. + +connection_params = { + openstack_auth_url: 'http://devstack.test:5000/v3/auth/tokens', + openstack_username: 'admin', + openstack_api_key: 'password', + openstack_project_name: 'admin', + openstack_domain_id: 'default' +} + +openstack_service 'myservice' do + type 'mytype' + connection_params connection_params +end + +openstack_service 'myservice' do + type 'mytype' + connection_params connection_params + action :delete +end diff --git a/spec/cookbooks/openstackclient_test/recipes/user.rb b/spec/cookbooks/openstackclient_test/recipes/user.rb new file mode 100644 index 0000000..2eb6ec5 --- /dev/null +++ b/spec/cookbooks/openstackclient_test/recipes/user.rb @@ -0,0 +1,64 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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. + +connection_params = { + openstack_auth_url: 'http://devstack.test:5000/v3/auth/tokens', + openstack_username: 'admin', + openstack_api_key: 'password', + openstack_project_name: 'admin', + openstack_domain_id: 'default' +} + +openstack_user 'myuser' do + email 'myemail' + password 'mypassword' + connection_params connection_params +end + +openstack_user 'myuser' do + connection_params connection_params + action :delete +end + +openstack_user 'myuser' do + role_name 'myrole' + project_name 'myproject' + connection_params connection_params + action :grant_role +end + +openstack_user 'myuser' do + role_name 'myrole' + project_name 'myproject' + connection_params connection_params + action :revoke_role +end + +openstack_user 'myuser' do + role_name 'myrole' + project_name 'myproject' + domain_name 'mydomain' + connection_params connection_params + action :grant_domain +end + +openstack_user 'myuser' do + role_name 'myrole' + project_name 'myproject' + domain_name 'mydomain' + connection_params connection_params + action :revoke_domain +end diff --git a/spec/domain_spec.rb b/spec/domain_spec.rb new file mode 100644 index 0000000..e639541 --- /dev/null +++ b/spec/domain_spec.rb @@ -0,0 +1,139 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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 'spec_helper' +require_relative '../libraries/openstack_domain' + +describe 'openstackclient_test::domain' do + let(:chef_run) do + runner = ChefSpec::SoloRunner.new(step_into: ['openstack_domain']) + runner.converge(described_recipe) + end + + let(:domains_empty) do + double :domains, + create: true, + destroy: true, + find: nil + end + + let(:found_domain) do + double :find, + destroy: true + end + + let(:domains_populated) do + double :domains, + create: true, + destroy: true, + find: found_domain + end + + context 'no domains defined' do + let(:connection_dub) do + double :fog_connection, + domains: domains_empty + end + + before do + allow_any_instance_of(OpenstackclientCookbook::OpenstackDomain) + .to receive(:connection).and_return(connection_dub) + end + + it do + expect(connection_dub).to receive(:domains) + chef_run + end + + it do + expect(chef_run).to create_openstack_domain('mydomain') + end + + it do + expect(chef_run).to delete_openstack_domain('mydomain') + end + + it do + expect(chef_run).to write_log( + 'Domain with name: "mydomain" doesn\'t exist' + ) + end + + it do + expect(chef_run).not_to write_log( + 'Domain with name: "mydomain" already exists' + ) + end + + it do + expect(domains_empty).to receive(:create) + .with(name: 'mydomain') + chef_run + end + + it do + expect(found_domain).not_to receive(:destory) + chef_run + end + end + + context 'domains defined' do + let(:connection_dub) do + double :fog_connection, + domains: domains_populated + end + + before do + allow_any_instance_of(OpenstackclientCookbook::OpenstackDomain) + .to receive(:connection).and_return(connection_dub) + end + + it do + expect(connection_dub).to receive(:domains) + chef_run + end + + it do + expect(chef_run).to create_openstack_domain('mydomain') + end + + it do + expect(chef_run).to delete_openstack_domain('mydomain') + end + + it do + expect(chef_run).not_to write_log( + 'Domain with name: "mydomain" doesn\'t exist' + ) + end + + it do + expect(chef_run).to write_log( + 'Domain with name: "mydomain" already exists' + ) + end + + it do + expect(domains_populated).not_to receive(:create) + chef_run + end + + it do + expect(found_domain).to receive(:destroy) + chef_run + end + end +end diff --git a/spec/endpoint_spec.rb b/spec/endpoint_spec.rb new file mode 100644 index 0000000..dc2286c --- /dev/null +++ b/spec/endpoint_spec.rb @@ -0,0 +1,165 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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 'spec_helper' +require_relative '../libraries/openstack_endpoint' + +describe 'openstackclient_test::endpoint' do + let(:chef_run) do + runner = ChefSpec::SoloRunner.new(step_into: ['openstack_endpoint']) + runner.converge(described_recipe) + end + + let(:services_dub) do + double :services, + find: double(id: 1) + end + + let(:endpoints_empty) do + double :endpoints, + create: true, + destroy: true, + find: nil + end + + let(:endpoints_populated) do + double :endpoints, + create: true, + destroy: true, + find: double(id: 2) + end + + context 'no endpoints defined' do + let(:connection_dub) do + double :fog_connection, + services: services_dub, + endpoints: endpoints_empty + end + + before do + allow_any_instance_of(OpenstackclientCookbook::OpenstackEndpoint) + .to receive(:connection).and_return(connection_dub) + end + + it do + expect(connection_dub).to receive(:endpoints) + chef_run + end + + it do + expect(connection_dub).to receive(:services) + chef_run + end + + %w(public internal admin).each do |interface| + it do + expect(chef_run).to write_log( + "#{interface}_endpoint for \"myservice\" doesn't exist" + ) + end + + it do + expect(chef_run).not_to write_log( + "#{interface}_endpoint for \"myservice\" already exists" + ) + end + + it do + expect(chef_run).to create_openstack_endpoint("myendpoint_#{interface}") + end + + it do + expect(chef_run).to delete_openstack_endpoint("myendpoint_#{interface}") + end + + it do + expect(endpoints_empty).to receive(:create) + .with( + interface: interface, + url: "http://localhost:80/#{interface}", + service_id: 1, + name: "myendpoint_#{interface}", + region: nil + ) + chef_run + end + it do + expect(endpoints_empty).not_to receive(:destroy) + chef_run + end + end + end + + context 'endpoints defined' do + let(:connection_dub) do + double :fog_connection, + services: services_dub, + endpoints: endpoints_populated + end + before do + allow_any_instance_of(OpenstackclientCookbook::OpenstackEndpoint) + .to receive(:connection).and_return(connection_dub) + end + it do + expect(connection_dub).to receive(:endpoints) + chef_run + end + + it do + expect(connection_dub).to receive(:services) + chef_run + end + %w(public internal admin).each do |interface| + it do + expect(chef_run).not_to write_log( + "#{interface}_endpoint for \"myservice\" doesn't exist" + ) + end + + it do + expect(chef_run).to write_log( + "#{interface}_endpoint for \"myservice\" already exists" + ) + end + + it do + expect(chef_run).to create_openstack_endpoint("myendpoint_#{interface}") + end + + it do + expect(chef_run).to delete_openstack_endpoint("myendpoint_#{interface}") + end + + it do + expect(endpoints_populated).not_to receive(:create) + .with( + interface: interface, + url: "http://localhost:80/#{interface}", + service_id: 1, + name: "myendpoint_#{interface}", + region: nil + ) + chef_run + end + + it do + expect(endpoints_populated).to receive(:destroy) + .with(2) + chef_run + end + end + end +end diff --git a/spec/project_spec.rb b/spec/project_spec.rb new file mode 100644 index 0000000..c5e7d0e --- /dev/null +++ b/spec/project_spec.rb @@ -0,0 +1,141 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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 'spec_helper' +require_relative '../libraries/openstack_project' + +describe 'openstackclient_test::project' do + let(:chef_run) do + runner = ChefSpec::SoloRunner.new(step_into: ['openstack_project']) + runner.converge(described_recipe) + end + + let(:projects_empty) do + double :projects, + create: true, + destroy: true, + find: nil + end + + let(:found_project) do + double :find, + destroy: true + end + + let(:projects_populated) do + double :projects, + create: true, + destroy: true, + find: found_project + end + + context 'no projects defined' do + let(:connection_dub) do + double :fog_connection, + projects: projects_empty + end + + before do + allow_any_instance_of(OpenstackclientCookbook::OpenstackProject) + .to receive(:connection).and_return(connection_dub) + end + + it do + expect(connection_dub).to receive(:projects) + chef_run + end + + it do + expect(chef_run).to create_openstack_project('myproject') + end + + it do + expect(chef_run).to delete_openstack_project('myproject') + end + + it do + expect(chef_run).to write_log( + 'Project with name: "myproject" doesn\'t exist' + ) + end + + it do + expect(chef_run).not_to write_log( + 'Project with name: "myproject" already exists' + ) + end + + it do + expect(projects_empty).to receive(:create) + .with( + name: 'myproject' + ) + chef_run + end + + it do + expect(found_project).not_to receive(:destroy) + chef_run + end + end + + context 'projects defined' do + let(:connection_dub) do + double :fog_connection, + projects: projects_populated + end + + before do + allow_any_instance_of(OpenstackclientCookbook::OpenstackProject) + .to receive(:connection).and_return(connection_dub) + end + + it do + expect(connection_dub).to receive(:projects) + chef_run + end + + it do + expect(chef_run).to create_openstack_project('myproject') + end + + it do + expect(chef_run).to delete_openstack_project('myproject') + end + + it do + expect(chef_run).not_to write_log( + 'Project with name: "myproject" doesn\'t exist' + ) + end + + it do + expect(chef_run).to write_log( + 'Project with name: "myproject" already exists' + ) + end + + it do + expect(projects_empty).not_to receive(:create) + chef_run + end + + it do + expect(found_project).to receive(:destroy) + chef_run + end + end +end diff --git a/spec/role_spec.rb b/spec/role_spec.rb new file mode 100644 index 0000000..c0531c2 --- /dev/null +++ b/spec/role_spec.rb @@ -0,0 +1,141 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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 'spec_helper' +require_relative '../libraries/openstack_role' + +describe 'openstackclient_test::role' do + let(:chef_run) do + runner = ChefSpec::SoloRunner.new(step_into: ['openstack_role']) + runner.converge(described_recipe) + end + + let(:roles_empty) do + double :role, + create: true, + destroy: true, + find: nil + end + + let(:found_role) do + double :find, + destroy: true + end + + let(:roles_populated) do + double :role, + create: true, + destroy: true, + find: found_role + end + + context 'no roles defined' do + let(:connection_dub) do + double :fog_connection, + roles: roles_empty + end + + before do + allow_any_instance_of(OpenstackclientCookbook::OpenstackRole) + .to receive(:connection).and_return(connection_dub) + end + + it do + expect(connection_dub).to receive(:roles) + chef_run + end + + it do + expect(chef_run).to create_openstack_role('myrole') + end + + it do + expect(chef_run).to delete_openstack_role('myrole') + end + + it do + expect(chef_run).to write_log( + 'Role with name: "myrole" doesn\'t exist' + ) + end + + it do + expect(chef_run).not_to write_log( + 'Role with name: "myrole" already exists' + ) + end + + it do + expect(roles_empty).to receive(:create) + .with( + name: 'myrole' + ) + chef_run + end + + it do + expect(found_role).not_to receive(:destroy) + chef_run + end + end + + context 'roles defined' do + let(:connection_dub) do + double :fog_connection, + roles: roles_populated + end + + before do + allow_any_instance_of(OpenstackclientCookbook::OpenstackRole) + .to receive(:connection).and_return(connection_dub) + end + + it do + expect(connection_dub).to receive(:roles) + chef_run + end + + it do + expect(chef_run).to create_openstack_role('myrole') + end + + it do + expect(chef_run).to delete_openstack_role('myrole') + end + + it do + expect(chef_run).not_to write_log( + 'Role with name: "myrole" doesn\'t exist' + ) + end + + it do + expect(chef_run).to write_log( + 'Role with name: "myrole" already exists' + ) + end + + it do + expect(roles_empty).not_to receive(:create) + chef_run + end + + it do + expect(found_role).to receive(:destroy) + chef_run + end + end +end diff --git a/spec/service_spec.rb b/spec/service_spec.rb new file mode 100644 index 0000000..1aec03e --- /dev/null +++ b/spec/service_spec.rb @@ -0,0 +1,142 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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 'spec_helper' +require_relative '../libraries/openstack_service' + +describe 'openstackclient_test::service' do + let(:chef_run) do + runner = ChefSpec::SoloRunner.new(step_into: ['openstack_service']) + runner.converge(described_recipe) + end + + let(:services_empty) do + double :service, + create: true, + destroy: true, + find: nil + end + + let(:found_service) do + double :find, + destroy: true + end + + let(:services_populated) do + double :service, + create: true, + destroy: true, + find: found_service + end + + context 'no services defined' do + let(:connection_dub) do + double :fog_connection, + services: services_empty + end + + before do + allow_any_instance_of(OpenstackclientCookbook::OpenstackService) + .to receive(:connection).and_return(connection_dub) + end + + it do + expect(connection_dub).to receive(:services) + chef_run + end + + it do + expect(chef_run).to create_openstack_service('myservice') + end + + it do + expect(chef_run).to delete_openstack_service('myservice') + end + + it do + expect(chef_run).to write_log( + 'Service with name: "myservice" doesn\'t exist' + ) + end + + it do + expect(chef_run).not_to write_log( + 'Service with name: "myservice" already exists' + ) + end + + it do + expect(services_empty).to receive(:create) + .with( + name: 'myservice', + type: 'mytype' + ) + chef_run + end + + it do + expect(found_service).not_to receive(:destroy) + chef_run + end + end + + context 'services defined' do + let(:connection_dub) do + double :fog_connection, + services: services_populated + end + + before do + allow_any_instance_of(OpenstackclientCookbook::OpenstackService) + .to receive(:connection).and_return(connection_dub) + end + + it do + expect(connection_dub).to receive(:services) + chef_run + end + + it do + expect(chef_run).to create_openstack_service('myservice') + end + + it do + expect(chef_run).to delete_openstack_service('myservice') + end + + it do + expect(chef_run).not_to write_log( + 'Service with name: "myservice" doesn\'t exist' + ) + end + + it do + expect(chef_run).to write_log( + 'Service with name: "myservice" already exists' + ) + end + + it do + expect(services_empty).not_to receive(:create) + chef_run + end + + it do + expect(found_service).to receive(:destroy) + chef_run + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb new file mode 100644 index 0000000..c52199f --- /dev/null +++ b/spec/spec_helper.rb @@ -0,0 +1,26 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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 'chefspec' +require 'chefspec/berkshelf' +require 'fog/openstack' + +RSpec.configure do |config| + config.color = true + config.log_level = :error +end + +at_exit { ChefSpec::Coverage.report! } diff --git a/spec/user_spec.rb b/spec/user_spec.rb new file mode 100644 index 0000000..bdecc54 --- /dev/null +++ b/spec/user_spec.rb @@ -0,0 +1,252 @@ +# encoding: UTF-8 +# +# Copyright 2016 cloudbau GmbH +# +# 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 'spec_helper' +require_relative '../libraries/openstack_user' + +describe 'openstackclient_test::user' do + let(:chef_run) do + runner = ChefSpec::SoloRunner.new(step_into: ['openstack_user']) + runner.converge(described_recipe) + end + + let(:users_empty) do + double :user, + create: true, + destroy: true, + find: nil + end + + let(:found_user) do + double :find, + id: 4, + destroy: true + end + + let(:users_populated) do + double :user, + create: true, + destroy: true, + find: found_user + end + + let(:found_role) do + double :find, + id: 3 + end + + let(:roles_populated) do + double :role, + find: found_role + end + + let(:found_domain) do + double :find, + grant_domain_user_role: true, + revoke_domain_user_role: true + end + + let(:domains_populated) do + double :domains, + find: found_domain + end + + let(:found_project) do + double :find, + grant_role_to_user: true, + revoke_role_from_user: true + end + + let(:projects_populated) do + double :projects, + find: found_project + end + + context 'no users defined' do + let(:connection_dub) do + double :fog_connection, + users: users_empty, + domains: domains_populated, + roles: roles_populated, + projects: projects_populated + end + + before do + allow_any_instance_of(OpenstackclientCookbook::OpenstackUser) + .to receive(:connection).and_return(connection_dub) + end + + it do + expect(connection_dub).to receive(:users) + chef_run + end + + it do + expect(connection_dub).to receive(:domains) + chef_run + end + + it do + expect(connection_dub).to receive(:roles) + chef_run + end + + it do + expect(connection_dub).to receive(:projects) + chef_run + end + + it do + expect(chef_run).to create_openstack_user('myuser') + end + + it do + expect(chef_run).to delete_openstack_user('myuser') + end + + it do + expect(chef_run).to write_log( + 'User with name: "myuser" doesn\'t exist' + ) + end + + it do + expect(chef_run).not_to write_log( + 'User with name: "myuser" already exists' + ) + end + + it do + expect(users_empty).to receive(:create) + .with( + name: 'myuser', + email: 'myemail', + password: 'mypassword' + ) + chef_run + end + + it do + expect(found_user).not_to receive(:destroy) + chef_run + end + end + + context 'users defined' do + let(:connection_dub) do + double :fog_connection, + users: users_populated, + domains: domains_populated, + roles: roles_populated, + projects: projects_populated + end + + before do + allow_any_instance_of(OpenstackclientCookbook::OpenstackUser) + .to receive(:connection).and_return(connection_dub) + end + + it do + expect(connection_dub).to receive(:users) + chef_run + end + + it do + expect(connection_dub).to receive(:domains) + chef_run + end + + it do + expect(connection_dub).to receive(:roles) + chef_run + end + + it do + expect(connection_dub).to receive(:projects) + chef_run + end + + it do + expect(chef_run).to create_openstack_user('myuser') + end + + it do + expect(chef_run).to delete_openstack_user('myuser') + end + + it do + expect(chef_run).not_to write_log( + 'User with name: "myuser" doesn\'t exist' + ) + end + + it do + expect(chef_run).to write_log( + 'User with name: "myuser" already exists' + ) + end + + it do + expect(chef_run).to grant_role_openstack_user('myuser') + end + + it do + expect(chef_run).to revoke_role_openstack_user('myuser') + end + + it do + expect(chef_run).to grant_domain_openstack_user('myuser') + end + + it do + expect(chef_run).to revoke_domain_openstack_user('myuser') + end + + it do + expect(users_empty).not_to receive(:create) + chef_run + end + + it do + expect(found_user).to receive(:destroy) + chef_run + end + + it do + expect(found_project).to receive(:grant_role_to_user) + .with(3, 4) + chef_run + end + + it do + expect(found_project).to receive(:revoke_role_from_user) + .with(3, 4) + chef_run + end + + it do + expect(found_domain).to receive(:grant_domain_user_role) + .with(4, 3) + chef_run + end + + it do + expect(found_domain).to receive(:revoke_domain_user_role) + .with(4, 3) + chef_run + end + end +end