From c6ca94ca712ebe671fc72f111eb379e86bc022d9 Mon Sep 17 00:00:00 2001 From: Gary Zheng Date: Thu, 28 Apr 2016 11:45:19 -0400 Subject: [PATCH] Version 0.4.5 - 4/25/2016 1. Added OneFlow resources (see readme): one_flow_template, one_flow_service. 2. Added RSpec tests for OneFlow. 3. Fixed RSpec tests for newest chef-client 12.9.38. 4. Fixed bug regarding destroying machines when machine_spec.reference is nil. 5. Permitted driver profile switching. 6. Added backwards compatibility for managing machines provisioned with gem versions prior to v0.3.3. 7. Added ability to automatically choose the correct opennebula gem version depending on server version. --- CHANGELOG.md | 9 + README.md | 277 ++++++++- chef-provisioning-opennebula.gemspec | 4 +- lib/chef/provider/one_flow_service.rb | 346 +++++++++++ lib/chef/provider/one_flow_template.rb | 175 ++++++ lib/chef/provider/one_image.rb | 12 +- lib/chef/provider/one_template.rb | 2 +- lib/chef/provider/one_user.rb | 8 +- lib/chef/provider/one_vnet.rb | 10 +- lib/chef/provider/one_vnet_lease.rb | 6 +- .../provisioning/driver_init/opennebula.rb | 2 +- .../driver_init/server_version.rb | 28 + lib/chef/provisioning/opennebula_driver.rb | 2 +- .../opennebula_driver/credentials.rb | 2 +- .../provisioning/opennebula_driver/driver.rb | 140 ++++- .../opennebula_driver/flow_lib.rb | 491 ++++++++++++++++ .../provisioning/opennebula_driver/one_lib.rb | 36 +- .../opennebula_driver/resources.rb | 4 +- .../provisioning/opennebula_driver/version.rb | 4 +- lib/chef/resource/one_flow_service.rb | 61 ++ lib/chef/resource/one_flow_template.rb | 53 ++ lib/chef/resource/one_image.rb | 4 +- lib/chef/resource/one_template.rb | 2 +- lib/chef/resource/one_user.rb | 2 +- lib/chef/resource/one_vnet.rb | 4 +- lib/chef/resource/one_vnet_lease.rb | 2 +- spec/config_sample.rb | 15 +- spec/integration/test_all_integration_spec.rb | 278 +-------- spec/integration/test_one_driver.rb | 177 ++++++ spec/integration/test_one_flow.rb | 546 ++++++++++++++++++ ...ate_spec.rb => allocate_change_profile.rb} | 12 +- ...ack_two_vm_spec.rb => attach_one_image.rb} | 9 +- .../OneDriver/create_back_one_vm_spec.rb | 20 - .../OneDriver/create_back_two_vm_spec.rb | 20 - spec/recipes/OneDriver/create_one_image.rb | 20 + ...nt_spec.rb => create_one_template_ints.rb} | 25 +- .../OneDriver/create_one_template_mix.rb | 51 ++ .../OneDriver/create_one_template_spec.rb | 21 - ...spec.rb => create_one_template_strings.rb} | 25 +- ...back_one_vm_spec.rb => create_one_vnet.rb} | 10 +- .../delete/OpenNebula-bootstrap-img.rb | 19 - .../OneDriver/delete/OpenNebula-snap-1-img.rb | 19 - .../OneDriver/delete/OpenNebula-snap-2-img.rb | 19 - ...ula-tpl-1-vm.rb => OpenNebula-test-img.rb} | 6 +- ...ck-1-vm.rb => OpenNebula-test-snap-img.rb} | 6 +- .../delete/OpenNebula-test-tpl-ints.rb | 6 +- ...test-tpl.rb => OpenNebula-test-tpl-mix.rb} | 6 +- .../delete/OpenNebula-test-tpl-strings.rb | 17 + ...ack-2-vm.rb => OpenNebula-test-vm-vnet.rb} | 6 +- ...-bootstrap-vm.rb => OpenNebula-test-vm.rb} | 6 +- .../OneDriver/delete/OpenNebula-test-vnet.rb | 17 + ...vm_spec.rb => instantiate_one_template.rb} | 13 +- ...ec.rb => instantiate_one_template_vnet.rb} | 18 +- spec/recipes/OneDriver/snapshot_one_image.rb | 19 + .../OneDriver/snapshot_one_image_spec.rb | 21 - .../OneDriver/snapshot_two_image_spec.rb | 21 - spec/recipes/OneFlowService/action/boot.rb | 19 + spec/recipes/OneFlowService/action/delete.rb | 18 + .../OneFlowService/action/delete_recreate.rb | 18 + spec/recipes/OneFlowService/action/hold.rb | 19 + .../recipes/OneFlowService/action/poweroff.rb | 18 + .../OneFlowService/action/poweroff_hard.rb | 18 + spec/recipes/OneFlowService/action/reboot.rb | 18 + .../OneFlowService/action/reboot_hard.rb | 18 + spec/recipes/OneFlowService/action/release.rb | 19 + spec/recipes/OneFlowService/action/resume.rb | 18 + spec/recipes/OneFlowService/action/scale.rb | 19 + .../recipes/OneFlowService/action/shutdown.rb | 18 + .../OneFlowService/action/shutdown_hard.rb | 18 + .../OneFlowService/action/shutdown_service.rb | 17 + .../OneFlowService/action/snapshot_create.rb | 18 + spec/recipes/OneFlowService/action/stop.rb | 18 + spec/recipes/OneFlowService/action/suspend.rb | 18 + .../recipes/OneFlowService/action/undeploy.rb | 18 + .../OneFlowService/action/undeploy_hard.rb | 18 + .../OneFlowService/chmod_simple_by_name.rb | 19 + .../OneFlowService/chmod_simple_by_name_2.rb | 18 + spec/recipes/OneFlowService/chmod_tpl_opts.rb | 31 + .../delete/test_instance_template_options.rb | 17 + .../OneFlowService/delete/test_role_action.rb | 17 + .../delete/test_simple_instance.rb | 17 + .../delete/test_simple_instance_by_id.rb | 17 + .../instance_role_action.rb} | 30 +- .../OneFlowService/instance_simple_by_id.rb | 20 + .../OneFlowService/instance_simple_by_name.rb | 18 + .../OneFlowService/instance_tpl_opts.rb | 30 + .../OneFlowTemplate/chmod_simple_from_hash.rb | 17 + .../chmod_update_simple_from_file.rb | 19 + .../create_branch_from_one_id.rb | 43 ++ .../create_branch_from_one_name.rb | 20 + .../create_role_action_instance.rb | 99 ++++ .../create_simple_from_file.rb | 18 + .../create_simple_from_hash.rb} | 14 +- .../OneFlowTemplate/create_simple_from_web.rb | 17 + .../create_simple_instance_tpl.rb} | 14 +- .../create_tpl_opts_from_file.rb | 30 + .../create_tpl_opts_from_hash.rb | 35 ++ .../delete/branch_from_one_id.rb | 17 + .../delete/branch_from_one_name.rb | 17 + .../delete/role_action_instance.rb | 17 + .../delete/simple_from_file.rb | 17 + .../delete/simple_from_hash.rb | 17 + .../OneFlowTemplate/delete/simple_from_web.rb | 17 + .../delete/simple_instance_tpl.rb | 17 + .../delete/tpl_opts_from_file.rb | 17 + .../delete/tpl_opts_from_hash.rb | 17 + .../update_simple_from_hash.rb | 57 ++ .../{driver_options_spec.rb => common.rb} | 12 +- spec/spec_helper.rb | 39 +- spec/support/opennebula_support.rb | 120 ++-- 110 files changed, 3738 insertions(+), 682 deletions(-) create mode 100644 lib/chef/provider/one_flow_service.rb create mode 100644 lib/chef/provider/one_flow_template.rb create mode 100644 lib/chef/provisioning/driver_init/server_version.rb create mode 100644 lib/chef/provisioning/opennebula_driver/flow_lib.rb create mode 100644 lib/chef/resource/one_flow_service.rb create mode 100644 lib/chef/resource/one_flow_template.rb create mode 100644 spec/integration/test_one_driver.rb create mode 100644 spec/integration/test_one_flow.rb rename spec/recipes/OneDriver/{instantiate_one_template_spec.rb => allocate_change_profile.rb} (73%) rename spec/recipes/OneDriver/{converge_back_two_vm_spec.rb => attach_one_image.rb} (80%) delete mode 100644 spec/recipes/OneDriver/create_back_one_vm_spec.rb delete mode 100644 spec/recipes/OneDriver/create_back_two_vm_spec.rb create mode 100644 spec/recipes/OneDriver/create_one_image.rb rename spec/recipes/OneDriver/{create_one_template_int_spec.rb => create_one_template_ints.rb} (58%) create mode 100644 spec/recipes/OneDriver/create_one_template_mix.rb delete mode 100644 spec/recipes/OneDriver/create_one_template_spec.rb rename spec/recipes/OneDriver/{create_one_image_spec.rb => create_one_template_strings.rb} (59%) rename spec/recipes/OneDriver/{converge_back_one_vm_spec.rb => create_one_vnet.rb} (80%) delete mode 100644 spec/recipes/OneDriver/delete/OpenNebula-bootstrap-img.rb delete mode 100644 spec/recipes/OneDriver/delete/OpenNebula-snap-1-img.rb delete mode 100644 spec/recipes/OneDriver/delete/OpenNebula-snap-2-img.rb rename spec/recipes/OneDriver/delete/{OpenNebula-tpl-1-vm.rb => OpenNebula-test-img.rb} (83%) rename spec/recipes/OneDriver/delete/{OpenNebula-back-1-vm.rb => OpenNebula-test-snap-img.rb} (83%) rename spec/recipes/OneDriver/delete/{OpenNebula-test-tpl.rb => OpenNebula-test-tpl-mix.rb} (82%) create mode 100644 spec/recipes/OneDriver/delete/OpenNebula-test-tpl-strings.rb rename spec/recipes/OneDriver/delete/{OpenNebula-back-2-vm.rb => OpenNebula-test-vm-vnet.rb} (83%) rename spec/recipes/OneDriver/delete/{OpenNebula-bootstrap-vm.rb => OpenNebula-test-vm.rb} (82%) create mode 100644 spec/recipes/OneDriver/delete/OpenNebula-test-vnet.rb rename spec/recipes/OneDriver/{attach_back_one_vm_spec.rb => instantiate_one_template.rb} (73%) rename spec/recipes/OneDriver/{converge_bootstrap_vm_spec.rb => instantiate_one_template_vnet.rb} (66%) create mode 100644 spec/recipes/OneDriver/snapshot_one_image.rb delete mode 100644 spec/recipes/OneDriver/snapshot_one_image_spec.rb delete mode 100644 spec/recipes/OneDriver/snapshot_two_image_spec.rb create mode 100644 spec/recipes/OneFlowService/action/boot.rb create mode 100644 spec/recipes/OneFlowService/action/delete.rb create mode 100644 spec/recipes/OneFlowService/action/delete_recreate.rb create mode 100644 spec/recipes/OneFlowService/action/hold.rb create mode 100644 spec/recipes/OneFlowService/action/poweroff.rb create mode 100644 spec/recipes/OneFlowService/action/poweroff_hard.rb create mode 100644 spec/recipes/OneFlowService/action/reboot.rb create mode 100644 spec/recipes/OneFlowService/action/reboot_hard.rb create mode 100644 spec/recipes/OneFlowService/action/release.rb create mode 100644 spec/recipes/OneFlowService/action/resume.rb create mode 100644 spec/recipes/OneFlowService/action/scale.rb create mode 100644 spec/recipes/OneFlowService/action/shutdown.rb create mode 100644 spec/recipes/OneFlowService/action/shutdown_hard.rb create mode 100644 spec/recipes/OneFlowService/action/shutdown_service.rb create mode 100644 spec/recipes/OneFlowService/action/snapshot_create.rb create mode 100644 spec/recipes/OneFlowService/action/stop.rb create mode 100644 spec/recipes/OneFlowService/action/suspend.rb create mode 100644 spec/recipes/OneFlowService/action/undeploy.rb create mode 100644 spec/recipes/OneFlowService/action/undeploy_hard.rb create mode 100644 spec/recipes/OneFlowService/chmod_simple_by_name.rb create mode 100644 spec/recipes/OneFlowService/chmod_simple_by_name_2.rb create mode 100644 spec/recipes/OneFlowService/chmod_tpl_opts.rb create mode 100644 spec/recipes/OneFlowService/delete/test_instance_template_options.rb create mode 100644 spec/recipes/OneFlowService/delete/test_role_action.rb create mode 100644 spec/recipes/OneFlowService/delete/test_simple_instance.rb create mode 100644 spec/recipes/OneFlowService/delete/test_simple_instance_by_id.rb rename spec/recipes/{OneDriver/create_bootstrap_vm_spec.rb => OneFlowService/instance_role_action.rb} (53%) create mode 100644 spec/recipes/OneFlowService/instance_simple_by_id.rb create mode 100644 spec/recipes/OneFlowService/instance_simple_by_name.rb create mode 100644 spec/recipes/OneFlowService/instance_tpl_opts.rb create mode 100644 spec/recipes/OneFlowTemplate/chmod_simple_from_hash.rb create mode 100644 spec/recipes/OneFlowTemplate/chmod_update_simple_from_file.rb create mode 100644 spec/recipes/OneFlowTemplate/create_branch_from_one_id.rb create mode 100644 spec/recipes/OneFlowTemplate/create_branch_from_one_name.rb create mode 100644 spec/recipes/OneFlowTemplate/create_role_action_instance.rb create mode 100644 spec/recipes/OneFlowTemplate/create_simple_from_file.rb rename spec/recipes/{OneDriver/attach_back_two_vm_spec.rb => OneFlowTemplate/create_simple_from_hash.rb} (73%) create mode 100644 spec/recipes/OneFlowTemplate/create_simple_from_web.rb rename spec/recipes/{OneDriver/attach_one_image_spec.rb => OneFlowTemplate/create_simple_instance_tpl.rb} (72%) create mode 100644 spec/recipes/OneFlowTemplate/create_tpl_opts_from_file.rb create mode 100644 spec/recipes/OneFlowTemplate/create_tpl_opts_from_hash.rb create mode 100644 spec/recipes/OneFlowTemplate/delete/branch_from_one_id.rb create mode 100644 spec/recipes/OneFlowTemplate/delete/branch_from_one_name.rb create mode 100644 spec/recipes/OneFlowTemplate/delete/role_action_instance.rb create mode 100644 spec/recipes/OneFlowTemplate/delete/simple_from_file.rb create mode 100644 spec/recipes/OneFlowTemplate/delete/simple_from_hash.rb create mode 100644 spec/recipes/OneFlowTemplate/delete/simple_from_web.rb create mode 100644 spec/recipes/OneFlowTemplate/delete/simple_instance_tpl.rb create mode 100644 spec/recipes/OneFlowTemplate/delete/tpl_opts_from_file.rb create mode 100644 spec/recipes/OneFlowTemplate/delete/tpl_opts_from_hash.rb create mode 100644 spec/recipes/OneFlowTemplate/update_simple_from_hash.rb rename spec/recipes/{driver_options_spec.rb => common.rb} (75%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 010cf5b..c67aa3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 0.4.5 (4/28/2016) +- Added OneFlow resources (see readme): one_flow_template, one_flow_service +- Added RSpec tests for OneFlow +- Fixed RSpec tests for newest chef-client 12.9.38 +- Fixed bug regarding destroying machines when machine_spec.reference is nil +- Permitted driver profile switching +- Added backwards compatibility for managing machines provisioned with gem versions prior to v0.3.3 +- Added ability to automatically choose the correct opennebula gem version depending on server version + ## 0.4.4 (2/29/2016) - Rewrote RSpec test suite - Improved chef-run error detection algorithm diff --git a/README.md b/README.md index 16d145e..ecb31a1 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,7 @@ This is the implementation of the OpenNebula driver for chef-provisioning. It a * Image (one_image) * VNET (one_vnet) * Lease (one_vnet_lease) +* OneFlow (one_flow_template & one_flow_service) Setup ----- @@ -45,6 +46,14 @@ A sample one_config file would look like this: } ``` +To use OneFlow, you also need to specify a ```with_flow_url``` directive. This is the API endpoint of your OneFlow. + +Example: + +```ruby +with_flow_url "http://gary.1.2.3.4:9876" +``` + In context of OpenNebula ```machine``` resource will take the following additional options: ```ruby @@ -89,7 +98,7 @@ Resources ## one_template -This resource will allow to create and delete OpenNebula templates. +This resource will allow you to create and delete OpenNebula templates. ### Attributes @@ -332,7 +341,7 @@ This resource will allow to create and delete OpenNebula vnets. ### Examples -#### 1. Reserver vnet 'boggi_vnet' from parent vnet 12345 with default size 1 +#### 1. Reserve vnet 'boggi_vnet' from parent vnet 12345 with default size 1 ```ruby one_vnet "boggi_vnet" do @@ -341,7 +350,7 @@ one_vnet "boggi_vnet" do end ``` -#### 2. Reserver vnet 'boggi_vnet' from parent vnet 12345 with size 100 +#### 2. Reserve vnet 'boggi_vnet' from parent vnet 12345 with size 100 ```ruby one_vnet "boggi_vnet" do @@ -478,10 +487,270 @@ one_user "boggi" do end ``` +## one_flow_template + +This resource will allow you to create, delete, and instantiate OneFlow templates. + +### Attributes + +```ruby +:name => String name of the OneFlow template you are targeting, default is what you put between 'one_flow_template' and 'do' +:template => Hash defining your OneFlow template, or Fixnum ID of a OneFlow template from ONE, or String file location denoted by file://my_template.json or web location denoted by http(s)://1.2.3.4/my_template.json +:template_options => Hash that override-merges into template +:mode => String octet to set permissions, default is '600' +``` + +### Actions + +```ruby +actions :create, :delete +default_action :create +``` + +### Examples + +#### 1. Create OneFlow template from file with mode 640 + +```ruby +one_flow_template "garys_flow_template" do + template "file:///opt/one/flow_templates/my_template.tpl" + mode '640' + action :create +end +``` +**Note:** If 'name' is not specified in the template file, the template will be named 'garys_flow_template' +If you want to get it from a url, you can do any of the following: +```ruby +template "http://1.2.3.4/my_template.tpl" +template "gary@https://1.2.3.4/my_template.tpl" +template "gary:password@https://1.2.3.4/my_template.tpl" +``` + +#### 2. Create OneFlow template from hash + +```ruby +one_flow_template "I can write anything I want here" do + template :name => "garys_flow_template", + :description => "This is my description.", + :shutdown_action => "shutdown-hard", + :deployment => "straight", + :ready_status_gate => true, + :roles => [ + { + :vm_template => 1398, # OR :vm_template => 'name_of_vm_template', + :scheduled_policies => [ + { + :type => "CHANGE", + :adjust => 1, + :start_time => "0 3 1-10 * *" + }, + { + :type => "CARDINALITY", + :recurrence => "0 4 1-10 * *", + :adjust => 2 + }, + { + :type => "PERCENTAGE_CHANGE", + :recurrence => "0 1 1-10 * *", + :adjust => 3, + :min_adjust_step => 14 + } + ], + :max_vms => 4, + :cooldown => 15, + :elasticity_policies => [ + { + :type => "CHANGE", + :cooldown => 17, + :period => 15, + :adjust => 2, + :period_number => 2, + :expression => "ATT == 20" + }, + { + :type => "CARDINALITY", + :cooldown => 14, + :period => 13, + :adjust => 3, + :period_number => 1, + :expression => "ATT > 20" + }, + { + :type => "PERCENTAGE_CHANGE", + :cooldown => 13, + :period => 12, + :adjust => 1, + :period_number => 3, + :expression => "ATT < 20", + :min_adjust_step => 13 + } + ], + :cardinality => 3, + :shutdown_action => "shutdown", + :name => "gary_role_1", + :vm_template_contents => "NIC=[NETWORK_ID=\"$NetConfg1\"]\nNIC=[NETWORK_ID=\"$NetConfg2\"]\n", + :min_vms => 2 + } + ], + :custom_attrs => { + :NetConfg2 => "M|vnet_id|another description", + :NetConfg1 => "M|vnet_id|description for net confg 1" + } + action :create +end +``` +**Note:** This is a template with (nearly) all fields filled out. By no means should you use this template, all the values were entered randomly. +Notice that I specified 'name' in my hash. As for vm_template, you can either put the name of a VM template or put its ID. Using ID will be faster. +See here for more info: http://docs.opennebula.org/4.14/integration/system_interfaces/appflow_api.html#examples + +#### 3. Update OneFlow template from hash (overwrite-merge) + +```ruby +one_flow_template "garys_flow_template" do + template :deployment => nil, # setting any value to nil will reset it back to default + :roles => [ + { + :name => 'delete_this_role', + :delete_role => nil # specifying this will delete this role + }, + { + :name => 'new_role', # assuming new_role does not exist, creates a new role + :vm_template => 'gary-ubuntu-14.04', + :cooldown => 8 + }, + { + :name => 'existing_role', # assuming existing_role exists, updates cooldown to 88 seconds + :vm_template => 'gary-ubuntu-14.04', + :cooldown => 88 + } + ] + action :update +end +``` + +#### 4. Delete a OneFlow template + +```ruby +one_flow_template "garys_flow_template" do + action :delete +end +``` + +#### 5. Change the permissions of a OneFlow template + +```ruby +one_flow_template "garys_flow_template" do + mode '640' + action :create +end +``` + +## one_flow_service + +This resource will allow you to create, delete, and instantiate OneFlow templates. + +### Attributes + +```ruby +:name => String name of the OneFlow service you are targeting, default is what you put between 'one_flow_service' and 'do' +:template => String name or Fixnum ID of the template you want to instantiate +:template_options => Hash that override-merges into template +:mode => String octet to set permissions, default is '600' +:role => String name of the role of a service you are targeting +:period => Integer seconds between each group of actions +:number => Integer number of VMs to apply the action to each period +:cardinality => Integer number of VMs to deploy +:force_scale => Boolean that allows scaling to cardinality above or below templated range +:override_failsafe => Boolean that allows the user to ignore aborts due to untested / partionally implemented code and execute the action anyways, default false +``` +**More on override_failsafe:** This only affects the actions :hold, :release, and :boot. The reason for this is because I was unable to figure out how to get the my VMs in a state that allows the running of these actions. As such, I was unable to test these actions. +Here is the warning you will receive: +```ruby +Chef::Log.warn('You have chose to use an action that is untested / partially implemented.') +Chef::Log.warn('Specifically, the driver will send the appropriate POST request to the Flow API') +Chef::Log.warn('But the driver will not verify that the action ran successfully, or ran at all.') +Chef::Log.warn('Moreover, the driver will not wait for the action complete, as in, the action will') +Chef::Log.warn('run asynchronously, meaning dependent actions after this one may fail.') +Chef::Log.warn('Use at your own risk. Please report any issues.') +``` + +### Actions + +```ruby +actions :instantiate, :recover, :delete, :shutdown, + :scale, :shutdown_hard, :undeploy, :undeploy_hard, + :hold, :release, :stop, :suspend, :resume, :boot, + :delete_recreate, :reboot, :reboot_hard, :poweroff, + :poweroff_hard, :snapshot_create +default_action :instantiate +``` + +### Examples + +#### 1. Instantiate a service from template + +```ruby +one_flow_service "gary_service" do + template garys_flow_template # or ID, eg. template 555 + template_options :roles => [ + { + :name => 'random_role', + :vm_template => 'gary-ubuntu-14.04', + :cooldown => 10 + } + ] + mode '640' + action :instantiate +end +``` + +#### 2. Recover a service (or delete / shutdown) + +```ruby +one_flow_service "gary_service" do + action :recover # or :delete / :shutdown +end +``` + +#### 3. Change permissions of a service + +```ruby +one_flow_service "I can write anything I want here" do + name "gary_service" + mode "640" + action :instantiate +end +``` + +#### 4. Scale a role of a service to have 3 VMs regardless of the min/max VM setting + +```ruby +one_flow_service "gary_service" do + cardinality 3 + force_scale true # optional, default = false + role "gary_role" + action :scale +end +``` + +#### 5. Perform a hard poweroff of a role + +```ruby +one_flow_service "gary_service" do + role "gary_role" + period 3 # optional + number 5 # optional + action :poweroff_hard +end +``` +**Note:** All actions listed above except for :recover can be performed in the same manner. + ## Rspec Integration tests - Create and configure `spec/config.rb` from `spec/config_sample.rb`, be sure to **read the comments** -- Run `bundle exec rspec ./spec/integration/test_all_integration_spec.rb` from your chef-provisioning-opennebula folder +- From your chef-provisioning-opennebula folder, run: + - `bundle install` + - `rspec ./spec/integration/test_all_integration_spec.rb` ## Development diff --git a/chef-provisioning-opennebula.gemspec b/chef-provisioning-opennebula.gemspec index 339825e..c2e2b94 100644 --- a/chef-provisioning-opennebula.gemspec +++ b/chef-provisioning-opennebula.gemspec @@ -1,4 +1,4 @@ -# Copyright 2015, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -30,6 +30,8 @@ Gem::Specification.new do |s| s.add_dependency 'chef' s.add_dependency 'chef-provisioning', '> 0.15' s.add_dependency 'opennebula', '~> 4.10', '< 5' + s.add_dependency 'rest-client', '~> 1.8' + s.add_dependency 'json', '~> 1.8', '>= 1.8.3' s.add_development_dependency 'rspec' s.add_development_dependency 'rake' diff --git a/lib/chef/provider/one_flow_service.rb b/lib/chef/provider/one_flow_service.rb new file mode 100644 index 0000000..6329e69 --- /dev/null +++ b/lib/chef/provider/one_flow_service.rb @@ -0,0 +1,346 @@ +# Copyright 2016, BlackBerry Limited +# +# 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 'chef/provisioning/opennebula_driver/flow_lib' +require 'set' + +# +# Implementation of Provider class. +# +class Chef + # + # Implementation of Provider class. + # + class Provider + # + # Implementation of Provider class. + # + class OneFlowService < Chef::Provider::LWRPBase + use_inline_resources + + provides :one_flow_service + + def initialize(*args) + super + if !@new_resource.flow_url.nil? + flow_url = @new_resource.flow_url + elsif !run_context.chef_provisioning.flow_url.nil? + flow_url = run_context.chef_provisioning.flow_url + elsif !ENV['ONE_FLOW_URL'].nil? + flow_url = ENV['ONE_FLOW_URL'] + else + fail 'OneFlow API URL must be specified.' + end + @flow_lib = Chef::Provisioning::OpenNebulaDriver::FlowLib.new(flow_url, driver.one.client.one_auth) + end + + def whyrun_supported? + true + end + + def load_current_resource + @current_resource = Chef::Resource::OneFlowService.new(@new_resource.name, run_context) + service_id = @flow_lib.get_unique_service_id(@new_resource.name, true) + + @current_resource.exists = !service_id.nil? + return unless @current_resource.exists + + if @new_resource.template.nil? + @current_resource.template_equal = true + else + one_tpl_id = @new_resource.template.is_a?(Fixnum) ? @new_resource.template : @flow_lib.get_unique_template_id(@new_resource.template) + new_service_template = @flow_lib.get_template(one_tpl_id) + new_service_template = @flow_lib.normalize_template(@new_resource.name, driver, @flow_lib.merge_template(new_service_template, @new_resource.template_options, true)) + new_service_template.delete(:name) + new_service_template[:roles].each { |role| [:cardinality, :vm_template_contents].each { |key| role.delete(key) } } + current_service_template = @flow_lib.get_reduced_service_template(service_id) + @current_resource.template_equal = @flow_lib.hash_eq?(new_service_template, current_service_template) + end + + @current_resource.mode(@flow_lib.get_service_permissions(service_id)) + @current_resource.mode_equal = @new_resource.mode == @current_resource.mode + + @current_resource.in_running_state = @flow_lib.get_service_state(service_id) == @flow_lib.class::SERVICE_RUNNING + + @current_resource.equal = @current_resource.template_equal && @current_resource.mode_equal && @current_resource.in_running_state + end + + action :instantiate do + if @current_resource.exists + # recover and/or chmod + unless @current_resource.equal + service_id = @flow_lib.get_unique_service_id(@new_resource.name) + converge_by "updated service '#{@new_resource.name}'" do + unless @current_resource.in_running_state + @flow_lib.recover_service(service_id, @new_resource.name) + end + unless @current_resource.mode_equal + @flow_lib.chmod_service(service_id, @new_resource.mode) + end + @new_resource.updated_by_last_action(true) + end + end + else + # create and chmod + fail 'You must specify a Flow template to instantiate' if @new_resource.template.nil? + one_tpl_id = @new_resource.template.is_a?(Fixnum) ? @new_resource.template : @flow_lib.get_unique_template_id(@new_resource.template) + new_service_template = @flow_lib.normalize_template(@new_resource.name, driver, @flow_lib.get_template(one_tpl_id)) + new_service_template = @flow_lib.normalize_template(@new_resource.name, driver, @flow_lib.merge_template(new_service_template, @new_resource.template_options, true)) + new_service_template[:name] = @new_resource.name + converge_by "instantiated service '#{@new_resource.name}'" do + one_tpl_id = @new_resource.template.is_a?(Fixnum) ? @new_resource.template : @flow_lib.get_unique_template_id(@new_resource.template) + @flow_lib.instantiate_template(one_tpl_id, new_service_template, @new_resource.name) + service_id = @flow_lib.get_unique_service_id(@new_resource.name) + @flow_lib.chmod_service(service_id, @new_resource.mode) + @new_resource.updated_by_last_action(true) + end + end + end + + action :recover do + service_id = @flow_lib.get_unique_service_id(@new_resource.name) + dont_recover = Set[ + @flow_lib.class::SERVICE_RUNNING, + @flow_lib.class::SERVICE_DEPLOYING, + @flow_lib.class::SERVICE_PENDING, + @flow_lib.class::SERVICE_SCALING + ].include?(@flow_lib.get_service_state(service_id)) + unless dont_recover + converge_by "recovered service '#{@new_resource.name}'" do + @flow_lib.recover_service(service_id, @new_resource.name) + @new_resource.updated_by_last_action(true) + end + end + end + + action :delete do + if @new_resource.role.nil? + if @current_resource.exists + service_id = @flow_lib.get_unique_service_id(@new_resource.name, true) + converge_by "deleted service '#{@new_resource.name}'" do + @flow_lib.delete_service(service_id) + @new_resource.updated_by_last_action(true) + end + end + else + sid = @flow_lib.get_unique_service_id(@new_resource.name) + unless @flow_lib.get_role_state(sid, @new_resource.role) == @flow_lib.class::ROLE_NO_VMS + converge_by "deleted role '#{@new_resource.role}' of service '#{@new_resource.name}'" do + @flow_lib.role_action(sid, @new_resource.role, 'delete', @new_resource.period.to_s, @new_resource.number.to_s, @flow_lib.class::ROLE_NO_VMS) + @new_resource.updated_by_last_action(true) + end + end + end + end + + action :shutdown do + if @new_resource.role.nil? + sid = @flow_lib.get_unique_service_id(@new_resource.name) + dont_shutdown = Set[ + @flow_lib.class::SERVICE_DONE, + @flow_lib.class::SERVICE_UNDEPLOYING, + @flow_lib.class::SERVICE_FAILED_DEPLOYING + ].include?(@flow_lib.get_service_state(sid)) + unless dont_shutdown + converge_by "shutdown service '#{@new_resource.name}'" do + @flow_lib.shutdown_service(@new_resource.name, sid) + @new_resource.updated_by_last_action(true) + end + end + else + sid = @flow_lib.get_unique_service_id(@new_resource.name) + unless @flow_lib.get_role_state(sid, @new_resource.role) == @flow_lib.class::ROLE_NO_VMS + converge_by "shutdown role '#{@new_resource.role}' of service '#{@new_resource.name}'" do + @flow_lib.role_action(sid, @new_resource.role, 'shutdown', @new_resource.period.to_s, @new_resource.number.to_s, @flow_lib.class::ROLE_NO_VMS) + @new_resource.updated_by_last_action(true) + end + end + end + end + + action :scale do + fail 'You specified an action that is role specific, but did not provide a role.' if @new_resource.role.nil? + fail 'You must specify the attribute cardinality, and cardinality >= 0' if @new_resource.cardinality < 0 + + service_id = @flow_lib.get_unique_service_id(@new_resource.name) + unless @flow_lib.get_role_cardinality(service_id, @new_resource.role) == @new_resource.cardinality + converge_by "scaled role '#{@new_resource.role}' of service '#{@new_resource.name}' to cardinality '#{@new_resource.cardinality}'" do + @flow_lib.role_scale(service_id, @new_resource.name, @new_resource.role, @new_resource.cardinality, @new_resource.force_scale) + @new_resource.updated_by_last_action(true) + end + end + end + + action :shutdown_hard do + fail 'You specified an action that is role specific, but did not provide a role.' if @new_resource.role.nil? + sid = @flow_lib.get_unique_service_id(@new_resource.name) + unless @flow_lib.get_role_state(sid, @new_resource.role) == @flow_lib.class::ROLE_NO_VMS + converge_by "performed hard shutdown of role '#{@new_resource.role}' of service '#{@new_resource.name}'" do + @flow_lib.role_action(sid, @new_resource.role, 'shutdown-hard', @new_resource.period.to_s, @new_resource.number.to_s, @flow_lib.class::ROLE_NO_VMS) + @new_resource.updated_by_last_action(true) + end + end + end + + action :undeploy do + fail 'You specified an action that is role specific, but did not provide a role.' if @new_resource.role.nil? + sid = @flow_lib.get_unique_service_id(@new_resource.name) + unless @flow_lib.get_role_state(sid, @new_resource.role) == @flow_lib.class::ROLE_UNDEPLOYED + converge_by "undeployed role '#{@new_resource.role}' of service '#{@new_resource.name}'" do + @flow_lib.role_action(sid, @new_resource.role, 'undeploy', @new_resource.period.to_s, @new_resource.number.to_s, @flow_lib.class::ROLE_UNDEPLOYED) + @new_resource.updated_by_last_action(true) + end + end + end + + action :undeploy_hard do + fail 'You specified an action that is role specific, but did not provide a role.' if @new_resource.role.nil? + sid = @flow_lib.get_unique_service_id(@new_resource.name) + unless @flow_lib.get_role_state(sid, @new_resource.role) == @flow_lib.class::ROLE_UNDEPLOYED + converge_by "hard undeployed role '#{@new_resource.role}' of service '#{@new_resource.name}'" do + @flow_lib.role_action(sid, @new_resource.role, 'undeploy-hard', @new_resource.period.to_s, @new_resource.number.to_s, @flow_lib.class::ROLE_UNDEPLOYED) + @new_resource.updated_by_last_action(true) + end + end + end + + action :hold do + fail 'You specified an action that is role specific, but did not provide a role.' if @new_resource.role.nil? + @new_resource.override_failsafe ? @flow_lib.override_failsafe_warn : fail('UNTESTED / PARTIALLY IMPLEMENTED') + sid = @flow_lib.get_unique_service_id(@new_resource.name) + converge_by "held role '#{@new_resource.role}' of service '#{@new_resource.name}'" do + @flow_lib.role_action(sid, @new_resource.role, 'hold', @new_resource.period.to_s, @new_resource.number.to_s) + @new_resource.updated_by_last_action(true) + end + end + + action :release do + fail 'You specified an action that is role specific, but did not provide a role.' if @new_resource.role.nil? + @new_resource.override_failsafe ? @flow_lib.override_failsafe_warn : fail('UNTESTED / PARTIALLY IMPLEMENTED') + sid = @flow_lib.get_unique_service_id(@new_resource.name) + converge_by "released role '#{@new_resource.role}' of service '#{@new_resource.name}'" do + @flow_lib.role_action(sid, @new_resource.role, 'release', @new_resource.period.to_s, @new_resource.number.to_s) + @new_resource.updated_by_last_action(true) + end + end + + action :stop do + fail 'You specified an action that is role specific, but did not provide a role.' if @new_resource.role.nil? + sid = @flow_lib.get_unique_service_id(@new_resource.name) + unless @flow_lib.get_role_state(sid, @new_resource.role) == @flow_lib.class::ROLE_STOPPED + converge_by "stopped role '#{@new_resource.role}' of service '#{@new_resource.name}'" do + @flow_lib.role_action(sid, @new_resource.role, 'stop', @new_resource.period.to_s, @new_resource.number.to_s, @flow_lib.class::ROLE_STOPPED) + @new_resource.updated_by_last_action(true) + end + end + end + + action :suspend do + fail 'You specified an action that is role specific, but did not provide a role.' if @new_resource.role.nil? + sid = @flow_lib.get_unique_service_id(@new_resource.name) + unless @flow_lib.get_role_state(sid, @new_resource.role) == @flow_lib.class::ROLE_SUSPENDED + converge_by "suspended role '#{@new_resource.role}' of service '#{@new_resource.name}'" do + @flow_lib.role_action(sid, @new_resource.role, 'suspend', @new_resource.period.to_s, @new_resource.number.to_s, @flow_lib.class::ROLE_SUSPENDED) + @new_resource.updated_by_last_action(true) + end + end + end + + action :resume do + fail 'You specified an action that is role specific, but did not provide a role.' if @new_resource.role.nil? + sid = @flow_lib.get_unique_service_id(@new_resource.name) + unless @flow_lib.get_role_state(sid, @new_resource.role) == @flow_lib.class::ROLE_RUNNING + converge_by "resumed role '#{@new_resource.role}' of service '#{@new_resource.name}'" do + @flow_lib.role_action(sid, @new_resource.role, 'resume', @new_resource.period.to_s, @new_resource.number.to_s, @flow_lib.class::ROLE_RUNNING) + @new_resource.updated_by_last_action(true) + end + end + end + + action :boot do + fail 'You specified an action that is role specific, but did not provide a role.' if @new_resource.role.nil? + @new_resource.override_failsafe ? @flow_lib.override_failsafe_warn : fail('UNTESTED / PARTIALLY IMPLEMENTED') + sid = @flow_lib.get_unique_service_id(@new_resource.name) + converge_by "booted role '#{@new_resource.role}' of service '#{@new_resource.name}'" do + @flow_lib.role_action(sid, @new_resource.role, 'boot', @new_resource.period.to_s, @new_resource.number.to_s) + @new_resource.updated_by_last_action(true) + end + end + + action :delete_recreate do + fail 'You specified an action that is role specific, but did not provide a role.' if @new_resource.role.nil? + sid = @flow_lib.get_unique_service_id(@new_resource.name) + converge_by "deleted and recreated role '#{@new_resource.role}' of service '#{@new_resource.name}'" do + @flow_lib.role_action(sid, @new_resource.role, 'delete-recreate', @new_resource.period.to_s, @new_resource.number.to_s, @flow_lib.class::ROLE_RUNNING) + @new_resource.updated_by_last_action(true) + end + end + + action :reboot do + fail 'You specified an action that is role specific, but did not provide a role.' if @new_resource.role.nil? + sid = @flow_lib.get_unique_service_id(@new_resource.name) + converge_by "rebooted role '#{@new_resource.role}' of service '#{@new_resource.name}'" do + @flow_lib.role_action(sid, @new_resource.role, 'reboot', @new_resource.period.to_s, @new_resource.number.to_s, @flow_lib.class::ROLE_RUNNING) + @new_resource.updated_by_last_action(true) + end + end + + action :reboot_hard do + fail 'You specified an action that is role specific, but did not provide a role.' if @new_resource.role.nil? + sid = @flow_lib.get_unique_service_id(@new_resource.name) + converge_by "hard rebooted role '#{@new_resource.role}' of service '#{@new_resource.name}'" do + @flow_lib.role_action(sid, @new_resource.role, 'reboot-hard', @new_resource.period.to_s, @new_resource.number.to_s, @flow_lib.class::ROLE_RUNNING) + @new_resource.updated_by_last_action(true) + end + end + + action :poweroff do + fail 'You specified an action that is role specific, but did not provide a role.' if @new_resource.role.nil? + sid = @flow_lib.get_unique_service_id(@new_resource.name) + unless @flow_lib.get_role_state(sid, @new_resource.role) == @flow_lib.class::ROLE_POWEROFF + converge_by "powered-off role '#{@new_resource.role}' of service '#{@new_resource.name}'" do + @flow_lib.role_action(sid, @new_resource.role, 'poweroff', @new_resource.period.to_s, @new_resource.number.to_s, @flow_lib.class::ROLE_POWEROFF) + @new_resource.updated_by_last_action(true) + end + end + end + + action :poweroff_hard do + fail 'You specified an action that is role specific, but did not provide a role.' if @new_resource.role.nil? + sid = @flow_lib.get_unique_service_id(@new_resource.name) + unless @flow_lib.get_role_state(sid, @new_resource.role) == @flow_lib.class::ROLE_POWEROFF + converge_by "hard powered-off role '#{@new_resource.role}' of service '#{@new_resource.name}'" do + @flow_lib.role_action(sid, @new_resource.role, 'poweroff-hard', @new_resource.period.to_s, @new_resource.number.to_s, @flow_lib.class::ROLE_POWEROFF) + @new_resource.updated_by_last_action(true) + end + end + end + + action :snapshot_create do + fail 'You specified an action that is role specific, but did not provide a role.' if @new_resource.role.nil? + sid = @flow_lib.get_unique_service_id(@new_resource.name) + converge_by "created a snapshot for role '#{@new_resource.role}' of service '#{@new_resource.name}'" do + @flow_lib.role_action(sid, @new_resource.role, 'snapshot-create', @new_resource.period.to_s, @new_resource.number.to_s) + @new_resource.updated_by_last_action(true) + end + end + + protected + + def driver + @new_resource.driver.nil? ? run_context.chef_provisioning.current_driver : run_context.chef_provisioning.driver_for(@new_resource.driver) + end + end + end +end diff --git a/lib/chef/provider/one_flow_template.rb b/lib/chef/provider/one_flow_template.rb new file mode 100644 index 0000000..cd74824 --- /dev/null +++ b/lib/chef/provider/one_flow_template.rb @@ -0,0 +1,175 @@ +# Copyright 2016, BlackBerry Limited +# +# 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 'rest-client' +require 'json' + +# +# Implementation of Provider class. +# +class Chef + # + # Implementation of Provider class. + # + class Provider + # + # Implementation of Provider class. + # + class OneFlowTemplate < Chef::Provider::LWRPBase + use_inline_resources + + provides :one_flow_template + + def initialize(*args) + super + if !@new_resource.flow_url.nil? + flow_url = @new_resource.flow_url + elsif !run_context.chef_provisioning.flow_url.nil? + flow_url = run_context.chef_provisioning.flow_url + elsif !ENV['ONE_FLOW_URL'].nil? + flow_url = ENV['ONE_FLOW_URL'] + else + fail 'OneFlow API URL must be specified.' + end + @flow_lib = Chef::Provisioning::OpenNebulaDriver::FlowLib.new(flow_url, driver.one.client.one_auth) + end + + def whyrun_supported? + true + end + + def load_current_resource + @current_resource = Chef::Resource::OneFlowTemplate.new(@new_resource.name, run_context) + + template_name = @new_resource.name + + unless @new_resource.template.nil? + tpl = load_template_hash + if tpl.nil? + @current_resource.exists = false + return + end + tpl = @flow_lib.merge_template(tpl, @new_resource.template_options, true, false) + template_name = tpl[:name] if tpl.key?(:name) + end + + template_id = @flow_lib.get_unique_template_id(template_name, true) + + @current_resource.exists = !template_id.nil? + return unless @current_resource.exists + + @current_resource.template(@flow_lib.get_template(template_id)) + @current_resource.mode(@flow_lib.get_template_permissions(template_id)) + + @current_resource.template_equal = @new_resource.template.nil? ? true : @flow_lib.hash_eq?( + @current_resource.template, + @flow_lib.normalize_template(@new_resource.name, driver, @flow_lib.merge_template(@current_resource.template, tpl), true) + ) + @current_resource.mode_equal = @current_resource.mode == @new_resource.mode + @current_resource.equal = @current_resource.template_equal && @current_resource.mode_equal + end + + def load_template_hash + template = {} + case @new_resource.template + when Hash + template = @new_resource.template + when Fixnum + template = @flow_lib.get_template(@new_resource.template) + when String + case @new_resource.template + when %r{^file://(.*)$} + template = JSON.parse(::File.read(Regexp.last_match[1]), :symbolize_names => true) + when %r{^(?:(\w+)(?::(.*?))?@)?(https?://.*)$} + response = RestClient::Request.execute( + method: :get, + url: Regexp.last_match[3], + user: Regexp.last_match[1], + password: Regexp.last_match[2] + ) + template = JSON.parse(response, :symbolize_names => true) + else + tid = @flow_lib.get_unique_template_id(@new_resource.template) + template = @flow_lib.get_template(tid) + end + end + template + end + + action :create do + fail 'Cannot specify template_options without a template' if !@current_resource.template_options.empty? && @current_resource.template_options.nil? + + template_name = @new_resource.name + + unless @new_resource.template.nil? + template = load_template_hash + + if @new_resource.template_options.key?(:name) + template_name = @new_resource.template_options[:name] + elsif template.key?(:name) + template_name = template[:name] + end + end + + if @current_resource.exists + unless @current_resource.equal + converge_by "updated template '#{template_name}'" do + template_id = @flow_lib.get_unique_template_id(template_name) + unless @new_resource.template.nil? && @current_resource.template_equal + template = @flow_lib.normalize_template( + @new_resource.name, + driver, + @flow_lib.merge_template(template, @new_resource.template_options, true, false), + true, + true + ) + template = @flow_lib.normalize_template(@new_resource.name, driver, @flow_lib.merge_template(@current_resource.template, template)) + @flow_lib.update_template(template_name, template) + end + unless @current_resource.mode_equal + @flow_lib.chmod_template(template_id, @new_resource.mode) + end + @new_resource.updated_by_last_action(true) + end + end + else + fail 'Cannot create template without template attribute' if @new_resource.template.nil? + converge_by "created template '#{template_name}'" do + template = @flow_lib.normalize_template(@new_resource.name, driver, @flow_lib.merge_template(template, @new_resource.template_options, true)) + @flow_lib.create_template(template) + template_id = @flow_lib.get_unique_template_id(template_name) + @flow_lib.chmod_template(template_id, @new_resource.mode) + @new_resource.updated_by_last_action(true) + end + end + end + + action :delete do + if @current_resource.exists + template_id = @flow_lib.get_unique_template_id(@new_resource.name, true) + converge_by "deleted template '#{@new_resource.name}'" do + @flow_lib.delete_template(template_id) + @new_resource.updated_by_last_action(true) + end + end + end + + protected + + def driver + @new_resource.driver.nil? ? run_context.chef_provisioning.current_driver : run_context.chef_provisioning.driver_for(@new_resource.driver) + end + end + end +end diff --git a/lib/chef/provider/one_image.rb b/lib/chef/provider/one_image.rb index 4ac26f3..b2c164d 100644 --- a/lib/chef/provider/one_image.rb +++ b/lib/chef/provider/one_image.rb @@ -1,4 +1,4 @@ -# Copyright 2015, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -49,7 +49,7 @@ def exists? action :allocate do if exists? - action_handler.report_progress "image '#{new_resource.name}' already exists - nothing to do" + action_handler.report_progress "image '#{new_resource.name}' already exists - (up to date)" else fail "'size' must be specified" unless new_resource.size fail "'datastore_id' must be specified" unless new_resource.datastore_id @@ -81,7 +81,7 @@ def exists? @new_resource.updated_by_last_action(true) end when 'READY', 'USED', 'USED_PERS' - action_handler.report_progress "image '#{new_resource.name}' is already in #{@image.state_str} state - nothing to do" + action_handler.report_progress "image '#{new_resource.name}' is already in #{@image.state_str} state - (up to date)" else fail "Image #{new_resource.name} is in unexpected state '#{@image.state_str}'" end @@ -99,7 +99,7 @@ def exists? @new_resource.updated_by_last_action(true) end else - action_handler.report_progress "image '#{new_resource.name}' does not exist - nothing to do" + action_handler.report_progress "image '#{new_resource.name}' does not exist - (up to date)" end end @@ -120,7 +120,7 @@ def exists? disk_id = new_driver.one.get_disk_id(vm, disk_hash['IMAGE']['NAME']) if !disk_id.nil? - action_handler.report_progress "disk is already attached" unless disk_id.nil? + action_handler.report_progress "disk is already attached - (up to date)" unless disk_id.nil? elsif disk_id.nil? action_handler.report_progress "disk not attached, attaching..." rc = vm.disk_attach(disk_tpl) @@ -187,7 +187,7 @@ def exists? @image['TEMPLATE/DRIVER'] == image_config[:driver] && @image['TEMPLATE/DESCRIPTION'] == image_config[:description] && @image['DATASTORE_ID'] == image_config[:datastore_id] - action_handler.report_progress("image '#{@new_resource.name}' (ID: #{@image.id}) already exists - nothing to do") + action_handler.report_progress("image '#{@new_resource.name}' (ID: #{@image.id}) already exists - (up to date)") else fail "image '#{new_resource.name}' already exists, but it is not the same image" end diff --git a/lib/chef/provider/one_template.rb b/lib/chef/provider/one_template.rb index 236a037..7d2030c 100644 --- a/lib/chef/provider/one_template.rb +++ b/lib/chef/provider/one_template.rb @@ -1,4 +1,4 @@ -# Copyright 2015, BlackBerry, Ltd. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/lib/chef/provider/one_user.rb b/lib/chef/provider/one_user.rb index f0f6326..52bf940 100644 --- a/lib/chef/provider/one_user.rb +++ b/lib/chef/provider/one_user.rb @@ -1,4 +1,4 @@ -# Copyright 2015, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -45,7 +45,7 @@ def exists?(filter) fail "Missing attribute 'password'" unless @new_resource.password if exists?(:name => @new_resource.name) - action_handler.report_progress "user '#{@new_resource.name}' already exists - nothing to do" + action_handler.report_progress "user '#{@new_resource.name}' already exists - (up to date)" else action_handler.perform_action "create user '#{@new_resource.name}'" do user = OpenNebula::User.new(OpenNebula::User.build_xml, @client) @@ -65,7 +65,7 @@ def exists?(filter) @new_resource.updated_by_last_action(true) end else - action_handler.report_progress "user '#{new_resource.name}' does not exists - nothing to do" + action_handler.report_progress "user '#{new_resource.name}' does not exists - (up to date)" end end @@ -89,7 +89,7 @@ def driver if current_driver && current_driver.driver_url != new_driver.driver_url fail "Cannot move '#{machine_spec.name}' from #{current_driver.driver_url} to #{new_driver.driver_url}: machine moving is not supported. Destroy and recreate." end - fail "Driver not specified for one_image #{new_resource.name}" unless new_driver + fail "Driver not specified for one_user #{new_resource.name}" unless new_driver new_driver end diff --git a/lib/chef/provider/one_vnet.rb b/lib/chef/provider/one_vnet.rb index ba561ef..d55821a 100644 --- a/lib/chef/provider/one_vnet.rb +++ b/lib/chef/provider/one_vnet.rb @@ -1,4 +1,4 @@ -# Copyright 2015, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -46,7 +46,7 @@ def exists?(filter) fail "Missing attribute 'cluster_id'" unless @new_resource.cluster_id if exists?(:name => @new_resource.name) - action_handler.report_progress "vnet '#{@new_resource.name}' already exists - nothing to do" + action_handler.report_progress "vnet '#{@new_resource.name}' already exists - (up to date)" else action_handler.perform_action "created vnet '#{@new_resource.name}' from '#{@new_resource.template_file}'" do template_str = ::File.read(@new_resource.template_file) + "\nNAME=\"#{@new_resource.name}\"" @@ -67,7 +67,7 @@ def exists?(filter) @new_resource.updated_by_last_action(true) end else - action_handler.report_progress "vnet '#{new_resource.name}' does not exists - nothing to do" + action_handler.report_progress "vnet '#{new_resource.name}' does not exists - (up to date)" end end @@ -87,7 +87,7 @@ def exists?(filter) same = ar_pool[0]['AR']['SIZE'].to_i == @new_resource.size end if same - action_handler.report_progress "vnet '#{@new_resource.name}' already exists - nothing to do" + action_handler.report_progress "vnet '#{@new_resource.name}' already exists - (up to date)" else fail "vnet '#{@new_resource.name}' exists with different configuration" end @@ -107,7 +107,7 @@ def driver if current_driver && current_driver.driver_url != new_driver.driver_url fail "Cannot move '#{machine_spec.name}' from #{current_driver.driver_url} to #{new_driver.driver_url}: machine moving is not supported. Destroy and recreate." end - fail "Driver not specified for one_image #{new_resource.name}" unless new_driver + fail "Driver not specified for one_vnet #{new_resource.name}" unless new_driver new_driver end diff --git a/lib/chef/provider/one_vnet_lease.rb b/lib/chef/provider/one_vnet_lease.rb index fcbac54..c006b87 100644 --- a/lib/chef/provider/one_vnet_lease.rb +++ b/lib/chef/provider/one_vnet_lease.rb @@ -1,4 +1,4 @@ -# Copyright 2015, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -72,7 +72,7 @@ def exists? @new_resource.updated_by_last_action(true) end else - action_handler.report_progress("#{@new_resource.name} is not present - nothing do to") + action_handler.report_progress("#{@new_resource.name} is not present - (up to date)") end end @@ -102,7 +102,7 @@ def driver if current_driver && current_driver.driver_url != new_driver.driver_url fail "Cannot move '#{machine_spec.name}' from #{current_driver.driver_url} to #{new_driver.driver_url}: machine moving is not supported. Destroy and recreate." end - fail "Driver not specified for one_image #{new_resource.name}" unless new_driver + fail "Driver not specified for one_vnet_lease #{new_resource.name}" unless new_driver new_driver end diff --git a/lib/chef/provisioning/driver_init/opennebula.rb b/lib/chef/provisioning/driver_init/opennebula.rb index a706747..8ed3a73 100644 --- a/lib/chef/provisioning/driver_init/opennebula.rb +++ b/lib/chef/provisioning/driver_init/opennebula.rb @@ -1,4 +1,4 @@ -# Copyright 2015, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/lib/chef/provisioning/driver_init/server_version.rb b/lib/chef/provisioning/driver_init/server_version.rb new file mode 100644 index 0000000..52e50b8 --- /dev/null +++ b/lib/chef/provisioning/driver_init/server_version.rb @@ -0,0 +1,28 @@ +# Copyright 2016, BlackBerry Limited +# +# 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 'opennebula' +require 'json' + +endpoint = ARGV[0].dup +credentials = ARGV[1].dup +options = JSON.parse(ARGV[2].dup) + +version = OpenNebula::Client.new(credentials, endpoint, options).get_version + +if version.is_a?(String) + puts version +else + puts version.inspect +end diff --git a/lib/chef/provisioning/opennebula_driver.rb b/lib/chef/provisioning/opennebula_driver.rb index 338f442..5bedd46 100644 --- a/lib/chef/provisioning/opennebula_driver.rb +++ b/lib/chef/provisioning/opennebula_driver.rb @@ -1,4 +1,4 @@ -# Copyright 2015, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/lib/chef/provisioning/opennebula_driver/credentials.rb b/lib/chef/provisioning/opennebula_driver/credentials.rb index d3b6bbe..5974f1d 100644 --- a/lib/chef/provisioning/opennebula_driver/credentials.rb +++ b/lib/chef/provisioning/opennebula_driver/credentials.rb @@ -1,4 +1,4 @@ -# Copyright 2015, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/lib/chef/provisioning/opennebula_driver/driver.rb b/lib/chef/provisioning/opennebula_driver/driver.rb index 17ac14f..97ba044 100644 --- a/lib/chef/provisioning/opennebula_driver/driver.rb +++ b/lib/chef/provisioning/opennebula_driver/driver.rb @@ -1,4 +1,4 @@ -# Copyright 2015, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -19,13 +19,91 @@ require 'chef/provisioning/convergence_strategy/no_converge' require 'chef/provisioning/transport/ssh' require 'chef/provisioning/opennebula_driver/version' -require 'chef/provisioning/opennebula_driver/one_lib' require 'chef/provisioning/opennebula_driver/credentials' require 'net/ssh/proxy/command' +require 'json' +require 'open3' + +class Chef + module DSL + # + # Module extension. + # + module Recipe + def with_flow_url(url) + run_context.chef_provisioning.with_flow_url(url) + end + end + end +end + +class Chef + module Provisioning + # + # Class extension. + # + class ChefRunData + attr_accessor :flow_url + def with_flow_url(url) + @flow_url = url + end + end + end +end class Chef module Provisioning module OpenNebulaDriver + def self.match_driver_url(url, allow_nil_profile = false) + scan = url.match(%r/opennebula:(https?:\/\/[^:\/]+ (?::[0-9]{2,5})? (?:\/[^:\s]+) ) :?([^:\s]+)?/x) + fail "'driver_url' option has invalid format: #{url}" if scan.nil? + endpoint = scan[1] + profile = scan[2] + fail "'driver_url' option is missing an endpoint: #{url}" if endpoint.nil? + fail "'driver_url' option is missing a profile: #{url}" if profile.nil? && !allow_nil_profile + [endpoint, profile] + end + + def self.get_onelib(args) + endpoint = args[:endpoint] + credentials = args[:credentials] + options = args[:options] || {} + if args[:driver_url] + fail "OpenNebula driver_url cannot be #{args[:driver_url].class}, it must be a String" unless args[:driver_url].is_a?(String) + endpoint, profile = Chef::Provisioning::OpenNebulaDriver.match_driver_url(args[:driver_url]) + one_profile = Chef::Provisioning::OpenNebulaDriver::Credentials.new[profile] + credentials = one_profile[:credentials] + options = one_profile[:options] || {} + end + fail "OpenNebula credentials cannot be #{credentials.class}, it must be a String" unless credentials.is_a?(String) + fail "OpenNebula endpoint cannot be #{endpoint.class}, it must be a String" unless endpoint.is_a?(String) + fail "OpenNebula options cannot be #{options.class}, it must be a Hash" unless options.is_a?(Hash) + server_version, _ = Open3.capture2e("ruby #{File.dirname(__FILE__)}/../driver_init/server_version.rb #{endpoint} #{credentials} #{options.to_json.inspect}") + server_version.strip! + fail server_version unless server_version =~ /^\d+\.\d+(?:\.\d+)?$/ + begin + gem 'opennebula', "~> #{server_version}" + require 'opennebula' + rescue Gem::LoadError => e + e_inspect = e.inspect + if e_inspect.include?('already activated') + Chef::Log.warn(e_inspect) + else + raise e + end + end + require 'chef/provisioning/opennebula_driver/one_lib' + gem_version = Gem.loaded_specs['opennebula'].version.to_s + if gem_version == server_version + Chef::Log.debug("You are using OpenNebula gem version #{gem_version} against OpenNebula server version #{server_version}") + else + Chef::Log.warn('OPENNEBULA GEM / SERVER VERSION MISMATCH') + Chef::Log.warn("You are using OpenNebula gem version #{gem_version} against OpenNebula server version #{server_version}") + Chef::Log.warn('Users may experience issues with this gem.') + end + OneLib.new(:credentials => credentials, :endpoint => endpoint, :options => options) + end + # # A Driver instance represents a place where machines can be created # and found, and contains methods to create, delete, start, stop, and @@ -81,11 +159,14 @@ class Driver < Chef::Provisioning::Driver # # driver_options: # credentials: bbsl-auto:text_pass credentials has precedence over secret_file - # secret_file: local_path_to_one_auth_file + # endpoint: opennebula endpoint + # options: additional options for OpenNebula::Client # def initialize(driver_url, config) super - @one = OneLib.new(:driver_url => driver_url) + @one = Chef::Provisioning::OpenNebulaDriver.get_onelib(:driver_url => driver_url) + @driver_url_with_profile = driver_url + @driver_url = @one.client.one_endpoint end def self.from_url(driver_url, config) @@ -124,17 +205,17 @@ def allocate_machine(action_handler, machine_spec, machine_options) instance = instance_for(machine_spec) return machine_spec unless instance.nil? - unless machine_options.bootstrap_options + unless machine_options[:bootstrap_options] fail "'bootstrap_options' must be specified" end check_unique_names(machine_options, machine_spec) action_handler.perform_action "created vm '#{machine_spec.name}'" do Chef::Log.debug(machine_options) tpl = @one.get_template(machine_spec.name, - machine_options.bootstrap_options) + machine_options[:bootstrap_options]) vm = @one.allocate_vm(tpl) populate_node_object(machine_spec, machine_options, vm) - @one.chmod_resource(vm, machine_options.bootstrap_options[:mode]) + @one.chmod_resource(vm, machine_options[:bootstrap_options][:mode]) # This option allows to manipulate how the machine shows up # in the OpenNebula UI and CLI tools. We either set the VM @@ -225,7 +306,11 @@ def destroy_machine(action_handler, machine_spec, machine_options) fail "Failed to destroy '#{instance.name}'. Current state: #{instance.state_str}" if instance.state_str != 'DONE' end else - Chef::Log.info("vm #{machine_spec.name} (#{machine_spec.reference['instance_id']}) does not exist - nothing to do") + if machine_spec.reference + Chef::Log.info("vm #{machine_spec.name} (#{machine_spec.reference['instance_id']}) does not exist - (up to date)") + else + Chef::Log.info("vm #{machine_spec.name} does not exist - (up to date)") + end end strategy = convergence_strategy_for(machine_spec, machine_options) strategy.cleanup_convergence(action_handler, machine_spec) @@ -251,7 +336,7 @@ def stop_machine(action_handler, machine_spec, machine_options) end end else - Chef::Log.info("vm #{machine_spec.name} (#{machine_spec.reference['instance_id']}) does not exist - nothing to do") + Chef::Log.info("vm #{machine_spec.name} (#{machine_spec.reference['instance_id']}) does not exist - (up to date)") end end @@ -314,7 +399,7 @@ def ready_image(action_handler, image_spec, _image_options) def destroy_image(action_handler, image_spec, _image_options) img = @one.get_resource(:image, :id => image_spec.location['image_id'].to_i) if img.nil? - action_handler.report_progress "image #{image_spec.name} (#{image_spec.location['image_id']}) does not exist - nothing to do" + action_handler.report_progress "image #{image_spec.name} (#{image_spec.location['image_id']}) does not exist - (up to date)" else action_handler.perform_action "deleted image #{image_spec.name} (#{image_spec.location['image_id']})" do rc = img.delete @@ -413,6 +498,7 @@ def destroy_machines(action_handler, specs_and_options, parallelizer) # @param [Array[ChefMetal::MachineSpec]] machine_specs # An array of machine specs the load balancer should have def allocate_load_balancer(_action_handler, _lb_spec, _lb_options, _machine_specs) + fail "'allocate_load_balancer' is not implemented" end # Make the load balancer ready @@ -420,6 +506,7 @@ def allocate_load_balancer(_action_handler, _lb_spec, _lb_options, _machine_spec # @param [ChefMetal::LoadBalancerSpec] lb_spec Frozen LB specification # @param [Hash] lb_options A hash of options to pass the LB def ready_load_balancer(_action_handler, _lb_spec, _lb_options, _machine_specs) + fail "'ready_load_balancer' is not implemented" end # Destroy the load balancer @@ -427,6 +514,7 @@ def ready_load_balancer(_action_handler, _lb_spec, _lb_options, _machine_specs) # @param [ChefMetal::LoadBalancerSpec] lb_spec Frozen LB specification # @param [Hash] lb_options A hash of options to pass the LB def destroy_load_balancer(_action_handler, _lb_spec, _lb_options) + fail "'destroy_load_balancer' is not implemented" end protected @@ -444,7 +532,7 @@ def one_credentials end def check_unique_names(machine_options, machine_spec) - return unless machine_options.bootstrap_options[:unique_names] + return unless machine_options[:bootstrap_options][:unique_names] hostname = if machine_options[:vm_name] == :short machine_spec.name.split('.').first elsif machine_options[:vm_name].is_a?(String) @@ -458,13 +546,13 @@ def check_unique_names(machine_options, machine_spec) end def populate_node_object(machine_spec, machine_options, vm) - machine_spec.driver_url = driver_url + machine_spec.driver_url = @driver_url_with_profile machine_spec.reference = { 'driver_version' => Chef::Provisioning::OpenNebulaDriver::VERSION, 'allocated_at' => Time.now.utc.to_s, - 'image_id' => machine_options.bootstrap_options[:image_id] || nil, - 'is_shutdown' => machine_options.bootstrap_options[:is_shutdown] || false, - 'shutdown_hard' => machine_options.bootstrap_options[:shutdown_hard] || false, + 'image_id' => machine_options[:bootstrap_options][:image_id] || nil, + 'is_shutdown' => machine_options[:bootstrap_options][:is_shutdown] || false, + 'shutdown_hard' => machine_options[:bootstrap_options][:shutdown_hard] || false, 'instance_id' => vm.id, 'name' => vm.name, 'state' => vm.state_str @@ -478,7 +566,7 @@ def populate_node_object(machine_spec, machine_options, vm) end def populate_img_object(image_spec, new_image) - image_spec.driver_url = driver_url + image_spec.driver_url = @driver_url_with_profile image_spec.reference = { 'driver_version' => Chef::Provisioning::OpenNebulaDriver::VERSION, 'image_id' => new_image, @@ -492,13 +580,15 @@ def populate_img_object(image_spec, new_image) def instance_for(machine_spec) instance = nil if machine_spec.reference - fail "Switching a machine's driver from #{machine_spec.driver_url} to #{driver_url} is not supported!" \ - " Use machine :destroy and then :create the machine on the new driver." if machine_spec.driver_url != driver_url + current_endpoint, _ = Chef::Provisioning::OpenNebulaDriver.match_driver_url(machine_spec.driver_url, true) + fail "Cannot move '#{machine_spec.name}' from #{current_endpoint} to #{driver_url}: machine moving is not supported. Destroy and recreate." if current_endpoint != driver_url instance = @one.get_resource(:virtualmachine, :id => machine_spec.reference['instance_id'].to_i) + machine_spec.driver_url = @driver_url_with_profile elsif machine_spec.location - fail "Switching a machine's driver from #{machine_spec.driver_url} to #{driver_url} is not supported!" \ - " Use machine :destroy and then :create the machine on the new driver." if machine_spec.driver_url != driver_url + current_endpoint, _ = Chef::Provisioning::OpenNebulaDriver.match_driver_url(machine_spec.driver_url, true) + fail "Cannot move '#{machine_spec.name}' from #{current_endpoint} to #{driver_url}: machine moving is not supported. Destroy and recreate." if current_endpoint != driver_url instance = @one.get_resource(:virtualmachine, :id => machine_spec.location['server_id'].to_i) + machine_spec.driver_url = @driver_url_with_profile unless instance.nil? # Convert from previous driver machine_spec.reference = { @@ -518,9 +608,11 @@ def machine_for(machine_spec, machine_options) instance = instance_for(machine_spec) fail "#{machine_spec.name} (#{machine_spec.reference['instance_id']}) does not exist!" if instance.nil? # TODO: Support Windoze VMs (see chef-provisioning-vagrant) - Chef::Provisioning::Machine::UnixMachine.new(machine_spec, - transport_for(machine_spec, machine_options, instance), - convergence_strategy_for(machine_spec, machine_options)) + Chef::Provisioning::Machine::UnixMachine.new( + machine_spec, + transport_for(machine_spec, machine_options, instance), + convergence_strategy_for(machine_spec, machine_options) + ) end def get_ssh_user(machine_spec, machine_options) @@ -566,7 +658,7 @@ def transport_for(machine_spec, machine_options, _instance) def convergence_strategy_for(machine_spec, machine_options) # TODO: Support Windoze VMs (see chef-provisioning-vagrant) - convergence_options = Cheffish::MergedConfig.new(machine_options[:convergence_options] || {}) + convergence_options = Cheffish::MergedConfig.new(machine_options ? machine_options[:convergence_options] || {} : {}) if !machine_spec.reference Chef::Provisioning::ConvergenceStrategy::NoConverge.new(convergence_options, config) diff --git a/lib/chef/provisioning/opennebula_driver/flow_lib.rb b/lib/chef/provisioning/opennebula_driver/flow_lib.rb new file mode 100644 index 0000000..9771956 --- /dev/null +++ b/lib/chef/provisioning/opennebula_driver/flow_lib.rb @@ -0,0 +1,491 @@ +# Copyright 2016, BlackBerry Limited +# +# 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 'rest-client' +require 'json' +require 'set' + +# +# Implementation. +# +class Chef + # + # Module extension. + # + module Provisioning + # + # Module extension. + # + module OpenNebulaDriver + # + # ONE error. + # + class OpenNebulaException < Exception + end + + # + # Implementation. + # + class FlowLib + attr_accessor :flow_url, :username, :password + + # STATE NUMBERS TO SYMBOLS + + # SERVICE: + SERVICE_PENDING = 0 + SERVICE_DEPLOYING = 1 + SERVICE_RUNNING = 2 + SERVICE_UNDEPLOYING = 3 + SERVICE_DONE = 5 + SERVICE_FAILED_DEPLOYING = 7 + SERVICE_SCALING = 8 + SERVICE_FAILED_SCALING = 9 + SERVICE_COOLDOWN = 10 + + # ROLE: + ROLE_NOT_EXIST = nil + ROLE_NO_VMS = -1 + ROLE_PENDING = 1 + ROLE_RUNNING = 3 + ROLE_STOPPED = 4 + ROLE_SUSPENDED = 5 + ROLE_POWEROFF = 8 + ROLE_UNDEPLOYED = 9 + + def initialize(url, one_auth) + @flow_url = url + @username, _, @password = one_auth.rpartition(':') + end + + ########### + # HELPERS # + ########### + + # Performs some basic verifications on a template + # Also adds in default values + def normalize_template(name, driver, template, allow_no_roles = false, allow_no_vm_template = false) + template = { + :deployment => 'straight', + :name => name, + :ready_status_gate => false, + :description => '', + :roles => [], + :custom_attrs => {} + }.merge(template) + + fail "You must specify at least 1 role for template '#{name}'" if template[:roles].empty? && !allow_no_roles + id_cache = {} + template[:roles].map! do |role| + fail "Some roles in template '#{name}' are missing a name." if role[:name].nil? + fail "Role '#{role[:name]}' in template '#{name}' is missing a vm_template." if role[:vm_template].nil? && !allow_no_vm_template + new_role = { + :cardinality => role[:min_vms] || 1, + :elasticity_policies => [], + :scheduled_policies => [] + }.merge(role) + if role[:vm_template].is_a?(String) + if id_cache[role[:vm_template]].nil? + template_from_one = driver.one.get_resource(:template, :name => role[:vm_template]) + fail "Could not find a template with the name '#{role[:vm_template]}'" if template_from_one.nil? + id = template_from_one.to_hash['VMTEMPLATE']['ID'].to_i + id_cache[role[:vm_template]] = id + new_role[:vm_template] = id + else + new_role[:vm_template] = id_cache[role[:vm_template]] + end + end + new_role + end + template + end + + # Helper for merge_template + def special_merge_hash(base_hash, new_hash, delete_roles = true) + keys_to_delete = [] + merged = base_hash.merge(new_hash) do |key, oldval, newval| + # This is probably a redundant fail ... + fail 'Class of values in the templates must remain the same. If you want to delete an entry, set it to nil.' unless + oldval.is_a?(newval.class) || newval.is_a?(NilClass) || key == :vm_template + case newval + when NilClass + keys_to_delete.push(key) + nil + when Array + if key == :roles + new_array = [] + old_as_hash = Hash[oldval.collect { |role| [role[:name], role] }] + + newval.each do |role| + if role.key?(:delete_role) && delete_roles + old_as_hash.delete(role[:name]) + next + end + fail 'All roles must have a name.' if role[:name].nil? + if old_as_hash.key?(role[:name]) + new_array.push(special_merge_hash(old_as_hash[role[:name]], role)) + old_as_hash.delete(role[:name]) + else + new_array.push(role) + end + end + + new_array + old_as_hash.values + else + newval + end + when Hash + special_merge_hash(oldval, newval) + else + newval + end + end + keys_to_delete.each { |key| merged.delete(key) } + merged + end + + # Performs a overwrite-merge of two OneFlow templates, any key with nil value will be deleted + def merge_template(base_tpl, new_tpl, overwrite_name = false, delete_roles = true) + fail 'Service template name changing is not supported.' if new_tpl.key?(:name) && !overwrite_name && base_tpl[:name] != new_tpl[:name] + special_merge_hash(base_tpl, new_tpl, delete_roles) + end + + # Issues warnings for a failsafe override + def override_failsafe_warn + Chef::Log.warn('You have chose to use an action that is untested / partially implemented.') + Chef::Log.warn('Specifically, the driver will send the appropriate POST request to the Flow API') + Chef::Log.warn('But the driver will not verify that the action ran successfully, or ran at all.') + Chef::Log.warn('Moreover, the driver will not wait for the action complete, as in, the action will') + Chef::Log.warn('run asynchronously, meaning dependent actions after this one may fail.') + Chef::Log.warn('Use at your own risk. Please report any issues.') + end + + # Validate the attributes period and number + def validate_role_action(period, number) + fail "Make sure 'period' >= 0" if !period.empty? && period.to_i < 0 + fail "Make sure 'number' >= 0" if !number.empty? && number.to_i < 0 + end + + # REST call to flow api + def request(method, url, payload = '{}') + case payload + when Hash + RestClient::Request.execute( + method: method, + url: @flow_url + url, + user: @username, + password: @password, + payload: payload.to_json + ) + when String + JSON.parse(payload) + RestClient::Request.execute( + method: method, + url: @flow_url + url, + user: @username, + password: @password, + payload: payload + ) + else + fail 'Payload must be hash or json string.' + end + rescue JSON::ParserError + fail 'Malformed json string.' + rescue RestClient::ResourceNotFound, RestClient::BadRequest, RestClient::InternalServerError => e + raise OpenNebulaException, "#{e}\nThere's a problem. Here's a hint:\n#{e.response}" + end + + # Converts all arrays to sets + def recursive_array_to_set(object) + case object + when Array + return object.map { |e| recursive_array_to_set(e) }.to_set + when Hash + object.each do |key, value| + object[key] = recursive_array_to_set(value) + end + return object + else + return object + end + end + + # Checks if two hashes are equal, ignore array order + def hash_eq?(hash1, hash2) + recursive_array_to_set(Marshal.load(Marshal.dump(hash1))) == recursive_array_to_set(Marshal.load(Marshal.dump(hash2))) + end + + # Returns all of the IDs of a service or template that matches a name + def get_ids(type, name) + response = request(:get, type == :template ? '/service_template' : '/service') + ids = [] + data = JSON.parse(response, :symbolize_names => true) + return [] if data[:DOCUMENT_POOL][:DOCUMENT].nil? + data[:DOCUMENT_POOL][:DOCUMENT].each { |e| ids.push(e[:ID].to_i) if e[:NAME] == name } + ids + end + + # Gets a single ID of a service or template, fails if there's not exactly 1, or returns nil if there 0 and nil_if_none + def get_unique_id(type, name, nil_if_none = false) + matches = get_ids(type, name) + if matches.length == 0 + return nil if nil_if_none + fail "There are no OneFlow #{type}s with the name '#{name}'" + elsif matches.length > 1 + fail "There are multiple OneFlow #{type}s with the name '#{name}'" + else + matches[0] + end + end + + # Check if a service or template exists + def exists?(type, name) + get_ids(type, name).length == 0 ? false : true + end + + # Gets permission of service or template + def get_permissions(type, id) + id = id.to_s + response = request(:get, type == :template ? '/service_template' : '/service') + data = JSON.parse(response, :symbolize_names => true)[:DOCUMENT_POOL][:DOCUMENT] + data.each do |tpl| + next unless tpl[:ID] == id + perms = tpl[:PERMISSIONS] + mode = '' + [:OWNER_U, :OWNER_M, :OWNER_A, :GROUP_U, :GROUP_M, :GROUP_A, :OTHER_U, :OTHER_M, :OTHER_A].each { |m| mode += perms[m] } + return mode.to_i(2).to_s(8) + end + fail "#{type} with id=#{id} does not exist." + end + + # Wrapper for get_ids + def get_template_ids(name) + get_ids(:template, name) + end + + # Wrapper for get_unique_id + def get_unique_template_id(name, nil_if_none = false) + get_unique_id(:template, name, nil_if_none) + end + + # Wrapper for exists? + def template_exists?(name) + exists?(:template, name) + end + + # Gets a template given a template ID + def get_template(id) + response = request(:get, "/service_template/#{id}") + JSON.parse(response, :symbolize_names => true)[:DOCUMENT][:TEMPLATE][:BODY] + end + + # Wrapper for get_permissions + def get_template_permissions(id) + get_permissions(:template, id) + end + + # Wrapper for get_ids + def get_service_ids(name) + get_ids(:service, name) + end + + # Wrapper for get_unique_id + def get_unique_service_id(name, nil_if_none = false) + get_unique_id(:service, name, nil_if_none) + end + + # Wrapper for exists? + def service_exists?(name) + exists?(:service, name) + end + + # Wrapper for get_permissions + def get_service_permissions(id) + get_permissions(:service, id) + end + + # Returns the template of a service with runtime content removed + def get_reduced_service_template(id) + response = request(:get, "/service/#{id}") + template_from_one = JSON.parse(response, :symbolize_names => true)[:DOCUMENT][:TEMPLATE][:BODY] + service_name = template_from_one[:name] + [:log, :name, :state, :custom_attrs_values].each { |key| template_from_one.delete(key) } + template_from_one[:roles].each do |role| + role[:nodes].each do |node| + unless node[:running] + Chef::Log.warn("A node in role '#{node[:vm_info][:VM][:USER_TEMPLATE][:ROLE_NAME]}' of service '#{service_name}' is not normal!") + end + end + [:cardinality, :nodes, :state, :disposed_nodes, :cooldown_end, :last_vmname, :user_inputs_values, :vm_template_contents].each { |key| role.delete(key) } + end + template_from_one + end + + # Gets the state of a service + # 0 => PENDING, 1 => DEPLOYING, 2 => RUNNING, 3 => UNDEPLOYING, 5 => DONE, + # 7 => FAILED_DEPLOYING, 8 => SCALING, 9 => FAILED_SCALING, 10 => COOLDOWN + def get_service_state(id) + response = request(:get, "/service/#{id}") + JSON.parse(response, :symbolize_names => true)[:DOCUMENT][:TEMPLATE][:BODY][:state].to_i + end + + # Returns a role of a service + def get_role(service_id, role_name) + response = request(:get, "/service/#{service_id}") + JSON.parse(response, :symbolize_names => true)[:DOCUMENT][:TEMPLATE][:BODY][:roles].each { |role| return role if role[:name] == role_name } + fail "#{role_name} doesn't seem to exist!" + end + + # Returns the state of a role + # It seems that regardless of the state of the VMs, the state of a role will be RUNNING + # So I will be doing a workaround where I will return that it's SUSPENDED if all of the VMs are SUSPENDED + # nil => role doesn't exist, -1 => there are no VMs, 1 => PENDING, + # 3 => RUNNING, 4 => STOPPED, 5 => SUSPENDED, 8 => POWEROFF, 9 => UNDEPLOYED + def get_role_state(id, role_name) + role = get_role(id, role_name) + return -1 if role[:cardinality].to_i == 0 + state_counter = { 1 => 0, 2 => 0, 3 => 0, 4 => 0, 5 => 0, 8 => 0, 9 => 0 } + role[:nodes].each do |node| + state = node[:vm_info][:VM][:STATE].to_i + fail "UNSUPPORTED STATE #{state}" if state_counter[state].nil? + state_counter[state] += 1 + return state if state_counter[state] == role[:cardinality].to_i + end + state_counter # Return the hash of counters if states are staggered + end + + # Gets the cardinality of a role + def get_role_cardinality(id, role_name) + get_role(id, role_name)[:cardinality].to_i + end + + # Creates a post request for an action + def perform_action(url, action, params) + request(:post, url, "{\"action\":{\"perform\":\"#{action}\",\"params\":#{params.to_json}}}") + end + + #################### + # TEMPLATE ACTIONS # + #################### + + # Creates a template in ONE + def create_template(payload) + request(:post, '/service_template', payload) + true + end + + # Updates a template in ONE + def update_template(template_name, payload) + request(:put, "/service_template/#{get_unique_template_id(template_name)}", payload) + end + + # Deletes a template in ONE + def delete_template(template_id) + request(:delete, "/service_template/#{template_id}") + end + + # Spawns a service from a template + def instantiate_template(tid, template, service_name) + url = "/service_template/#{tid}/action" + perform_action(url, 'instantiate', :merge_template => template) + + service_id = get_unique_service_id(service_name) + state = nil + while state != SERVICE_RUNNING + Chef::Log.info("Waiting for RUNNING for '#{service_name}'") + sleep(15) + state = get_service_state(service_id) + fail "Service failed to deploy ...\nThere's probably something wrong with your template." if state == SERVICE_FAILED_DEPLOYING + end + end + + # Modifies the permissions of a template + def chmod_template(template_id, octet) + url = "/service_template/#{template_id}/action" + perform_action(url, 'chmod', :octet => octet) + end + + ################### + # SERVICE ACTIONS # + ################### + + # Deletes a service in ONE + def delete_service(service_id) + request(:delete, "/service/#{service_id}") + end + + # Performs shutdown on an entire service + def shutdown_service(service_name, sid) + url = "/service/#{sid}/action" + perform_action(url, 'shutdown', {}) + + state = nil + while state != SERVICE_DONE + Chef::Log.info("Waiting for SHUTDOWN COMPLETE for '#{service_name}'") + sleep(15) + state = get_service_state(sid) + fail 'Service failed to shutdown ...' unless Set[SERVICE_RUNNING, SERVICE_UNDEPLOYING, SERVICE_DONE].include?(state) + end + end + + # Performs the recover action on a service + def recover_service(service_id, service_name) + url = "/service/#{service_id}/action" + perform_action(url, 'recover', {}) + + state = nil + while state != SERVICE_RUNNING + Chef::Log.info("Waiting for RUNNING for '#{service_name}'") + sleep(15) + state = get_service_state(service_id) + fail 'Service failed to recover ...' if state == SERVICE_FAILED_DEPLOYING + end + end + + # Modifies the permissions of a service + def chmod_service(sid, octet) + url = "/service/#{sid}/action" + perform_action(url, 'chmod', :octet => octet) + end + + # Performs an action on a role + def role_action(sid, role_name, action, period, number, desired_state = nil) + validate_role_action(period, number) + url = "/service/#{sid}/role/#{role_name}/action" + perform_action(url, action, :period => period, :number => number) + + state = nil + while state != desired_state + Chef::Log.info("Waiting for #{action} to complete") + sleep(15) + state = get_role_state(sid, role_name) + fail "#{action} failed. Got unsupported state #{state}" unless Set[ROLE_NO_VMS, ROLE_PENDING, ROLE_RUNNING, ROLE_STOPPED, ROLE_SUSPENDED, ROLE_POWEROFF, ROLE_UNDEPLOYED].include?(state) + end + end + + # Scales a role to a new cardinality + def role_scale(service_id, service_name, role_name, card, force) + request(:put, "/service/#{service_id}/role/#{role_name}", :cardinality => card, :force => force) + + state = nil + while state != SERVICE_RUNNING + Chef::Log.info("Waiting for RUNNING for '#{service_name}'") + sleep(15) + state = get_service_state(service_id) + fail 'Service failed to scale ...' if state == SERVICE_FAILED_SCALING + end + end + end + end + end +end diff --git a/lib/chef/provisioning/opennebula_driver/one_lib.rb b/lib/chef/provisioning/opennebula_driver/one_lib.rb index af5dbfb..efb7cb6 100644 --- a/lib/chef/provisioning/opennebula_driver/one_lib.rb +++ b/lib/chef/provisioning/opennebula_driver/one_lib.rb @@ -1,4 +1,4 @@ -# Copyright 2015, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,10 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'opennebula' - -require 'opennebula/document' - # # Sample Document definition. # @@ -50,30 +46,14 @@ class OpenNebulaException < Exception # Implementation. # class OneLib - attr_accessor :client, :version_ge_4_14 + attr_reader :client, :version_ge_4_14 def initialize(args) - credentials = args[:credentials] - endpoint = args[:endpoint] - options = args[:options] || {} - if args[:driver_url] - scan = args[:driver_url].match(%r/(opennebula):(https?:\/\/[^:\/]+ (?::[0-9]{2,5})? (?:\/[^:\s]+) ) :?([^:\s]+)?/x) - endpoint = scan[2] - profile = scan[3] - fail "'driver_url' option has invalid format: #{args[:driver_url]}" if endpoint.nil? || profile.nil? - one_profile = Chef::Provisioning::OpenNebulaDriver::Credentials.new[profile] - credentials = one_profile[:credentials] - options = one_profile[:options] || {} - end - @client = OpenNebula::Client.new(credentials, endpoint, options) + @client = OpenNebula::Client.new(args[:credentials], args[:endpoint], args[:options]) rc = @client.get_version raise OpenNebulaException, rc.message if OpenNebula.is_error?(rc) - - server_version = rc.split('.').map(&:to_i) - gem_version = Gem.loaded_specs["opennebula"].version.to_s.split('.').map(&:to_i) + gem_version = Gem.loaded_specs['opennebula'].version.to_s.split('.').map(&:to_i) @version_ge_4_14 = gem_version[0] > 4 || (gem_version[0] == 4 && gem_version[1] >= 14) - - version_mismatch_warning(server_version, gem_version) if server_version != gem_version end # This function provides a more readable way to return a @@ -399,7 +379,7 @@ def template_from_hash(options) # # This method will create a VM template from parameters provided - # in the 't' Hash. The hash must have equivalent structure as the + # in the 't' Hash. The hash must have equivalent structure as the # VM template. # # We considered using OpenNebulaHelper::create_template for this, @@ -486,12 +466,6 @@ def create_template(t, level = 0) end tpl end - - def version_mismatch_warning(server, gem) - Chef::Log.warn('GEM / SERVER VERSION MISMATCH') - Chef::Log.warn("Your gem version is #{gem.join('.')} and the server version is #{server.join('.')}") - Chef::Log.warn('Users may experience issues with this gem.') - end end end end diff --git a/lib/chef/provisioning/opennebula_driver/resources.rb b/lib/chef/provisioning/opennebula_driver/resources.rb index bb3dcbb..71ff908 100644 --- a/lib/chef/provisioning/opennebula_driver/resources.rb +++ b/lib/chef/provisioning/opennebula_driver/resources.rb @@ -1,4 +1,4 @@ -# Copyright 2015, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,7 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -resources = %w( image template vnet vnet_lease user ) +resources = %w( image template vnet vnet_lease user flow_template flow_service ) resources.each do |r| Chef::Log.debug "OpenNebula driver loading resource: one_#{r}" diff --git a/lib/chef/provisioning/opennebula_driver/version.rb b/lib/chef/provisioning/opennebula_driver/version.rb index ddbbff8..c707a7b 100644 --- a/lib/chef/provisioning/opennebula_driver/version.rb +++ b/lib/chef/provisioning/opennebula_driver/version.rb @@ -1,4 +1,4 @@ -# Copyright 2015, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ module Provisioning # Extending module. # module OpenNebulaDriver - VERSION = '0.4.4' + VERSION = '0.4.5' end end end diff --git a/lib/chef/resource/one_flow_service.rb b/lib/chef/resource/one_flow_service.rb new file mode 100644 index 0000000..498f277 --- /dev/null +++ b/lib/chef/resource/one_flow_service.rb @@ -0,0 +1,61 @@ +# Copyright 2016, BlackBerry Limited +# +# 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 'chef/provider/one_flow_service' + +# +# Implementation of Resource class. +# +class Chef + # + # Implementation of Resource class. + # + class Resource + # + # Implementation of Resource class. + # + class OneFlowService < Chef::Resource::LWRPBase + resource_name :one_flow_service + + attribute :name, :kind_of => String, :name_attribute => true + attribute :template, :kind_of => [Fixnum, String], :default => nil + attribute :template_options, :kind_of => Hash, :default => {} + attribute :mode, :regex => [/^[0-7]{3}$/], :default => '600' + attribute :role, :regex => [/^\w+$/], :default => nil + attribute :cardinality, :kind_of => Fixnum, :default => -1 + attribute :period, :kind_of => Fixnum, :default => nil + attribute :number, :kind_of => Fixnum, :default => nil + attribute :force_scale, :kind_of => [TrueClass, FalseClass], :default => false + attribute :override_failsafe, :kind_of => [TrueClass, FalseClass], :default => false + + attribute :driver + attribute :flow_url + + attr_accessor :exists, :equal, :template_equal, :mode_equal, :in_running_state + + actions :instantiate, :recover, :delete, :shutdown, :scale, + :shutdown_hard, :undeploy, :undeploy_hard, :hold, + :release, :stop, :suspend, :resume, :boot, + :delete_recreate, :reboot, :reboot_hard, :poweroff, + :poweroff_hard, :snapshot_create + + default_action :instantiate + + def initialize(*args) + super + @driver = run_context.chef_provisioning.current_driver + end + end + end +end diff --git a/lib/chef/resource/one_flow_template.rb b/lib/chef/resource/one_flow_template.rb new file mode 100644 index 0000000..5b231ae --- /dev/null +++ b/lib/chef/resource/one_flow_template.rb @@ -0,0 +1,53 @@ +# Copyright 2016, BlackBerry Limited +# +# 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 'chef/provider/one_flow_template' + +# +# Implementation of Resource class. +# +class Chef + # + # Implementation of Resource class. + # + class Resource + # + # Implementation of Resource class. + # + class OneFlowTemplate < Chef::Resource::LWRPBase + resource_name :one_flow_template + + attribute :name, :kind_of => String, :name_attribute => true + + attribute :template, :kind_of => [Hash, String, Fixnum], :default => nil + attribute :template_options, :kind_of => Hash, :default => {} + + attribute :service_name, :kind_of => String, :default => nil + attribute :mode, :regex => [/^[0-7]{3}$/], :default => '600' + + attribute :driver + attribute :flow_url + + attr_accessor :exists, :equal, :template_equal, :mode_equal + + actions :create, :delete + default_action :create + + def initialize(*args) + super + @driver = run_context.chef_provisioning.current_driver + end + end + end +end diff --git a/lib/chef/resource/one_image.rb b/lib/chef/resource/one_image.rb index 62ef198..51fa8e3 100644 --- a/lib/chef/resource/one_image.rb +++ b/lib/chef/resource/one_image.rb @@ -1,4 +1,4 @@ -# Copyright 2015, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -42,7 +42,7 @@ class OneImage < Chef::Resource::LWRPBase attribute :prefix, :kind_of => String, :equal_to => %w(vd xvd sd hd) attribute :persistent, :kind_of => [TrueClass, FalseClass] attribute :public, :kind_of => [TrueClass, FalseClass] - attribute :mode, :regex => [/^\d\d\d$/] + attribute :mode, :regex => [/^[0-7]{3}$/] attribute :disk_type, :kind_of => String attribute :source, :kind_of => String attribute :target, :kind_of => String diff --git a/lib/chef/resource/one_template.rb b/lib/chef/resource/one_template.rb index bd72efb..469a8eb 100644 --- a/lib/chef/resource/one_template.rb +++ b/lib/chef/resource/one_template.rb @@ -1,4 +1,4 @@ -# Copyright 2015, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/lib/chef/resource/one_user.rb b/lib/chef/resource/one_user.rb index 431c8e6..2a6f843 100644 --- a/lib/chef/resource/one_user.rb +++ b/lib/chef/resource/one_user.rb @@ -1,4 +1,4 @@ -# Copyright 2015, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/lib/chef/resource/one_vnet.rb b/lib/chef/resource/one_vnet.rb index 78c6d65..635aa96 100644 --- a/lib/chef/resource/one_vnet.rb +++ b/lib/chef/resource/one_vnet.rb @@ -1,4 +1,4 @@ -# Copyright 2015, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -36,7 +36,7 @@ class OneVnet < Chef::Resource::LWRPBase attribute :ar_id, :kind_of => Integer attribute :template_file, :kind_of => String attribute :cluster_id, :kind_of => Integer - attribute :mode, :regex => [/^\d\d\d$/] + attribute :mode, :regex => [/^[0-7]{3}$/] attribute :driver diff --git a/lib/chef/resource/one_vnet_lease.rb b/lib/chef/resource/one_vnet_lease.rb index ff2fe60..eaea5a3 100644 --- a/lib/chef/resource/one_vnet_lease.rb +++ b/lib/chef/resource/one_vnet_lease.rb @@ -1,4 +1,4 @@ -# Copyright 2015, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/spec/config_sample.rb b/spec/config_sample.rb index 4057ec4..8f56628 100644 --- a/spec/config_sample.rb +++ b/spec/config_sample.rb @@ -3,15 +3,24 @@ ## Feel free to modify any variables to your needs. ## ####################################################### -# this is the OpenNebula endpoint url -ONE_XMLRPC = 'http://1.2.3.4:443/api:boggi' +# your driver url, opennebula:: +DRIVER_URL = 'opennebula:http://1.2.3.4:443/api:boggi' + +# test for profile moving, set nil to skip +DRIVER_URL_2 = 'opennebula:http://1.2.3.4:443/api:gary' + +# set this to nil if you do not want to test OneFlow +ONE_FLOW_URL = 'http://gary.1.2.3.4:9876' # the path to your local chef repo, an empty folder would work, if the folder does not exist, one will be automatically created CHEF_REPO_PATH = '/home/gary/test-repo' -# required for recipes/OneDriver/create_one_image_spec.rb +# required for recipes involving allocating datablocks DATASTORE_ID = 103 +# required for recipes involving allocating vnets +VNET_ID = 394 + VM_TEMPLATE = { # the base URL from which files are downloaded eg. chef-client.deb, init.sh, service.gz etc. 'HTTPBASE' => 'http://my.server.com', diff --git a/spec/integration/test_all_integration_spec.rb b/spec/integration/test_all_integration_spec.rb index 9dfd769..b26e335 100644 --- a/spec/integration/test_all_integration_spec.rb +++ b/spec/integration/test_all_integration_spec.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,276 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'spec_helper' -require 'chef/provisioning/opennebula_driver' +require "#{File.dirname(__FILE__)}/../config.rb" -describe 'OneDriver' do - describe 'create_one_template_spec.rb' do - test_helper( - 'create_one_template_spec.rb', - 'OneDriver/create_one_template_spec.rb', - "create template 'OpenNebula-test-tpl'" - ) - end +# Test OneDriver +require_relative 'test_one_driver' - describe 'create_one_template_int_spec.rb' do - test_helper( - 'create_one_template_int_spec.rb', - 'OneDriver/create_one_template_int_spec.rb', - "create template 'OpenNebula-test-tpl-ints'" - ) - end - - describe 'instantiate_one_template_spec.rb' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/instantiate_one_template_spec.rb', - "created vm 'OpenNebula-tpl-1-vm'" - ) - end - end - - describe 'create_bootstrap_vm_spec.rb' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/create_bootstrap_vm_spec.rb', - "created vm 'OpenNebula-bootstrap-vm'" - ) - end - end - - describe 'create_one_image_spec.rb' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/create_one_image_spec.rb', - /allocated image 'OpenNebula-bootstrap-img'.*?wait for image 'OpenNebula-bootstrap-img' to be READY/m - ) - end - end - describe 'create_one_image_spec.rb' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/create_one_image_spec.rb', - /image 'OpenNebula-bootstrap-img' already exists - nothing to do.*?image 'OpenNebula-bootstrap-img' is already in READY state - nothing to do/m - ) - end - end - - describe 'attach_one_image_spec.rb' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/attach_one_image_spec.rb', - /disk not attached, attaching.*?attached disk OpenNebula-bootstrap-img to OpenNebula-bootstrap-vm/m - ) - end - end - describe 'attach_one_image_spec.rb' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/attach_one_image_spec.rb', - /disk is already attached.*?attached disk OpenNebula-bootstrap-img to OpenNebula-bootstrap-vm/m - ) - end - end - - describe 'snapshot_one_image_spec.rb' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/snapshot_one_image_spec.rb', - "created snapshot from 'OpenNebula-bootstrap-vm'" - ) - end - end - - describe 'converge_bootstrap_vm_spec.rb' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/converge_bootstrap_vm_spec.rb', - /vm 'OpenNebula-bootstrap-vm' is ready.*?create client OpenNebula-bootstrap-vm at clients.*?run 'chef-client -l info' on OpenNebula-bootstrap-vm/m - ) - end - end - - # deploys two test backend VM's - describe 'snapshot_two_image_spec.rb' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/snapshot_two_image_spec.rb', - "created snapshot from 'OpenNebula-bootstrap-vm'" - ) - end - end - - describe 'create_back_one_vm_spec.rb' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/create_back_one_vm_spec.rb', - /created vm 'OpenNebula-back-1-vm'.*?create node OpenNebula-back-1-vm.*?vm 'OpenNebula-back-1-vm' is ready.*?update node OpenNebula-back-1-vm/m - ) - end - end - - describe 'attach_back_one_vm_spec.rb' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/attach_back_one_vm_spec.rb', - /disk not attached, attaching.*?attached disk OpenNebula-snap-1-img to OpenNebula-back-1-vm/m - ) - end - end - describe 'attach_back_one_vm_spec.rb' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/attach_back_one_vm_spec.rb', - /disk is already attached.*?attached disk OpenNebula-snap-1-img to OpenNebula-back-1-vm/m - ) - end - end - - describe 'converge_back_one_vm_spec.rb' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/converge_back_one_vm_spec.rb', - /vm 'OpenNebula-back-1-vm' is ready.*?create client OpenNebula-back-1-vm at clients.*?run 'chef-client -l info' on OpenNebula-back-1-vm/m - ) - end - end - - describe 'create_back_two_vm_spec.rb' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/create_back_two_vm_spec.rb', - /created vm 'OpenNebula-back-2-vm'.*?create node OpenNebula-back-2-vm.*?vm 'OpenNebula-back-2-vm' is ready.*?update node OpenNebula-back-2-vm/m - ) - end - end - - describe 'attach_back_two_vm_spec.rb' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/attach_back_two_vm_spec.rb', - /disk not attached, attaching.*?attached disk OpenNebula-snap-2-img to OpenNebula-back-2-vm/m - ) - end - end - describe 'attach_back_two_vm_spec.rb' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/attach_back_two_vm_spec.rb', - /disk is already attached.*?attached disk OpenNebula-snap-2-img to OpenNebula-back-2-vm/m - ) - end - end - - describe 'converge_back_two_vm_spec.rb' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/converge_back_two_vm_spec.rb', - /vm 'OpenNebula-back-2-vm' is ready.*?create client OpenNebula-back-2-vm at clients.*?run 'chef-client -l info' on OpenNebula-back-2-vm/m - ) - end - end - - ############# - ## CLEANUP ## - ############# - - describe 'delete OpenNebula-test-tpl' do - test_helper( - 'delete OpenNebula-test-tpl', - 'OneDriver/delete/OpenNebula-test-tpl.rb', - "delete template 'OpenNebula-test-tpl'" - ) - end - - describe 'delete OpenNebula-test-tpl-ints' do - test_helper( - 'delete OpenNebula-test-tpl-ints', - 'OneDriver/delete/OpenNebula-test-tpl-ints.rb', - "delete template 'OpenNebula-test-tpl-ints'" - ) - end - - describe 'delete OpenNebula-tpl-1-vm' do - test_helper( - 'delete OpenNebula-tpl-1-vm', - 'OneDriver/delete/OpenNebula-tpl-1-vm.rb', - /destroyed machine OpenNebula-tpl-1-vm.*?delete node OpenNebula-tpl-1-vm.*?delete client OpenNebula-tpl-1-vm at clients/m - ) - end - - describe 'delete OpenNebula-bootstrap-vm' do - test_helper( - 'delete OpenNebula-bootstrap-vm', - 'OneDriver/delete/OpenNebula-bootstrap-vm.rb', - /destroyed machine OpenNebula-bootstrap-vm.*?delete node OpenNebula-bootstrap-vm.*?delete client OpenNebula-bootstrap-vm at clients/m - ) - end - - describe 'delete OpenNebula-bootstrap-img' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/delete/OpenNebula-bootstrap-img.rb', - "deleted image 'OpenNebula-bootstrap-img'" - ) - end - end - describe 'delete OpenNebula-bootstrap-img' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/delete/OpenNebula-bootstrap-img.rb', - "image 'OpenNebula-bootstrap-img' does not exist - nothing to do" - ) - end - end - - describe 'delete OpenNebula-back-1-vm' do - test_helper( - 'delete OpenNebula-back-1-vm', - 'OneDriver/delete/OpenNebula-back-1-vm.rb', - /destroyed machine OpenNebula-back-1-vm.*?delete node OpenNebula-back-1-vm.*?delete client OpenNebula-back-1-vm at clients/m - ) - end - - describe 'delete OpenNebula-back-2-vm' do - test_helper( - 'delete OpenNebula-back-2-vm', - 'OneDriver/delete/OpenNebula-back-2-vm.rb', - /destroyed machine OpenNebula-back-2-vm.*?delete node OpenNebula-back-2-vm.*?delete client OpenNebula-back-2-vm at clients/m - ) - end - - describe 'delete OpenNebula-snap-1-img' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/delete/OpenNebula-snap-1-img.rb', - "deleted image 'OpenNebula-snap-1-img'" - ) - end - end - describe 'delete OpenNebula-snap-1-img' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/delete/OpenNebula-snap-1-img.rb', - "image 'OpenNebula-snap-1-img' does not exist - nothing to do" - ) - end - end - - describe 'delete OpenNebula-snap-2-img' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/delete/OpenNebula-snap-2-img.rb', - "deleted image 'OpenNebula-snap-2-img'" - ) - end - end - describe 'delete OpenNebula-snap-2-img' do - it do - is_expected.to converge_test_recipe( - 'OneDriver/delete/OpenNebula-snap-2-img.rb', - "image 'OpenNebula-snap-2-img' does not exist - nothing to do" - ) - end - end -end +# Test OneFlow +require_relative 'test_one_flow' unless ONE_FLOW_URL.nil? diff --git a/spec/integration/test_one_driver.rb b/spec/integration/test_one_driver.rb new file mode 100644 index 0000000..83a928d --- /dev/null +++ b/spec/integration/test_one_driver.rb @@ -0,0 +1,177 @@ +# Copyright 2016, BlackBerry Limited +# +# 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 "#{File.dirname(__FILE__)}/../config.rb" + +describe 'OneDriver' do + describe 'create_one_template_strings.rb' do + idempotency_helper( + 'create_one_template_strings.rb', + 'OneDriver/create_one_template_strings.rb', + "create template 'OpenNebula-test-tpl-strings'" + ) + end + + describe 'create_one_template_ints.rb' do + idempotency_helper( + 'create_one_template_ints.rb', + 'OneDriver/create_one_template_ints.rb', + "create template 'OpenNebula-test-tpl-ints'" + ) + end + + describe 'create_one_template_mix.rb' do + idempotency_helper( + 'create_one_template_mix.rb', + 'OneDriver/create_one_template_mix.rb', + "create template 'OpenNebula-test-tpl-mix'" + ) + end + + describe 'create_one_vnet.rb' do + idempotency_helper( + 'create_one_vnet.rb', + 'OneDriver/create_one_vnet.rb', + "reserved vnet 'OpenNebula-test-vnet'" + ) + end + + describe 'instantiate_one_template.rb' do + it do + is_expected.to converge_test_recipe( + :recipe => 'OneDriver/instantiate_one_template.rb', + :expected => "created vm 'OpenNebula-test-vm'" + ) + end + end + + describe 'allocate_change_profile.rb' do + it do + is_expected.to converge_test_recipe( + :recipe => 'OneDriver/allocate_change_profile.rb', + :expected => "update normal.chef_provisioning.driver_url from \"#{DRIVER_URL}\" to \"#{DRIVER_URL_2}\"" + ) + end + end unless DRIVER_URL_2.nil? + + + describe 'instantiate_one_template_vnet.rb' do + it do + is_expected.to converge_test_recipe( + :recipe => 'OneDriver/instantiate_one_template_vnet.rb', + :expected => "created vm 'OpenNebula-test-vm-vnet'" + ) + end + end + + describe 'create_one_image.rb' do + idempotency_helper( + 'create_one_image.rb', + 'OneDriver/create_one_image.rb', + /allocated image 'OpenNebula-test-img'.*?wait for image 'OpenNebula-test-img' to be READY/m + ) + end + + describe 'attach_one_image.rb' do + idempotency_helper( + 'attach_one_image.rb', + 'OneDriver/attach_one_image.rb', + /disk not attached, attaching.*?attached disk OpenNebula-test-img to OpenNebula-test-vm/m + ) + end + + describe 'snapshot_one_image.rb' do + it do + is_expected.to converge_test_recipe( + :recipe => 'OneDriver/snapshot_one_image.rb', + :expected => "created snapshot from 'OpenNebula-test-vm'" + ) + end + it do + is_expected.to converge_test_recipe( + :recipe => 'OneDriver/snapshot_one_image.rb', + :expected => "snapshot 'OpenNebula-test-snap-img' already exists" + ) + end + end + + ############# + ## DELETES ## + ############# + + describe 'delete OpenNebula-test-tpl-strings' do + idempotency_helper( + 'delete OpenNebula-test-tpl-strings', + 'OneDriver/delete/OpenNebula-test-tpl-strings.rb', + "delete template 'OpenNebula-test-tpl-strings'" + ) + end + + describe 'delete OpenNebula-test-tpl-ints' do + idempotency_helper( + 'delete OpenNebula-test-tpl-ints', + 'OneDriver/delete/OpenNebula-test-tpl-ints.rb', + "delete template 'OpenNebula-test-tpl-ints'" + ) + end + + describe 'delete OpenNebula-test-tpl-mix' do + idempotency_helper( + 'delete OpenNebula-test-tpl-mix', + 'OneDriver/delete/OpenNebula-test-tpl-mix.rb', + "delete template 'OpenNebula-test-tpl-mix'" + ) + end + + describe 'delete OpenNebula-test-vm' do + idempotency_helper( + 'delete OpenNebula-test-vm', + 'OneDriver/delete/OpenNebula-test-vm.rb', + /destroyed machine OpenNebula-test-vm.*?delete node OpenNebula-test-vm.*?delete client OpenNebula-test-vm at clients/m + ) + end + + describe 'delete OpenNebula-test-vm-vnet' do + idempotency_helper( + 'delete OpenNebula-test-vm-vnet', + 'OneDriver/delete/OpenNebula-test-vm-vnet.rb', + /destroyed machine OpenNebula-test-vm-vnet.*?delete node OpenNebula-test-vm-vnet.*?delete client OpenNebula-test-vm-vnet at clients/m + ) + end + + describe 'delete OpenNebula-test-vnet' do + idempotency_helper( + 'delete OpenNebula-test-vnet', + 'OneDriver/delete/OpenNebula-test-vnet.rb', + "deleted vnet 'OpenNebula-test-vnet'" + ) + end + + describe 'delete OpenNebula-test-img' do + idempotency_helper( + 'delete OpenNebula-test-img', + 'OneDriver/delete/OpenNebula-test-img.rb', + "deleted image 'OpenNebula-test-img'" + ) + end + + describe 'delete OpenNebula-test-snap-img' do + idempotency_helper( + 'delete OpenNebula-test-snap-img', + 'OneDriver/delete/OpenNebula-test-snap-img.rb', + "deleted image 'OpenNebula-test-snap-img'" + ) + end +end diff --git a/spec/integration/test_one_flow.rb b/spec/integration/test_one_flow.rb new file mode 100644 index 0000000..d844645 --- /dev/null +++ b/spec/integration/test_one_flow.rb @@ -0,0 +1,546 @@ +# Copyright 2016, BlackBerry Limited +# +# 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 'chef/provisioning/opennebula_driver' +require "#{File.dirname(__FILE__)}/../config.rb" + +describe 'OneFlow' do + ######################## + ## CREATE VM TEMPLATE ## + ######################## + + describe 'create_one_template_strings.rb' do + it do + is_expected.to converge_test_recipe( + :recipe => 'OneDriver/create_one_template_strings.rb', + :expected => "create template 'OpenNebula-test-tpl-strings'" + ) + end + end + + ########################### + ## CREATE FLOW TEMPLATES ## + ########################### + + describe ':create' do + idempotency_helper( + 'Create simple flow template from hash', + 'OneFlowTemplate/create_simple_from_hash.rb', + "created template 'test_simple_from_hash'" + ) + end + + describe ':create' do + idempotency_helper( + 'Update simple flow template from hash', + 'OneFlowTemplate/update_simple_from_hash.rb', + "updated template 'test_simple_from_hash'" + ) + end + + describe ':create' do + idempotency_helper( + 'Chmod simple flow template from hash', + 'OneFlowTemplate/chmod_simple_from_hash.rb', + "updated template 'test_simple_from_hash'" + ) + end + + describe ':create' do + idempotency_helper( + 'Update simple flow template from web', + 'OneFlowTemplate/create_simple_from_web.rb', + "created template 'test_simple_from_web'" + ) + end + + describe ':create' do + before(:context) do + File.open('/tmp/one_rspec_test.json', 'w') do |f| + f.write( + { + :roles => [ + { + :name => 'gary_ubuntu', + :vm_template => Chef::Provisioning::OpenNebulaDriver.get_onelib( + :driver_url => DRIVER_URL + ).get_resource(:template, :name => 'OpenNebula-test-tpl-strings').to_hash['VMTEMPLATE']['ID'].to_i + } + ] + }.to_json + ) + end + end + idempotency_helper( + 'Create simple flow template from file', + 'OneFlowTemplate/create_simple_from_file.rb', + "created template 'test_simple_from_file'" + ) + after(:context) do + File.delete('/tmp/one_rspec_test.json') + end + end + + describe ':create' do + before(:context) do + File.open('/tmp/one_rspec_test.json', 'w') do |f| + f.write( + { + :name => 'test_simple_from_file', + :roles => [ + { + :name => 'gary_ubuntu', + :delete_role => true + }, + { + :name => 'gary_ubuntu_new', + :vm_template => Chef::Provisioning::OpenNebulaDriver.get_onelib( + :driver_url => DRIVER_URL + ).get_resource(:template, :name => 'OpenNebula-test-tpl-strings').to_hash['VMTEMPLATE']['ID'].to_i + } + ] + }.to_json + ) + end + end + idempotency_helper( + 'Chmod and update simple flow template from file', + 'OneFlowTemplate/chmod_update_simple_from_file.rb', + "updated template 'test_simple_from_file'" + ) + after(:context) do + File.delete('/tmp/one_rspec_test.json') + end + end + + describe ':create' do + idempotency_helper( + 'Create flow template with template_options from hash', + 'OneFlowTemplate/create_tpl_opts_from_hash.rb', + "created template 'test_tpl_opts_from_hash'" + ) + end + + describe ':create' do + before(:context) do + File.open('/tmp/one_rspec_test.json', 'w') do |f| + f.write( + { + :name => 'gary', + :deployment => 'straight', + :roles => [ + { + :name => 'gary_ubuntu', + :vm_template => Chef::Provisioning::OpenNebulaDriver.get_onelib( + :driver_url => DRIVER_URL + ).get_resource(:template, :name => 'OpenNebula-test-tpl-strings').to_hash['VMTEMPLATE']['ID'].to_i + } + ] + }.to_json + ) + end + end + idempotency_helper( + 'Create flow template with template_options from file', + 'OneFlowTemplate/create_tpl_opts_from_file.rb', + "created template 'test_tpl_opts_from_file'" + ) + after(:context) do + File.delete('/tmp/one_rspec_test.json') + end + end + + describe ':create' do + idempotency_helper( + 'Create flow template that branch off of \'test_simple_from_hash\' by name', + 'OneFlowTemplate/create_branch_from_one_name.rb', + "created template 'test_branch_from_one_name'" + ) + end + + describe ':create' do + idempotency_helper( + 'Create flow template that branch off of \'test_simple_from_hash\' by id', + 'OneFlowTemplate/create_branch_from_one_id.rb', + "created template 'test_branch_from_one_id'" + ) + end + + describe ':create' do + idempotency_helper( + 'Create simple instance flow template', + 'OneFlowTemplate/create_simple_instance_tpl.rb', + "created template 'test_simple_instance_tpl'" + ) + end + + describe ':create' do + idempotency_helper( + 'Create flow template which will be used to test all role actions', + 'OneFlowTemplate/create_role_action_instance.rb', + "created template 'test_role_action_instance'" + ) + end + + ########################### + ## INSTANTIATE TEMPLATES ## + ########################### + + describe ':instantiate' do + idempotency_helper( + 'Create simple instance by name', + 'OneFlowService/instance_simple_by_name.rb', + "instantiated service 'test_simple_instance'" + ) + end + + describe ':instantiate' do + idempotency_helper( + 'Create simple instance by id', + 'OneFlowService/instance_simple_by_id.rb', + "instantiated service 'test_simple_instance_by_id'" + ) + end + + describe ':instantiate' do + idempotency_helper( + 'Create simple instance with template_options', + 'OneFlowService/instance_tpl_opts.rb', + "instantiated service 'test_instance_template_options'" + ) + end + + describe ':instantiate' do + idempotency_helper( + 'Chmod simple instance', + 'OneFlowService/chmod_simple_by_name.rb', + "updated service 'test_simple_instance'" + ) + end + + describe ':instantiate' do + idempotency_helper( + 'Chmod simple instance', + 'OneFlowService/chmod_simple_by_name_2.rb', + "updated service 'test_simple_instance'" + ) + end + + describe ':instantiate' do + idempotency_helper( + 'Chmod simple instance with template_options', + 'OneFlowService/chmod_tpl_opts.rb', + "updated service 'test_instance_template_options'" + ) + end + + describe ':instantiate' do + idempotency_helper( + 'Create instance for testing role actions', + 'OneFlowService/instance_role_action.rb', + "instantiated service 'test_role_action'" + ) + end + + describe ':snapshot_create' do + context 'Snapshot of a role' do + it do + is_expected.to converge_test_recipe( + :recipe => 'OneFlowService/action/snapshot_create.rb', + :expected => "created a snapshot for role 'snapshot_create' of service 'test_role_action'" + ) + end + end + end + + describe ':scale' do + idempotency_helper( + 'Scale a role', + 'OneFlowService/action/scale.rb', + "scaled role 'scale' of service 'test_role_action' to cardinality '2'" + ) + end + + describe ':shutdown' do + idempotency_helper( + 'Shutdown a role', + 'OneFlowService/action/shutdown.rb', + "shutdown role 'shutdown' of service 'test_role_action'" + ) + end + + describe ':shutdown_hard' do + idempotency_helper( + 'Shutdown-hard a role', + 'OneFlowService/action/shutdown_hard.rb', + "performed hard shutdown of role 'shutdown_hard' of service 'test_role_action'" + ) + end + + describe ':undeploy' do + idempotency_helper( + 'Undeploy a role', + 'OneFlowService/action/undeploy.rb', + "undeployed role 'undeploy' of service 'test_role_action'" + ) + end + + describe ':undeploy_hard' do + idempotency_helper( + 'Undeploy-hard a role', + 'OneFlowService/action/undeploy_hard.rb', + "hard undeployed role 'undeploy_hard' of service 'test_role_action'" + ) + end + + describe ':hold' do + context 'Hold a role' do + it do + is_expected.to converge_test_recipe( + :recipe => 'OneFlowService/action/hold.rb', + :expected => "held role 'hold' of service 'test_role_action'" + ) + end + end + end + + describe ':release' do + context 'Release of a role' do + it do + is_expected.to converge_test_recipe( + :recipe => 'OneFlowService/action/release.rb', + :expected => "released role 'release' of service 'test_role_action'" + ) + end + end + end + + describe ':suspend' do + idempotency_helper( + 'Suspend a role', + 'OneFlowService/action/suspend.rb', + "suspended role 'suspend_resume' of service 'test_role_action'" + ) + end + + describe ':resume' do + idempotency_helper( + 'Resume a role', + 'OneFlowService/action/resume.rb', + "resumed role 'suspend_resume' of service 'test_role_action'" + ) + end + + describe ':boot' do + context 'Boot a role' do + it do + is_expected.to converge_test_recipe( + :recipe => 'OneFlowService/action/boot.rb', + :expected => "booted role 'boot' of service 'test_role_action'" + ) + end + end + end + + describe ':delete' do + idempotency_helper( + 'Delete a role', + 'OneFlowService/action/delete.rb', + "deleted role 'delete' of service 'test_role_action'" + ) + end + + describe ':delete_recreate' do + context 'Delete recreate a role' do + it do + is_expected.to converge_test_recipe( + :recipe => 'OneFlowService/action/delete_recreate.rb', + :expected => "deleted and recreated role 'delete_recreate' of service 'test_role_action'" + ) + end + end + end + + describe ':reboot' do + context 'Reboot recreate a role' do + it do + is_expected.to converge_test_recipe( + :recipe => 'OneFlowService/action/reboot.rb', + :expected => "rebooted role 'reboot' of service 'test_role_action'" + ) + end + end + end + + describe ':reboot_hard' do + context 'Reboot hard a role' do + it do + is_expected.to converge_test_recipe( + :recipe => 'OneFlowService/action/reboot_hard.rb', + :expected => "hard rebooted role 'reboot_hard' of service 'test_role_action'" + ) + end + end + end + + describe ':poweroff' do + idempotency_helper( + 'Poweroff a role', + 'OneFlowService/action/poweroff.rb', + "powered-off role 'poweroff' of service 'test_role_action'" + ) + end + + describe ':poweroff_hard' do + idempotency_helper( + 'Poweroff hard a role', + 'OneFlowService/action/poweroff_hard.rb', + "hard powered-off role 'poweroff_hard' of service 'test_role_action'" + ) + end + + describe ':shutdown' do + idempotency_helper( + 'Shutdown the service', + 'OneFlowService/action/shutdown_service.rb', + "shutdown service 'test_role_action'" + ) + end + + ##################### + ## DELETE SERVICES ## + ##################### + + describe ':delete' do + idempotency_helper( + 'Delete service test_simple_instance', + 'OneFlowService/delete/test_simple_instance.rb', + "deleted service 'test_simple_instance'" + ) + end + + describe ':delete' do + idempotency_helper( + 'Delete service test_simple_instance_by_id', + 'OneFlowService/delete/test_simple_instance_by_id.rb', + "deleted service 'test_simple_instance_by_id'" + ) + end + + describe ':delete' do + idempotency_helper( + 'Delete service test_instance_template_options', + 'OneFlowService/delete/test_instance_template_options.rb', + "deleted service 'test_instance_template_options'" + ) + end + + describe ':delete' do + idempotency_helper( + 'Delete service test_role_action', + 'OneFlowService/delete/test_role_action.rb', + "deleted service 'test_role_action'" + ) + end + + ########################### + ## DELETE FLOW TEMPLATES ## + ########################### + + describe ':delete' do + idempotency_helper( + 'Delete simple flow template from hash', + 'OneFlowTemplate/delete/simple_from_hash.rb', + "deleted template 'test_simple_from_hash'" + ) + end + + describe ':delete' do + idempotency_helper( + 'Delete simple flow template from web', + 'OneFlowTemplate/delete/simple_from_web.rb', + "deleted template 'test_simple_from_web'" + ) + end + + describe ':delete' do + idempotency_helper( + 'Delete simple flow template from file', + 'OneFlowTemplate/delete/simple_from_file.rb', + "deleted template 'test_simple_from_file'" + ) + end + + describe ':delete' do + idempotency_helper( + 'Delete flow template with template_options from hash', + 'OneFlowTemplate/delete/tpl_opts_from_hash.rb', + "deleted template 'test_tpl_opts_from_hash'" + ) + end + + describe ':delete' do + idempotency_helper( + 'Delete flow template with template_options from file', + 'OneFlowTemplate/delete/tpl_opts_from_file.rb', + "deleted template 'test_tpl_opts_from_file'" + ) + end + + describe ':delete' do + idempotency_helper( + 'Delete flow template that branch off of \'test_simple_from_hash\' by name', + 'OneFlowTemplate/delete/branch_from_one_name.rb', + "deleted template 'test_branch_from_one_name'" + ) + end + + describe ':delete' do + idempotency_helper( + 'Delete flow template that branch off of \'test_simple_from_hash\' by id', + 'OneFlowTemplate/delete/branch_from_one_id.rb', + "deleted template 'test_branch_from_one_id'" + ) + end + + describe ':delete' do + idempotency_helper( + 'Delete simple instance flow template', + 'OneFlowTemplate/delete/simple_instance_tpl.rb', + "deleted template 'test_simple_instance_tpl'" + ) + end + + describe ':delete' do + idempotency_helper( + 'Delete role action flow template', + 'OneFlowTemplate/delete/role_action_instance.rb', + "deleted template 'test_role_action_instance'" + ) + end + + ######################## + ## DELETE VM TEMPLATE ## + ######################## + + describe 'delete OpenNebula-test-tpl-strings' do + it do + is_expected.to converge_test_recipe( + :recipe => 'OneDriver/delete/OpenNebula-test-tpl-strings.rb', + :expected => "delete template 'OpenNebula-test-tpl-strings'" + ) + end + end +end diff --git a/spec/recipes/OneDriver/instantiate_one_template_spec.rb b/spec/recipes/OneDriver/allocate_change_profile.rb similarity index 73% rename from spec/recipes/OneDriver/instantiate_one_template_spec.rb rename to spec/recipes/OneDriver/allocate_change_profile.rb index 999b1e4..9611a3c 100644 --- a/spec/recipes/OneDriver/instantiate_one_template_spec.rb +++ b/spec/recipes/OneDriver/allocate_change_profile.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,14 +12,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'chef/provisioning/opennebula_driver' -require "#{File.dirname(__FILE__)}/../../config.rb" - -machine 'OpenNebula-tpl-1-vm' do +machine 'OpenNebula-test-vm' do machine_options MACHINE_OPTIONS.merge( :bootstrap_options => { - :template_name => 'OpenNebula-test-tpl' + :template_name => 'OpenNebula-test-tpl-mix' } ) - run_list [] + driver DRIVER_URL_2 + action :allocate end diff --git a/spec/recipes/OneDriver/converge_back_two_vm_spec.rb b/spec/recipes/OneDriver/attach_one_image.rb similarity index 80% rename from spec/recipes/OneDriver/converge_back_two_vm_spec.rb rename to spec/recipes/OneDriver/attach_one_image.rb index c71505d..336bfd2 100644 --- a/spec/recipes/OneDriver/converge_back_two_vm_spec.rb +++ b/spec/recipes/OneDriver/attach_one_image.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,8 +12,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'chef/provisioning/opennebula_driver' - -machine 'OpenNebula-back-2-vm' do - run_list [] +one_image 'OpenNebula-test-img' do + machine_id 'OpenNebula-test-vm' + action :attach end diff --git a/spec/recipes/OneDriver/create_back_one_vm_spec.rb b/spec/recipes/OneDriver/create_back_one_vm_spec.rb deleted file mode 100644 index e7d34fa..0000000 --- a/spec/recipes/OneDriver/create_back_one_vm_spec.rb +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2016, BlackBerry, Inc. -# -# 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 'chef/provisioning/opennebula_driver' - -machine 'OpenNebula-back-1-vm' do - from_image 'OpenNebula-snap-1-img' - action :ready -end diff --git a/spec/recipes/OneDriver/create_back_two_vm_spec.rb b/spec/recipes/OneDriver/create_back_two_vm_spec.rb deleted file mode 100644 index 7809e78..0000000 --- a/spec/recipes/OneDriver/create_back_two_vm_spec.rb +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2016, BlackBerry, Inc. -# -# 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 'chef/provisioning/opennebula_driver' - -machine 'OpenNebula-back-2-vm' do - from_image 'OpenNebula-snap-2-img' - action :ready -end diff --git a/spec/recipes/OneDriver/create_one_image.rb b/spec/recipes/OneDriver/create_one_image.rb new file mode 100644 index 0000000..c18ffec --- /dev/null +++ b/spec/recipes/OneDriver/create_one_image.rb @@ -0,0 +1,20 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_image 'OpenNebula-test-img' do + type 'DATABLOCK' + size 256 + datastore_id DATASTORE_ID + action :create +end diff --git a/spec/recipes/OneDriver/create_one_template_int_spec.rb b/spec/recipes/OneDriver/create_one_template_ints.rb similarity index 58% rename from spec/recipes/OneDriver/create_one_template_int_spec.rb rename to spec/recipes/OneDriver/create_one_template_ints.rb index b2f24ce..fbe462b 100644 --- a/spec/recipes/OneDriver/create_one_template_int_spec.rb +++ b/spec/recipes/OneDriver/create_one_template_ints.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,10 +12,27 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'chef/provisioning/opennebula_driver' -require "#{File.dirname(__FILE__)}/../../config.rb" +def i?(s) + !!(s =~ /\A[-+]?[0-9]+\z/) +end + +# supports Hash, Array +def primitive_strings_to_ints(data) + case data + when Hash + data.map { |k, v| [k, primitive_strings_to_ints(v)] }.to_h + when Array + data.map { |x| primitive_strings_to_ints(x) } + when String + i?(data) ? data.to_i : data + else + data + end +end + +vm_template = primitive_strings_to_ints(VM_TEMPLATE) one_template 'OpenNebula-test-tpl-ints' do - template VM_TEMPLATE.merge('MEMORY' => 256) + template vm_template action :create end diff --git a/spec/recipes/OneDriver/create_one_template_mix.rb b/spec/recipes/OneDriver/create_one_template_mix.rb new file mode 100644 index 0000000..7700cb5 --- /dev/null +++ b/spec/recipes/OneDriver/create_one_template_mix.rb @@ -0,0 +1,51 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +def i?(s) + !!(s =~ /\A[-+]?[0-9]+\z/) +end + +@n = 0 +def int_or_str? + @n += 1 + @n.even? ? :int : :string +end + +# supports Hash, Array +def mix_ints_and_strings(data) + case data + when Hash + data.map { |k, v| [k, mix_ints_and_strings(v)] }.to_h + when Array + data.map { |x| mix_ints_and_strings(x) } + when String + if i?(data) + int_or_str? == :int ? data.to_i : data + else + data + end + when Fixnum + int_or_str? == :string ? data.to_s : data + else + data + end +end + +vm_template = mix_ints_and_strings(VM_TEMPLATE) + +one_template 'OpenNebula-test-tpl-mix' do + template vm_template + mode '666' + action :create +end diff --git a/spec/recipes/OneDriver/create_one_template_spec.rb b/spec/recipes/OneDriver/create_one_template_spec.rb deleted file mode 100644 index 5e1e460..0000000 --- a/spec/recipes/OneDriver/create_one_template_spec.rb +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2016, BlackBerry, Inc. -# -# 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 'chef/provisioning/opennebula_driver' -require "#{File.dirname(__FILE__)}/../../config.rb" - -one_template 'OpenNebula-test-tpl' do - template VM_TEMPLATE - action :create -end diff --git a/spec/recipes/OneDriver/create_one_image_spec.rb b/spec/recipes/OneDriver/create_one_template_strings.rb similarity index 59% rename from spec/recipes/OneDriver/create_one_image_spec.rb rename to spec/recipes/OneDriver/create_one_template_strings.rb index 055a2e8..245a98f 100644 --- a/spec/recipes/OneDriver/create_one_image_spec.rb +++ b/spec/recipes/OneDriver/create_one_template_strings.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,12 +12,23 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'chef/provisioning/opennebula_driver' -require "#{File.dirname(__FILE__)}/../../config.rb" +# supports Hash, Array +def ints_to_strings(data) + case data + when Hash + data.map { |k, v| [k, ints_to_strings(v)] }.to_h + when Array + data.map { |x| ints_to_strings(x) } + when Fixnum + data.to_s + else + data + end +end + +vm_template = ints_to_strings(VM_TEMPLATE) -one_image 'OpenNebula-bootstrap-img' do - type 'DATABLOCK' - size 2048 - datastore_id DATASTORE_ID +one_template 'OpenNebula-test-tpl-strings' do + template vm_template action :create end diff --git a/spec/recipes/OneDriver/converge_back_one_vm_spec.rb b/spec/recipes/OneDriver/create_one_vnet.rb similarity index 80% rename from spec/recipes/OneDriver/converge_back_one_vm_spec.rb rename to spec/recipes/OneDriver/create_one_vnet.rb index 2c95d99..7501c49 100644 --- a/spec/recipes/OneDriver/converge_back_one_vm_spec.rb +++ b/spec/recipes/OneDriver/create_one_vnet.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,8 +12,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'chef/provisioning/opennebula_driver' - -machine 'OpenNebula-back-1-vm' do - run_list [] +one_vnet 'OpenNebula-test-vnet' do + network VNET_ID + size 2 + action :reserve end diff --git a/spec/recipes/OneDriver/delete/OpenNebula-bootstrap-img.rb b/spec/recipes/OneDriver/delete/OpenNebula-bootstrap-img.rb deleted file mode 100644 index 8eca756..0000000 --- a/spec/recipes/OneDriver/delete/OpenNebula-bootstrap-img.rb +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2016, BlackBerry, Inc. -# -# 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 'chef/provisioning/opennebula_driver' - -one_image "OpenNebula-bootstrap-img" do - action :destroy -end diff --git a/spec/recipes/OneDriver/delete/OpenNebula-snap-1-img.rb b/spec/recipes/OneDriver/delete/OpenNebula-snap-1-img.rb deleted file mode 100644 index af05a5f..0000000 --- a/spec/recipes/OneDriver/delete/OpenNebula-snap-1-img.rb +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2016, BlackBerry, Inc. -# -# 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 'chef/provisioning/opennebula_driver' - -one_image "OpenNebula-snap-1-img" do - action :destroy -end diff --git a/spec/recipes/OneDriver/delete/OpenNebula-snap-2-img.rb b/spec/recipes/OneDriver/delete/OpenNebula-snap-2-img.rb deleted file mode 100644 index ef815b7..0000000 --- a/spec/recipes/OneDriver/delete/OpenNebula-snap-2-img.rb +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright 2016, BlackBerry, Inc. -# -# 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 'chef/provisioning/opennebula_driver' - -one_image "OpenNebula-snap-2-img" do - action :destroy -end diff --git a/spec/recipes/OneDriver/delete/OpenNebula-tpl-1-vm.rb b/spec/recipes/OneDriver/delete/OpenNebula-test-img.rb similarity index 83% rename from spec/recipes/OneDriver/delete/OpenNebula-tpl-1-vm.rb rename to spec/recipes/OneDriver/delete/OpenNebula-test-img.rb index 338687f..2690c91 100644 --- a/spec/recipes/OneDriver/delete/OpenNebula-tpl-1-vm.rb +++ b/spec/recipes/OneDriver/delete/OpenNebula-test-img.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'chef/provisioning/opennebula_driver' - -machine "OpenNebula-tpl-1-vm" do +one_image 'OpenNebula-test-img' do action :destroy end diff --git a/spec/recipes/OneDriver/delete/OpenNebula-back-1-vm.rb b/spec/recipes/OneDriver/delete/OpenNebula-test-snap-img.rb similarity index 83% rename from spec/recipes/OneDriver/delete/OpenNebula-back-1-vm.rb rename to spec/recipes/OneDriver/delete/OpenNebula-test-snap-img.rb index 3459111..e3b5fb4 100644 --- a/spec/recipes/OneDriver/delete/OpenNebula-back-1-vm.rb +++ b/spec/recipes/OneDriver/delete/OpenNebula-test-snap-img.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'chef/provisioning/opennebula_driver' - -machine "OpenNebula-back-1-vm" do +one_image 'OpenNebula-test-snap-img' do action :destroy end diff --git a/spec/recipes/OneDriver/delete/OpenNebula-test-tpl-ints.rb b/spec/recipes/OneDriver/delete/OpenNebula-test-tpl-ints.rb index dafa6ad..4e6425b 100644 --- a/spec/recipes/OneDriver/delete/OpenNebula-test-tpl-ints.rb +++ b/spec/recipes/OneDriver/delete/OpenNebula-test-tpl-ints.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'chef/provisioning/opennebula_driver' - -one_template "OpenNebula-test-tpl-ints" do +one_template 'OpenNebula-test-tpl-ints' do action :delete end diff --git a/spec/recipes/OneDriver/delete/OpenNebula-test-tpl.rb b/spec/recipes/OneDriver/delete/OpenNebula-test-tpl-mix.rb similarity index 82% rename from spec/recipes/OneDriver/delete/OpenNebula-test-tpl.rb rename to spec/recipes/OneDriver/delete/OpenNebula-test-tpl-mix.rb index 6fd8390..dfd1587 100644 --- a/spec/recipes/OneDriver/delete/OpenNebula-test-tpl.rb +++ b/spec/recipes/OneDriver/delete/OpenNebula-test-tpl-mix.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'chef/provisioning/opennebula_driver' - -one_template "OpenNebula-test-tpl" do +one_template 'OpenNebula-test-tpl-mix' do action :delete end diff --git a/spec/recipes/OneDriver/delete/OpenNebula-test-tpl-strings.rb b/spec/recipes/OneDriver/delete/OpenNebula-test-tpl-strings.rb new file mode 100644 index 0000000..674b049 --- /dev/null +++ b/spec/recipes/OneDriver/delete/OpenNebula-test-tpl-strings.rb @@ -0,0 +1,17 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_template 'OpenNebula-test-tpl-strings' do + action :delete +end diff --git a/spec/recipes/OneDriver/delete/OpenNebula-back-2-vm.rb b/spec/recipes/OneDriver/delete/OpenNebula-test-vm-vnet.rb similarity index 83% rename from spec/recipes/OneDriver/delete/OpenNebula-back-2-vm.rb rename to spec/recipes/OneDriver/delete/OpenNebula-test-vm-vnet.rb index 6d7703e..14ce63e 100644 --- a/spec/recipes/OneDriver/delete/OpenNebula-back-2-vm.rb +++ b/spec/recipes/OneDriver/delete/OpenNebula-test-vm-vnet.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'chef/provisioning/opennebula_driver' - -machine "OpenNebula-back-2-vm" do +machine 'OpenNebula-test-vm-vnet' do action :destroy end diff --git a/spec/recipes/OneDriver/delete/OpenNebula-bootstrap-vm.rb b/spec/recipes/OneDriver/delete/OpenNebula-test-vm.rb similarity index 82% rename from spec/recipes/OneDriver/delete/OpenNebula-bootstrap-vm.rb rename to spec/recipes/OneDriver/delete/OpenNebula-test-vm.rb index fff8fcb..897c934 100644 --- a/spec/recipes/OneDriver/delete/OpenNebula-bootstrap-vm.rb +++ b/spec/recipes/OneDriver/delete/OpenNebula-test-vm.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,8 +12,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'chef/provisioning/opennebula_driver' - -machine "OpenNebula-bootstrap-vm" do +machine 'OpenNebula-test-vm' do action :destroy end diff --git a/spec/recipes/OneDriver/delete/OpenNebula-test-vnet.rb b/spec/recipes/OneDriver/delete/OpenNebula-test-vnet.rb new file mode 100644 index 0000000..51650b5 --- /dev/null +++ b/spec/recipes/OneDriver/delete/OpenNebula-test-vnet.rb @@ -0,0 +1,17 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_vnet 'OpenNebula-test-vnet' do + action :delete +end diff --git a/spec/recipes/OneDriver/attach_back_one_vm_spec.rb b/spec/recipes/OneDriver/instantiate_one_template.rb similarity index 73% rename from spec/recipes/OneDriver/attach_back_one_vm_spec.rb rename to spec/recipes/OneDriver/instantiate_one_template.rb index f62c566..e16a301 100644 --- a/spec/recipes/OneDriver/attach_back_one_vm_spec.rb +++ b/spec/recipes/OneDriver/instantiate_one_template.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,9 +12,10 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'chef/provisioning/opennebula_driver' - -one_image 'OpenNebula-snap-1-img' do - machine_id 'OpenNebula-back-1-vm' - action :attach +machine 'OpenNebula-test-vm' do + machine_options MACHINE_OPTIONS.merge( + :bootstrap_options => { + :template_name => 'OpenNebula-test-tpl-mix' + } + ) end diff --git a/spec/recipes/OneDriver/converge_bootstrap_vm_spec.rb b/spec/recipes/OneDriver/instantiate_one_template_vnet.rb similarity index 66% rename from spec/recipes/OneDriver/converge_bootstrap_vm_spec.rb rename to spec/recipes/OneDriver/instantiate_one_template_vnet.rb index 6cb2f5a..e6e237b 100644 --- a/spec/recipes/OneDriver/converge_bootstrap_vm_spec.rb +++ b/spec/recipes/OneDriver/instantiate_one_template_vnet.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,15 +12,17 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'chef/provisioning/opennebula_driver' -require "#{File.dirname(__FILE__)}/../../config.rb" - -machine 'OpenNebula-bootstrap-vm' do +machine 'OpenNebula-test-vm-vnet' do machine_options MACHINE_OPTIONS.merge( :bootstrap_options => { - :template_options => { 'MEMORY' => '512', 'CONTEXT' => { 'TEST' => 'test' } }, - :template_name => 'OpenNebula-test-tpl' + :template_name => 'OpenNebula-test-tpl-mix', + :template_options => { + 'NIC' => { + 'NETWORK' => 'OpenNebula-test-vnet', + 'NETWORK_UNAME' => username + } + }, + :mode => '666' } ) - run_list [] end diff --git a/spec/recipes/OneDriver/snapshot_one_image.rb b/spec/recipes/OneDriver/snapshot_one_image.rb new file mode 100644 index 0000000..0d888d7 --- /dev/null +++ b/spec/recipes/OneDriver/snapshot_one_image.rb @@ -0,0 +1,19 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_image 'OpenNebula-test-snap-img' do + machine_id 'OpenNebula-test-vm' + disk_id 'OpenNebula-test-img' + action :snapshot +end diff --git a/spec/recipes/OneDriver/snapshot_one_image_spec.rb b/spec/recipes/OneDriver/snapshot_one_image_spec.rb deleted file mode 100644 index e533b97..0000000 --- a/spec/recipes/OneDriver/snapshot_one_image_spec.rb +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2016, BlackBerry, Inc. -# -# 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 'chef/provisioning/opennebula_driver' - -one_image 'OpenNebula-snap-1-img' do - machine_id 'OpenNebula-bootstrap-vm' - disk_id 'OpenNebula-bootstrap-img' - action :snapshot -end diff --git a/spec/recipes/OneDriver/snapshot_two_image_spec.rb b/spec/recipes/OneDriver/snapshot_two_image_spec.rb deleted file mode 100644 index a34ab74..0000000 --- a/spec/recipes/OneDriver/snapshot_two_image_spec.rb +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2016, BlackBerry, Inc. -# -# 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 'chef/provisioning/opennebula_driver' - -one_image 'OpenNebula-snap-2-img' do - machine_id 'OpenNebula-bootstrap-vm' - disk_id 'OpenNebula-bootstrap-img' - action :snapshot -end diff --git a/spec/recipes/OneFlowService/action/boot.rb b/spec/recipes/OneFlowService/action/boot.rb new file mode 100644 index 0000000..feeb0c0 --- /dev/null +++ b/spec/recipes/OneFlowService/action/boot.rb @@ -0,0 +1,19 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + role 'boot' + override_failsafe true + action :boot +end diff --git a/spec/recipes/OneFlowService/action/delete.rb b/spec/recipes/OneFlowService/action/delete.rb new file mode 100644 index 0000000..b90e159 --- /dev/null +++ b/spec/recipes/OneFlowService/action/delete.rb @@ -0,0 +1,18 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + role 'delete' + action :delete +end diff --git a/spec/recipes/OneFlowService/action/delete_recreate.rb b/spec/recipes/OneFlowService/action/delete_recreate.rb new file mode 100644 index 0000000..c94611e --- /dev/null +++ b/spec/recipes/OneFlowService/action/delete_recreate.rb @@ -0,0 +1,18 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + role 'delete_recreate' + action :delete_recreate +end diff --git a/spec/recipes/OneFlowService/action/hold.rb b/spec/recipes/OneFlowService/action/hold.rb new file mode 100644 index 0000000..6052e83 --- /dev/null +++ b/spec/recipes/OneFlowService/action/hold.rb @@ -0,0 +1,19 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + role 'hold' + override_failsafe true + action :hold +end diff --git a/spec/recipes/OneFlowService/action/poweroff.rb b/spec/recipes/OneFlowService/action/poweroff.rb new file mode 100644 index 0000000..ae04031 --- /dev/null +++ b/spec/recipes/OneFlowService/action/poweroff.rb @@ -0,0 +1,18 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + role 'poweroff' + action :poweroff +end diff --git a/spec/recipes/OneFlowService/action/poweroff_hard.rb b/spec/recipes/OneFlowService/action/poweroff_hard.rb new file mode 100644 index 0000000..b5411a4 --- /dev/null +++ b/spec/recipes/OneFlowService/action/poweroff_hard.rb @@ -0,0 +1,18 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + role 'poweroff_hard' + action :poweroff_hard +end diff --git a/spec/recipes/OneFlowService/action/reboot.rb b/spec/recipes/OneFlowService/action/reboot.rb new file mode 100644 index 0000000..40b1cca --- /dev/null +++ b/spec/recipes/OneFlowService/action/reboot.rb @@ -0,0 +1,18 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + role 'reboot' + action :reboot +end diff --git a/spec/recipes/OneFlowService/action/reboot_hard.rb b/spec/recipes/OneFlowService/action/reboot_hard.rb new file mode 100644 index 0000000..08b5e3f --- /dev/null +++ b/spec/recipes/OneFlowService/action/reboot_hard.rb @@ -0,0 +1,18 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + role 'reboot_hard' + action :reboot_hard +end diff --git a/spec/recipes/OneFlowService/action/release.rb b/spec/recipes/OneFlowService/action/release.rb new file mode 100644 index 0000000..4a6071d --- /dev/null +++ b/spec/recipes/OneFlowService/action/release.rb @@ -0,0 +1,19 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + role 'release' + override_failsafe true + action :release +end diff --git a/spec/recipes/OneFlowService/action/resume.rb b/spec/recipes/OneFlowService/action/resume.rb new file mode 100644 index 0000000..64c532d --- /dev/null +++ b/spec/recipes/OneFlowService/action/resume.rb @@ -0,0 +1,18 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + role 'suspend_resume' + action :resume +end diff --git a/spec/recipes/OneFlowService/action/scale.rb b/spec/recipes/OneFlowService/action/scale.rb new file mode 100644 index 0000000..d674584 --- /dev/null +++ b/spec/recipes/OneFlowService/action/scale.rb @@ -0,0 +1,19 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + role 'scale' + cardinality 2 + action :scale +end diff --git a/spec/recipes/OneFlowService/action/shutdown.rb b/spec/recipes/OneFlowService/action/shutdown.rb new file mode 100644 index 0000000..616f0c0 --- /dev/null +++ b/spec/recipes/OneFlowService/action/shutdown.rb @@ -0,0 +1,18 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + role 'shutdown' + action :shutdown +end diff --git a/spec/recipes/OneFlowService/action/shutdown_hard.rb b/spec/recipes/OneFlowService/action/shutdown_hard.rb new file mode 100644 index 0000000..483a948 --- /dev/null +++ b/spec/recipes/OneFlowService/action/shutdown_hard.rb @@ -0,0 +1,18 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + role 'shutdown_hard' + action :shutdown_hard +end diff --git a/spec/recipes/OneFlowService/action/shutdown_service.rb b/spec/recipes/OneFlowService/action/shutdown_service.rb new file mode 100644 index 0000000..f5cba23 --- /dev/null +++ b/spec/recipes/OneFlowService/action/shutdown_service.rb @@ -0,0 +1,17 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + action :shutdown +end diff --git a/spec/recipes/OneFlowService/action/snapshot_create.rb b/spec/recipes/OneFlowService/action/snapshot_create.rb new file mode 100644 index 0000000..68a709b --- /dev/null +++ b/spec/recipes/OneFlowService/action/snapshot_create.rb @@ -0,0 +1,18 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + role 'snapshot_create' + action :snapshot_create +end diff --git a/spec/recipes/OneFlowService/action/stop.rb b/spec/recipes/OneFlowService/action/stop.rb new file mode 100644 index 0000000..5d7da4e --- /dev/null +++ b/spec/recipes/OneFlowService/action/stop.rb @@ -0,0 +1,18 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + role 'stop' + action :stop +end diff --git a/spec/recipes/OneFlowService/action/suspend.rb b/spec/recipes/OneFlowService/action/suspend.rb new file mode 100644 index 0000000..0f5d2db --- /dev/null +++ b/spec/recipes/OneFlowService/action/suspend.rb @@ -0,0 +1,18 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + role 'suspend_resume' + action :suspend +end diff --git a/spec/recipes/OneFlowService/action/undeploy.rb b/spec/recipes/OneFlowService/action/undeploy.rb new file mode 100644 index 0000000..679077e --- /dev/null +++ b/spec/recipes/OneFlowService/action/undeploy.rb @@ -0,0 +1,18 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + role 'undeploy' + action :undeploy +end diff --git a/spec/recipes/OneFlowService/action/undeploy_hard.rb b/spec/recipes/OneFlowService/action/undeploy_hard.rb new file mode 100644 index 0000000..10e7e01 --- /dev/null +++ b/spec/recipes/OneFlowService/action/undeploy_hard.rb @@ -0,0 +1,18 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + role 'undeploy_hard' + action :undeploy_hard +end diff --git a/spec/recipes/OneFlowService/chmod_simple_by_name.rb b/spec/recipes/OneFlowService/chmod_simple_by_name.rb new file mode 100644 index 0000000..a92fde1 --- /dev/null +++ b/spec/recipes/OneFlowService/chmod_simple_by_name.rb @@ -0,0 +1,19 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_simple_instance' do + template 'test_simple_instance_tpl' + mode '600' + action :instantiate +end diff --git a/spec/recipes/OneFlowService/chmod_simple_by_name_2.rb b/spec/recipes/OneFlowService/chmod_simple_by_name_2.rb new file mode 100644 index 0000000..067624d --- /dev/null +++ b/spec/recipes/OneFlowService/chmod_simple_by_name_2.rb @@ -0,0 +1,18 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_simple_instance' do + mode '666' + action :instantiate +end diff --git a/spec/recipes/OneFlowService/chmod_tpl_opts.rb b/spec/recipes/OneFlowService/chmod_tpl_opts.rb new file mode 100644 index 0000000..448b09d --- /dev/null +++ b/spec/recipes/OneFlowService/chmod_tpl_opts.rb @@ -0,0 +1,31 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_instance_template_options' do + template 'test_simple_instance_tpl' + template_options :name => 'gary', + :deployment => 'none', + :roles => [ + { + :name => 'gary_ubuntu', + :delete_role => true + }, + { + :name => 'gary_ubuntu_new', + :vm_template => 'OpenNebula-test-tpl-strings' + } + ] + mode '644' + action :instantiate +end diff --git a/spec/recipes/OneFlowService/delete/test_instance_template_options.rb b/spec/recipes/OneFlowService/delete/test_instance_template_options.rb new file mode 100644 index 0000000..3e2f9d0 --- /dev/null +++ b/spec/recipes/OneFlowService/delete/test_instance_template_options.rb @@ -0,0 +1,17 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_instance_template_options' do + action :delete +end diff --git a/spec/recipes/OneFlowService/delete/test_role_action.rb b/spec/recipes/OneFlowService/delete/test_role_action.rb new file mode 100644 index 0000000..93daecd --- /dev/null +++ b/spec/recipes/OneFlowService/delete/test_role_action.rb @@ -0,0 +1,17 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_role_action' do + action :delete +end diff --git a/spec/recipes/OneFlowService/delete/test_simple_instance.rb b/spec/recipes/OneFlowService/delete/test_simple_instance.rb new file mode 100644 index 0000000..cc73ed7 --- /dev/null +++ b/spec/recipes/OneFlowService/delete/test_simple_instance.rb @@ -0,0 +1,17 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_simple_instance' do + action :delete +end diff --git a/spec/recipes/OneFlowService/delete/test_simple_instance_by_id.rb b/spec/recipes/OneFlowService/delete/test_simple_instance_by_id.rb new file mode 100644 index 0000000..f320167 --- /dev/null +++ b/spec/recipes/OneFlowService/delete/test_simple_instance_by_id.rb @@ -0,0 +1,17 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_simple_instance_by_id' do + action :delete +end diff --git a/spec/recipes/OneDriver/create_bootstrap_vm_spec.rb b/spec/recipes/OneFlowService/instance_role_action.rb similarity index 53% rename from spec/recipes/OneDriver/create_bootstrap_vm_spec.rb rename to spec/recipes/OneFlowService/instance_role_action.rb index 4e4396b..04b9515 100644 --- a/spec/recipes/OneDriver/create_bootstrap_vm_spec.rb +++ b/spec/recipes/OneFlowService/instance_role_action.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,15 +12,23 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'chef/provisioning/opennebula_driver' -require "#{File.dirname(__FILE__)}/../../config.rb" - -machine 'OpenNebula-bootstrap-vm' do - machine_options MACHINE_OPTIONS.merge( - :bootstrap_options => { - :template_options => { 'MEMORY' => '512', 'CONTEXT' => { 'TEST' => 'test' } }, - :template_name => 'OpenNebula-test-tpl' +one_flow_service 'test_role_action' do + template 'test_role_action_instance' + template_options :roles => [ + { + :name => 'do_not_instance', + :delete_role => true + }, + { + :name => 'snapshot_create', + :vm_template => 'OpenNebula-test-tpl-strings', + :cooldown => 10 + }, + { + :name => 'scale', + :vm_template => 'OpenNebula-test-tpl-strings', + :cooldown => 10 } - ) - action :ready + ] + action :instantiate end diff --git a/spec/recipes/OneFlowService/instance_simple_by_id.rb b/spec/recipes/OneFlowService/instance_simple_by_id.rb new file mode 100644 index 0000000..550eb69 --- /dev/null +++ b/spec/recipes/OneFlowService/instance_simple_by_id.rb @@ -0,0 +1,20 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +id = Chef::Provisioning::OpenNebulaDriver::FlowLib.new(ONE_FLOW_URL, one_auth).get_unique_template_id('test_simple_instance_tpl') + +one_flow_service 'test_simple_instance_by_id' do + template id + action :instantiate +end diff --git a/spec/recipes/OneFlowService/instance_simple_by_name.rb b/spec/recipes/OneFlowService/instance_simple_by_name.rb new file mode 100644 index 0000000..f4fae67 --- /dev/null +++ b/spec/recipes/OneFlowService/instance_simple_by_name.rb @@ -0,0 +1,18 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_simple_instance' do + template 'test_simple_instance_tpl' + mode '640' +end diff --git a/spec/recipes/OneFlowService/instance_tpl_opts.rb b/spec/recipes/OneFlowService/instance_tpl_opts.rb new file mode 100644 index 0000000..757022d --- /dev/null +++ b/spec/recipes/OneFlowService/instance_tpl_opts.rb @@ -0,0 +1,30 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_service 'test_instance_template_options' do + template 'test_simple_instance_tpl' + template_options :name => 'gary', + :deployment => 'none', + :roles => [ + { + :name => 'gary_ubuntu', + :delete_role => true + }, + { + :name => 'gary_ubuntu_new', + :vm_template => 'OpenNebula-test-tpl-strings' + } + ] + action :instantiate +end diff --git a/spec/recipes/OneFlowTemplate/chmod_simple_from_hash.rb b/spec/recipes/OneFlowTemplate/chmod_simple_from_hash.rb new file mode 100644 index 0000000..dc4362a --- /dev/null +++ b/spec/recipes/OneFlowTemplate/chmod_simple_from_hash.rb @@ -0,0 +1,17 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_template 'test_simple_from_hash' do + mode '640' +end diff --git a/spec/recipes/OneFlowTemplate/chmod_update_simple_from_file.rb b/spec/recipes/OneFlowTemplate/chmod_update_simple_from_file.rb new file mode 100644 index 0000000..5948db6 --- /dev/null +++ b/spec/recipes/OneFlowTemplate/chmod_update_simple_from_file.rb @@ -0,0 +1,19 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_template 'gary' do + name 'test_simple_from_file' + template 'file:///tmp/one_rspec_test.json' + mode '666' +end diff --git a/spec/recipes/OneFlowTemplate/create_branch_from_one_id.rb b/spec/recipes/OneFlowTemplate/create_branch_from_one_id.rb new file mode 100644 index 0000000..c5bdbd5 --- /dev/null +++ b/spec/recipes/OneFlowTemplate/create_branch_from_one_id.rb @@ -0,0 +1,43 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +id = Chef::Provisioning::OpenNebulaDriver::FlowLib.new(ONE_FLOW_URL, one_auth).get_unique_template_id('test_simple_from_hash') + +one_flow_template 'gary' do + name 'gary2' + template id + template_options :name => 'test_branch_from_one_id', + :description => 'my description is very descriptive', + :roles => [ + { + :name => 'gary_ubuntu_2', + :delete_role => true + }, + { + :name => 'gary_ubuntu', + :scheduled_policies => [ + { + :type => "CHANGE", + :adjust => 1, + :start_time => "0 3 1-10 * *" + }, + { + :type => "CARDINALITY", + :recurrence => "0 4 1-10 * *", + :adjust => 2 + } + ] + } + ] +end diff --git a/spec/recipes/OneFlowTemplate/create_branch_from_one_name.rb b/spec/recipes/OneFlowTemplate/create_branch_from_one_name.rb new file mode 100644 index 0000000..fb9e7ad --- /dev/null +++ b/spec/recipes/OneFlowTemplate/create_branch_from_one_name.rb @@ -0,0 +1,20 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_template 'gary' do + name 'gary2' + template 'test_simple_from_hash' + template_options :name => 'test_branch_from_one_name', + :description => 'my description is very descriptive' +end diff --git a/spec/recipes/OneFlowTemplate/create_role_action_instance.rb b/spec/recipes/OneFlowTemplate/create_role_action_instance.rb new file mode 100644 index 0000000..69201df --- /dev/null +++ b/spec/recipes/OneFlowTemplate/create_role_action_instance.rb @@ -0,0 +1,99 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_template 'test_role_action_instance' do + template :roles => [ + { + :name => 'shutdown', + :vm_template => 'OpenNebula-test-tpl-strings', + :cooldown => 10 + }, + { + :name => 'shutdown_hard', + :vm_template => 'OpenNebula-test-tpl-strings', + :cooldown => 10 + }, + { + :name => 'undeploy', + :vm_template => 'OpenNebula-test-tpl-strings', + :cooldown => 10 + }, + { + :name => 'undeploy_hard', + :vm_template => 'OpenNebula-test-tpl-strings', + :cooldown => 10 + }, + { + :name => 'hold', + :vm_template => 'OpenNebula-test-tpl-strings', + :cooldown => 10 + }, + { + :name => 'release', + :vm_template => 'OpenNebula-test-tpl-strings', + :cooldown => 10 + }, + { + :name => 'stop', + :vm_template => 'OpenNebula-test-tpl-strings', + :cooldown => 10 + }, + { + :name => 'suspend_resume', + :vm_template => 'OpenNebula-test-tpl-strings', + :cooldown => 10 + }, + { + :name => 'boot', + :vm_template => 'OpenNebula-test-tpl-strings', + :cooldown => 10 + }, + { + :name => 'delete', + :vm_template => 'OpenNebula-test-tpl-strings', + :cooldown => 10 + }, + { + :name => 'delete_recreate', + :vm_template => 'OpenNebula-test-tpl-strings', + :cooldown => 10 + }, + { + :name => 'reboot', + :vm_template => 'OpenNebula-test-tpl-strings', + :cooldown => 10 + }, + { + :name => 'reboot_hard', + :vm_template => 'OpenNebula-test-tpl-strings', + :cooldown => 10 + }, + { + :name => 'poweroff', + :vm_template => 'OpenNebula-test-tpl-strings', + :cooldown => 10 + }, + { + :name => 'poweroff_hard', + :vm_template => 'OpenNebula-test-tpl-strings', + :cooldown => 10 + }, + { + :name => 'do_not_instance', + :vm_template => 'OpenNebula-test-tpl-strings', + :cooldown => 10 + } + ] + action :create +end diff --git a/spec/recipes/OneFlowTemplate/create_simple_from_file.rb b/spec/recipes/OneFlowTemplate/create_simple_from_file.rb new file mode 100644 index 0000000..140731d --- /dev/null +++ b/spec/recipes/OneFlowTemplate/create_simple_from_file.rb @@ -0,0 +1,18 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_template 'gary' do + name 'test_simple_from_file' + template 'file:///tmp/one_rspec_test.json' +end diff --git a/spec/recipes/OneDriver/attach_back_two_vm_spec.rb b/spec/recipes/OneFlowTemplate/create_simple_from_hash.rb similarity index 73% rename from spec/recipes/OneDriver/attach_back_two_vm_spec.rb rename to spec/recipes/OneFlowTemplate/create_simple_from_hash.rb index bb0f253..4d29503 100644 --- a/spec/recipes/OneDriver/attach_back_two_vm_spec.rb +++ b/spec/recipes/OneFlowTemplate/create_simple_from_hash.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,9 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'chef/provisioning/opennebula_driver' - -one_image 'OpenNebula-snap-2-img' do - machine_id 'OpenNebula-back-2-vm' - action :attach +one_flow_template 'test_simple_from_hash' do + template :roles => [ + { + :name => 'gary_ubuntu', + :vm_template => 'OpenNebula-test-tpl-strings' + } + ] end diff --git a/spec/recipes/OneFlowTemplate/create_simple_from_web.rb b/spec/recipes/OneFlowTemplate/create_simple_from_web.rb new file mode 100644 index 0000000..470008e --- /dev/null +++ b/spec/recipes/OneFlowTemplate/create_simple_from_web.rb @@ -0,0 +1,17 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_template 'test_simple_from_web' do + template 'https://dongyuzheng.com/static/misc/one_rspec_test.json' +end diff --git a/spec/recipes/OneDriver/attach_one_image_spec.rb b/spec/recipes/OneFlowTemplate/create_simple_instance_tpl.rb similarity index 72% rename from spec/recipes/OneDriver/attach_one_image_spec.rb rename to spec/recipes/OneFlowTemplate/create_simple_instance_tpl.rb index efe8fc2..b23259d 100644 --- a/spec/recipes/OneDriver/attach_one_image_spec.rb +++ b/spec/recipes/OneFlowTemplate/create_simple_instance_tpl.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,9 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. -require 'chef/provisioning/opennebula_driver' - -one_image 'OpenNebula-bootstrap-img' do - machine_id 'OpenNebula-bootstrap-vm' - action :attach +one_flow_template 'test_simple_instance_tpl' do + template :roles => [ + { + :name => 'gary_ubuntu', + :vm_template => 'OpenNebula-test-tpl-strings' + } + ] end diff --git a/spec/recipes/OneFlowTemplate/create_tpl_opts_from_file.rb b/spec/recipes/OneFlowTemplate/create_tpl_opts_from_file.rb new file mode 100644 index 0000000..2808e67 --- /dev/null +++ b/spec/recipes/OneFlowTemplate/create_tpl_opts_from_file.rb @@ -0,0 +1,30 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_template 'gary' do + template 'file:///tmp/one_rspec_test.json' + template_options :name => 'test_tpl_opts_from_file', + :deployment => nil, + :roles => [ + { + :name => 'gary_ubuntu', + :delete_role => true + }, + { + :name => 'gary_ubuntu_new', + :vm_template => 'OpenNebula-test-tpl-strings' + } + ] + mode '640' +end diff --git a/spec/recipes/OneFlowTemplate/create_tpl_opts_from_hash.rb b/spec/recipes/OneFlowTemplate/create_tpl_opts_from_hash.rb new file mode 100644 index 0000000..e998468 --- /dev/null +++ b/spec/recipes/OneFlowTemplate/create_tpl_opts_from_hash.rb @@ -0,0 +1,35 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_template 'gary' do + template :name => 'test_tpl_opts_from_hash', + :roles => [ + { + :name => 'gary_ubuntu', + :vm_template => 'OpenNebula-test-tpl-strings' + } + ] + template_options :deployment => 'none', + :roles => [ + { + :name => 'gary_ubuntu', + :delete_role => true + }, + { + :name => 'gary_ubuntu_new', + :vm_template => 'OpenNebula-test-tpl-strings' + } + ] + action :create +end diff --git a/spec/recipes/OneFlowTemplate/delete/branch_from_one_id.rb b/spec/recipes/OneFlowTemplate/delete/branch_from_one_id.rb new file mode 100644 index 0000000..d00ad5f --- /dev/null +++ b/spec/recipes/OneFlowTemplate/delete/branch_from_one_id.rb @@ -0,0 +1,17 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_template 'test_branch_from_one_id' do + action :delete +end diff --git a/spec/recipes/OneFlowTemplate/delete/branch_from_one_name.rb b/spec/recipes/OneFlowTemplate/delete/branch_from_one_name.rb new file mode 100644 index 0000000..cbd3a28 --- /dev/null +++ b/spec/recipes/OneFlowTemplate/delete/branch_from_one_name.rb @@ -0,0 +1,17 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_template 'test_branch_from_one_name' do + action :delete +end diff --git a/spec/recipes/OneFlowTemplate/delete/role_action_instance.rb b/spec/recipes/OneFlowTemplate/delete/role_action_instance.rb new file mode 100644 index 0000000..0c8d459 --- /dev/null +++ b/spec/recipes/OneFlowTemplate/delete/role_action_instance.rb @@ -0,0 +1,17 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_template 'test_role_action_instance' do + action :delete +end diff --git a/spec/recipes/OneFlowTemplate/delete/simple_from_file.rb b/spec/recipes/OneFlowTemplate/delete/simple_from_file.rb new file mode 100644 index 0000000..862e874 --- /dev/null +++ b/spec/recipes/OneFlowTemplate/delete/simple_from_file.rb @@ -0,0 +1,17 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_template 'test_simple_from_file' do + action :delete +end diff --git a/spec/recipes/OneFlowTemplate/delete/simple_from_hash.rb b/spec/recipes/OneFlowTemplate/delete/simple_from_hash.rb new file mode 100644 index 0000000..2b82cc4 --- /dev/null +++ b/spec/recipes/OneFlowTemplate/delete/simple_from_hash.rb @@ -0,0 +1,17 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_template 'test_simple_from_hash' do + action :delete +end diff --git a/spec/recipes/OneFlowTemplate/delete/simple_from_web.rb b/spec/recipes/OneFlowTemplate/delete/simple_from_web.rb new file mode 100644 index 0000000..7364605 --- /dev/null +++ b/spec/recipes/OneFlowTemplate/delete/simple_from_web.rb @@ -0,0 +1,17 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_template 'test_simple_from_web' do + action :delete +end diff --git a/spec/recipes/OneFlowTemplate/delete/simple_instance_tpl.rb b/spec/recipes/OneFlowTemplate/delete/simple_instance_tpl.rb new file mode 100644 index 0000000..cf37ec0 --- /dev/null +++ b/spec/recipes/OneFlowTemplate/delete/simple_instance_tpl.rb @@ -0,0 +1,17 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_template 'test_simple_instance_tpl' do + action :delete +end diff --git a/spec/recipes/OneFlowTemplate/delete/tpl_opts_from_file.rb b/spec/recipes/OneFlowTemplate/delete/tpl_opts_from_file.rb new file mode 100644 index 0000000..c8c0033 --- /dev/null +++ b/spec/recipes/OneFlowTemplate/delete/tpl_opts_from_file.rb @@ -0,0 +1,17 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_template 'test_tpl_opts_from_file' do + action :delete +end diff --git a/spec/recipes/OneFlowTemplate/delete/tpl_opts_from_hash.rb b/spec/recipes/OneFlowTemplate/delete/tpl_opts_from_hash.rb new file mode 100644 index 0000000..9462a6e --- /dev/null +++ b/spec/recipes/OneFlowTemplate/delete/tpl_opts_from_hash.rb @@ -0,0 +1,17 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_template 'test_tpl_opts_from_hash' do + action :delete +end diff --git a/spec/recipes/OneFlowTemplate/update_simple_from_hash.rb b/spec/recipes/OneFlowTemplate/update_simple_from_hash.rb new file mode 100644 index 0000000..56d50ed --- /dev/null +++ b/spec/recipes/OneFlowTemplate/update_simple_from_hash.rb @@ -0,0 +1,57 @@ +# Copyright 2016, BlackBerry Limited +# +# 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. + +one_flow_template 'test_simple_from_hash' do + template :deployment => 'none', + :roles => [ + { + :name => 'gary_ubuntu', + :min_vms => 1, + :max_vms => 5, + :scheduled_policies => [ + { + :type => "PERCENTAGE_CHANGE", + :recurrence => "0 1 1-10 * *", + :adjust => 3, + :min_adjust_step => 14 + } + ] + }, + { + :name => 'gary_ubuntu_2', + :vm_template => 'OpenNebula-test-tpl-strings', + :cooldown => 123, + :min_vms => 1, + :max_vms => 5, + :elasticity_policies => [ + { + :type => "CHANGE", + :cooldown => 17, + :period => 15, + :adjust => 2, + :period_number => 2, + :expression => "ATT == 20" + }, + { + :type => "CARDINALITY", + :cooldown => 14, + :period => 13, + :adjust => 3, + :period_number => 1, + :expression => "ATT > 20" + } + ] + } + ] +end diff --git a/spec/recipes/driver_options_spec.rb b/spec/recipes/common.rb similarity index 75% rename from spec/recipes/driver_options_spec.rb rename to spec/recipes/common.rb index d41e41a..da973aa 100644 --- a/spec/recipes/driver_options_spec.rb +++ b/spec/recipes/common.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,14 +14,20 @@ require 'chef/provisioning/opennebula_driver' require 'fileutils' -require "#{File.dirname(__FILE__)}/../config.rb" FileUtils.mkdir_p(CHEF_REPO_PATH.chomp('/')) with_chef_local_server :chef_repo_path => CHEF_REPO_PATH.chomp('/') -with_driver((ONE_XMLRPC[0, 11] == 'opennebula:' ? ONE_XMLRPC : 'opennebula:' + ONE_XMLRPC).chomp('/')) +with_driver DRIVER_URL +with_flow_url ONE_FLOW_URL.chomp('/') unless ONE_FLOW_URL.nil? with_machine_options MACHINE_OPTIONS.merge( :bootstrap_options => { :template => VM_TEMPLATE } ) + +one_auth = Chef::Provisioning::OpenNebulaDriver.get_onelib( + :driver_url => DRIVER_URL +).client.one_auth + +username = one_auth.split(':').first diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 39a3af7..6faf99f 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -19,31 +19,35 @@ require 'chef/provisioning/opennebula_driver' require 'chef/run_context' require 'cheffish/rspec/matchers' -require 'opennebula' require 'support/opennebula_support' require 'fileutils' +require_relative 'config.rb' -def test_helper(context, recipe, expected, error = nil) +def idempotency_helper(context, recipe, expected = nil) context context do - it { is_expected.to converge_test_recipe(recipe, expected, error) } + it { is_expected.to converge_test_recipe(:recipe => recipe, :expected => expected, :fail_if => '(up to date)') } end context "[SKIP] #{context}" do - it { is_expected.to converge_test_recipe(recipe, :idempotent, error) } + it { is_expected.to converge_test_recipe(:recipe => recipe, :expected => '(up to date)', :fail_if => nil) } end end def cleanup - chef_run(%w( - OneDriver/delete/OpenNebula-test-tpl.rb + # OneDriver deletes are listed explicitly because they need to be run in a certain order. + cleanup_list = %w( + OneDriver/delete/OpenNebula-test-tpl-strings.rb OneDriver/delete/OpenNebula-test-tpl-ints.rb - OneDriver/delete/OpenNebula-tpl-1-vm.rb - OneDriver/delete/OpenNebula-bootstrap-vm.rb - OneDriver/delete/OpenNebula-bootstrap-img.rb - OneDriver/delete/OpenNebula-back-1-vm.rb - OneDriver/delete/OpenNebula-back-2-vm.rb - OneDriver/delete/OpenNebula-snap-1-img.rb - OneDriver/delete/OpenNebula-snap-2-img.rb - )) + OneDriver/delete/OpenNebula-test-tpl-mix.rb + OneDriver/delete/OpenNebula-test-vm.rb + OneDriver/delete/OpenNebula-test-vm-vnet.rb + OneDriver/delete/OpenNebula-test-vnet.rb + OneDriver/delete/OpenNebula-test-img.rb + OneDriver/delete/OpenNebula-test-snap-img.rb + ).map { |f| "#{File.dirname(__FILE__)}/recipes/" + f } + cleanup_list += Dir["#{File.dirname(__FILE__)}/recipes/OneFlowTemplate/delete/*.rb"] unless ONE_FLOW_URL.nil? + cleanup_list += Dir["#{File.dirname(__FILE__)}/recipes/OneFlowService/delete/*.rb"] unless ONE_FLOW_URL.nil? + err = get_error(chef_run(cleanup_list, false), 'Chef Client finished', nil) + fail "\n\nTest suite cleanup failed\n#{err.first}\n\n" unless err.first.nil? end RSpec.configure do |config| @@ -54,10 +58,11 @@ def cleanup FileUtils.rm_rf(config.log_dir) FileUtils.mkdir_p(config.log_dir) FileUtils.rm_rf('nodes') - fail 'Quick cleanup before testing failed.' unless cleanup.include?('Chef Client finished') + cleanup end config.after(:suite) do FileUtils.rm_rf('nodes') - fail 'Quick cleanup after testing failed.' unless cleanup.include?('Chef Client finished') + cleanup + FileUtils.rm_rf('/tmp/chef-provisioning-opennebula-rspec-recipe.rb') end end diff --git a/spec/support/opennebula_support.rb b/spec/support/opennebula_support.rb index 433427a..deb9701 100644 --- a/spec/support/opennebula_support.rb +++ b/spec/support/opennebula_support.rb @@ -1,4 +1,4 @@ -# Copyright 2016, BlackBerry, Inc. +# Copyright 2016, BlackBerry Limited # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,10 +17,21 @@ require 'chef/provisioning/opennebula_driver' require 'fileutils' -def chef_run(recipe) +def chef_run(recipe, append_path = true) recipe_array = recipe.is_a?(Array) ? recipe : [recipe] + recipe_array.map! { |r| './spec/recipes/' + r } if append_path + recipe_array = ['./spec/recipes/common.rb'] + recipe_array + FileUtils.rm_rf('/tmp/chef-provisioning-opennebula-rspec-recipe.rb') + File.open('/tmp/chef-provisioning-opennebula-rspec-recipe.rb', 'a') do |file| + file.puts("require '#{File.dirname(__FILE__)}/../config.rb'") + recipe_array.each do |recipe_file| + content = File.read(recipe_file) + file.puts('') + file.puts(content) + end + end chef_client = Mixlib::ShellOut.new( - "bundle exec chef-client -z ./spec/recipes/driver_options_spec.rb #{recipe_array.map { |r| './spec/recipes/' + r }.join(' ')} --force-formatter", + 'chef-client -z /tmp/chef-provisioning-opennebula-rspec-recipe.rb --force-formatter', shellout_options(:timeout => 900) ) chef_client.run_command @@ -32,65 +43,84 @@ def shellout_options(options = {}) end def format_error(msg) - "================================================================================\n#{msg}\n================================================================================" + "================================================================================\n#{msg}\n================================================================================\n " +end + +def get_unique_file(path, basename, rest) + p = path.chomp('/') + fn = "#{p}/#{basename}#{rest}" + return fn unless File.exist?(fn) + n = 1 + n += 1 while File.exist?("#{p}/#{basename}__#{n}#{rest}") + "#{p}/#{basename}__#{n}#{rest}" end -# gets runtime / idempotency-related errors from stdout -def get_error(stdout, expected = nil, error = nil) - err = stdout.include?('Chef Client finished') ? nil : "Chef run did not report 'Chef Client finished', no errors were detected." +def get_error(stdout, expected, fail_if) + stacktrace = stdout.match(/FATAL: Stacktrace dumped to (.*?chef-stacktrace\.out)/) + stacktrace = stacktrace ? stacktrace[1] : nil + err = stacktrace ? "Chef run did not report 'Chef Client finished'." : nil - unless error.nil? - case error + case fail_if + when Regexp + return "stdout matched the following when it should not have:\n#{fail_if}", stacktrace if stdout =~ fail_if + when String + return "stdout included the following when it should not have:\n#{fail_if}", stacktrace if stdout.include?(fail_if) + end unless fail_if.nil? + + # Each chef run can only fail due to one reason, so if it was an expected error, we can simply return nil + [' RuntimeError: ', ' NoMethodError: ', ' TypeError: ', ' ERROR: ', ' FATAL: '].each do |e| + the_error = (stdout.split(e).last).split("\n")[0...-1].join("\n") + case expected when Regexp - return "stdout matched:\n#{error}" if stdout =~ error + if e + the_error =~ expected + return nil, nil + else + return "#{e.strip}\n#{the_error}", stacktrace + end when String - return "stdout included:\n#{error}" if stdout.include?(error) - end - end - - if stdout.include?('RuntimeError: ') - return "RuntimeError\n" + (stdout.split('RuntimeError: ').last).split("\n").first - elsif stdout.include?('NoMethodError: ') - return "NoMethodError\n" + (stdout.split('NoMethodError: ').last).split("\n").first - elsif stdout.include?('ERROR: ') && err - return "ERROR\n" + (stdout.split('ERROR: ').last).split("\n").first - elsif stdout.include?('FATAL: ') - return "FATAL\nAn unknown fatal error has occurred." - end + if (e + the_error).include?(expected) + return nil, nil + else + return "#{e.strip}\n#{the_error}", stacktrace + end + else + return "#{e.strip}\n#{the_error}", stacktrace + end if stdout.include?(e) + end if err - return err if expected.nil? + return err, stacktrace if expected.nil? case expected - when Symbol - fail "The only symbol supported for 'expected' is :idempotent, you passed :#{expected}" unless expected == :idempotent - return 'Chef run did not idempotently skip when it should have.' unless stdout.include?('(up to date)') when Regexp - return "Chef run idempotently skipped when it should not have.\nIf you intended for it to skip, pass in :idempotent as 'expected' instead." if stdout.include?('(up to date)') - return "No match in stdout for:\n#{expected}" unless stdout =~ expected + return "stdout did not match the following when it should have:\n#{expected}", stacktrace unless stdout =~ expected when String - return "Chef run idempotently skipped when it should not have.\nIf you intended for it to skip, pass in :idempotent as 'expected' instead." if stdout.include?('(up to date)') - return "stdout did not include:\n#{expected}" unless stdout.include?(expected) + return "stdout did not include the following when it should have:\n#{expected}", stacktrace unless stdout.include?(expected) end - err + [err, stacktrace] end -RSpec::Matchers.define :converge_test_recipe do |recipe = nil, expected = :idempotent, error = nil| - fail 'All tests require a recipe.' if recipe.nil? +# data = { +# :recipe => 'recipe to test, must be given', +# :expected => 'fail if not match, can be errors', +# :fail_if => 'fail if match' +# } +RSpec::Matchers.define :converge_test_recipe do |data = {}| + fail 'All tests require a :recipe.' unless data[:recipe] match do - stdout = chef_run(recipe) - # logs each chef run - dir = RSpec.configuration.log_dir + '/' + File.dirname(recipe) + stdout = chef_run(data[:recipe]) + + dir = RSpec.configuration.log_dir + '/' + File.dirname(data[:recipe]) FileUtils.mkdir_p(dir) - log_basename = expected == :idempotent ? File.basename(recipe, '.*') + '__i' : File.basename(recipe, '.*') - File.open("./#{dir}/#{log_basename}_stdout.log", 'w+') { |file| file.write(stdout) } - @error_message = get_error(stdout, expected, error) + + log_basename = File.basename(data[:recipe], '.*') + File.open(get_unique_file("./#{dir}", log_basename, '.stdout.log'), 'w+') { |file| file.write(stdout) } + + @error_message, stacktrace = get_error(stdout, data[:expected], data[:fail_if]) @error_message = format_error(@error_message) unless @error_message.nil? - # copies the stacktrace for tests that have failed - FileUtils.cp( - "#{ENV['HOME']}/.chef/local-mode-cache/cache/chef-stacktrace.out", - "./#{dir}/#{log_basename}_stacktrace.out" - ) unless @error_message.nil? + + FileUtils.cp(stacktrace, get_unique_file("./#{dir}", log_basename, '.stacktrace.out')) if stacktrace + @error_message.nil? end failure_message do