vagrant_cloud 1.1.0 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: d6540c7adaf6171dba9ebfc84c6e7318668bf162
4
- data.tar.gz: 0d1670e8ab10effb005977fbad33a093098bf56d
2
+ SHA256:
3
+ metadata.gz: 360b98c309f3b2804dce161d08972266978ac3059dbc5516bd12b52e5c1fff98
4
+ data.tar.gz: d258cb4d89be2bc698e4f087e8a504e2ba9a4e085ff9ab5e48c24c262926784f
5
5
  SHA512:
6
- metadata.gz: fdac04b8abf7afda5bd6346aff9d1501adc381fb7e2b92b068e8c8c5fb5b2f4ca6bec3e601ace3f6fd1d7f44852d1f16e51866a0124881eebf40a4a48228d032
7
- data.tar.gz: 586674a4c7a71c102d2a71e9ea2b13f205e65bac47cc95096d0defc891ca18a43001eacd09ebfc168e5ab66894e5db76d14859b66024d533af394d7e692f47ea
6
+ metadata.gz: 4dadf15e12aa55529ff8023f73c19a59f4882496003246cca6ee5e2b798f86004beb343b68c97dcda465205a227312ba49023ba91b83429ac24da8cb919c8372
7
+ data.tar.gz: b46249ed808cf36ffe8e65f0e234ef7fb291e9648e8cc1d8e044c1fe0ac7b1da2814eda39a14b048728bd5376b7a14a24a31d2ab68ab56f832e4ea0c2ebafb4b
data/LICENSE CHANGED
@@ -1,6 +1,7 @@
1
1
  The MIT License (MIT)
2
2
 
3
3
  Copyright (c) 2014 Cargo Media
4
+ Copyright (c) 2017 HashiCorp
4
5
 
5
6
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
7
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -1,39 +1,149 @@
1
- vagrant_cloud
2
- =============
3
- Minimalistic ruby client for the [HashiCorp Atlas API](https://vagrantcloud.com/docs) (previously *Vagrant Cloud API*).
1
+ # vagrant_cloud
2
+
3
+ Ruby client for the [Vagrant Cloud API](https://www.vagrantup.com/docs/vagrant-cloud/api.html).
4
4
 
5
- [![Build Status](https://img.shields.io/travis/cargomedia/vagrant_cloud/master.svg)](https://travis-ci.org/cargomedia/vagrant_cloud)
6
5
  [![Gem Version](https://img.shields.io/gem/v/vagrant_cloud.svg)](https://rubygems.org/gems/vagrant_cloud)
7
6
 
7
+ This library provides the functionality to create, modify, and delete boxes, versions,
8
+ and providers on Vagrant Cloud.
9
+
10
+ ## Usage
11
+
12
+ The Vagrant Cloud library provides two methods for interacting with the Vagrant Cloud API. The
13
+ first is direct interaction using a `VagrantCloud::Client` instance. The second is a basic
14
+ model based approach using a `VagrantCloud::Account` instance.
8
15
 
9
- This client allows to create, modify and delete *boxes*, *versions* and *providers*.
10
- The main entry point is an object referencing your *account*.
16
+ ### Direct Client
17
+
18
+ The `VagrantCloud::Client` class contains all the underlying functionality which with
19
+ `vagrant_cloud` library uses for communicating with Vagrant Cloud. It can be used directly
20
+ for quickly and easily sending requests to Vagrant Cloud. The `VagrantCloud::Client`
21
+ class will automatically handle any configured authentication, request parameter
22
+ structuring, and response validation. All API related methods in the `VagrantCloud::Client`
23
+ class will return `Hash` results.
24
+
25
+ Example usage (display box details):
11
26
 
12
- Usage
13
- -----
14
- Example usage:
15
27
  ```ruby
16
- account = VagrantCloud::Account.new('<username>', '<access_token>')
17
- box = account.ensure_box('my_box')
18
- version = box.ensure_version('0.0.1')
19
- provider = version.ensure_provider('virtualbox', 'http://example.com/foo.box')
28
+ require "vagrant_cloud"
20
29
 
21
- version.release
22
- puts provider.download_url
30
+ client = VagrantCloud::Client.new(access_token: "MY_TOKEN")
31
+ box = client.box_get(username: "hashicorp", name: "bionic64")
32
+
33
+ puts "Box: #{box[:tag]} Description: #{box[:description]}"
23
34
  ```
24
35
 
25
- Example CLI usage:
26
- Create a version and provider within an existing Box, upload a file to be hosted by Vagrant/Atlas, and release the version
27
- ```sh
28
- vagrant_cloud create_version --username $USERNAME --token $VAGRANT_CLOUD_TOKEN --box $BOX_NAME --version $BOX_VERSION
29
- vagrant_cloud create_provider --username $USERNAME --token $VAGRANT_CLOUD_TOKEN --box $BOX_NAME --version $BOX_VERSION
30
- vagrant_cloud upload_file --username $USERNAME --token $VAGRANT_CLOUD_TOKEN --box $BOX_NAME --version $BOX_VERSION --provider_file_path $PACKAGE_PATH
31
- vagrant_cloud release_version --username $USERNAME --token $VAGRANT_CLOUD_TOKEN --box $BOX_NAME --version $BOX_VERSION
36
+ Example usage (creating box and releasing a new version):
37
+
38
+ ```ruby
39
+ require "vagrant_cloud"
40
+ require "net/http"
41
+
42
+ # Create a new client
43
+ client = VagrantCloud::Client.new(access_token: "MY_TOKEN")
44
+
45
+ # Create a new box
46
+ client.box_create(
47
+ username: "hashicorp",
48
+ name: "test-bionic64",
49
+ short_description: "Test Box",
50
+ long_description: "Testing box for an example",
51
+ is_private: false
52
+ )
53
+
54
+ # Create a new version
55
+ client.box_version_create(
56
+ username: "hashicorp",
57
+ name: "test-bionic64",
58
+ version: "1.0.0",
59
+ description: "Version 1.0.0 release"
60
+ )
61
+
62
+ # Create a new provider
63
+ client.box_version_provider_create(
64
+ username: "hashicorp",
65
+ name: "test-bionic64",
66
+ version: "1.0.0",
67
+ provider: "virtualbox"
68
+ )
69
+
70
+ # Request box upload URL
71
+ upload_url = client.box_version_provider_upload(
72
+ username: "hashicorp",
73
+ name: "test-bionic64",
74
+ version: "1.0.0",
75
+ provider: "virtualbox"
76
+ )
77
+
78
+ # Upload box asset
79
+ uri = URI.parse(upload_url[:upload_path])
80
+ request = Net::HTTP::Post.new(uri)
81
+ box = File.open(BOX_PATH, "rb")
82
+ request.set_form([["file", box]], "multipart/form-data")
83
+ response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme.eql?("https")) do |http|
84
+ http.request(request)
85
+ end
86
+
87
+ # Release the version
88
+ client.box_version_release(
89
+ username: "hashicorp",
90
+ name: "test-bionic64",
91
+ version: "1.0.0"
92
+ )
32
93
  ```
33
- If you installed vagrant_cloud with bundler, then you may have to invoke using `bundle exec vagrant_cloud`
34
94
 
35
- Development & Contributing
36
- --------------------------
95
+ ### Simple Models
96
+
97
+ The `VagrantCloud::Account` class is the entry point for using simple models to
98
+ interact with Vagrant Cloud.
99
+
100
+ Example usage (display box details):
101
+
102
+ ```ruby
103
+ require "vagrant_cloud"
104
+
105
+ account = VagrantCloud::Account.new(access_token: "MY_TOKEN")
106
+ org = account.organization(name: "hashicorp")
107
+ box = org.boxes.select { |b| b.name == "bionic64" }
108
+
109
+ puts "Box: #{box[:tag]} Description: #{box[:description]}"
110
+ ```
111
+
112
+ Example usage (creating box and releasing a new version):
113
+
114
+ ```ruby
115
+ require "vagrant_cloud"
116
+
117
+ # Load our account
118
+ account = VagrantCloud::Account.new(access_token: "MY_TOKEN")
119
+
120
+ # Load organization
121
+ org = account.organization(name: "hashicorp")
122
+
123
+ # Create a new box
124
+ box = org.add_box("test-bionic64")
125
+ box.description = "Testing box for an example"
126
+ box.short_description = "Test Box"
127
+
128
+ # Create a new version
129
+ version = box.add_version("1.0.0")
130
+ version.description = "Version 1.0.0 release"
131
+
132
+ # Create a new provider
133
+ provider = version.add_provider("virtualbox")
134
+
135
+ # Save the box, version, and provider
136
+ box.save
137
+
138
+ # Upload box asset
139
+ provider.upload(path: BOX_PATH)
140
+
141
+ # Release the version
142
+ version.release
143
+ ```
144
+
145
+ ## Development & Contributing
146
+
37
147
  Pull requests are very welcome!
38
148
 
39
149
  Install dependencies:
@@ -46,13 +156,18 @@ Run the tests:
46
156
  bundle exec rspec
47
157
  ```
48
158
 
49
- Check the code syntax:
50
- ```
51
- bundle exec rubocop
52
- ```
159
+ ## Releasing
53
160
 
54
161
  Release a new version:
55
162
 
56
- 1. Bump the version in `vagrant_cloud.gemspec`, merge to master.
57
- 2. Push a new tag to master.
58
- 3. Release to RubyGems with `bundle exec rake release`.
163
+ 1. Update the version in the `version.txt` file
164
+ 1. Commit the change to master
165
+ 1. Create a new version tag in git: `git tag vX.X.X`
166
+ 1. Push the new tag and master to GitHub `git push origin master --tags`
167
+
168
+ The new release will be automatically built and published.
169
+
170
+ ## History
171
+
172
+ - This gem was developed and maintained by [Cargo Media](https://www.cargomedia.ch) from April 2014 until October 2017.
173
+ - The `vagrant_cloud` CLI tool included in this RubyGem has been deprecated and removed. See `vagrant cloud` for a replacement.
@@ -1,10 +1,21 @@
1
- module VagrantCloud
2
- require 'json'
3
- require 'rest_client'
1
+ require "excon"
2
+ require "log4r"
3
+ require "json"
4
+ require "securerandom"
5
+ require "set"
6
+ require 'singleton'
7
+ require "thread"
4
8
 
5
- require 'vagrant_cloud/account'
6
- require 'vagrant_cloud/box'
7
- require 'vagrant_cloud/version'
8
- require 'vagrant_cloud/provider'
9
- require 'vagrant_cloud/cli'
9
+ module VagrantCloud
10
+ autoload :Account, "vagrant_cloud/account"
11
+ autoload :Box, "vagrant_cloud/box"
12
+ autoload :Client, "vagrant_cloud/client"
13
+ autoload :Data, "vagrant_cloud/data"
14
+ autoload :Error, "vagrant_cloud/error"
15
+ autoload :Instrumentor, "vagrant_cloud/instrumentor"
16
+ autoload :Logger, "vagrant_cloud/logger"
17
+ autoload :Organization, "vagrant_cloud/organization"
18
+ autoload :Response, "vagrant_cloud/response"
19
+ autoload :Search, "vagrant_cloud/search"
20
+ autoload :VERSION, "vagrant_cloud/version"
10
21
  end
@@ -1,109 +1,112 @@
1
1
  module VagrantCloud
2
+ # VagrantCloud account
2
3
  class Account
3
- attr_accessor :username
4
- attr_accessor :access_token
5
-
6
- # @param [String] username
7
- # @param [String] access_token
8
- def initialize(username, access_token)
9
- @username = username
10
- @access_token = access_token
4
+ # @return [Client]
5
+ attr_reader :client
6
+ # @return [String] username of this account
7
+ attr_reader :username
8
+ # @return [Instrumentor::Collection] Instrumentor in use
9
+ attr_reader :instrumentor
10
+
11
+ # Create a new Account instance
12
+ #
13
+ # @param [String] access_token Authentication token
14
+ # @param [Client] client Client to use for account
15
+ # @param [String] custom_server Custom server URL for client
16
+ # @param [Integer] retry_count Number of retries on idempotent requests
17
+ # @param [Integer] retry_interval Number of seconds to wait between requests
18
+ # @param [Instrumentor::Core] instrumentor Instrumentor to use
19
+ # @return [Account]
20
+ def initialize(access_token: nil, client: nil, custom_server: nil, retry_count: nil, retry_interval: nil, instrumentor: nil)
21
+ raise ArgumentError, "Account accepts `access_token` or `client` but not both" if
22
+ client && access_token
23
+ raise TypeError, "Expected `#{Client.name}` but received `#{client.class.name}`" if
24
+ client && !client.is_a?(Client)
25
+
26
+ if client
27
+ @client = client
28
+ else
29
+ @client = Client.new(
30
+ access_token: access_token,
31
+ url_base: custom_server,
32
+ retry_count: retry_count,
33
+ retry_interval: retry_interval,
34
+ instrumentor: instrumentor
35
+ )
36
+ end
37
+ setup!
11
38
  end
12
39
 
13
- # @param [String] name
14
- # @param [Hash]
15
- # @return [Box]
16
- def get_box(name, data = nil)
17
- Box.new(self, name, data)
40
+ # @return [Search]
41
+ def searcher
42
+ Search.new(account: self)
18
43
  end
19
44
 
20
- # @param [String] name
21
- # @param [Hash] args
22
- # @return [Box]
23
- def create_box(name, *args)
24
- params = box_params(*args)
25
- params[:name] = name
26
-
27
- data = request('post', '/boxes', box: params)
28
- get_box(name, data)
45
+ #---------------------------
46
+ # Authentication API Helpers
47
+ #---------------------------
48
+
49
+ # Create a new access token
50
+ # @param [String] password Remote password
51
+ # @param [String] description Description of token
52
+ # @param [String] code 2FA code
53
+ # @return [Response::CreateToken]
54
+ def create_token(password:, description: Data::Nil, code: Data::Nil)
55
+ r = client.authentication_token_create(username: username,
56
+ password: password, description: description, code: code)
57
+
58
+ Response::CreateToken.new(
59
+ token: r[:token],
60
+ token_hash: r[:token_hash],
61
+ created_at: r[:created_at],
62
+ description: r[:description]
63
+ )
29
64
  end
30
65
 
31
- # @param [String] name
32
- # @param [Hash] args
33
- # @return [Box]
34
- def ensure_box(name, *args)
35
- params = box_params(*args)
36
-
37
- begin
38
- box = get_box(name)
39
- box.data
40
- rescue RestClient::ResourceNotFound => e
41
- box = create_box(name, params)
42
- # If we've just created the box, we're done.
43
- return box
44
- end
45
-
46
- # Select elements from params that don't match what we have in the box
47
- # data. These are changed parameters and should be updated.
48
- update_params = params.select do |k, v|
49
- box.data[box.param_name(k)] != v
50
- end
51
-
52
- # Update the box with any params that had changed.
53
- box.update(update_params) unless update_params.empty?
54
-
55
- box
66
+ # Delete the current token
67
+ #
68
+ # @return [self]
69
+ def delete_token
70
+ client.authentication_token_delete
71
+ self
56
72
  end
57
73
 
58
- # @param [String] method
59
- # @param [String] path
60
- # @param [Hash] params
61
- # @return [Hash]
62
- def request(method, path, params = {})
63
- params[:access_token] = access_token
64
- result = RestClient::Request.execute(
65
- method: method,
66
- url: url_base + path,
67
- payload: params,
68
- ssl_version: 'TLSv1'
69
- )
70
- result = JSON.parse(result)
71
- errors = result['errors']
72
- raise "Vagrant Cloud returned error: #{errors}" if errors
73
- result
74
+ # Validate the current token
75
+ #
76
+ # @return [self]
77
+ def validate_token
78
+ client.request(path: "authenticate")
79
+ self
74
80
  end
75
81
 
76
- private
82
+ # Request a 2FA code is sent
83
+ #
84
+ # @param [String] delivery_method Delivery method of 2FA
85
+ # @param [String] password Account password
86
+ # @return [Response]
87
+ def request_2fa_code(delivery_method:, password:)
88
+ r = client.authentication_request_2fa_code(username: username,
89
+ password: password, delivery_method: delivery_method)
90
+ Response::Request2FA.new(destination: r.dig(:two_factor, :obfuscated_destination))
91
+ end
77
92
 
78
- # @return [String]
79
- def url_base
80
- 'https://vagrantcloud.com/api/v1'
93
+ # Fetch the requested organization
94
+ #
95
+ # @param [String] name Organization name
96
+ # @return [Organization]
97
+ def organization(name: nil)
98
+ org_name = name || username
99
+ r = client.organization_get(name: org_name)
100
+ Organization.load(account: self, **r)
81
101
  end
82
102
 
83
- # @param [Array] args
84
- # @return [Hash]
85
- def box_params(*args)
86
- # Prepares a hash based on the *args array passed in.
87
- # Acceptable parameters are those documented by Hashicorp for the v1 API
88
- # at https://vagrantcloud.com/docs
103
+ protected
89
104
 
90
- # This dance is to simulate what we could have accomplished with **args
91
- # in Ruby 2.0+
92
- # This will silently discard any options that are not passed in as a
93
- # hash.
94
- # Find and remove the first hash we find in *args. Set params to an
95
- # empty hash if we weren't passed one.
96
- params = args.select { |v| v.is_a?(Hash) }.first
97
- if params.nil?
98
- params = {}
99
- else
100
- args.delete_if { |v| v == params }
105
+ def setup!
106
+ if client.access_token
107
+ r = client.request(path: "authenticate")
108
+ @username = r.dig(:user, :username)
101
109
  end
102
-
103
- # Default boxes to public can be overridden by providing :is_private
104
- params[:is_private] = false unless params.key?(:is_private)
105
-
106
- params
107
110
  end
108
111
  end
109
112
  end