pax_global_header00006660000000000000000000000064135471400050014511gustar00rootroot0000000000000052 comment=369e980716d12d379a7d256288076eea68a3686d vagrant_cloud-2.0.3/000077500000000000000000000000001354714000500143435ustar00rootroot00000000000000vagrant_cloud-2.0.3/.circleci/000077500000000000000000000000001354714000500161765ustar00rootroot00000000000000vagrant_cloud-2.0.3/.circleci/config.yml000066400000000000000000000061021354714000500201650ustar00rootroot00000000000000version: 2 reference: environment: &ENVIRONMENT SLACK_TITLE: Vagrant Cloud CI RELEASE_TARGET_REPONAME: vagrant_cloud images: ruby24: &ruby24 docker: - image: circleci/ruby:2.4 ruby25: &ruby25 docker: - image: circleci/ruby:2.5 ruby26: &ruby26 docker: - image: circleci/ruby:2.6 builder: &builder environment: <<: *ENVIRONMENT docker: - image: $BUILDER_IMAGE auth: username: $BUILDER_USERNAME password: $BUILDER_PASSWORD workflows: public: &PUBLIC_WORKFLOW filters: branches: only: - /^pull\/.*/ - master private_build: &PRIVATE_WORKFLOW context: vagrant filters: branches: ignore: /.*/ tags: only: /.*/ jobs: private_failure: &PRIVATE_FAILURE run: name: Failure handler command: | if [ -f .output ]; then slack -m "Vagrant Cloud RubyGem job has failed: *${CIRCLE_JOB}*" -s error -f .output -T 5 else slack -m "Vagrant Cloud RubyGem job has failed: *${CIRCLE_JOB}*" -s error fi when: on_fail unit_tests: &unit_tests steps: - checkout - run: bundle install - run: bundle exec rake jobs: test_ruby24: <<: *ruby24 <<: *unit_tests test_ruby25: <<: *ruby25 <<: *unit_tests test_ruby26: <<: *ruby26 <<: *unit_tests build: <<: *builder steps: - checkout - run: gem build vagrant_cloud.gemspec - *PRIVATE_FAILURE - persist_to_workspace: root: . paths: - ./*.gem release: <<: *builder steps: - attach_workspace: at: . - run: | set +e gem=(vagrant_cloud-*.gem) gem_version="${gem##vagrant_cloud-}" gem_version="${gem_version%%.gem}" export GITHUB_TOKEN="${HASHIBOT_TOKEN}" version="${CIRCLE_TAG}" ghr -u $CIRCLE_PROJECT_USERNAME} -r ${RELEASE_TARGET_REPONAME} -c ${CIRCLE_SHA1} -delete -replace ${version} ${gem} > .output 2>&1 slack -m "Created new GitHub release for vagrant_cloud - ${version}" - *PRIVATE_FAILURE publish: <<: *builder steps: - attach_workspace: at: . - run: | set +e mkdir -p ~/.gem echo "---\n:rubygems_api_key: ${RUBYGEMS_API_KEY}" > ~/.gem/credentials chmod 0600 ~/.gem/credentials gem=(vagrant_cloud-*.gem) gem push ${gem} slack -m "Published new version to RubyGems - ${gem}" - *PRIVATE_FAILURE workflows: version: 2 tests: jobs: - test_ruby24: <<: *PUBLIC_WORKFLOW - test_ruby25: <<: *PUBLIC_WORKFLOW - test_ruby26: <<: *PUBLIC_WORKFLOW release: jobs: - build: <<: *PRIVATE_WORKFLOW - release: <<: *PRIVATE_WORKFLOW requires: - build - publish: <<: *PRIVATE_WORKFLOW requires: - build vagrant_cloud-2.0.3/.gitignore000066400000000000000000000000451354714000500163320ustar00rootroot00000000000000/Gemfile.lock /vendor /.bundle *.gem vagrant_cloud-2.0.3/.rubocop.yml000066400000000000000000000013711354714000500166170ustar00rootroot00000000000000AllCops: Exclude: - 'Rakefile' Lint/PercentStringArray: Enabled: False Metrics/ClassLength: Enabled: False Metrics/CyclomaticComplexity: Enabled: False Metrics/LineLength: Max: 160 Metrics/ModuleLength: Enabled: false Metrics/MethodLength: Enabled: false Metrics/BlockLength: Enabled: false Metrics/ParameterLists: Enabled: False Style/ConditionalAssignment: Enabled: False Style/Documentation: Enabled: false Style/NegatedIf: Enabled: false Style/BlockDelimiters: Enabled: False Layout/MultilineBlockLayout: Enabled: False Style/WordArray: Enabled: False Style/DoubleNegation: Enabled: False Metrics/AbcSize: Enabled: False Style/InverseMethods: Enabled: False Style/IfUnlessModifier: Enabled: False vagrant_cloud-2.0.3/.runner.sh000077500000000000000000000001401354714000500162640ustar00rootroot00000000000000#!/usr/bin/env bash set -e gem build *.gemspec mkdir -p assets mv vagrant_cloud-*.gem assets/ vagrant_cloud-2.0.3/CHANGELOG.md000066400000000000000000000020441354714000500161540ustar00rootroot00000000000000# v2.0.3 (October 8, 2019) * Pass access_token and base_url into legacy ensure methods [GH-50](https://github.com/hashicorp/vagrant_cloud/pull/50) * Support passing checksum and checksum type values [GH-51](https://github.com/hashicorp/vagrant_cloud/pull/51) # v2.0.2 (January 9, 2019) * Properly raise error if CLI is invoked [GH-40](https://github.com/hashicorp/vagrant_cloud/pull/40) * Only update Box attribute if non-empty hash is given [GH-44](https://github.com/hashicorp/vagrant_cloud/pull/44) * Raise InvalidVersion error if version number for Version attribute is invalid [GH-45](https://github.com/hashicorp/vagrant_cloud/pull/45) * Fix `ensure_box` when box does not exist [GH-43](https://github.com/hashicorp/vagrant_cloud/pull/43) # v2.0.1 * Remove JSON runtime dependency [GH-39](https://github.com/hashicorp/vagrant_cloud/pull/39) # v2.0.0 * Refactor with updated APIs [GH-35](https://github.com/hashicorp/vagrant_cloud/pull/35) * Use header for authentication token [GH-33](https://github.com/hashicorp/vagrant_cloud/pull/33) # v1.1.0 vagrant_cloud-2.0.3/Gemfile000066400000000000000000000000471354714000500156370ustar00rootroot00000000000000source 'https://rubygems.org' gemspec vagrant_cloud-2.0.3/LICENSE000066400000000000000000000021231354714000500153460ustar00rootroot00000000000000The MIT License (MIT) Copyright (c) 2014 Cargo Media Copyright (c) 2017 HashiCorp 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. vagrant_cloud-2.0.3/README.md000066400000000000000000000045621354714000500156310ustar00rootroot00000000000000vagrant_cloud ============= Ruby client for the [Vagrant Cloud API](https://www.vagrantup.com/docs/vagrant-cloud/api.html). [![Build Status](https://img.shields.io/travis/hashicorp/vagrant_cloud/master.svg)](https://travis-ci.org/hashicorp/vagrant_cloud) [![Gem Version](https://img.shields.io/gem/v/vagrant_cloud.svg)](https://rubygems.org/gems/vagrant_cloud) This client allows to create, modify and delete *boxes*, *versions* and *providers*. The main entry point is an object referencing your *account*. Usage ----- Example usage: ```ruby account = VagrantCloud::Account.new('', '') box = account.ensure_box('my_box') version = box.ensure_version('0.0.1') provider = version.ensure_provider('virtualbox', 'http://example.com/foo.box') version.release puts provider.download_url ``` __NOTE:__ As of version 2.0.0, the CLI has been deprecated in favor of the `vagrant cloud` command. More information about how to use the `vagrant cloud` command can be found on the [Vagrant documentation](https://www.vagrantup.com/docs/cli/cloud.html). Example CLI usage: Create a version and provider within an existing Box, upload a file to be hosted by Vagrant Cloud, and release the version ```sh vagrant_cloud create_version --username $USERNAME --token $VAGRANT_CLOUD_TOKEN --box $BOX_NAME --version $BOX_VERSION vagrant_cloud create_provider --username $USERNAME --token $VAGRANT_CLOUD_TOKEN --box $BOX_NAME --version $BOX_VERSION vagrant_cloud upload_file --username $USERNAME --token $VAGRANT_CLOUD_TOKEN --box $BOX_NAME --version $BOX_VERSION --provider_file_path $PACKAGE_PATH vagrant_cloud release_version --username $USERNAME --token $VAGRANT_CLOUD_TOKEN --box $BOX_NAME --version $BOX_VERSION ``` If you installed vagrant_cloud with bundler, then you may have to invoke using `bundle exec vagrant_cloud` Development & Contributing -------------------------- Pull requests are very welcome! Install dependencies: ``` bundle install ``` Run the tests: ``` bundle exec rspec ``` Check the code syntax: ``` bundle exec rubocop ``` Release a new version: 1. Bump the version in `vagrant_cloud.gemspec`, merge to master. 2. Push a new tag to master. 3. Release to RubyGems with `bundle exec rake release`. History ------- This gem has been developed and maintained by [Cargo Media](https://www.cargomedia.ch) since April 2014. HashiCorp became the official maintainer in October 2017. vagrant_cloud-2.0.3/Rakefile000066400000000000000000000003711354714000500160110ustar00rootroot00000000000000$LOAD_PATH.unshift File.expand_path('lib', __dir__) require 'bundler/gem_tasks' require 'rubocop/rake_task' RuboCop::RakeTask.new Dir.glob(File.expand_path('tasks/*.rake', __dir__)).each do |task| load task end task default: [:spec, :rubocop] vagrant_cloud-2.0.3/bin/000077500000000000000000000000001354714000500151135ustar00rootroot00000000000000vagrant_cloud-2.0.3/bin/vagrant_cloud000077500000000000000000000005171354714000500176740ustar00rootroot00000000000000#!/usr/bin/env ruby raise 'As of the 2.0.0 release, the vagrant_cloud gem provides library' \ ' functionality and no longer includes a command line client. For a' \ ' command line client, use the `vagrant cloud` subcommand from Vagrant.' \ ' Vagrant can be downloaded from: https://www.vagrantup.com/downloads.html' vagrant_cloud-2.0.3/lib/000077500000000000000000000000001354714000500151115ustar00rootroot00000000000000vagrant_cloud-2.0.3/lib/vagrant_cloud.rb000066400000000000000000000004011354714000500202610ustar00rootroot00000000000000require 'json' require 'rest_client' require 'vagrant_cloud/errors' require 'vagrant_cloud/account' require 'vagrant_cloud/box' require 'vagrant_cloud/version' require 'vagrant_cloud/provider' require 'vagrant_cloud/search' require 'vagrant_cloud/client' vagrant_cloud-2.0.3/lib/vagrant_cloud/000077500000000000000000000000001354714000500177415ustar00rootroot00000000000000vagrant_cloud-2.0.3/lib/vagrant_cloud/account.rb000066400000000000000000000125541354714000500217310ustar00rootroot00000000000000module VagrantCloud class Account attr_accessor :username attr_accessor :access_token # @param [String] username # @param [String] access_token def initialize(username, access_token, custom_server = nil) @username = username @access_token = access_token @client = Client.new(access_token, custom_server) end #--------------------------- # Authentication API Helpers #--------------------------- # @param [String] password # @param [String] description # @param [String] 2FA code # @return [Hash] response body def create_token(password, description = nil, code = nil) token_data_params = { token: { description: description }, user: { login: @username, password: password }, two_factor: code }.delete_if { |_, v| v.nil? } token_response = @client.request('post', '/authenticate', token_data_params) token_response end # @param [String] token def delete_token(access_token = nil) token_response = @client.request('delete', '/authenticate', nil, access_token) token_response end # Validates a token on the account or a one-off validation token request. # Will return nil if token is valid, otherwise will return Hash of response # from Vagrant Cloud # # @param [String] access_token # @return [Hash] response body def validate_token(access_token = nil) token_response = @client.request('get', '/authenticate', nil, access_token) token_response end # @param [String] delivery_method # @param [String] password # @return [Hash] response body def request_2fa_code(delivery_method, password) twofa_code_params = { two_factor: { delivery_method: delivery_method }, user: { login: @username, password: password } } code_response = @client.request('post', '/two-factor/request-code', twofa_code_params) code_response end #--------------------------- # Organization API Helpers #--------------------------- # @param [String] - organization # @return [Hash] def read_organization(org = nil) if org name = org else name = @username end @client.request('get', "/user/#{name}") end #-------------------- # Old Box API Helpers #-------------------- # @param [String] name # @param [Hash] data # @return [Box] def get_box(name, data = nil) Box.new(self, name, data, nil, nil, @client.access_token, @client.url_base) end # @param [String] name # @param [Hash] args # @return [Box] def create_box(name, *args) params = box_params(*args) params[:name] = name data = @client.request('post', '/boxes', box: params) get_box(name, data) end # @param [String] name # @param [Hash] args # @return [Box] def ensure_box(name, *args) params = box_params(*args) # try to read the box data begin box = get_box(name) box.data rescue VagrantCloud::ClientError => err # Check if it's a 404 error. If so, then create # the missing box raise if err.error_code != 404 box = create_box(name, params) # If we've just created the box, we're done. return box end # Select elements from params that don't match what we have in the box # data. These are changed parameters and should be updated. update_params = params.select do |k, v| box.data[box.param_name(k)] != v end # Update the box with any params that had changed. box.update(update_params) unless update_params.empty? box end #-------------------- # Old Box API Helpers #-------------------- # REMOVED IN FAVOR OF CLIENT CLASS, but still exists to support any old clients # # @param [String] method # @param [String] path # @param [Hash] params # @return [Hash] def request(method, path, params = {}) headers = {} headers['Authorization'] = "Bearer #{access_token}" if access_token result = RestClient::Request.execute( method: method, url: url_base + path, payload: params, headers: headers, ssl_version: 'TLSv1' ) result = JSON.parse(result) errors = result['errors'] raise "Vagrant Cloud returned error: #{errors}" if errors result end private # @return [String] def url_base 'https://vagrantcloud.com/api/v1' end # @param [Array] args # @return [Hash] def box_params(*args) # Prepares a hash based on the *args array passed in. # Acceptable parameters are those documented by Hashicorp for the v1 API # at https://vagrantcloud.com/docs # This dance is to simulate what we could have accomplished with **args # in Ruby 2.0+ # This will silently discard any options that are not passed in as a # hash. # Find and remove the first hash we find in *args. Set params to an # empty hash if we weren't passed one. params = args.select { |v| v.is_a?(Hash) }.first if params.nil? params = {} else args.delete_if { |v| v == params } end # Default boxes to public can be overridden by providing :is_private params[:is_private] = false unless params.key?(:is_private) params end end end vagrant_cloud-2.0.3/lib/vagrant_cloud/box.rb000066400000000000000000000130411354714000500210550ustar00rootroot00000000000000module VagrantCloud class Box attr_accessor :account attr_accessor :name # @param [VagrantCloud::Account] account # @param [String] name # @param [Hash] data # @param [String] description # @param [String] short_description # @param [String] access_token def initialize(account, name = nil, data = nil, short_description = nil, description = nil, access_token = nil, custom_server = nil) @account = account @name = name @data = data @description = description @short_description = short_description @client = Client.new(access_token, custom_server) end #-------------------- # Box API Helpers #-------------------- # Read this box # @return [Hash] def data @data ||= @client.request('get', box_path) end # Update a box # # @param [Hash] args # @param [String] org - organization of the box to read # @param [String] box_name - name of the box to read # @return [Hash] @data def update(args = {}) # hash arguments kept for backwards compatibility return @data if args.empty? org = args[:organization] || account.username box_name = args[:name] || @name data = @client.request('put', box_path(org, box_name), box: args) # Update was called on *this* object, so update # objects data locally @data = data if !args[:organization] && !args[:name] data end # A generic function to read any box on Vagrant Cloud # If org and box name is not supplied, it will default to # reading the given Box object # # @param [String] org - organization of the box to read # @param [String] box_name - name of the box to read # @return [Hash] def delete(org = nil, box_name = nil) @client.request('delete', box_path(org, box_name)) end # A generic function to read any box on Vagrant Cloud # # @param [String] org - organization of the box to read # @param [String] box_name - name of the box to read # @return [Hash] def read(org = nil, box_name = nil) @client.request('get', box_path(org, box_name)) end # @param [String] short_description # @param [String] description # @param [Bool] is_private # @return [Hash] def create(short_description = nil, description = nil, org = nil, box_name = nil, is_private = false) update_data = !(org && box_name) org ||= account.username box_name ||= @name short_description ||= @short_description description ||= @description params = { name: box_name, username: org, is_private: is_private, short_description: short_description, description: description }.delete_if { |_, v| v.nil? } data = @client.request('post', '/boxes', box: params) # Create was called on *this* object, so update # objects data locally @data = data if update_data data end #-------------------- # Metadata Helpers #-------------------- # @return [String] def description data['description_markdown'].to_s end # @return [String] def description_short data['short_description'].to_s end # @return [TrueClass, FalseClass] def private !!data['private'] end # @return [Array] def versions version_list = data['versions'].map { |data| VagrantCloud::Version.new(self, data['number'], data, nil, @client.access_token, @client.url_base) } version_list.sort_by { |version| Gem::Version.new(version.number) } end #------------------------ # Old Version API Helpers #------------------------ # @param [Integer] number # @param [Hash] data # @return [Version] def get_version(number, data = nil) VagrantCloud::Version.new(self, number, data, nil, @client.access_token, @client.url_base) end # @param [String] name # @param [String] description # @return [Version] def create_version(name, description = nil) params = { version: name } params[:description] = description if description data = @client.request('post', "#{box_path}/versions", version: params) get_version(data['number'], data) end # @param [String] name # @param [String] description # @return [Version] def ensure_version(name, description = nil) version = versions.select { |v| v.version == name }.first version ||= create_version(name, description) if description && (description != version.description) version.update(description) end version end # @param [Symbol] # @return [String] def param_name(param) # This needs to return strings, otherwise it won't match the JSON that # Vagrant Cloud returns. ATTR_MAP.fetch(param, param.to_s) end private # Constructs the box path based on an account and box name. # If no params are given, it constructs a path for *this* Box object, # but if both params are given it will construct a path for a one-off request # # @param [String] - username # @param [String] - box_name # @return [String] - API path to box def box_path(username = nil, box_name = nil) if username && box_name "/box/#{username}/#{box_name}" else "/box/#{account.username}/#{name}" end end # Vagrant Cloud returns keys different from what you set for some params. # Values in this map should be strings. ATTR_MAP = { is_private: 'private', description: 'description_markdown' }.freeze end end vagrant_cloud-2.0.3/lib/vagrant_cloud/client.rb000066400000000000000000000035211354714000500215450ustar00rootroot00000000000000require 'json' module VagrantCloud class Client # Base Vagrant Cloud API URL URL_BASE = 'https://vagrantcloud.com/api/v1'.freeze attr_accessor :access_token attr_accessor :url_base # @param [String] access_token - token used to authenticate API requests # @param [String] url_base - URL used to make API requests def initialize(access_token = nil, url_base = nil) if url_base @url_base = url_base else @url_base = URL_BASE end @access_token = access_token end # @param [String] method # @param [String] path # @param [Hash] params # @param [String] token # @return [Hash] def request(method, path, params = {}, token = nil) headers = {} if token headers['Authorization'] = "Bearer #{token}" elsif @access_token headers['Authorization'] = "Bearer #{@access_token}" end headers['Accept'] = 'application/json' request_params = { method: method, url: @url_base + path, headers: headers, ssl_version: 'TLSv1' } if ['get', 'head', 'delete'].include?(method.downcase) headers[:params] = params else request_params[:payload] = params end begin result = RestClient::Request.execute(request_params) parse_json(result) rescue RestClient::ExceptionWithResponse => e raise ClientError.new(e.message, e.http_body, e.http_code) end end protected # Parse string of JSON # # @param [String] string JSON encoded string # @return [Object] # @note This is included to provide expected behavior on # Ruby 2.3. Once it has reached EOL this can be removed. def parse_json(string) JSON.parse(string) rescue JSON::ParserError raise if string != 'null' end end end vagrant_cloud-2.0.3/lib/vagrant_cloud/errors.rb000066400000000000000000000016521354714000500216060ustar00rootroot00000000000000module VagrantCloud class ClientError < StandardError attr_accessor :error_arr attr_accessor :error_code def initialize(msg, http_body, http_code) message = msg begin errors = JSON.parse(http_body) if errors.is_a?(Hash) vagrant_cloud_msg = errors['errors'] if vagrant_cloud_msg.is_a?(Array) message = msg + ' - ' + vagrant_cloud_msg.map(&:to_s).join(', ').to_s elsif !vagrant_cloud_msg.to_s.empty? message = msg + ' - ' + vagrant_cloud_msg.to_s end end rescue JSON::ParserError => err vagrant_cloud_msg = err.message end @error_arr = vagrant_cloud_msg @error_code = http_code.to_i super(message) end end class InvalidVersion < StandardError def initialize(version_number) message = 'Invalid version given: ' + version_number super(message) end end end vagrant_cloud-2.0.3/lib/vagrant_cloud/provider.rb000066400000000000000000000115501354714000500221220ustar00rootroot00000000000000module VagrantCloud class Provider attr_accessor :version attr_accessor :name # @param [Version] version # @param [String] name # @param [Hash] data # @param [String] access_token def initialize(version, name, data = nil, url = nil, username = nil, box_name = nil, access_token = nil, custom_server = nil, checksum = nil, checksum_type = nil) # rubocop:disable LineLength @version = version @name = name @data = data @username = username @box_name = box_name @url = url @checksum = checksum @checksum_type = checksum_type @client = Client.new(access_token, custom_server) end #-------------------- # Metadata Helpers #-------------------- # @return [String] def url data['original_url'].to_s end # @return [String] def download_url data['download_url'].to_s end #-------------------- # Provider API Helpers #-------------------- # @return [Hash] def data @data ||= @client.request('get', provider_path) end # Creates a provider for *this* Provider object, or if all params are given, # will make a one-off request to create a Provider and return its data # # @param [String] name # @param [String] url # @param [String] username # @param [String] box_name # @param [String] version_number def create_provider(name = nil, url = nil, username = nil, box_name = nil, version_number = nil) update_data = !(username && version_number && box_name) name ||= @name url ||= @url username ||= @username box_name ||= @box_name version_number ||= @version checksum = @checksum checksum_type = @checksum_type params = { name: name, url: url, checksum: checksum, checksum_type: checksum_type }.compact data = @client.request('post', create_provider_path(username, box_name, version_number), provider: params) @data = data if update_data data end # @param [String] url # @param [String] username # @param [String] box_name # @param [String] version_number # @param [String] provider_name def update(url = nil, username = nil, box_name = nil, version_number = nil, provider_name = nil) update_data = !(username && version_number && provider_name && box_name) provider_name ||= @name url ||= @url username ||= @username box_name ||= @box_name version_number ||= @version checksum = @checksum checksum_type = @checksum_type params = { url: url, checksum: checksum, checksum_type: checksum_type }.compact data = @client.request('put', provider_path(username, box_name, version_number, provider_name), provider: params) @data = data if update_data data end # @param [String] username # @param [String] box_name # @param [String] version_number # @param [String] provider_name def delete(username = nil, box_name = nil, version_number = nil, provider_name = nil) @client.request('delete', provider_path(username, box_name, version_number, provider_name)) end # @param [String] username # @param [String] box_name # @param [String] version_number # @param [String] provider_name # @return [String] def upload_url(username = nil, box_name = nil, version_number = nil, provider_name = nil) @client.request('get', "#{provider_path(username, box_name, version_number, provider_name)}/upload")['upload_path'] end # @param [String] username # @param [String] box_name # @param [String] version_number # @param [String] provider_name # @param [String] file_path def upload_file(file_path, username = nil, box_name = nil, version_number = nil, provider_name = nil) url = upload_url(username, box_name, version_number, provider_name) payload = File.open(file_path, 'r') RestClient::Request.execute( method: :put, url: url, payload: payload, ssl_version: 'TLSv1' ) end private # @return [Box] def box version.box end # @return [Account] def account box.account end def create_provider_path(username = nil, box_name = nil, version_number = nil) if username && box_name && version_number "/box/#{username}/#{box_name}/version/#{version_number}/providers" else "/box/#{account.username}/#{box.name}/version/#{version.number}/providers" end end def provider_path(username = nil, box_name = nil, version_number = nil, provider_name = nil) if username && box_name && version_number && name "/box/#{username}/#{box_name}/version/#{version_number}/provider/#{provider_name}" else "/box/#{account.username}/#{box.name}/version/#{version.number}/provider/#{name}" end end end end vagrant_cloud-2.0.3/lib/vagrant_cloud/search.rb000066400000000000000000000014151354714000500215340ustar00rootroot00000000000000module VagrantCloud class Search attr_accessor :account def initialize(access_token = nil, custom_server = nil) @client = Client.new(access_token, custom_server) end # Requests a search based on the given parameters # # @param [String] query # @param [String] provider # @param [String] sort # @param [String] order # @param [String] limit # @param [String] page # @return [Hash] def search(query = nil, provider = nil, sort = nil, order = nil, limit = nil, page = nil) params = { q: query, provider: provider, sort: sort, order: order, limit: limit, page: page }.delete_if { |_, v| v.nil? } @client.request('get', '/search', params) end end end vagrant_cloud-2.0.3/lib/vagrant_cloud/version.rb000066400000000000000000000133111354714000500217520ustar00rootroot00000000000000module VagrantCloud class Version attr_accessor :box attr_accessor :number # @param [Box] box # @param [String] number # @param [Hash] data # @param [String] description # @param [String] access_token def initialize(box, number, data = nil, description = nil, access_token = nil, custom_server = nil) @box = box @number = number @data = data @description = description @client = Client.new(access_token, custom_server) end #-------------------- # Metadata Helpers #-------------------- # @return [String] def version data['version'].to_s end # @return [String] def description data['description_markdown'].to_s end # @return [String] def status data['status'].to_s end # @return [Array] def providers data['providers'].map { |data| Provider.new(self, data['name'], data, nil, nil, nil, @client.access_token, @client.url_base) } end # @return [String] def to_s version end #-------------------- # Version API Helpers #-------------------- # @return [Hash] def data @data ||= @client.request('get', version_path) end # @param [String] username # @param [String] box_name # @param [String] version_number # @return [Hash] def read(username = nil, box_name = nil, version_number = nil) @client.request('get', version_path(username, box_name, version_number)) end # @param [String] username # @param [String] box_name # @param [String] version_number # @param [String] description def update(description = nil, username = nil, box_name = nil, version_number = nil) # Ensure version given is a 'proper' version begin Gem::Version.new(version_number) if version_number rescue ArgumentError raise VagrantCloud::InvalidVersion, version_number end update_data = !(username && box_name && version_number) description ||= @description version = { description: description } data = @client.request('put', version_path(username, box_name, version_number), version: version) @data = data if update_data data end # @param [String] username # @param [String] box_name # @param [String] version_number def delete(username = nil, box_name = nil, version_number = nil) @client.request('delete', version_path(username, box_name, version_number)) end # @param [String] username # @param [String] box_name # @param [String] version_number def release(username = nil, box_name = nil, version_number = nil) data = @client.request('put', "#{version_path(username, box_name, version_number)}/release") @data = data if !(username && box_name && version_number) data end # @param [String] username # @param [String] box_name # @param [String] version_number def revoke(username = nil, box_name = nil, version_number = nil) update_data = !(username && box_name && version_number) data = @client.request('put', "#{version_path(username, box_name, version_number)}/revoke") @data = data if update_data data end # @param [String] number # @param [String] description # @param [String] org # @param [String] box_name # @return [Hash] def create_version(number = nil, description = nil, org = nil, box_name = nil) update_data = !(org && box_name && description && number) number ||= @number description ||= @description # Ensure version given is a 'proper' version begin Gem::Version.new(number) if number rescue ArgumentError raise VagrantCloud::InvalidVersion, number end params = { version: number, description: description } data = @client.request('post', create_version_path(org, box_name).to_s, version: params) @data = data if update_data data end #-------------------- # Old Provider Helpers #-------------------- # @param [String] name # @param [Hash] data # @return [Provider] def get_provider(name, data = nil) Provider.new(self, name, data, nil, nil, nil, @client.access_token, @client.url_base) end # @param [String] name # @param [String] url # @return [Provider] def create_provider(name, url = nil) params = { name: name, url: url }.delete_if { |_, v| v.nil? } data = @client.request('post', "#{version_path}/providers", provider: params) get_provider(name, data) end # @param [String] name # @param [String] url # @return [Provider] def ensure_provider(name, url) provider = providers.select { |p| p.name == name }.first provider ||= create_provider(name, url) provider.update(url) if url != provider.url provider end private # @return [Account] def account box.account end # Path used to generate a new version on a box # # @param [String] - username # @param [String] - box_name # @return [String] def create_version_path(username = nil, box_name = nil) if username && box_name "/box/#{username}/#{box_name}/versions" else "/box/#{account.username}/#{box.name}/versions" end end # @param [String] - username # @param [String] - box_name # @param [String] - version_number # @return [String] def version_path(username = nil, box_name = nil, version_number = nil) if username && box_name && version_number "/box/#{username}/#{box_name}/version/#{version_number}" else "/box/#{account.username}/#{box.name}/version/#{number}" end end end end vagrant_cloud-2.0.3/spec/000077500000000000000000000000001354714000500152755ustar00rootroot00000000000000vagrant_cloud-2.0.3/spec/spec_helper.rb000066400000000000000000000002561354714000500201160ustar00rootroot00000000000000require 'webmock/rspec' RSpec.configure do |config| config.expect_with :rspec do |c| c.syntax = :expect end end WebMock.disable_net_connect!(allow_localhost: true) vagrant_cloud-2.0.3/spec/vagrant_cloud/000077500000000000000000000000001354714000500201255ustar00rootroot00000000000000vagrant_cloud-2.0.3/spec/vagrant_cloud/account_spec.rb000066400000000000000000000165541354714000500231330ustar00rootroot00000000000000require 'spec_helper' require 'vagrant_cloud' module VagrantCloud describe Account do let(:account) { Account.new('my-acc', 'my-token') } let(:client_error) { VagrantCloud::ClientError.new( client_error_message, client_error_http_body, client_error_http_code ) } let(:client_error_message) { '' } let(:client_error_http_body) { '' } let(:client_error_http_code) { 400 } describe '#initialize' do it 'stores credentials' do expect(account.username).to eq('my-acc') expect(account.access_token).to eq('my-token') end end describe '#create_token' do let(:result) { { 'description' => 'one off token', 'token' => 'qwlIE1qBVUafsg.atlasv1.FLwfJSSYkl49i4qZIu8R31GBnI9r8DrW4IQKMppkGq5rD264lRksTqaIN0zY9Bmy0zs', 'token_hash' => '7598236a879ecb42cb0f25399d6f25d1d2cfbbc6333392131bbdfba325eb352795c169daa4a61a8094d44afe817a857e0e5fc7dc72a1401eb434577337d1246c', 'created_at' => '2017-10-18T19:16:24.956Z' } } it 'creates a token' do stub_request(:post, 'https://vagrantcloud.com/api/v1/authenticate') .with(body: { 'token' => { 'description' => 'one off token' }, 'user' => { 'login' => 'my-acc', 'password' => 'password' } }) .to_return(status: 200, body: JSON.dump(result)) expect(account.create_token('password', 'one off token')).to eq(result) end end describe '#delete_token' do it 'deletes a token' do stub_request(:delete, 'https://vagrantcloud.com/api/v1/authenticate') .to_return(status: 200, body: 'null') expect(account.delete_token).to eq(nil) end end describe '#validate_token' do it 'validates a token' do stub_request(:get, 'https://vagrantcloud.com/api/v1/authenticate') .to_return(status: 200, body: 'null') expect(account.validate_token).to eq(nil) end end describe '#request_2fa_code' do end describe '#request' do it 'includes an Authorization header' do stub_request(:get, 'https://vagrantcloud.com/api/v1/foo') .with(headers: { 'Authorization' => 'Bearer my-token' }) .to_return(status: 200, body: JSON.dump(bar: 'bar')) expect(account.request(:get, '/foo')).to eq('bar' => 'bar') end it 'parses GET response' do stub_request(:get, 'https://vagrantcloud.com/api/v1/foo') .to_return(status: 200, body: JSON.dump(bar: 'bar')) expect(account.request(:get, '/foo')).to eq('bar' => 'bar') end it 'sends POST params and parses response' do stub_request(:post, 'https://vagrantcloud.com/api/v1/foo').with( body: { foo: 'foo' } ).to_return(status: 200, body: JSON.dump(bar: 'bar')) expect(account.request(:post, '/foo', foo: 'foo')).to eq('bar' => 'bar') end it 'raises on errors' do stub_request(:get, 'https://vagrantcloud.com/api/v1/foo') .to_return(status: 200, body: JSON.dump(errors: 'bar')) expect { account.request(:get, '/foo', foo: 'foo') } .to raise_error(RuntimeError, 'Vagrant Cloud returned error: bar') end end describe '.create_box' do it 'creates and returns box' do result = { 'return_foo' => 'foo' } stub_request(:post, 'https://vagrantcloud.com/api/v1/boxes').with( body: { box: { name: 'my-name', description: 'my-desc', short_description: 'my-desc', is_private: 'true' } } ).to_return(status: 200, body: JSON.dump(result)) box = account.create_box('my-name', description: 'my-desc', short_description: 'my-desc', is_private: true) expect(box).to be_a(Box) expect(box.data).to eq(result) end context 'when not passing :is_private' do it 'creates a public box' do result = { 'return_foo' => 'foo' } stub_request(:post, 'https://vagrantcloud.com/api/v1/boxes').with( body: { box: { name: 'my-name', description: 'my-desc', is_private: 'false' } } ).to_return(status: 200, body: JSON.dump(result)) box = account.create_box('my-name', description: 'my-desc') expect(box).to be_a(Box) expect(box.data).to eq(result) end end end describe '.ensure_box' do let(:client_error_http_code) { 404 } it 'creates nonexisting boxes' do box_requested = Box.new(account, 'foo') expect(box_requested).to receive(:data).and_raise(client_error) box_created = Box.new(account, 'foo', 'description_markdown' => 'desc', 'short_description' => 'desc', 'private' => true) expect(account).to receive(:get_box).with('foo').and_return(box_requested) expect(account).to receive(:create_box).with('foo', description: 'desc', short_description: 'desc', is_private: true).and_return(box_created) box = account.ensure_box('foo', description: 'desc', short_description: 'desc', is_private: true) expect(box).to eq(box_created) end it 'returns existing boxes' do box_requested = Box.new(account, 'foo', 'description_markdown' => 'desc', 'short_description' => 'desc', 'private' => true) expect(account).to receive(:get_box).with('foo').and_return(box_requested) box = account.ensure_box('foo', description: 'desc', short_description: 'desc', is_private: true) expect(box).to eq(box_requested) end it 'updates existing boxes' do box_requested = Box.new(account, 'foo', 'description_markdown' => 'desc2', 'short_description' => 'desc2', 'private' => true) expect(account).to receive(:get_box).with('foo').and_return(box_requested) expect(box_requested).to receive(:update).with(description: 'desc', short_description: 'desc') box = account.ensure_box('foo', description: 'desc', short_description: 'desc', is_private: true) expect(box).to eq(box_requested) end end describe '.get_box' do it 'returns a box with the client credentials and custom site of the account' do account = VagrantCloud::Account.new('my-acc', 'my-token', 'my-custom-site') box = account.get_box('foo') client = box.instance_variable_get(:'@client') expect(client.access_token).to eq('my-token') expect(client.url_base).to eq('my-custom-site') end end end end vagrant_cloud-2.0.3/spec/vagrant_cloud/box_spec.rb000066400000000000000000000176671354714000500222750ustar00rootroot00000000000000require 'spec_helper' require 'vagrant_cloud' module VagrantCloud describe Box do let(:token) { 'my-token' } let(:account) { Account.new('my-acc', token) } let(:client) { Account.new(token) } describe '#initialize' do it 'stores data' do data = { 'description_markdown' => 'desc-markdown', 'short_description' => 'desc-short', 'private' => false, 'versions' => [] } box = Box.new(account, 'foo', data, 'desc-short', 'desc-markdown', token) expect(box.account).to eq(account) expect(box.data).to eq(data) expect(box.name).to eq('foo') expect(box.description).to eq('desc-markdown') expect(box.description_short).to eq('desc-short') expect(box.private).to eq(false) end end describe '.versions' do it 'returns version in the right order' do box = Box.new(account, 'foo', 'versions' => [ { 'number' => '2.0' }, { 'number' => '1.0' } ]) expect(box.versions.length).to eq(2) expect(box.versions[0].number).to eq('1.0') expect(box.versions[1].number).to eq('2.0') end it 'returns versions with the client credentials of the Box' do data = { 'versions' => [{ 'number' => '1.2' }] } box = Box.new(account, 'foo', data, nil, nil, 'my-token', 'my-custom-site') versions = box.versions client = versions.first.instance_variable_get(:'@client') expect(client.access_token).to eq('my-token') expect(client.url_base).to eq('my-custom-site') end end describe '.get_version' do it 'returns a version with the client credentials of the Box' do box = Box.new(account, 'foo', nil, nil, nil, 'my-token', 'my-custom-site') version = box.get_version('1.2') client = version.instance_variable_get(:'@client') expect(client.access_token).to eq('my-token') expect(client.url_base).to eq('my-custom-site') end end describe '.update' do it 'sends a PUT request and assigns the result' do result = { 'foo' => 'foo' } stub_request(:put, 'https://vagrantcloud.com/api/v1/box/my-acc/foo').with( body: { box: { short_description: 'my-desc', description: 'my-desc', is_private: 'true' } } ).to_return(status: 200, body: JSON.dump(result)) box = Box.new(account, 'foo') box.update(description: 'my-desc', short_description: 'my-desc', is_private: true) expect(box.data).to eq(result) end it 'returns empty if no args provided' do box = Box.new(account, 'foo') expect(box.update({})).to eq(nil) end it 'sends a PUT request for a one-off update' do result = { 'foo' => 'foo' } stub_request(:put, 'https://vagrantcloud.com/api/v1/box/brian/test123').with( body: { box: { short_description: 'my-desc', description: 'my-desc', is_private: 'true', organization: 'brian', name: 'test123' } } ).to_return(status: 200, body: JSON.dump(result)) box = Box.new(account, 'foo') expect(box.update(description: 'my-desc', short_description: 'my-desc', is_private: true, organization: 'brian', name: 'test123')).to eq(result) end end describe '.delete' do it 'sends a DELETE request' do stub_request(:delete, 'https://vagrantcloud.com/api/v1/box/my-acc/foo') .to_return(status: 200, body: JSON.dump({})) box = Box.new(account, 'foo') box.delete end it 'sends a DELETE request for a one-off box' do stub_request(:delete, 'https://vagrantcloud.com/api/v1/box/my-org/my-box') .to_return(status: 200, body: JSON.dump({})) box = Box.new(account, 'foo') box.delete('my-org', 'my-box') end end describe '.read' do it 'returns information about a one-off box' do result = { 'foo' => 'foo' } stub_request(:get, 'https://vagrantcloud.com/api/v1/box/my-org/my-box') .to_return(status: 200, body: JSON.dump(result)) box = Box.new(account, 'foo') expect(box.read('my-org', 'my-box')).to eq(result) end end describe '.create' do it 'creates a one off box given params' do result = { 'foo' => 'foo' } stub_request(:post, 'https://vagrantcloud.com/api/v1/boxes').with( body: { box: { short_description: 'Short description', description: 'Description', is_private: false, username: 'my-org', name: 'my-box' } } ).to_return(status: 200, body: JSON.dump(result)) box = Box.new(account, 'foo') expect(box.create('Short description', 'Description', 'my-org', 'my-box', false)) .to eq(result) end end # Old api methods describe '.create_version' do it 'sends a POST request and returns the right instance' do result = { 'number' => '1.2', 'foo' => 'foo' } stub_request(:post, 'https://vagrantcloud.com/api/v1/box/my-acc/foo/versions').with( body: { version: { version: '1.2', description: 'my-desc' } } ).to_return(status: 200, body: JSON.dump(result)) box = Box.new(account, 'foo') version = box.create_version('1.2', 'my-desc') expect(version).to be_a(Version) expect(version.data).to eq(result) end end describe '.ensure_version' do it 'creates nonexisting versions' do box = Box.new(account, 'foo') version_created = VagrantCloud::Version.new(box, '1.2', 'description_markdown' => 'my-desc') expect(box).to receive(:versions).and_return([]) expect(box).to receive(:create_version).with('1.2', 'my-desc').and_return(version_created) version = box.ensure_version('1.2', 'my-desc') expect(version).to eq(version_created) end it 'returns existing versions' do box = Box.new(account, 'foo') version_requested = VagrantCloud::Version.new(box, '1.2', 'version' => '1.2', 'description_markdown' => 'my-desc') expect(box).to receive(:versions).and_return([version_requested]) version = box.ensure_version('1.2', 'my-desc') expect(version).to eq(version_requested) end it 'updates existing versions' do box = Box.new(account, 'foo') version_requested = VagrantCloud::Version.new(box, '1.2', 'version' => '1.2', 'description_markdown' => 'my-desc') expect(box).to receive(:versions).and_return([version_requested]) expect(version_requested).to receive(:update).with('my-desc2') version = box.ensure_version('1.2', 'my-desc2') expect(version).to eq(version_requested) end end describe '#box_path' do it 'returns a box path based on an Account object' do data = { 'description_markdown' => 'desc-markdown', 'short_description' => 'desc-short', 'private' => false, 'versions' => [] } box = Box.new(account, 'foo', data) expect(box.send(:box_path)).to eq('/box/my-acc/foo') end it 'returns a box path based on the passed in params' do box = Box.new(account, 'foo', {}) expect(box.send(:box_path, 'my-org', 'mybox')).to eq('/box/my-org/mybox') end end end end vagrant_cloud-2.0.3/spec/vagrant_cloud/client_spec.rb000066400000000000000000000033631354714000500227470ustar00rootroot00000000000000require 'spec_helper' require 'vagrant_cloud' module VagrantCloud describe Client do let(:token) { 'my-token' } let(:client) { Client.new(token) } describe '#request' do it 'includes an Authorization header' do stub_request(:get, 'https://vagrantcloud.com/api/v1/foo') .with(headers: { 'Authorization' => 'Bearer my-token' }) .to_return(status: 200, body: JSON.dump(bar: 'bar')) expect(client.request(:get, '/foo')).to eq('bar' => 'bar') end it 'parses GET response' do stub_request(:get, 'https://vagrantcloud.com/api/v1/foo') .to_return(status: 200, body: JSON.dump(bar: 'bar')) expect(client.request(:get, '/foo')).to eq('bar' => 'bar') end it 'sends POST params and parses response' do stub_request(:post, 'https://vagrantcloud.com/api/v1/foo').with( body: { foo: 'foo' } ).to_return(status: 200, body: JSON.dump(bar: 'bar')) expect(client.request(:post, '/foo', foo: 'foo')).to eq('bar' => 'bar') end it 'raises on errors' do stub_request(:get, 'https://vagrantcloud.com/api/v1/foo') .to_return(status: 500, body: JSON.dump(errors: ['bar', 'foo'])) expect { client.request(:get, '/foo', foo: 'foo') } .to raise_error(VagrantCloud::ClientError, '500 Internal Server Error - bar, foo') end it 'raises on errors with an error array' do stub_request(:get, 'https://vagrantcloud.com/api/v1/foo') .to_return(status: 500, body: JSON.dump(errors: 'bar')) expect { client.request(:get, '/foo', foo: 'foo') } .to raise_error(VagrantCloud::ClientError, '500 Internal Server Error - bar') end end end end vagrant_cloud-2.0.3/spec/vagrant_cloud/errors_spec.rb000066400000000000000000000064601354714000500230060ustar00rootroot00000000000000require 'spec_helper' require 'vagrant_cloud' module VagrantCloud describe ClientError do let(:subject) { described_class.new(message, body, code) } let(:message) { 'default error' } let(:body) { '' } let(:code) { 0 } describe '#initialize' do it 'is a StandardError' do expect(subject).to be_a_kind_of(StandardError) end context 'with message' do let(:message) { 'custom message' } it 'should set the message' do expect(subject.message).to eq(message) end it 'should output custom message with #to_s' do expect(subject.to_s).to eq(message) end end context 'with http body' do context 'with invalid JSON' do let(:body) { '{"errors:["invalid"]}' } it 'should not generate a parse error' do expect { subject }.not_to raise_error end it 'should set parse error within #error_arr' do expect(subject.error_arr.downcase).to include('unexpected token') end end context 'with valid JSON array' do let(:body) { '[]' } it 'should not generate an error' do expect { subject }.not_to raise_error end end context 'with valid JSON hash' do let(:body) { '{}' } it 'should not generate an error' do expect { subject }.not_to raise_error end end context 'with array of errors in JSON hash' do let(:body) { '{"errors":["error1", "error2"]}' } it 'should append errors to exception message' do expect(subject.message).to include('error1, error2') end it 'should return error with #error_arr' do expect(subject.error_arr).to eq(['error1', 'error2']) end end context 'with string errors in JSON hash' do let(:body) { '{"errors":"error1"}' } it 'should append error to exception message' do expect(subject.message).to include('error1') expect(subject.message).not_to include(',') end it 'should return error with #error_arr' do expect(subject.error_arr).to eq('error1') end end context 'with empty errors in JSON hash' do let(:body) { '{"errors":""}' } it 'should not modify the exception message' do expect(subject.message).to eq(message) end end context 'with null errors in JSON hash' do let(:body) { '{"errors":null}' } it 'should not modify the exception message' do expect(subject.message).to eq(message) end end end context 'with http code' do let(:code) { 404 } it 'should return the code value' do expect(subject.error_code).to eq(code) end it 'should be an integer' do expect(subject.error_code).to be_a(Integer) end context 'with string type code' do let(:code) { '404' } it 'should return the integer value' do expect(subject.error_code).to eq(404) end it 'should be an integer' do expect(subject.error_code).to be_a(Integer) end end end end end end vagrant_cloud-2.0.3/spec/vagrant_cloud/provider_spec.rb000066400000000000000000000137301354714000500233220ustar00rootroot00000000000000require 'spec_helper' require 'vagrant_cloud' module VagrantCloud describe Provider do let(:token) { 'my-token' } let(:account) { Account.new('my-acc', token) } let(:box) { Box.new(account, 'my-box') } let(:version) { VagrantCloud::Version.new(box, '1.2') } describe '#initialize' do it 'stores data' do data = { 'original_url' => 'http://example.com/foo', 'download_url' => 'http://vagrant.com/foo' } provider = Provider.new(version, 'my-prov', data) expect(provider.version).to eq(version) expect(provider.data).to eq(data) expect(provider.url).to eq('http://example.com/foo') expect(provider.download_url).to eq('http://vagrant.com/foo') end end describe '.update' do it 'sends a PUT request and assigns the result' do result = { 'foo' => 'foo' } stub_request(:put, 'https://vagrantcloud.com/api/v1/box/my-acc/my-box/version/1.2/provider/my-prov').with( body: { provider: { url: 'http://example.com' } } ).to_return(status: 200, body: JSON.dump(result)) provider = Provider.new(version, 'my-prov') provider.update('http://example.com') expect(provider.data).to eq(result) end it 'sends checksum information when provided' do result = { 'foo' => 'foo' } stub_request(:put, 'https://vagrantcloud.com/api/v1/box/my-acc/my-box/version/1.2/provider/my-prov').with( body: { provider: { checksum: 'CHECKSUM', checksum_type: 'CHECKSUM_TYPE', url: 'http://example.com' } } ).to_return(status: 200, body: JSON.dump(result)) provider = Provider.new(version, 'my-prov', *[nil] * 6, 'CHECKSUM', 'CHECKSUM_TYPE') provider.update('http://example.com') expect(provider.data).to eq(result) end it 'sends a PUT request for one-off providers' do result = { 'foo' => 'foo' } stub_request(:put, 'https://vagrantcloud.com/api/v1/box/hashicorp/precise64/version/2.0.0/provider/virtualbox').with( body: { provider: { url: 'http://example.com' } } ).to_return(status: 200, body: JSON.dump(result)) provider = Provider.new(version, 'my-prov', nil, token) expect(provider.update('http://example.com', 'hashicorp', 'precise64', '2.0.0', 'virtualbox')).to eq(result) end end describe '.delete' do it 'sends a DELETE request' do stub_request(:delete, 'https://vagrantcloud.com/api/v1/box/my-acc/my-box/version/1.2/provider/my-prov') .to_return(status: 200, body: JSON.dump({})) provider = Provider.new(version, 'my-prov') provider.delete end it 'sends a DELETE request for a one off request' do stub_request(:delete, 'https://vagrantcloud.com/api/v1/box/hashicorp/precise64/version/2.0.0/provider/virtualbox') .to_return(status: 200, body: JSON.dump({})) provider = Provider.new(version, 'anything') provider.delete('hashicorp', 'precise64', '2.0.0', 'virtualbox') end end describe '.upload_url' do it 'sends a POST request' do stub_request(:get, 'https://vagrantcloud.com/api/v1/box/my-acc/my-box/version/1.2/provider/my-prov/upload') .to_return(status: 200, body: JSON.dump({})) provider = Provider.new(version, 'my-prov') provider.upload_url end it 'sends a POST request for one-off requests' do stub_request(:get, 'https://vagrantcloud.com/api/v1/box/hashicorp/precise64/version/2.0.0/provider/virtualbox/upload') .to_return(status: 200, body: JSON.dump({})) provider = Provider.new(version, 'my-prov') provider.upload_url('hashicorp', 'precise64', '2.0.0', 'virtualbox') end end describe '.upload_file' do let(:provider) { Provider.new(version, 'my-prov') } let(:file_path) { './example.box' } let(:response) do { 'upload_path' => 'http://example.org/upload_url' } end before(:each) do File.open(file_path, 'w') do |f| f.write 'temp-file' f.flush end end it 'sends a PUT request to upload a file' do stub_request(:get, 'https://vagrantcloud.com/api/v1/box/my-acc/my-box/version/1.2/provider/my-prov/upload') .to_return(status: 200, body: JSON.dump(response)) stub_request(:put, response['upload_path']).with(body: File.read(file_path)).to_return(status: 200, body: '') results = provider.upload_file(file_path) expect(results).to eq('') end it 'sends a PUT request to upload a file for a one-off request' do stub_request(:get, 'https://vagrantcloud.com/api/v1/box/hashicorp/precise64/version/2.0/provider/virtualbox/upload') .to_return(status: 200, body: JSON.dump(response)) stub_request(:put, response['upload_path']).with(body: File.read(file_path)).to_return(status: 200, body: '') results = provider.upload_file(file_path, 'hashicorp', 'precise64', '2.0', 'virtualbox') expect(results).to eq('') end after(:each) do File.delete(file_path) end end describe '.provider_path' do it 'returns a path to create a version with the given objects attributes' do provider = VagrantCloud::Provider.new(version, 'virtualbox', nil, token) expect(provider.send(:provider_path)).to eq('/box/my-acc/my-box/version/1.2/provider/virtualbox') end it 'returns a path to create a version for a one off version' do provider = VagrantCloud::Provider.new(version, 'virtualbox', nil, token) expect(provider.send(:provider_path, 'hashicorp', 'precise64', '2.2', 'virtualbox')) .to eq('/box/hashicorp/precise64/version/2.2/provider/virtualbox') end end end end vagrant_cloud-2.0.3/spec/vagrant_cloud/search_spec.rb000066400000000000000000000012261354714000500227320ustar00rootroot00000000000000require 'spec_helper' require 'vagrant_cloud' module VagrantCloud describe Search do let(:token) { 'my-token' } let(:account) { Account.new('my-acc', token) } let(:client) { Account.new(token) } describe '.search' do it 'sends a GET request' do result = { 'foo' => 'foo' } stub_request(:get, 'https://vagrantcloud.com/api/v1/search?limit=10&order=desc&page=1&provider=virtualbox&q=ubuntu&sort=downloads') .to_return(status: 200, body: JSON.dump(result)) search = Search.new(token) search.search('ubuntu', 'virtualbox', 'downloads', 'desc', 10, 1) end end end end vagrant_cloud-2.0.3/spec/vagrant_cloud/version_spec.rb000066400000000000000000000216551354714000500231620ustar00rootroot00000000000000require 'spec_helper' require 'vagrant_cloud' module VagrantCloud describe Box do let(:account) { Account.new('my-acc', 'my-token') } let(:box) { Box.new(account, 'my-box') } describe '#initialize' do it 'stores data' do data = { 'version' => '1.2', 'description_markdown' => 'desc-markdown', 'status' => 'unreleased' } version = VagrantCloud::Version.new(box, '1.2', data) expect(version.box).to eq(box) expect(version.data).to eq(data) expect(version.version).to eq('1.2') expect(version.description).to eq('desc-markdown') expect(version.status).to eq('unreleased') end end describe '.update' do it 'sends a PUT request and assigns the result' do result = { 'foo' => 'foo' } stub_request(:put, 'https://vagrantcloud.com/api/v1/box/my-acc/my-box/version/1.2').with( body: { version: { description: 'my-desc' } } ).to_return(status: 200, body: JSON.dump(result)) version = VagrantCloud::Version.new(box, '1.2') version.update('my-desc') expect(version.data).to eq(result) end it 'sents a PUT request and assigns the result for a one off version' do result = { 'foo' => 'foo' } stub_request(:put, 'https://vagrantcloud.com/api/v1/box/hashicorp/precise64/version/1.2.3').with( body: { version: { description: 'my-desc' } } ).to_return(status: 200, body: JSON.dump(result)) version = VagrantCloud::Version.new(box, '1.2') expect(version.update('my-desc', 'hashicorp', 'precise64', '1.2.3')) .to eq(result) end it 'raises an exception if the version number is invalid' do version = VagrantCloud::Version.new(box, '1.2.3') expect { version.update('my-desc', 'hashicorp', 'precise64', 'v1.2.4') } .to raise_error(VagrantCloud::InvalidVersion, 'Invalid version given: v1.2.4') end end describe '.delete' do it 'sends a DELETE request' do stub_request(:delete, 'https://vagrantcloud.com/api/v1/box/my-acc/my-box/version/1.2') .to_return(status: 200, body: JSON.dump({})) version = VagrantCloud::Version.new(box, '1.2') version.delete end it 'sends a DELETE request for one-off versions' do stub_request(:delete, 'https://vagrantcloud.com/api/v1/box/hashicorp/precise64/version/1.2.3') .to_return(status: 200, body: JSON.dump({})) version = VagrantCloud::Version.new(box, '1.2') version.delete('hashicorp', 'precise64', '1.2.3') end end describe '.release' do it 'sends a PUT request' do stub_request(:put, 'https://vagrantcloud.com/api/v1/box/my-acc/my-box/version/1.2/release') .to_return(status: 200, body: JSON.dump({})) version = VagrantCloud::Version.new(box, '1.2') version.release end it 'sends a PUT request for one off versions' do stub_request(:put, 'https://vagrantcloud.com/api/v1/box/hashicorp/precise64/version/1.2.3/release') .to_return(status: 200, body: JSON.dump({})) version = VagrantCloud::Version.new(box, '1.2') version.release('hashicorp', 'precise64', '1.2.3') end end describe '.revoke' do it 'sends a PUT request' do stub_request(:put, 'https://vagrantcloud.com/api/v1/box/my-acc/my-box/version/1.2/revoke') .to_return(status: 200, body: JSON.dump({})) version = VagrantCloud::Version.new(box, '1.2') version.revoke end it 'sends a PUT request for one-off versions' do stub_request(:put, 'https://vagrantcloud.com/api/v1/box/hashicorp/precise64/version/1.2.3/revoke') .to_return(status: 200, body: JSON.dump({})) version = VagrantCloud::Version.new(box, '1.2') version.revoke('hashicorp', 'precise64', '1.2.3') end end describe '.providers' do it 'returns providers with the client credentials of the Version' do data = { 'providers' => [{ 'name' => 'my-prov' }] } version = Version.new(box, '1.2', data, nil, 'my-token', 'my-custom-site') providers = version.providers client = providers.first.instance_variable_get(:'@client') expect(client.access_token).to eq('my-token') expect(client.url_base).to eq('my-custom-site') end end describe '.get_provider' do it 'returns a provider with the client credentials of the Version' do version = Version.new(box, '1.2', nil, nil, 'my-token', 'my-custom-site') provider = version.get_provider('my-prov') client = provider.instance_variable_get(:'@client') expect(client.access_token).to eq('my-token') expect(client.url_base).to eq('my-custom-site') end end describe '.create_provider' do it 'sends a POST request and returns the right instance' do result = { 'foo' => 'foo' } stub_request(:post, 'https://vagrantcloud.com/api/v1/box/my-acc/my-box/version/1.2/providers').with( body: { provider: { name: 'my-prov', url: 'http://example.com' } } ).to_return(status: 200, body: JSON.dump(result)) version = VagrantCloud::Version.new(box, '1.2') provider = version.create_provider('my-prov', 'http://example.com') expect(provider).to be_a(Provider) expect(provider.data).to eq(result) end it 'sends a POST request without a provider_url and creates an instance' do result = { 'foo' => 'foo' } stub_request(:post, 'https://vagrantcloud.com/api/v1/box/my-acc/my-box/version/1.2/providers').with( body: { provider: { name: 'my-prov' } } ).to_return(status: 200, body: JSON.dump(result)) provider = VagrantCloud::Version.new(box, '1.2').create_provider('my-prov') expect(provider).to be_a(Provider) expect(provider.data).to eq(result) end end describe '.ensure_provider' do it 'creates nonexisting providers' do version = VagrantCloud::Version.new(box, '1.2') provider_created = Provider.new(version, 'my-prov', 'original_url' => 'http://example.com') expect(version).to receive(:providers).and_return([]) expect(version).to receive(:create_provider).with('my-prov', 'http://example.com').and_return(provider_created) provider = version.ensure_provider('my-prov', 'http://example.com') expect(provider).to eq(provider_created) end it 'returns existing providers' do version = VagrantCloud::Version.new(box, '1.2') provider_requested = Provider.new(version, 'my-prov', 'original_url' => 'http://example.com') expect(version).to receive(:providers).and_return([provider_requested]) provider = version.ensure_provider('my-prov', 'http://example.com') expect(provider).to eq(provider_requested) end it 'updates existing providers' do version = VagrantCloud::Version.new(box, '1.2') provider_requested = Provider.new(version, 'my-prov', 'original_url' => 'http://example.com') expect(version).to receive(:providers).and_return([provider_requested]) expect(provider_requested).to receive(:update).with('http://example2.com') provider = version.ensure_provider('my-prov', 'http://example2.com') expect(provider).to eq(provider_requested) end end describe '.create_version_path' do it 'returns a path to create a version with the given objects attributes' do data = { 'version' => '1.2', 'description_markdown' => 'desc-markdown', 'status' => 'unreleased' } version = VagrantCloud::Version.new(box, '1.2', data) expect(version.send(:create_version_path)).to eq('/box/my-acc/my-box/versions') end it 'returns a path to create a version for a one off version' do data = { 'version' => '1.2', 'description_markdown' => 'desc-markdown', 'status' => 'unreleased' } version = VagrantCloud::Version.new(box, '1.2', data) expect(version.send(:create_version_path, 'hashicorp', 'precise64')) .to eq('/box/hashicorp/precise64/versions') end end describe '.version_path' do it 'returns a path to create a version with the given objects attributes' do data = { 'version' => '1.2', 'description_markdown' => 'desc-markdown', 'status' => 'unreleased' } version = VagrantCloud::Version.new(box, '1.2', data) expect(version.send(:version_path)).to eq('/box/my-acc/my-box/version/1.2') end it 'returns a path to create a version for a one off version' do data = { 'version' => '1.2', 'description_markdown' => 'desc-markdown', 'status' => 'unreleased' } version = VagrantCloud::Version.new(box, '1.2', data) expect(version.send(:version_path, 'hashicorp', 'precise64', '2.2')) .to eq('/box/hashicorp/precise64/version/2.2') end end end end vagrant_cloud-2.0.3/tasks/000077500000000000000000000000001354714000500154705ustar00rootroot00000000000000vagrant_cloud-2.0.3/tasks/rspec.rake000066400000000000000000000002031354714000500174430ustar00rootroot00000000000000require 'rspec/core/rake_task' desc 'Run all specs' RSpec::Core::RakeTask.new(:spec) do |t| t.pattern = 'spec/**/*_spec.rb' end vagrant_cloud-2.0.3/vagrant_cloud.gemspec000066400000000000000000000020671354714000500205450ustar00rootroot00000000000000Gem::Specification.new do |s| s.name = 'vagrant_cloud' s.version = '2.0.3' s.summary = 'Vagrant Cloud API Library' s.description = 'Ruby library for the HashiCorp Vagrant Cloud API' s.authors = ['HashiCorp', 'Cargo Media'] s.email = 'vagrant@hashicorp.com' s.files = Dir['LICENSE*', 'README*', '{bin,lib}/**/*'].reject { |f| f.end_with?('~') } s.homepage = 'https://github.com/hashicorp/vagrant_cloud' s.license = 'MIT' s.add_runtime_dependency 'rest-client', '~> 2.0.2' s.add_development_dependency 'rake', '~> 10.4' s.add_development_dependency 'rspec', '~> 3.0' s.add_development_dependency 'rubocop', '~> 0.59.1' s.add_development_dependency 'webmock', '~> 3.0' s.post_install_message = "NOTICE: As of the 2.0.0 release, the vagrant_cloud gem provides library functionality and no longer includes a command line client. For a command line client, use the `vagrant cloud` subcommand from Vagrant. Vagrant can be downloaded from: https://www.vagrantup.com/downloads.html" end