From: Martin Zobel-Helas Date: Sun, 21 Jun 2015 19:47:42 +0000 (+0000) Subject: add aimonb/aviator to 3rdparty X-Git-Url: https://git.adam-barratt.org.uk/?a=commitdiff_plain;h=b7626cbcbb2fb8e7ce3dc5ac60e80a981175f9d3;p=mirror%2Fdsa-puppet.git add aimonb/aviator to 3rdparty Signed-off-by: Martin Zobel-Helas --- diff --git a/3rdparty/Puppetfile b/3rdparty/Puppetfile index 67741c4b0..bcf63fd58 100644 --- a/3rdparty/Puppetfile +++ b/3rdparty/Puppetfile @@ -12,3 +12,4 @@ mod 'elasticsearch/elasticsearch', '0.9.5' mod 'nanliu/staging', '1.0.3' mod 'stackforge/openstacklib', '5.1.0' +mod 'aimonb/aviator', '0.5.1' diff --git a/3rdparty/modules/aviator/Aviator_README.md b/3rdparty/modules/aviator/Aviator_README.md new file mode 100644 index 000000000..d85f93a0a --- /dev/null +++ b/3rdparty/modules/aviator/Aviator_README.md @@ -0,0 +1,11 @@ +![Aviator](https://raw.github.com/aviator/www/gh-pages/images/logo-small.png) +
A lightweight library for communicating with the OpenStack API. + +[![Build Status](https://travis-ci.org/aviator/aviator.png?branch=master)](https://travis-ci.org/aviator/aviator) +[![Coverage Status](https://coveralls.io/repos/aviator/aviator/badge.png?branch=master)](https://coveralls.io/r/aviator/aviator?branch=master) +[![Code Climate](https://codeclimate.com/github/aviator/aviator.png)](https://codeclimate.com/github/aviator/aviator) +[![Gem Version](https://badge.fury.io/rb/aviator.png)](http://badge.fury.io/rb/aviator) +[![Dependency Status](https://gemnasium.com/aviator/aviator.png)](https://gemnasium.com/aviator/aviator) + + +Usage and Installation diff --git a/3rdparty/modules/aviator/Gemfile b/3rdparty/modules/aviator/Gemfile new file mode 100644 index 000000000..483cfd0aa --- /dev/null +++ b/3rdparty/modules/aviator/Gemfile @@ -0,0 +1,17 @@ +# A sample Gemfile +source "https://rubygems.org" + +gem 'ci_reporter' +gem 'simplecov' +gem 'simplecov-rcov' +gem "rspec", '~> 2.0' +gem "mocha" +gem 'puppet', '= 3.5.1' +gem 'puppet-lint' +gem 'facter', '>= 1.6.10' +gem 'rspec-puppet', :git => 'https://github.com/rodjek/rspec-puppet.git', :branch => 'master' +gem 'rake', '>= 0.9.2' +gem 'puppetlabs_spec_helper', '0.3.0' +gem 'test-unit' +gem 'rspec_junit_formatter' +gem 'rspec-puppet-utils' diff --git a/3rdparty/modules/aviator/Gemfile.lock b/3rdparty/modules/aviator/Gemfile.lock new file mode 100644 index 000000000..b45c0880d --- /dev/null +++ b/3rdparty/modules/aviator/Gemfile.lock @@ -0,0 +1,81 @@ +GIT + remote: https://github.com/rodjek/rspec-puppet.git + revision: 389f99ef666521fec1b4530fe69dc1ab84a060a8 + branch: master + specs: + rspec-puppet (1.0.1) + rspec + +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (2.2.8) + builder (3.2.2) + ci_reporter (2.0.0) + builder (>= 2.1.2) + diff-lcs (1.2.5) + docile (1.1.5) + facter (2.2.0) + CFPropertyList (~> 2.2.6) + hiera (1.3.4) + json_pure + json_pure (1.8.1) + metaclass (0.0.4) + mocha (1.1.0) + metaclass (~> 0.0.1) + multi_json (1.10.1) + power_assert (0.1.3) + puppet (3.5.1) + facter (> 1.6, < 3) + hiera (~> 1.0) + json_pure + rgen (~> 0.6.5) + puppet-lint (1.0.1) + puppetlabs_spec_helper (0.3.0) + mocha (>= 0.10.5) + rake + rspec (>= 2.9.0) + rspec-puppet (>= 0.1.1) + rake (10.3.2) + rgen (0.6.6) + rspec (2.99.0) + rspec-core (~> 2.99.0) + rspec-expectations (~> 2.99.0) + rspec-mocks (~> 2.99.0) + rspec-core (2.99.2) + rspec-expectations (2.99.2) + diff-lcs (>= 1.1.3, < 2.0) + rspec-mocks (2.99.2) + rspec-puppet-utils (2.0.4) + rspec_junit_formatter (0.2.0) + builder (< 4) + rspec (>= 2, < 4) + rspec-core (!= 2.12.0) + simplecov (0.9.0) + docile (~> 1.1.0) + multi_json + simplecov-html (~> 0.8.0) + simplecov-html (0.8.0) + simplecov-rcov (0.2.3) + simplecov (>= 0.4.1) + test-unit (3.0.1) + power_assert + +PLATFORMS + ruby + +DEPENDENCIES + ci_reporter + facter (>= 1.6.10) + mocha + puppet (= 3.5.1) + puppet-lint + puppetlabs_spec_helper (= 0.3.0) + rake (>= 0.9.2) + rspec (~> 2.0) + rspec-puppet! + rspec-puppet-utils + rspec_junit_formatter + simplecov + simplecov-rcov + test-unit diff --git a/3rdparty/modules/aviator/LICENSE.txt b/3rdparty/modules/aviator/LICENSE.txt new file mode 100644 index 000000000..5c8a6e3a1 --- /dev/null +++ b/3rdparty/modules/aviator/LICENSE.txt @@ -0,0 +1,22 @@ +Copyright (c) 2014 Mark Maglana + +MIT License + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/3rdparty/modules/aviator/Modulefile b/3rdparty/modules/aviator/Modulefile new file mode 100644 index 000000000..133a66cb9 --- /dev/null +++ b/3rdparty/modules/aviator/Modulefile @@ -0,0 +1,11 @@ +name 'aimonb-aviator' +version '0.5.1' +source 'https://github.com/aimonb/puppet_aviator' +author 'aimonb' +license 'MIT License' +summary 'Puppet feature wrapper for the Aviator OpenStack API library for Ruby' +description 'UNKNOWN' +project_page 'https://github.com/aimonb/puppet_aviator' + +## Add dependencies, if any: +# dependency 'username/name', '>= 1.2.0' diff --git a/3rdparty/modules/aviator/README b/3rdparty/modules/aviator/README new file mode 100644 index 000000000..db81dbee9 --- /dev/null +++ b/3rdparty/modules/aviator/README @@ -0,0 +1,45 @@ +Puppet Aviator + +A feature module for the Aviator project. + +Aviator is a lightweight library for communicating with the OpenStack +API + +See Aviator_README.md for more information on Aviator. + +License +------- +MIT License + +Contact +------- +Aimon Bustardo + +Example Usage: +------- + + $LOAD_PATH.push(File.join(File.dirname(__FILE__), '..', '..', +'..')) + require 'puppet/feature/aviator' + + configuration = { + :provider => 'openstack', + :auth_service => { + :name => 'identity', + :host_uri => 'http://devstack:5000/v2.0', + :request => 'create_token', + :validator => 'list_tenants' + }, + :auth_credentials => { + :username => 'myusername', + :password => 'mypassword', + :tenant_name => 'myproject' + } + } + + openstack = Aviator::Session.new(:config => configuration) + + openstack.authenticate + response = openstack.request :identity_service, :list_tenants, :endpoint_type => 'admin' + + puts response[:body] diff --git a/3rdparty/modules/aviator/checksums.json b/3rdparty/modules/aviator/checksums.json new file mode 100644 index 000000000..751222b9a --- /dev/null +++ b/3rdparty/modules/aviator/checksums.json @@ -0,0 +1,261 @@ +{ + "Aviator_README.md": "06fac4cf003223c93ed23ea30e134e0a", + "Gemfile": "6d7f95a9e9993f49da52c1aa034ca599", + "Gemfile.lock": "5f2229c686025c1c5fcf0386bf08ebc1", + "LICENSE.txt": "25c9cebc4248703a08cfe5c333398bc6", + "Modulefile": "887af1b027892ea3a1e45350d9734643", + "README": "29e71fa36fbf6b393b3922ee892a9cc3", + "feature/aviator/compatibility.rb": "d103a261221e127c48ae8db01623cbb7", + "feature/aviator/core/cli/describer.rb": "a94adec4d61b706461597d23df66f76f", + "feature/aviator/core/cli.rb": "4fe815c3d85859dd6a9893a5aa38c7f8", + "feature/aviator/core/logger.rb": "99aa5ef113f491a563fdf8ecf6a44db2", + "feature/aviator/core/request.rb": "2477263dfc7b32751906c39448600838", + "feature/aviator/core/request_builder.rb": "2e3996fcfe619898c2b4638c96cc1616", + "feature/aviator/core/response.rb": "71629a33c4778a79b9f27fb4b8d469c0", + "feature/aviator/core/service.rb": "8f3c0b07e8a0c2d4ef6af7c7e0113d85", + "feature/aviator/core/session.rb": "3dabc2f13471632e809eb6ace4b6fbbe", + "feature/aviator/core.rb": "3d116a1ade58c869219ad2c2e3a01e59", + "feature/aviator/hashish.rb": "b9cf59c89b22cb6b39ec6916db1c5fb6", + "feature/aviator/openstack/common/v2/admin/base.rb": "8e88c76b3aa87bf3f69772bc5a7b4cfa", + "feature/aviator/openstack/common/v2/public/base.rb": "e1688afd9f65822599cfc8996256f979", + "feature/aviator/openstack/compute/v2/admin/confirm_server_resize.rb": "d7c43043c66a862d5232e999254c8f1a", + "feature/aviator/openstack/compute/v2/admin/create_network.rb": "b11ff615a495b3189ff18d2fdd580340", + "feature/aviator/openstack/compute/v2/admin/get_host_details.rb": "4e0200122c40d2acd95ca29ffb1a648f", + "feature/aviator/openstack/compute/v2/admin/list_hosts.rb": "25448fc1b14189d0d6aa6562c25d2172", + "feature/aviator/openstack/compute/v2/admin/lock_server.rb": "ff124f629375a069d0a39674a835669d", + "feature/aviator/openstack/compute/v2/admin/migrate_server.rb": "9b27fe512de6592e28e8ae534ef4e227", + "feature/aviator/openstack/compute/v2/admin/reset_server.rb": "83ceb5bde8297f40637901107c0779ce", + "feature/aviator/openstack/compute/v2/admin/resize_server.rb": "38d073f289de8cbcd54326dfcceb1203", + "feature/aviator/openstack/compute/v2/admin/revert_server_resize.rb": "c86f20c4c92417da7470a93adf2ac886", + "feature/aviator/openstack/compute/v2/admin/unlock_server.rb": "844f5380140805475c7a44d964960558", + "feature/aviator/openstack/compute/v2/public/change_admin_password.rb": "e5ed804402e4c969de89f669bbdbed52", + "feature/aviator/openstack/compute/v2/public/create_image.rb": "605c7f1dccc0e25f75a22b8133e0ac1c", + "feature/aviator/openstack/compute/v2/public/create_server.rb": "3d1408639e56cf9e32d26967dbbfc3f3", + "feature/aviator/openstack/compute/v2/public/delete_image.rb": "fb0f14aa4d3cd80e0b32ebcd0d32b62b", + "feature/aviator/openstack/compute/v2/public/delete_image_metadata_item.rb": "8f24549420f5b2ec73d245d84364f6a1", + "feature/aviator/openstack/compute/v2/public/delete_server.rb": "89fca14a34d08483992b03e0b3256e24", + "feature/aviator/openstack/compute/v2/public/delete_server_metadata_item.rb": "1caa8f632ee0e7964d0774f8fcdde5f8", + "feature/aviator/openstack/compute/v2/public/get_flavor_details.rb": "335012feb1abc4a0c0bfd57e09dd906f", + "feature/aviator/openstack/compute/v2/public/get_image_details.rb": "779845403f9314ddbda05121b54cd428", + "feature/aviator/openstack/compute/v2/public/get_image_metadata_item.rb": "cdc2caa68f52f33f5944770cb0594623", + "feature/aviator/openstack/compute/v2/public/get_network_details.rb": "43f08bb5513fd78f5685f065111a89e7", + "feature/aviator/openstack/compute/v2/public/get_server.rb": "9b764bb9b93cf368b7bec8ed70654490", + "feature/aviator/openstack/compute/v2/public/get_server_metadata_item.rb": "7e6a0feca6e6e2afc89e8b8cf00e6493", + "feature/aviator/openstack/compute/v2/public/list_addresses.rb": "ff343fead191c3d13677448daee3822c", + "feature/aviator/openstack/compute/v2/public/list_flavors.rb": "7050181d84ada85de9a3cfe476040432", + "feature/aviator/openstack/compute/v2/public/list_image_metadata.rb": "36cc324f2f8ec4e12a7f47846099aaa1", + "feature/aviator/openstack/compute/v2/public/list_images.rb": "9dcace5a72ef644072ede3bdcdf031ed", + "feature/aviator/openstack/compute/v2/public/list_networks.rb": "5639d0a86c7b37a0ba957f9cdb5a83ab", + "feature/aviator/openstack/compute/v2/public/list_server_metadata.rb": "5815bd0f48e81dea65c13bb0bb4c944e", + "feature/aviator/openstack/compute/v2/public/list_servers.rb": "deaf400faab4a9c0dd632be988fa002b", + "feature/aviator/openstack/compute/v2/public/pause_server.rb": "e2ac1913b925f61707516103d5c204cf", + "feature/aviator/openstack/compute/v2/public/reboot_server.rb": "73a34c9cf36b087e167e4d5a0a0b9762", + "feature/aviator/openstack/compute/v2/public/rebuild_server.rb": "907eee7ab63f3c8c3c93c9cc522aa208", + "feature/aviator/openstack/compute/v2/public/resume_server.rb": "f24ef2b6d7e4be1664d89a5d1bd76c2f", + "feature/aviator/openstack/compute/v2/public/root.rb": "cee3dd2aff0710d0f5fccc23508a7f58", + "feature/aviator/openstack/compute/v2/public/set_image_metadata.rb": "e49c35f9b95a268803578549ffce5cc0", + "feature/aviator/openstack/compute/v2/public/set_server_metadata.rb": "ece9d9a873ef6a3e468ae7285cd335f1", + "feature/aviator/openstack/compute/v2/public/suspend_server.rb": "a9fe5dc5c43dbb9da293de1eecd440a4", + "feature/aviator/openstack/compute/v2/public/unpause_server.rb": "9075ce7b123abce8917371fc545bbf92", + "feature/aviator/openstack/compute/v2/public/update_image_metadata.rb": "453dc71ce53a784322460afe8f8a0ffd", + "feature/aviator/openstack/compute/v2/public/update_server.rb": "19bab4a3b3b5fc8af215c53f3582f0cc", + "feature/aviator/openstack/compute/v2/public/update_server_metadata.rb": "72107bf121c284fb859e1d0d544c9f8c", + "feature/aviator/openstack/identity/v2/admin/add_role_to_user_on_tenant.rb": "d5962f765a8e2091aa0d7feab0f860b6", + "feature/aviator/openstack/identity/v2/admin/create_tenant.rb": "eb5b538285459bbc70da43ecb10a2ae1", + "feature/aviator/openstack/identity/v2/admin/create_user.rb": "a6f1152f0d2f2db837e9c87bf6dc8c76", + "feature/aviator/openstack/identity/v2/admin/delete_role_from_user_on_tenant.rb": "82e5b5520e9e10e8dba716b2e852cad9", + "feature/aviator/openstack/identity/v2/admin/delete_tenant.rb": "ad0bd04e86d4025a462ef6094313db63", + "feature/aviator/openstack/identity/v2/admin/delete_user.rb": "152712c94b6cec9da57cbff82a983ae1", + "feature/aviator/openstack/identity/v2/admin/get_tenant_by_id.rb": "0c93905f14e07e67f709739dd763d6e1", + "feature/aviator/openstack/identity/v2/admin/list_tenants.rb": "e75b66b966e49f045b7c61789ffd5b5e", + "feature/aviator/openstack/identity/v2/admin/list_users.rb": "afe6aea93af4ce623eb423e42a56473f", + "feature/aviator/openstack/identity/v2/admin/update_tenant.rb": "5e0250596b90187e09f5da7b2bb6c283", + "feature/aviator/openstack/identity/v2/admin/update_user.rb": "dd0ade2d22271f2e236caa42c65fb2bf", + "feature/aviator/openstack/identity/v2/public/create_token.rb": "2e44dafa7758d4610a5c06d54fc53ffa", + "feature/aviator/openstack/identity/v2/public/list_tenants.rb": "826d93b39fba2b8e85c4c9979f363afd", + "feature/aviator/openstack/identity/v2/public/root.rb": "49c81b24643287440458224c9eabc350", + "feature/aviator/openstack/image/v1/public/list_public_images.rb": "746ac90e4d5099a64ad08f4cc3829d97", + "feature/aviator/openstack/image/v1/public/root.rb": "b3b0897ea44361584961832fedf8f2ce", + "feature/aviator/openstack/metering/v1/admin/list_projects.rb": "22fc778d98d8424efcd14fa64e023c91", + "feature/aviator/openstack/volume/v1/public/create_volume.rb": "b0118b8f421376da64eb4a93afc483ec", + "feature/aviator/openstack/volume/v1/public/delete_volume.rb": "ebbcd8a8e470259cabed51fe41a03249", + "feature/aviator/openstack/volume/v1/public/get_volume.rb": "9a977461b76e1846e256d41bc5636c92", + "feature/aviator/openstack/volume/v1/public/list_volume_types.rb": "4338eb77f2e6df58a57fcd6cf22491cd", + "feature/aviator/openstack/volume/v1/public/list_volumes.rb": "2930615edc76b89b9e5888ca58d4ddd7", + "feature/aviator/openstack/volume/v1/public/root.rb": "fd7f423b9080b158b341530ff37b868e", + "feature/aviator/openstack/volume/v1/public/update_volume.rb": "67b9d740d4477d2d1cb22fa931f91458", + "feature/aviator/string.rb": "3c412951f02b4268890b599125174360", + "feature/aviator/version.rb": "10852d0b210481f820997ca1948953ab", + "feature/aviator.rb": "3ce701ef95c1be09eb46bcc12eeaac32", + "feature/composite_io.rb": "7578e6fc78d81b363658d0c047ef7355", + "feature/faraday/adapter/em_http.rb": "2b62006966ab41b68ba4b22f7499c6e7", + "feature/faraday/adapter/em_http_ssl_patch.rb": "353bac212b9c67a415cad9c2d0a33a1f", + "feature/faraday/adapter/em_synchrony/parallel_manager.rb": "ed23bb89721bfcc7be531d8a7fa1d75a", + "feature/faraday/adapter/em_synchrony.rb": "4d9eb3f1ca759f7008c4cd51ad055ddc", + "feature/faraday/adapter/excon.rb": "4d1bcdeeeb3623c5f5847350420102cb", + "feature/faraday/adapter/httpclient.rb": "cffdad2f5f9f109fb62ace392fabbcf1", + "feature/faraday/adapter/net_http.rb": "98ca2bafc840b0049e12448c12f7d9f6", + "feature/faraday/adapter/net_http_persistent.rb": "1d8cbd07de4b3464ed42774728d866d8", + "feature/faraday/adapter/patron.rb": "771a78d359202538a062b6e1de186b62", + "feature/faraday/adapter/rack.rb": "70078f81411a4294bd20302f9a857120", + "feature/faraday/adapter/test.rb": "e3177c396bb40d922e8aee81c745b173", + "feature/faraday/adapter/typhoeus.rb": "2bb446cc26a8fce211a92670838e977c", + "feature/faraday/adapter.rb": "c8e0aacec14e78a9d1b73bc674c147d7", + "feature/faraday/autoload.rb": "c3825f673dcd897eccbbf0204b290342", + "feature/faraday/connection.rb": "0ffff1f6f1996dbb7643c87e5acc482d", + "feature/faraday/error.rb": "a5900e607b1573bb6b6549e6573e2e90", + "feature/faraday/middleware.rb": "da7f0af70a005cabe297f64f613e04f5", + "feature/faraday/options.rb": "d92eea6cceda8cd61a984893ba5cc25c", + "feature/faraday/parameters.rb": "162fbb7a45756695909c49e099d6b412", + "feature/faraday/rack_builder.rb": "e1a93cd64e1d555530b6aa31b5b7812c", + "feature/faraday/request/authorization.rb": "a2aa3b3b22fa39e4f1fc6c87008a5e50", + "feature/faraday/request/basic_authentication.rb": "3da9b3b931d19e9669c3b32841ececfd", + "feature/faraday/request/instrumentation.rb": "c48435dbd1ba855f71c4f538baa7b665", + "feature/faraday/request/multipart.rb": "dcc172d9443f53d28d06cba93de2cd7b", + "feature/faraday/request/retry.rb": "57892cf880e6db7486daf8e015e9418a", + "feature/faraday/request/token_authentication.rb": "aedd602972c21fccb6b672d8caaa77ac", + "feature/faraday/request/url_encoded.rb": "7d8715e5cea35a1d3416a174e1fb492e", + "feature/faraday/request.rb": "0d5064fe1ae944b7aa21a111ccfbaf4d", + "feature/faraday/response/logger.rb": "0d4a6a3809bb3612715faf2b862ed147", + "feature/faraday/response/raise_error.rb": "8544053fd9007b42885793222f917b26", + "feature/faraday/response.rb": "6423348722701307e11f261b4ca09af8", + "feature/faraday/upload_io.rb": "7b0b80bc2cbbfca411a867d621f7b497", + "feature/faraday/utils.rb": "4df493a45499dbca0770f613da3d7bf6", + "feature/faraday.rb": "61f81f20888a0a1c992c0b108c96019d", + "feature/multipart_post.rb": "3433edf755f20e56edf3c167492a8a0f", + "feature/multipartable.rb": "5465ba7b40057b35eccf93bd1e50180d", + "feature/net/http/post/multipart.rb": "469d05036cd0b981b201d0fe50360f5b", + "feature/parts.rb": "c6a86930e784e4ab7d8d022b6f64e636", + "lib/puppet/feature/aviator/core/cli/describer.rb": "6cadcef2c8c51b5665243f090151afc6", + "lib/puppet/feature/aviator/core/cli.rb": "4fe815c3d85859dd6a9893a5aa38c7f8", + "lib/puppet/feature/aviator/core/logger.rb": "99aa5ef113f491a563fdf8ecf6a44db2", + "lib/puppet/feature/aviator/core/request.rb": "2477263dfc7b32751906c39448600838", + "lib/puppet/feature/aviator/core/request_builder.rb": "1705d21fb6db847d6521f643047f8675", + "lib/puppet/feature/aviator/core/response.rb": "2c6d777c3bf886a36e09855ec96d3911", + "lib/puppet/feature/aviator/core/service.rb": "3186cbe84f209286f03b8c8a347c38cb", + "lib/puppet/feature/aviator/core/session.rb": "a82ca88a3f76379184481e9d9d88bb5c", + "lib/puppet/feature/aviator/core/utils/compatibility.rb": "d103a261221e127c48ae8db01623cbb7", + "lib/puppet/feature/aviator/core/utils/hashish.rb": "3e54d1cdb0b25379c4adb73057072fbb", + "lib/puppet/feature/aviator/core/utils/string.rb": "3b1939aab12529f545b8a10ab27c0e05", + "lib/puppet/feature/aviator/core.rb": "8fd9c5413074f0de2aa5c5860abbbef8", + "lib/puppet/feature/aviator/openstack/common/requests/v0/public/base.rb": "c9690b0fa25efdcdbf6184a740a84fa3", + "lib/puppet/feature/aviator/openstack/common/requests/v2/admin/base.rb": "8e88c76b3aa87bf3f69772bc5a7b4cfa", + "lib/puppet/feature/aviator/openstack/common/requests/v2/public/base.rb": "4766de221d8e84c07e5bc997f4b4bda5", + "lib/puppet/feature/aviator/openstack/common/requests/v3/public/base.rb": "ac958d139dc2eff20ec08e591109bb42", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/confirm_server_resize.rb": "d7c43043c66a862d5232e999254c8f1a", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/create_network.rb": "b11ff615a495b3189ff18d2fdd580340", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/get_host_details.rb": "4e0200122c40d2acd95ca29ffb1a648f", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/list_hosts.rb": "25448fc1b14189d0d6aa6562c25d2172", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/list_hypervisors.rb": "d531290063e073bc72a0f508e5946989", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/lock_server.rb": "ff124f629375a069d0a39674a835669d", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/migrate_server.rb": "9b27fe512de6592e28e8ae534ef4e227", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/reset_server.rb": "83ceb5bde8297f40637901107c0779ce", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/resize_server.rb": "38d073f289de8cbcd54326dfcceb1203", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/revert_server_resize.rb": "ec60b35f97bb6de54d06ae53ab0a48f3", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/unlock_server.rb": "844f5380140805475c7a44d964960558", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/add_floating_ip.rb": "5ce446270f6216b19922f62a63e983bc", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/allocate_floating_ip.rb": "be0c5b2e87a7bf8d29b5997240aca6e5", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/change_admin_password.rb": "e5ed804402e4c969de89f669bbdbed52", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/create_image.rb": "605c7f1dccc0e25f75a22b8133e0ac1c", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/create_keypair.rb": "626715aa5a067328afa056229ee6bc96", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/create_server.rb": "b58dc498308a031f23c8ba2d6cf49293", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/delete_image.rb": "fb0f14aa4d3cd80e0b32ebcd0d32b62b", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/delete_image_metadata_item.rb": "8f24549420f5b2ec73d245d84364f6a1", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/delete_server.rb": "89fca14a34d08483992b03e0b3256e24", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/delete_server_metadata_item.rb": "1caa8f632ee0e7964d0774f8fcdde5f8", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_flavor_details.rb": "335012feb1abc4a0c0bfd57e09dd906f", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_image_details.rb": "779845403f9314ddbda05121b54cd428", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_image_metadata_item.rb": "cdc2caa68f52f33f5944770cb0594623", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_network_details.rb": "43f08bb5513fd78f5685f065111a89e7", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_server.rb": "9b764bb9b93cf368b7bec8ed70654490", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_server_metadata_item.rb": "7e6a0feca6e6e2afc89e8b8cf00e6493", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_addresses.rb": "ff343fead191c3d13677448daee3822c", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_flavors.rb": "7050181d84ada85de9a3cfe476040432", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_floating_ips.rb": "c967d5705e55c1840f1ff18d8b198936", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_image_metadata.rb": "36cc324f2f8ec4e12a7f47846099aaa1", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_images.rb": "9dcace5a72ef644072ede3bdcdf031ed", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_keypairs.rb": "7f2fc592742874b8a9cd05bd67eb8fad", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_networks.rb": "5639d0a86c7b37a0ba957f9cdb5a83ab", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_server_metadata.rb": "5815bd0f48e81dea65c13bb0bb4c944e", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_servers.rb": "deaf400faab4a9c0dd632be988fa002b", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/pause_server.rb": "e2ac1913b925f61707516103d5c204cf", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/reboot_server.rb": "73a34c9cf36b087e167e4d5a0a0b9762", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/rebuild_server.rb": "907eee7ab63f3c8c3c93c9cc522aa208", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/resume_server.rb": "f24ef2b6d7e4be1664d89a5d1bd76c2f", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/root.rb": "cee3dd2aff0710d0f5fccc23508a7f58", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/set_image_metadata.rb": "e49c35f9b95a268803578549ffce5cc0", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/set_server_metadata.rb": "ece9d9a873ef6a3e468ae7285cd335f1", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/suspend_server.rb": "a9fe5dc5c43dbb9da293de1eecd440a4", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/unpause_server.rb": "9075ce7b123abce8917371fc545bbf92", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/update_image_metadata.rb": "453dc71ce53a784322460afe8f8a0ffd", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/update_server.rb": "19bab4a3b3b5fc8af215c53f3582f0cc", + "lib/puppet/feature/aviator/openstack/compute/requests/v2/public/update_server_metadata.rb": "72107bf121c284fb859e1d0d544c9f8c", + "lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/add_role_to_user_on_tenant.rb": "d5962f765a8e2091aa0d7feab0f860b6", + "lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/create_tenant.rb": "eb5b538285459bbc70da43ecb10a2ae1", + "lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/create_user.rb": "817e3936db1e0a000014b0464a64a8ea", + "lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/delete_role_from_user_on_tenant.rb": "82e5b5520e9e10e8dba716b2e852cad9", + "lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/delete_tenant.rb": "ad0bd04e86d4025a462ef6094313db63", + "lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/delete_user.rb": "1a727d8adc5d4a1753acd7224f77e505", + "lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/get_tenant_by_id.rb": "0c93905f14e07e67f709739dd763d6e1", + "lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/get_user.rb": "3fb7869597c8f68adb91fefe5d0c0791", + "lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/list_tenants.rb": "e75b66b966e49f045b7c61789ffd5b5e", + "lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/list_users.rb": "058de058e0a98e2a7549a52e384b5807", + "lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/update_tenant.rb": "ff218d457b3ddce85168a85e98014c51", + "lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/update_user.rb": "47e295d5f138acda2bcb8b6a5ee1f87d", + "lib/puppet/feature/aviator/openstack/identity/requests/v2/public/create_token.rb": "2e44dafa7758d4610a5c06d54fc53ffa", + "lib/puppet/feature/aviator/openstack/identity/requests/v2/public/list_tenants.rb": "826d93b39fba2b8e85c4c9979f363afd", + "lib/puppet/feature/aviator/openstack/identity/requests/v2/public/root.rb": "49c81b24643287440458224c9eabc350", + "lib/puppet/feature/aviator/openstack/identity/requests/v3/public/create_token.rb": "c092532638e57c55c38eaae925e41b71", + "lib/puppet/feature/aviator/openstack/image/requests/v1/public/list_public_images.rb": "746ac90e4d5099a64ad08f4cc3829d97", + "lib/puppet/feature/aviator/openstack/image/requests/v1/public/root.rb": "b3b0897ea44361584961832fedf8f2ce", + "lib/puppet/feature/aviator/openstack/metering/requests/v1/admin/list_projects.rb": "22fc778d98d8424efcd14fa64e023c91", + "lib/puppet/feature/aviator/openstack/provider.rb": "e9ba93565ad683778c5901f30ab9fead", + "lib/puppet/feature/aviator/openstack/volume/requests/v1/public/create_volume.rb": "b0118b8f421376da64eb4a93afc483ec", + "lib/puppet/feature/aviator/openstack/volume/requests/v1/public/delete_volume.rb": "ebbcd8a8e470259cabed51fe41a03249", + "lib/puppet/feature/aviator/openstack/volume/requests/v1/public/get_volume.rb": "9a977461b76e1846e256d41bc5636c92", + "lib/puppet/feature/aviator/openstack/volume/requests/v1/public/list_volume_types.rb": "4338eb77f2e6df58a57fcd6cf22491cd", + "lib/puppet/feature/aviator/openstack/volume/requests/v1/public/list_volumes.rb": "2930615edc76b89b9e5888ca58d4ddd7", + "lib/puppet/feature/aviator/openstack/volume/requests/v1/public/root.rb": "fd7f423b9080b158b341530ff37b868e", + "lib/puppet/feature/aviator/openstack/volume/requests/v1/public/update_volume.rb": "67b9d740d4477d2d1cb22fa931f91458", + "lib/puppet/feature/aviator/version.rb": "7dacc5a489888d3bbb3e29d0d3fd0857", + "lib/puppet/feature/aviator.rb": "2bfe991671863c6b9f66fefb45edd586", + "lib/puppet/feature/composite_io.rb": "7578e6fc78d81b363658d0c047ef7355", + "lib/puppet/feature/faraday/adapter/em_http.rb": "2b62006966ab41b68ba4b22f7499c6e7", + "lib/puppet/feature/faraday/adapter/em_http_ssl_patch.rb": "353bac212b9c67a415cad9c2d0a33a1f", + "lib/puppet/feature/faraday/adapter/em_synchrony/parallel_manager.rb": "ed23bb89721bfcc7be531d8a7fa1d75a", + "lib/puppet/feature/faraday/adapter/em_synchrony.rb": "4d9eb3f1ca759f7008c4cd51ad055ddc", + "lib/puppet/feature/faraday/adapter/excon.rb": "4d1bcdeeeb3623c5f5847350420102cb", + "lib/puppet/feature/faraday/adapter/httpclient.rb": "cffdad2f5f9f109fb62ace392fabbcf1", + "lib/puppet/feature/faraday/adapter/net_http.rb": "98ca2bafc840b0049e12448c12f7d9f6", + "lib/puppet/feature/faraday/adapter/net_http_persistent.rb": "1d8cbd07de4b3464ed42774728d866d8", + "lib/puppet/feature/faraday/adapter/patron.rb": "771a78d359202538a062b6e1de186b62", + "lib/puppet/feature/faraday/adapter/rack.rb": "70078f81411a4294bd20302f9a857120", + "lib/puppet/feature/faraday/adapter/test.rb": "e3177c396bb40d922e8aee81c745b173", + "lib/puppet/feature/faraday/adapter/typhoeus.rb": "2bb446cc26a8fce211a92670838e977c", + "lib/puppet/feature/faraday/adapter.rb": "c8e0aacec14e78a9d1b73bc674c147d7", + "lib/puppet/feature/faraday/autoload.rb": "c3825f673dcd897eccbbf0204b290342", + "lib/puppet/feature/faraday/connection.rb": "0ffff1f6f1996dbb7643c87e5acc482d", + "lib/puppet/feature/faraday/error.rb": "a5900e607b1573bb6b6549e6573e2e90", + "lib/puppet/feature/faraday/middleware.rb": "da7f0af70a005cabe297f64f613e04f5", + "lib/puppet/feature/faraday/options.rb": "d92eea6cceda8cd61a984893ba5cc25c", + "lib/puppet/feature/faraday/parameters.rb": "162fbb7a45756695909c49e099d6b412", + "lib/puppet/feature/faraday/rack_builder.rb": "e1a93cd64e1d555530b6aa31b5b7812c", + "lib/puppet/feature/faraday/request/authorization.rb": "a2aa3b3b22fa39e4f1fc6c87008a5e50", + "lib/puppet/feature/faraday/request/basic_authentication.rb": "3da9b3b931d19e9669c3b32841ececfd", + "lib/puppet/feature/faraday/request/instrumentation.rb": "c48435dbd1ba855f71c4f538baa7b665", + "lib/puppet/feature/faraday/request/multipart.rb": "dcc172d9443f53d28d06cba93de2cd7b", + "lib/puppet/feature/faraday/request/retry.rb": "57892cf880e6db7486daf8e015e9418a", + "lib/puppet/feature/faraday/request/token_authentication.rb": "aedd602972c21fccb6b672d8caaa77ac", + "lib/puppet/feature/faraday/request/url_encoded.rb": "7d8715e5cea35a1d3416a174e1fb492e", + "lib/puppet/feature/faraday/request.rb": "0d5064fe1ae944b7aa21a111ccfbaf4d", + "lib/puppet/feature/faraday/response/logger.rb": "0d4a6a3809bb3612715faf2b862ed147", + "lib/puppet/feature/faraday/response/raise_error.rb": "8544053fd9007b42885793222f917b26", + "lib/puppet/feature/faraday/response.rb": "6423348722701307e11f261b4ca09af8", + "lib/puppet/feature/faraday/upload_io.rb": "7b0b80bc2cbbfca411a867d621f7b497", + "lib/puppet/feature/faraday/utils.rb": "4df493a45499dbca0770f613da3d7bf6", + "lib/puppet/feature/faraday.rb": "61f81f20888a0a1c992c0b108c96019d", + "lib/puppet/feature/multipart_post.rb": "3433edf755f20e56edf3c167492a8a0f", + "lib/puppet/feature/multipartable.rb": "5465ba7b40057b35eccf93bd1e50180d", + "lib/puppet/feature/net/http/post/multipart.rb": "469d05036cd0b981b201d0fe50360f5b", + "lib/puppet/feature/parts.rb": "c6a86930e784e4ab7d8d022b6f64e636" +} \ No newline at end of file diff --git a/3rdparty/modules/aviator/feature/aviator.rb b/3rdparty/modules/aviator/feature/aviator.rb new file mode 100644 index 000000000..3543aac60 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator.rb @@ -0,0 +1,6 @@ +# Add the parent dir to the load path. This is for when +# Aviator is not installed as a gem +lib_path = File.dirname(__FILE__) +$LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include? lib_path + +require 'aviator/core' diff --git a/3rdparty/modules/aviator/feature/aviator/compatibility.rb b/3rdparty/modules/aviator/feature/aviator/compatibility.rb new file mode 100644 index 000000000..560fc2b70 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/compatibility.rb @@ -0,0 +1,34 @@ +module Aviator + + module Compatibility + RUBY_1_8_MODE = (not (RUBY_VERSION =~ /1\.8\.\d*/).nil?) + end + +end + +if Aviator::Compatibility::RUBY_1_8_MODE + + class Module + + alias_method :old_const_defined?, :const_defined? + + def const_defined?(sym, ignore=nil) + old_const_defined?(sym) + end + + + alias_method :old_const_get, :const_get + + def const_get(sym, ignore=nil) + old_const_get(sym) + end + + alias_method :old_instance_methods, :instance_methods + + def instance_methods(include_super=true) + old_instance_methods(include_super).map(&:to_sym) + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/core.rb b/3rdparty/modules/aviator/feature/aviator/core.rb new file mode 100644 index 000000000..eb94adeeb --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/core.rb @@ -0,0 +1,14 @@ +require 'yaml' +require 'json' +require 'faraday' + +require "aviator/string" +require "aviator/version" +require "aviator/compatibility" +require "aviator/hashish" +require "aviator/core/request" +require "aviator/core/request_builder" +require "aviator/core/response" +require "aviator/core/service" +require "aviator/core/session" +require "aviator/core/logger" diff --git a/3rdparty/modules/aviator/feature/aviator/core/cli.rb b/3rdparty/modules/aviator/feature/aviator/core/cli.rb new file mode 100644 index 000000000..cd937d0e7 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/core/cli.rb @@ -0,0 +1,2 @@ +require "terminal-table" +require "aviator/core/cli/describer" diff --git a/3rdparty/modules/aviator/feature/aviator/core/cli/describer.rb b/3rdparty/modules/aviator/feature/aviator/core/cli/describer.rb new file mode 100644 index 000000000..b7426c310 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/core/cli/describer.rb @@ -0,0 +1,146 @@ +module Aviator + + class Describer + + def self.describe_aviator + str = "Available providers:\n" + + provider_names.each do |provider_name| + str << " #{ provider_name }\n" + end + + str + end + + + def self.describe_provider(provider_name) + str = "Available services for #{ provider_name }:\n" + + service_names(provider_name).each do |service_name| + str << " #{ service_name }\n" + end + + str + end + + + def self.describe_request(provider_name, service_name, api_version, endpoint_type, request_name) + service = Aviator::Service.new :provider => provider_name, :service => service_name + request_class = "Aviator::#{ provider_name.camelize }::#{ service_name.camelize }::"\ + "#{ api_version.camelize }::#{ endpoint_type.camelize }::#{ request_name.camelize }".constantize + + display = ":Request => #{ request_name }\n" + + + # Build the parameters + params = request_class.optional_params.map{|p| [p, false]} + + request_class.required_params.map{|p| [p, true]} + + aliases = request_class.param_aliases + + if params.length > 0 + display << "\n" + + headings = ['NAME', 'REQUIRED?'] + + headings << 'ALIAS' if aliases.length > 0 + + rows = [] + params.sort{|a,b| a[0].to_s <=> b[0].to_s }.each do |param| + row = [ param[0], param[1] ? 'Y' : 'N' ] + + if aliases.length > 0 + row << (aliases.find{|a,p| p == param[0] } || [''])[0] + end + + rows << row + end + + widths = [ + rows.map{|row| row[0].to_s.length }.max, + rows.map{|row| row[1].to_s.length }.max + ] + + widths << rows.map{|row| row[2].to_s.length }.max if aliases.length > 0 + + table = Terminal::Table.new(:headings => headings, :rows => rows) + + table.align_column(1, :center) + + display << "Parameters:\n" + display << " " + table.to_s.split("\n").join("\n ") + display << "\n" + end + + + # Build the sample code + display << "\nSample Code:\n" + + display << " session.#{ service_name }_service.request(:#{ request_name })" + + if params && params.length > 0 + display << " do |params|\n" + params.each do |pair| + display << " params.#{ (aliases.find{|a,p| p == pair[0] } || pair)[0] } = value\n" + end + display << " end" + end + + display << "\n" + + + # Build the links + if request_class.links && request_class.links.length > 0 + display << "\nLinks:\n" + + request_class.links.each do |link| + display << " #{ link[:rel] }:\n" + display << " #{ link[:href] }\n" + end + end + + display + end + + + def self.describe_service(provider_name, service_name) + str = "Available requests for #{ provider_name } #{ service_name }_service:\n" + + request_classes(provider_name, service_name).each do |klass| + str << " #{ klass.api_version } #{ klass.endpoint_type } #{ klass.name.split('::').last.underscore }\n" + end + + str + end + + + class < provider_name, :service => service_name) + service.request_classes + end + + + def service_names(provider_name) + Pathname.new(__FILE__) \ + .join('..', '..', '..', provider_name) \ + .children \ + .select{|c| c.directory? } \ + .map{|c| c.basename.to_s } + end + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/core/logger.rb b/3rdparty/modules/aviator/feature/aviator/core/logger.rb new file mode 100644 index 000000000..bbb537d7f --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/core/logger.rb @@ -0,0 +1,55 @@ +module Aviator + + class Logger < Faraday::Response::Middleware + extend Forwardable + + def initialize(app, logger=nil) + super(app) + @logger = logger || begin + require 'logger' + ::Logger.new(self.class::LOG_FILE_PATH) + end + end + + + def_delegators :@logger, :debug, :info, :warn, :error, :fatal + + + def call(env) + info(env[:method].to_s.upcase) { env[:url].to_s } + debug('REQ_HEAD') { dump_headers env[:request_headers] } + debug('REQ_BODY') { dump_body env[:body] } + super + end + + + def on_complete(env) + info('STATUS') { env[:status].to_s } + debug('RES_HEAD') { dump_headers env[:response_headers] } + debug('RES_BODY') { dump_body env[:body] } + end + + + def self.configure(log_file_path) + # Return a subclass with its logfile path set. This + # must be done so that different sessions can log to + # different paths. + Class.new(self) { const_set('LOG_FILE_PATH', log_file_path) } + end + + + private + + def dump_body(body) + return if body.nil? + + # :TODO => Make this configurable + body.gsub(/["']password["']:["']\w*["']/, '"password":[FILTERED_VALUE]') + end + + def dump_headers(headers) + headers.map { |k, v| "#{k}: #{v.inspect}" }.join("; ") + end + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/core/request.rb b/3rdparty/modules/aviator/feature/aviator/core/request.rb new file mode 100644 index 000000000..ed9c6cef1 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/core/request.rb @@ -0,0 +1,229 @@ +module Aviator + + class Request + + class ApiVersionNotDefinedError < StandardError + def initialize + super "api_version is not defined." + end + end + + class EndpointTypeNotDefinedError < StandardError + def initialize + super "endpoint_type is not defined." + end + end + + class PathNotDefinedError < StandardError + def initialize + super "path is not defined." + end + end + + + def initialize(session_data=nil) + @session_data = session_data + + params = self.class.params_class.new if self.class.params_class + + if params + yield(params) if block_given? + validate_params(params) + end + + @params = params + end + + + def anonymous? + self.class.anonymous? + end + + + def body? + self.class.body? + end + + + def headers? + self.class.headers? + end + + + def links + self.class.links + end + + + def optional_params + self.class.optional_params + end + + + def params + @params.dup + end + + + def required_params + self.class.required_params + end + + + def session_data + @session_data + end + + + def session_data? + !session_data.nil? + end + + + def querystring? + self.class.querystring? + end + + + def url? + self.class.url? + end + + + private + + + def validate_params(params) + required_params = self.class.required_params + + required_params.each do |name| + raise ArgumentError.new("Missing parameter #{ name }.") if params.send(name).nil? + end + end + + + # NOTE that, because we are defining the following as class methods, when they + # are called, all 'instance' variables are actually defined in the descendant class, + # not in the instance/object. This is by design since we want to keep these attributes + # within the class and because they don't change between instances anyway. + class << self + + def anonymous? + respond_to?(:anonymous) && anonymous == true + end + + + def body? + instance_methods.include? :body + end + + + def headers? + instance_methods.include? :headers + end + + + def links + @links ||= [] + end + + + def param_aliases + @param_aliases ||= {} + end + + + def params_class + all_params = required_params + optional_params + + if all_params.length > 0 && @params_class.nil? + @params_class = build_params_class(all_params, self.param_aliases) + end + + @params_class + end + + + def optional_params + @optional_params ||= [] + end + + + def querystring? + instance_methods.include? :querystring + end + + + def required_params + @required_params ||= [] + end + + + def url? + instance_methods.include? :url + end + + + private + + + def build_params_class(all_params, param_aliases) + Struct.new(*all_params) do + alias :param_getter :[] + alias :param_setter :[]= + + define_method :[] do |key| + key = param_aliases[key.to_sym] if param_aliases.keys.include? key.to_sym + param_getter(key) + end + + define_method :[]= do |key, value| + key = param_aliases[key.to_sym] if param_aliases.keys.include? key.to_sym + param_setter(key, value) + end + + param_aliases.each do |param_alias, param_name| + define_method param_alias do + param_getter(param_name) + end + + define_method "#{ param_alias }=" do |value| + param_setter(param_name, value) + end + end + end + end + + + def link(rel, href) + links << { :rel => rel, :href => href } + end + + + def meta(attr_name, attr_value) + eigenclass = class << self; self; end + eigenclass.send(:define_method, attr_name) do + attr_value + end + + define_method(attr_name) do + self.class.send(attr_name) + end + end + + + def param(param_name, opts={}) + opts = Hashish.new(opts) + list = (opts[:required] == false ? optional_params : required_params) + list << param_name unless optional_params.include?(param_name) + + if opts[:alias] + self.param_aliases[opts[:alias]] = param_name + end + end + + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/core/request_builder.rb b/3rdparty/modules/aviator/feature/aviator/core/request_builder.rb new file mode 100644 index 000000000..249cf1699 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/core/request_builder.rb @@ -0,0 +1,89 @@ +module Aviator + + class BaseRequestNotFoundError < StandardError + attr_reader :base_request_hierarchy + + def initialize(base_hierarchy) + @base_request_hierarchy = base_hierarchy + super("#{ base_request_hierarchy } could not be found!") + end + end + + + class RequestAlreadyDefinedError < StandardError + attr_reader :namespace, + :request_name + + def initialize(namespace, request_name) + @namespace = namespace + @request_name = request_name + super("#{ namespace }::#{ request_name } is already defined") + end + end + + + class RequestBuilder + + class << self + + def define_request(root_namespace, request_name, options, &block) + base_klass = get_request_class(root_namespace, options[:inherit]) + + klass = Class.new(base_klass, &block) + + namespace_arr = [ + klass.provider, + klass.service, + klass.api_version, + klass.endpoint_type + ] + + namespace = namespace_arr.inject(root_namespace) do |namespace, sym| + const_name = sym.to_s.camelize + namespace.const_set(const_name, Module.new) unless namespace.const_defined?(const_name, false) + namespace.const_get(const_name, false) + end + + klassname = request_name.to_s.camelize + + if namespace.const_defined?(klassname, false) + raise RequestAlreadyDefinedError.new(namespace, klassname) + end + + namespace.const_set(klassname, klass) + end + + + def get_request_class(root_namespace, request_class_arr) + request_class_arr.inject(root_namespace) do |namespace, sym| + namespace.const_get(sym.to_s.camelize, false) + end + rescue NameError => e + arr = ['..', '..'] + request_class_arr + arr[-1,1] = arr.last.to_s + '.rb' + path = Pathname.new(__FILE__).join(*arr.map{|i| i.to_s }).expand_path + + if path.exist? + require path + request_class_arr.inject(root_namespace) do |namespace, sym| + namespace.const_get(sym.to_s.camelize, false) + end + else + raise BaseRequestNotFoundError.new(request_class_arr) + end + end + + end + + end + + + class << self + + def define_request(request_name, options={ :inherit => [:request] }, &block) + RequestBuilder.define_request self, request_name, options, &block + end + + end # class << self + +end \ No newline at end of file diff --git a/3rdparty/modules/aviator/feature/aviator/core/response.rb b/3rdparty/modules/aviator/feature/aviator/core/response.rb new file mode 100644 index 000000000..8fa63c1d6 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/core/response.rb @@ -0,0 +1,39 @@ +module Aviator + + class Response + extend Forwardable + + def_delegators :@response, :headers, :status + + attr_reader :request + + def initialize(response, request) + @response = response + @request = request + end + + + def body + if raw_body.length > 0 + if Aviator::Compatibility::RUBY_1_8_MODE + clean_body = raw_body.gsub(/\\ /, ' ') + else + clean_body = raw_body + end + + Hashish.new(JSON.parse(clean_body)) + else + Hashish.new({}) + end + end + + + private + + def raw_body + @response.body + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/core/service.rb b/3rdparty/modules/aviator/feature/aviator/core/service.rb new file mode 100644 index 000000000..96a4b464d --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/core/service.rb @@ -0,0 +1,197 @@ +module Aviator + + class Service + + class AccessDetailsNotDefinedError < StandardError + def initialize + super ":access_details is not defined." + end + end + + class ProviderNotDefinedError < StandardError + def initialize + super ":provider is not defined." + end + end + + class ServiceNameNotDefinedError < StandardError + def initialize + super ":service is not defined." + end + end + + class SessionDataNotProvidedError < StandardError + def initialize + super "default_session_data is not initialized and no session data was "\ + "provided in the method call." + end + end + + + class UnknownRequestError < StandardError + def initialize(request_name) + super "Unknown request #{ request_name }." + end + end + + + class MissingServiceEndpointError < StandardError + def initialize(service_name, request_name) + request_name = request_name.to_s.split('::').last.underscore + super "The session's service catalog does not have an entry for the #{ service_name } "\ + "service. Therefore, I don't know to which base URL the request should be sent. "\ + "This may be because you are using a default or unscoped token. If this is not your "\ + "intention, please authenticate with a scoped token. If using a default token is your "\ + "intention, make sure to provide a base url when you call the request. For :example => \n\n"\ + "session.#{ service_name }_service.request :#{ request_name }, :base_url => 'http://myenv.com:9999/v2.0' do |params|\n"\ + " params[:example1] = 'example1'\n"\ + " params[:example2] = 'example2'\n"\ + "end\n\n" + end + end + + attr_accessor :default_session_data + + attr_reader :service, + :provider + + + def initialize(opts={}) + @provider = opts[:provider] || (raise ProviderNotDefinedError.new) + @service = opts[:service] || (raise ServiceNameNotDefinedError.new) + @log_file = opts[:log_file] + + @default_session_data = opts[:default_session_data] + + load_requests + end + + + def request(request_name, options={}, ¶ms) + session_data = options[:session_data] || default_session_data + + raise SessionDataNotProvidedError.new unless session_data + + [:base_url].each do |k| + session_data[k] = options[k] if options[k] + end + + request_class = find_request(request_name, session_data, options[:endpoint_type]) + + raise UnknownRequestError.new(request_name) unless request_class + + request = request_class.new(session_data, ¶ms) + + response = http_connection.send(request.http_method) do |r| + r.url request.url + r.headers.merge!(request.headers) if request.headers? + r.query = request.querystring if request.querystring? + r.body = JSON.generate(request.body) if request.body? + end + + Aviator::Response.send(:new, response, request) + end + + + def request_classes + @request_classes + end + + + private + + + def http_connection + @http_connection ||= Faraday.new do |conn| + conn.use Logger.configure(log_file) if log_file + conn.adapter Faraday.default_adapter + + conn.headers['Content-Type'] = 'application/json' + end + end + + + # Candidate for extraction to aviator/openstack + def find_request(name, session_data, endpoint_type=nil) + endpoint_types = if endpoint_type + [endpoint_type.to_s.camelize] + else + ['Public', 'Admin'] + end + + namespace = Aviator.const_get(provider.camelize) \ + .const_get(service.camelize) + + version = infer_version(session_data, name).to_s.camelize + + return nil unless version && namespace.const_defined?(version) + + namespace = namespace.const_get(version, name) + + endpoint_types.each do |endpoint_type| + name = name.to_s.camelize + + next unless namespace.const_defined?(endpoint_type) + next unless namespace.const_get(endpoint_type).const_defined?(name) + + return namespace.const_get(endpoint_type).const_get(name) + end + + nil + end + + + # Candidate for extraction to aviator/openstack + def infer_version(session_data, request_name='sample_request') + if session_data.has_key?(:auth_service) && session_data[:auth_service][:api_version] + session_data[:auth_service][:api_version].to_sym + + elsif session_data.has_key?(:auth_service) && session_data[:auth_service][:host_uri] + m = session_data[:auth_service][:host_uri].match(/(v\d+)\.?\d*/) + return m[1].to_sym unless m.nil? + + elsif session_data.has_key? :base_url + m = session_data[:base_url].match(/(v\d+)\.?\d*/) + return m[1].to_sym unless m.nil? + + elsif session_data.has_key? :access + service_spec = session_data[:access][:serviceCatalog].find{|s| s[:type] == service } + raise MissingServiceEndpointError.new(service.to_s, request_name) unless service_spec + version = service_spec[:endpoints][0][:publicURL].match(/(v\d+)\.?\d*/) + version ? version[1].to_sym : :v1 + end + end + + + def load_requests + # :TODO => This should be determined by a provider-specific module. + # e.g. Aviator::OpenStack::requests_base_dir + request_file_paths = Dir.glob(Pathname.new(__FILE__).join( + '..', + '..', + provider.to_s, + service.to_s, + '**', + '*.rb' + ).expand_path + ) + + request_file_paths.each{ |path| require path } + + constant_parts = request_file_paths \ + .map{|rf| rf.to_s.match(/#{provider}\/#{service}\/([\w\/]+)\.rb$/) } \ + .map{|rf| rf[1].split('/').map{|c| c.camelize }.join('::') } + + @request_classes = constant_parts.map do |cp| + "Aviator::#{provider.camelize}::#{service.camelize}::#{cp}".constantize + end + end + + + def log_file + @log_file + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/core/session.rb b/3rdparty/modules/aviator/feature/aviator/core/session.rb new file mode 100644 index 000000000..09ebcc731 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/core/session.rb @@ -0,0 +1,204 @@ +module Aviator + + class Session + + class AuthenticationError < StandardError + def initialize(last_auth_body) + super("Authentication failed. The server returned #{ last_auth_body }") + end + end + + + class EnvironmentNotDefinedError < ArgumentError + def initialize(path, env) + super("The environment '#{ env }' is not defined in #{ path }.") + end + end + + class InitializationError < StandardError + def initialize + super("The session could not find :session_dump, :config_file, and " \ + ":config in the constructor arguments provided") + end + end + + class InvalidConfigFilePathError < ArgumentError + def initialize(path) + super("The config file at #{ path } does not exist!") + end + end + + + class NotAuthenticatedError < StandardError + def initialize + super("Session is not authenticated. Please authenticate before proceeding.") + end + end + + + class ValidatorNotDefinedError < StandardError + def initialize + super("The validator request name is not defined for this session object.") + end + end + + + def initialize(opts={}) + if opts.has_key? :session_dump + initialize_with_dump(opts[:session_dump]) + elsif opts.has_key? :config_file + initialize_with_config(opts[:config_file], opts[:environment]) + elsif opts.has_key? :config + initialize_with_hash(opts[:config]) + else + raise InitializationError.new + end + + @log_file = opts[:log_file] + end + + + def authenticate(&block) + block ||= lambda do |params| + environment[:auth_credentials].each do |key, value| + params[key] = value + end + end + + response = auth_service.request environment[:auth_service][:request].to_sym, &block + + if response.status == 200 + @auth_info = response.body + update_services_session_data + else + raise AuthenticationError.new(response.body) + end + end + + + def authenticated? + !auth_info.nil? + end + + + def dump + JSON.generate({ + :environment => environment, + :auth_info => auth_info + }) + end + + + def load(session_dump) + initialize_with_dump(session_dump) + update_services_session_data + self + end + + + def method_missing(name, *args, &block) + service_name_parts = name.to_s.match(/^(\w+)_service$/) + + if service_name_parts + get_service_obj(service_name_parts[1]) + else + super name, *args, &block + end + end + + + def self.load(session_dump, opts={}) + opts[:session_dump] = session_dump + + new(opts) + end + + + def validate + raise NotAuthenticatedError.new unless authenticated? + raise ValidatorNotDefinedError.new unless environment[:auth_service][:validator] + + auth_with_bootstrap = auth_info.merge({ :auth_service => environment[:auth_service] }) + + response = auth_service.request environment[:auth_service][:validator].to_sym, :session_data => auth_with_bootstrap + + response.status == 200 || response.status == 203 + end + + + private + + + def auth_info + @auth_info + end + + + def auth_service + @auth_service ||= Service.new( + :provider => environment[:provider], + :service => environment[:auth_service][:name], + :default_session_data => { :auth_service => environment[:auth_service] }, + :log_file => log_file + ) + end + + + def environment + @environment + end + + + def get_service_obj(service_name) + raise NotAuthenticatedError.new unless self.authenticated? + + @services ||= {} + + @services[service_name] ||= Service.new( + :provider => environment[:provider], + :service => service_name, + :default_session_data => auth_info, + :log_file => log_file + ) + + @services[service_name] + end + + + def initialize_with_config(config_path, environment) + raise InvalidConfigFilePathError.new(config_path) unless Pathname.new(config_path).file? + + config = Hashish.new(YAML.load_file(config_path)) + + raise EnvironmentNotDefinedError.new(config_path, environment) unless config[environment] + + @environment = config[environment] + end + + + def initialize_with_dump(session_dump) + session_info = Hashish.new(JSON.parse(session_dump)) + @environment = session_info[:environment] + @auth_info = session_info[:auth_info] + end + + def initialize_with_hash(hash_obj) + @environment = Hashish.new(hash_obj) + end + + def log_file + @log_file + end + + + def update_services_session_data + return unless @services + + @services.each do |name, obj| + obj.default_session_data = auth_info + end + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/hashish.rb b/3rdparty/modules/aviator/feature/aviator/hashish.rb new file mode 100644 index 000000000..26025af48 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/hashish.rb @@ -0,0 +1,111 @@ +# Hash-ish! +# +# This class is implemented using composition rather than inheritance so +# that we have control over what operations it exposes to peers. +class Hashish + include Enumerable + + def initialize(hash={}) + @hash = hash + hashishify_values + end + + def ==(other_obj) + other_obj.class == self.class && + other_obj.hash == self.hash + end + + def [](key) + @hash[normalize(key)] + end + + def []=(key, value) + @hash[normalize(key)] = value + end + + def each(&block) + @hash.each(&block) + end + + def empty? + @hash.empty? + end + + def has_key?(name) + @hash.has_key? normalize(name) + end + + def hash + @hash + end + + def keys + @hash.keys + end + + def length + @hash.length + end + + def merge(other_hash) + Hashish.new(@hash.merge(other_hash)) + end + + def merge!(other_hash) + @hash.merge! other_hash + self + end + + def to_json(obj) + @hash.to_json(obj) + end + + def to_s + str = "{" + @hash.each do |key, value| + if value.kind_of? String + value = "'#{value}'" + elsif value.nil? + value = "nil" + elsif value.kind_of? Array + value = "[#{value.join(", ")}]" + end + + str += " #{key}: #{value}," + end + + str = str[0...-1] + " }" + str + end + + private + + # Hashishify all the things! + def hashishify_values + @hash.each do |key, value| + if @hash[key].kind_of? Hash + @hash[key] = Hashish.new(value) + elsif @hash[key].kind_of? Array + @hash[key].each_index do |index| + element = @hash[key][index] + if element.kind_of? Hash + @hash[key][index] = Hashish.new(element) + end + end + end + end + end + + def normalize(key) + if @hash.has_key? key + key + elsif key.is_a? String + key.to_sym + elsif key.is_a? Symbol + key.to_s + else + key + end + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/common/v2/admin/base.rb b/3rdparty/modules/aviator/feature/aviator/openstack/common/v2/admin/base.rb new file mode 100644 index 000000000..dd07d2f31 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/common/v2/admin/base.rb @@ -0,0 +1,9 @@ +module Aviator + + define_request :base, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :endpoint_type, :admin + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/common/v2/public/base.rb b/3rdparty/modules/aviator/feature/aviator/openstack/common/v2/public/base.rb new file mode 100644 index 000000000..7871a9f27 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/common/v2/public/base.rb @@ -0,0 +1,47 @@ +module Aviator + + define_request :base do + + meta :provider, :openstack + meta :service, :common + meta :api_version, :v2 + meta :endpoint_type, :public + + def headers + {}.tap do |h| + h['X-Auth-Token'] = session_data[:access][:token][:id] unless self.anonymous? + end + end + + + private + + + def base_url + if session_data[:base_url] + session_data[:base_url] + elsif service_spec = session_data[:access][:serviceCatalog].find { |s| s[:type] == service.to_s } + service_spec[:endpoints][0]["#{ endpoint_type }URL".to_sym] + elsif session_data[:auth_service] && session_data[:auth_service][:host_uri] && session_data[:auth_service][:api_version] + "#{ session_data[:auth_service][:host_uri] }/v2.0" + elsif session_data[:auth_service] && session_data[:auth_service][:host_uri] + session_data[:auth_service][:host_uri] + else + raise Aviator::Service::MissingServiceEndpointError.new(service.to_s, self.class) + end + end + + + def params_to_querystring(param_names) + filters = [] + + param_names.each do |param_name| + filters << "#{ param_name }=#{ params[param_name] }" if params[param_name] + end + + filters.empty? ? "" : "?#{ filters.join('&') }" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/confirm_server_resize.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/confirm_server_resize.rb new file mode 100644 index 000000000..0c672da8a --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/confirm_server_resize.rb @@ -0,0 +1,36 @@ +module Aviator + + define_request :confirm_server_resize, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Confirm_Resized_Server-d1e3868.html' + + param :id, :required => true + + + def body + { + :confirmResize => nil + } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/create_network.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/create_network.rb new file mode 100644 index 000000000..f45ef1a78 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/create_network.rb @@ -0,0 +1,56 @@ +module Aviator + + define_request :create_network, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :compute + + link 'documentation', + 'http://api.openstack.org/api-ref-compute.html#ext-os-networks' + + + param :label, :required => true + param :bridge, :required => false + param :bridge_interface, :required => false + param :cidr, :required => false + param :cidr_v6, :required => false + param :dns1, :required => false + param :dns2, :required => false + param :gateway, :required => false + param :gateway_v6, :required => false + param :multi_host, :required => false + param :project_id, :required => false + param :vlan, :required => false + + + def body + p = { + :network => { + :label => params[:label] + } + } + + optional_params.each do |key| + p[:network][key] = params[key] if params[key] + end + + p + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/os-networks" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/get_host_details.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/get_host_details.rb new file mode 100644 index 000000000..daf25a3cd --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/get_host_details.rb @@ -0,0 +1,29 @@ +module Aviator + + define_request :get_host_details, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :compute + + link 'documentation', + 'http://api.openstack.org/api-ref.html#ext-os-hosts' + + param :host_name, :required => true + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/os-hosts/#{ params[:host_name] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/list_hosts.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/list_hosts.rb new file mode 100644 index 000000000..8c47aa835 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/list_hosts.rb @@ -0,0 +1,44 @@ +module Aviator + + define_request :list_hosts, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :compute + + link 'documentation', + 'http://api.openstack.org/api-ref.html#ext-os-hosts' + + link 'documentation bug', + 'https://bugs.launchpad.net/nova/+bug/1224763' + + param :service, :required => false + param :zone, :required => false + + + def headers + super + end + + + def http_method + :get + end + + + def url + url = "#{ base_url }/os-hosts" + + filters = [] + + optional_params.each do |param_name| + filters << "#{ param_name }=#{ params[param_name] }" if params[param_name] + end + + url += "?#{ filters.join('&') }" unless filters.empty? + + url + end + + end + +end + diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/lock_server.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/lock_server.rb new file mode 100644 index 000000000..6db89fee2 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/lock_server.rb @@ -0,0 +1,34 @@ +module Aviator + + define_request :lock_server, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/POST_lock_v2__tenant_id__servers__server_id__action_ext-os-admin-actions.html' + + param :id, :required => true + + + def body + { :lock => nil } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/migrate_server.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/migrate_server.rb new file mode 100644 index 000000000..56259cdff --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/migrate_server.rb @@ -0,0 +1,34 @@ +module Aviator + + define_request :migrate_server, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/POST_migrate_v2__tenant_id__servers__server_id__action_ext-os-admin-actions.html' + + param :id, :required => true + + + def body + { :migrate => nil } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/reset_server.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/reset_server.rb new file mode 100644 index 000000000..ea8af1f0a --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/reset_server.rb @@ -0,0 +1,39 @@ +module Aviator + + define_request :reset_server, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/POST_os-resetState_v2__tenant_id__servers__server_id__action_ext-os-admin-actions.html' + + param :id, :required => true + param :state, :required => true + + + def body + { + 'os-resetState' => { + 'state' => params[:state] + } + } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/resize_server.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/resize_server.rb new file mode 100644 index 000000000..e4b6582a6 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/resize_server.rb @@ -0,0 +1,41 @@ +module Aviator + + define_request :resize_server, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Resize_Server-d1e3707.html' + + param :id, :required => true + param :name, :required => true + param :flavorRef, :required => true, :alias => :flavor_ref + + + def body + { + :resize => { + :name => params[:name], + :flavorRef => params[:flavorRef] + } + } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/revert_server_resize.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/revert_server_resize.rb new file mode 100644 index 000000000..6d8bec091 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/revert_server_resize.rb @@ -0,0 +1,46 @@ +module Aviator + + define_request :revert_server_resize do + + meta :provider, :openstack + meta :service, :compute + meta :api_version, :v2 + meta :endpoint_type, :admin + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Revert_Resized_Server-d1e4024.html' + + param :id, :required => true + + + def body + { + :revertResize => nil + } + end + + + def headers + h = {} + + unless self.anonymous? + h['X-Auth-Token'] = session_data[:access][:token][:id] + end + + h + end + + + def http_method + :post + end + + + def url + service_spec = session_data[:access][:serviceCatalog].find{|s| s[:type] == service.to_s } + "#{ service_spec[:endpoints][0][:adminURL] }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/unlock_server.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/unlock_server.rb new file mode 100644 index 000000000..eede63524 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/admin/unlock_server.rb @@ -0,0 +1,34 @@ +module Aviator + + define_request :unlock_server, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/POST_unlock_v2__tenant_id__servers__server_id__action_ext-os-admin-actions.html' + + param :id, :required => true + + + def body + { :unlock => nil } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/change_admin_password.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/change_admin_password.rb new file mode 100644 index 000000000..03aced50a --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/change_admin_password.rb @@ -0,0 +1,44 @@ +module Aviator + + define_request :change_admin_password, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Change_Password-d1e3234.html' + + link 'additional spec', + 'https://answers.launchpad.net/nova/+question/228462' + + param :adminPass, :required => true, :alias => :admin_pass + param :id, :required => true + + + def body + p = { + :changePassword => { + :adminPass => params[:adminPass] + } + } + + p + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/create_image.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/create_image.rb new file mode 100644 index 000000000..0a4622370 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/create_image.rb @@ -0,0 +1,46 @@ +module Aviator + + define_request :create_image, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Create_Image-d1e4655.html' + + param :id, :required => true + param :metadata, :required => false + param :name, :required => true + + + def body + p = { + :createImage => { + :name => params[:name] + } + } + + [:metadata].each do |key| + p[:createImage][key] = params[key] if params[key] + end + + p + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/create_server.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/create_server.rb new file mode 100644 index 000000000..b7666414c --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/create_server.rb @@ -0,0 +1,54 @@ +module Aviator + + define_request :create_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/CreateServers.html' + + param :accessIPv4, :required => false, :alias => :access_ipv4 + param :accessIPv6, :required => false, :alias => :access_ipv6 + param :adminPass, :required => false, :alias => :admin_pass + param :imageRef, :required => true, :alias => :image_ref + param :flavorRef, :required => true, :alias => :flavor_ref + param :metadata, :required => false + param :name, :required => true + param :networks, :required => false + param :personality, :required => false + + + def body + p = { + :server => { + :flavorRef => params[:flavorRef], + :imageRef => params[:imageRef], + :name => params[:name] + } + } + + [:adminPass, :metadata, :personality, :networks, :accessIPv4, :accessIPv6].each do |key| + p[:server][key] = params[key] if params[key] + end + + p + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/delete_image.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/delete_image.rb new file mode 100644 index 000000000..35ea8cf40 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/delete_image.rb @@ -0,0 +1,29 @@ +module Aviator + + define_request :delete_image, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Delete_Image-d1e4957.html' + + param :id, :required => true + + + def headers + super + end + + + def http_method + :delete + end + + + def url + "#{ base_url }/images/#{ params[:id]}" + end + + end + +end \ No newline at end of file diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/delete_image_metadata_item.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/delete_image_metadata_item.rb new file mode 100644 index 000000000..7b1fc3d70 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/delete_image_metadata_item.rb @@ -0,0 +1,31 @@ +module Aviator + + define_request :delete_image_metadata_item, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Delete_Metadata_Item-d1e5790.html' + + + param :id, :required => true + param :key, :required => true + + + def headers + super + end + + + def http_method + :delete + end + + + def url + "#{ base_url }/images/#{ params[:id] }/metadata/#{ params[:key] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/delete_server.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/delete_server.rb new file mode 100644 index 000000000..a991efb8e --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/delete_server.rb @@ -0,0 +1,29 @@ +module Aviator + + define_request :delete_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Delete_Server-d1e2883.html' + + param :id, :required => true + + + def headers + super + end + + + def http_method + :delete + end + + + def url + "#{ base_url }/servers/#{ params[:id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/delete_server_metadata_item.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/delete_server_metadata_item.rb new file mode 100644 index 000000000..facbbb537 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/delete_server_metadata_item.rb @@ -0,0 +1,31 @@ +module Aviator + + define_request :delete_server_metadata_item, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Delete_Metadata_Item-d1e5790.html' + + + param :id, :required => true + param :key, :required => true + + + def headers + super + end + + + def http_method + :delete + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/metadata/#{ params[:key] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/get_flavor_details.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/get_flavor_details.rb new file mode 100644 index 000000000..8faeb900e --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/get_flavor_details.rb @@ -0,0 +1,29 @@ +module Aviator + + define_request :get_flavor_details, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Get_Flavor_Details-d1e4317.html' + + param :id, :required => true + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/flavors/#{ params[:id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/get_image_details.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/get_image_details.rb new file mode 100644 index 000000000..b9fd3cce8 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/get_image_details.rb @@ -0,0 +1,29 @@ +module Aviator + + define_request :get_image_details, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Get_Image_Details-d1e4848.html' + + param :id, :required => true + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/images/#{ params[:id]}" + end + + end + +end \ No newline at end of file diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/get_image_metadata_item.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/get_image_metadata_item.rb new file mode 100644 index 000000000..01476744a --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/get_image_metadata_item.rb @@ -0,0 +1,31 @@ +module Aviator + + define_request :get_image_metadata_item, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Get_Metadata_Item-d1e5507.html' + + + param :id, :required => true + param :key, :required => true + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/images/#{ params[:id] }/metadata/#{ params[:key] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/get_network_details.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/get_network_details.rb new file mode 100644 index 000000000..8d4192bfe --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/get_network_details.rb @@ -0,0 +1,30 @@ +module Aviator + + define_request :get_network_details, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://api.openstack.org/api-ref-compute.html#ext-os-networks' + + + param :id, :required => true + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/os-networks/#{ params[:id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/get_server.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/get_server.rb new file mode 100644 index 000000000..e5c391106 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/get_server.rb @@ -0,0 +1,28 @@ +module Aviator + + define_request :get_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Get_Server_Details-d1e2623.html' + + param :id, :required => true + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/servers/#{ params[:id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/get_server_metadata_item.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/get_server_metadata_item.rb new file mode 100644 index 000000000..580320f24 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/get_server_metadata_item.rb @@ -0,0 +1,31 @@ +module Aviator + + define_request :get_server_metadata_item, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Get_Metadata_Item-d1e5507.html' + + + param :id, :required => true + param :key, :required => true + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/metadata/#{ params[:key] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_addresses.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_addresses.rb new file mode 100644 index 000000000..2c6fe60a4 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_addresses.rb @@ -0,0 +1,36 @@ +module Aviator + + define_request :list_addresses, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/List_Addresses-d1e3014.html' + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/List_Addresses_by_Network-d1e3118.html' + + + param :id, :required => true + param :networkID, :required => false, :alias => :network_id + + + def headers + super + end + + + def http_method + :get + end + + + def url + url = "#{ base_url }/servers/#{ params[:id] }/ips" + url += "/#{ params[:networkID] }" if params[:networkID] + url + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_flavors.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_flavors.rb new file mode 100644 index 000000000..9eba13626 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_flavors.rb @@ -0,0 +1,35 @@ +module Aviator + + define_request :list_flavors, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/List_Flavors-d1e4188.html' + + param :details, :required => false + param :minDisk, :required => false, :alias => :min_disk + param :minRam, :required => false, :alias => :min_ram + param :marker, :required => false + param :limit, :required => false + + + def headers + super + end + + + def http_method + :get + end + + + def url + str = "#{ base_url }/flavors" + str += "/detail" if params[:details] + str += params_to_querystring(optional_params + required_params - [:details]) + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_image_metadata.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_image_metadata.rb new file mode 100644 index 000000000..7b176891f --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_image_metadata.rb @@ -0,0 +1,30 @@ +module Aviator + + define_request :list_image_metadata, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/List_Metadata-d1e5089.html' + + + param :id, :required => true + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/images/#{ params[:id] }/metadata" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_images.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_images.rb new file mode 100644 index 000000000..b282aec97 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_images.rb @@ -0,0 +1,38 @@ +module Aviator + + define_request :list_images, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/List_Images-d1e4435.html' + + param :details, :required => false + param :server, :required => false + param :name, :required => false + param :status, :required => false + param 'changes-since', :required => false, :alias => :changes_since + param :marker, :required => false + param :limit, :required => false + param :type, :required => false + + + def headers + super + end + + + def http_method + :get + end + + + def url + str = "#{ base_url }/images" + str += "/detail" if params[:details] + str += params_to_querystring(optional_params + required_params - [:details]) + end + + end + +end \ No newline at end of file diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_networks.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_networks.rb new file mode 100644 index 000000000..472ab1bd0 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_networks.rb @@ -0,0 +1,27 @@ +module Aviator + + define_request :list_networks, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://api.openstack.org/api-ref-compute.html#ext-os-networks' + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/os-networks" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_server_metadata.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_server_metadata.rb new file mode 100644 index 000000000..d90936c1b --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_server_metadata.rb @@ -0,0 +1,30 @@ +module Aviator + + define_request :list_server_metadata, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/List_Metadata-d1e5089.html' + + + param :id, :required => true + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/metadata" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_servers.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_servers.rb new file mode 100644 index 000000000..f8126f0c5 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/list_servers.rb @@ -0,0 +1,58 @@ +module Aviator + + define_request :list_servers, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/List_Servers-d1e2078.html' + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/GET_listServers_v2__tenant_id__servers_compute_servers.html' + + link 'github :issue => getting all servers', + 'https://github.com/aviator/aviator/issues/35' + + link 'related mailing list discussion', + 'https://lists.launchpad.net/openstack/msg24695.html' + + param :all_tenants, :required => false + param :details, :required => false + param :flavor, :required => false + param :image, :required => false + param :limit, :required => false + param :marker, :required => false + param :server, :required => false + param :status, :required => false + param 'changes-since', :required => false, :alias => :changes_since + + + def headers + super + end + + + def http_method + :get + end + + + def url + str = "#{ base_url }/servers" + str += "/detail" if params[:details] + + filters = [] + + (optional_params + required_params - [:details]).each do |param_name| + value = param_name == :all_tenants && params[param_name] ? 1 : params[param_name] + filters << "#{ param_name }=#{ value }" if value + end + + str += "?#{ filters.join('&') }" unless filters.empty? + + str + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/pause_server.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/pause_server.rb new file mode 100644 index 000000000..00e5ec663 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/pause_server.rb @@ -0,0 +1,34 @@ +module Aviator + + define_request :pause_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/POST_pause_v2__tenant_id__servers__server_id__action_ext-os-admin-actions.html' + + param :id, :required => true + + + def body + { :pause => nil } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/reboot_server.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/reboot_server.rb new file mode 100644 index 000000000..8aa2296da --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/reboot_server.rb @@ -0,0 +1,41 @@ +module Aviator + + define_request :reboot_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Reboot_Server-d1e3371.html' + + param :id, :required => true + param :type, :required => false + + + def body + p = { + :reboot => { + :type => params[:type] || 'SOFT' + } + } + + p + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/rebuild_server.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/rebuild_server.rb new file mode 100644 index 000000000..8383f571a --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/rebuild_server.rb @@ -0,0 +1,53 @@ +module Aviator + + define_request :rebuild_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Rebuild_Server-d1e3538.html' + + param :accessIPv4, :required => false, :alias => :access_ipv4 + param :accessIPv6, :required => false, :alias => :access_ipv6 + param :adminPass, :required => true, :alias => :admin_pass + param :id, :required => true + param :imageRef, :required => true, :alias => :image_ref + param :metadata, :required => false + param :name, :required => true + param :personality, :required => false + + + def body + p = { + :rebuild => { + :adminPass => params[:adminPass], + :imageRef => params[:imageRef], + :name => params[:name] + } + } + + [:accessIPv4, :accessIPv6, :metadata, :personality].each do |key| + p[:rebuild][key] = params[key] if params[key] + end + + p + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/resume_server.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/resume_server.rb new file mode 100644 index 000000000..f220b366c --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/resume_server.rb @@ -0,0 +1,34 @@ +module Aviator + + define_request :resume_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/POST_resume_v2__tenant_id__servers__server_id__action_ext-os-admin-actions.html' + + param :id, :required => true + + + def body + { :resume => nil } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/root.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/root.rb new file mode 100644 index 000000000..3a3c4dabc --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/root.rb @@ -0,0 +1,24 @@ +module Aviator + + define_request :root, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + def headers + super + end + + + def http_method + :get + end + + + def url + uri = URI(base_url) + "#{ uri.scheme }://#{ uri.host }:#{ uri.port.to_s }/v2/" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/set_image_metadata.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/set_image_metadata.rb new file mode 100644 index 000000000..c17976f9e --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/set_image_metadata.rb @@ -0,0 +1,38 @@ +module Aviator + + define_request :set_image_metadata, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Create_or_Replace_Metadata-d1e5358.html' + + + param :id, :required => true + param :metadata, :required => true + + + def body + { + :metadata => params[:metadata] + } + end + + + def headers + super + end + + + def http_method + :put + end + + + def url + "#{ base_url }/images/#{ params[:id] }/metadata" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/set_server_metadata.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/set_server_metadata.rb new file mode 100644 index 000000000..8631c0397 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/set_server_metadata.rb @@ -0,0 +1,38 @@ +module Aviator + + define_request :set_server_metadata, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Create_or_Replace_Metadata-d1e5358.html' + + + param :id, :required => true + param :metadata, :required => true + + + def body + { + :metadata => params[:metadata] + } + end + + + def headers + super + end + + + def http_method + :put + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/metadata" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/suspend_server.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/suspend_server.rb new file mode 100644 index 000000000..a9bb9a52e --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/suspend_server.rb @@ -0,0 +1,34 @@ +module Aviator + + define_request :suspend_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/POST_suspend_v2__tenant_id__servers__server_id__action_ext-os-admin-actions.html' + + param :id, :required => true + + + def body + { :suspend => nil } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/unpause_server.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/unpause_server.rb new file mode 100644 index 000000000..e11089a62 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/unpause_server.rb @@ -0,0 +1,34 @@ +module Aviator + + define_request :unpause_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/POST_unpause_v2__tenant_id__servers__server_id__action_ext-os-admin-actions.html' + + param :id, :required => true + + + def body + { :unpause => nil } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/update_image_metadata.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/update_image_metadata.rb new file mode 100644 index 000000000..0ec3694b0 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/update_image_metadata.rb @@ -0,0 +1,38 @@ +module Aviator + + define_request :update_image_metadata, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Update_Metadata-d1e5208.html' + + + param :id, :required => true + param :metadata, :required => true + + + def body + { + :metadata => params[:metadata] + } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/images/#{ params[:id] }/metadata" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/update_server.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/update_server.rb new file mode 100644 index 000000000..453c58329 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/update_server.rb @@ -0,0 +1,45 @@ +module Aviator + + define_request :update_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/ServerUpdate.html' + + param :accessIPv4, :required => false, :alias => :access_ipv4 + param :accessIPv6, :required => false, :alias => :access_ipv6 + param :id, :required => true + param :name, :required => false + + + def body + p = { + :server => { } + } + + [:name, :accessIPv4, :accessIPv6].each do |key| + p[:server][key] = params[key] if params[key] + end + + p + end + + + def headers + super + end + + + def http_method + :put + end + + + def url + "#{ base_url }/servers/#{ params[:id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/update_server_metadata.rb b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/update_server_metadata.rb new file mode 100644 index 000000000..e1e5ad17d --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/compute/v2/public/update_server_metadata.rb @@ -0,0 +1,38 @@ +module Aviator + + define_request :update_server_metadata, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Update_Metadata-d1e5208.html' + + + param :id, :required => true + param :metadata, :required => true + + + def body + { + :metadata => params[:metadata] + } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/metadata" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/add_role_to_user_on_tenant.rb b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/add_role_to_user_on_tenant.rb new file mode 100644 index 000000000..e69b196eb --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/add_role_to_user_on_tenant.rb @@ -0,0 +1,33 @@ +module Aviator + + define_request :add_role_to_user_on_tenant, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :identity + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/PUT_addRolesToUserOnTenant_v2.0_tenants__tenantId__users__userId__roles_OS-KSADM__roleId__.html' + + + param :tenant_id, :required => true + param :user_id, :required => true + param :role_id, :required => true + + + def headers + super + end + + + def http_method + :put + end + + + def url + p = params + "#{ base_url }/tenants/#{ p[:tenant_id] }/users/#{ p[:user_id] }/roles/OS-KSADM/#{ p[:role_id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/create_tenant.rb b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/create_tenant.rb new file mode 100644 index 000000000..6578ae060 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/create_tenant.rb @@ -0,0 +1,43 @@ +module Aviator + + define_request :create_tenant, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :identity + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/' + + + param :name, :required => true + param :description, :required => true + param :enabled, :required => true + + + def body + { + :tenant => { + :name => params[:name], + :description => params[:description], + :enabled => params[:enabled] + } + } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/tenants" + end + + end + +end \ No newline at end of file diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/create_user.rb b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/create_user.rb new file mode 100644 index 000000000..d9d87f77e --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/create_user.rb @@ -0,0 +1,66 @@ +module Aviator + + define_request :create_user do + + meta :provider, :openstack + meta :service, :identity + meta :api_version, :v2 + meta :endpoint_type, :admin + + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/POST_addUser_v2.0_users_.html' + + link 'documentation bug', + 'https://bugs.launchpad.net/keystone/+bug/1110435' + + link 'documentation bug', + 'https://bugs.launchpad.net/keystone/+bug/1226466' + + + param :name, :required => true + param :password, :required => true + + param :email, :required => false + param :enabled, :required => false + param :tenantId, :required => false, :alias => :tenant_id + + + def body + p = { + :user => {} + } + + (required_params + optional_params).each do |key| + p[:user][key] = params[key] if params[key] + end + + p + end + + + def headers + h = {} + + unless self.anonymous? + h['X-Auth-Token'] = session_data[:access][:token][:id] + end + + h + end + + + def http_method + :post + end + + + def url + service_spec = session_data[:access][:serviceCatalog].find{|s| s[:type] == 'identity' } + "#{ service_spec[:endpoints][0][:adminURL] }/users" + end + + end + +end + diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/delete_role_from_user_on_tenant.rb b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/delete_role_from_user_on_tenant.rb new file mode 100644 index 000000000..4d24469a7 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/delete_role_from_user_on_tenant.rb @@ -0,0 +1,34 @@ +module Aviator + + define_request :delete_role_from_user_on_tenant, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :identity + + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/DELETE_deleteRoleFromUserOnTenant_v2.0_tenants__tenantId__users__userId__roles_OS-KSADM__roleId__.html' + + + param :tenant_id, :required => true + param :user_id, :required => true + param :role_id, :required => true + + + def headers + super + end + + + def http_method + :delete + end + + + def url + p = params + "#{ base_url }/tenants/#{ p[:tenant_id] }/users/#{ p[:user_id] }/roles/OS-KSADM/#{ p[:role_id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/delete_tenant.rb b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/delete_tenant.rb new file mode 100644 index 000000000..63ad6437f --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/delete_tenant.rb @@ -0,0 +1,29 @@ +module Aviator + + define_request :delete_tenant, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :identity + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/DELETE_deleteTenant_v2.0_tenants__tenantId__.html' + + param :id, :required => true + + + def headers + super + end + + + def http_method + :delete + end + + + def url + "#{ base_url }/tenants/#{ params[:id]}" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/delete_user.rb b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/delete_user.rb new file mode 100644 index 000000000..f66bbaa4e --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/delete_user.rb @@ -0,0 +1,39 @@ +module Aviator + + define_request :delete_user do + + meta :provider, :openstack + meta :service, :identity + meta :api_version, :v2 + meta :endpoint_type, :admin + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/DELETE_deleteUser_v2.0_users__userId__.html' + + param :id, :required => true + + + def headers + h = {} + + unless self.anonymous? + h['X-Auth-Token'] = session_data[:access][:token][:id] + end + + h + end + + + def http_method + :delete + end + + + def url + service_spec = session_data[:access][:serviceCatalog].find{|s| s[:type] == service.to_s } + "#{ service_spec[:endpoints][0][:adminURL] }/users/#{ params[:id]}" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/get_tenant_by_id.rb b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/get_tenant_by_id.rb new file mode 100644 index 000000000..fe2dcc986 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/get_tenant_by_id.rb @@ -0,0 +1,30 @@ +module Aviator + + define_request :get_tenant_by_id, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :identity + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/GET_listUsers_v2.0_users_.html' + + + param :id, :required => true + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/tenants/#{ params[:id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/list_tenants.rb b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/list_tenants.rb new file mode 100644 index 000000000..48d293062 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/list_tenants.rb @@ -0,0 +1,35 @@ +module Aviator + + define_request :list_tenants, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :identity + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/GET_listTenants_v2.0_tenants_Tenant_Operations.html' + + link 'documentation bug', + 'https://bugs.launchpad.net/keystone/+bug/1218601' + + + param :marker, :required => false + param :limit, :required => false + + + def headers + super + end + + + def http_method + :get + end + + + def url + str = "#{ base_url }/tenants" + str += params_to_querystring(optional_params + required_params) + end + + end + +end \ No newline at end of file diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/list_users.rb b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/list_users.rb new file mode 100644 index 000000000..c17631035 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/list_users.rb @@ -0,0 +1,37 @@ +module Aviator + + define_request :list_users do + + meta :provider, :openstack + meta :service, :identity + meta :api_version, :v2 + meta :endpoint_type, :admin + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/GET_listUsers_v2.0_users_.html' + + + def headers + h = {} + + unless self.anonymous? + h['X-Auth-Token'] = session_data[:access][:token][:id] + end + + h + end + + + def http_method + :get + end + + + def url + service_spec = session_data[:access][:serviceCatalog].find{|s| s[:type] == 'identity' } + "#{ service_spec[:endpoints][0][:adminURL] }/users" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/update_tenant.rb b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/update_tenant.rb new file mode 100644 index 000000000..d3a56cf6b --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/update_tenant.rb @@ -0,0 +1,47 @@ +module Aviator + + define_request :update_tenant, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :identity + + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/POST_updateTenant_v2.0_tenants__tenantId__.html' + + + param :id, :required => true + param :name, :required => false + param :enabled, :required => false + param :description, :required => false + + + def body + p = { + :tenant => {} + } + + [:name, :enabled, :description].each do |key| + p[:tenant][key] = params[key] if params[key] + end + + p + end + + + def headers + super + end + + + def http_method + :put + end + + + def url + "#{ base_url }/tenants/#{ params[:id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/update_user.rb b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/update_user.rb new file mode 100644 index 000000000..4676de4cc --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/admin/update_user.rb @@ -0,0 +1,61 @@ +module Aviator + + define_request :update_user do + + meta :provider, :openstack + meta :service, :identity + meta :api_version, :v2 + meta :endpoint_type, :admin + + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/POST_updateUser_v2.0_users__userId__.html' + + link 'bug', + 'https://bugs.launchpad.net/keystone/+bug/1226475' + + param :id, :required => true + param :name, :required => false + param :password, :required => false + param :email, :required => false + param :enabled, :required => false + param :tenantId, :required => false, :alias => :tenant_id + + + def body + p = { + :user => {} + } + + optional_params.each do |key| + p[:user][key] = params[key] if params[key] + end + + p + end + + + def headers + h = {} + + unless self.anonymous? + h['X-Auth-Token'] = session_data[:access][:token][:id] + end + + h + end + + + def http_method + :put + end + + + def url + service_spec = session_data[:access][:serviceCatalog].find { |s| s[:type] == service.to_s } + "#{ service_spec[:endpoints][0][:adminURL] }/users/#{ params[:id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/public/create_token.rb b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/public/create_token.rb new file mode 100644 index 000000000..91731d462 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/public/create_token.rb @@ -0,0 +1,62 @@ +module Aviator + + define_request :create_token, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :anonymous, true + meta :service, :identity + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/POST_authenticate_v2.0_tokens_.html' + + link 'documentation bug', + 'https://bugs.launchpad.net/keystone/+bug/1208607' + + + param :username, :required => false + param :password, :required => false + param :tokenId, :required => false, :alias => :token_id + param :tenantName, :required => false, :alias => :tenant_name + param :tenantId, :required => false, :alias => :tenant_id + + + def body + p = if params[:tokenId] + { + :auth => { + :token => { + :id => params[:tokenId] + } + } + } + else + { + :auth => { + :passwordCredentials => { + :username => params[:username], + :password => params[:password] + } + } + } + end + + p[:auth][:tenantName] = params[:tenantName] if params[:tenantName] + p[:auth][:tenantId] = params[:tenantId] if params[:tenantId] + + p + end + + + def http_method + :post + end + + + def url + url = session_data[:auth_service][:host_uri] + url += '/v2.0' if (URI(url).path =~ /^\/?\w+/).nil? + url += "/tokens" + end + + end + +end \ No newline at end of file diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/public/list_tenants.rb b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/public/list_tenants.rb new file mode 100644 index 000000000..094032ab0 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/public/list_tenants.rb @@ -0,0 +1,35 @@ +module Aviator + + define_request :list_tenants, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :identity + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/GET_listTenants_v2.0_tokens_tenants_.html' + + link 'documentation bug', + 'https://bugs.launchpad.net/keystone/+bug/1218601' + + + param :marker, :required => false + param :limit, :required => false + + + def url + str = "#{ base_url }/tenants" + str += params_to_querystring(optional_params + required_params) + end + + + def headers + super + end + + + def http_method + :get + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/public/root.rb b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/public/root.rb new file mode 100644 index 000000000..0c6d38358 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/identity/v2/public/root.rb @@ -0,0 +1,25 @@ +module Aviator + + define_request :root, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :identity + + + def headers + super + end + + + def http_method + :get + end + + + def url + uri = URI(base_url) + "#{ uri.scheme }://#{ uri.host }:#{ uri.port.to_s }/v2.0/" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/image/v1/public/list_public_images.rb b/3rdparty/modules/aviator/feature/aviator/openstack/image/v1/public/list_public_images.rb new file mode 100644 index 000000000..2164d73eb --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/image/v1/public/list_public_images.rb @@ -0,0 +1,45 @@ +module Aviator + + define_request :list_public_images, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :image + meta :api_version, :v1 + + link 'documentation', 'http://docs.openstack.org/api/openstack-image-service/1.1/content/requesting-a-list-of-public-vm-images.html' + + param :name, :required => false + param :container_format, :required => false + param :disk_format, :required => false + param :status, :required => false + param :size_min, :required => false + param :size_max, :required => false + param :sort_key, :required => false + param :sort_dir, :required => false + + + def headers + super + end + + def http_method + :get + end + + def url + uri = URI(base_url) + url = "#{ uri.scheme }://#{ uri.host }:#{ uri.port.to_s }/v1/images" + + filters = [] + + optional_params.each do |param_name| + filters << "#{ param_name }=#{ params[param_name] }" if params[param_name] + end + + url += "?#{ filters.join('&') }" unless filters.empty? + + url + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/image/v1/public/root.rb b/3rdparty/modules/aviator/feature/aviator/openstack/image/v1/public/root.rb new file mode 100644 index 000000000..553f5369e --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/image/v1/public/root.rb @@ -0,0 +1,25 @@ +module Aviator + + define_request :root, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :image + meta :api_version, :v1 + + def headers + super + end + + + def http_method + :get + end + + + def url + uri = URI(base_url) + "#{ uri.scheme }://#{ uri.host }:#{ uri.port.to_s }/v1/" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/metering/v1/admin/list_projects.rb b/3rdparty/modules/aviator/feature/aviator/openstack/metering/v1/admin/list_projects.rb new file mode 100644 index 000000000..7ec8e667d --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/metering/v1/admin/list_projects.rb @@ -0,0 +1,27 @@ +module Aviator + + define_request :list_projects, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :metering + meta :api_version, :v1 + meta :endpoint_type, :admin + + + def headers + super + end + + + def http_method + :get + end + + + def url + uri = URI(base_url) + "#{ uri.scheme }://#{ uri.host }:#{ uri.port.to_s }/v1/projects" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/create_volume.rb b/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/create_volume.rb new file mode 100644 index 000000000..f40354d99 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/create_volume.rb @@ -0,0 +1,47 @@ +module Aviator + + define_request :create_volume, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :volume + meta :api_version, :v1 + + link 'documentation', 'http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/POST_createVolume_v1__tenant_id__volumes_v1__tenant_id__volumes.html' + + param :display_name, :required => true + param :display_description, :required => true + param :size, :required => true + param :volume_type, :required => false + param :availability_zone, :required => false + param :snapshot_id, :required => false + param :metadata, :required => false + + def body + p = { + :volume => { + :display_name => params[:display_name], + :display_description => params[:display_description], + :size => params[:size] + } + } + + optional_params.each do |key| + p[:volume][key] = params[key] if params[key] + end + + p + end + + def headers + super + end + + def http_method + :post + end + + def url + "#{ base_url }/volumes" + end + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/delete_volume.rb b/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/delete_volume.rb new file mode 100644 index 000000000..1397959aa --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/delete_volume.rb @@ -0,0 +1,25 @@ +module Aviator + + define_request :delete_volume, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :volume + meta :api_version, :v1 + + link 'documentation', 'http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/DELETE_deleteVolume_v1__tenant_id__volumes__volume_id__v1__tenant_id__volumes.html' + + param :id, :required => true + + def headers + super + end + + def http_method + :delete + end + + def url + "#{ base_url }/volumes/#{ params[:id] }" + end + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/get_volume.rb b/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/get_volume.rb new file mode 100644 index 000000000..991dc4454 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/get_volume.rb @@ -0,0 +1,28 @@ +module Aviator + + define_request :get_volume, :inherit => [:openstack, :common, :v2, :public, :base] do + meta :provider, :openstack + meta :service, :volume + meta :api_version, :v1 + meta :endpoint_type, :public + + link 'documentation', 'http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/GET_getVolume_v1__tenant_id__volumes__volume_id__v1__tenant_id__volumes.html' + + param :id, :required => true + + def headers + super + end + + def http_method + :get + end + + def url + "#{ base_url }/volumes/#{ params[:id] }" + end + + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/list_volume_types.rb b/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/list_volume_types.rb new file mode 100644 index 000000000..d2f0b5c8a --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/list_volume_types.rb @@ -0,0 +1,29 @@ +module Aviator + + define_request :list_volume_types, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :provider, :openstack + meta :service, :volume + meta :api_version, :v1 + meta :endpoint_type, :public + + link 'documentation', 'http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/GET_getVolumeTypes_v1__tenant_id__types_v1__tenant_id__types.html' + + param :extra_specs, :required => false + param :name, :required => false + + def headers + super + end + + def http_method + :get + end + + def url + "#{ base_url }/types" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/list_volumes.rb b/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/list_volumes.rb new file mode 100644 index 000000000..c88cf7500 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/list_volumes.rb @@ -0,0 +1,48 @@ +module Aviator + + define_request :list_volumes, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :volume + meta :api_version, :v1 + + link 'documentation', 'http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/GET_getVolumesSimple_v1__tenant_id__volumes_v1__tenant_id__volumes.html' + + param :all_tenants, :required => false + param :details, :required => false + param :status, :required => false + param :availability_zone, :required => false + param :bootable, :required => false + param :display_name, :required => false + param :display_description, :required => false + param :volume_type, :required => false + param :snapshot_id, :required => false + param :size, :required => false + + + def headers + super + end + + def http_method + :get + end + + def url + str = "#{ base_url }/volumes" + str += "/detail" if params[:details] + + filters = [] + + (optional_params + required_params - [:details]).each do |param_name| + value = param_name == :all_tenants && params[param_name] ? 1 : params[param_name] + filters << "#{ param_name }=#{ value }" if value + end + + str += "?#{ filters.join('&') }" unless filters.empty? + + str + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/root.rb b/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/root.rb new file mode 100644 index 000000000..0e3748c9c --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/root.rb @@ -0,0 +1,26 @@ +module Aviator + + define_request :root, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :volume + meta :api_version, :v1 + + + def headers + super + end + + + def http_method + :get + end + + + def url + uri = URI(base_url) + "#{ uri.scheme }://#{ uri.host }:#{ uri.port.to_s }/v1/" + end + + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/update_volume.rb b/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/update_volume.rb new file mode 100644 index 000000000..67121c36f --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/openstack/volume/v1/public/update_volume.rb @@ -0,0 +1,43 @@ +module Aviator + + define_request :update_volume, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :volume + meta :api_version, :v1 + + link 'documentation', 'http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/PUT_renameVolume_v1__tenant_id__volumes__volume_id__v1__tenant_id__volumes.html' + + param :id, :required => true + param :display_name, :required => false + param :display_description, :required => false + + + def body + p = { :volume => {} } + + [:display_name, :display_description].each do |key| + p[:volume][key] = params[key] if params[key] + end + + p + end + + + def headers + super + end + + + def http_method + :put + end + + + def url + "#{ base_url }/volumes/#{ params[:id] }" + end + + end + + +end diff --git a/3rdparty/modules/aviator/feature/aviator/string.rb b/3rdparty/modules/aviator/feature/aviator/string.rb new file mode 100644 index 000000000..7efa2e1ac --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/string.rb @@ -0,0 +1,18 @@ +class String + + def camelize + word = self.slice(0,1).capitalize + self.slice(1..-1) + word.gsub(/_([a-zA-Z\d])/) { "#{$1.capitalize}" } + end + + def constantize + self.split("::").inject(Object) do |namespace, sym| + namespace.const_get(sym.to_s.camelize, false) + end + end + + def underscore + self.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase + end + +end diff --git a/3rdparty/modules/aviator/feature/aviator/version.rb b/3rdparty/modules/aviator/feature/aviator/version.rb new file mode 100644 index 000000000..5726b3025 --- /dev/null +++ b/3rdparty/modules/aviator/feature/aviator/version.rb @@ -0,0 +1,3 @@ +module Aviator + VERSION = "0.0.7" +end diff --git a/3rdparty/modules/aviator/feature/composite_io.rb b/3rdparty/modules/aviator/feature/composite_io.rb new file mode 100644 index 000000000..4ba7cf5ff --- /dev/null +++ b/3rdparty/modules/aviator/feature/composite_io.rb @@ -0,0 +1,108 @@ +#-- +# Copyright (c) 2007-2012 Nick Sieger. +# See the file README.txt included with the distribution for +# software license details. +#++ + +# Concatenate together multiple IO objects into a single, composite IO object +# for purposes of reading as a single stream. +# +# Usage: +# +# crio = CompositeReadIO.new(StringIO.new('one'), StringIO.new('two'), StringIO.new('three')) +# puts crio.read # => "onetwothree" +# +class CompositeReadIO + # Create a new composite-read IO from the arguments, all of which should + # respond to #read in a manner consistent with IO. + def initialize(*ios) + @ios = ios.flatten + @index = 0 + end + + # Read from IOs in order until `length` bytes have been received. + def read(length = nil, outbuf = nil) + got_result = false + outbuf = outbuf ? outbuf.replace("") : "" + + while io = current_io + if result = io.read(length) + got_result ||= !result.nil? + result.force_encoding("BINARY") if result.respond_to?(:force_encoding) + outbuf << result + length -= result.length if length + break if length == 0 + end + advance_io + end + (!got_result && length) ? nil : outbuf + end + + def rewind + @ios.each { |io| io.rewind } + @index = 0 + end + + private + + def current_io + @ios[@index] + end + + def advance_io + @index += 1 + end +end + +# Convenience methods for dealing with files and IO that are to be uploaded. +class UploadIO + # Create an upload IO suitable for including in the params hash of a + # Net::HTTP::Post::Multipart. + # + # Can take two forms. The first accepts a filename and content type, and + # opens the file for reading (to be closed by finalizer). + # + # The second accepts an already-open IO, but also requires a third argument, + # the filename from which it was opened (particularly useful/recommended if + # uploading directly from a form in a framework, which often save the file to + # an arbitrarily named RackMultipart file in /tmp). + # + # Usage: + # + # UploadIO.new("file.txt", "text/plain") + # UploadIO.new(file_io, "text/plain", "file.txt") + # + attr_reader :content_type, :original_filename, :local_path, :io, :opts + + def initialize(filename_or_io, content_type, filename = nil, opts = {}) + io = filename_or_io + local_path = "" + if io.respond_to? :read + # in Ruby 1.9.2, StringIOs no longer respond to path + # (since they respond to :length, so we don't need their local path, see parts.rb:41) + local_path = filename_or_io.respond_to?(:path) ? filename_or_io.path : "local.path" + else + io = File.open(filename_or_io) + local_path = filename_or_io + end + filename ||= local_path + + @content_type = content_type + @original_filename = File.basename(filename) + @local_path = local_path + @io = io + @opts = opts + end + + def self.convert!(io, content_type, original_filename, local_path) + raise ArgumentError, "convert! has been removed. You must now wrap IOs using:\nUploadIO.new(filename_or_io, content_type, filename=nil)\nPlease update your code." + end + + def method_missing(*args) + @io.send(*args) + end + + def respond_to?(meth, include_all = false) + @io.respond_to?(meth, include_all) || super(meth, include_all) + end +end diff --git a/3rdparty/modules/aviator/feature/faraday.rb b/3rdparty/modules/aviator/feature/faraday.rb new file mode 100644 index 000000000..4b63ec8e9 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday.rb @@ -0,0 +1,268 @@ +require 'thread' +require 'cgi' +require 'set' +require 'forwardable' + +# Public: This is the main namespace for Faraday. You can either use it to +# create Faraday::Connection objects, or access it directly. +# +# Examples +# +# Faraday.get "http://faraday.com" +# +# conn = Faraday.new "http://faraday.com" +# conn.get '/' +# +module Faraday + VERSION = "0.9.0" + + class << self + # Public: Gets or sets the root path that Faraday is being loaded from. + # This is the root from where the libraries are auto-loaded from. + attr_accessor :root_path + + # Public: Gets or sets the path that the Faraday libs are loaded from. + attr_accessor :lib_path + + # Public: Gets or sets the Symbol key identifying a default Adapter to use + # for the default Faraday::Connection. + attr_reader :default_adapter + + # Public: Sets the default Faraday::Connection for simple scripts that + # access the Faraday constant directly. + # + # Faraday.get "https://faraday.com" + attr_writer :default_connection + + # Public: Sets the default options used when calling Faraday#new. + attr_writer :default_connection_options + + # Public: Initializes a new Faraday::Connection. + # + # url - The optional String base URL to use as a prefix for all + # requests. Can also be the options Hash. + # options - The optional Hash used to configure this Faraday::Connection. + # Any of these values will be set on every request made, unless + # overridden for a specific request. + # :url - String base URL. + # :params - Hash of URI query unencoded key/value pairs. + # :headers - Hash of unencoded HTTP header key/value pairs. + # :request - Hash of request options. + # :ssl - Hash of SSL options. + # :proxy - Hash of Proxy options. + # + # Examples + # + # Faraday.new 'http://faraday.com' + # + # # http://faraday.com?page=1 + # Faraday.new 'http://faraday.com', :params => {:page => 1} + # + # # same + # + # Faraday.new :url => 'http://faraday.com', + # :params => {:page => 1} + # + # Returns a Faraday::Connection. + def new(url = nil, options = nil) + block = block_given? ? Proc.new : nil + options = options ? default_connection_options.merge(options) : default_connection_options.dup + Faraday::Connection.new(url, options, &block) + end + + # Internal: Requires internal Faraday libraries. + # + # *libs - One or more relative String names to Faraday classes. + # + # Returns nothing. + def require_libs(*libs) + libs.each do |lib| + require "#{lib_path}/#{lib}" + end + end + + # Public: Updates default adapter while resetting + # #default_connection. + # + # Returns the new default_adapter. + def default_adapter=(adapter) + @default_connection = nil + @default_adapter = adapter + end + + alias require_lib require_libs + + private + # Internal: Proxies method calls on the Faraday constant to + # #default_connection. + def method_missing(name, *args, &block) + default_connection.send(name, *args, &block) + end + end + + self.root_path = File.expand_path "..", __FILE__ + self.lib_path = File.expand_path "../faraday", __FILE__ + self.default_adapter = :net_http + + # Gets the default connection used for simple scripts. + # + # Returns a Faraday::Connection, configured with the #default_adapter. + def self.default_connection + @default_connection ||= Connection.new + end + + # Gets the default connection options used when calling Faraday#new. + # + # Returns a Faraday::ConnectionOptions. + def self.default_connection_options + @default_connection_options ||= ConnectionOptions.new + end + + if (!defined?(RUBY_ENGINE) || "ruby" == RUBY_ENGINE) && RUBY_VERSION < '1.9' + begin + require 'system_timer' + Timer = SystemTimer + rescue LoadError + warn "Faraday: you may want to install system_timer for reliable timeouts" + end + end + + unless const_defined? :Timer + require 'timeout' + Timer = Timeout + end + + # Public: Adds the ability for other modules to register and lookup + # middleware classes. + module MiddlewareRegistry + # Public: Register middleware class(es) on the current module. + # + # mapping - A Hash mapping Symbol keys to classes. Classes can be expressed + # as fully qualified constant, or a Proc that will be lazily + # called to return the former. + # + # Examples + # + # module Faraday + # class Whatever + # # Middleware looked up by :foo returns Faraday::Whatever::Foo. + # register_middleware :foo => Foo + # + # # Middleware looked up by :bar returns Faraday::Whatever.const_get(:Bar) + # register_middleware :bar => :Bar + # + # # Middleware looked up by :baz requires 'baz' and returns Faraday::Whatever.const_get(:Baz) + # register_middleware :baz => [:Baz, 'baz'] + # end + # end + # + # Returns nothing. + def register_middleware(autoload_path = nil, mapping = nil) + if mapping.nil? + mapping = autoload_path + autoload_path = nil + end + middleware_mutex do + @middleware_autoload_path = autoload_path if autoload_path + (@registered_middleware ||= {}).update(mapping) + end + end + + # Public: Lookup middleware class with a registered Symbol shortcut. + # + # key - The Symbol key for the registered middleware. + # + # Examples + # + # module Faraday + # class Whatever + # register_middleware :foo => Foo + # end + # end + # + # Faraday::Whatever.lookup_middleware(:foo) + # # => Faraday::Whatever::Foo + # + # Returns a middleware Class. + def lookup_middleware(key) + load_middleware(key) || + raise(Faraday::Error.new("#{key.inspect} is not registered on #{self}")) + end + + def middleware_mutex(&block) + @middleware_mutex ||= begin + require 'monitor' + Monitor.new + end + @middleware_mutex.synchronize(&block) + end + + def fetch_middleware(key) + defined?(@registered_middleware) && @registered_middleware[key] + end + + def load_middleware(key) + value = fetch_middleware(key) + case value + when Module + value + when Symbol, String + middleware_mutex do + @registered_middleware[key] = const_get(value) + end + when Proc + middleware_mutex do + @registered_middleware[key] = value.call + end + when Array + middleware_mutex do + const, path = value + if root = @middleware_autoload_path + path = "#{root}/#{path}" + end + require(path) + @registered_middleware[key] = const + end + load_middleware(key) + end + end + end + + def self.const_missing(name) + if name.to_sym == :Builder + warn "Faraday::Builder is now Faraday::RackBuilder." + const_set name, RackBuilder + else + super + end + end + + require_libs "utils", "options", "connection", "rack_builder", "parameters", + "middleware", "adapter", "request", "response", "upload_io", "error" + + if !ENV["FARADAY_NO_AUTOLOAD"] + require_lib 'autoload' + end +end + +# not pulling in active-support JUST for this method. And I love this method. +class Object + # The primary purpose of this method is to "tap into" a method chain, + # in order to perform operations on intermediate results within the chain. + # + # Examples + # + # (1..10).tap { |x| puts "original: #{x.inspect}" }.to_a. + # tap { |x| puts "array: #{x.inspect}" }. + # select { |x| x%2 == 0 }. + # tap { |x| puts "evens: #{x.inspect}" }. + # map { |x| x*x }. + # tap { |x| puts "squares: #{x.inspect}" } + # + # Yields self. + # Returns self. + def tap + yield(self) + self + end unless Object.respond_to?(:tap) +end diff --git a/3rdparty/modules/aviator/feature/faraday/adapter.rb b/3rdparty/modules/aviator/feature/faraday/adapter.rb new file mode 100644 index 000000000..f018b509a --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/adapter.rb @@ -0,0 +1,46 @@ +module Faraday + # Public: This is a base class for all Faraday adapters. Adapters are + # responsible for fulfilling a Faraday request. + class Adapter < Middleware + CONTENT_LENGTH = 'Content-Length'.freeze + + register_middleware File.expand_path('../adapter', __FILE__), + :test => [:Test, 'test'], + :net_http => [:NetHttp, 'net_http'], + :net_http_persistent => [:NetHttpPersistent, 'net_http_persistent'], + :typhoeus => [:Typhoeus, 'typhoeus'], + :patron => [:Patron, 'patron'], + :em_synchrony => [:EMSynchrony, 'em_synchrony'], + :em_http => [:EMHttp, 'em_http'], + :excon => [:Excon, 'excon'], + :rack => [:Rack, 'rack'], + :httpclient => [:HTTPClient, 'httpclient'] + + # Public: This module marks an Adapter as supporting parallel requests. + module Parallelism + attr_writer :supports_parallel + def supports_parallel?() @supports_parallel end + + def inherited(subclass) + super + subclass.supports_parallel = self.supports_parallel? + end + end + + extend Parallelism + self.supports_parallel = false + + def call(env) + env.clear_body if env.needs_body? + end + + def save_response(env, status, body, headers = nil) + env.status = status + env.body = body + env.response_headers = Utils::Headers.new.tap do |response_headers| + response_headers.update headers unless headers.nil? + yield(response_headers) if block_given? + end + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/adapter/em_http.rb b/3rdparty/modules/aviator/feature/faraday/adapter/em_http.rb new file mode 100644 index 000000000..a248fcfd2 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/adapter/em_http.rb @@ -0,0 +1,237 @@ +module Faraday + class Adapter + # EventMachine adapter is useful for either asynchronous requests + # when in EM reactor loop or for making parallel requests in + # synchronous code. + class EMHttp < Faraday::Adapter + module Options + def connection_config(env) + options = {} + configure_proxy(options, env) + configure_timeout(options, env) + configure_socket(options, env) + configure_ssl(options, env) + options + end + + def request_config(env) + options = { + :body => read_body(env), + :head => env[:request_headers], + # :keepalive => true, + # :file => 'path/to/file', # stream data off disk + } + configure_compression(options, env) + options + end + + def read_body(env) + body = env[:body] + body.respond_to?(:read) ? body.read : body + end + + def configure_proxy(options, env) + if proxy = request_options(env)[:proxy] + options[:proxy] = { + :host => proxy[:uri].host, + :port => proxy[:uri].port, + :authorization => [proxy[:user], proxy[:password]] + } + end + end + + def configure_socket(options, env) + if bind = request_options(env)[:bind] + options[:bind] = { + :host => bind[:host], + :port => bind[:port] + } + end + end + + def configure_ssl(options, env) + if env[:url].scheme == 'https' && env[:ssl] + options[:ssl] = { + :cert_chain_file => env[:ssl][:ca_file], + :verify_peer => env[:ssl].fetch(:verify, true) + } + end + end + + def configure_timeout(options, env) + timeout, open_timeout = request_options(env).values_at(:timeout, :open_timeout) + options[:connect_timeout] = options[:inactivity_timeout] = timeout + options[:connect_timeout] = open_timeout if open_timeout + end + + def configure_compression(options, env) + if env[:method] == :get and not options[:head].key? 'accept-encoding' + options[:head]['accept-encoding'] = 'gzip, compressed' + end + end + + def request_options(env) + env[:request] + end + end + + include Options + + dependency 'em-http' + + self.supports_parallel = true + + def self.setup_parallel_manager(options = nil) + Manager.new + end + + def call(env) + super + perform_request env + @app.call env + end + + def perform_request(env) + if parallel?(env) + manager = env[:parallel_manager] + manager.add { + perform_single_request(env). + callback { env[:response].finish(env) } + } + else + unless EventMachine.reactor_running? + error = nil + # start EM, block until request is completed + EventMachine.run do + perform_single_request(env). + callback { EventMachine.stop }. + errback { |client| + error = error_message(client) + EventMachine.stop + } + end + raise_error(error) if error + else + # EM is running: instruct upstream that this is an async request + env[:parallel_manager] = true + perform_single_request(env). + callback { env[:response].finish(env) }. + errback { + # TODO: no way to communicate the error in async mode + raise NotImplementedError + } + end + end + rescue EventMachine::Connectify::CONNECTError => err + if err.message.include?("Proxy Authentication Required") + raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "} + else + raise Error::ConnectionFailed, err + end + rescue => err + if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err + raise Faraday::SSLError, err + else + raise + end + end + + # TODO: reuse the connection to support pipelining + def perform_single_request(env) + req = EventMachine::HttpRequest.new(env[:url], connection_config(env)) + req.setup_request(env[:method], request_config(env)).callback { |client| + save_response(env, client.response_header.status, client.response) do |resp_headers| + client.response_header.each do |name, value| + resp_headers[name.to_sym] = value + end + end + } + end + + def error_message(client) + client.error or "request failed" + end + + def raise_error(msg) + errklass = Faraday::Error::ClientError + if msg == Errno::ETIMEDOUT + errklass = Faraday::Error::TimeoutError + msg = "request timed out" + elsif msg == Errno::ECONNREFUSED + errklass = Faraday::Error::ConnectionFailed + msg = "connection refused" + elsif msg == "connection closed by server" + errklass = Faraday::Error::ConnectionFailed + end + raise errklass, msg + end + + def parallel?(env) + !!env[:parallel_manager] + end + + # The parallel manager is designed to start an EventMachine loop + # and block until all registered requests have been completed. + class Manager + def initialize + reset + end + + def reset + @registered_procs = [] + @num_registered = 0 + @num_succeeded = 0 + @errors = [] + @running = false + end + + def running?() @running end + + def add + if running? + perform_request { yield } + else + @registered_procs << Proc.new + end + @num_registered += 1 + end + + def run + if @num_registered > 0 + @running = true + EventMachine.run do + @registered_procs.each do |proc| + perform_request(&proc) + end + end + if @errors.size > 0 + raise Faraday::Error::ClientError, @errors.first || "connection failed" + end + end + ensure + reset + end + + def perform_request + client = yield + client.callback { @num_succeeded += 1; check_finished } + client.errback { @errors << client.error; check_finished } + end + + def check_finished + if @num_succeeded + @errors.size == @num_registered + EventMachine.stop + end + end + end + end + end +end + +begin + require 'openssl' +rescue LoadError + warn "Warning: no such file to load -- openssl. Make sure it is installed if you want HTTPS support" +else + require 'faraday/adapter/em_http_ssl_patch' +end if Faraday::Adapter::EMHttp.loaded? diff --git a/3rdparty/modules/aviator/feature/faraday/adapter/em_http_ssl_patch.rb b/3rdparty/modules/aviator/feature/faraday/adapter/em_http_ssl_patch.rb new file mode 100644 index 000000000..8bbfcbce3 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/adapter/em_http_ssl_patch.rb @@ -0,0 +1,56 @@ +require 'openssl' +require 'em-http' + +module EmHttpSslPatch + def ssl_verify_peer(cert_string) + cert = nil + begin + cert = OpenSSL::X509::Certificate.new(cert_string) + rescue OpenSSL::X509::CertificateError + return false + end + + @last_seen_cert = cert + + if certificate_store.verify(@last_seen_cert) + begin + certificate_store.add_cert(@last_seen_cert) + rescue OpenSSL::X509::StoreError => e + raise e unless e.message == 'cert already in hash table' + end + true + else + raise OpenSSL::SSL::SSLError.new(%(unable to verify the server certificate for "#{host}")) + end + end + + def ssl_handshake_completed + return true unless verify_peer? + + unless OpenSSL::SSL.verify_certificate_identity(@last_seen_cert, host) + raise OpenSSL::SSL::SSLError.new(%(host "#{host}" does not match the server certificate)) + else + true + end + end + + def verify_peer? + parent.connopts.tls[:verify_peer] + end + + def host + parent.connopts.host + end + + def certificate_store + @certificate_store ||= begin + store = OpenSSL::X509::Store.new + store.set_default_paths + ca_file = parent.connopts.tls[:cert_chain_file] + store.add_file(ca_file) if ca_file + store + end + end +end + +EventMachine::HttpStubConnection.send(:include, EmHttpSslPatch) diff --git a/3rdparty/modules/aviator/feature/faraday/adapter/em_synchrony.rb b/3rdparty/modules/aviator/feature/faraday/adapter/em_synchrony.rb new file mode 100644 index 000000000..305e702f8 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/adapter/em_synchrony.rb @@ -0,0 +1,92 @@ +require 'uri' + +module Faraday + class Adapter + class EMSynchrony < Faraday::Adapter + include EMHttp::Options + + dependency do + require 'em-synchrony/em-http' + require 'em-synchrony/em-multi' + require 'fiber' + end + + self.supports_parallel = true + + def self.setup_parallel_manager(options = {}) + ParallelManager.new + end + + def call(env) + super + request = EventMachine::HttpRequest.new(Utils::URI(env[:url].to_s), connection_config(env)) + + http_method = env[:method].to_s.downcase.to_sym + + # Queue requests for parallel execution. + if env[:parallel_manager] + env[:parallel_manager].add(request, http_method, request_config(env)) do |resp| + save_response(env, resp.response_header.status, resp.response) do |resp_headers| + resp.response_header.each do |name, value| + resp_headers[name.to_sym] = value + end + end + + # Finalize the response object with values from `env`. + env[:response].finish(env) + end + + # Execute single request. + else + client = nil + block = lambda { request.send(http_method, request_config(env)) } + + if !EM.reactor_running? + EM.run do + Fiber.new { + client = block.call + EM.stop + }.resume + end + else + client = block.call + end + + raise client.error if client.error + + save_response(env, client.response_header.status, client.response) do |resp_headers| + client.response_header.each do |name, value| + resp_headers[name.to_sym] = value + end + end + end + + @app.call env + rescue Errno::ECONNREFUSED + raise Error::ConnectionFailed, $! + rescue EventMachine::Connectify::CONNECTError => err + if err.message.include?("Proxy Authentication Required") + raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "} + else + raise Error::ConnectionFailed, err + end + rescue => err + if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err + raise Faraday::SSLError, err + else + raise + end + end + end + end +end + +require 'faraday/adapter/em_synchrony/parallel_manager' + +begin + require 'openssl' +rescue LoadError + warn "Warning: no such file to load -- openssl. Make sure it is installed if you want HTTPS support" +else + require 'faraday/adapter/em_http_ssl_patch' +end if Faraday::Adapter::EMSynchrony.loaded? diff --git a/3rdparty/modules/aviator/feature/faraday/adapter/em_synchrony/parallel_manager.rb b/3rdparty/modules/aviator/feature/faraday/adapter/em_synchrony/parallel_manager.rb new file mode 100644 index 000000000..12a1bafa4 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/adapter/em_synchrony/parallel_manager.rb @@ -0,0 +1,66 @@ +module Faraday + class Adapter + class EMSynchrony < Faraday::Adapter + class ParallelManager + + # Add requests to queue. The `request` argument should be a + # `EM::HttpRequest` object. + def add(request, method, *args, &block) + queue << { + :request => request, + :method => method, + :args => args, + :block => block + } + end + + # Run all requests on queue with `EM::Synchrony::Multi`, wrapping + # it in a reactor and fiber if needed. + def run + result = nil + if !EM.reactor_running? + EM.run { + Fiber.new do + result = perform + EM.stop + end.resume + } + else + result = perform + end + result + end + + + private + + # The request queue. + def queue + @queue ||= [] + end + + # Main `EM::Synchrony::Multi` performer. + def perform + multi = ::EM::Synchrony::Multi.new + + queue.each do |item| + method = "a#{item[:method]}".to_sym + + req = item[:request].send(method, *item[:args]) + req.callback(&item[:block]) + + req_name = "req_#{multi.requests.size}".to_sym + multi.add(req_name, req) + end + + # Clear the queue, so parallel manager objects can be reused. + @queue = [] + + # Block fiber until all requests have returned. + multi.perform + end + + end # ParallelManager + end # EMSynchrony + end # Adapter +end # Faraday diff --git a/3rdparty/modules/aviator/feature/faraday/adapter/excon.rb b/3rdparty/modules/aviator/feature/faraday/adapter/excon.rb new file mode 100644 index 000000000..db0c7c352 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/adapter/excon.rb @@ -0,0 +1,80 @@ +module Faraday + class Adapter + class Excon < Faraday::Adapter + dependency 'excon' + + def initialize(app, connection_options = {}) + @connection_options = connection_options + super(app) + end + + def call(env) + super + + opts = {} + if env[:url].scheme == 'https' && ssl = env[:ssl] + opts[:ssl_verify_peer] = !!ssl.fetch(:verify, true) + opts[:ssl_ca_path] = ssl[:ca_path] if ssl[:ca_path] + opts[:ssl_ca_file] = ssl[:ca_file] if ssl[:ca_file] + opts[:client_cert] = ssl[:client_cert] if ssl[:client_cert] + opts[:client_key] = ssl[:client_key] if ssl[:client_key] + opts[:certificate] = ssl[:certificate] if ssl[:certificate] + opts[:private_key] = ssl[:private_key] if ssl[:private_key] + + # https://github.com/geemus/excon/issues/106 + # https://github.com/jruby/jruby-ossl/issues/19 + opts[:nonblock] = false + end + + if ( req = env[:request] ) + if req[:timeout] + opts[:read_timeout] = req[:timeout] + opts[:connect_timeout] = req[:timeout] + opts[:write_timeout] = req[:timeout] + end + + if req[:open_timeout] + opts[:connect_timeout] = req[:open_timeout] + opts[:write_timeout] = req[:open_timeout] + end + + if req[:proxy] + opts[:proxy] = { + :host => req[:proxy][:uri].host, + :port => req[:proxy][:uri].port, + :scheme => req[:proxy][:uri].scheme, + :user => req[:proxy][:user], + :password => req[:proxy][:password] + } + end + end + + conn = ::Excon.new(env[:url].to_s, opts.merge(@connection_options)) + + resp = conn.request \ + :method => env[:method].to_s.upcase, + :headers => env[:request_headers], + :body => read_body(env) + + save_response(env, resp.status.to_i, resp.body, resp.headers) + + @app.call env + rescue ::Excon::Errors::SocketError => err + if err.message =~ /\btimeout\b/ + raise Error::TimeoutError, err + elsif err.message =~ /\bcertificate\b/ + raise Faraday::SSLError, err + else + raise Error::ConnectionFailed, err + end + rescue ::Excon::Errors::Timeout => err + raise Error::TimeoutError, err + end + + # TODO: support streaming requests + def read_body(env) + env[:body].respond_to?(:read) ? env[:body].read : env[:body] + end + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/adapter/httpclient.rb b/3rdparty/modules/aviator/feature/faraday/adapter/httpclient.rb new file mode 100644 index 000000000..06c663f03 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/adapter/httpclient.rb @@ -0,0 +1,106 @@ +module Faraday + class Adapter + class HTTPClient < Faraday::Adapter + dependency 'httpclient' + + def client + @client ||= ::HTTPClient.new + end + + def call(env) + super + + if req = env[:request] + if proxy = req[:proxy] + configure_proxy proxy + end + + if bind = req[:bind] + configure_socket bind + end + + configure_timeouts req + end + + if env[:url].scheme == 'https' && ssl = env[:ssl] + configure_ssl ssl + end + + # TODO Don't stream yet. + # https://github.com/nahi/httpclient/pull/90 + env[:body] = env[:body].read if env[:body].respond_to? :read + + resp = client.request env[:method], env[:url], + :body => env[:body], + :header => env[:request_headers] + + save_response env, resp.status, resp.body, resp.headers + + @app.call env + rescue ::HTTPClient::TimeoutError + raise Faraday::Error::TimeoutError, $! + rescue ::HTTPClient::BadResponseError => err + if err.message.include?('status 407') + raise Faraday::Error::ConnectionFailed, %{407 "Proxy Authentication Required "} + else + raise Faraday::Error::ClientError, $! + end + rescue Errno::ECONNREFUSED, EOFError + raise Faraday::Error::ConnectionFailed, $! + rescue => err + if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err + raise Faraday::SSLError, err + else + raise + end + end + + def configure_socket(bind) + client.socket_local.host = bind[:host] + client.socket_local.port = bind[:port] + end + + def configure_proxy(proxy) + client.proxy = proxy[:uri] + if proxy[:user] && proxy[:password] + client.set_proxy_auth proxy[:user], proxy[:password] + end + end + + def configure_ssl(ssl) + ssl_config = client.ssl_config + + ssl_config.add_trust_ca ssl[:ca_file] if ssl[:ca_file] + ssl_config.add_trust_ca ssl[:ca_path] if ssl[:ca_path] + ssl_config.cert_store = ssl[:cert_store] if ssl[:cert_store] + ssl_config.client_cert = ssl[:client_cert] if ssl[:client_cert] + ssl_config.client_key = ssl[:client_key] if ssl[:client_key] + ssl_config.verify_depth = ssl[:verify_depth] if ssl[:verify_depth] + ssl_config.verify_mode = ssl_verify_mode(ssl) + end + + def configure_timeouts(req) + if req[:timeout] + client.connect_timeout = req[:timeout] + client.receive_timeout = req[:timeout] + client.send_timeout = req[:timeout] + end + + if req[:open_timeout] + client.connect_timeout = req[:open_timeout] + client.send_timeout = req[:open_timeout] + end + end + + def ssl_verify_mode(ssl) + ssl[:verify_mode] || begin + if ssl.fetch(:verify, true) + OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT + else + OpenSSL::SSL::VERIFY_NONE + end + end + end + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/adapter/net_http.rb b/3rdparty/modules/aviator/feature/faraday/adapter/net_http.rb new file mode 100644 index 000000000..449388a7f --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/adapter/net_http.rb @@ -0,0 +1,124 @@ +begin + require 'net/https' +rescue LoadError + warn "Warning: no such file to load -- net/https. Make sure openssl is installed if you want ssl support" + require 'net/http' +end +require 'zlib' + +module Faraday + class Adapter + class NetHttp < Faraday::Adapter + NET_HTTP_EXCEPTIONS = [ + EOFError, + Errno::ECONNABORTED, + Errno::ECONNREFUSED, + Errno::ECONNRESET, + Errno::EHOSTUNREACH, + Errno::EINVAL, + Errno::ENETUNREACH, + Net::HTTPBadResponse, + Net::HTTPHeaderSyntaxError, + Net::ProtocolError, + SocketError, + Zlib::GzipFile::Error, + ] + + NET_HTTP_EXCEPTIONS << OpenSSL::SSL::SSLError if defined?(OpenSSL) + + def call(env) + super + http = net_http_connection(env) + configure_ssl(http, env[:ssl]) if env[:url].scheme == 'https' and env[:ssl] + + req = env[:request] + http.read_timeout = http.open_timeout = req[:timeout] if req[:timeout] + http.open_timeout = req[:open_timeout] if req[:open_timeout] + + begin + http_response = perform_request(http, env) + rescue *NET_HTTP_EXCEPTIONS => err + if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err + raise Faraday::SSLError, err + else + raise Error::ConnectionFailed, err + end + end + + save_response(env, http_response.code.to_i, http_response.body || '') do |response_headers| + http_response.each_header do |key, value| + response_headers[key] = value + end + end + + @app.call env + rescue Timeout::Error => err + raise Faraday::Error::TimeoutError, err + end + + def create_request(env) + request = Net::HTTPGenericRequest.new \ + env[:method].to_s.upcase, # request method + !!env[:body], # is there request body + :head != env[:method], # is there response body + env[:url].request_uri, # request uri path + env[:request_headers] # request headers + + if env[:body].respond_to?(:read) + request.body_stream = env[:body] + else + request.body = env[:body] + end + request + end + + def perform_request(http, env) + if :get == env[:method] and !env[:body] + # prefer `get` to `request` because the former handles gzip (ruby 1.9) + http.get env[:url].request_uri, env[:request_headers] + else + http.request create_request(env) + end + end + + def net_http_connection(env) + if proxy = env[:request][:proxy] + Net::HTTP::Proxy(proxy[:uri].host, proxy[:uri].port, proxy[:user], proxy[:password]) + else + Net::HTTP + end.new(env[:url].host, env[:url].port) + end + + def configure_ssl(http, ssl) + http.use_ssl = true + http.verify_mode = ssl_verify_mode(ssl) + http.cert_store = ssl_cert_store(ssl) + + http.cert = ssl[:client_cert] if ssl[:client_cert] + http.key = ssl[:client_key] if ssl[:client_key] + http.ca_file = ssl[:ca_file] if ssl[:ca_file] + http.ca_path = ssl[:ca_path] if ssl[:ca_path] + http.verify_depth = ssl[:verify_depth] if ssl[:verify_depth] + http.ssl_version = ssl[:version] if ssl[:version] + end + + def ssl_cert_store(ssl) + return ssl[:cert_store] if ssl[:cert_store] + # Use the default cert store by default, i.e. system ca certs + cert_store = OpenSSL::X509::Store.new + cert_store.set_default_paths + cert_store + end + + def ssl_verify_mode(ssl) + ssl[:verify_mode] || begin + if ssl.fetch(:verify, true) + OpenSSL::SSL::VERIFY_PEER + else + OpenSSL::SSL::VERIFY_NONE + end + end + end + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/adapter/net_http_persistent.rb b/3rdparty/modules/aviator/feature/faraday/adapter/net_http_persistent.rb new file mode 100644 index 000000000..e0cc9587e --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/adapter/net_http_persistent.rb @@ -0,0 +1,47 @@ +# Rely on autoloading instead of explicit require; helps avoid the "already +# initialized constant" warning on Ruby 1.8.7 when NetHttp is refereced below. +# require 'faraday/adapter/net_http' + +module Faraday + class Adapter + # Experimental adapter for net-http-persistent + class NetHttpPersistent < NetHttp + dependency 'net/http/persistent' + + def net_http_connection(env) + if proxy = env[:request][:proxy] + proxy_uri = ::URI::HTTP === proxy[:uri] ? proxy[:uri].dup : ::URI.parse(proxy[:uri].to_s) + proxy_uri.user = proxy_uri.password = nil + # awful patch for net-http-persistent 2.8 not unescaping user/password + (class << proxy_uri; self; end).class_eval do + define_method(:user) { proxy[:user] } + define_method(:password) { proxy[:password] } + end if proxy[:user] + end + Net::HTTP::Persistent.new 'Faraday', proxy_uri + end + + def perform_request(http, env) + http.request env[:url], create_request(env) + rescue Net::HTTP::Persistent::Error => error + if error.message.include? 'Timeout' + raise Faraday::Error::TimeoutError, error + elsif error.message.include? 'connection refused' + raise Faraday::Error::ConnectionFailed, error + else + raise + end + end + + def configure_ssl(http, ssl) + http.verify_mode = ssl_verify_mode(ssl) + http.cert_store = ssl_cert_store(ssl) + + http.certificate = ssl[:client_cert] if ssl[:client_cert] + http.private_key = ssl[:client_key] if ssl[:client_key] + http.ca_file = ssl[:ca_file] if ssl[:ca_file] + http.ssl_version = ssl[:version] if ssl[:version] + end + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/adapter/patron.rb b/3rdparty/modules/aviator/feature/faraday/adapter/patron.rb new file mode 100644 index 000000000..cf2d37fbe --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/adapter/patron.rb @@ -0,0 +1,72 @@ +module Faraday + class Adapter + class Patron < Faraday::Adapter + dependency 'patron' + + def initialize(app, &block) + super(app) + @block = block + end + + def call(env) + super + + # TODO: support streaming requests + env[:body] = env[:body].read if env[:body].respond_to? :read + + session = @session ||= create_session + + if req = env[:request] + session.timeout = session.connect_timeout = req[:timeout] if req[:timeout] + session.connect_timeout = req[:open_timeout] if req[:open_timeout] + + if proxy = req[:proxy] + proxy_uri = proxy[:uri].dup + proxy_uri.user = proxy[:user] && Utils.escape(proxy[:user]).gsub('+', '%20') + proxy_uri.password = proxy[:password] && Utils.escape(proxy[:password]).gsub('+', '%20') + session.proxy = proxy_uri.to_s + end + end + + response = begin + data = env[:body] ? env[:body].to_s : nil + session.request(env[:method], env[:url].to_s, env[:request_headers], :data => data) + rescue Errno::ECONNREFUSED, ::Patron::ConnectionFailed + raise Error::ConnectionFailed, $! + end + + save_response(env, response.status, response.body, response.headers) + + @app.call env + rescue ::Patron::TimeoutError => err + if err.message == "Connection time-out" + raise Faraday::Error::ConnectionFailed, err + else + raise Faraday::Error::TimeoutError, err + end + rescue ::Patron::Error => err + if err.message.include?("code 407") + raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "} + else + raise Error::ConnectionFailed, err + end + end + + if loaded? && defined?(::Patron::Request::VALID_ACTIONS) + # HAX: helps but doesn't work completely + # https://github.com/toland/patron/issues/34 + ::Patron::Request::VALID_ACTIONS.tap do |actions| + actions << :patch unless actions.include? :patch + actions << :options unless actions.include? :options + end + end + + def create_session + session = ::Patron::Session.new + session.insecure = true + @block.call(session) if @block + session + end + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/adapter/rack.rb b/3rdparty/modules/aviator/feature/faraday/adapter/rack.rb new file mode 100644 index 000000000..0d2146487 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/adapter/rack.rb @@ -0,0 +1,58 @@ +module Faraday + class Adapter + # Sends requests to a Rack app. + # + # Examples + # + # class MyRackApp + # def call(env) + # [200, {'Content-Type' => 'text/html'}, ["hello world"]] + # end + # end + # + # Faraday.new do |conn| + # conn.adapter :rack, MyRackApp.new + # end + class Rack < Faraday::Adapter + dependency 'rack/test' + + # not prefixed with "HTTP_" + SPECIAL_HEADERS = %w[ CONTENT_LENGTH CONTENT_TYPE ] + + def initialize(faraday_app, rack_app) + super(faraday_app) + mock_session = ::Rack::MockSession.new(rack_app) + @session = ::Rack::Test::Session.new(mock_session) + end + + def call(env) + super + rack_env = { + :method => env[:method], + :input => env[:body].respond_to?(:read) ? env[:body].read : env[:body], + 'rack.url_scheme' => env[:url].scheme + } + + env[:request_headers].each do |name, value| + name = name.upcase.tr('-', '_') + name = "HTTP_#{name}" unless SPECIAL_HEADERS.include? name + rack_env[name] = value + end if env[:request_headers] + + timeout = env[:request][:timeout] || env[:request][:open_timeout] + response = if timeout + Timer.timeout(timeout, Faraday::Error::TimeoutError) { execute_request(env, rack_env) } + else + execute_request(env, rack_env) + end + + save_response(env, response.status, response.body, response.headers) + @app.call env + end + + def execute_request(env, rack_env) + @session.request(env[:url].to_s, rack_env) + end + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/adapter/test.rb b/3rdparty/modules/aviator/feature/faraday/adapter/test.rb new file mode 100644 index 000000000..9a345758e --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/adapter/test.rb @@ -0,0 +1,162 @@ +module Faraday + class Adapter + # test = Faraday::Connection.new do + # use Faraday::Adapter::Test do |stub| + # stub.get '/nigiri/sake.json' do + # [200, {}, 'hi world'] + # end + # end + # end + # + # resp = test.get '/nigiri/sake.json' + # resp.body # => 'hi world' + # + class Test < Faraday::Adapter + attr_accessor :stubs + + class Stubs + class NotFound < StandardError + end + + def initialize + # {:get => [Stub, Stub]} + @stack, @consumed = {}, {} + yield(self) if block_given? + end + + def empty? + @stack.empty? + end + + def match(request_method, path, headers, body) + return false if !@stack.key?(request_method) + stack = @stack[request_method] + consumed = (@consumed[request_method] ||= []) + + if stub = matches?(stack, path, headers, body) + consumed << stack.delete(stub) + stub + else + matches?(consumed, path, headers, body) + end + end + + def get(path, headers = {}, &block) + new_stub(:get, path, headers, &block) + end + + def head(path, headers = {}, &block) + new_stub(:head, path, headers, &block) + end + + def post(path, body=nil, headers = {}, &block) + new_stub(:post, path, headers, body, &block) + end + + def put(path, body=nil, headers = {}, &block) + new_stub(:put, path, headers, body, &block) + end + + def patch(path, body=nil, headers = {}, &block) + new_stub(:patch, path, headers, body, &block) + end + + def delete(path, headers = {}, &block) + new_stub(:delete, path, headers, &block) + end + + def options(path, headers = {}, &block) + new_stub(:options, path, headers, &block) + end + + # Raises an error if any of the stubbed calls have not been made. + def verify_stubbed_calls + failed_stubs = [] + @stack.each do |method, stubs| + unless stubs.size == 0 + failed_stubs.concat(stubs.map {|stub| + "Expected #{method} #{stub}." + }) + end + end + raise failed_stubs.join(" ") unless failed_stubs.size == 0 + end + + protected + + def new_stub(request_method, path, headers = {}, body=nil, &block) + normalized_path = Faraday::Utils.normalize_path(path) + (@stack[request_method] ||= []) << Stub.new(normalized_path, headers, body, block) + end + + def matches?(stack, path, headers, body) + stack.detect { |stub| stub.matches?(path, headers, body) } + end + end + + class Stub < Struct.new(:path, :params, :headers, :body, :block) + def initialize(full, headers, body, block) + path, query = full.split('?') + params = query ? + Faraday::Utils.parse_nested_query(query) : + {} + super(path, params, headers, body, block) + end + + def matches?(request_uri, request_headers, request_body) + request_path, request_query = request_uri.split('?') + request_params = request_query ? + Faraday::Utils.parse_nested_query(request_query) : + {} + request_path == path && + params_match?(request_params) && + (body.to_s.size.zero? || request_body == body) && + headers_match?(request_headers) + end + + def params_match?(request_params) + params.keys.all? do |key| + request_params[key] == params[key] + end + end + + def headers_match?(request_headers) + headers.keys.all? do |key| + request_headers[key] == headers[key] + end + end + + def to_s + "#{path} #{body}" + end + end + + def initialize(app, stubs=nil, &block) + super(app) + @stubs = stubs || Stubs.new + configure(&block) if block + end + + def configure + yield(stubs) + end + + def call(env) + super + normalized_path = Faraday::Utils.normalize_path(env[:url]) + params_encoder = env.request.params_encoder || Faraday::Utils.default_params_encoder + + if stub = stubs.match(env[:method], normalized_path, env.request_headers, env[:body]) + env[:params] = (query = env[:url].query) ? + params_encoder.decode(query) : + {} + status, headers, body = stub.block.call(env) + save_response(env, status, body, headers) + else + raise Stubs::NotFound, "no stubbed request for #{env[:method]} #{normalized_path} #{env[:body]}" + end + @app.call(env) + end + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/adapter/typhoeus.rb b/3rdparty/modules/aviator/feature/faraday/adapter/typhoeus.rb new file mode 100644 index 000000000..69b6a5139 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/adapter/typhoeus.rb @@ -0,0 +1,123 @@ +module Faraday + class Adapter + class Typhoeus < Faraday::Adapter + self.supports_parallel = true + + def self.setup_parallel_manager(options = {}) + options.empty? ? ::Typhoeus::Hydra.hydra : ::Typhoeus::Hydra.new(options) + end + + dependency 'typhoeus' + + def call(env) + super + perform_request env + @app.call env + end + + def perform_request(env) + read_body env + + hydra = env[:parallel_manager] || self.class.setup_parallel_manager + hydra.queue request(env) + hydra.run unless parallel?(env) + rescue Errno::ECONNREFUSED + raise Error::ConnectionFailed, $! + end + + # TODO: support streaming requests + def read_body(env) + env[:body] = env[:body].read if env[:body].respond_to? :read + end + + def request(env) + method = env[:method] + # For some reason, prevents Typhoeus from using "100-continue". + # We want this because Webrick 1.3.1 can't seem to handle it w/ PUT. + method = method.to_s.upcase if method == :put + + req = ::Typhoeus::Request.new env[:url].to_s, + :method => method, + :body => env[:body], + :headers => env[:request_headers], + :disable_ssl_peer_verification => (env[:ssl] && env[:ssl].disable?) + + configure_ssl req, env + configure_proxy req, env + configure_timeout req, env + configure_socket req, env + + req.on_complete do |resp| + if resp.timed_out? + if parallel?(env) + # TODO: error callback in async mode + else + raise Faraday::Error::TimeoutError, "request timed out" + end + end + + case resp.curl_return_code + when 0 + # everything OK + when 7 + raise Error::ConnectionFailed, resp.curl_error_message + when 60 + raise Faraday::SSLError, resp.curl_error_message + else + raise Error::ClientError, resp.curl_error_message + end + + save_response(env, resp.code, resp.body) do |response_headers| + response_headers.parse resp.headers + end + # in async mode, :response is initialized at this point + env[:response].finish(env) if parallel?(env) + end + + req + end + + def configure_ssl(req, env) + ssl = env[:ssl] + + req.ssl_version = ssl[:version] if ssl[:version] + req.ssl_cert = ssl[:client_cert] if ssl[:client_cert] + req.ssl_key = ssl[:client_key] if ssl[:client_key] + req.ssl_cacert = ssl[:ca_file] if ssl[:ca_file] + req.ssl_capath = ssl[:ca_path] if ssl[:ca_path] + end + + def configure_proxy(req, env) + proxy = request_options(env)[:proxy] + return unless proxy + + req.proxy = "#{proxy[:uri].host}:#{proxy[:uri].port}" + + if proxy[:user] && proxy[:password] + req.proxy_username = proxy[:user] + req.proxy_password = proxy[:password] + end + end + + def configure_timeout(req, env) + env_req = request_options(env) + req.timeout = req.connect_timeout = (env_req[:timeout] * 1000) if env_req[:timeout] + req.connect_timeout = (env_req[:open_timeout] * 1000) if env_req[:open_timeout] + end + + def configure_socket(req, env) + if bind = request_options(env)[:bind] + req.interface = bind[:host] + end + end + + def request_options(env) + env[:request] + end + + def parallel?(env) + !!env[:parallel_manager] + end + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/autoload.rb b/3rdparty/modules/aviator/feature/faraday/autoload.rb new file mode 100644 index 000000000..ec413ff84 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/autoload.rb @@ -0,0 +1,85 @@ +module Faraday + # Internal: Adds the ability for other modules to manage autoloadable + # constants. + module AutoloadHelper + # Internal: Registers the constants to be auto loaded. + # + # prefix - The String require prefix. If the path is inside Faraday, then + # it will be prefixed with the root path of this loaded Faraday + # version. + # options - Hash of Symbol => String library names. + # + # Examples. + # + # Faraday.autoload_all 'faraday/foo', + # :Bar => 'bar' + # + # # requires faraday/foo/bar to load Faraday::Bar. + # Faraday::Bar + # + # + # Returns nothing. + def autoload_all(prefix, options) + if prefix =~ /^faraday(\/|$)/i + prefix = File.join(Faraday.root_path, prefix) + end + options.each do |const_name, path| + autoload const_name, File.join(prefix, path) + end + end + + # Internal: Loads each autoloaded constant. If thread safety is a concern, + # wrap this in a Mutex. + # + # Returns nothing. + def load_autoloaded_constants + constants.each do |const| + const_get(const) if autoload?(const) + end + end + + # Internal: Filters the module's contents with those that have been already + # autoloaded. + # + # Returns an Array of Class/Module objects. + def all_loaded_constants + constants.map { |c| const_get(c) }. + select { |a| a.respond_to?(:loaded?) && a.loaded? } + end + end + + class Adapter + extend AutoloadHelper + autoload_all 'faraday/adapter', + :NetHttp => 'net_http', + :NetHttpPersistent => 'net_http_persistent', + :Typhoeus => 'typhoeus', + :EMSynchrony => 'em_synchrony', + :EMHttp => 'em_http', + :Patron => 'patron', + :Excon => 'excon', + :Test => 'test', + :Rack => 'rack', + :HTTPClient => 'httpclient' + end + + class Request + extend AutoloadHelper + autoload_all 'faraday/request', + :UrlEncoded => 'url_encoded', + :Multipart => 'multipart', + :Retry => 'retry', + :Timeout => 'timeout', + :Authorization => 'authorization', + :BasicAuthentication => 'basic_authentication', + :TokenAuthentication => 'token_authentication', + :Instrumentation => 'instrumentation' + end + + class Response + extend AutoloadHelper + autoload_all 'faraday/response', + :RaiseError => 'raise_error', + :Logger => 'logger' + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/connection.rb b/3rdparty/modules/aviator/feature/faraday/connection.rb new file mode 100644 index 000000000..1e408e2c2 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/connection.rb @@ -0,0 +1,432 @@ +module Faraday + # Public: Connection objects manage the default properties and the middleware + # stack for fulfilling an HTTP request. + # + # Examples + # + # conn = Faraday::Connection.new 'http://sushi.com' + # + # # GET http://sushi.com/nigiri + # conn.get 'nigiri' + # # => # + # + class Connection + # A Set of allowed HTTP verbs. + METHODS = Set.new [:get, :post, :put, :delete, :head, :patch, :options] + + # Public: Returns a Hash of URI query unencoded key/value pairs. + attr_reader :params + + # Public: Returns a Hash of unencoded HTTP header key/value pairs. + attr_reader :headers + + # Public: Returns a URI with the prefix used for all requests from this + # Connection. This includes a default host name, scheme, port, and path. + attr_reader :url_prefix + + # Public: Returns the Faraday::Builder for this Connection. + attr_reader :builder + + # Public: Returns a Hash of the request options. + attr_reader :options + + # Public: Returns a Hash of the SSL options. + attr_reader :ssl + + # Public: Returns the parallel manager for this Connection. + attr_reader :parallel_manager + + # Public: Sets the default parallel manager for this connection. + attr_writer :default_parallel_manager + + # Public: Initializes a new Faraday::Connection. + # + # url - URI or String base URL to use as a prefix for all + # requests (optional). + # options - Hash or Faraday::ConnectionOptions. + # :url - URI or String base URL (default: "http:/"). + # :params - Hash of URI query unencoded key/value pairs. + # :headers - Hash of unencoded HTTP header key/value pairs. + # :request - Hash of request options. + # :ssl - Hash of SSL options. + # :proxy - URI, String or Hash of HTTP proxy options + # (default: "http_proxy" environment variable). + # :uri - URI or String + # :user - String (optional) + # :password - String (optional) + def initialize(url = nil, options = nil) + if url.is_a?(Hash) + options = ConnectionOptions.from(url) + url = options.url + else + options = ConnectionOptions.from(options) + end + + @parallel_manager = nil + @headers = Utils::Headers.new + @params = Utils::ParamsHash.new + @options = options.request + @ssl = options.ssl + @default_parallel_manager = options.parallel_manager + + @builder = options.builder || begin + # pass an empty block to Builder so it doesn't assume default middleware + options.new_builder(block_given? ? Proc.new { |b| } : nil) + end + + self.url_prefix = url || 'http:/' + + @params.update(options.params) if options.params + @headers.update(options.headers) if options.headers + + @proxy = nil + proxy(options.fetch(:proxy) { + uri = ENV['http_proxy'] + if uri && !uri.empty? + uri = 'http://' + uri if uri !~ /^http/i + uri + end + }) + + yield(self) if block_given? + + @headers[:user_agent] ||= "Faraday v#{VERSION}" + end + + # Public: Sets the Hash of URI query unencoded key/value pairs. + def params=(hash) + @params.replace hash + end + + # Public: Sets the Hash of unencoded HTTP header key/value pairs. + def headers=(hash) + @headers.replace hash + end + + extend Forwardable + + def_delegators :builder, :build, :use, :request, :response, :adapter, :app + + # Public: Makes an HTTP request without a body. + # + # url - The optional String base URL to use as a prefix for all + # requests. Can also be the options Hash. + # params - Hash of URI query unencoded key/value pairs. + # headers - Hash of unencoded HTTP header key/value pairs. + # + # Examples + # + # conn.get '/items', {:page => 1}, :accept => 'application/json' + # conn.head '/items/1' + # + # # ElasticSearch example sending a body with GET. + # conn.get '/twitter/tweet/_search' do |req| + # req.headers[:content_type] = 'application/json' + # req.params[:routing] = 'kimchy' + # req.body = JSON.generate(:query => {...}) + # end + # + # Yields a Faraday::Response for further request customizations. + # Returns a Faraday::Response. + # + # Signature + # + # (url = nil, params = nil, headers = nil) + # + # verb - An HTTP verb: get, head, or delete. + %w[get head delete].each do |method| + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{method}(url = nil, params = nil, headers = nil) + run_request(:#{method}, url, nil, headers) { |request| + request.params.update(params) if params + yield(request) if block_given? + } + end + RUBY + end + + # Public: Makes an HTTP request with a body. + # + # url - The optional String base URL to use as a prefix for all + # requests. Can also be the options Hash. + # body - The String body for the request. + # headers - Hash of unencoded HTTP header key/value pairs. + # + # Examples + # + # conn.post '/items', data, :content_type => 'application/json' + # + # # Simple ElasticSearch indexing sample. + # conn.post '/twitter/tweet' do |req| + # req.headers[:content_type] = 'application/json' + # req.params[:routing] = 'kimchy' + # req.body = JSON.generate(:user => 'kimchy', ...) + # end + # + # Yields a Faraday::Response for further request customizations. + # Returns a Faraday::Response. + # + # Signature + # + # (url = nil, body = nil, headers = nil) + # + # verb - An HTTP verb: post, put, or patch. + %w[post put patch].each do |method| + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{method}(url = nil, body = nil, headers = nil, &block) + run_request(:#{method}, url, body, headers, &block) + end + RUBY + end + + # Public: Sets up the Authorization header with these credentials, encoded + # with base64. + # + # login - The authentication login. + # pass - The authentication password. + # + # Examples + # + # conn.basic_auth 'Aladdin', 'open sesame' + # conn.headers['Authorization'] + # # => "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" + # + # Returns nothing. + def basic_auth(login, pass) + set_authorization_header(:basic_auth, login, pass) + end + + # Public: Sets up the Authorization header with the given token. + # + # token - The String token. + # options - Optional Hash of extra token options. + # + # Examples + # + # conn.token_auth 'abcdef', :foo => 'bar' + # conn.headers['Authorization'] + # # => "Token token=\"abcdef\", + # foo=\"bar\"" + # + # Returns nothing. + def token_auth(token, options = nil) + set_authorization_header(:token_auth, token, options) + end + + # Public: Sets up a custom Authorization header. + # + # type - The String authorization type. + # token - The String or Hash token. A String value is taken literally, and + # a Hash is encoded into comma separated key/value pairs. + # + # Examples + # + # conn.authorization :Bearer, 'mF_9.B5f-4.1JqM' + # conn.headers['Authorization'] + # # => "Bearer mF_9.B5f-4.1JqM" + # + # conn.authorization :Token, :token => 'abcdef', :foo => 'bar' + # conn.headers['Authorization'] + # # => "Token token=\"abcdef\", + # foo=\"bar\"" + # + # Returns nothing. + def authorization(type, token) + set_authorization_header(:authorization, type, token) + end + + # Internal: Traverse the middleware stack in search of a + # parallel-capable adapter. + # + # Yields in case of not found. + # + # Returns a parallel manager or nil if not found. + def default_parallel_manager + @default_parallel_manager ||= begin + handler = @builder.handlers.detect do |h| + h.klass.respond_to?(:supports_parallel?) and h.klass.supports_parallel? + end + + if handler + handler.klass.setup_parallel_manager + elsif block_given? + yield + end + end + end + + # Public: Determine if this Faraday::Connection can make parallel requests. + # + # Returns true or false. + def in_parallel? + !!@parallel_manager + end + + # Public: Sets up the parallel manager to make a set of requests. + # + # manager - The parallel manager that this Connection's Adapter uses. + # + # Yields a block to execute multiple requests. + # Returns nothing. + def in_parallel(manager = nil) + @parallel_manager = manager || default_parallel_manager { + warn "Warning: `in_parallel` called but no parallel-capable adapter on Faraday stack" + warn caller[2,10].join("\n") + nil + } + yield + @parallel_manager && @parallel_manager.run + ensure + @parallel_manager = nil + end + + # Public: Gets or Sets the Hash proxy options. + def proxy(arg = nil) + return @proxy if arg.nil? + @proxy = ProxyOptions.from(arg) + end + + def_delegators :url_prefix, :scheme, :scheme=, :host, :host=, :port, :port= + def_delegator :url_prefix, :path, :path_prefix + + # Public: Parses the giving url with URI and stores the individual + # components in this connection. These components serve as defaults for + # requests made by this connection. + # + # url - A String or URI. + # + # Examples + # + # conn = Faraday::Connection.new { ... } + # conn.url_prefix = "https://sushi.com/api" + # conn.scheme # => https + # conn.path_prefix # => "/api" + # + # conn.get("nigiri?page=2") # accesses https://sushi.com/api/nigiri + # + # Returns the parsed URI from teh given input.. + def url_prefix=(url, encoder = nil) + uri = @url_prefix = Utils.URI(url) + self.path_prefix = uri.path + + params.merge_query(uri.query, encoder) + uri.query = nil + + with_uri_credentials(uri) do |user, password| + basic_auth user, password + uri.user = uri.password = nil + end + + uri + end + + # Public: Sets the path prefix and ensures that it always has a leading + # slash. + # + # value - A String. + # + # Returns the new String path prefix. + def path_prefix=(value) + url_prefix.path = if value + value = '/' + value unless value[0,1] == '/' + value + end + end + + # Public: Takes a relative url for a request and combines it with the defaults + # set on the connection instance. + # + # conn = Faraday::Connection.new { ... } + # conn.url_prefix = "https://sushi.com/api?token=abc" + # conn.scheme # => https + # conn.path_prefix # => "/api" + # + # conn.build_url("nigiri?page=2") # => https://sushi.com/api/nigiri?token=abc&page=2 + # conn.build_url("nigiri", :page => 2) # => https://sushi.com/api/nigiri?token=abc&page=2 + # + def build_url(url = nil, extra_params = nil) + uri = build_exclusive_url(url) + + query_values = params.dup.merge_query(uri.query, options.params_encoder) + query_values.update extra_params if extra_params + uri.query = query_values.empty? ? nil : query_values.to_query(options.params_encoder) + + uri + end + + # Builds and runs the Faraday::Request. + # + # method - The Symbol HTTP method. + # url - The String or URI to access. + # body - The String body + # headers - Hash of unencoded HTTP header key/value pairs. + # + # Returns a Faraday::Response. + def run_request(method, url, body, headers) + if !METHODS.include?(method) + raise ArgumentError, "unknown http method: #{method}" + end + + request = build_request(method) do |req| + req.url(url) if url + req.headers.update(headers) if headers + req.body = body if body + yield(req) if block_given? + end + + builder.build_response(self, request) + end + + # Creates and configures the request object. + # + # Returns the new Request. + def build_request(method) + Request.create(method) do |req| + req.params = self.params.dup + req.headers = self.headers.dup + req.options = self.options.merge(:proxy => self.proxy) + yield(req) if block_given? + end + end + + # Internal: Build an absolute URL based on url_prefix. + # + # url - A String or URI-like object + # params - A Faraday::Utils::ParamsHash to replace the query values + # of the resulting url (default: nil). + # + # Returns the resulting URI instance. + def build_exclusive_url(url = nil, params = nil) + url = nil if url.respond_to?(:empty?) and url.empty? + base = url_prefix + if url and base.path and base.path !~ /\/$/ + base = base.dup + base.path = base.path + '/' # ensure trailing slash + end + uri = url ? base + url : base + uri.query = params.to_query(options.params_encoder) if params + uri.query = nil if uri.query and uri.query.empty? + uri + end + + # Internal: Creates a duplicate of this Faraday::Connection. + # + # Returns a Faraday::Connection. + def dup + self.class.new(build_exclusive_url, :headers => headers.dup, :params => params.dup, :builder => builder.dup, :ssl => ssl.dup) + end + + # Internal: Yields username and password extracted from a URI if they both exist. + def with_uri_credentials(uri) + if uri.user and uri.password + yield(Utils.unescape(uri.user), Utils.unescape(uri.password)) + end + end + + def set_authorization_header(header_type, *args) + header = Faraday::Request.lookup_middleware(header_type). + header(*args) + headers[Faraday::Request::Authorization::KEY] = header + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/error.rb b/3rdparty/modules/aviator/feature/faraday/error.rb new file mode 100644 index 000000000..17712309d --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/error.rb @@ -0,0 +1,53 @@ +module Faraday + class Error < StandardError; end + class MissingDependency < Error; end + + class ClientError < Error + attr_reader :response + + def initialize(ex, response = nil) + @wrapped_exception = nil + @response = response + + if ex.respond_to?(:backtrace) + super(ex.message) + @wrapped_exception = ex + elsif ex.respond_to?(:each_key) + super("the server responded with status #{ex[:status]}") + @response = ex + else + super(ex.to_s) + end + end + + def backtrace + if @wrapped_exception + @wrapped_exception.backtrace + else + super + end + end + + def inspect + %(#<#{self.class}>) + end + end + + class ConnectionFailed < ClientError; end + class ResourceNotFound < ClientError; end + class ParsingError < ClientError; end + + class TimeoutError < ClientError + def initialize(ex = nil) + super(ex || "timeout") + end + end + + class SSLError < ClientError + end + + [:MissingDependency, :ClientError, :ConnectionFailed, :ResourceNotFound, + :ParsingError, :TimeoutError, :SSLError].each do |const| + Error.const_set(const, Faraday.const_get(const)) + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/middleware.rb b/3rdparty/modules/aviator/feature/faraday/middleware.rb new file mode 100644 index 000000000..c45d51ade --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/middleware.rb @@ -0,0 +1,37 @@ +module Faraday + class Middleware + extend MiddlewareRegistry + + class << self + attr_accessor :load_error + private :load_error= + end + + self.load_error = nil + + # Executes a block which should try to require and reference dependent libraries + def self.dependency(lib = nil) + lib ? require(lib) : yield + rescue LoadError, NameError => error + self.load_error = error + end + + def self.new(*) + raise "missing dependency for #{self}: #{load_error.message}" unless loaded? + super + end + + def self.loaded? + load_error.nil? + end + + def self.inherited(subclass) + super + subclass.send(:load_error=, self.load_error) + end + + def initialize(app = nil) + @app = app + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/options.rb b/3rdparty/modules/aviator/feature/faraday/options.rb new file mode 100644 index 000000000..c1b36f60f --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/options.rb @@ -0,0 +1,350 @@ +module Faraday + # Subclasses Struct with some special helpers for converting from a Hash to + # a Struct. + class Options < Struct + # Public + def self.from(value) + value ? new.update(value) : new + end + + # Public + def each + return to_enum(:each) unless block_given? + members.each do |key| + yield(key.to_sym, send(key)) + end + end + + # Public + def update(obj) + obj.each do |key, value| + if sub_options = self.class.options_for(key) + value = sub_options.from(value) if value + elsif Hash === value + hash = {} + value.each do |hash_key, hash_value| + hash[hash_key] = hash_value + end + value = hash + end + + self.send("#{key}=", value) unless value.nil? + end + self + end + + alias merge! update + + # Public + def delete(key) + value = send(key) + send("#{key}=", nil) + value + end + + # Public + def clear + members.each { |member| delete(member) } + end + + # Public + def merge(value) + dup.update(value) + end + + # Public + def fetch(key, *args) + unless symbolized_key_set.include?(key.to_sym) + key_setter = "#{key}=" + if args.size > 0 + send(key_setter, args.first) + elsif block_given? + send(key_setter, Proc.new.call(key)) + else + raise self.class.fetch_error_class, "key not found: #{key.inspect}" + end + end + send(key) + end + + # Public + def values_at(*keys) + keys.map { |key| send(key) } + end + + # Public + def keys + members.reject { |member| send(member).nil? } + end + + # Public + def empty? + keys.empty? + end + + # Public + def each_key + return to_enum(:each_key) unless block_given? + keys.each do |key| + yield(key) + end + end + + # Public + def key?(key) + keys.include?(key) + end + + alias has_key? key? + + # Public + def each_value + return to_enum(:each_value) unless block_given? + values.each do |value| + yield(value) + end + end + + # Public + def value?(value) + values.include?(value) + end + + alias has_value? value? + + # Public + def to_hash + hash = {} + members.each do |key| + value = send(key) + hash[key.to_sym] = value unless value.nil? + end + hash + end + + # Internal + def inspect + values = [] + members.each do |member| + value = send(member) + values << "#{member}=#{value.inspect}" if value + end + values = values.empty? ? ' (empty)' : (' ' << values.join(", ")) + + %(#<#{self.class}#{values}>) + end + + # Internal + def self.options(mapping) + attribute_options.update(mapping) + end + + # Internal + def self.options_for(key) + attribute_options[key] + end + + # Internal + def self.attribute_options + @attribute_options ||= {} + end + + def self.memoized(key) + memoized_attributes[key.to_sym] = Proc.new + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{key}() self[:#{key}]; end + RUBY + end + + def self.memoized_attributes + @memoized_attributes ||= {} + end + + def [](key) + key = key.to_sym + if method = self.class.memoized_attributes[key] + super(key) || (self[key] = instance_eval(&method)) + else + super + end + end + + def symbolized_key_set + @symbolized_key_set ||= Set.new(keys.map { |k| k.to_sym }) + end + + def self.inherited(subclass) + super + subclass.attribute_options.update(attribute_options) + subclass.memoized_attributes.update(memoized_attributes) + end + + def self.fetch_error_class + @fetch_error_class ||= if Object.const_defined?(:KeyError) + ::KeyError + else + ::IndexError + end + end + end + + class RequestOptions < Options.new(:params_encoder, :proxy, :bind, + :timeout, :open_timeout, :boundary, + :oauth) + + def []=(key, value) + if key && key.to_sym == :proxy + super(key, value ? ProxyOptions.from(value) : nil) + else + super(key, value) + end + end + end + + class SSLOptions < Options.new(:verify, :ca_file, :ca_path, :verify_mode, + :cert_store, :client_cert, :client_key, :certificate, :private_key, :verify_depth, :version) + + def verify? + verify != false + end + + def disable? + !verify? + end + end + + class ProxyOptions < Options.new(:uri, :user, :password) + extend Forwardable + def_delegators :uri, :scheme, :scheme=, :host, :host=, :port, :port=, :path, :path= + + def self.from(value) + case value + when String + value = {:uri => Utils.URI(value)} + when URI + value = {:uri => value} + when Hash, Options + if uri = value.delete(:uri) + value[:uri] = Utils.URI(uri) + end + end + super(value) + end + + memoized(:user) { uri.user && Utils.unescape(uri.user) } + memoized(:password) { uri.password && Utils.unescape(uri.password) } + end + + class ConnectionOptions < Options.new(:request, :proxy, :ssl, :builder, :url, + :parallel_manager, :params, :headers, :builder_class) + + options :request => RequestOptions, :ssl => SSLOptions + + memoized(:request) { self.class.options_for(:request).new } + + memoized(:ssl) { self.class.options_for(:ssl).new } + + memoized(:builder_class) { RackBuilder } + + def new_builder(block) + builder_class.new(&block) + end + end + + class Env < Options.new(:method, :body, :url, :request, :request_headers, + :ssl, :parallel_manager, :params, :response, :response_headers, :status) + + ContentLength = 'Content-Length'.freeze + StatusesWithoutBody = Set.new [204, 304] + SuccessfulStatuses = 200..299 + + # A Set of HTTP verbs that typically send a body. If no body is set for + # these requests, the Content-Length header is set to 0. + MethodsWithBodies = Set.new [:post, :put, :patch, :options] + + options :request => RequestOptions, + :request_headers => Utils::Headers, :response_headers => Utils::Headers + + extend Forwardable + + def_delegators :request, :params_encoder + + # Public + def [](key) + if in_member_set?(key) + super(key) + else + custom_members[key] + end + end + + # Public + def []=(key, value) + if in_member_set?(key) + super(key, value) + else + custom_members[key] = value + end + end + + # Public + def success? + SuccessfulStatuses.include?(status) + end + + # Public + def needs_body? + !body && MethodsWithBodies.include?(method) + end + + # Public + def clear_body + request_headers[ContentLength] = '0' + self.body = '' + end + + # Public + def parse_body? + !StatusesWithoutBody.include?(status) + end + + # Public + def parallel? + !!parallel_manager + end + + def inspect + attrs = [nil] + members.each do |mem| + if value = send(mem) + attrs << "@#{mem}=#{value.inspect}" + end + end + if !custom_members.empty? + attrs << "@custom=#{custom_members.inspect}" + end + %(#<#{self.class}#{attrs.join(" ")}>) + end + + # Internal + def custom_members + @custom_members ||= {} + end + + # Internal + if members.first.is_a?(Symbol) + def in_member_set?(key) + self.class.member_set.include?(key.to_sym) + end + else + def in_member_set?(key) + self.class.member_set.include?(key.to_s) + end + end + + # Internal + def self.member_set + @member_set ||= Set.new(members) + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/parameters.rb b/3rdparty/modules/aviator/feature/faraday/parameters.rb new file mode 100644 index 000000000..136c43bca --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/parameters.rb @@ -0,0 +1,193 @@ +module Faraday + module NestedParamsEncoder + ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/ + + def self.escape(s) + return s.to_s.gsub(ESCAPE_RE) { + '%' + $&.unpack('H2' * $&.bytesize).join('%').upcase + }.tr(' ', '+') + end + + def self.unescape(s) + CGI.unescape(s.to_s) + end + + def self.encode(params) + return nil if params == nil + + if !params.is_a?(Array) + if !params.respond_to?(:to_hash) + raise TypeError, + "Can't convert #{params.class} into Hash." + end + params = params.to_hash + params = params.map do |key, value| + key = key.to_s if key.kind_of?(Symbol) + [key, value] + end + # Useful default for OAuth and caching. + # Only to be used for non-Array inputs. Arrays should preserve order. + params.sort! + end + + # Helper lambda + to_query = lambda do |parent, value| + if value.is_a?(Hash) + value = value.map do |key, val| + key = escape(key) + [key, val] + end + value.sort! + buffer = "" + value.each do |key, val| + new_parent = "#{parent}%5B#{key}%5D" + buffer << "#{to_query.call(new_parent, val)}&" + end + return buffer.chop + elsif value.is_a?(Array) + buffer = "" + value.each_with_index do |val, i| + new_parent = "#{parent}%5B%5D" + buffer << "#{to_query.call(new_parent, val)}&" + end + return buffer.chop + else + encoded_value = escape(value) + return "#{parent}=#{encoded_value}" + end + end + + # The params have form [['key1', 'value1'], ['key2', 'value2']]. + buffer = '' + params.each do |parent, value| + encoded_parent = escape(parent) + buffer << "#{to_query.call(encoded_parent, value)}&" + end + return buffer.chop + end + + def self.decode(query) + return nil if query == nil + # Recursive helper lambda + dehash = lambda do |hash| + hash.each do |(key, value)| + if value.kind_of?(Hash) + hash[key] = dehash.call(value) + end + end + # Numeric keys implies an array + if hash != {} && hash.keys.all? { |key| key =~ /^\d+$/ } + hash.sort.inject([]) do |accu, (_, value)| + accu << value; accu + end + else + hash + end + end + + empty_accumulator = {} + return ((query.split('&').map do |pair| + pair.split('=', 2) if pair && !pair.empty? + end).compact.inject(empty_accumulator.dup) do |accu, (key, value)| + key = unescape(key) + if value.kind_of?(String) + value = unescape(value.gsub(/\+/, ' ')) + end + + array_notation = !!(key =~ /\[\]$/) + subkeys = key.split(/[\[\]]+/) + current_hash = accu + for i in 0...(subkeys.size - 1) + subkey = subkeys[i] + current_hash[subkey] = {} unless current_hash[subkey] + current_hash = current_hash[subkey] + end + if array_notation + current_hash[subkeys.last] = [] unless current_hash[subkeys.last] + current_hash[subkeys.last] << value + else + current_hash[subkeys.last] = value + end + accu + end).inject(empty_accumulator.dup) do |accu, (key, value)| + accu[key] = value.kind_of?(Hash) ? dehash.call(value) : value + accu + end + end + end + + module FlatParamsEncoder + ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/ + + def self.escape(s) + return s.to_s.gsub(ESCAPE_RE) { + '%' + $&.unpack('H2' * $&.bytesize).join('%').upcase + }.tr(' ', '+') + end + + def self.unescape(s) + CGI.unescape(s.to_s) + end + + def self.encode(params) + return nil if params == nil + + if !params.is_a?(Array) + if !params.respond_to?(:to_hash) + raise TypeError, + "Can't convert #{params.class} into Hash." + end + params = params.to_hash + params = params.map do |key, value| + key = key.to_s if key.kind_of?(Symbol) + [key, value] + end + # Useful default for OAuth and caching. + # Only to be used for non-Array inputs. Arrays should preserve order. + params.sort! + end + + # The params have form [['key1', 'value1'], ['key2', 'value2']]. + buffer = '' + params.each do |key, value| + encoded_key = escape(key) + value = value.to_s if value == true || value == false + if value == nil + buffer << "#{encoded_key}&" + elsif value.kind_of?(Array) + value.each do |sub_value| + encoded_value = escape(sub_value) + buffer << "#{encoded_key}=#{encoded_value}&" + end + else + encoded_value = escape(value) + buffer << "#{encoded_key}=#{encoded_value}&" + end + end + return buffer.chop + end + + def self.decode(query) + empty_accumulator = {} + return nil if query == nil + split_query = (query.split('&').map do |pair| + pair.split('=', 2) if pair && !pair.empty? + end).compact + return split_query.inject(empty_accumulator.dup) do |accu, pair| + pair[0] = unescape(pair[0]) + pair[1] = true if pair[1].nil? + if pair[1].respond_to?(:to_str) + pair[1] = unescape(pair[1].to_str.gsub(/\+/, " ")) + end + if accu[pair[0]].kind_of?(Array) + accu[pair[0]] << pair[1] + elsif accu[pair[0]] + accu[pair[0]] = [accu[pair[0]], pair[1]] + else + accu[pair[0]] = pair[1] + end + accu + end + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/rack_builder.rb b/3rdparty/modules/aviator/feature/faraday/rack_builder.rb new file mode 100644 index 000000000..204ce41d1 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/rack_builder.rb @@ -0,0 +1,212 @@ +module Faraday + # A Builder that processes requests into responses by passing through an inner + # middleware stack (heavily inspired by Rack). + # + # Faraday::Connection.new(:url => 'http://sushi.com') do |builder| + # builder.request :url_encoded # Faraday::Request::UrlEncoded + # builder.adapter :net_http # Faraday::Adapter::NetHttp + # end + class RackBuilder + attr_accessor :handlers + + # Error raised when trying to modify the stack after calling `lock!` + class StackLocked < RuntimeError; end + + # borrowed from ActiveSupport::Dependencies::Reference & + # ActionDispatch::MiddlewareStack::Middleware + class Handler + @@constants_mutex = Mutex.new + @@constants = Hash.new { |h, k| + value = k.respond_to?(:constantize) ? k.constantize : Object.const_get(k) + @@constants_mutex.synchronize { h[k] = value } + } + + attr_reader :name + + def initialize(klass, *args, &block) + @name = klass.to_s + if klass.respond_to?(:name) + @@constants_mutex.synchronize { @@constants[@name] = klass } + end + @args, @block = args, block + end + + def klass() @@constants[@name] end + def inspect() @name end + + def ==(other) + if other.is_a? Handler + self.name == other.name + elsif other.respond_to? :name + klass == other + else + @name == other.to_s + end + end + + def build(app) + klass.new(app, *@args, &@block) + end + end + + def initialize(handlers = []) + @handlers = handlers + if block_given? + build(&Proc.new) + elsif @handlers.empty? + # default stack, if nothing else is configured + self.request :url_encoded + self.adapter Faraday.default_adapter + end + end + + def build(options = {}) + raise_if_locked + @handlers.clear unless options[:keep] + yield(self) if block_given? + end + + def [](idx) + @handlers[idx] + end + + # Locks the middleware stack to ensure no further modifications are possible. + def lock! + @handlers.freeze + end + + def locked? + @handlers.frozen? + end + + def use(klass, *args, &block) + if klass.is_a? Symbol + use_symbol(Faraday::Middleware, klass, *args, &block) + else + raise_if_locked + @handlers << self.class::Handler.new(klass, *args, &block) + end + end + + def request(key, *args, &block) + use_symbol(Faraday::Request, key, *args, &block) + end + + def response(key, *args, &block) + use_symbol(Faraday::Response, key, *args, &block) + end + + def adapter(key, *args, &block) + use_symbol(Faraday::Adapter, key, *args, &block) + end + + ## methods to push onto the various positions in the stack: + + def insert(index, *args, &block) + raise_if_locked + index = assert_index(index) + handler = self.class::Handler.new(*args, &block) + @handlers.insert(index, handler) + end + + alias_method :insert_before, :insert + + def insert_after(index, *args, &block) + index = assert_index(index) + insert(index + 1, *args, &block) + end + + def swap(index, *args, &block) + raise_if_locked + index = assert_index(index) + @handlers.delete_at(index) + insert(index, *args, &block) + end + + def delete(handler) + raise_if_locked + @handlers.delete(handler) + end + + # Processes a Request into a Response by passing it through this Builder's + # middleware stack. + # + # connection - Faraday::Connection + # request - Faraday::Request + # + # Returns a Faraday::Response. + def build_response(connection, request) + app.call(build_env(connection, request)) + end + + # The "rack app" wrapped in middleware. All requests are sent here. + # + # The builder is responsible for creating the app object. After this, + # the builder gets locked to ensure no further modifications are made + # to the middleware stack. + # + # Returns an object that responds to `call` and returns a Response. + def app + @app ||= begin + lock! + to_app(lambda { |env| + response = Response.new + response.finish(env) unless env.parallel? + env.response = response + }) + end + end + + def to_app(inner_app) + # last added handler is the deepest and thus closest to the inner app + @handlers.reverse.inject(inner_app) { |app, handler| handler.build(app) } + end + + def ==(other) + other.is_a?(self.class) && @handlers == other.handlers + end + + def dup + self.class.new(@handlers.dup) + end + + # ENV Keys + # :method - a symbolized request method (:get, :post) + # :body - the request body that will eventually be converted to a string. + # :url - URI instance for the current request. + # :status - HTTP response status code + # :request_headers - hash of HTTP Headers to be sent to the server + # :response_headers - Hash of HTTP headers from the server + # :parallel_manager - sent if the connection is in parallel mode + # :request - Hash of options for configuring the request. + # :timeout - open/read timeout Integer in seconds + # :open_timeout - read timeout Integer in seconds + # :proxy - Hash of proxy options + # :uri - Proxy Server URI + # :user - Proxy server username + # :password - Proxy server password + # :ssl - Hash of options for configuring SSL requests. + def build_env(connection, request) + Env.new(request.method, request.body, + connection.build_exclusive_url(request.path, request.params), + request.options, request.headers, connection.ssl, + connection.parallel_manager) + end + + private + + def raise_if_locked + raise StackLocked, "can't modify middleware stack after making a request" if locked? + end + + def use_symbol(mod, key, *args, &block) + use(mod.lookup_middleware(key), *args, &block) + end + + def assert_index(index) + idx = index.is_a?(Integer) ? index : @handlers.index(index) + raise "No such handler: #{index.inspect}" unless idx + idx + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/request.rb b/3rdparty/modules/aviator/feature/faraday/request.rb new file mode 100644 index 000000000..481077f14 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/request.rb @@ -0,0 +1,92 @@ +module Faraday + # Used to setup urls, params, headers, and the request body in a sane manner. + # + # @connection.post do |req| + # req.url 'http://localhost', 'a' => '1' # 'http://localhost?a=1' + # req.headers['b'] = '2' # Header + # req.params['c'] = '3' # GET Param + # req['b'] = '2' # also Header + # req.body = 'abc' + # end + # + class Request < Struct.new(:method, :path, :params, :headers, :body, :options) + extend MiddlewareRegistry + + register_middleware File.expand_path('../request', __FILE__), + :url_encoded => [:UrlEncoded, 'url_encoded'], + :multipart => [:Multipart, 'multipart'], + :retry => [:Retry, 'retry'], + :authorization => [:Authorization, 'authorization'], + :basic_auth => [:BasicAuthentication, 'basic_authentication'], + :token_auth => [:TokenAuthentication, 'token_authentication'], + :instrumentation => [:Instrumentation, 'instrumentation'] + + def self.create(request_method) + new(request_method).tap do |request| + yield(request) if block_given? + end + end + + # Public: Replace params, preserving the existing hash type + def params=(hash) + if params + params.replace hash + else + super + end + end + + # Public: Replace request headers, preserving the existing hash type + def headers=(hash) + if headers + headers.replace hash + else + super + end + end + + def url(path, params = nil) + if path.respond_to? :query + if query = path.query + path = path.dup + path.query = nil + end + else + path, query = path.split('?', 2) + end + self.path = path + self.params.merge_query query, options.params_encoder + self.params.update(params) if params + end + + def [](key) + headers[key] + end + + def []=(key, value) + headers[key] = value + end + + # ENV Keys + # :method - a symbolized request method (:get, :post) + # :body - the request body that will eventually be converted to a string. + # :url - URI instance for the current request. + # :status - HTTP response status code + # :request_headers - hash of HTTP Headers to be sent to the server + # :response_headers - Hash of HTTP headers from the server + # :parallel_manager - sent if the connection is in parallel mode + # :request - Hash of options for configuring the request. + # :timeout - open/read timeout Integer in seconds + # :open_timeout - read timeout Integer in seconds + # :proxy - Hash of proxy options + # :uri - Proxy Server URI + # :user - Proxy server username + # :password - Proxy server password + # :ssl - Hash of options for configuring SSL requests. + def to_env(connection) + Env.new(method, body, connection.build_exclusive_url(path, params), + options, headers, connection.ssl, connection.parallel_manager) + end + end +end + diff --git a/3rdparty/modules/aviator/feature/faraday/request/authorization.rb b/3rdparty/modules/aviator/feature/faraday/request/authorization.rb new file mode 100644 index 000000000..43b452880 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/request/authorization.rb @@ -0,0 +1,42 @@ +module Faraday + class Request::Authorization < Faraday::Middleware + KEY = "Authorization".freeze unless defined? KEY + + # Public + def self.header(type, token) + case token + when String, Symbol + "#{type} #{token}" + when Hash + build_hash(type.to_s, token) + else + raise ArgumentError, "Can't build an Authorization #{type} header from #{token.inspect}" + end + end + + # Internal + def self.build_hash(type, hash) + offset = KEY.size + type.size + 3 + comma = ",\n#{' ' * offset}" + values = [] + hash.each do |key, value| + values << "#{key}=#{value.to_s.inspect}" + end + "#{type} #{values * comma}" + end + + def initialize(app, type, token) + @header_value = self.class.header(type, token) + super(app) + end + + # Public + def call(env) + unless env.request_headers[KEY] + env.request_headers[KEY] = @header_value + end + @app.call(env) + end + end +end + diff --git a/3rdparty/modules/aviator/feature/faraday/request/basic_authentication.rb b/3rdparty/modules/aviator/feature/faraday/request/basic_authentication.rb new file mode 100644 index 000000000..54c8dee97 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/request/basic_authentication.rb @@ -0,0 +1,13 @@ +require 'base64' + +module Faraday + class Request::BasicAuthentication < Request.load_middleware(:authorization) + # Public + def self.header(login, pass) + value = Base64.encode64([login, pass].join(':')) + value.gsub!("\n", '') + super(:Basic, value) + end + end +end + diff --git a/3rdparty/modules/aviator/feature/faraday/request/instrumentation.rb b/3rdparty/modules/aviator/feature/faraday/request/instrumentation.rb new file mode 100644 index 000000000..42af8bc44 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/request/instrumentation.rb @@ -0,0 +1,36 @@ +module Faraday + class Request::Instrumentation < Faraday::Middleware + class Options < Faraday::Options.new(:name, :instrumenter) + def name + self[:name] ||= 'request.faraday' + end + + def instrumenter + self[:instrumenter] ||= ActiveSupport::Notifications + end + end + + # Public: Instruments requests using Active Support. + # + # Measures time spent only for synchronous requests. + # + # Examples + # + # ActiveSupport::Notifications.subscribe('request.faraday') do |name, starts, ends, _, env| + # url = env[:url] + # http_method = env[:method].to_s.upcase + # duration = ends - starts + # $stderr.puts '[%s] %s %s (%.3f s)' % [url.host, http_method, url.request_uri, duration] + # end + def initialize(app, options = nil) + super(app) + @name, @instrumenter = Options.from(options).values_at(:name, :instrumenter) + end + + def call(env) + @instrumenter.instrument(@name, env) do + @app.call(env) + end + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/request/multipart.rb b/3rdparty/modules/aviator/feature/faraday/request/multipart.rb new file mode 100644 index 000000000..38b452af7 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/request/multipart.rb @@ -0,0 +1,63 @@ +require File.expand_path("../url_encoded", __FILE__) + +module Faraday + class Request::Multipart < Request::UrlEncoded + self.mime_type = 'multipart/form-data'.freeze + DEFAULT_BOUNDARY = "-----------RubyMultipartPost".freeze unless defined? DEFAULT_BOUNDARY + + def call(env) + match_content_type(env) do |params| + env.request.boundary ||= DEFAULT_BOUNDARY + env.request_headers[CONTENT_TYPE] += "; boundary=#{env.request.boundary}" + env.body = create_multipart(env, params) + end + @app.call env + end + + def process_request?(env) + type = request_type(env) + env.body.respond_to?(:each_key) and !env.body.empty? and ( + (type.empty? and has_multipart?(env.body)) or + type == self.class.mime_type + ) + end + + def has_multipart?(obj) + # string is an enum in 1.8, returning list of itself + if obj.respond_to?(:each) && !obj.is_a?(String) + (obj.respond_to?(:values) ? obj.values : obj).each do |val| + return true if (val.respond_to?(:content_type) || has_multipart?(val)) + end + end + false + end + + def create_multipart(env, params) + boundary = env.request.boundary + parts = process_params(params) do |key, value| + Faraday::Parts::Part.new(boundary, key, value) + end + parts << Faraday::Parts::EpiloguePart.new(boundary) + + body = Faraday::CompositeReadIO.new(parts) + env.request_headers[Faraday::Env::ContentLength] = body.length.to_s + return body + end + + def process_params(params, prefix = nil, pieces = nil, &block) + params.inject(pieces || []) do |all, (key, value)| + key = "#{prefix}[#{key}]" if prefix + + case value + when Array + values = value.inject([]) { |a,v| a << [nil, v] } + process_params(values, key, all, &block) + when Hash + process_params(value, key, all, &block) + else + all << block.call(key, value) + end + end + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/request/retry.rb b/3rdparty/modules/aviator/feature/faraday/request/retry.rb new file mode 100644 index 000000000..08bc83766 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/request/retry.rb @@ -0,0 +1,140 @@ +module Faraday + # Catches exceptions and retries each request a limited number of times. + # + # By default, it retries 2 times and handles only timeout exceptions. It can + # be configured with an arbitrary number of retries, a list of exceptions to + # handle, a retry interval, a percentage of randomness to add to the retry + # interval, and a backoff factor. + # + # Examples + # + # Faraday.new do |conn| + # conn.request :retry, max: 2, interval: 0.05, + # interval_randomness: 0.5, backoff_factor: 2 + # exceptions: [CustomException, 'Timeout::Error'] + # conn.adapter ... + # end + # + # This example will result in a first interval that is random between 0.05 and 0.075 and a second + # interval that is random between 0.1 and 0.15 + # + class Request::Retry < Faraday::Middleware + + IDEMPOTENT_METHODS = [:delete, :get, :head, :options, :put] + + class Options < Faraday::Options.new(:max, :interval, :interval_randomness, :backoff_factor, :exceptions, :retry_if) + DEFAULT_CHECK = lambda { |env,exception| false } + + def self.from(value) + if Fixnum === value + new(value) + else + super(value) + end + end + + def max + (self[:max] ||= 2).to_i + end + + def interval + (self[:interval] ||= 0).to_f + end + + def interval_randomness + (self[:interval_randomness] ||= 0).to_i + end + + def backoff_factor + (self[:backoff_factor] ||= 1).to_f + end + + def exceptions + Array(self[:exceptions] ||= [Errno::ETIMEDOUT, 'Timeout::Error', + Error::TimeoutError]) + end + + def retry_if + self[:retry_if] ||= DEFAULT_CHECK + end + + end + + # Public: Initialize middleware + # + # Options: + # max - Maximum number of retries (default: 2) + # interval - Pause in seconds between retries (default: 0) + # interval_randomness - The maximum random interval amount expressed + # as a float between 0 and 1 to use in addition to the + # interval. (default: 0) + # backoff_factor - The amount to multiple each successive retry's + # interval amount by in order to provide backoff + # (default: 1) + # exceptions - The list of exceptions to handle. Exceptions can be + # given as Class, Module, or String. (default: + # [Errno::ETIMEDOUT, Timeout::Error, + # Error::TimeoutError]) + # retry_if - block that will receive the env object and the exception raised + # and should decide if the code should retry still the action or + # not independent of the retry count. This would be useful + # if the exception produced is non-recoverable or if the + # the HTTP method called is not idempotent. + # (defaults to return false) + def initialize(app, options = nil) + super(app) + @options = Options.from(options) + @errmatch = build_exception_matcher(@options.exceptions) + end + + def sleep_amount(retries) + retry_index = @options.max - retries + current_interval = @options.interval * (@options.backoff_factor ** retry_index) + random_interval = rand * @options.interval_randomness.to_f * @options.interval + current_interval + random_interval + end + + def call(env) + retries = @options.max + request_body = env[:body] + begin + env[:body] = request_body # after failure env[:body] is set to the response body + @app.call(env) + rescue @errmatch => exception + if retries > 0 && retry_request?(env, exception) + retries -= 1 + sleep sleep_amount(retries + 1) + retry + end + raise + end + end + + # Private: construct an exception matcher object. + # + # An exception matcher for the rescue clause can usually be any object that + # responds to `===`, but for Ruby 1.8 it has to be a Class or Module. + def build_exception_matcher(exceptions) + matcher = Module.new + (class << matcher; self; end).class_eval do + define_method(:===) do |error| + exceptions.any? do |ex| + if ex.is_a? Module + error.is_a? ex + else + error.class.to_s == ex.to_s + end + end + end + end + matcher + end + + private + + def retry_request?(env, exception) + IDEMPOTENT_METHODS.include?(env[:method]) || @options.retry_if.call(env, exception) + end + + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/request/token_authentication.rb b/3rdparty/modules/aviator/feature/faraday/request/token_authentication.rb new file mode 100644 index 000000000..25586080c --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/request/token_authentication.rb @@ -0,0 +1,15 @@ +module Faraday + class Request::TokenAuthentication < Request.load_middleware(:authorization) + # Public + def self.header(token, options = nil) + options ||= {} + options[:token] = token + super(:Token, options) + end + + def initialize(app, token, options = nil) + super(app, token, options) + end + end +end + diff --git a/3rdparty/modules/aviator/feature/faraday/request/url_encoded.rb b/3rdparty/modules/aviator/feature/faraday/request/url_encoded.rb new file mode 100644 index 000000000..b02a26621 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/request/url_encoded.rb @@ -0,0 +1,36 @@ +module Faraday + class Request::UrlEncoded < Faraday::Middleware + CONTENT_TYPE = 'Content-Type'.freeze unless defined? CONTENT_TYPE + + class << self + attr_accessor :mime_type + end + self.mime_type = 'application/x-www-form-urlencoded'.freeze + + def call(env) + match_content_type(env) do |data| + params = Faraday::Utils::ParamsHash[data] + env.body = params.to_query(env.params_encoder) + end + @app.call env + end + + def match_content_type(env) + if process_request?(env) + env.request_headers[CONTENT_TYPE] ||= self.class.mime_type + yield(env.body) unless env.body.respond_to?(:to_str) + end + end + + def process_request?(env) + type = request_type(env) + env.body and (type.empty? or type == self.class.mime_type) + end + + def request_type(env) + type = env.request_headers[CONTENT_TYPE].to_s + type = type.split(';', 2).first if type.index(';') + type + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/response.rb b/3rdparty/modules/aviator/feature/faraday/response.rb new file mode 100644 index 000000000..88ec5310a --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/response.rb @@ -0,0 +1,93 @@ +require 'forwardable' + +module Faraday + class Response + # Used for simple response middleware. + class Middleware < Faraday::Middleware + def call(env) + @app.call(env).on_complete do |environment| + on_complete(environment) + end + end + + # Override this to modify the environment after the response has finished. + # Calls the `parse` method if defined + def on_complete(env) + env.body = parse(env.body) if respond_to?(:parse) && env.parse_body? + end + end + + extend Forwardable + extend MiddlewareRegistry + + register_middleware File.expand_path('../response', __FILE__), + :raise_error => [:RaiseError, 'raise_error'], + :logger => [:Logger, 'logger'] + + def initialize(env = nil) + @env = Env.from(env) if env + @on_complete_callbacks = [] + end + + attr_reader :env + + def_delegators :env, :to_hash + + def status + finished? ? env.status : nil + end + + def headers + finished? ? env.response_headers : {} + end + def_delegator :headers, :[] + + def body + finished? ? env.body : nil + end + + def finished? + !!env + end + + def on_complete + if not finished? + @on_complete_callbacks << Proc.new + else + yield(env) + end + return self + end + + def finish(env) + raise "response already finished" if finished? + @on_complete_callbacks.each { |callback| callback.call(env) } + @env = Env.from(env) + return self + end + + def success? + finished? && env.success? + end + + # because @on_complete_callbacks cannot be marshalled + def marshal_dump + !finished? ? nil : { + :status => @env.status, :body => @env.body, + :response_headers => @env.response_headers + } + end + + def marshal_load(env) + @env = Env.from(env) + end + + # Expand the env with more properties, without overriding existing ones. + # Useful for applying request params after restoring a marshalled Response. + def apply_request(request_env) + raise "response didn't finish yet" unless finished? + @env = Env.from(request_env).update(@env) + return self + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/response/logger.rb b/3rdparty/modules/aviator/feature/faraday/response/logger.rb new file mode 100644 index 000000000..cab7f1b7c --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/response/logger.rb @@ -0,0 +1,34 @@ +require 'forwardable' + +module Faraday + class Response::Logger < Response::Middleware + extend Forwardable + + def initialize(app, logger = nil) + super(app) + @logger = logger || begin + require 'logger' + ::Logger.new(STDOUT) + end + end + + def_delegators :@logger, :debug, :info, :warn, :error, :fatal + + def call(env) + info "#{env.method} #{env.url.to_s}" + debug('request') { dump_headers env.request_headers } + super + end + + def on_complete(env) + info('Status') { env.status.to_s } + debug('response') { dump_headers env.response_headers } + end + + private + + def dump_headers(headers) + headers.map { |k, v| "#{k}: #{v.inspect}" }.join("\n") + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/response/raise_error.rb b/3rdparty/modules/aviator/feature/faraday/response/raise_error.rb new file mode 100644 index 000000000..437762bc1 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/response/raise_error.rb @@ -0,0 +1,21 @@ +module Faraday + class Response::RaiseError < Response::Middleware + ClientErrorStatuses = 400...600 + + def on_complete(env) + case env[:status] + when 404 + raise Faraday::Error::ResourceNotFound, response_values(env) + when 407 + # mimic the behavior that we get with proxy requests with HTTPS + raise Faraday::Error::ConnectionFailed, %{407 "Proxy Authentication Required "} + when ClientErrorStatuses + raise Faraday::Error::ClientError, response_values(env) + end + end + + def response_values(env) + {:status => env.status, :headers => env.response_headers, :body => env.body} + end + end +end diff --git a/3rdparty/modules/aviator/feature/faraday/upload_io.rb b/3rdparty/modules/aviator/feature/faraday/upload_io.rb new file mode 100644 index 000000000..9130d159d --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/upload_io.rb @@ -0,0 +1,67 @@ +begin + require 'composite_io' + require 'parts' + require 'stringio' +rescue LoadError + $stderr.puts "Install the multipart-post gem." + raise +end + +module Faraday + # Similar but not compatible with ::CompositeReadIO provided by multipart-post. + class CompositeReadIO + def initialize(*parts) + @parts = parts.flatten + @ios = @parts.map { |part| part.to_io } + @index = 0 + end + + def length + @parts.inject(0) { |sum, part| sum + part.length } + end + + def rewind + @ios.each { |io| io.rewind } + @index = 0 + end + + # Read from IOs in order until `length` bytes have been received. + def read(length = nil, outbuf = nil) + got_result = false + outbuf = outbuf ? outbuf.replace("") : "" + + while io = current_io + if result = io.read(length) + got_result ||= !result.nil? + result.force_encoding("BINARY") if result.respond_to?(:force_encoding) + outbuf << result + length -= result.length if length + break if length == 0 + end + advance_io + end + (!got_result && length) ? nil : outbuf + end + + def close + @ios.each { |io| io.close } + end + + def ensure_open_and_readable + # Rubinius compatibility + end + + private + + def current_io + @ios[@index] + end + + def advance_io + @index += 1 + end + end + + UploadIO = ::UploadIO + Parts = ::Parts +end diff --git a/3rdparty/modules/aviator/feature/faraday/utils.rb b/3rdparty/modules/aviator/feature/faraday/utils.rb new file mode 100644 index 000000000..1cd6526a6 --- /dev/null +++ b/3rdparty/modules/aviator/feature/faraday/utils.rb @@ -0,0 +1,297 @@ +require 'thread' +Faraday.require_libs 'parameters' + +module Faraday + module Utils + extend self + + # Adapted from Rack::Utils::HeaderHash + class Headers < ::Hash + def self.from(value) + new(value) + end + + def initialize(hash = nil) + super() + @names = {} + self.update(hash || {}) + end + + # need to synchronize concurrent writes to the shared KeyMap + keymap_mutex = Mutex.new + + # symbol -> string mapper + cache + KeyMap = Hash.new do |map, key| + value = if key.respond_to?(:to_str) + key + else + key.to_s.split('_'). # :user_agent => %w(user agent) + each { |w| w.capitalize! }. # => %w(User Agent) + join('-') # => "User-Agent" + end + keymap_mutex.synchronize { map[key] = value } + end + KeyMap[:etag] = "ETag" + + def [](k) + k = KeyMap[k] + super(k) || super(@names[k.downcase]) + end + + def []=(k, v) + k = KeyMap[k] + k = (@names[k.downcase] ||= k) + # join multiple values with a comma + v = v.to_ary.join(', ') if v.respond_to? :to_ary + super(k, v) + end + + def fetch(k, *args, &block) + k = KeyMap[k] + key = @names.fetch(k.downcase, k) + super(key, *args, &block) + end + + def delete(k) + k = KeyMap[k] + if k = @names[k.downcase] + @names.delete k.downcase + super(k) + end + end + + def include?(k) + @names.include? k.downcase + end + + alias_method :has_key?, :include? + alias_method :member?, :include? + alias_method :key?, :include? + + def merge!(other) + other.each { |k, v| self[k] = v } + self + end + alias_method :update, :merge! + + def merge(other) + hash = dup + hash.merge! other + end + + def replace(other) + clear + self.update other + self + end + + def to_hash() ::Hash.new.update(self) end + + def parse(header_string) + return unless header_string && !header_string.empty? + header_string.split(/\r\n/). + tap { |a| a.shift if a.first.index('HTTP/') == 0 }. # drop the HTTP status line + map { |h| h.split(/:\s+/, 2) }.reject { |p| p[0].nil? }. # split key and value, ignore blank lines + each { |key, value| + # join multiple values with a comma + if self[key] + self[key] << ', ' << value + else + self[key] = value + end + } + end + end + + # hash with stringified keys + class ParamsHash < Hash + def [](key) + super(convert_key(key)) + end + + def []=(key, value) + super(convert_key(key), value) + end + + def delete(key) + super(convert_key(key)) + end + + def include?(key) + super(convert_key(key)) + end + + alias_method :has_key?, :include? + alias_method :member?, :include? + alias_method :key?, :include? + + def update(params) + params.each do |key, value| + self[key] = value + end + self + end + alias_method :merge!, :update + + def merge(params) + dup.update(params) + end + + def replace(other) + clear + update(other) + end + + def merge_query(query, encoder = nil) + if query && !query.empty? + update((encoder || Utils.default_params_encoder).decode(query)) + end + self + end + + def to_query(encoder = nil) + (encoder || Utils.default_params_encoder).encode(self) + end + + private + + def convert_key(key) + key.to_s + end + end + + def build_query(params) + FlatParamsEncoder.encode(params) + end + + def build_nested_query(params) + NestedParamsEncoder.encode(params) + end + + ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/ + + def escape(s) + s.to_s.gsub(ESCAPE_RE) {|match| + '%' + match.unpack('H2' * match.bytesize).join('%').upcase + }.tr(' ', '+') + end + + def unescape(s) CGI.unescape s.to_s end + + DEFAULT_SEP = /[&;] */n + + # Adapted from Rack + def parse_query(query) + FlatParamsEncoder.decode(query) + end + + def parse_nested_query(query) + NestedParamsEncoder.decode(query) + end + + def default_params_encoder + @default_params_encoder ||= NestedParamsEncoder + end + + class << self + attr_writer :default_params_encoder + end + + # Stolen from Rack + def normalize_params(params, name, v = nil) + name =~ %r(\A[\[\]]*([^\[\]]+)\]*) + k = $1 || '' + after = $' || '' + + return if k.empty? + + if after == "" + if params[k] + params[k] = Array[params[k]] unless params[k].kind_of?(Array) + params[k] << v + else + params[k] = v + end + elsif after == "[]" + params[k] ||= [] + raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array) + params[k] << v + elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$) + child_key = $1 + params[k] ||= [] + raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array) + if params[k].last.is_a?(Hash) && !params[k].last.key?(child_key) + normalize_params(params[k].last, child_key, v) + else + params[k] << normalize_params({}, child_key, v) + end + else + params[k] ||= {} + raise TypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Hash) + params[k] = normalize_params(params[k], after, v) + end + + return params + end + + # Normalize URI() behavior across Ruby versions + # + # url - A String or URI. + # + # Returns a parsed URI. + def URI(url) + if url.respond_to?(:host) + url + elsif url.respond_to?(:to_str) + default_uri_parser.call(url) + else + raise ArgumentError, "bad argument (expected URI object or URI string)" + end + end + + def default_uri_parser + @default_uri_parser ||= begin + require 'uri' + Kernel.method(:URI) + end + end + + def default_uri_parser=(parser) + @default_uri_parser = if parser.respond_to?(:call) || parser.nil? + parser + else + parser.method(:parse) + end + end + + # Receives a String or URI and returns just the path with the query string sorted. + def normalize_path(url) + url = URI(url) + (url.path.start_with?('/') ? url.path : '/' + url.path) + + (url.query ? "?#{sort_query_params(url.query)}" : "") + end + + # Recursive hash update + def deep_merge!(target, hash) + hash.each do |key, value| + if Hash === value and Hash === target[key] + target[key] = deep_merge(target[key], value) + else + target[key] = value + end + end + target + end + + # Recursive hash merge + def deep_merge(source, hash) + deep_merge!(source.dup, hash) + end + + protected + + def sort_query_params(query) + query.split('&').sort.join('&') + end + end +end diff --git a/3rdparty/modules/aviator/feature/multipart_post.rb b/3rdparty/modules/aviator/feature/multipart_post.rb new file mode 100644 index 000000000..76540a8b7 --- /dev/null +++ b/3rdparty/modules/aviator/feature/multipart_post.rb @@ -0,0 +1,9 @@ +#-- +# Copyright (c) 2007-2013 Nick Sieger. +# See the file README.txt included with the distribution for +# software license details. +#++ + +module MultipartPost + VERSION = "2.0.0" +end diff --git a/3rdparty/modules/aviator/feature/multipartable.rb b/3rdparty/modules/aviator/feature/multipartable.rb new file mode 100644 index 000000000..28fa41e6d --- /dev/null +++ b/3rdparty/modules/aviator/feature/multipartable.rb @@ -0,0 +1,29 @@ +#-- +# Copyright (c) 2007-2013 Nick Sieger. +# See the file README.txt included with the distribution for +# software license details. +#++ + +require 'parts' + module Multipartable + DEFAULT_BOUNDARY = "-----------RubyMultipartPost" + def initialize(path, params, headers={}, boundary = DEFAULT_BOUNDARY) + headers = headers.clone # don't want to modify the original variable + parts_headers = headers.delete(:parts) || {} + super(path, headers) + parts = params.map do |k,v| + case v + when Array + v.map {|item| Parts::Part.new(boundary, k, item, parts_headers[k]) } + else + Parts::Part.new(boundary, k, v, parts_headers[k]) + end + end.flatten + parts << Parts::EpiloguePart.new(boundary) + ios = parts.map {|p| p.to_io } + self.set_content_type(headers["Content-Type"] || "multipart/form-data", + { "boundary" => boundary }) + self.content_length = parts.inject(0) {|sum,i| sum + i.length } + self.body_stream = CompositeReadIO.new(*ios) + end + end diff --git a/3rdparty/modules/aviator/feature/net/http/post/multipart.rb b/3rdparty/modules/aviator/feature/net/http/post/multipart.rb new file mode 100644 index 000000000..757058220 --- /dev/null +++ b/3rdparty/modules/aviator/feature/net/http/post/multipart.rb @@ -0,0 +1,27 @@ +#-- +# Copyright (c) 2007-2012 Nick Sieger. +# See the file README.txt included with the distribution for +# software license details. +#++ + +require 'net/http' +require 'stringio' +require 'cgi' +require 'composite_io' +require 'multipartable' +require 'parts' + +module Net #:nodoc: + class HTTP #:nodoc: + class Put + class Multipart < Put + include Multipartable + end + end + class Post #:nodoc: + class Multipart < Post + include Multipartable + end + end + end +end diff --git a/3rdparty/modules/aviator/feature/parts.rb b/3rdparty/modules/aviator/feature/parts.rb new file mode 100644 index 000000000..c06cbd95d --- /dev/null +++ b/3rdparty/modules/aviator/feature/parts.rb @@ -0,0 +1,96 @@ +#-- +# Copyright (c) 2007-2013 Nick Sieger. +# See the file README.txt included with the distribution for +# software license details. +#++ + +module Parts + module Part #:nodoc: + def self.new(boundary, name, value, headers = {}) + headers ||= {} # avoid nil values + if file?(value) + FilePart.new(boundary, name, value, headers) + else + ParamPart.new(boundary, name, value, headers) + end + end + + def self.file?(value) + value.respond_to?(:content_type) && value.respond_to?(:original_filename) + end + + def length + @part.length + end + + def to_io + @io + end + end + + class ParamPart + include Part + def initialize(boundary, name, value, headers = {}) + @part = build_part(boundary, name, value, headers) + @io = StringIO.new(@part) + end + + def length + @part.bytesize + end + + def build_part(boundary, name, value, headers = {}) + part = '' + part << "--#{boundary}\r\n" + part << "Content-Disposition: form-data; name=\"#{name.to_s}\"\r\n" + part << "Content-Type: #{headers["Content-Type"]}\r\n" if headers["Content-Type"] + part << "\r\n" + part << "#{value}\r\n" + end + end + + # Represents a part to be filled from file IO. + class FilePart + include Part + attr_reader :length + def initialize(boundary, name, io, headers = {}) + file_length = io.respond_to?(:length) ? io.length : File.size(io.local_path) + @head = build_head(boundary, name, io.original_filename, io.content_type, file_length, + io.respond_to?(:opts) ? io.opts.merge(headers) : headers) + @foot = "\r\n" + @length = @head.bytesize + file_length + @foot.length + @io = CompositeReadIO.new(StringIO.new(@head), io, StringIO.new(@foot)) + end + + def build_head(boundary, name, filename, type, content_len, opts = {}, headers = {}) + trans_encoding = opts["Content-Transfer-Encoding"] || "binary" + content_disposition = opts["Content-Disposition"] || "form-data" + + part = '' + part << "--#{boundary}\r\n" + part << "Content-Disposition: #{content_disposition}; name=\"#{name.to_s}\"; filename=\"#{filename}\"\r\n" + part << "Content-Length: #{content_len}\r\n" + if content_id = opts["Content-ID"] + part << "Content-ID: #{content_id}\r\n" + end + + if headers["Content-Type"] != nil + part << "Content-Type: " + headers["Content-Type"] + "\r\n" + else + part << "Content-Type: #{type}\r\n" + end + + part << "Content-Transfer-Encoding: #{trans_encoding}\r\n" + part << "\r\n" + end + end + + # Represents the epilogue or closing boundary. + class EpiloguePart + include Part + def initialize(boundary) + @part = "--#{boundary}--\r\n\r\n" + @io = StringIO.new(@part) + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator.rb new file mode 100644 index 000000000..e70ba3918 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator.rb @@ -0,0 +1,7 @@ +# Add the parent dir to the load path. This is for when +# Aviator is not installed as a gem +lib_path = File.dirname(__FILE__) +$LOAD_PATH.unshift(lib_path) unless $LOAD_PATH.include? lib_path + +require 'aviator/core' +require "aviator/openstack/provider" diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/core.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core.rb new file mode 100644 index 000000000..73576f914 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core.rb @@ -0,0 +1,15 @@ +require 'yaml' +require 'json' +require 'faraday' +require 'pathname' + +require "aviator/version" +require "aviator/core/utils/string" +require "aviator/core/utils/compatibility" +require "aviator/core/utils/hashish" +require "aviator/core/request" +require "aviator/core/request_builder" +require "aviator/core/response" +require "aviator/core/service" +require "aviator/core/session" +require "aviator/core/logger" diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/cli.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/cli.rb new file mode 100644 index 000000000..cd937d0e7 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/cli.rb @@ -0,0 +1,2 @@ +require "terminal-table" +require "aviator/core/cli/describer" diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/cli/describer.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/cli/describer.rb new file mode 100644 index 000000000..a6ad8507a --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/cli/describer.rb @@ -0,0 +1,161 @@ +module Aviator + + class Describer + + class InvalidProviderNameError < StandardError + def initialize(name) + super "Provider '#{ name }' does not exist." + end + end + + + def self.describe_aviator + str = "Available providers:\n" + + provider_names.each do |provider_name| + str << " #{ provider_name }\n" + end + + str + end + + + def self.describe_provider(provider_name) + str = "Available services for #{ provider_name }:\n" + + service_names(provider_name).each do |service_name| + str << " #{ service_name }\n" + end + + str + end + + + def self.describe_request(provider_name, service_name, api_version, endpoint_type, request_name) + service = Aviator::Service.new :provider => provider_name, :service => service_name + request_class = "Aviator::#{ provider_name.camelize }::#{ service_name.camelize }::Requests::"\ + "#{ api_version.camelize }::#{ endpoint_type.camelize }::#{ request_name.camelize }".constantize + + display = "Request: #{ request_name }\n" + + + # Build the parameters + params = request_class.optional_params.map{|p| [p, false]} + + request_class.required_params.map{|p| [p, true]} + + aliases = request_class.param_aliases + + if params.length > 0 + display << "\n" + + headings = ['NAME', 'REQUIRED?'] + + headings << 'ALIAS' if aliases.length > 0 + + rows = [] + params.sort{|a,b| a[0].to_s <=> b[0].to_s }.each do |param| + row = [ param[0], param[1] ? 'Y' : 'N' ] + + if aliases.length > 0 + row << (aliases.find{|a,p| p == param[0] } || [''])[0] + end + + rows << row + end + + widths = [ + rows.map{|row| row[0].to_s.length }.max, + rows.map{|row| row[1].to_s.length }.max + ] + + widths << rows.map{|row| row[2].to_s.length }.max if aliases.length > 0 + + table = Terminal::Table.new(:headings => headings, :rows => rows) + + table.align_column(1, :center) + + display << "Parameters:\n" + display << " " + table.to_s.split("\n").join("\n ") + display << "\n" + end + + + # Build the sample code + display << "\nSample Code:\n" + + display << " session.request(:#{ service_name }_service, :#{ request_name })" + + if params && params.length > 0 + display << " do |params|\n" + params.each do |pair| + display << " params.#{ (aliases.find{|a,p| p == pair[0] } || pair)[0] } = value\n" + end + display << " end" + end + + display << "\n" + + + # Build the links + if request_class.links && request_class.links.length > 0 + display << "\nLinks:\n" + + request_class.links.each do |link| + display << " #{ link[:rel] }:\n" + display << " #{ link[:href] }\n" + end + end + + display + end + + + def self.describe_service(provider_name, service_name) + requests = request_classes(provider_name, service_name) + + if requests.empty? + str = "No requests found for #{ provider_name } #{ service_name }_service." + else + str = "Available requests for #{ provider_name } #{ service_name }_service:\n" + + requests.each do |klass| + str << " #{ klass.api_version } #{ klass.endpoint_type } #{ klass.name.split('::').last.underscore }\n" + end + + str + end + end + + + class < provider_name, :service => service_name) + service.request_classes + end + + + def service_names(name) + provider = Pathname.new(__FILE__).join('..', '..', '..', name) + + raise InvalidProviderNameError.new(name) unless provider.exist? + + provider.children \ + .select{|c| c.directory? } \ + .map{|c| c.basename.to_s } + end + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/logger.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/logger.rb new file mode 100644 index 000000000..bbb537d7f --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/logger.rb @@ -0,0 +1,55 @@ +module Aviator + + class Logger < Faraday::Response::Middleware + extend Forwardable + + def initialize(app, logger=nil) + super(app) + @logger = logger || begin + require 'logger' + ::Logger.new(self.class::LOG_FILE_PATH) + end + end + + + def_delegators :@logger, :debug, :info, :warn, :error, :fatal + + + def call(env) + info(env[:method].to_s.upcase) { env[:url].to_s } + debug('REQ_HEAD') { dump_headers env[:request_headers] } + debug('REQ_BODY') { dump_body env[:body] } + super + end + + + def on_complete(env) + info('STATUS') { env[:status].to_s } + debug('RES_HEAD') { dump_headers env[:response_headers] } + debug('RES_BODY') { dump_body env[:body] } + end + + + def self.configure(log_file_path) + # Return a subclass with its logfile path set. This + # must be done so that different sessions can log to + # different paths. + Class.new(self) { const_set('LOG_FILE_PATH', log_file_path) } + end + + + private + + def dump_body(body) + return if body.nil? + + # :TODO => Make this configurable + body.gsub(/["']password["']:["']\w*["']/, '"password":[FILTERED_VALUE]') + end + + def dump_headers(headers) + headers.map { |k, v| "#{k}: #{v.inspect}" }.join("; ") + end + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/request.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/request.rb new file mode 100644 index 000000000..ed9c6cef1 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/request.rb @@ -0,0 +1,229 @@ +module Aviator + + class Request + + class ApiVersionNotDefinedError < StandardError + def initialize + super "api_version is not defined." + end + end + + class EndpointTypeNotDefinedError < StandardError + def initialize + super "endpoint_type is not defined." + end + end + + class PathNotDefinedError < StandardError + def initialize + super "path is not defined." + end + end + + + def initialize(session_data=nil) + @session_data = session_data + + params = self.class.params_class.new if self.class.params_class + + if params + yield(params) if block_given? + validate_params(params) + end + + @params = params + end + + + def anonymous? + self.class.anonymous? + end + + + def body? + self.class.body? + end + + + def headers? + self.class.headers? + end + + + def links + self.class.links + end + + + def optional_params + self.class.optional_params + end + + + def params + @params.dup + end + + + def required_params + self.class.required_params + end + + + def session_data + @session_data + end + + + def session_data? + !session_data.nil? + end + + + def querystring? + self.class.querystring? + end + + + def url? + self.class.url? + end + + + private + + + def validate_params(params) + required_params = self.class.required_params + + required_params.each do |name| + raise ArgumentError.new("Missing parameter #{ name }.") if params.send(name).nil? + end + end + + + # NOTE that, because we are defining the following as class methods, when they + # are called, all 'instance' variables are actually defined in the descendant class, + # not in the instance/object. This is by design since we want to keep these attributes + # within the class and because they don't change between instances anyway. + class << self + + def anonymous? + respond_to?(:anonymous) && anonymous == true + end + + + def body? + instance_methods.include? :body + end + + + def headers? + instance_methods.include? :headers + end + + + def links + @links ||= [] + end + + + def param_aliases + @param_aliases ||= {} + end + + + def params_class + all_params = required_params + optional_params + + if all_params.length > 0 && @params_class.nil? + @params_class = build_params_class(all_params, self.param_aliases) + end + + @params_class + end + + + def optional_params + @optional_params ||= [] + end + + + def querystring? + instance_methods.include? :querystring + end + + + def required_params + @required_params ||= [] + end + + + def url? + instance_methods.include? :url + end + + + private + + + def build_params_class(all_params, param_aliases) + Struct.new(*all_params) do + alias :param_getter :[] + alias :param_setter :[]= + + define_method :[] do |key| + key = param_aliases[key.to_sym] if param_aliases.keys.include? key.to_sym + param_getter(key) + end + + define_method :[]= do |key, value| + key = param_aliases[key.to_sym] if param_aliases.keys.include? key.to_sym + param_setter(key, value) + end + + param_aliases.each do |param_alias, param_name| + define_method param_alias do + param_getter(param_name) + end + + define_method "#{ param_alias }=" do |value| + param_setter(param_name, value) + end + end + end + end + + + def link(rel, href) + links << { :rel => rel, :href => href } + end + + + def meta(attr_name, attr_value) + eigenclass = class << self; self; end + eigenclass.send(:define_method, attr_name) do + attr_value + end + + define_method(attr_name) do + self.class.send(attr_name) + end + end + + + def param(param_name, opts={}) + opts = Hashish.new(opts) + list = (opts[:required] == false ? optional_params : required_params) + list << param_name unless optional_params.include?(param_name) + + if opts[:alias] + self.param_aliases[opts[:alias]] = param_name + end + end + + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/request_builder.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/request_builder.rb new file mode 100644 index 000000000..ac5590166 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/request_builder.rb @@ -0,0 +1,102 @@ +module Aviator + + class BaseRequestNotFoundError < StandardError + attr_reader :base_request_hierarchy + + def initialize(base_hierarchy) + @base_request_hierarchy = base_hierarchy + super("#{ base_request_hierarchy } could not be found!") + end + end + + + class RequestAlreadyDefinedError < StandardError + attr_reader :namespace, + :request_name + + def initialize(namespace, request_name) + @namespace = namespace + @request_name = request_name + super("#{ namespace }::#{ request_name } is already defined") + end + end + + + class RequestBuilder + + class << self + + def define_request(root_namespace, request_name, options, &block) + base_klass = get_request_class(root_namespace, options[:inherit]) + + klass = Class.new(base_klass, &block) + + namespace_arr = [ + klass.provider, + klass.service, + 'Requests', + klass.api_version, + klass.endpoint_type + ] + + namespace = namespace_arr.inject(root_namespace) do |namespace, sym| + const_name = sym.to_s.camelize + namespace.const_set(const_name, Module.new) unless namespace.const_defined?(const_name, false) + namespace.const_get(const_name, false) + end + + klassname = request_name.to_s.camelize + + if namespace.const_defined?(klassname, false) + raise RequestAlreadyDefinedError.new(namespace, klassname) + end + + namespace.const_set(klassname, klass) + end + + + def get_request_class(root_namespace, request_class_arr) + provider_specific = request_class_arr != [:request] + + if provider_specific + full_request_class_arr = request_class_arr.dup + full_request_class_arr.insert(2, :requests) if provider_specific + else + full_request_class_arr = request_class_arr + end + + full_request_class_arr.inject(root_namespace) do |namespace, sym| + namespace.const_get(sym.to_s.camelize, false) + end + rescue NameError => e + if Aviator.const_defined?(full_request_class_arr[0].to_s.camelize) + provider = "Aviator::#{ full_request_class_arr[0] }::Provider".constantize + arr = ['..'] + full_request_class_arr + arr[-1,1] = arr.last.to_s + '.rb' + path = Pathname.new(provider.root_dir).join(*arr.map{|i| i.to_s }).expand_path + end + + if provider && path.exist? + require path + full_request_class_arr.inject(root_namespace) do |namespace, sym| + namespace.const_get(sym.to_s.camelize, false) + end + else + raise BaseRequestNotFoundError.new(request_class_arr) + end + end + + end + + end + + + class << self + + def define_request(request_name, options={ :inherit => [:request] }, &block) + RequestBuilder.define_request self, request_name, options, &block + end + + end # class << self + +end \ No newline at end of file diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/response.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/response.rb new file mode 100644 index 000000000..12c9561af --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/response.rb @@ -0,0 +1,52 @@ +module Aviator + + class Response + extend Forwardable + + def_delegators :@response, :status + + attr_reader :request + + def initialize(response, request) + @response = response + @request = request + end + + + def body + @body ||= if raw_body.length > 0 + if Aviator::Compatibility::RUBY_1_8_MODE + clean_body = raw_body.gsub(/\\ /, ' ') + else + clean_body = raw_body + end + + Hashish.new(JSON.parse(clean_body)) + else + Hashish.new({}) + end + end + + + def headers + @headers ||= Hashish.new(@response.headers) + end + + + def to_hash + Hashish.new({ + :status => status, + :headers => headers, + :body => body + }) + end + + private + + def raw_body + @raw_body ||= @response.body + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/service.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/service.rb new file mode 100644 index 000000000..f31645549 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/service.rb @@ -0,0 +1,169 @@ +module Aviator + + # + # Manages a service + # + class Service + + class AccessDetailsNotDefinedError < StandardError + def initialize + super ":access_details is not defined." + end + end + + class ProviderNotDefinedError < StandardError + def initialize + super ":provider is not defined." + end + end + + class ServiceNameNotDefinedError < StandardError + def initialize + super ":service is not defined." + end + end + + class SessionDataNotProvidedError < StandardError + def initialize(service_name, request_name) + super "\n\nERROR: default_session_data is not initialized and no session data was provided in\n"\ + "the method call. You have two ways to fix this:\n\n"\ + " 1) Call Session#authenticate before calling Session##{service_name}_service, or\n\n"\ + " 2) If you're really sure you don't want to authenticate beforehand,\n"\ + " construct the method call this way:\n\n"\ + " service = session.#{service_name}_service\n"\ + " service.request :#{request_name}, :api_version => :v2, :session_data => sessiondatavar\n\n"\ + " Replace :v2 with whatever available version you want to use and make sure sessiondatavar\n"\ + " is a hash that contains, at least, the :base_url key. Other keys, such as :service_token may\n"\ + " be needed depending on what the request class you are calling requires.\n\n" + end + end + + class UnknownRequestError < StandardError + def initialize(request_name, options) + super "Unknown request #{ request_name } #{ options }." + end + end + + + class MissingServiceEndpointError < StandardError + def initialize(service_name, request_name) + request_name = request_name.to_s.split('::').last.underscore + super "The session's service catalog does not have an entry for the #{ service_name } "\ + "service. Therefore, I don't know to which base URL the request should be sent. "\ + "This may be because you are using a default or unscoped token. If this is not your "\ + "intention, please authenticate with a scoped token. If using a default token is your "\ + "intention, make sure to provide a base url when you call the request. For :example => \n\n"\ + "session.#{ service_name }_service.request :#{ request_name }, :base_url => 'http://myenv.com:9999/v2.0' do |params|\n"\ + " params[:example1] = 'example1'\n"\ + " params[:example2] = 'example2'\n"\ + "end\n\n" + end + end + + attr_accessor :default_session_data + + attr_reader :service, + :provider + + + def initialize(opts={}) + @provider = opts[:provider] || (raise ProviderNotDefinedError.new) + @service = opts[:service] || (raise ServiceNameNotDefinedError.new) + @log_file = opts[:log_file] + @default_options = opts[:default_options] || {} + + @default_session_data = opts[:default_session_data] + + load_requests + end + + # + # No longer recommended for public use. Use Aviator::Session#request instead + # + def request(request_name, options={}, ¶ms) + if options[:api_version].nil? && @default_options[:api_version] + options[:api_version] = @default_options[:api_version] + end + + session_data = options[:session_data] || default_session_data + + raise SessionDataNotProvidedError.new(@service, request_name) unless session_data + + [:base_url].each do |k| + session_data[k] = options[k] if options[k] + end + + request_class = provider_module.find_request(service, request_name, session_data, options) + + raise UnknownRequestError.new(request_name, options) unless request_class + + # Always use :params over ¶ms if provided + if options[:params] + params = lambda do |params| + options[:params].each do |key, value| + begin + params[key] = value + rescue NameError => e + raise NameError.new("Unknown param name '#{key}'") + end + end + end + end + + request = request_class.new(session_data, ¶ms) + + response = http_connection.send(request.http_method) do |r| + r.url request.url + r.headers.merge!(request.headers) if request.headers? + r.query = request.querystring if request.querystring? + r.body = JSON.generate(request.body) if request.body? + end + + Aviator::Response.send(:new, response, request) + end + + + def request_classes + @request_classes + end + + + private + + + def http_connection + @http_connection ||= Faraday.new do |conn| + conn.use Logger.configure(log_file) if log_file + conn.adapter Faraday.default_adapter + + conn.headers['Content-Type'] = 'application/json' + end + end + + + def load_requests + request_file_paths = provider_module.request_file_paths(service) + request_file_paths.each{ |path| require path } + + constant_parts = request_file_paths \ + .map{|rf| rf.to_s.match(/#{provider}\/#{service}\/([\w\/]+)\.rb$/) } \ + .map{|rf| rf[1].split('/').map{|c| c.camelize }.join('::') } + + @request_classes = constant_parts.map do |cp| + "Aviator::#{provider.camelize}::#{service.camelize}::#{cp}".constantize + end + end + + + def log_file + @log_file + end + + + def provider_module + @provider_module ||= "Aviator::#{provider.camelize}::Provider".constantize + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/session.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/session.rb new file mode 100644 index 000000000..f93db097c --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/session.rb @@ -0,0 +1,491 @@ +# +# Author:: Mark Maglana (mmaglana@gmail.com) +# Copyright:: Copyright (c) 2014 Mark Maglana +# License:: Distributed under the MIT license +# Homepage:: http://aviator.github.io/www/ +# +module Aviator + + # + # Manages a provider (e.g. OpenStack) session and serves as the entry point + # for a consumer class/object. See Session::new for notes on usage. + # + class Session + + class AuthenticationError < StandardError + def initialize(last_auth_body) + super("Authentication failed. The server returned #{ last_auth_body }") + end + end + + + class EnvironmentNotDefinedError < ArgumentError + def initialize(path, env) + super("The environment '#{ env }' is not defined in #{ path }.") + end + end + + class InitializationError < StandardError + def initialize + super("The session could not find :session_dump, :config_file, and " \ + ":config in the constructor arguments provided") + end + end + + class InvalidConfigFilePathError < ArgumentError + def initialize(path) + super("The config file at #{ path } does not exist!") + end + end + + + class NotAuthenticatedError < StandardError + def initialize + super("Session is not authenticated. Please authenticate before proceeding.") + end + end + + + class ValidatorNotDefinedError < StandardError + def initialize + super("The validator request name is not defined for this session object.") + end + end + + # + # Create a new Session instance. + # + # Initialize with a config file + # + # Aviator::Session.new(:config_file => 'path/to/aviator.yml', :environment => :production) + # + # In the above example, the config file must have the following form: + # + # production: + # provider: openstack + # auth_service: + # name: identity + # host_uri: 'http://my.openstackenv.org:5000' + # request: create_token + # validator: list_tenants + # api_version: v2 + # auth_credentials: + # username: myusername + # password: mypassword + # tenant_name: myproject + # + # SIDENOTE: For more information about the validator member, see Session#validate. + # + # Once the session has been instantiated, you may authenticate against the + # provider as follows: + # + # session.authenticate + # + # The members you put under auth_credentials will depend on the request + # class you declare under auth_service:request and what parameters it + # accepts. To know more about a request class and its parameters, you can use + # the CLI tool aviator describe or view the request definition file directly. + # + # If writing the auth_credentials in the config file is not acceptable, + # you may omit it and just supply the credentials at runtime. For example: + # + # session.authenticate do |params| + # params.username = ARGV[0] + # params.password = ARGV[1] + # params.tenant_name = ARGV[2] + # end + # + # See Session#authenticate for more info. + # + # Note that while the example config file above only has one environment (production), + # you can declare an arbitrary number of environments in your config file. Shifting + # between environments is as simple as changing the :environment to refer to that. + # + # + # Initialize with an in-memory hash + # + # You can create an in-memory hash with a structure similar to the config file but without + # the environment name. For example: + # + # configuration = { + # :provider => 'openstack', + # :auth_service => { + # :name => 'identity', + # :host_uri => 'http://devstack:5000/v2.0', + # :request => 'create_token', + # :validator => 'list_tenants' + # } + # } + # + # Supply this to the initializer using the :config option. For example: + # + # Aviator::Session.new(:config => configuration) + # + # + # Initialize with a session dump + # + # You can create a new Session instance using a dump from another instance. For example: + # + # session_dump = session1.dump + # session2 = Aviator::Session.new(:session_dump => session_dump) + # + # However, Session.load is cleaner and recommended over this method. + # + # + # Optionally supply a log file + # + # In all forms above, you may optionally add a :log_file option to make + # Aviator write all HTTP calls to the given path. For example: + # + # Aviator::Session.new(:config_file => 'path/to/aviator.yml', :environment => :production, :log_file => 'path/to/log') + # + def initialize(opts={}) + if opts.has_key? :session_dump + initialize_with_dump(opts[:session_dump]) + elsif opts.has_key? :config_file + initialize_with_config(opts[:config_file], opts[:environment]) + elsif opts.has_key? :config + initialize_with_hash(opts[:config]) + else + raise InitializationError.new + end + + @log_file = opts[:log_file] + end + + # + # Authenticates against the backend provider using the auth_service request class + # declared in the session's configuration. Please see Session.new for more information + # on declaring the request class to use for authentication. + # + # Request params block + # + # If the auth_service request class accepts parameters, you may supply that + # as a block and it will be directly passed to the request. For example: + # + # session = Aviator::Session.new(:config => config) + # session.authenticate do |params| + # params.username = username + # params.password = password + # params.tenant_name = project + # end + # + # If your configuration happens to have an auth_credentials in it, those + # will be overridden by this block. + # + # Treat parameters as a hash + # + # You can also treat the params struct like a hash with the attribute + # names as the keys. For example, we can rewrite the above as: + # + # session = Aviator::Session.new(:config => config) + # session.authenticate do |params| + # params[:username] = username + # params[:password] = password + # params[:tenant_name] = project + # end + # + # Keys can be symbols or strings. + # + # Use a hash argument instead of a block + # + # You may also provide request params as an argument instead of a block. This is + # especially useful if you want to mock Aviator as it's easier to specify ordinary + # argument expectations over blocks. Further rewriting the example above, + # we end up with: + # + # session = Aviator::Session.new(:config => config) + # session.authenticate :params => { + # :username => username, + # :password => password, + # :tenant_name => project + # } + # + # If both :params and a block are provided, the :params + # values will be used and the block ignored. + # + # Success requirements + # + # Expects an HTTP status 200 or 201 response from the backend. Any other + # status is treated as a failure. + # + def authenticate(opts={}, &block) + block ||= lambda do |params| + config[:auth_credentials].each do |key, value| + begin + params[key] = value + rescue NameError => e + raise NameError.new("Unknown param name '#{key}'") + end + end + end + + response = auth_service.request(config[:auth_service][:request].to_sym, opts, &block) + + if [200, 201].include? response.status + @auth_response = Hashish.new({ + :headers => response.headers, + :body => response.body + }) + update_services_session_data + else + raise AuthenticationError.new(response.body) + end + self + end + + # + # Returns true if the session has been authenticated. Note that this relies on + # cached response from a previous run of Session#authenticate if one was made. + # If you want to check against the backend provider if the session is still valid, + # use Session#validate instead. + # + def authenticated? + !auth_response.nil? + end + + # + # Returns its configuration. + # + def config + @config + end + + # + # Returns a JSON string of its configuration and auth_data. This string can be streamed + # or stored and later re-loaded in another Session instance. For example: + # + # session = Aviator::Session.new(:config => configuration) + # str = session.dump + # + # # time passes... + # + # session = Aviator::Session.load(str) + # + def dump + JSON.generate({ + :config => config, + :auth_response => auth_response + }) + end + + + # + # Same as Session::load but re-uses the Session instance this method is + # called on instead of creating a new one. + # + def load(session_dump) + initialize_with_dump(session_dump) + update_services_session_data + self + end + + + def method_missing(name, *args, &block) # :nodoc: + service_name_parts = name.to_s.match(/^(\w+)_service$/) + + if service_name_parts + get_service_obj(service_name_parts[1]) + else + super name, *args, &block + end + end + + + # + # Creates a new Session object from a previous session's dump. See Session#dump for + # more information. + # + # If you want the newly deserialized session to log its output, add a :log_file + # option. + # + # Aviator::Session.load(session_dump_str, :log_file => 'path/to/aviator.log') + # + def self.load(session_dump, opts={}) + opts[:session_dump] = session_dump + + new(opts) + end + + + # + # Returns the log file path. May be nil if none was provided during initialization. + # + def log_file + @log_file + end + + + # + # Calls the given request of the given service. An example call might look like: + # + # session.request :compute_service, :create_server do |p| + # p.name = "My Server" + # p.image_ref = "7cae8c8e-fb01-4a88-bba3-ae0fcb1dbe29" + # p.flavor_ref = "fa283da1-59a5-4245-8569-b6eadf69f10b" + # end + # + # Note that you can also treat the block's argument like a hash with the attribute + # names as the keys. For example, we can rewrite the above as: + # + # session.request :compute_service, :create_server do |p| + # p[:name] = "My Server" + # p[:image_ref] = "7cae8c8e-fb01-4a88-bba3-ae0fcb1dbe29" + # p[:flavor_ref] = "fa283da1-59a5-4245-8569-b6eadf69f10b" + # end + # + # Keys can be symbols or strings. + # + # You may also provide parameters as an argument instead of a block. This is + # especially useful when mocking Aviator as it's easier to specify ordinary + # argument expectations over blocks. Further rewriting the example above, + # we end up with: + # + # session.request :compute_service, :create_server, :params => { + # :name => "My Server", + # :image_ref => "7cae8c8e-fb01-4a88-bba3-ae0fcb1dbe29", + # :flavor_ref => "fa283da1-59a5-4245-8569-b6eadf69f10b" + # } + # + # If both :params and a block are provided, the values in :params + # will be used and the block ignored. + # + # Return Value + # + # The return value will be an instance of Hashish, a lightweight replacement for + # activesupport's HashWithIndifferentAccess, with the following structure: + # + # { + # :status => 200, + # :headers => { + # 'X-Auth-Token' => 'd9186f45ce5446eaa0adc9def1c46f5f', + # 'Content-Type' => 'application/json' + # }, + # :body => { + # :some_key => :some_value + # } + # } + # + # Note that the members in :headers and :body will vary depending + # on the provider and the request that was made. + # + # --- + # + # Request Options + # + # You can further customize how the method behaves by providing one or more + # options to the call. For example, assuming you are using the openstack + # provider, the following will call the :create_server request of the + # v1 API of :compute_service. + # + # session.request :compute_service, :create_server, :api_version => v1, :params => params + # + # The available options vary depending on the provider. See the documentation + # on the provider's Provider class for more information (e.g. Aviator::Openstack::Provider) + # + def request(service_name, request_name, opts={}, &block) + service = send("#{service_name.to_s}_service") + response = service.request(request_name, opts, &block) + response.to_hash + end + + + # + # Returns true if the session is still valid in the underlying provider. This method calls + # the validator request class declared under auth_service in the + # configuration. The validator can be any request class as long as: + # + # * The request class exists! + # * Is not an anonymous request. Otherwise it will always return true. + # * Does not require any parameters + # * It returns an HTTP status 200 or 203 to indicate auth info validity. + # * It returns any other HTTP status to indicate that the auth info is invalid. + # + # See Session::new for an example on how to specify the request class to use for session validation. + # + # Note that this method requires the session to be previously authenticated otherwise a + # NotAuthenticatedError will be raised. If you just want to check if the session was previously + # authenticated, use Session#authenticated? instead. + # + def validate + raise NotAuthenticatedError.new unless authenticated? + raise ValidatorNotDefinedError.new unless config[:auth_service][:validator] + + auth_with_bootstrap = auth_response.merge({ :auth_service => config[:auth_service] }) + + response = auth_service.request config[:auth_service][:validator].to_sym, :session_data => auth_with_bootstrap + response.status == 200 || response.status == 203 + end + + + private + + + def auth_response + @auth_response + end + + + def auth_service + @auth_service ||= Service.new( + :provider => config[:provider], + :service => config[:auth_service][:name], + :default_session_data => { :auth_service => config[:auth_service] }, + :log_file => log_file + ) + end + + + def get_service_obj(service_name) + @services ||= {} + + if @services[service_name].nil? + default_options = config["#{ service_name }_service"] + + @services[service_name] = Service.new( + :provider => config[:provider], + :service => service_name, + :default_session_data => auth_response, + :default_options => default_options, + :log_file => log_file + ) + end + + @services[service_name] + end + + + def initialize_with_config(config_path, environment) + raise InvalidConfigFilePathError.new(config_path) unless Pathname.new(config_path).file? + + all_config = Hashish.new(YAML.load_file(config_path)) + + raise EnvironmentNotDefinedError.new(config_path, environment) unless all_config[environment] + + @config = all_config[environment] + end + + + def initialize_with_dump(session_dump) + session_info = Hashish.new(JSON.parse(session_dump)) + @config = session_info[:config] + @auth_response = session_info[:auth_response] + end + + + def initialize_with_hash(hash_obj) + @config = Hashish.new(hash_obj) + end + + + def update_services_session_data + return unless @services + + @services.each do |name, obj| + obj.default_session_data = auth_response + end + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/utils/compatibility.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/utils/compatibility.rb new file mode 100644 index 000000000..560fc2b70 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/utils/compatibility.rb @@ -0,0 +1,34 @@ +module Aviator + + module Compatibility + RUBY_1_8_MODE = (not (RUBY_VERSION =~ /1\.8\.\d*/).nil?) + end + +end + +if Aviator::Compatibility::RUBY_1_8_MODE + + class Module + + alias_method :old_const_defined?, :const_defined? + + def const_defined?(sym, ignore=nil) + old_const_defined?(sym) + end + + + alias_method :old_const_get, :const_get + + def const_get(sym, ignore=nil) + old_const_get(sym) + end + + alias_method :old_instance_methods, :instance_methods + + def instance_methods(include_super=true) + old_instance_methods(include_super).map(&:to_sym) + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/utils/hashish.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/utils/hashish.rb new file mode 100644 index 000000000..b50b5bf92 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/utils/hashish.rb @@ -0,0 +1,127 @@ +require 'json' + +# Hash-ish! +# +# This class is implemented using composition rather than inheritance so +# that we have control over what operations it exposes to peers. +class Hashish + include Enumerable + + def initialize(hash={}) + @hash = hash.dup + stringify_keys + hashishify_values + end + + def ==(other_obj) + other_obj.class == self.class && + other_obj.hash == self.hash + end + + def [](key) + @hash[normalize(key)] + end + + def []=(key, value) + @hash[normalize(key)] = value + end + + def dup + Hashish.new(JSON.parse(@hash.to_json)) + end + + def each(&block) + @hash.each(&block) + end + + def empty? + @hash.empty? + end + + def has_key?(name) + @hash.has_key? normalize(name) + end + + def hash + @hash + end + + def keys + @hash.keys + end + + def length + @hash.length + end + + def merge(other_hash) + Hashish.new(@hash.merge(other_hash)) + end + + def merge!(other_hash) + @hash.merge! other_hash + self + end + + def to_json(obj) + @hash.to_json(obj) + end + + def to_s + str = "{" + @hash.each do |key, value| + if value.kind_of? String + value = "'#{value}'" + elsif value.nil? + value = "nil" + elsif value.kind_of? Array + value = "[#{value.join(", ")}]" + end + + str += " #{key}: #{value}," + end + + str = str[0...-1] + " }" + str + end + + private + + # Hashishify all the things! + def hashishify_values + @hash.each do |key, value| + if @hash[key].kind_of? Hash + @hash[key] = Hashish.new(value) + elsif @hash[key].kind_of? Array + @hash[key].each_index do |index| + element = @hash[key][index] + if element.kind_of? Hash + @hash[key][index] = Hashish.new(element) + end + end + end + end + end + + + def normalize(key) + if @hash.has_key? key + key + elsif key.is_a? Symbol + key.to_s + else + key + end + end + + + def stringify_keys + keys = @hash.keys + keys.each do |key| + if key.is_a? Symbol + @hash[key.to_s] = @hash.delete(key) + end + end + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/utils/string.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/utils/string.rb new file mode 100644 index 000000000..25d24b66e --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/core/utils/string.rb @@ -0,0 +1,24 @@ +class String + + unless instance_methods.include? 'camelize' + define_method :camelize do + word = self.slice(0,1).capitalize + self.slice(1..-1) + word.gsub(/_([a-zA-Z\d])/) { "#{$1.capitalize}" } + end + end + + unless instance_methods.include? 'constantize' + define_method :constantize do + self.split("::").inject(Object) do |namespace, sym| + namespace.const_get(sym.to_s.camelize, false) + end + end + end + + unless instance_methods.include? 'underscore' + define_method :underscore do + self.gsub(/([a-z\d])([A-Z])/, '\1_\2').downcase + end + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/common/requests/v0/public/base.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/common/requests/v0/public/base.rb new file mode 100644 index 000000000..a80b8c850 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/common/requests/v0/public/base.rb @@ -0,0 +1,125 @@ +module Aviator + + define_request :base do + + meta :provider, :openstack + meta :service, :common + meta :api_version, :v0 + meta :endpoint_type, :public + + def headers + {}.tap do |h| + if self.anonymous? + # do nothing + + elsif session_data.has_key? :service_token + # service_token is the token that one would bootstrap OpenStack + # with during the installation process. This token can be used + # directly and does not require authentication beforehand. + h['X-Auth-Token'] = session_data[:service_token] + + elsif keystone_v2_style_session_data? + h['X-Auth-Token'] = session_data[:body][:access][:token][:id] + + elsif keystone_v3_style_session_data? + h['X-Auth-Token'] = session_data[:headers]['x-subject-token'] + + else + raise "Unknown session data format!" + + end + end + end + + + private + + def base_url + if session_data[:base_url] + session_data[:base_url] + + elsif keystone_v2_style_session_data? && keystone_v2_style_service_info? + extract_base_url_from_keystone_v2_session_data + + elsif keystone_v3_style_session_data? && keystone_v3_style_service_info? + extract_base_url_from_keystone_v3_session_data + + elsif session_data[:auth_service] && session_data[:auth_service][:host_uri] && session_data[:auth_service][:api_version] + version = session_data[:auth_service][:api_version].to_s == "v2" ? "v2.0" : session_data[:auth_service][:api_version] + "#{ session_data[:auth_service][:host_uri] }/#{ version }" + + elsif session_data[:auth_service] && session_data[:auth_service][:host_uri] + session_data[:auth_service][:host_uri] + + else + raise Aviator::Service::MissingServiceEndpointError.new(service.to_s, self.class) + end + end + + + def build_service_type_string + api_versions_without_a_suffix = [ + [:compute, :v2], + [:ec2, :v1], + [:identity, :v2], + [:image, :v1], + [:metering, :v1], + [:s3, :v1], + [:volume, :v1] + ] + + if api_versions_without_a_suffix.include? [service, api_version] + service.to_s + else + "#{ service }#{ api_version }" + end + end + + + def extract_base_url_from_keystone_v2_session_data + service_info = session_data[:body][:access][:serviceCatalog].find{ |s| s[:type] == build_service_type_string } + service_info[:endpoints][0]["#{ endpoint_type }URL".to_sym] + end + + + def extract_base_url_from_keystone_v3_session_data + service_info = session_data[:body][:token][:catalog].select{ |s| s[:type] == build_service_type_string } + endpoints = service_info.find{ |s| s.keys.include? "endpoints" }['endpoints'] + + endpoints.find{ |s| s['interface'] == endpoint_type.to_s }['url'] + end + + + def keystone_v2_style_service_info? + not session_data[:body][:access][:serviceCatalog].find{ |s| s[:type] == build_service_type_string }.nil? + end + + + def keystone_v2_style_session_data? + session_data.has_key?(:body) && session_data[:body].has_key?(:access) + end + + + def keystone_v3_style_service_info? + not session_data[:body][:token][:catalog].find{ |s| s[:type] == build_service_type_string }.nil? + end + + + def keystone_v3_style_session_data? + session_data.has_key?(:headers) && session_data[:headers].has_key?("x-subject-token") + end + + + def params_to_querystring(param_names) + filters = [] + + param_names.each do |param_name| + filters << "#{ param_name }=#{ params[param_name] }" if params[param_name] + end + + filters.empty? ? "" : "?#{ filters.join('&') }" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/common/requests/v2/admin/base.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/common/requests/v2/admin/base.rb new file mode 100644 index 000000000..dd07d2f31 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/common/requests/v2/admin/base.rb @@ -0,0 +1,9 @@ +module Aviator + + define_request :base, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :endpoint_type, :admin + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/common/requests/v2/public/base.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/common/requests/v2/public/base.rb new file mode 100644 index 000000000..863a1ddc8 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/common/requests/v2/public/base.rb @@ -0,0 +1,9 @@ +module Aviator + + define_request :base, :inherit => [:openstack, :common, :v0, :public, :base] do + + meta :api_version, :v2 + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/common/requests/v3/public/base.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/common/requests/v3/public/base.rb new file mode 100644 index 000000000..1340aeab0 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/common/requests/v3/public/base.rb @@ -0,0 +1,9 @@ +module Aviator + + define_request :base, :inherit => [:openstack, :common, :v0, :public, :base] do + + meta :api_version, :v3 + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/confirm_server_resize.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/confirm_server_resize.rb new file mode 100644 index 000000000..0c672da8a --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/confirm_server_resize.rb @@ -0,0 +1,36 @@ +module Aviator + + define_request :confirm_server_resize, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Confirm_Resized_Server-d1e3868.html' + + param :id, :required => true + + + def body + { + :confirmResize => nil + } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/create_network.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/create_network.rb new file mode 100644 index 000000000..f45ef1a78 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/create_network.rb @@ -0,0 +1,56 @@ +module Aviator + + define_request :create_network, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :compute + + link 'documentation', + 'http://api.openstack.org/api-ref-compute.html#ext-os-networks' + + + param :label, :required => true + param :bridge, :required => false + param :bridge_interface, :required => false + param :cidr, :required => false + param :cidr_v6, :required => false + param :dns1, :required => false + param :dns2, :required => false + param :gateway, :required => false + param :gateway_v6, :required => false + param :multi_host, :required => false + param :project_id, :required => false + param :vlan, :required => false + + + def body + p = { + :network => { + :label => params[:label] + } + } + + optional_params.each do |key| + p[:network][key] = params[key] if params[key] + end + + p + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/os-networks" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/get_host_details.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/get_host_details.rb new file mode 100644 index 000000000..daf25a3cd --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/get_host_details.rb @@ -0,0 +1,29 @@ +module Aviator + + define_request :get_host_details, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :compute + + link 'documentation', + 'http://api.openstack.org/api-ref.html#ext-os-hosts' + + param :host_name, :required => true + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/os-hosts/#{ params[:host_name] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/list_hosts.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/list_hosts.rb new file mode 100644 index 000000000..8c47aa835 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/list_hosts.rb @@ -0,0 +1,44 @@ +module Aviator + + define_request :list_hosts, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :compute + + link 'documentation', + 'http://api.openstack.org/api-ref.html#ext-os-hosts' + + link 'documentation bug', + 'https://bugs.launchpad.net/nova/+bug/1224763' + + param :service, :required => false + param :zone, :required => false + + + def headers + super + end + + + def http_method + :get + end + + + def url + url = "#{ base_url }/os-hosts" + + filters = [] + + optional_params.each do |param_name| + filters << "#{ param_name }=#{ params[param_name] }" if params[param_name] + end + + url += "?#{ filters.join('&') }" unless filters.empty? + + url + end + + end + +end + diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/list_hypervisors.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/list_hypervisors.rb new file mode 100644 index 000000000..5f84de5df --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/list_hypervisors.rb @@ -0,0 +1,27 @@ +module Aviator + + define_request :list_hypervisors, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :compute + + link 'documentation', + 'http://api.openstack.org/api-ref-compute-v2-ext.html#ext-os-hypervisors' + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/os-hypervisors" + end + + end + +end + diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/lock_server.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/lock_server.rb new file mode 100644 index 000000000..6db89fee2 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/lock_server.rb @@ -0,0 +1,34 @@ +module Aviator + + define_request :lock_server, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/POST_lock_v2__tenant_id__servers__server_id__action_ext-os-admin-actions.html' + + param :id, :required => true + + + def body + { :lock => nil } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/migrate_server.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/migrate_server.rb new file mode 100644 index 000000000..56259cdff --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/migrate_server.rb @@ -0,0 +1,34 @@ +module Aviator + + define_request :migrate_server, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/POST_migrate_v2__tenant_id__servers__server_id__action_ext-os-admin-actions.html' + + param :id, :required => true + + + def body + { :migrate => nil } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/reset_server.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/reset_server.rb new file mode 100644 index 000000000..ea8af1f0a --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/reset_server.rb @@ -0,0 +1,39 @@ +module Aviator + + define_request :reset_server, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/POST_os-resetState_v2__tenant_id__servers__server_id__action_ext-os-admin-actions.html' + + param :id, :required => true + param :state, :required => true + + + def body + { + 'os-resetState' => { + 'state' => params[:state] + } + } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/resize_server.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/resize_server.rb new file mode 100644 index 000000000..e4b6582a6 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/resize_server.rb @@ -0,0 +1,41 @@ +module Aviator + + define_request :resize_server, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Resize_Server-d1e3707.html' + + param :id, :required => true + param :name, :required => true + param :flavorRef, :required => true, :alias => :flavor_ref + + + def body + { + :resize => { + :name => params[:name], + :flavorRef => params[:flavorRef] + } + } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/revert_server_resize.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/revert_server_resize.rb new file mode 100644 index 000000000..3eb95164b --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/revert_server_resize.rb @@ -0,0 +1,46 @@ +module Aviator + + define_request :revert_server_resize do + + meta :provider, :openstack + meta :service, :compute + meta :api_version, :v2 + meta :endpoint_type, :admin + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Revert_Resized_Server-d1e4024.html' + + param :id, :required => true + + + def body + { + :revertResize => nil + } + end + + + def headers + h = {} + + unless self.anonymous? + h['X-Auth-Token'] = session_data[:body][:access][:token][:id] + end + + h + end + + + def http_method + :post + end + + + def url + service_spec = session_data[:body][:access][:serviceCatalog].find{|s| s[:type] == service.to_s } + "#{ service_spec[:endpoints][0][:adminURL] }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/unlock_server.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/unlock_server.rb new file mode 100644 index 000000000..eede63524 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/admin/unlock_server.rb @@ -0,0 +1,34 @@ +module Aviator + + define_request :unlock_server, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/POST_unlock_v2__tenant_id__servers__server_id__action_ext-os-admin-actions.html' + + param :id, :required => true + + + def body + { :unlock => nil } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/add_floating_ip.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/add_floating_ip.rb new file mode 100644 index 000000000..56ff62457 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/add_floating_ip.rb @@ -0,0 +1,38 @@ +module Aviator + + define_request :add_floating_ip, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/POST_os-floating-ips-v2_AddFloatingIP__v2__tenant_id__servers__server_id__action_ext-os-floating-ips.html#POST_os-floating-ips-v2_AddFloatingIP__v2__tenant_id__servers__server_id__action_ext-os-floating-ips-Request' + + param :server_id, :required => true + param :address, :required => true + + def body + { + :addFloatingIp => { + :address => params[:address] + } + } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:server_id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/allocate_floating_ip.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/allocate_floating_ip.rb new file mode 100644 index 000000000..92b9c5c37 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/allocate_floating_ip.rb @@ -0,0 +1,35 @@ +module Aviator + + define_request :allocate_floating_ip, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/POST_os-floating-ips-v2_AllocateFloatingIP__v2__tenant_id__os-floating-ips_ext-os-floating-ips.html' + + param :pool, :required => false + + def body + { + :pool => params[:pool] + } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/os-floating-ips" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/change_admin_password.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/change_admin_password.rb new file mode 100644 index 000000000..03aced50a --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/change_admin_password.rb @@ -0,0 +1,44 @@ +module Aviator + + define_request :change_admin_password, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Change_Password-d1e3234.html' + + link 'additional spec', + 'https://answers.launchpad.net/nova/+question/228462' + + param :adminPass, :required => true, :alias => :admin_pass + param :id, :required => true + + + def body + p = { + :changePassword => { + :adminPass => params[:adminPass] + } + } + + p + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/create_image.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/create_image.rb new file mode 100644 index 000000000..0a4622370 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/create_image.rb @@ -0,0 +1,46 @@ +module Aviator + + define_request :create_image, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Create_Image-d1e4655.html' + + param :id, :required => true + param :metadata, :required => false + param :name, :required => true + + + def body + p = { + :createImage => { + :name => params[:name] + } + } + + [:metadata].each do |key| + p[:createImage][key] = params[key] if params[key] + end + + p + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/create_keypair.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/create_keypair.rb new file mode 100644 index 000000000..b90485fb4 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/create_keypair.rb @@ -0,0 +1,39 @@ +module Aviator + + define_request :create_keypair, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/POST_os-keypairs-v2_createKeypair__v2__tenant_id__os-keypairs_ext-os-keypairs.html' + + param :name, :required => true + param :public_key, :required => false + + def body + { + :keypair => { + :name => params[:name], + :public_key => params[:public_key], + } + } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/os-keypairs" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/create_server.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/create_server.rb new file mode 100644 index 000000000..682223543 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/create_server.rb @@ -0,0 +1,55 @@ +module Aviator + + define_request :create_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/CreateServers.html' + + param :accessIPv4, :required => false, :alias => :access_ipv4 + param :accessIPv6, :required => false, :alias => :access_ipv6 + param :adminPass, :required => false, :alias => :admin_pass + param :imageRef, :required => true, :alias => :image_ref + param :flavorRef, :required => true, :alias => :flavor_ref + param :key_name, :required => false + param :metadata, :required => false + param :name, :required => true + param :networks, :required => false + param :personality, :required => false + + + def body + p = { + :server => { + :flavorRef => params[:flavorRef], + :imageRef => params[:imageRef], + :name => params[:name] + } + } + + [:adminPass, :metadata, :personality, :networks, :accessIPv4, :accessIPv6, :key_name].each do |key| + p[:server][key] = params[key] if params[key] + end + + p + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/delete_image.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/delete_image.rb new file mode 100644 index 000000000..35ea8cf40 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/delete_image.rb @@ -0,0 +1,29 @@ +module Aviator + + define_request :delete_image, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Delete_Image-d1e4957.html' + + param :id, :required => true + + + def headers + super + end + + + def http_method + :delete + end + + + def url + "#{ base_url }/images/#{ params[:id]}" + end + + end + +end \ No newline at end of file diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/delete_image_metadata_item.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/delete_image_metadata_item.rb new file mode 100644 index 000000000..7b1fc3d70 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/delete_image_metadata_item.rb @@ -0,0 +1,31 @@ +module Aviator + + define_request :delete_image_metadata_item, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Delete_Metadata_Item-d1e5790.html' + + + param :id, :required => true + param :key, :required => true + + + def headers + super + end + + + def http_method + :delete + end + + + def url + "#{ base_url }/images/#{ params[:id] }/metadata/#{ params[:key] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/delete_server.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/delete_server.rb new file mode 100644 index 000000000..a991efb8e --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/delete_server.rb @@ -0,0 +1,29 @@ +module Aviator + + define_request :delete_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Delete_Server-d1e2883.html' + + param :id, :required => true + + + def headers + super + end + + + def http_method + :delete + end + + + def url + "#{ base_url }/servers/#{ params[:id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/delete_server_metadata_item.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/delete_server_metadata_item.rb new file mode 100644 index 000000000..facbbb537 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/delete_server_metadata_item.rb @@ -0,0 +1,31 @@ +module Aviator + + define_request :delete_server_metadata_item, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Delete_Metadata_Item-d1e5790.html' + + + param :id, :required => true + param :key, :required => true + + + def headers + super + end + + + def http_method + :delete + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/metadata/#{ params[:key] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_flavor_details.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_flavor_details.rb new file mode 100644 index 000000000..8faeb900e --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_flavor_details.rb @@ -0,0 +1,29 @@ +module Aviator + + define_request :get_flavor_details, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Get_Flavor_Details-d1e4317.html' + + param :id, :required => true + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/flavors/#{ params[:id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_image_details.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_image_details.rb new file mode 100644 index 000000000..b9fd3cce8 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_image_details.rb @@ -0,0 +1,29 @@ +module Aviator + + define_request :get_image_details, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Get_Image_Details-d1e4848.html' + + param :id, :required => true + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/images/#{ params[:id]}" + end + + end + +end \ No newline at end of file diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_image_metadata_item.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_image_metadata_item.rb new file mode 100644 index 000000000..01476744a --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_image_metadata_item.rb @@ -0,0 +1,31 @@ +module Aviator + + define_request :get_image_metadata_item, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Get_Metadata_Item-d1e5507.html' + + + param :id, :required => true + param :key, :required => true + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/images/#{ params[:id] }/metadata/#{ params[:key] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_network_details.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_network_details.rb new file mode 100644 index 000000000..8d4192bfe --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_network_details.rb @@ -0,0 +1,30 @@ +module Aviator + + define_request :get_network_details, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://api.openstack.org/api-ref-compute.html#ext-os-networks' + + + param :id, :required => true + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/os-networks/#{ params[:id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_server.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_server.rb new file mode 100644 index 000000000..e5c391106 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_server.rb @@ -0,0 +1,28 @@ +module Aviator + + define_request :get_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Get_Server_Details-d1e2623.html' + + param :id, :required => true + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/servers/#{ params[:id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_server_metadata_item.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_server_metadata_item.rb new file mode 100644 index 000000000..580320f24 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/get_server_metadata_item.rb @@ -0,0 +1,31 @@ +module Aviator + + define_request :get_server_metadata_item, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Get_Metadata_Item-d1e5507.html' + + + param :id, :required => true + param :key, :required => true + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/metadata/#{ params[:key] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_addresses.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_addresses.rb new file mode 100644 index 000000000..2c6fe60a4 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_addresses.rb @@ -0,0 +1,36 @@ +module Aviator + + define_request :list_addresses, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/List_Addresses-d1e3014.html' + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/List_Addresses_by_Network-d1e3118.html' + + + param :id, :required => true + param :networkID, :required => false, :alias => :network_id + + + def headers + super + end + + + def http_method + :get + end + + + def url + url = "#{ base_url }/servers/#{ params[:id] }/ips" + url += "/#{ params[:networkID] }" if params[:networkID] + url + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_flavors.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_flavors.rb new file mode 100644 index 000000000..9eba13626 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_flavors.rb @@ -0,0 +1,35 @@ +module Aviator + + define_request :list_flavors, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/List_Flavors-d1e4188.html' + + param :details, :required => false + param :minDisk, :required => false, :alias => :min_disk + param :minRam, :required => false, :alias => :min_ram + param :marker, :required => false + param :limit, :required => false + + + def headers + super + end + + + def http_method + :get + end + + + def url + str = "#{ base_url }/flavors" + str += "/detail" if params[:details] + str += params_to_querystring(optional_params + required_params - [:details]) + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_floating_ips.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_floating_ips.rb new file mode 100644 index 000000000..54f07be3a --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_floating_ips.rb @@ -0,0 +1,26 @@ +module Aviator + + define_request :list_floating_ips, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/GET_os-floating-ips-v2_ListFloatingIPs__v2__tenant_id__os-floating-ips_ext-os-floating-ips.html' + + def headers + super + end + + + def http_method + :get + end + + + def url + str = "#{ base_url }/os-floating-ips" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_image_metadata.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_image_metadata.rb new file mode 100644 index 000000000..7b176891f --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_image_metadata.rb @@ -0,0 +1,30 @@ +module Aviator + + define_request :list_image_metadata, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/List_Metadata-d1e5089.html' + + + param :id, :required => true + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/images/#{ params[:id] }/metadata" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_images.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_images.rb new file mode 100644 index 000000000..b282aec97 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_images.rb @@ -0,0 +1,38 @@ +module Aviator + + define_request :list_images, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/List_Images-d1e4435.html' + + param :details, :required => false + param :server, :required => false + param :name, :required => false + param :status, :required => false + param 'changes-since', :required => false, :alias => :changes_since + param :marker, :required => false + param :limit, :required => false + param :type, :required => false + + + def headers + super + end + + + def http_method + :get + end + + + def url + str = "#{ base_url }/images" + str += "/detail" if params[:details] + str += params_to_querystring(optional_params + required_params - [:details]) + end + + end + +end \ No newline at end of file diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_keypairs.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_keypairs.rb new file mode 100644 index 000000000..f01ce0bd6 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_keypairs.rb @@ -0,0 +1,26 @@ +module Aviator + + define_request :list_keypairs, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/GET_os-keypairs-v2_getKeypair__v2__tenant_id__os-keypairs_ext-os-keypairs.html' + + def headers + super + end + + + def http_method + :get + end + + + def url + str = "#{ base_url }/os-keypairs" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_networks.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_networks.rb new file mode 100644 index 000000000..472ab1bd0 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_networks.rb @@ -0,0 +1,27 @@ +module Aviator + + define_request :list_networks, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://api.openstack.org/api-ref-compute.html#ext-os-networks' + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/os-networks" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_server_metadata.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_server_metadata.rb new file mode 100644 index 000000000..d90936c1b --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_server_metadata.rb @@ -0,0 +1,30 @@ +module Aviator + + define_request :list_server_metadata, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/List_Metadata-d1e5089.html' + + + param :id, :required => true + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/metadata" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_servers.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_servers.rb new file mode 100644 index 000000000..f8126f0c5 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/list_servers.rb @@ -0,0 +1,58 @@ +module Aviator + + define_request :list_servers, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/List_Servers-d1e2078.html' + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/GET_listServers_v2__tenant_id__servers_compute_servers.html' + + link 'github :issue => getting all servers', + 'https://github.com/aviator/aviator/issues/35' + + link 'related mailing list discussion', + 'https://lists.launchpad.net/openstack/msg24695.html' + + param :all_tenants, :required => false + param :details, :required => false + param :flavor, :required => false + param :image, :required => false + param :limit, :required => false + param :marker, :required => false + param :server, :required => false + param :status, :required => false + param 'changes-since', :required => false, :alias => :changes_since + + + def headers + super + end + + + def http_method + :get + end + + + def url + str = "#{ base_url }/servers" + str += "/detail" if params[:details] + + filters = [] + + (optional_params + required_params - [:details]).each do |param_name| + value = param_name == :all_tenants && params[param_name] ? 1 : params[param_name] + filters << "#{ param_name }=#{ value }" if value + end + + str += "?#{ filters.join('&') }" unless filters.empty? + + str + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/pause_server.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/pause_server.rb new file mode 100644 index 000000000..00e5ec663 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/pause_server.rb @@ -0,0 +1,34 @@ +module Aviator + + define_request :pause_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/POST_pause_v2__tenant_id__servers__server_id__action_ext-os-admin-actions.html' + + param :id, :required => true + + + def body + { :pause => nil } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/reboot_server.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/reboot_server.rb new file mode 100644 index 000000000..8aa2296da --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/reboot_server.rb @@ -0,0 +1,41 @@ +module Aviator + + define_request :reboot_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Reboot_Server-d1e3371.html' + + param :id, :required => true + param :type, :required => false + + + def body + p = { + :reboot => { + :type => params[:type] || 'SOFT' + } + } + + p + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/rebuild_server.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/rebuild_server.rb new file mode 100644 index 000000000..8383f571a --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/rebuild_server.rb @@ -0,0 +1,53 @@ +module Aviator + + define_request :rebuild_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Rebuild_Server-d1e3538.html' + + param :accessIPv4, :required => false, :alias => :access_ipv4 + param :accessIPv6, :required => false, :alias => :access_ipv6 + param :adminPass, :required => true, :alias => :admin_pass + param :id, :required => true + param :imageRef, :required => true, :alias => :image_ref + param :metadata, :required => false + param :name, :required => true + param :personality, :required => false + + + def body + p = { + :rebuild => { + :adminPass => params[:adminPass], + :imageRef => params[:imageRef], + :name => params[:name] + } + } + + [:accessIPv4, :accessIPv6, :metadata, :personality].each do |key| + p[:rebuild][key] = params[key] if params[key] + end + + p + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/resume_server.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/resume_server.rb new file mode 100644 index 000000000..f220b366c --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/resume_server.rb @@ -0,0 +1,34 @@ +module Aviator + + define_request :resume_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/POST_resume_v2__tenant_id__servers__server_id__action_ext-os-admin-actions.html' + + param :id, :required => true + + + def body + { :resume => nil } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/root.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/root.rb new file mode 100644 index 000000000..3a3c4dabc --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/root.rb @@ -0,0 +1,24 @@ +module Aviator + + define_request :root, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + def headers + super + end + + + def http_method + :get + end + + + def url + uri = URI(base_url) + "#{ uri.scheme }://#{ uri.host }:#{ uri.port.to_s }/v2/" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/set_image_metadata.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/set_image_metadata.rb new file mode 100644 index 000000000..c17976f9e --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/set_image_metadata.rb @@ -0,0 +1,38 @@ +module Aviator + + define_request :set_image_metadata, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Create_or_Replace_Metadata-d1e5358.html' + + + param :id, :required => true + param :metadata, :required => true + + + def body + { + :metadata => params[:metadata] + } + end + + + def headers + super + end + + + def http_method + :put + end + + + def url + "#{ base_url }/images/#{ params[:id] }/metadata" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/set_server_metadata.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/set_server_metadata.rb new file mode 100644 index 000000000..8631c0397 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/set_server_metadata.rb @@ -0,0 +1,38 @@ +module Aviator + + define_request :set_server_metadata, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Create_or_Replace_Metadata-d1e5358.html' + + + param :id, :required => true + param :metadata, :required => true + + + def body + { + :metadata => params[:metadata] + } + end + + + def headers + super + end + + + def http_method + :put + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/metadata" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/suspend_server.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/suspend_server.rb new file mode 100644 index 000000000..a9bb9a52e --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/suspend_server.rb @@ -0,0 +1,34 @@ +module Aviator + + define_request :suspend_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/POST_suspend_v2__tenant_id__servers__server_id__action_ext-os-admin-actions.html' + + param :id, :required => true + + + def body + { :suspend => nil } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/unpause_server.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/unpause_server.rb new file mode 100644 index 000000000..e11089a62 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/unpause_server.rb @@ -0,0 +1,34 @@ +module Aviator + + define_request :unpause_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/POST_unpause_v2__tenant_id__servers__server_id__action_ext-os-admin-actions.html' + + param :id, :required => true + + + def body + { :unpause => nil } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/action" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/update_image_metadata.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/update_image_metadata.rb new file mode 100644 index 000000000..0ec3694b0 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/update_image_metadata.rb @@ -0,0 +1,38 @@ +module Aviator + + define_request :update_image_metadata, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Update_Metadata-d1e5208.html' + + + param :id, :required => true + param :metadata, :required => true + + + def body + { + :metadata => params[:metadata] + } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/images/#{ params[:id] }/metadata" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/update_server.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/update_server.rb new file mode 100644 index 000000000..453c58329 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/update_server.rb @@ -0,0 +1,45 @@ +module Aviator + + define_request :update_server, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/ServerUpdate.html' + + param :accessIPv4, :required => false, :alias => :access_ipv4 + param :accessIPv6, :required => false, :alias => :access_ipv6 + param :id, :required => true + param :name, :required => false + + + def body + p = { + :server => { } + } + + [:name, :accessIPv4, :accessIPv6].each do |key| + p[:server][key] = params[key] if params[key] + end + + p + end + + + def headers + super + end + + + def http_method + :put + end + + + def url + "#{ base_url }/servers/#{ params[:id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/update_server_metadata.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/update_server_metadata.rb new file mode 100644 index 000000000..e1e5ad17d --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/compute/requests/v2/public/update_server_metadata.rb @@ -0,0 +1,38 @@ +module Aviator + + define_request :update_server_metadata, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :compute + + link 'documentation', + 'http://docs.openstack.org/api/openstack-compute/2/content/Update_Metadata-d1e5208.html' + + + param :id, :required => true + param :metadata, :required => true + + + def body + { + :metadata => params[:metadata] + } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/servers/#{ params[:id] }/metadata" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/add_role_to_user_on_tenant.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/add_role_to_user_on_tenant.rb new file mode 100644 index 000000000..e69b196eb --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/add_role_to_user_on_tenant.rb @@ -0,0 +1,33 @@ +module Aviator + + define_request :add_role_to_user_on_tenant, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :identity + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/PUT_addRolesToUserOnTenant_v2.0_tenants__tenantId__users__userId__roles_OS-KSADM__roleId__.html' + + + param :tenant_id, :required => true + param :user_id, :required => true + param :role_id, :required => true + + + def headers + super + end + + + def http_method + :put + end + + + def url + p = params + "#{ base_url }/tenants/#{ p[:tenant_id] }/users/#{ p[:user_id] }/roles/OS-KSADM/#{ p[:role_id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/create_tenant.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/create_tenant.rb new file mode 100644 index 000000000..6578ae060 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/create_tenant.rb @@ -0,0 +1,43 @@ +module Aviator + + define_request :create_tenant, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :identity + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/' + + + param :name, :required => true + param :description, :required => true + param :enabled, :required => true + + + def body + { + :tenant => { + :name => params[:name], + :description => params[:description], + :enabled => params[:enabled] + } + } + end + + + def headers + super + end + + + def http_method + :post + end + + + def url + "#{ base_url }/tenants" + end + + end + +end \ No newline at end of file diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/create_user.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/create_user.rb new file mode 100644 index 000000000..bf82b64e4 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/create_user.rb @@ -0,0 +1,67 @@ +module Aviator + + define_request :create_user do + + meta :provider, :openstack + meta :service, :identity + meta :api_version, :v2 + meta :endpoint_type, :admin + + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/POST_addUser_v2.0_users_.html' + + link 'documentation bug', + 'https://bugs.launchpad.net/keystone/+bug/1110435' + + link 'documentation bug', + 'https://bugs.launchpad.net/keystone/+bug/1226466' + + + param :name, :required => true + param :password, :required => true + + param :email, :required => false + param :enabled, :required => false + param :tenantId, :required => false, :alias => :tenant_id + param :extras, :required => false + + + def body + p = { + :user => {} + } + + (required_params + optional_params).each do |key| + p[:user][key] = params[key] if params[key] + end + + p + end + + + def headers + h = {} + + unless self.anonymous? + h['X-Auth-Token'] = session_data[:body][:access][:token][:id] + end + + h + end + + + def http_method + :post + end + + + def url + service_spec = session_data[:body][:access][:serviceCatalog].find{|s| s[:type] == 'identity' } + "#{ service_spec[:endpoints][0][:adminURL] }/users" + end + + end + +end + diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/delete_role_from_user_on_tenant.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/delete_role_from_user_on_tenant.rb new file mode 100644 index 000000000..4d24469a7 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/delete_role_from_user_on_tenant.rb @@ -0,0 +1,34 @@ +module Aviator + + define_request :delete_role_from_user_on_tenant, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :identity + + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/DELETE_deleteRoleFromUserOnTenant_v2.0_tenants__tenantId__users__userId__roles_OS-KSADM__roleId__.html' + + + param :tenant_id, :required => true + param :user_id, :required => true + param :role_id, :required => true + + + def headers + super + end + + + def http_method + :delete + end + + + def url + p = params + "#{ base_url }/tenants/#{ p[:tenant_id] }/users/#{ p[:user_id] }/roles/OS-KSADM/#{ p[:role_id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/delete_tenant.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/delete_tenant.rb new file mode 100644 index 000000000..63ad6437f --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/delete_tenant.rb @@ -0,0 +1,29 @@ +module Aviator + + define_request :delete_tenant, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :identity + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/DELETE_deleteTenant_v2.0_tenants__tenantId__.html' + + param :id, :required => true + + + def headers + super + end + + + def http_method + :delete + end + + + def url + "#{ base_url }/tenants/#{ params[:id]}" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/delete_user.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/delete_user.rb new file mode 100644 index 000000000..0bee46951 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/delete_user.rb @@ -0,0 +1,39 @@ +module Aviator + + define_request :delete_user do + + meta :provider, :openstack + meta :service, :identity + meta :api_version, :v2 + meta :endpoint_type, :admin + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/DELETE_deleteUser_v2.0_users__userId__.html' + + param :id, :required => true + + + def headers + h = {} + + unless self.anonymous? + h['X-Auth-Token'] = session_data[:body][:access][:token][:id] + end + + h + end + + + def http_method + :delete + end + + + def url + service_spec = session_data[:body][:access][:serviceCatalog].find{|s| s[:type] == service.to_s } + "#{ service_spec[:endpoints][0][:adminURL] }/users/#{ params[:id]}" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/get_tenant_by_id.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/get_tenant_by_id.rb new file mode 100644 index 000000000..fe2dcc986 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/get_tenant_by_id.rb @@ -0,0 +1,30 @@ +module Aviator + + define_request :get_tenant_by_id, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :identity + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/GET_listUsers_v2.0_users_.html' + + + param :id, :required => true + + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/tenants/#{ params[:id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/get_user.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/get_user.rb new file mode 100644 index 000000000..9a1e1431a --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/get_user.rb @@ -0,0 +1,33 @@ +require 'cgi' + +module Aviator + + define_request :get_user, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :provider, :openstack + meta :service, :identity + meta :api_version, :v2 + meta :endpoint_type, :admin + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/GET_getUserByName_v2.0_users__User_Operations.html' + + param :name, :required => true + + def headers + super + end + + + def http_method + :get + end + + + def url + "#{ base_url }/users?name=#{ CGI::escape(params.name) }" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/list_tenants.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/list_tenants.rb new file mode 100644 index 000000000..48d293062 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/list_tenants.rb @@ -0,0 +1,35 @@ +module Aviator + + define_request :list_tenants, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :identity + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/GET_listTenants_v2.0_tenants_Tenant_Operations.html' + + link 'documentation bug', + 'https://bugs.launchpad.net/keystone/+bug/1218601' + + + param :marker, :required => false + param :limit, :required => false + + + def headers + super + end + + + def http_method + :get + end + + + def url + str = "#{ base_url }/tenants" + str += params_to_querystring(optional_params + required_params) + end + + end + +end \ No newline at end of file diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/list_users.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/list_users.rb new file mode 100644 index 000000000..2debeddc6 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/list_users.rb @@ -0,0 +1,37 @@ +module Aviator + + define_request :list_users do + + meta :provider, :openstack + meta :service, :identity + meta :api_version, :v2 + meta :endpoint_type, :admin + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/GET_listUsers_v2.0_users_.html' + + + def headers + h = {} + + unless self.anonymous? + h['X-Auth-Token'] = session_data[:body][:access][:token][:id] + end + + h + end + + + def http_method + :get + end + + + def url + service_spec = session_data[:body][:access][:serviceCatalog].find{|s| s[:type] == 'identity' } + "#{ service_spec[:endpoints][0][:adminURL] }/users" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/update_tenant.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/update_tenant.rb new file mode 100644 index 000000000..91ae3573d --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/update_tenant.rb @@ -0,0 +1,47 @@ +module Aviator + + define_request :update_tenant, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :identity + + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/POST_updateTenant_v2.0_tenants__tenantId__.html' + + + param :id, :required => true + param :name, :required => false + param :enabled, :required => false + param :description, :required => false + + + def body + p = { + :tenant => {} + } + + [:name, :enabled, :description].each do |key| + p[:tenant][key] = params[key] unless params[key].nil? + end + + p + end + + + def headers + super + end + + + def http_method + :put + end + + + def url + "#{ base_url }/tenants/#{ params[:id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/update_user.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/update_user.rb new file mode 100644 index 000000000..31f8fb213 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/admin/update_user.rb @@ -0,0 +1,62 @@ +module Aviator + + define_request :update_user do + + meta :provider, :openstack + meta :service, :identity + meta :api_version, :v2 + meta :endpoint_type, :admin + + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/POST_updateUser_v2.0_users__userId__.html' + + link 'bug', + 'https://bugs.launchpad.net/keystone/+bug/1226475' + + param :id, :required => true + param :name, :required => false + param :password, :required => false + param :email, :required => false + param :enabled, :required => false + param :tenantId, :required => false, :alias => :tenant_id + param :extras, :required => false + + + def body + p = { + :user => {} + } + + optional_params.each do |key| + p[:user][key] = params[key] if params[key] + end + + p + end + + + def headers + h = {} + + unless self.anonymous? + h['X-Auth-Token'] = session_data[:body][:access][:token][:id] + end + + h + end + + + def http_method + :put + end + + + def url + service_spec = session_data[:body][:access][:serviceCatalog].find { |s| s[:type] == service.to_s } + "#{ service_spec[:endpoints][0][:adminURL] }/users/#{ params[:id] }" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/public/create_token.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/public/create_token.rb new file mode 100644 index 000000000..91731d462 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/public/create_token.rb @@ -0,0 +1,62 @@ +module Aviator + + define_request :create_token, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :anonymous, true + meta :service, :identity + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/POST_authenticate_v2.0_tokens_.html' + + link 'documentation bug', + 'https://bugs.launchpad.net/keystone/+bug/1208607' + + + param :username, :required => false + param :password, :required => false + param :tokenId, :required => false, :alias => :token_id + param :tenantName, :required => false, :alias => :tenant_name + param :tenantId, :required => false, :alias => :tenant_id + + + def body + p = if params[:tokenId] + { + :auth => { + :token => { + :id => params[:tokenId] + } + } + } + else + { + :auth => { + :passwordCredentials => { + :username => params[:username], + :password => params[:password] + } + } + } + end + + p[:auth][:tenantName] = params[:tenantName] if params[:tenantName] + p[:auth][:tenantId] = params[:tenantId] if params[:tenantId] + + p + end + + + def http_method + :post + end + + + def url + url = session_data[:auth_service][:host_uri] + url += '/v2.0' if (URI(url).path =~ /^\/?\w+/).nil? + url += "/tokens" + end + + end + +end \ No newline at end of file diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/public/list_tenants.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/public/list_tenants.rb new file mode 100644 index 000000000..094032ab0 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/public/list_tenants.rb @@ -0,0 +1,35 @@ +module Aviator + + define_request :list_tenants, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :identity + + link 'documentation', + 'http://docs.openstack.org/api/openstack-identity-service/2.0/content/GET_listTenants_v2.0_tokens_tenants_.html' + + link 'documentation bug', + 'https://bugs.launchpad.net/keystone/+bug/1218601' + + + param :marker, :required => false + param :limit, :required => false + + + def url + str = "#{ base_url }/tenants" + str += params_to_querystring(optional_params + required_params) + end + + + def headers + super + end + + + def http_method + :get + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/public/root.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/public/root.rb new file mode 100644 index 000000000..0c6d38358 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v2/public/root.rb @@ -0,0 +1,25 @@ +module Aviator + + define_request :root, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :identity + + + def headers + super + end + + + def http_method + :get + end + + + def url + uri = URI(base_url) + "#{ uri.scheme }://#{ uri.host }:#{ uri.port.to_s }/v2.0/" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v3/public/create_token.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v3/public/create_token.rb new file mode 100644 index 000000000..17d8bb078 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/identity/requests/v3/public/create_token.rb @@ -0,0 +1,125 @@ +module Aviator + # Original work by Stephen Paul Suarez + # https://github.com/musashi-dev/aviator/blob/develop/lib/aviator/openstack/identity/v3/public/create_token.rb + + define_request :create_token, :inherit => [:openstack, :common, :v3, :public, :base] do + + meta :anonymous, true + meta :service, :identity + meta :api_version, :v3 + + link 'documentation', + 'http://api.openstack.org/api-ref-identity-v3.html#Token_Calls' + + param :domainId, :required => false, :alias => :domain_id + param :domainName, :required => false, :alias => :domain_name + param :password, :required => false + param :tenantId, :required => false, :alias => :tenant_id + param :tenantName, :required => false, :alias => :tenant_name + param :tokenId, :required => false, :alias => :token_id + param :userId, :required => false, :alias => :user_id + param :username, :required => false + + + def body + params[:token_id] ? token_auth_body : password_auth_body + end + + + def http_method + :post + end + + + def url + url = session_data[:auth_service][:host_uri] + url += '/v3' if (URI(url).path =~ /^\/?\w+/).nil? + url += "/auth/tokens" + end + + + private + + # Removes nil elements from hash + # Adapted from http://stackoverflow.com/a/14773555/402145 + def compact_hash(hash, opts = {}) + opts[:recurse] ||= true + hash.inject({}) do |new_hash, (k,v)| + if !v.nil? + new_hash[k] = opts[:recurse] && v.kind_of?(Hash) ? compact_hash(v, opts) : v + end + new_hash + end + end + + + def domain_hash + compact_hash({ + :id => params[:domain_id], + :name => params[:domain_name] + }) + end + + + def password_auth_body + p = { + :auth => { + :identity => { + :methods => ['password'], + :password => { + :user => compact_hash({ + :id => params[:user_id], + :name => params[:username], + :password => params[:password] + }) + } + } + } + } + + if params[:domain_name] || params[:domain_id] + p[:auth][:identity][:password][:user][:domain] = domain_hash + end + + if params[:tenant_name] || params[:tenant_id] || params[:domain_name] || params[:domain_id] + p[:auth][:scope] = scope_hash + end + p + end + + + def scope_hash + p = {} + + if params[:tenant_name] || params[:tenant_id] + p[:project] = compact_hash({ + :id => params[:tenant_id], + :name => params[:tenant_name] + }) + p[:project][:domain] = domain_hash if params[:domain_name] || params[:domain_id] + + elsif params[:domain_name] || params[:domain_id] + p[:domain] = domain_hash + end + + p + end + + + def token_auth_body + p = { + :auth => { + :identity => { + :methods => ['token'], + :token => { :id => params[:token_id] } + } + } + } + p[:auth][:scope] = scope_hash if params[:tenant_name] || params[:tenant_id] + p + end + + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/image/requests/v1/public/list_public_images.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/image/requests/v1/public/list_public_images.rb new file mode 100644 index 000000000..2164d73eb --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/image/requests/v1/public/list_public_images.rb @@ -0,0 +1,45 @@ +module Aviator + + define_request :list_public_images, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :image + meta :api_version, :v1 + + link 'documentation', 'http://docs.openstack.org/api/openstack-image-service/1.1/content/requesting-a-list-of-public-vm-images.html' + + param :name, :required => false + param :container_format, :required => false + param :disk_format, :required => false + param :status, :required => false + param :size_min, :required => false + param :size_max, :required => false + param :sort_key, :required => false + param :sort_dir, :required => false + + + def headers + super + end + + def http_method + :get + end + + def url + uri = URI(base_url) + url = "#{ uri.scheme }://#{ uri.host }:#{ uri.port.to_s }/v1/images" + + filters = [] + + optional_params.each do |param_name| + filters << "#{ param_name }=#{ params[param_name] }" if params[param_name] + end + + url += "?#{ filters.join('&') }" unless filters.empty? + + url + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/image/requests/v1/public/root.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/image/requests/v1/public/root.rb new file mode 100644 index 000000000..553f5369e --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/image/requests/v1/public/root.rb @@ -0,0 +1,25 @@ +module Aviator + + define_request :root, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :image + meta :api_version, :v1 + + def headers + super + end + + + def http_method + :get + end + + + def url + uri = URI(base_url) + "#{ uri.scheme }://#{ uri.host }:#{ uri.port.to_s }/v1/" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/metering/requests/v1/admin/list_projects.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/metering/requests/v1/admin/list_projects.rb new file mode 100644 index 000000000..7ec8e667d --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/metering/requests/v1/admin/list_projects.rb @@ -0,0 +1,27 @@ +module Aviator + + define_request :list_projects, :inherit => [:openstack, :common, :v2, :admin, :base] do + + meta :service, :metering + meta :api_version, :v1 + meta :endpoint_type, :admin + + + def headers + super + end + + + def http_method + :get + end + + + def url + uri = URI(base_url) + "#{ uri.scheme }://#{ uri.host }:#{ uri.port.to_s }/v1/projects" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/provider.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/provider.rb new file mode 100644 index 000000000..a4c64e806 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/provider.rb @@ -0,0 +1,187 @@ +module Aviator +module Openstack + + # + # Request Options + # + # The following options may be used in combination with each other when calling + # an OpenStack request class + # + # :api_version => :v2:: + # Forces Aviator to use the request class for the v2 API. For any other + # version, replace :v2 with the desired one. Note that this may throw an + # error if no such request class for the given api version exists. If you + # want to globally specify the API version to use for a specific service, + # declare it in your config file under the correct environment. For example: + # + # production: + # provider: openstack + # ... + # compute_service: + # api_version: v2 + # + # Note that the :api_version option overrides whatever is declared in the + # configuration. + # + # :endpoint_type => (:public|:admin):: + # This allows you to be specific about the endpoint type in cases where two + # request classes under admin and public endpoints of the same service share + # the same name. This is true, for example, for the :list_tenants request of + # the identity service's v2 API. Its public endpoint will return only the tenants + # the user is a member of whereas the admin endpoint will return all tenants + # in the system. + # + # :session_data => Hash:: + # Under normal situations, you wouldn't need to use this as it is automatically populated + # by the Session object provided it is authenticated. The specific use case when you'd + # need to set thsi optin is when you want to use Aviator to seed your OpenStack installation. + # In such a scenario, you would need to use a service token since no usernames and tenants + # would exist yet in the environment. To use a service token with Aviator, you will need to + # write something similar to the following example: + # + # openstack = Aviator::Session.new(:config => { :provider => 'openstack'}) + # + # session_data = {:base_url => 'http://example.com', + # :service_token => 'service-token-created-at-openstack-install-time'} + # + # openstack.request :identity, :create_tenant, :api_version => :v2, :session_data => session_data) do |params| + # params.name = 'Tenant A' + # params.description = 'First Tenant!' + # params.enabled = true + # end + # + # Notice how the above code skips authentication. This is because the service token is + # pre-validated and ready for use with any request. Also note how we're providing a :base_url + # member in our session data. This is necessary since we normally get the service endpoints from + # Keystone when we authenticate. Now since we are not authenticating against Keystone, we don't have + # that catalogue to begin with. Thus the need to hardcode it in the request. + # + module Provider + + class MultipleServiceApisError < StandardError + def initialize(service, entries, request_name) + types = entries.map{|e| e[:type] }.join("\n - ") + msg = < :v2 { ... } + +If you combine the two methods, method #2 will override method #1 + +EOF + super(msg) + end + end + + class << self + + #:nodoc: + def find_request(service, name, session_data, options) + service = service.to_s + endpoint_type = options[:endpoint_type] + endpoint_types = if endpoint_type + [endpoint_type.to_s.camelize] + else + ['Public', 'Admin'] + end + + namespace = Aviator.const_get('Openstack') \ + .const_get(service.camelize) \ + .const_get('Requests') + + if options[:api_version] + m = options[:api_version].to_s.match(/(v\d+)\.?\d*/) + version = m[1].to_s.camelize unless m.nil? + end + + version ||= infer_version(session_data, name, service) + + unless version.nil? + version = version.to_s.camelize + end + + return nil unless version && namespace.const_defined?(version) + + namespace = namespace.const_get(version, name) + + endpoint_types.each do |endpoint_type| + name = name.to_s.camelize + + next unless namespace.const_defined?(endpoint_type) + next unless namespace.const_get(endpoint_type).const_defined?(name) + + return namespace.const_get(endpoint_type).const_get(name) + end + + nil + end + + + def root_dir + Pathname.new(__FILE__).join('..').expand_path + end + + + def request_file_paths(service) + Dir.glob(Pathname.new(__FILE__).join( + '..', + service.to_s, + 'requests', + '**', + '*.rb' + ).expand_path + ) + end + + + private + + def infer_version(session_data, request_name, service) + if session_data.has_key?(:auth_service) && session_data[:auth_service][:api_version] + session_data[:auth_service][:api_version].to_sym + + elsif session_data.has_key?(:auth_service) && session_data[:auth_service][:host_uri] + m = session_data[:auth_service][:host_uri].match(/(v\d+)\.?\d*/) + return m[1].to_sym unless m.nil? + + elsif session_data.has_key? :base_url + m = session_data[:base_url].match(/(v\d+)\.?\d*/) + return m[1].to_sym unless m.nil? + + elsif session_data.has_key?(:body) && session_data[:body].has_key?(:access) + service_specs = session_data[:body][:access][:serviceCatalog].select{|s| s[:type].match("#{ service }(v\d+)?") } + raise MultipleServiceApisError.new(service, service_specs, request_name) unless service_specs.length <= 1 + raise Aviator::Service::MissingServiceEndpointError.new(service.to_s, request_name) unless service_specs.length > 0 + version = service_specs[0][:endpoints][0][:publicURL].match(/(v\d+)\.?\d*/) + version ? version[1].to_sym : :v1 + + elsif session_data.has_key?(:headers) && session_data[:headers].has_key?("x-subject-token") + service_specs = session_data[:body][:token][:catalog].select{|s| s[:type].match("#{ service }(v\d+)?") } + raise MultipleServiceApisError.new(service, service_specs, request_name) unless service_specs.length <= 1 + raise Aviator::Service::MissingServiceEndpointError.new(service.to_s, request_name) unless service_specs.length > 0 + version = service_specs[0][:endpoints][0][:url].match(/(v\d+)\.?\d*/) + version ? version[1].to_sym : :v1 + end + end + + end # class << self + + end # module Provider + +end # module Openstack +end # module Aviator diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/create_volume.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/create_volume.rb new file mode 100644 index 000000000..f40354d99 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/create_volume.rb @@ -0,0 +1,47 @@ +module Aviator + + define_request :create_volume, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :volume + meta :api_version, :v1 + + link 'documentation', 'http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/POST_createVolume_v1__tenant_id__volumes_v1__tenant_id__volumes.html' + + param :display_name, :required => true + param :display_description, :required => true + param :size, :required => true + param :volume_type, :required => false + param :availability_zone, :required => false + param :snapshot_id, :required => false + param :metadata, :required => false + + def body + p = { + :volume => { + :display_name => params[:display_name], + :display_description => params[:display_description], + :size => params[:size] + } + } + + optional_params.each do |key| + p[:volume][key] = params[key] if params[key] + end + + p + end + + def headers + super + end + + def http_method + :post + end + + def url + "#{ base_url }/volumes" + end + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/delete_volume.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/delete_volume.rb new file mode 100644 index 000000000..1397959aa --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/delete_volume.rb @@ -0,0 +1,25 @@ +module Aviator + + define_request :delete_volume, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :volume + meta :api_version, :v1 + + link 'documentation', 'http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/DELETE_deleteVolume_v1__tenant_id__volumes__volume_id__v1__tenant_id__volumes.html' + + param :id, :required => true + + def headers + super + end + + def http_method + :delete + end + + def url + "#{ base_url }/volumes/#{ params[:id] }" + end + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/get_volume.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/get_volume.rb new file mode 100644 index 000000000..991dc4454 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/get_volume.rb @@ -0,0 +1,28 @@ +module Aviator + + define_request :get_volume, :inherit => [:openstack, :common, :v2, :public, :base] do + meta :provider, :openstack + meta :service, :volume + meta :api_version, :v1 + meta :endpoint_type, :public + + link 'documentation', 'http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/GET_getVolume_v1__tenant_id__volumes__volume_id__v1__tenant_id__volumes.html' + + param :id, :required => true + + def headers + super + end + + def http_method + :get + end + + def url + "#{ base_url }/volumes/#{ params[:id] }" + end + + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/list_volume_types.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/list_volume_types.rb new file mode 100644 index 000000000..d2f0b5c8a --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/list_volume_types.rb @@ -0,0 +1,29 @@ +module Aviator + + define_request :list_volume_types, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :provider, :openstack + meta :service, :volume + meta :api_version, :v1 + meta :endpoint_type, :public + + link 'documentation', 'http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/GET_getVolumeTypes_v1__tenant_id__types_v1__tenant_id__types.html' + + param :extra_specs, :required => false + param :name, :required => false + + def headers + super + end + + def http_method + :get + end + + def url + "#{ base_url }/types" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/list_volumes.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/list_volumes.rb new file mode 100644 index 000000000..c88cf7500 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/list_volumes.rb @@ -0,0 +1,48 @@ +module Aviator + + define_request :list_volumes, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :volume + meta :api_version, :v1 + + link 'documentation', 'http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/GET_getVolumesSimple_v1__tenant_id__volumes_v1__tenant_id__volumes.html' + + param :all_tenants, :required => false + param :details, :required => false + param :status, :required => false + param :availability_zone, :required => false + param :bootable, :required => false + param :display_name, :required => false + param :display_description, :required => false + param :volume_type, :required => false + param :snapshot_id, :required => false + param :size, :required => false + + + def headers + super + end + + def http_method + :get + end + + def url + str = "#{ base_url }/volumes" + str += "/detail" if params[:details] + + filters = [] + + (optional_params + required_params - [:details]).each do |param_name| + value = param_name == :all_tenants && params[param_name] ? 1 : params[param_name] + filters << "#{ param_name }=#{ value }" if value + end + + str += "?#{ filters.join('&') }" unless filters.empty? + + str + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/root.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/root.rb new file mode 100644 index 000000000..0e3748c9c --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/root.rb @@ -0,0 +1,26 @@ +module Aviator + + define_request :root, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :volume + meta :api_version, :v1 + + + def headers + super + end + + + def http_method + :get + end + + + def url + uri = URI(base_url) + "#{ uri.scheme }://#{ uri.host }:#{ uri.port.to_s }/v1/" + end + + end + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/update_volume.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/update_volume.rb new file mode 100644 index 000000000..67121c36f --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/openstack/volume/requests/v1/public/update_volume.rb @@ -0,0 +1,43 @@ +module Aviator + + define_request :update_volume, :inherit => [:openstack, :common, :v2, :public, :base] do + + meta :service, :volume + meta :api_version, :v1 + + link 'documentation', 'http://docs.rackspace.com/cbs/api/v1.0/cbs-devguide/content/PUT_renameVolume_v1__tenant_id__volumes__volume_id__v1__tenant_id__volumes.html' + + param :id, :required => true + param :display_name, :required => false + param :display_description, :required => false + + + def body + p = { :volume => {} } + + [:display_name, :display_description].each do |key| + p[:volume][key] = params[key] if params[key] + end + + p + end + + + def headers + super + end + + + def http_method + :put + end + + + def url + "#{ base_url }/volumes/#{ params[:id] }" + end + + end + + +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/aviator/version.rb b/3rdparty/modules/aviator/lib/puppet/feature/aviator/version.rb new file mode 100644 index 000000000..faa1543f9 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/aviator/version.rb @@ -0,0 +1,3 @@ +module Aviator + VERSION = "0.2.1" +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/composite_io.rb b/3rdparty/modules/aviator/lib/puppet/feature/composite_io.rb new file mode 100644 index 000000000..4ba7cf5ff --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/composite_io.rb @@ -0,0 +1,108 @@ +#-- +# Copyright (c) 2007-2012 Nick Sieger. +# See the file README.txt included with the distribution for +# software license details. +#++ + +# Concatenate together multiple IO objects into a single, composite IO object +# for purposes of reading as a single stream. +# +# Usage: +# +# crio = CompositeReadIO.new(StringIO.new('one'), StringIO.new('two'), StringIO.new('three')) +# puts crio.read # => "onetwothree" +# +class CompositeReadIO + # Create a new composite-read IO from the arguments, all of which should + # respond to #read in a manner consistent with IO. + def initialize(*ios) + @ios = ios.flatten + @index = 0 + end + + # Read from IOs in order until `length` bytes have been received. + def read(length = nil, outbuf = nil) + got_result = false + outbuf = outbuf ? outbuf.replace("") : "" + + while io = current_io + if result = io.read(length) + got_result ||= !result.nil? + result.force_encoding("BINARY") if result.respond_to?(:force_encoding) + outbuf << result + length -= result.length if length + break if length == 0 + end + advance_io + end + (!got_result && length) ? nil : outbuf + end + + def rewind + @ios.each { |io| io.rewind } + @index = 0 + end + + private + + def current_io + @ios[@index] + end + + def advance_io + @index += 1 + end +end + +# Convenience methods for dealing with files and IO that are to be uploaded. +class UploadIO + # Create an upload IO suitable for including in the params hash of a + # Net::HTTP::Post::Multipart. + # + # Can take two forms. The first accepts a filename and content type, and + # opens the file for reading (to be closed by finalizer). + # + # The second accepts an already-open IO, but also requires a third argument, + # the filename from which it was opened (particularly useful/recommended if + # uploading directly from a form in a framework, which often save the file to + # an arbitrarily named RackMultipart file in /tmp). + # + # Usage: + # + # UploadIO.new("file.txt", "text/plain") + # UploadIO.new(file_io, "text/plain", "file.txt") + # + attr_reader :content_type, :original_filename, :local_path, :io, :opts + + def initialize(filename_or_io, content_type, filename = nil, opts = {}) + io = filename_or_io + local_path = "" + if io.respond_to? :read + # in Ruby 1.9.2, StringIOs no longer respond to path + # (since they respond to :length, so we don't need their local path, see parts.rb:41) + local_path = filename_or_io.respond_to?(:path) ? filename_or_io.path : "local.path" + else + io = File.open(filename_or_io) + local_path = filename_or_io + end + filename ||= local_path + + @content_type = content_type + @original_filename = File.basename(filename) + @local_path = local_path + @io = io + @opts = opts + end + + def self.convert!(io, content_type, original_filename, local_path) + raise ArgumentError, "convert! has been removed. You must now wrap IOs using:\nUploadIO.new(filename_or_io, content_type, filename=nil)\nPlease update your code." + end + + def method_missing(*args) + @io.send(*args) + end + + def respond_to?(meth, include_all = false) + @io.respond_to?(meth, include_all) || super(meth, include_all) + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday.rb new file mode 100644 index 000000000..4b63ec8e9 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday.rb @@ -0,0 +1,268 @@ +require 'thread' +require 'cgi' +require 'set' +require 'forwardable' + +# Public: This is the main namespace for Faraday. You can either use it to +# create Faraday::Connection objects, or access it directly. +# +# Examples +# +# Faraday.get "http://faraday.com" +# +# conn = Faraday.new "http://faraday.com" +# conn.get '/' +# +module Faraday + VERSION = "0.9.0" + + class << self + # Public: Gets or sets the root path that Faraday is being loaded from. + # This is the root from where the libraries are auto-loaded from. + attr_accessor :root_path + + # Public: Gets or sets the path that the Faraday libs are loaded from. + attr_accessor :lib_path + + # Public: Gets or sets the Symbol key identifying a default Adapter to use + # for the default Faraday::Connection. + attr_reader :default_adapter + + # Public: Sets the default Faraday::Connection for simple scripts that + # access the Faraday constant directly. + # + # Faraday.get "https://faraday.com" + attr_writer :default_connection + + # Public: Sets the default options used when calling Faraday#new. + attr_writer :default_connection_options + + # Public: Initializes a new Faraday::Connection. + # + # url - The optional String base URL to use as a prefix for all + # requests. Can also be the options Hash. + # options - The optional Hash used to configure this Faraday::Connection. + # Any of these values will be set on every request made, unless + # overridden for a specific request. + # :url - String base URL. + # :params - Hash of URI query unencoded key/value pairs. + # :headers - Hash of unencoded HTTP header key/value pairs. + # :request - Hash of request options. + # :ssl - Hash of SSL options. + # :proxy - Hash of Proxy options. + # + # Examples + # + # Faraday.new 'http://faraday.com' + # + # # http://faraday.com?page=1 + # Faraday.new 'http://faraday.com', :params => {:page => 1} + # + # # same + # + # Faraday.new :url => 'http://faraday.com', + # :params => {:page => 1} + # + # Returns a Faraday::Connection. + def new(url = nil, options = nil) + block = block_given? ? Proc.new : nil + options = options ? default_connection_options.merge(options) : default_connection_options.dup + Faraday::Connection.new(url, options, &block) + end + + # Internal: Requires internal Faraday libraries. + # + # *libs - One or more relative String names to Faraday classes. + # + # Returns nothing. + def require_libs(*libs) + libs.each do |lib| + require "#{lib_path}/#{lib}" + end + end + + # Public: Updates default adapter while resetting + # #default_connection. + # + # Returns the new default_adapter. + def default_adapter=(adapter) + @default_connection = nil + @default_adapter = adapter + end + + alias require_lib require_libs + + private + # Internal: Proxies method calls on the Faraday constant to + # #default_connection. + def method_missing(name, *args, &block) + default_connection.send(name, *args, &block) + end + end + + self.root_path = File.expand_path "..", __FILE__ + self.lib_path = File.expand_path "../faraday", __FILE__ + self.default_adapter = :net_http + + # Gets the default connection used for simple scripts. + # + # Returns a Faraday::Connection, configured with the #default_adapter. + def self.default_connection + @default_connection ||= Connection.new + end + + # Gets the default connection options used when calling Faraday#new. + # + # Returns a Faraday::ConnectionOptions. + def self.default_connection_options + @default_connection_options ||= ConnectionOptions.new + end + + if (!defined?(RUBY_ENGINE) || "ruby" == RUBY_ENGINE) && RUBY_VERSION < '1.9' + begin + require 'system_timer' + Timer = SystemTimer + rescue LoadError + warn "Faraday: you may want to install system_timer for reliable timeouts" + end + end + + unless const_defined? :Timer + require 'timeout' + Timer = Timeout + end + + # Public: Adds the ability for other modules to register and lookup + # middleware classes. + module MiddlewareRegistry + # Public: Register middleware class(es) on the current module. + # + # mapping - A Hash mapping Symbol keys to classes. Classes can be expressed + # as fully qualified constant, or a Proc that will be lazily + # called to return the former. + # + # Examples + # + # module Faraday + # class Whatever + # # Middleware looked up by :foo returns Faraday::Whatever::Foo. + # register_middleware :foo => Foo + # + # # Middleware looked up by :bar returns Faraday::Whatever.const_get(:Bar) + # register_middleware :bar => :Bar + # + # # Middleware looked up by :baz requires 'baz' and returns Faraday::Whatever.const_get(:Baz) + # register_middleware :baz => [:Baz, 'baz'] + # end + # end + # + # Returns nothing. + def register_middleware(autoload_path = nil, mapping = nil) + if mapping.nil? + mapping = autoload_path + autoload_path = nil + end + middleware_mutex do + @middleware_autoload_path = autoload_path if autoload_path + (@registered_middleware ||= {}).update(mapping) + end + end + + # Public: Lookup middleware class with a registered Symbol shortcut. + # + # key - The Symbol key for the registered middleware. + # + # Examples + # + # module Faraday + # class Whatever + # register_middleware :foo => Foo + # end + # end + # + # Faraday::Whatever.lookup_middleware(:foo) + # # => Faraday::Whatever::Foo + # + # Returns a middleware Class. + def lookup_middleware(key) + load_middleware(key) || + raise(Faraday::Error.new("#{key.inspect} is not registered on #{self}")) + end + + def middleware_mutex(&block) + @middleware_mutex ||= begin + require 'monitor' + Monitor.new + end + @middleware_mutex.synchronize(&block) + end + + def fetch_middleware(key) + defined?(@registered_middleware) && @registered_middleware[key] + end + + def load_middleware(key) + value = fetch_middleware(key) + case value + when Module + value + when Symbol, String + middleware_mutex do + @registered_middleware[key] = const_get(value) + end + when Proc + middleware_mutex do + @registered_middleware[key] = value.call + end + when Array + middleware_mutex do + const, path = value + if root = @middleware_autoload_path + path = "#{root}/#{path}" + end + require(path) + @registered_middleware[key] = const + end + load_middleware(key) + end + end + end + + def self.const_missing(name) + if name.to_sym == :Builder + warn "Faraday::Builder is now Faraday::RackBuilder." + const_set name, RackBuilder + else + super + end + end + + require_libs "utils", "options", "connection", "rack_builder", "parameters", + "middleware", "adapter", "request", "response", "upload_io", "error" + + if !ENV["FARADAY_NO_AUTOLOAD"] + require_lib 'autoload' + end +end + +# not pulling in active-support JUST for this method. And I love this method. +class Object + # The primary purpose of this method is to "tap into" a method chain, + # in order to perform operations on intermediate results within the chain. + # + # Examples + # + # (1..10).tap { |x| puts "original: #{x.inspect}" }.to_a. + # tap { |x| puts "array: #{x.inspect}" }. + # select { |x| x%2 == 0 }. + # tap { |x| puts "evens: #{x.inspect}" }. + # map { |x| x*x }. + # tap { |x| puts "squares: #{x.inspect}" } + # + # Yields self. + # Returns self. + def tap + yield(self) + self + end unless Object.respond_to?(:tap) +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter.rb new file mode 100644 index 000000000..f018b509a --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter.rb @@ -0,0 +1,46 @@ +module Faraday + # Public: This is a base class for all Faraday adapters. Adapters are + # responsible for fulfilling a Faraday request. + class Adapter < Middleware + CONTENT_LENGTH = 'Content-Length'.freeze + + register_middleware File.expand_path('../adapter', __FILE__), + :test => [:Test, 'test'], + :net_http => [:NetHttp, 'net_http'], + :net_http_persistent => [:NetHttpPersistent, 'net_http_persistent'], + :typhoeus => [:Typhoeus, 'typhoeus'], + :patron => [:Patron, 'patron'], + :em_synchrony => [:EMSynchrony, 'em_synchrony'], + :em_http => [:EMHttp, 'em_http'], + :excon => [:Excon, 'excon'], + :rack => [:Rack, 'rack'], + :httpclient => [:HTTPClient, 'httpclient'] + + # Public: This module marks an Adapter as supporting parallel requests. + module Parallelism + attr_writer :supports_parallel + def supports_parallel?() @supports_parallel end + + def inherited(subclass) + super + subclass.supports_parallel = self.supports_parallel? + end + end + + extend Parallelism + self.supports_parallel = false + + def call(env) + env.clear_body if env.needs_body? + end + + def save_response(env, status, body, headers = nil) + env.status = status + env.body = body + env.response_headers = Utils::Headers.new.tap do |response_headers| + response_headers.update headers unless headers.nil? + yield(response_headers) if block_given? + end + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/em_http.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/em_http.rb new file mode 100644 index 000000000..a248fcfd2 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/em_http.rb @@ -0,0 +1,237 @@ +module Faraday + class Adapter + # EventMachine adapter is useful for either asynchronous requests + # when in EM reactor loop or for making parallel requests in + # synchronous code. + class EMHttp < Faraday::Adapter + module Options + def connection_config(env) + options = {} + configure_proxy(options, env) + configure_timeout(options, env) + configure_socket(options, env) + configure_ssl(options, env) + options + end + + def request_config(env) + options = { + :body => read_body(env), + :head => env[:request_headers], + # :keepalive => true, + # :file => 'path/to/file', # stream data off disk + } + configure_compression(options, env) + options + end + + def read_body(env) + body = env[:body] + body.respond_to?(:read) ? body.read : body + end + + def configure_proxy(options, env) + if proxy = request_options(env)[:proxy] + options[:proxy] = { + :host => proxy[:uri].host, + :port => proxy[:uri].port, + :authorization => [proxy[:user], proxy[:password]] + } + end + end + + def configure_socket(options, env) + if bind = request_options(env)[:bind] + options[:bind] = { + :host => bind[:host], + :port => bind[:port] + } + end + end + + def configure_ssl(options, env) + if env[:url].scheme == 'https' && env[:ssl] + options[:ssl] = { + :cert_chain_file => env[:ssl][:ca_file], + :verify_peer => env[:ssl].fetch(:verify, true) + } + end + end + + def configure_timeout(options, env) + timeout, open_timeout = request_options(env).values_at(:timeout, :open_timeout) + options[:connect_timeout] = options[:inactivity_timeout] = timeout + options[:connect_timeout] = open_timeout if open_timeout + end + + def configure_compression(options, env) + if env[:method] == :get and not options[:head].key? 'accept-encoding' + options[:head]['accept-encoding'] = 'gzip, compressed' + end + end + + def request_options(env) + env[:request] + end + end + + include Options + + dependency 'em-http' + + self.supports_parallel = true + + def self.setup_parallel_manager(options = nil) + Manager.new + end + + def call(env) + super + perform_request env + @app.call env + end + + def perform_request(env) + if parallel?(env) + manager = env[:parallel_manager] + manager.add { + perform_single_request(env). + callback { env[:response].finish(env) } + } + else + unless EventMachine.reactor_running? + error = nil + # start EM, block until request is completed + EventMachine.run do + perform_single_request(env). + callback { EventMachine.stop }. + errback { |client| + error = error_message(client) + EventMachine.stop + } + end + raise_error(error) if error + else + # EM is running: instruct upstream that this is an async request + env[:parallel_manager] = true + perform_single_request(env). + callback { env[:response].finish(env) }. + errback { + # TODO: no way to communicate the error in async mode + raise NotImplementedError + } + end + end + rescue EventMachine::Connectify::CONNECTError => err + if err.message.include?("Proxy Authentication Required") + raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "} + else + raise Error::ConnectionFailed, err + end + rescue => err + if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err + raise Faraday::SSLError, err + else + raise + end + end + + # TODO: reuse the connection to support pipelining + def perform_single_request(env) + req = EventMachine::HttpRequest.new(env[:url], connection_config(env)) + req.setup_request(env[:method], request_config(env)).callback { |client| + save_response(env, client.response_header.status, client.response) do |resp_headers| + client.response_header.each do |name, value| + resp_headers[name.to_sym] = value + end + end + } + end + + def error_message(client) + client.error or "request failed" + end + + def raise_error(msg) + errklass = Faraday::Error::ClientError + if msg == Errno::ETIMEDOUT + errklass = Faraday::Error::TimeoutError + msg = "request timed out" + elsif msg == Errno::ECONNREFUSED + errklass = Faraday::Error::ConnectionFailed + msg = "connection refused" + elsif msg == "connection closed by server" + errklass = Faraday::Error::ConnectionFailed + end + raise errklass, msg + end + + def parallel?(env) + !!env[:parallel_manager] + end + + # The parallel manager is designed to start an EventMachine loop + # and block until all registered requests have been completed. + class Manager + def initialize + reset + end + + def reset + @registered_procs = [] + @num_registered = 0 + @num_succeeded = 0 + @errors = [] + @running = false + end + + def running?() @running end + + def add + if running? + perform_request { yield } + else + @registered_procs << Proc.new + end + @num_registered += 1 + end + + def run + if @num_registered > 0 + @running = true + EventMachine.run do + @registered_procs.each do |proc| + perform_request(&proc) + end + end + if @errors.size > 0 + raise Faraday::Error::ClientError, @errors.first || "connection failed" + end + end + ensure + reset + end + + def perform_request + client = yield + client.callback { @num_succeeded += 1; check_finished } + client.errback { @errors << client.error; check_finished } + end + + def check_finished + if @num_succeeded + @errors.size == @num_registered + EventMachine.stop + end + end + end + end + end +end + +begin + require 'openssl' +rescue LoadError + warn "Warning: no such file to load -- openssl. Make sure it is installed if you want HTTPS support" +else + require 'faraday/adapter/em_http_ssl_patch' +end if Faraday::Adapter::EMHttp.loaded? diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/em_http_ssl_patch.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/em_http_ssl_patch.rb new file mode 100644 index 000000000..8bbfcbce3 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/em_http_ssl_patch.rb @@ -0,0 +1,56 @@ +require 'openssl' +require 'em-http' + +module EmHttpSslPatch + def ssl_verify_peer(cert_string) + cert = nil + begin + cert = OpenSSL::X509::Certificate.new(cert_string) + rescue OpenSSL::X509::CertificateError + return false + end + + @last_seen_cert = cert + + if certificate_store.verify(@last_seen_cert) + begin + certificate_store.add_cert(@last_seen_cert) + rescue OpenSSL::X509::StoreError => e + raise e unless e.message == 'cert already in hash table' + end + true + else + raise OpenSSL::SSL::SSLError.new(%(unable to verify the server certificate for "#{host}")) + end + end + + def ssl_handshake_completed + return true unless verify_peer? + + unless OpenSSL::SSL.verify_certificate_identity(@last_seen_cert, host) + raise OpenSSL::SSL::SSLError.new(%(host "#{host}" does not match the server certificate)) + else + true + end + end + + def verify_peer? + parent.connopts.tls[:verify_peer] + end + + def host + parent.connopts.host + end + + def certificate_store + @certificate_store ||= begin + store = OpenSSL::X509::Store.new + store.set_default_paths + ca_file = parent.connopts.tls[:cert_chain_file] + store.add_file(ca_file) if ca_file + store + end + end +end + +EventMachine::HttpStubConnection.send(:include, EmHttpSslPatch) diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/em_synchrony.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/em_synchrony.rb new file mode 100644 index 000000000..305e702f8 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/em_synchrony.rb @@ -0,0 +1,92 @@ +require 'uri' + +module Faraday + class Adapter + class EMSynchrony < Faraday::Adapter + include EMHttp::Options + + dependency do + require 'em-synchrony/em-http' + require 'em-synchrony/em-multi' + require 'fiber' + end + + self.supports_parallel = true + + def self.setup_parallel_manager(options = {}) + ParallelManager.new + end + + def call(env) + super + request = EventMachine::HttpRequest.new(Utils::URI(env[:url].to_s), connection_config(env)) + + http_method = env[:method].to_s.downcase.to_sym + + # Queue requests for parallel execution. + if env[:parallel_manager] + env[:parallel_manager].add(request, http_method, request_config(env)) do |resp| + save_response(env, resp.response_header.status, resp.response) do |resp_headers| + resp.response_header.each do |name, value| + resp_headers[name.to_sym] = value + end + end + + # Finalize the response object with values from `env`. + env[:response].finish(env) + end + + # Execute single request. + else + client = nil + block = lambda { request.send(http_method, request_config(env)) } + + if !EM.reactor_running? + EM.run do + Fiber.new { + client = block.call + EM.stop + }.resume + end + else + client = block.call + end + + raise client.error if client.error + + save_response(env, client.response_header.status, client.response) do |resp_headers| + client.response_header.each do |name, value| + resp_headers[name.to_sym] = value + end + end + end + + @app.call env + rescue Errno::ECONNREFUSED + raise Error::ConnectionFailed, $! + rescue EventMachine::Connectify::CONNECTError => err + if err.message.include?("Proxy Authentication Required") + raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "} + else + raise Error::ConnectionFailed, err + end + rescue => err + if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err + raise Faraday::SSLError, err + else + raise + end + end + end + end +end + +require 'faraday/adapter/em_synchrony/parallel_manager' + +begin + require 'openssl' +rescue LoadError + warn "Warning: no such file to load -- openssl. Make sure it is installed if you want HTTPS support" +else + require 'faraday/adapter/em_http_ssl_patch' +end if Faraday::Adapter::EMSynchrony.loaded? diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/em_synchrony/parallel_manager.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/em_synchrony/parallel_manager.rb new file mode 100644 index 000000000..12a1bafa4 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/em_synchrony/parallel_manager.rb @@ -0,0 +1,66 @@ +module Faraday + class Adapter + class EMSynchrony < Faraday::Adapter + class ParallelManager + + # Add requests to queue. The `request` argument should be a + # `EM::HttpRequest` object. + def add(request, method, *args, &block) + queue << { + :request => request, + :method => method, + :args => args, + :block => block + } + end + + # Run all requests on queue with `EM::Synchrony::Multi`, wrapping + # it in a reactor and fiber if needed. + def run + result = nil + if !EM.reactor_running? + EM.run { + Fiber.new do + result = perform + EM.stop + end.resume + } + else + result = perform + end + result + end + + + private + + # The request queue. + def queue + @queue ||= [] + end + + # Main `EM::Synchrony::Multi` performer. + def perform + multi = ::EM::Synchrony::Multi.new + + queue.each do |item| + method = "a#{item[:method]}".to_sym + + req = item[:request].send(method, *item[:args]) + req.callback(&item[:block]) + + req_name = "req_#{multi.requests.size}".to_sym + multi.add(req_name, req) + end + + # Clear the queue, so parallel manager objects can be reused. + @queue = [] + + # Block fiber until all requests have returned. + multi.perform + end + + end # ParallelManager + end # EMSynchrony + end # Adapter +end # Faraday diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/excon.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/excon.rb new file mode 100644 index 000000000..db0c7c352 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/excon.rb @@ -0,0 +1,80 @@ +module Faraday + class Adapter + class Excon < Faraday::Adapter + dependency 'excon' + + def initialize(app, connection_options = {}) + @connection_options = connection_options + super(app) + end + + def call(env) + super + + opts = {} + if env[:url].scheme == 'https' && ssl = env[:ssl] + opts[:ssl_verify_peer] = !!ssl.fetch(:verify, true) + opts[:ssl_ca_path] = ssl[:ca_path] if ssl[:ca_path] + opts[:ssl_ca_file] = ssl[:ca_file] if ssl[:ca_file] + opts[:client_cert] = ssl[:client_cert] if ssl[:client_cert] + opts[:client_key] = ssl[:client_key] if ssl[:client_key] + opts[:certificate] = ssl[:certificate] if ssl[:certificate] + opts[:private_key] = ssl[:private_key] if ssl[:private_key] + + # https://github.com/geemus/excon/issues/106 + # https://github.com/jruby/jruby-ossl/issues/19 + opts[:nonblock] = false + end + + if ( req = env[:request] ) + if req[:timeout] + opts[:read_timeout] = req[:timeout] + opts[:connect_timeout] = req[:timeout] + opts[:write_timeout] = req[:timeout] + end + + if req[:open_timeout] + opts[:connect_timeout] = req[:open_timeout] + opts[:write_timeout] = req[:open_timeout] + end + + if req[:proxy] + opts[:proxy] = { + :host => req[:proxy][:uri].host, + :port => req[:proxy][:uri].port, + :scheme => req[:proxy][:uri].scheme, + :user => req[:proxy][:user], + :password => req[:proxy][:password] + } + end + end + + conn = ::Excon.new(env[:url].to_s, opts.merge(@connection_options)) + + resp = conn.request \ + :method => env[:method].to_s.upcase, + :headers => env[:request_headers], + :body => read_body(env) + + save_response(env, resp.status.to_i, resp.body, resp.headers) + + @app.call env + rescue ::Excon::Errors::SocketError => err + if err.message =~ /\btimeout\b/ + raise Error::TimeoutError, err + elsif err.message =~ /\bcertificate\b/ + raise Faraday::SSLError, err + else + raise Error::ConnectionFailed, err + end + rescue ::Excon::Errors::Timeout => err + raise Error::TimeoutError, err + end + + # TODO: support streaming requests + def read_body(env) + env[:body].respond_to?(:read) ? env[:body].read : env[:body] + end + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/httpclient.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/httpclient.rb new file mode 100644 index 000000000..06c663f03 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/httpclient.rb @@ -0,0 +1,106 @@ +module Faraday + class Adapter + class HTTPClient < Faraday::Adapter + dependency 'httpclient' + + def client + @client ||= ::HTTPClient.new + end + + def call(env) + super + + if req = env[:request] + if proxy = req[:proxy] + configure_proxy proxy + end + + if bind = req[:bind] + configure_socket bind + end + + configure_timeouts req + end + + if env[:url].scheme == 'https' && ssl = env[:ssl] + configure_ssl ssl + end + + # TODO Don't stream yet. + # https://github.com/nahi/httpclient/pull/90 + env[:body] = env[:body].read if env[:body].respond_to? :read + + resp = client.request env[:method], env[:url], + :body => env[:body], + :header => env[:request_headers] + + save_response env, resp.status, resp.body, resp.headers + + @app.call env + rescue ::HTTPClient::TimeoutError + raise Faraday::Error::TimeoutError, $! + rescue ::HTTPClient::BadResponseError => err + if err.message.include?('status 407') + raise Faraday::Error::ConnectionFailed, %{407 "Proxy Authentication Required "} + else + raise Faraday::Error::ClientError, $! + end + rescue Errno::ECONNREFUSED, EOFError + raise Faraday::Error::ConnectionFailed, $! + rescue => err + if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err + raise Faraday::SSLError, err + else + raise + end + end + + def configure_socket(bind) + client.socket_local.host = bind[:host] + client.socket_local.port = bind[:port] + end + + def configure_proxy(proxy) + client.proxy = proxy[:uri] + if proxy[:user] && proxy[:password] + client.set_proxy_auth proxy[:user], proxy[:password] + end + end + + def configure_ssl(ssl) + ssl_config = client.ssl_config + + ssl_config.add_trust_ca ssl[:ca_file] if ssl[:ca_file] + ssl_config.add_trust_ca ssl[:ca_path] if ssl[:ca_path] + ssl_config.cert_store = ssl[:cert_store] if ssl[:cert_store] + ssl_config.client_cert = ssl[:client_cert] if ssl[:client_cert] + ssl_config.client_key = ssl[:client_key] if ssl[:client_key] + ssl_config.verify_depth = ssl[:verify_depth] if ssl[:verify_depth] + ssl_config.verify_mode = ssl_verify_mode(ssl) + end + + def configure_timeouts(req) + if req[:timeout] + client.connect_timeout = req[:timeout] + client.receive_timeout = req[:timeout] + client.send_timeout = req[:timeout] + end + + if req[:open_timeout] + client.connect_timeout = req[:open_timeout] + client.send_timeout = req[:open_timeout] + end + end + + def ssl_verify_mode(ssl) + ssl[:verify_mode] || begin + if ssl.fetch(:verify, true) + OpenSSL::SSL::VERIFY_PEER | OpenSSL::SSL::VERIFY_FAIL_IF_NO_PEER_CERT + else + OpenSSL::SSL::VERIFY_NONE + end + end + end + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/net_http.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/net_http.rb new file mode 100644 index 000000000..449388a7f --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/net_http.rb @@ -0,0 +1,124 @@ +begin + require 'net/https' +rescue LoadError + warn "Warning: no such file to load -- net/https. Make sure openssl is installed if you want ssl support" + require 'net/http' +end +require 'zlib' + +module Faraday + class Adapter + class NetHttp < Faraday::Adapter + NET_HTTP_EXCEPTIONS = [ + EOFError, + Errno::ECONNABORTED, + Errno::ECONNREFUSED, + Errno::ECONNRESET, + Errno::EHOSTUNREACH, + Errno::EINVAL, + Errno::ENETUNREACH, + Net::HTTPBadResponse, + Net::HTTPHeaderSyntaxError, + Net::ProtocolError, + SocketError, + Zlib::GzipFile::Error, + ] + + NET_HTTP_EXCEPTIONS << OpenSSL::SSL::SSLError if defined?(OpenSSL) + + def call(env) + super + http = net_http_connection(env) + configure_ssl(http, env[:ssl]) if env[:url].scheme == 'https' and env[:ssl] + + req = env[:request] + http.read_timeout = http.open_timeout = req[:timeout] if req[:timeout] + http.open_timeout = req[:open_timeout] if req[:open_timeout] + + begin + http_response = perform_request(http, env) + rescue *NET_HTTP_EXCEPTIONS => err + if defined?(OpenSSL) && OpenSSL::SSL::SSLError === err + raise Faraday::SSLError, err + else + raise Error::ConnectionFailed, err + end + end + + save_response(env, http_response.code.to_i, http_response.body || '') do |response_headers| + http_response.each_header do |key, value| + response_headers[key] = value + end + end + + @app.call env + rescue Timeout::Error => err + raise Faraday::Error::TimeoutError, err + end + + def create_request(env) + request = Net::HTTPGenericRequest.new \ + env[:method].to_s.upcase, # request method + !!env[:body], # is there request body + :head != env[:method], # is there response body + env[:url].request_uri, # request uri path + env[:request_headers] # request headers + + if env[:body].respond_to?(:read) + request.body_stream = env[:body] + else + request.body = env[:body] + end + request + end + + def perform_request(http, env) + if :get == env[:method] and !env[:body] + # prefer `get` to `request` because the former handles gzip (ruby 1.9) + http.get env[:url].request_uri, env[:request_headers] + else + http.request create_request(env) + end + end + + def net_http_connection(env) + if proxy = env[:request][:proxy] + Net::HTTP::Proxy(proxy[:uri].host, proxy[:uri].port, proxy[:user], proxy[:password]) + else + Net::HTTP + end.new(env[:url].host, env[:url].port) + end + + def configure_ssl(http, ssl) + http.use_ssl = true + http.verify_mode = ssl_verify_mode(ssl) + http.cert_store = ssl_cert_store(ssl) + + http.cert = ssl[:client_cert] if ssl[:client_cert] + http.key = ssl[:client_key] if ssl[:client_key] + http.ca_file = ssl[:ca_file] if ssl[:ca_file] + http.ca_path = ssl[:ca_path] if ssl[:ca_path] + http.verify_depth = ssl[:verify_depth] if ssl[:verify_depth] + http.ssl_version = ssl[:version] if ssl[:version] + end + + def ssl_cert_store(ssl) + return ssl[:cert_store] if ssl[:cert_store] + # Use the default cert store by default, i.e. system ca certs + cert_store = OpenSSL::X509::Store.new + cert_store.set_default_paths + cert_store + end + + def ssl_verify_mode(ssl) + ssl[:verify_mode] || begin + if ssl.fetch(:verify, true) + OpenSSL::SSL::VERIFY_PEER + else + OpenSSL::SSL::VERIFY_NONE + end + end + end + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/net_http_persistent.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/net_http_persistent.rb new file mode 100644 index 000000000..e0cc9587e --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/net_http_persistent.rb @@ -0,0 +1,47 @@ +# Rely on autoloading instead of explicit require; helps avoid the "already +# initialized constant" warning on Ruby 1.8.7 when NetHttp is refereced below. +# require 'faraday/adapter/net_http' + +module Faraday + class Adapter + # Experimental adapter for net-http-persistent + class NetHttpPersistent < NetHttp + dependency 'net/http/persistent' + + def net_http_connection(env) + if proxy = env[:request][:proxy] + proxy_uri = ::URI::HTTP === proxy[:uri] ? proxy[:uri].dup : ::URI.parse(proxy[:uri].to_s) + proxy_uri.user = proxy_uri.password = nil + # awful patch for net-http-persistent 2.8 not unescaping user/password + (class << proxy_uri; self; end).class_eval do + define_method(:user) { proxy[:user] } + define_method(:password) { proxy[:password] } + end if proxy[:user] + end + Net::HTTP::Persistent.new 'Faraday', proxy_uri + end + + def perform_request(http, env) + http.request env[:url], create_request(env) + rescue Net::HTTP::Persistent::Error => error + if error.message.include? 'Timeout' + raise Faraday::Error::TimeoutError, error + elsif error.message.include? 'connection refused' + raise Faraday::Error::ConnectionFailed, error + else + raise + end + end + + def configure_ssl(http, ssl) + http.verify_mode = ssl_verify_mode(ssl) + http.cert_store = ssl_cert_store(ssl) + + http.certificate = ssl[:client_cert] if ssl[:client_cert] + http.private_key = ssl[:client_key] if ssl[:client_key] + http.ca_file = ssl[:ca_file] if ssl[:ca_file] + http.ssl_version = ssl[:version] if ssl[:version] + end + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/patron.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/patron.rb new file mode 100644 index 000000000..cf2d37fbe --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/patron.rb @@ -0,0 +1,72 @@ +module Faraday + class Adapter + class Patron < Faraday::Adapter + dependency 'patron' + + def initialize(app, &block) + super(app) + @block = block + end + + def call(env) + super + + # TODO: support streaming requests + env[:body] = env[:body].read if env[:body].respond_to? :read + + session = @session ||= create_session + + if req = env[:request] + session.timeout = session.connect_timeout = req[:timeout] if req[:timeout] + session.connect_timeout = req[:open_timeout] if req[:open_timeout] + + if proxy = req[:proxy] + proxy_uri = proxy[:uri].dup + proxy_uri.user = proxy[:user] && Utils.escape(proxy[:user]).gsub('+', '%20') + proxy_uri.password = proxy[:password] && Utils.escape(proxy[:password]).gsub('+', '%20') + session.proxy = proxy_uri.to_s + end + end + + response = begin + data = env[:body] ? env[:body].to_s : nil + session.request(env[:method], env[:url].to_s, env[:request_headers], :data => data) + rescue Errno::ECONNREFUSED, ::Patron::ConnectionFailed + raise Error::ConnectionFailed, $! + end + + save_response(env, response.status, response.body, response.headers) + + @app.call env + rescue ::Patron::TimeoutError => err + if err.message == "Connection time-out" + raise Faraday::Error::ConnectionFailed, err + else + raise Faraday::Error::TimeoutError, err + end + rescue ::Patron::Error => err + if err.message.include?("code 407") + raise Error::ConnectionFailed, %{407 "Proxy Authentication Required "} + else + raise Error::ConnectionFailed, err + end + end + + if loaded? && defined?(::Patron::Request::VALID_ACTIONS) + # HAX: helps but doesn't work completely + # https://github.com/toland/patron/issues/34 + ::Patron::Request::VALID_ACTIONS.tap do |actions| + actions << :patch unless actions.include? :patch + actions << :options unless actions.include? :options + end + end + + def create_session + session = ::Patron::Session.new + session.insecure = true + @block.call(session) if @block + session + end + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/rack.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/rack.rb new file mode 100644 index 000000000..0d2146487 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/rack.rb @@ -0,0 +1,58 @@ +module Faraday + class Adapter + # Sends requests to a Rack app. + # + # Examples + # + # class MyRackApp + # def call(env) + # [200, {'Content-Type' => 'text/html'}, ["hello world"]] + # end + # end + # + # Faraday.new do |conn| + # conn.adapter :rack, MyRackApp.new + # end + class Rack < Faraday::Adapter + dependency 'rack/test' + + # not prefixed with "HTTP_" + SPECIAL_HEADERS = %w[ CONTENT_LENGTH CONTENT_TYPE ] + + def initialize(faraday_app, rack_app) + super(faraday_app) + mock_session = ::Rack::MockSession.new(rack_app) + @session = ::Rack::Test::Session.new(mock_session) + end + + def call(env) + super + rack_env = { + :method => env[:method], + :input => env[:body].respond_to?(:read) ? env[:body].read : env[:body], + 'rack.url_scheme' => env[:url].scheme + } + + env[:request_headers].each do |name, value| + name = name.upcase.tr('-', '_') + name = "HTTP_#{name}" unless SPECIAL_HEADERS.include? name + rack_env[name] = value + end if env[:request_headers] + + timeout = env[:request][:timeout] || env[:request][:open_timeout] + response = if timeout + Timer.timeout(timeout, Faraday::Error::TimeoutError) { execute_request(env, rack_env) } + else + execute_request(env, rack_env) + end + + save_response(env, response.status, response.body, response.headers) + @app.call env + end + + def execute_request(env, rack_env) + @session.request(env[:url].to_s, rack_env) + end + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/test.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/test.rb new file mode 100644 index 000000000..9a345758e --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/test.rb @@ -0,0 +1,162 @@ +module Faraday + class Adapter + # test = Faraday::Connection.new do + # use Faraday::Adapter::Test do |stub| + # stub.get '/nigiri/sake.json' do + # [200, {}, 'hi world'] + # end + # end + # end + # + # resp = test.get '/nigiri/sake.json' + # resp.body # => 'hi world' + # + class Test < Faraday::Adapter + attr_accessor :stubs + + class Stubs + class NotFound < StandardError + end + + def initialize + # {:get => [Stub, Stub]} + @stack, @consumed = {}, {} + yield(self) if block_given? + end + + def empty? + @stack.empty? + end + + def match(request_method, path, headers, body) + return false if !@stack.key?(request_method) + stack = @stack[request_method] + consumed = (@consumed[request_method] ||= []) + + if stub = matches?(stack, path, headers, body) + consumed << stack.delete(stub) + stub + else + matches?(consumed, path, headers, body) + end + end + + def get(path, headers = {}, &block) + new_stub(:get, path, headers, &block) + end + + def head(path, headers = {}, &block) + new_stub(:head, path, headers, &block) + end + + def post(path, body=nil, headers = {}, &block) + new_stub(:post, path, headers, body, &block) + end + + def put(path, body=nil, headers = {}, &block) + new_stub(:put, path, headers, body, &block) + end + + def patch(path, body=nil, headers = {}, &block) + new_stub(:patch, path, headers, body, &block) + end + + def delete(path, headers = {}, &block) + new_stub(:delete, path, headers, &block) + end + + def options(path, headers = {}, &block) + new_stub(:options, path, headers, &block) + end + + # Raises an error if any of the stubbed calls have not been made. + def verify_stubbed_calls + failed_stubs = [] + @stack.each do |method, stubs| + unless stubs.size == 0 + failed_stubs.concat(stubs.map {|stub| + "Expected #{method} #{stub}." + }) + end + end + raise failed_stubs.join(" ") unless failed_stubs.size == 0 + end + + protected + + def new_stub(request_method, path, headers = {}, body=nil, &block) + normalized_path = Faraday::Utils.normalize_path(path) + (@stack[request_method] ||= []) << Stub.new(normalized_path, headers, body, block) + end + + def matches?(stack, path, headers, body) + stack.detect { |stub| stub.matches?(path, headers, body) } + end + end + + class Stub < Struct.new(:path, :params, :headers, :body, :block) + def initialize(full, headers, body, block) + path, query = full.split('?') + params = query ? + Faraday::Utils.parse_nested_query(query) : + {} + super(path, params, headers, body, block) + end + + def matches?(request_uri, request_headers, request_body) + request_path, request_query = request_uri.split('?') + request_params = request_query ? + Faraday::Utils.parse_nested_query(request_query) : + {} + request_path == path && + params_match?(request_params) && + (body.to_s.size.zero? || request_body == body) && + headers_match?(request_headers) + end + + def params_match?(request_params) + params.keys.all? do |key| + request_params[key] == params[key] + end + end + + def headers_match?(request_headers) + headers.keys.all? do |key| + request_headers[key] == headers[key] + end + end + + def to_s + "#{path} #{body}" + end + end + + def initialize(app, stubs=nil, &block) + super(app) + @stubs = stubs || Stubs.new + configure(&block) if block + end + + def configure + yield(stubs) + end + + def call(env) + super + normalized_path = Faraday::Utils.normalize_path(env[:url]) + params_encoder = env.request.params_encoder || Faraday::Utils.default_params_encoder + + if stub = stubs.match(env[:method], normalized_path, env.request_headers, env[:body]) + env[:params] = (query = env[:url].query) ? + params_encoder.decode(query) : + {} + status, headers, body = stub.block.call(env) + save_response(env, status, body, headers) + else + raise Stubs::NotFound, "no stubbed request for #{env[:method]} #{normalized_path} #{env[:body]}" + end + @app.call(env) + end + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/typhoeus.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/typhoeus.rb new file mode 100644 index 000000000..69b6a5139 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/adapter/typhoeus.rb @@ -0,0 +1,123 @@ +module Faraday + class Adapter + class Typhoeus < Faraday::Adapter + self.supports_parallel = true + + def self.setup_parallel_manager(options = {}) + options.empty? ? ::Typhoeus::Hydra.hydra : ::Typhoeus::Hydra.new(options) + end + + dependency 'typhoeus' + + def call(env) + super + perform_request env + @app.call env + end + + def perform_request(env) + read_body env + + hydra = env[:parallel_manager] || self.class.setup_parallel_manager + hydra.queue request(env) + hydra.run unless parallel?(env) + rescue Errno::ECONNREFUSED + raise Error::ConnectionFailed, $! + end + + # TODO: support streaming requests + def read_body(env) + env[:body] = env[:body].read if env[:body].respond_to? :read + end + + def request(env) + method = env[:method] + # For some reason, prevents Typhoeus from using "100-continue". + # We want this because Webrick 1.3.1 can't seem to handle it w/ PUT. + method = method.to_s.upcase if method == :put + + req = ::Typhoeus::Request.new env[:url].to_s, + :method => method, + :body => env[:body], + :headers => env[:request_headers], + :disable_ssl_peer_verification => (env[:ssl] && env[:ssl].disable?) + + configure_ssl req, env + configure_proxy req, env + configure_timeout req, env + configure_socket req, env + + req.on_complete do |resp| + if resp.timed_out? + if parallel?(env) + # TODO: error callback in async mode + else + raise Faraday::Error::TimeoutError, "request timed out" + end + end + + case resp.curl_return_code + when 0 + # everything OK + when 7 + raise Error::ConnectionFailed, resp.curl_error_message + when 60 + raise Faraday::SSLError, resp.curl_error_message + else + raise Error::ClientError, resp.curl_error_message + end + + save_response(env, resp.code, resp.body) do |response_headers| + response_headers.parse resp.headers + end + # in async mode, :response is initialized at this point + env[:response].finish(env) if parallel?(env) + end + + req + end + + def configure_ssl(req, env) + ssl = env[:ssl] + + req.ssl_version = ssl[:version] if ssl[:version] + req.ssl_cert = ssl[:client_cert] if ssl[:client_cert] + req.ssl_key = ssl[:client_key] if ssl[:client_key] + req.ssl_cacert = ssl[:ca_file] if ssl[:ca_file] + req.ssl_capath = ssl[:ca_path] if ssl[:ca_path] + end + + def configure_proxy(req, env) + proxy = request_options(env)[:proxy] + return unless proxy + + req.proxy = "#{proxy[:uri].host}:#{proxy[:uri].port}" + + if proxy[:user] && proxy[:password] + req.proxy_username = proxy[:user] + req.proxy_password = proxy[:password] + end + end + + def configure_timeout(req, env) + env_req = request_options(env) + req.timeout = req.connect_timeout = (env_req[:timeout] * 1000) if env_req[:timeout] + req.connect_timeout = (env_req[:open_timeout] * 1000) if env_req[:open_timeout] + end + + def configure_socket(req, env) + if bind = request_options(env)[:bind] + req.interface = bind[:host] + end + end + + def request_options(env) + env[:request] + end + + def parallel?(env) + !!env[:parallel_manager] + end + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/autoload.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/autoload.rb new file mode 100644 index 000000000..ec413ff84 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/autoload.rb @@ -0,0 +1,85 @@ +module Faraday + # Internal: Adds the ability for other modules to manage autoloadable + # constants. + module AutoloadHelper + # Internal: Registers the constants to be auto loaded. + # + # prefix - The String require prefix. If the path is inside Faraday, then + # it will be prefixed with the root path of this loaded Faraday + # version. + # options - Hash of Symbol => String library names. + # + # Examples. + # + # Faraday.autoload_all 'faraday/foo', + # :Bar => 'bar' + # + # # requires faraday/foo/bar to load Faraday::Bar. + # Faraday::Bar + # + # + # Returns nothing. + def autoload_all(prefix, options) + if prefix =~ /^faraday(\/|$)/i + prefix = File.join(Faraday.root_path, prefix) + end + options.each do |const_name, path| + autoload const_name, File.join(prefix, path) + end + end + + # Internal: Loads each autoloaded constant. If thread safety is a concern, + # wrap this in a Mutex. + # + # Returns nothing. + def load_autoloaded_constants + constants.each do |const| + const_get(const) if autoload?(const) + end + end + + # Internal: Filters the module's contents with those that have been already + # autoloaded. + # + # Returns an Array of Class/Module objects. + def all_loaded_constants + constants.map { |c| const_get(c) }. + select { |a| a.respond_to?(:loaded?) && a.loaded? } + end + end + + class Adapter + extend AutoloadHelper + autoload_all 'faraday/adapter', + :NetHttp => 'net_http', + :NetHttpPersistent => 'net_http_persistent', + :Typhoeus => 'typhoeus', + :EMSynchrony => 'em_synchrony', + :EMHttp => 'em_http', + :Patron => 'patron', + :Excon => 'excon', + :Test => 'test', + :Rack => 'rack', + :HTTPClient => 'httpclient' + end + + class Request + extend AutoloadHelper + autoload_all 'faraday/request', + :UrlEncoded => 'url_encoded', + :Multipart => 'multipart', + :Retry => 'retry', + :Timeout => 'timeout', + :Authorization => 'authorization', + :BasicAuthentication => 'basic_authentication', + :TokenAuthentication => 'token_authentication', + :Instrumentation => 'instrumentation' + end + + class Response + extend AutoloadHelper + autoload_all 'faraday/response', + :RaiseError => 'raise_error', + :Logger => 'logger' + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/connection.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/connection.rb new file mode 100644 index 000000000..1e408e2c2 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/connection.rb @@ -0,0 +1,432 @@ +module Faraday + # Public: Connection objects manage the default properties and the middleware + # stack for fulfilling an HTTP request. + # + # Examples + # + # conn = Faraday::Connection.new 'http://sushi.com' + # + # # GET http://sushi.com/nigiri + # conn.get 'nigiri' + # # => # + # + class Connection + # A Set of allowed HTTP verbs. + METHODS = Set.new [:get, :post, :put, :delete, :head, :patch, :options] + + # Public: Returns a Hash of URI query unencoded key/value pairs. + attr_reader :params + + # Public: Returns a Hash of unencoded HTTP header key/value pairs. + attr_reader :headers + + # Public: Returns a URI with the prefix used for all requests from this + # Connection. This includes a default host name, scheme, port, and path. + attr_reader :url_prefix + + # Public: Returns the Faraday::Builder for this Connection. + attr_reader :builder + + # Public: Returns a Hash of the request options. + attr_reader :options + + # Public: Returns a Hash of the SSL options. + attr_reader :ssl + + # Public: Returns the parallel manager for this Connection. + attr_reader :parallel_manager + + # Public: Sets the default parallel manager for this connection. + attr_writer :default_parallel_manager + + # Public: Initializes a new Faraday::Connection. + # + # url - URI or String base URL to use as a prefix for all + # requests (optional). + # options - Hash or Faraday::ConnectionOptions. + # :url - URI or String base URL (default: "http:/"). + # :params - Hash of URI query unencoded key/value pairs. + # :headers - Hash of unencoded HTTP header key/value pairs. + # :request - Hash of request options. + # :ssl - Hash of SSL options. + # :proxy - URI, String or Hash of HTTP proxy options + # (default: "http_proxy" environment variable). + # :uri - URI or String + # :user - String (optional) + # :password - String (optional) + def initialize(url = nil, options = nil) + if url.is_a?(Hash) + options = ConnectionOptions.from(url) + url = options.url + else + options = ConnectionOptions.from(options) + end + + @parallel_manager = nil + @headers = Utils::Headers.new + @params = Utils::ParamsHash.new + @options = options.request + @ssl = options.ssl + @default_parallel_manager = options.parallel_manager + + @builder = options.builder || begin + # pass an empty block to Builder so it doesn't assume default middleware + options.new_builder(block_given? ? Proc.new { |b| } : nil) + end + + self.url_prefix = url || 'http:/' + + @params.update(options.params) if options.params + @headers.update(options.headers) if options.headers + + @proxy = nil + proxy(options.fetch(:proxy) { + uri = ENV['http_proxy'] + if uri && !uri.empty? + uri = 'http://' + uri if uri !~ /^http/i + uri + end + }) + + yield(self) if block_given? + + @headers[:user_agent] ||= "Faraday v#{VERSION}" + end + + # Public: Sets the Hash of URI query unencoded key/value pairs. + def params=(hash) + @params.replace hash + end + + # Public: Sets the Hash of unencoded HTTP header key/value pairs. + def headers=(hash) + @headers.replace hash + end + + extend Forwardable + + def_delegators :builder, :build, :use, :request, :response, :adapter, :app + + # Public: Makes an HTTP request without a body. + # + # url - The optional String base URL to use as a prefix for all + # requests. Can also be the options Hash. + # params - Hash of URI query unencoded key/value pairs. + # headers - Hash of unencoded HTTP header key/value pairs. + # + # Examples + # + # conn.get '/items', {:page => 1}, :accept => 'application/json' + # conn.head '/items/1' + # + # # ElasticSearch example sending a body with GET. + # conn.get '/twitter/tweet/_search' do |req| + # req.headers[:content_type] = 'application/json' + # req.params[:routing] = 'kimchy' + # req.body = JSON.generate(:query => {...}) + # end + # + # Yields a Faraday::Response for further request customizations. + # Returns a Faraday::Response. + # + # Signature + # + # (url = nil, params = nil, headers = nil) + # + # verb - An HTTP verb: get, head, or delete. + %w[get head delete].each do |method| + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{method}(url = nil, params = nil, headers = nil) + run_request(:#{method}, url, nil, headers) { |request| + request.params.update(params) if params + yield(request) if block_given? + } + end + RUBY + end + + # Public: Makes an HTTP request with a body. + # + # url - The optional String base URL to use as a prefix for all + # requests. Can also be the options Hash. + # body - The String body for the request. + # headers - Hash of unencoded HTTP header key/value pairs. + # + # Examples + # + # conn.post '/items', data, :content_type => 'application/json' + # + # # Simple ElasticSearch indexing sample. + # conn.post '/twitter/tweet' do |req| + # req.headers[:content_type] = 'application/json' + # req.params[:routing] = 'kimchy' + # req.body = JSON.generate(:user => 'kimchy', ...) + # end + # + # Yields a Faraday::Response for further request customizations. + # Returns a Faraday::Response. + # + # Signature + # + # (url = nil, body = nil, headers = nil) + # + # verb - An HTTP verb: post, put, or patch. + %w[post put patch].each do |method| + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{method}(url = nil, body = nil, headers = nil, &block) + run_request(:#{method}, url, body, headers, &block) + end + RUBY + end + + # Public: Sets up the Authorization header with these credentials, encoded + # with base64. + # + # login - The authentication login. + # pass - The authentication password. + # + # Examples + # + # conn.basic_auth 'Aladdin', 'open sesame' + # conn.headers['Authorization'] + # # => "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==" + # + # Returns nothing. + def basic_auth(login, pass) + set_authorization_header(:basic_auth, login, pass) + end + + # Public: Sets up the Authorization header with the given token. + # + # token - The String token. + # options - Optional Hash of extra token options. + # + # Examples + # + # conn.token_auth 'abcdef', :foo => 'bar' + # conn.headers['Authorization'] + # # => "Token token=\"abcdef\", + # foo=\"bar\"" + # + # Returns nothing. + def token_auth(token, options = nil) + set_authorization_header(:token_auth, token, options) + end + + # Public: Sets up a custom Authorization header. + # + # type - The String authorization type. + # token - The String or Hash token. A String value is taken literally, and + # a Hash is encoded into comma separated key/value pairs. + # + # Examples + # + # conn.authorization :Bearer, 'mF_9.B5f-4.1JqM' + # conn.headers['Authorization'] + # # => "Bearer mF_9.B5f-4.1JqM" + # + # conn.authorization :Token, :token => 'abcdef', :foo => 'bar' + # conn.headers['Authorization'] + # # => "Token token=\"abcdef\", + # foo=\"bar\"" + # + # Returns nothing. + def authorization(type, token) + set_authorization_header(:authorization, type, token) + end + + # Internal: Traverse the middleware stack in search of a + # parallel-capable adapter. + # + # Yields in case of not found. + # + # Returns a parallel manager or nil if not found. + def default_parallel_manager + @default_parallel_manager ||= begin + handler = @builder.handlers.detect do |h| + h.klass.respond_to?(:supports_parallel?) and h.klass.supports_parallel? + end + + if handler + handler.klass.setup_parallel_manager + elsif block_given? + yield + end + end + end + + # Public: Determine if this Faraday::Connection can make parallel requests. + # + # Returns true or false. + def in_parallel? + !!@parallel_manager + end + + # Public: Sets up the parallel manager to make a set of requests. + # + # manager - The parallel manager that this Connection's Adapter uses. + # + # Yields a block to execute multiple requests. + # Returns nothing. + def in_parallel(manager = nil) + @parallel_manager = manager || default_parallel_manager { + warn "Warning: `in_parallel` called but no parallel-capable adapter on Faraday stack" + warn caller[2,10].join("\n") + nil + } + yield + @parallel_manager && @parallel_manager.run + ensure + @parallel_manager = nil + end + + # Public: Gets or Sets the Hash proxy options. + def proxy(arg = nil) + return @proxy if arg.nil? + @proxy = ProxyOptions.from(arg) + end + + def_delegators :url_prefix, :scheme, :scheme=, :host, :host=, :port, :port= + def_delegator :url_prefix, :path, :path_prefix + + # Public: Parses the giving url with URI and stores the individual + # components in this connection. These components serve as defaults for + # requests made by this connection. + # + # url - A String or URI. + # + # Examples + # + # conn = Faraday::Connection.new { ... } + # conn.url_prefix = "https://sushi.com/api" + # conn.scheme # => https + # conn.path_prefix # => "/api" + # + # conn.get("nigiri?page=2") # accesses https://sushi.com/api/nigiri + # + # Returns the parsed URI from teh given input.. + def url_prefix=(url, encoder = nil) + uri = @url_prefix = Utils.URI(url) + self.path_prefix = uri.path + + params.merge_query(uri.query, encoder) + uri.query = nil + + with_uri_credentials(uri) do |user, password| + basic_auth user, password + uri.user = uri.password = nil + end + + uri + end + + # Public: Sets the path prefix and ensures that it always has a leading + # slash. + # + # value - A String. + # + # Returns the new String path prefix. + def path_prefix=(value) + url_prefix.path = if value + value = '/' + value unless value[0,1] == '/' + value + end + end + + # Public: Takes a relative url for a request and combines it with the defaults + # set on the connection instance. + # + # conn = Faraday::Connection.new { ... } + # conn.url_prefix = "https://sushi.com/api?token=abc" + # conn.scheme # => https + # conn.path_prefix # => "/api" + # + # conn.build_url("nigiri?page=2") # => https://sushi.com/api/nigiri?token=abc&page=2 + # conn.build_url("nigiri", :page => 2) # => https://sushi.com/api/nigiri?token=abc&page=2 + # + def build_url(url = nil, extra_params = nil) + uri = build_exclusive_url(url) + + query_values = params.dup.merge_query(uri.query, options.params_encoder) + query_values.update extra_params if extra_params + uri.query = query_values.empty? ? nil : query_values.to_query(options.params_encoder) + + uri + end + + # Builds and runs the Faraday::Request. + # + # method - The Symbol HTTP method. + # url - The String or URI to access. + # body - The String body + # headers - Hash of unencoded HTTP header key/value pairs. + # + # Returns a Faraday::Response. + def run_request(method, url, body, headers) + if !METHODS.include?(method) + raise ArgumentError, "unknown http method: #{method}" + end + + request = build_request(method) do |req| + req.url(url) if url + req.headers.update(headers) if headers + req.body = body if body + yield(req) if block_given? + end + + builder.build_response(self, request) + end + + # Creates and configures the request object. + # + # Returns the new Request. + def build_request(method) + Request.create(method) do |req| + req.params = self.params.dup + req.headers = self.headers.dup + req.options = self.options.merge(:proxy => self.proxy) + yield(req) if block_given? + end + end + + # Internal: Build an absolute URL based on url_prefix. + # + # url - A String or URI-like object + # params - A Faraday::Utils::ParamsHash to replace the query values + # of the resulting url (default: nil). + # + # Returns the resulting URI instance. + def build_exclusive_url(url = nil, params = nil) + url = nil if url.respond_to?(:empty?) and url.empty? + base = url_prefix + if url and base.path and base.path !~ /\/$/ + base = base.dup + base.path = base.path + '/' # ensure trailing slash + end + uri = url ? base + url : base + uri.query = params.to_query(options.params_encoder) if params + uri.query = nil if uri.query and uri.query.empty? + uri + end + + # Internal: Creates a duplicate of this Faraday::Connection. + # + # Returns a Faraday::Connection. + def dup + self.class.new(build_exclusive_url, :headers => headers.dup, :params => params.dup, :builder => builder.dup, :ssl => ssl.dup) + end + + # Internal: Yields username and password extracted from a URI if they both exist. + def with_uri_credentials(uri) + if uri.user and uri.password + yield(Utils.unescape(uri.user), Utils.unescape(uri.password)) + end + end + + def set_authorization_header(header_type, *args) + header = Faraday::Request.lookup_middleware(header_type). + header(*args) + headers[Faraday::Request::Authorization::KEY] = header + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/error.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/error.rb new file mode 100644 index 000000000..17712309d --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/error.rb @@ -0,0 +1,53 @@ +module Faraday + class Error < StandardError; end + class MissingDependency < Error; end + + class ClientError < Error + attr_reader :response + + def initialize(ex, response = nil) + @wrapped_exception = nil + @response = response + + if ex.respond_to?(:backtrace) + super(ex.message) + @wrapped_exception = ex + elsif ex.respond_to?(:each_key) + super("the server responded with status #{ex[:status]}") + @response = ex + else + super(ex.to_s) + end + end + + def backtrace + if @wrapped_exception + @wrapped_exception.backtrace + else + super + end + end + + def inspect + %(#<#{self.class}>) + end + end + + class ConnectionFailed < ClientError; end + class ResourceNotFound < ClientError; end + class ParsingError < ClientError; end + + class TimeoutError < ClientError + def initialize(ex = nil) + super(ex || "timeout") + end + end + + class SSLError < ClientError + end + + [:MissingDependency, :ClientError, :ConnectionFailed, :ResourceNotFound, + :ParsingError, :TimeoutError, :SSLError].each do |const| + Error.const_set(const, Faraday.const_get(const)) + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/middleware.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/middleware.rb new file mode 100644 index 000000000..c45d51ade --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/middleware.rb @@ -0,0 +1,37 @@ +module Faraday + class Middleware + extend MiddlewareRegistry + + class << self + attr_accessor :load_error + private :load_error= + end + + self.load_error = nil + + # Executes a block which should try to require and reference dependent libraries + def self.dependency(lib = nil) + lib ? require(lib) : yield + rescue LoadError, NameError => error + self.load_error = error + end + + def self.new(*) + raise "missing dependency for #{self}: #{load_error.message}" unless loaded? + super + end + + def self.loaded? + load_error.nil? + end + + def self.inherited(subclass) + super + subclass.send(:load_error=, self.load_error) + end + + def initialize(app = nil) + @app = app + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/options.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/options.rb new file mode 100644 index 000000000..c1b36f60f --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/options.rb @@ -0,0 +1,350 @@ +module Faraday + # Subclasses Struct with some special helpers for converting from a Hash to + # a Struct. + class Options < Struct + # Public + def self.from(value) + value ? new.update(value) : new + end + + # Public + def each + return to_enum(:each) unless block_given? + members.each do |key| + yield(key.to_sym, send(key)) + end + end + + # Public + def update(obj) + obj.each do |key, value| + if sub_options = self.class.options_for(key) + value = sub_options.from(value) if value + elsif Hash === value + hash = {} + value.each do |hash_key, hash_value| + hash[hash_key] = hash_value + end + value = hash + end + + self.send("#{key}=", value) unless value.nil? + end + self + end + + alias merge! update + + # Public + def delete(key) + value = send(key) + send("#{key}=", nil) + value + end + + # Public + def clear + members.each { |member| delete(member) } + end + + # Public + def merge(value) + dup.update(value) + end + + # Public + def fetch(key, *args) + unless symbolized_key_set.include?(key.to_sym) + key_setter = "#{key}=" + if args.size > 0 + send(key_setter, args.first) + elsif block_given? + send(key_setter, Proc.new.call(key)) + else + raise self.class.fetch_error_class, "key not found: #{key.inspect}" + end + end + send(key) + end + + # Public + def values_at(*keys) + keys.map { |key| send(key) } + end + + # Public + def keys + members.reject { |member| send(member).nil? } + end + + # Public + def empty? + keys.empty? + end + + # Public + def each_key + return to_enum(:each_key) unless block_given? + keys.each do |key| + yield(key) + end + end + + # Public + def key?(key) + keys.include?(key) + end + + alias has_key? key? + + # Public + def each_value + return to_enum(:each_value) unless block_given? + values.each do |value| + yield(value) + end + end + + # Public + def value?(value) + values.include?(value) + end + + alias has_value? value? + + # Public + def to_hash + hash = {} + members.each do |key| + value = send(key) + hash[key.to_sym] = value unless value.nil? + end + hash + end + + # Internal + def inspect + values = [] + members.each do |member| + value = send(member) + values << "#{member}=#{value.inspect}" if value + end + values = values.empty? ? ' (empty)' : (' ' << values.join(", ")) + + %(#<#{self.class}#{values}>) + end + + # Internal + def self.options(mapping) + attribute_options.update(mapping) + end + + # Internal + def self.options_for(key) + attribute_options[key] + end + + # Internal + def self.attribute_options + @attribute_options ||= {} + end + + def self.memoized(key) + memoized_attributes[key.to_sym] = Proc.new + class_eval <<-RUBY, __FILE__, __LINE__ + 1 + def #{key}() self[:#{key}]; end + RUBY + end + + def self.memoized_attributes + @memoized_attributes ||= {} + end + + def [](key) + key = key.to_sym + if method = self.class.memoized_attributes[key] + super(key) || (self[key] = instance_eval(&method)) + else + super + end + end + + def symbolized_key_set + @symbolized_key_set ||= Set.new(keys.map { |k| k.to_sym }) + end + + def self.inherited(subclass) + super + subclass.attribute_options.update(attribute_options) + subclass.memoized_attributes.update(memoized_attributes) + end + + def self.fetch_error_class + @fetch_error_class ||= if Object.const_defined?(:KeyError) + ::KeyError + else + ::IndexError + end + end + end + + class RequestOptions < Options.new(:params_encoder, :proxy, :bind, + :timeout, :open_timeout, :boundary, + :oauth) + + def []=(key, value) + if key && key.to_sym == :proxy + super(key, value ? ProxyOptions.from(value) : nil) + else + super(key, value) + end + end + end + + class SSLOptions < Options.new(:verify, :ca_file, :ca_path, :verify_mode, + :cert_store, :client_cert, :client_key, :certificate, :private_key, :verify_depth, :version) + + def verify? + verify != false + end + + def disable? + !verify? + end + end + + class ProxyOptions < Options.new(:uri, :user, :password) + extend Forwardable + def_delegators :uri, :scheme, :scheme=, :host, :host=, :port, :port=, :path, :path= + + def self.from(value) + case value + when String + value = {:uri => Utils.URI(value)} + when URI + value = {:uri => value} + when Hash, Options + if uri = value.delete(:uri) + value[:uri] = Utils.URI(uri) + end + end + super(value) + end + + memoized(:user) { uri.user && Utils.unescape(uri.user) } + memoized(:password) { uri.password && Utils.unescape(uri.password) } + end + + class ConnectionOptions < Options.new(:request, :proxy, :ssl, :builder, :url, + :parallel_manager, :params, :headers, :builder_class) + + options :request => RequestOptions, :ssl => SSLOptions + + memoized(:request) { self.class.options_for(:request).new } + + memoized(:ssl) { self.class.options_for(:ssl).new } + + memoized(:builder_class) { RackBuilder } + + def new_builder(block) + builder_class.new(&block) + end + end + + class Env < Options.new(:method, :body, :url, :request, :request_headers, + :ssl, :parallel_manager, :params, :response, :response_headers, :status) + + ContentLength = 'Content-Length'.freeze + StatusesWithoutBody = Set.new [204, 304] + SuccessfulStatuses = 200..299 + + # A Set of HTTP verbs that typically send a body. If no body is set for + # these requests, the Content-Length header is set to 0. + MethodsWithBodies = Set.new [:post, :put, :patch, :options] + + options :request => RequestOptions, + :request_headers => Utils::Headers, :response_headers => Utils::Headers + + extend Forwardable + + def_delegators :request, :params_encoder + + # Public + def [](key) + if in_member_set?(key) + super(key) + else + custom_members[key] + end + end + + # Public + def []=(key, value) + if in_member_set?(key) + super(key, value) + else + custom_members[key] = value + end + end + + # Public + def success? + SuccessfulStatuses.include?(status) + end + + # Public + def needs_body? + !body && MethodsWithBodies.include?(method) + end + + # Public + def clear_body + request_headers[ContentLength] = '0' + self.body = '' + end + + # Public + def parse_body? + !StatusesWithoutBody.include?(status) + end + + # Public + def parallel? + !!parallel_manager + end + + def inspect + attrs = [nil] + members.each do |mem| + if value = send(mem) + attrs << "@#{mem}=#{value.inspect}" + end + end + if !custom_members.empty? + attrs << "@custom=#{custom_members.inspect}" + end + %(#<#{self.class}#{attrs.join(" ")}>) + end + + # Internal + def custom_members + @custom_members ||= {} + end + + # Internal + if members.first.is_a?(Symbol) + def in_member_set?(key) + self.class.member_set.include?(key.to_sym) + end + else + def in_member_set?(key) + self.class.member_set.include?(key.to_s) + end + end + + # Internal + def self.member_set + @member_set ||= Set.new(members) + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/parameters.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/parameters.rb new file mode 100644 index 000000000..136c43bca --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/parameters.rb @@ -0,0 +1,193 @@ +module Faraday + module NestedParamsEncoder + ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/ + + def self.escape(s) + return s.to_s.gsub(ESCAPE_RE) { + '%' + $&.unpack('H2' * $&.bytesize).join('%').upcase + }.tr(' ', '+') + end + + def self.unescape(s) + CGI.unescape(s.to_s) + end + + def self.encode(params) + return nil if params == nil + + if !params.is_a?(Array) + if !params.respond_to?(:to_hash) + raise TypeError, + "Can't convert #{params.class} into Hash." + end + params = params.to_hash + params = params.map do |key, value| + key = key.to_s if key.kind_of?(Symbol) + [key, value] + end + # Useful default for OAuth and caching. + # Only to be used for non-Array inputs. Arrays should preserve order. + params.sort! + end + + # Helper lambda + to_query = lambda do |parent, value| + if value.is_a?(Hash) + value = value.map do |key, val| + key = escape(key) + [key, val] + end + value.sort! + buffer = "" + value.each do |key, val| + new_parent = "#{parent}%5B#{key}%5D" + buffer << "#{to_query.call(new_parent, val)}&" + end + return buffer.chop + elsif value.is_a?(Array) + buffer = "" + value.each_with_index do |val, i| + new_parent = "#{parent}%5B%5D" + buffer << "#{to_query.call(new_parent, val)}&" + end + return buffer.chop + else + encoded_value = escape(value) + return "#{parent}=#{encoded_value}" + end + end + + # The params have form [['key1', 'value1'], ['key2', 'value2']]. + buffer = '' + params.each do |parent, value| + encoded_parent = escape(parent) + buffer << "#{to_query.call(encoded_parent, value)}&" + end + return buffer.chop + end + + def self.decode(query) + return nil if query == nil + # Recursive helper lambda + dehash = lambda do |hash| + hash.each do |(key, value)| + if value.kind_of?(Hash) + hash[key] = dehash.call(value) + end + end + # Numeric keys implies an array + if hash != {} && hash.keys.all? { |key| key =~ /^\d+$/ } + hash.sort.inject([]) do |accu, (_, value)| + accu << value; accu + end + else + hash + end + end + + empty_accumulator = {} + return ((query.split('&').map do |pair| + pair.split('=', 2) if pair && !pair.empty? + end).compact.inject(empty_accumulator.dup) do |accu, (key, value)| + key = unescape(key) + if value.kind_of?(String) + value = unescape(value.gsub(/\+/, ' ')) + end + + array_notation = !!(key =~ /\[\]$/) + subkeys = key.split(/[\[\]]+/) + current_hash = accu + for i in 0...(subkeys.size - 1) + subkey = subkeys[i] + current_hash[subkey] = {} unless current_hash[subkey] + current_hash = current_hash[subkey] + end + if array_notation + current_hash[subkeys.last] = [] unless current_hash[subkeys.last] + current_hash[subkeys.last] << value + else + current_hash[subkeys.last] = value + end + accu + end).inject(empty_accumulator.dup) do |accu, (key, value)| + accu[key] = value.kind_of?(Hash) ? dehash.call(value) : value + accu + end + end + end + + module FlatParamsEncoder + ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/ + + def self.escape(s) + return s.to_s.gsub(ESCAPE_RE) { + '%' + $&.unpack('H2' * $&.bytesize).join('%').upcase + }.tr(' ', '+') + end + + def self.unescape(s) + CGI.unescape(s.to_s) + end + + def self.encode(params) + return nil if params == nil + + if !params.is_a?(Array) + if !params.respond_to?(:to_hash) + raise TypeError, + "Can't convert #{params.class} into Hash." + end + params = params.to_hash + params = params.map do |key, value| + key = key.to_s if key.kind_of?(Symbol) + [key, value] + end + # Useful default for OAuth and caching. + # Only to be used for non-Array inputs. Arrays should preserve order. + params.sort! + end + + # The params have form [['key1', 'value1'], ['key2', 'value2']]. + buffer = '' + params.each do |key, value| + encoded_key = escape(key) + value = value.to_s if value == true || value == false + if value == nil + buffer << "#{encoded_key}&" + elsif value.kind_of?(Array) + value.each do |sub_value| + encoded_value = escape(sub_value) + buffer << "#{encoded_key}=#{encoded_value}&" + end + else + encoded_value = escape(value) + buffer << "#{encoded_key}=#{encoded_value}&" + end + end + return buffer.chop + end + + def self.decode(query) + empty_accumulator = {} + return nil if query == nil + split_query = (query.split('&').map do |pair| + pair.split('=', 2) if pair && !pair.empty? + end).compact + return split_query.inject(empty_accumulator.dup) do |accu, pair| + pair[0] = unescape(pair[0]) + pair[1] = true if pair[1].nil? + if pair[1].respond_to?(:to_str) + pair[1] = unescape(pair[1].to_str.gsub(/\+/, " ")) + end + if accu[pair[0]].kind_of?(Array) + accu[pair[0]] << pair[1] + elsif accu[pair[0]] + accu[pair[0]] = [accu[pair[0]], pair[1]] + else + accu[pair[0]] = pair[1] + end + accu + end + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/rack_builder.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/rack_builder.rb new file mode 100644 index 000000000..204ce41d1 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/rack_builder.rb @@ -0,0 +1,212 @@ +module Faraday + # A Builder that processes requests into responses by passing through an inner + # middleware stack (heavily inspired by Rack). + # + # Faraday::Connection.new(:url => 'http://sushi.com') do |builder| + # builder.request :url_encoded # Faraday::Request::UrlEncoded + # builder.adapter :net_http # Faraday::Adapter::NetHttp + # end + class RackBuilder + attr_accessor :handlers + + # Error raised when trying to modify the stack after calling `lock!` + class StackLocked < RuntimeError; end + + # borrowed from ActiveSupport::Dependencies::Reference & + # ActionDispatch::MiddlewareStack::Middleware + class Handler + @@constants_mutex = Mutex.new + @@constants = Hash.new { |h, k| + value = k.respond_to?(:constantize) ? k.constantize : Object.const_get(k) + @@constants_mutex.synchronize { h[k] = value } + } + + attr_reader :name + + def initialize(klass, *args, &block) + @name = klass.to_s + if klass.respond_to?(:name) + @@constants_mutex.synchronize { @@constants[@name] = klass } + end + @args, @block = args, block + end + + def klass() @@constants[@name] end + def inspect() @name end + + def ==(other) + if other.is_a? Handler + self.name == other.name + elsif other.respond_to? :name + klass == other + else + @name == other.to_s + end + end + + def build(app) + klass.new(app, *@args, &@block) + end + end + + def initialize(handlers = []) + @handlers = handlers + if block_given? + build(&Proc.new) + elsif @handlers.empty? + # default stack, if nothing else is configured + self.request :url_encoded + self.adapter Faraday.default_adapter + end + end + + def build(options = {}) + raise_if_locked + @handlers.clear unless options[:keep] + yield(self) if block_given? + end + + def [](idx) + @handlers[idx] + end + + # Locks the middleware stack to ensure no further modifications are possible. + def lock! + @handlers.freeze + end + + def locked? + @handlers.frozen? + end + + def use(klass, *args, &block) + if klass.is_a? Symbol + use_symbol(Faraday::Middleware, klass, *args, &block) + else + raise_if_locked + @handlers << self.class::Handler.new(klass, *args, &block) + end + end + + def request(key, *args, &block) + use_symbol(Faraday::Request, key, *args, &block) + end + + def response(key, *args, &block) + use_symbol(Faraday::Response, key, *args, &block) + end + + def adapter(key, *args, &block) + use_symbol(Faraday::Adapter, key, *args, &block) + end + + ## methods to push onto the various positions in the stack: + + def insert(index, *args, &block) + raise_if_locked + index = assert_index(index) + handler = self.class::Handler.new(*args, &block) + @handlers.insert(index, handler) + end + + alias_method :insert_before, :insert + + def insert_after(index, *args, &block) + index = assert_index(index) + insert(index + 1, *args, &block) + end + + def swap(index, *args, &block) + raise_if_locked + index = assert_index(index) + @handlers.delete_at(index) + insert(index, *args, &block) + end + + def delete(handler) + raise_if_locked + @handlers.delete(handler) + end + + # Processes a Request into a Response by passing it through this Builder's + # middleware stack. + # + # connection - Faraday::Connection + # request - Faraday::Request + # + # Returns a Faraday::Response. + def build_response(connection, request) + app.call(build_env(connection, request)) + end + + # The "rack app" wrapped in middleware. All requests are sent here. + # + # The builder is responsible for creating the app object. After this, + # the builder gets locked to ensure no further modifications are made + # to the middleware stack. + # + # Returns an object that responds to `call` and returns a Response. + def app + @app ||= begin + lock! + to_app(lambda { |env| + response = Response.new + response.finish(env) unless env.parallel? + env.response = response + }) + end + end + + def to_app(inner_app) + # last added handler is the deepest and thus closest to the inner app + @handlers.reverse.inject(inner_app) { |app, handler| handler.build(app) } + end + + def ==(other) + other.is_a?(self.class) && @handlers == other.handlers + end + + def dup + self.class.new(@handlers.dup) + end + + # ENV Keys + # :method - a symbolized request method (:get, :post) + # :body - the request body that will eventually be converted to a string. + # :url - URI instance for the current request. + # :status - HTTP response status code + # :request_headers - hash of HTTP Headers to be sent to the server + # :response_headers - Hash of HTTP headers from the server + # :parallel_manager - sent if the connection is in parallel mode + # :request - Hash of options for configuring the request. + # :timeout - open/read timeout Integer in seconds + # :open_timeout - read timeout Integer in seconds + # :proxy - Hash of proxy options + # :uri - Proxy Server URI + # :user - Proxy server username + # :password - Proxy server password + # :ssl - Hash of options for configuring SSL requests. + def build_env(connection, request) + Env.new(request.method, request.body, + connection.build_exclusive_url(request.path, request.params), + request.options, request.headers, connection.ssl, + connection.parallel_manager) + end + + private + + def raise_if_locked + raise StackLocked, "can't modify middleware stack after making a request" if locked? + end + + def use_symbol(mod, key, *args, &block) + use(mod.lookup_middleware(key), *args, &block) + end + + def assert_index(index) + idx = index.is_a?(Integer) ? index : @handlers.index(index) + raise "No such handler: #{index.inspect}" unless idx + idx + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/request.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/request.rb new file mode 100644 index 000000000..481077f14 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/request.rb @@ -0,0 +1,92 @@ +module Faraday + # Used to setup urls, params, headers, and the request body in a sane manner. + # + # @connection.post do |req| + # req.url 'http://localhost', 'a' => '1' # 'http://localhost?a=1' + # req.headers['b'] = '2' # Header + # req.params['c'] = '3' # GET Param + # req['b'] = '2' # also Header + # req.body = 'abc' + # end + # + class Request < Struct.new(:method, :path, :params, :headers, :body, :options) + extend MiddlewareRegistry + + register_middleware File.expand_path('../request', __FILE__), + :url_encoded => [:UrlEncoded, 'url_encoded'], + :multipart => [:Multipart, 'multipart'], + :retry => [:Retry, 'retry'], + :authorization => [:Authorization, 'authorization'], + :basic_auth => [:BasicAuthentication, 'basic_authentication'], + :token_auth => [:TokenAuthentication, 'token_authentication'], + :instrumentation => [:Instrumentation, 'instrumentation'] + + def self.create(request_method) + new(request_method).tap do |request| + yield(request) if block_given? + end + end + + # Public: Replace params, preserving the existing hash type + def params=(hash) + if params + params.replace hash + else + super + end + end + + # Public: Replace request headers, preserving the existing hash type + def headers=(hash) + if headers + headers.replace hash + else + super + end + end + + def url(path, params = nil) + if path.respond_to? :query + if query = path.query + path = path.dup + path.query = nil + end + else + path, query = path.split('?', 2) + end + self.path = path + self.params.merge_query query, options.params_encoder + self.params.update(params) if params + end + + def [](key) + headers[key] + end + + def []=(key, value) + headers[key] = value + end + + # ENV Keys + # :method - a symbolized request method (:get, :post) + # :body - the request body that will eventually be converted to a string. + # :url - URI instance for the current request. + # :status - HTTP response status code + # :request_headers - hash of HTTP Headers to be sent to the server + # :response_headers - Hash of HTTP headers from the server + # :parallel_manager - sent if the connection is in parallel mode + # :request - Hash of options for configuring the request. + # :timeout - open/read timeout Integer in seconds + # :open_timeout - read timeout Integer in seconds + # :proxy - Hash of proxy options + # :uri - Proxy Server URI + # :user - Proxy server username + # :password - Proxy server password + # :ssl - Hash of options for configuring SSL requests. + def to_env(connection) + Env.new(method, body, connection.build_exclusive_url(path, params), + options, headers, connection.ssl, connection.parallel_manager) + end + end +end + diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/authorization.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/authorization.rb new file mode 100644 index 000000000..43b452880 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/authorization.rb @@ -0,0 +1,42 @@ +module Faraday + class Request::Authorization < Faraday::Middleware + KEY = "Authorization".freeze unless defined? KEY + + # Public + def self.header(type, token) + case token + when String, Symbol + "#{type} #{token}" + when Hash + build_hash(type.to_s, token) + else + raise ArgumentError, "Can't build an Authorization #{type} header from #{token.inspect}" + end + end + + # Internal + def self.build_hash(type, hash) + offset = KEY.size + type.size + 3 + comma = ",\n#{' ' * offset}" + values = [] + hash.each do |key, value| + values << "#{key}=#{value.to_s.inspect}" + end + "#{type} #{values * comma}" + end + + def initialize(app, type, token) + @header_value = self.class.header(type, token) + super(app) + end + + # Public + def call(env) + unless env.request_headers[KEY] + env.request_headers[KEY] = @header_value + end + @app.call(env) + end + end +end + diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/basic_authentication.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/basic_authentication.rb new file mode 100644 index 000000000..54c8dee97 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/basic_authentication.rb @@ -0,0 +1,13 @@ +require 'base64' + +module Faraday + class Request::BasicAuthentication < Request.load_middleware(:authorization) + # Public + def self.header(login, pass) + value = Base64.encode64([login, pass].join(':')) + value.gsub!("\n", '') + super(:Basic, value) + end + end +end + diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/instrumentation.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/instrumentation.rb new file mode 100644 index 000000000..42af8bc44 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/instrumentation.rb @@ -0,0 +1,36 @@ +module Faraday + class Request::Instrumentation < Faraday::Middleware + class Options < Faraday::Options.new(:name, :instrumenter) + def name + self[:name] ||= 'request.faraday' + end + + def instrumenter + self[:instrumenter] ||= ActiveSupport::Notifications + end + end + + # Public: Instruments requests using Active Support. + # + # Measures time spent only for synchronous requests. + # + # Examples + # + # ActiveSupport::Notifications.subscribe('request.faraday') do |name, starts, ends, _, env| + # url = env[:url] + # http_method = env[:method].to_s.upcase + # duration = ends - starts + # $stderr.puts '[%s] %s %s (%.3f s)' % [url.host, http_method, url.request_uri, duration] + # end + def initialize(app, options = nil) + super(app) + @name, @instrumenter = Options.from(options).values_at(:name, :instrumenter) + end + + def call(env) + @instrumenter.instrument(@name, env) do + @app.call(env) + end + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/multipart.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/multipart.rb new file mode 100644 index 000000000..38b452af7 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/multipart.rb @@ -0,0 +1,63 @@ +require File.expand_path("../url_encoded", __FILE__) + +module Faraday + class Request::Multipart < Request::UrlEncoded + self.mime_type = 'multipart/form-data'.freeze + DEFAULT_BOUNDARY = "-----------RubyMultipartPost".freeze unless defined? DEFAULT_BOUNDARY + + def call(env) + match_content_type(env) do |params| + env.request.boundary ||= DEFAULT_BOUNDARY + env.request_headers[CONTENT_TYPE] += "; boundary=#{env.request.boundary}" + env.body = create_multipart(env, params) + end + @app.call env + end + + def process_request?(env) + type = request_type(env) + env.body.respond_to?(:each_key) and !env.body.empty? and ( + (type.empty? and has_multipart?(env.body)) or + type == self.class.mime_type + ) + end + + def has_multipart?(obj) + # string is an enum in 1.8, returning list of itself + if obj.respond_to?(:each) && !obj.is_a?(String) + (obj.respond_to?(:values) ? obj.values : obj).each do |val| + return true if (val.respond_to?(:content_type) || has_multipart?(val)) + end + end + false + end + + def create_multipart(env, params) + boundary = env.request.boundary + parts = process_params(params) do |key, value| + Faraday::Parts::Part.new(boundary, key, value) + end + parts << Faraday::Parts::EpiloguePart.new(boundary) + + body = Faraday::CompositeReadIO.new(parts) + env.request_headers[Faraday::Env::ContentLength] = body.length.to_s + return body + end + + def process_params(params, prefix = nil, pieces = nil, &block) + params.inject(pieces || []) do |all, (key, value)| + key = "#{prefix}[#{key}]" if prefix + + case value + when Array + values = value.inject([]) { |a,v| a << [nil, v] } + process_params(values, key, all, &block) + when Hash + process_params(value, key, all, &block) + else + all << block.call(key, value) + end + end + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/retry.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/retry.rb new file mode 100644 index 000000000..08bc83766 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/retry.rb @@ -0,0 +1,140 @@ +module Faraday + # Catches exceptions and retries each request a limited number of times. + # + # By default, it retries 2 times and handles only timeout exceptions. It can + # be configured with an arbitrary number of retries, a list of exceptions to + # handle, a retry interval, a percentage of randomness to add to the retry + # interval, and a backoff factor. + # + # Examples + # + # Faraday.new do |conn| + # conn.request :retry, max: 2, interval: 0.05, + # interval_randomness: 0.5, backoff_factor: 2 + # exceptions: [CustomException, 'Timeout::Error'] + # conn.adapter ... + # end + # + # This example will result in a first interval that is random between 0.05 and 0.075 and a second + # interval that is random between 0.1 and 0.15 + # + class Request::Retry < Faraday::Middleware + + IDEMPOTENT_METHODS = [:delete, :get, :head, :options, :put] + + class Options < Faraday::Options.new(:max, :interval, :interval_randomness, :backoff_factor, :exceptions, :retry_if) + DEFAULT_CHECK = lambda { |env,exception| false } + + def self.from(value) + if Fixnum === value + new(value) + else + super(value) + end + end + + def max + (self[:max] ||= 2).to_i + end + + def interval + (self[:interval] ||= 0).to_f + end + + def interval_randomness + (self[:interval_randomness] ||= 0).to_i + end + + def backoff_factor + (self[:backoff_factor] ||= 1).to_f + end + + def exceptions + Array(self[:exceptions] ||= [Errno::ETIMEDOUT, 'Timeout::Error', + Error::TimeoutError]) + end + + def retry_if + self[:retry_if] ||= DEFAULT_CHECK + end + + end + + # Public: Initialize middleware + # + # Options: + # max - Maximum number of retries (default: 2) + # interval - Pause in seconds between retries (default: 0) + # interval_randomness - The maximum random interval amount expressed + # as a float between 0 and 1 to use in addition to the + # interval. (default: 0) + # backoff_factor - The amount to multiple each successive retry's + # interval amount by in order to provide backoff + # (default: 1) + # exceptions - The list of exceptions to handle. Exceptions can be + # given as Class, Module, or String. (default: + # [Errno::ETIMEDOUT, Timeout::Error, + # Error::TimeoutError]) + # retry_if - block that will receive the env object and the exception raised + # and should decide if the code should retry still the action or + # not independent of the retry count. This would be useful + # if the exception produced is non-recoverable or if the + # the HTTP method called is not idempotent. + # (defaults to return false) + def initialize(app, options = nil) + super(app) + @options = Options.from(options) + @errmatch = build_exception_matcher(@options.exceptions) + end + + def sleep_amount(retries) + retry_index = @options.max - retries + current_interval = @options.interval * (@options.backoff_factor ** retry_index) + random_interval = rand * @options.interval_randomness.to_f * @options.interval + current_interval + random_interval + end + + def call(env) + retries = @options.max + request_body = env[:body] + begin + env[:body] = request_body # after failure env[:body] is set to the response body + @app.call(env) + rescue @errmatch => exception + if retries > 0 && retry_request?(env, exception) + retries -= 1 + sleep sleep_amount(retries + 1) + retry + end + raise + end + end + + # Private: construct an exception matcher object. + # + # An exception matcher for the rescue clause can usually be any object that + # responds to `===`, but for Ruby 1.8 it has to be a Class or Module. + def build_exception_matcher(exceptions) + matcher = Module.new + (class << matcher; self; end).class_eval do + define_method(:===) do |error| + exceptions.any? do |ex| + if ex.is_a? Module + error.is_a? ex + else + error.class.to_s == ex.to_s + end + end + end + end + matcher + end + + private + + def retry_request?(env, exception) + IDEMPOTENT_METHODS.include?(env[:method]) || @options.retry_if.call(env, exception) + end + + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/token_authentication.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/token_authentication.rb new file mode 100644 index 000000000..25586080c --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/token_authentication.rb @@ -0,0 +1,15 @@ +module Faraday + class Request::TokenAuthentication < Request.load_middleware(:authorization) + # Public + def self.header(token, options = nil) + options ||= {} + options[:token] = token + super(:Token, options) + end + + def initialize(app, token, options = nil) + super(app, token, options) + end + end +end + diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/url_encoded.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/url_encoded.rb new file mode 100644 index 000000000..b02a26621 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/request/url_encoded.rb @@ -0,0 +1,36 @@ +module Faraday + class Request::UrlEncoded < Faraday::Middleware + CONTENT_TYPE = 'Content-Type'.freeze unless defined? CONTENT_TYPE + + class << self + attr_accessor :mime_type + end + self.mime_type = 'application/x-www-form-urlencoded'.freeze + + def call(env) + match_content_type(env) do |data| + params = Faraday::Utils::ParamsHash[data] + env.body = params.to_query(env.params_encoder) + end + @app.call env + end + + def match_content_type(env) + if process_request?(env) + env.request_headers[CONTENT_TYPE] ||= self.class.mime_type + yield(env.body) unless env.body.respond_to?(:to_str) + end + end + + def process_request?(env) + type = request_type(env) + env.body and (type.empty? or type == self.class.mime_type) + end + + def request_type(env) + type = env.request_headers[CONTENT_TYPE].to_s + type = type.split(';', 2).first if type.index(';') + type + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/response.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/response.rb new file mode 100644 index 000000000..88ec5310a --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/response.rb @@ -0,0 +1,93 @@ +require 'forwardable' + +module Faraday + class Response + # Used for simple response middleware. + class Middleware < Faraday::Middleware + def call(env) + @app.call(env).on_complete do |environment| + on_complete(environment) + end + end + + # Override this to modify the environment after the response has finished. + # Calls the `parse` method if defined + def on_complete(env) + env.body = parse(env.body) if respond_to?(:parse) && env.parse_body? + end + end + + extend Forwardable + extend MiddlewareRegistry + + register_middleware File.expand_path('../response', __FILE__), + :raise_error => [:RaiseError, 'raise_error'], + :logger => [:Logger, 'logger'] + + def initialize(env = nil) + @env = Env.from(env) if env + @on_complete_callbacks = [] + end + + attr_reader :env + + def_delegators :env, :to_hash + + def status + finished? ? env.status : nil + end + + def headers + finished? ? env.response_headers : {} + end + def_delegator :headers, :[] + + def body + finished? ? env.body : nil + end + + def finished? + !!env + end + + def on_complete + if not finished? + @on_complete_callbacks << Proc.new + else + yield(env) + end + return self + end + + def finish(env) + raise "response already finished" if finished? + @on_complete_callbacks.each { |callback| callback.call(env) } + @env = Env.from(env) + return self + end + + def success? + finished? && env.success? + end + + # because @on_complete_callbacks cannot be marshalled + def marshal_dump + !finished? ? nil : { + :status => @env.status, :body => @env.body, + :response_headers => @env.response_headers + } + end + + def marshal_load(env) + @env = Env.from(env) + end + + # Expand the env with more properties, without overriding existing ones. + # Useful for applying request params after restoring a marshalled Response. + def apply_request(request_env) + raise "response didn't finish yet" unless finished? + @env = Env.from(request_env).update(@env) + return self + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/response/logger.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/response/logger.rb new file mode 100644 index 000000000..cab7f1b7c --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/response/logger.rb @@ -0,0 +1,34 @@ +require 'forwardable' + +module Faraday + class Response::Logger < Response::Middleware + extend Forwardable + + def initialize(app, logger = nil) + super(app) + @logger = logger || begin + require 'logger' + ::Logger.new(STDOUT) + end + end + + def_delegators :@logger, :debug, :info, :warn, :error, :fatal + + def call(env) + info "#{env.method} #{env.url.to_s}" + debug('request') { dump_headers env.request_headers } + super + end + + def on_complete(env) + info('Status') { env.status.to_s } + debug('response') { dump_headers env.response_headers } + end + + private + + def dump_headers(headers) + headers.map { |k, v| "#{k}: #{v.inspect}" }.join("\n") + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/response/raise_error.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/response/raise_error.rb new file mode 100644 index 000000000..437762bc1 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/response/raise_error.rb @@ -0,0 +1,21 @@ +module Faraday + class Response::RaiseError < Response::Middleware + ClientErrorStatuses = 400...600 + + def on_complete(env) + case env[:status] + when 404 + raise Faraday::Error::ResourceNotFound, response_values(env) + when 407 + # mimic the behavior that we get with proxy requests with HTTPS + raise Faraday::Error::ConnectionFailed, %{407 "Proxy Authentication Required "} + when ClientErrorStatuses + raise Faraday::Error::ClientError, response_values(env) + end + end + + def response_values(env) + {:status => env.status, :headers => env.response_headers, :body => env.body} + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/upload_io.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/upload_io.rb new file mode 100644 index 000000000..9130d159d --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/upload_io.rb @@ -0,0 +1,67 @@ +begin + require 'composite_io' + require 'parts' + require 'stringio' +rescue LoadError + $stderr.puts "Install the multipart-post gem." + raise +end + +module Faraday + # Similar but not compatible with ::CompositeReadIO provided by multipart-post. + class CompositeReadIO + def initialize(*parts) + @parts = parts.flatten + @ios = @parts.map { |part| part.to_io } + @index = 0 + end + + def length + @parts.inject(0) { |sum, part| sum + part.length } + end + + def rewind + @ios.each { |io| io.rewind } + @index = 0 + end + + # Read from IOs in order until `length` bytes have been received. + def read(length = nil, outbuf = nil) + got_result = false + outbuf = outbuf ? outbuf.replace("") : "" + + while io = current_io + if result = io.read(length) + got_result ||= !result.nil? + result.force_encoding("BINARY") if result.respond_to?(:force_encoding) + outbuf << result + length -= result.length if length + break if length == 0 + end + advance_io + end + (!got_result && length) ? nil : outbuf + end + + def close + @ios.each { |io| io.close } + end + + def ensure_open_and_readable + # Rubinius compatibility + end + + private + + def current_io + @ios[@index] + end + + def advance_io + @index += 1 + end + end + + UploadIO = ::UploadIO + Parts = ::Parts +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/faraday/utils.rb b/3rdparty/modules/aviator/lib/puppet/feature/faraday/utils.rb new file mode 100644 index 000000000..1cd6526a6 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/faraday/utils.rb @@ -0,0 +1,297 @@ +require 'thread' +Faraday.require_libs 'parameters' + +module Faraday + module Utils + extend self + + # Adapted from Rack::Utils::HeaderHash + class Headers < ::Hash + def self.from(value) + new(value) + end + + def initialize(hash = nil) + super() + @names = {} + self.update(hash || {}) + end + + # need to synchronize concurrent writes to the shared KeyMap + keymap_mutex = Mutex.new + + # symbol -> string mapper + cache + KeyMap = Hash.new do |map, key| + value = if key.respond_to?(:to_str) + key + else + key.to_s.split('_'). # :user_agent => %w(user agent) + each { |w| w.capitalize! }. # => %w(User Agent) + join('-') # => "User-Agent" + end + keymap_mutex.synchronize { map[key] = value } + end + KeyMap[:etag] = "ETag" + + def [](k) + k = KeyMap[k] + super(k) || super(@names[k.downcase]) + end + + def []=(k, v) + k = KeyMap[k] + k = (@names[k.downcase] ||= k) + # join multiple values with a comma + v = v.to_ary.join(', ') if v.respond_to? :to_ary + super(k, v) + end + + def fetch(k, *args, &block) + k = KeyMap[k] + key = @names.fetch(k.downcase, k) + super(key, *args, &block) + end + + def delete(k) + k = KeyMap[k] + if k = @names[k.downcase] + @names.delete k.downcase + super(k) + end + end + + def include?(k) + @names.include? k.downcase + end + + alias_method :has_key?, :include? + alias_method :member?, :include? + alias_method :key?, :include? + + def merge!(other) + other.each { |k, v| self[k] = v } + self + end + alias_method :update, :merge! + + def merge(other) + hash = dup + hash.merge! other + end + + def replace(other) + clear + self.update other + self + end + + def to_hash() ::Hash.new.update(self) end + + def parse(header_string) + return unless header_string && !header_string.empty? + header_string.split(/\r\n/). + tap { |a| a.shift if a.first.index('HTTP/') == 0 }. # drop the HTTP status line + map { |h| h.split(/:\s+/, 2) }.reject { |p| p[0].nil? }. # split key and value, ignore blank lines + each { |key, value| + # join multiple values with a comma + if self[key] + self[key] << ', ' << value + else + self[key] = value + end + } + end + end + + # hash with stringified keys + class ParamsHash < Hash + def [](key) + super(convert_key(key)) + end + + def []=(key, value) + super(convert_key(key), value) + end + + def delete(key) + super(convert_key(key)) + end + + def include?(key) + super(convert_key(key)) + end + + alias_method :has_key?, :include? + alias_method :member?, :include? + alias_method :key?, :include? + + def update(params) + params.each do |key, value| + self[key] = value + end + self + end + alias_method :merge!, :update + + def merge(params) + dup.update(params) + end + + def replace(other) + clear + update(other) + end + + def merge_query(query, encoder = nil) + if query && !query.empty? + update((encoder || Utils.default_params_encoder).decode(query)) + end + self + end + + def to_query(encoder = nil) + (encoder || Utils.default_params_encoder).encode(self) + end + + private + + def convert_key(key) + key.to_s + end + end + + def build_query(params) + FlatParamsEncoder.encode(params) + end + + def build_nested_query(params) + NestedParamsEncoder.encode(params) + end + + ESCAPE_RE = /[^a-zA-Z0-9 .~_-]/ + + def escape(s) + s.to_s.gsub(ESCAPE_RE) {|match| + '%' + match.unpack('H2' * match.bytesize).join('%').upcase + }.tr(' ', '+') + end + + def unescape(s) CGI.unescape s.to_s end + + DEFAULT_SEP = /[&;] */n + + # Adapted from Rack + def parse_query(query) + FlatParamsEncoder.decode(query) + end + + def parse_nested_query(query) + NestedParamsEncoder.decode(query) + end + + def default_params_encoder + @default_params_encoder ||= NestedParamsEncoder + end + + class << self + attr_writer :default_params_encoder + end + + # Stolen from Rack + def normalize_params(params, name, v = nil) + name =~ %r(\A[\[\]]*([^\[\]]+)\]*) + k = $1 || '' + after = $' || '' + + return if k.empty? + + if after == "" + if params[k] + params[k] = Array[params[k]] unless params[k].kind_of?(Array) + params[k] << v + else + params[k] = v + end + elsif after == "[]" + params[k] ||= [] + raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array) + params[k] << v + elsif after =~ %r(^\[\]\[([^\[\]]+)\]$) || after =~ %r(^\[\](.+)$) + child_key = $1 + params[k] ||= [] + raise TypeError, "expected Array (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Array) + if params[k].last.is_a?(Hash) && !params[k].last.key?(child_key) + normalize_params(params[k].last, child_key, v) + else + params[k] << normalize_params({}, child_key, v) + end + else + params[k] ||= {} + raise TypeError, "expected Hash (got #{params[k].class.name}) for param `#{k}'" unless params[k].is_a?(Hash) + params[k] = normalize_params(params[k], after, v) + end + + return params + end + + # Normalize URI() behavior across Ruby versions + # + # url - A String or URI. + # + # Returns a parsed URI. + def URI(url) + if url.respond_to?(:host) + url + elsif url.respond_to?(:to_str) + default_uri_parser.call(url) + else + raise ArgumentError, "bad argument (expected URI object or URI string)" + end + end + + def default_uri_parser + @default_uri_parser ||= begin + require 'uri' + Kernel.method(:URI) + end + end + + def default_uri_parser=(parser) + @default_uri_parser = if parser.respond_to?(:call) || parser.nil? + parser + else + parser.method(:parse) + end + end + + # Receives a String or URI and returns just the path with the query string sorted. + def normalize_path(url) + url = URI(url) + (url.path.start_with?('/') ? url.path : '/' + url.path) + + (url.query ? "?#{sort_query_params(url.query)}" : "") + end + + # Recursive hash update + def deep_merge!(target, hash) + hash.each do |key, value| + if Hash === value and Hash === target[key] + target[key] = deep_merge(target[key], value) + else + target[key] = value + end + end + target + end + + # Recursive hash merge + def deep_merge(source, hash) + deep_merge!(source.dup, hash) + end + + protected + + def sort_query_params(query) + query.split('&').sort.join('&') + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/multipart_post.rb b/3rdparty/modules/aviator/lib/puppet/feature/multipart_post.rb new file mode 100644 index 000000000..76540a8b7 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/multipart_post.rb @@ -0,0 +1,9 @@ +#-- +# Copyright (c) 2007-2013 Nick Sieger. +# See the file README.txt included with the distribution for +# software license details. +#++ + +module MultipartPost + VERSION = "2.0.0" +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/multipartable.rb b/3rdparty/modules/aviator/lib/puppet/feature/multipartable.rb new file mode 100644 index 000000000..28fa41e6d --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/multipartable.rb @@ -0,0 +1,29 @@ +#-- +# Copyright (c) 2007-2013 Nick Sieger. +# See the file README.txt included with the distribution for +# software license details. +#++ + +require 'parts' + module Multipartable + DEFAULT_BOUNDARY = "-----------RubyMultipartPost" + def initialize(path, params, headers={}, boundary = DEFAULT_BOUNDARY) + headers = headers.clone # don't want to modify the original variable + parts_headers = headers.delete(:parts) || {} + super(path, headers) + parts = params.map do |k,v| + case v + when Array + v.map {|item| Parts::Part.new(boundary, k, item, parts_headers[k]) } + else + Parts::Part.new(boundary, k, v, parts_headers[k]) + end + end.flatten + parts << Parts::EpiloguePart.new(boundary) + ios = parts.map {|p| p.to_io } + self.set_content_type(headers["Content-Type"] || "multipart/form-data", + { "boundary" => boundary }) + self.content_length = parts.inject(0) {|sum,i| sum + i.length } + self.body_stream = CompositeReadIO.new(*ios) + end + end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/net/http/post/multipart.rb b/3rdparty/modules/aviator/lib/puppet/feature/net/http/post/multipart.rb new file mode 100644 index 000000000..757058220 --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/net/http/post/multipart.rb @@ -0,0 +1,27 @@ +#-- +# Copyright (c) 2007-2012 Nick Sieger. +# See the file README.txt included with the distribution for +# software license details. +#++ + +require 'net/http' +require 'stringio' +require 'cgi' +require 'composite_io' +require 'multipartable' +require 'parts' + +module Net #:nodoc: + class HTTP #:nodoc: + class Put + class Multipart < Put + include Multipartable + end + end + class Post #:nodoc: + class Multipart < Post + include Multipartable + end + end + end +end diff --git a/3rdparty/modules/aviator/lib/puppet/feature/parts.rb b/3rdparty/modules/aviator/lib/puppet/feature/parts.rb new file mode 100644 index 000000000..c06cbd95d --- /dev/null +++ b/3rdparty/modules/aviator/lib/puppet/feature/parts.rb @@ -0,0 +1,96 @@ +#-- +# Copyright (c) 2007-2013 Nick Sieger. +# See the file README.txt included with the distribution for +# software license details. +#++ + +module Parts + module Part #:nodoc: + def self.new(boundary, name, value, headers = {}) + headers ||= {} # avoid nil values + if file?(value) + FilePart.new(boundary, name, value, headers) + else + ParamPart.new(boundary, name, value, headers) + end + end + + def self.file?(value) + value.respond_to?(:content_type) && value.respond_to?(:original_filename) + end + + def length + @part.length + end + + def to_io + @io + end + end + + class ParamPart + include Part + def initialize(boundary, name, value, headers = {}) + @part = build_part(boundary, name, value, headers) + @io = StringIO.new(@part) + end + + def length + @part.bytesize + end + + def build_part(boundary, name, value, headers = {}) + part = '' + part << "--#{boundary}\r\n" + part << "Content-Disposition: form-data; name=\"#{name.to_s}\"\r\n" + part << "Content-Type: #{headers["Content-Type"]}\r\n" if headers["Content-Type"] + part << "\r\n" + part << "#{value}\r\n" + end + end + + # Represents a part to be filled from file IO. + class FilePart + include Part + attr_reader :length + def initialize(boundary, name, io, headers = {}) + file_length = io.respond_to?(:length) ? io.length : File.size(io.local_path) + @head = build_head(boundary, name, io.original_filename, io.content_type, file_length, + io.respond_to?(:opts) ? io.opts.merge(headers) : headers) + @foot = "\r\n" + @length = @head.bytesize + file_length + @foot.length + @io = CompositeReadIO.new(StringIO.new(@head), io, StringIO.new(@foot)) + end + + def build_head(boundary, name, filename, type, content_len, opts = {}, headers = {}) + trans_encoding = opts["Content-Transfer-Encoding"] || "binary" + content_disposition = opts["Content-Disposition"] || "form-data" + + part = '' + part << "--#{boundary}\r\n" + part << "Content-Disposition: #{content_disposition}; name=\"#{name.to_s}\"; filename=\"#{filename}\"\r\n" + part << "Content-Length: #{content_len}\r\n" + if content_id = opts["Content-ID"] + part << "Content-ID: #{content_id}\r\n" + end + + if headers["Content-Type"] != nil + part << "Content-Type: " + headers["Content-Type"] + "\r\n" + else + part << "Content-Type: #{type}\r\n" + end + + part << "Content-Transfer-Encoding: #{trans_encoding}\r\n" + part << "\r\n" + end + end + + # Represents the epilogue or closing boundary. + class EpiloguePart + include Part + def initialize(boundary) + @part = "--#{boundary}--\r\n\r\n" + @io = StringIO.new(@part) + end + end +end diff --git a/3rdparty/modules/aviator/metadata.json b/3rdparty/modules/aviator/metadata.json new file mode 100644 index 000000000..7eff1a6c0 --- /dev/null +++ b/3rdparty/modules/aviator/metadata.json @@ -0,0 +1,14 @@ +{ + "name": "aimonb-aviator", + "version": "0.5.1", + "author": "aimonb", + "summary": "Puppet feature wrapper for the Aviator OpenStack API library for Ruby", + "license": "MIT License", + "source": "https://github.com/aimonb/puppet_aviator", + "project_page": "https://github.com/aimonb/puppet_aviator", + "issues_url": "https://github.com/aimonb/puppet_aviator/issues", + "description": "UNKNOWN", + "dependencies": [ + + ] +}