mirror of
				https://github.com/avitex/elixir-vultr
				synced 2025-11-03 23:53:28 +00:00 
			
		
		
		
	Initial commit
This commit is contained in:
		
						commit
						60c132e440
					
				
							
								
								
									
										17
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,17 @@
 | 
				
			|||||||
 | 
					# The directory Mix will write compiled artifacts to.
 | 
				
			||||||
 | 
					/_build
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If you run "mix test --cover", coverage assets end up here.
 | 
				
			||||||
 | 
					/cover
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# The directory Mix downloads your dependencies sources to.
 | 
				
			||||||
 | 
					/deps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Where 3rd-party dependencies like ExDoc output generated docs.
 | 
				
			||||||
 | 
					/doc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# If the VM crashes, it generates a dump, let's ignore it too.
 | 
				
			||||||
 | 
					erl_crash.dump
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Also ignore archive artifacts (built via "mix archive.build").
 | 
				
			||||||
 | 
					*.ez
 | 
				
			||||||
							
								
								
									
										14
									
								
								.travis.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								.travis.yml
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					language: elixir
 | 
				
			||||||
 | 
					elixir:
 | 
				
			||||||
 | 
					  - 1.4.0
 | 
				
			||||||
 | 
					notifications:
 | 
				
			||||||
 | 
					  recipients:
 | 
				
			||||||
 | 
					    - theavitex@gmail.com
 | 
				
			||||||
 | 
					otp_release:
 | 
				
			||||||
 | 
					  - 18.2
 | 
				
			||||||
 | 
					env:
 | 
				
			||||||
 | 
					  - MIX_ENV=test
 | 
				
			||||||
 | 
					script:
 | 
				
			||||||
 | 
					  - "mix do deps.get, compile"
 | 
				
			||||||
 | 
					after_script:
 | 
				
			||||||
 | 
					  - "MIX_ENV=docs mix do deps.get, inch.report"
 | 
				
			||||||
							
								
								
									
										42
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								README.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					[](https://travis-ci.org/avitex/elixir-vultr)
 | 
				
			||||||
 | 
					[](http://inch-ci.org/github/avitex/elixir-vultr)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Vultr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					**Simple wrapper for the [Vultr API](https://www.vultr.com/api/).**  
 | 
				
			||||||
 | 
					Documentation hosted on [hexdocs](https://hexdocs.pm/vultr).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Installation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  Add `vultr` to your list of dependencies in `mix.exs`:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```elixir
 | 
				
			||||||
 | 
					  def deps do
 | 
				
			||||||
 | 
					    [{:vultr, "~> 0.1.0"}]
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Examples
 | 
				
			||||||
 | 
					### Retrieving app list
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```elixir
 | 
				
			||||||
 | 
					  Vultr.app_list()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  # Example response
 | 
				
			||||||
 | 
					  %{
 | 
				
			||||||
 | 
					    body: %{ "1" => %{"APPID" => "1", "deploy_name" => "LEMP on CentOS 6 x64", ... }, ... },
 | 
				
			||||||
 | 
					    headers: %{ "content-type" => "application/json", ... },
 | 
				
			||||||
 | 
					    method: :get,
 | 
				
			||||||
 | 
					    opts: [],
 | 
				
			||||||
 | 
					    query: [],
 | 
				
			||||||
 | 
					    status: 200,
 | 
				
			||||||
 | 
					    url: "https://api.vultr.com/v1/app/list"
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Using authenticated methods
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  ```elixir
 | 
				
			||||||
 | 
					  client = Vultr.client("<APIKEY>")
 | 
				
			||||||
 | 
					  Vultr.server_list(client, %{})
 | 
				
			||||||
 | 
					  ```
 | 
				
			||||||
							
								
								
									
										148
									
								
								lib/request.ex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								lib/request.ex
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,148 @@
 | 
				
			|||||||
 | 
					defmodule Vultr.Request do
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						#@SPECIAL_PARAMS ["SUBID", "DCID", "RECORDID", "VPSPLANID", "APPID", "OSID", "ISOID", "SCRIPTID", "SNAPSHOTID", "SSHKEYID", "BACKUPID", "USERID"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defmacro __using__(_) do
 | 
				
			||||||
 | 
							quote do
 | 
				
			||||||
 | 
								import Vultr.Request, only: [request: 3]
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defmacro request(endpoint_method, endpoint_path, endpoint_opts) do
 | 
				
			||||||
 | 
							endpoint_params = Keyword.get(endpoint_opts, :params, {nil, nil, []}) |> normalize_params
 | 
				
			||||||
 | 
							endpoint_description = Keyword.fetch!(endpoint_opts, :desc)
 | 
				
			||||||
 | 
							endpoint_requires_api_key = Keyword.get(endpoint_opts, :api_key, nil)	
 | 
				
			||||||
 | 
							endpoint_required_access = Keyword.get(endpoint_opts, :required_access, nil)
 | 
				
			||||||
 | 
							endpoint_has_params = (length(endpoint_params) > 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							request_client_var = Macro.var(:client, nil)
 | 
				
			||||||
 | 
							request_params_var = Macro.var(:params, nil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							function_args =
 | 
				
			||||||
 | 
								cond do
 | 
				
			||||||
 | 
									endpoint_requires_api_key && endpoint_has_params ->
 | 
				
			||||||
 | 
										[request_client_var, request_params_var]
 | 
				
			||||||
 | 
									endpoint_requires_api_key ->
 | 
				
			||||||
 | 
										[request_client_var]
 | 
				
			||||||
 | 
									endpoint_has_params ->
 | 
				
			||||||
 | 
										[request_params_var]
 | 
				
			||||||
 | 
									true ->
 | 
				
			||||||
 | 
										[]
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							tesla_args =
 | 
				
			||||||
 | 
								if endpoint_requires_api_key do
 | 
				
			||||||
 | 
									[request_client_var]
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									[]
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							tesla_args =
 | 
				
			||||||
 | 
								if endpoint_method === :get && endpoint_has_params do
 | 
				
			||||||
 | 
									tesla_args ++ [quote do
 | 
				
			||||||
 | 
										unquote(endpoint_path) <> "?" <> URI.encode_query(unquote(request_params_var))
 | 
				
			||||||
 | 
									end]
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									tesla_args ++ [quote do
 | 
				
			||||||
 | 
										unquote(endpoint_path)
 | 
				
			||||||
 | 
									end]
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
							
 | 
				
			||||||
 | 
							tesla_args =
 | 
				
			||||||
 | 
								if endpoint_method !== :get && endpoint_has_params do
 | 
				
			||||||
 | 
									tesla_args ++ [request_params_var]
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									tesla_args
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							quote do
 | 
				
			||||||
 | 
								@doc unquote(documentation(endpoint_method, endpoint_path, endpoint_description, endpoint_params, endpoint_required_access, endpoint_requires_api_key))
 | 
				
			||||||
 | 
								def unquote(function_name(endpoint_path))(unquote_splicing(function_args)) do
 | 
				
			||||||
 | 
									unquote(endpoint_method)(unquote_splicing(tesla_args))
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defp function_name(path), do: path |> String.replace("/", "_") |> String.to_atom
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defp normalize_param({name, opts}) do
 | 
				
			||||||
 | 
							type = Keyword.fetch!(opts, :type)
 | 
				
			||||||
 | 
							%{
 | 
				
			||||||
 | 
								name: name,
 | 
				
			||||||
 | 
								default: Keyword.get(opts, :default, nil),
 | 
				
			||||||
 | 
								name_atom: (name |> String.downcase |> String.to_atom),
 | 
				
			||||||
 | 
								optional: Keyword.get(opts, :optional, false),
 | 
				
			||||||
 | 
								type: type,
 | 
				
			||||||
 | 
								type_string: (type |> Atom.to_string),
 | 
				
			||||||
 | 
								desc: Keyword.fetch!(opts, :desc),
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defp normalize_params({_, _, []}), do: []
 | 
				
			||||||
 | 
						defp normalize_params({_, _, params}), do: params |> Enum.map(&normalize_param/1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						##################################################
 | 
				
			||||||
 | 
						# Documentation helpers
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defp documentation(method, path, desc, params, required_access, api_key) do
 | 
				
			||||||
 | 
							doc = """
 | 
				
			||||||
 | 
							#{desc}
 | 
				
			||||||
 | 
							"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							doc = 
 | 
				
			||||||
 | 
								if length(params) > 0 do
 | 
				
			||||||
 | 
									doc <> ("""
 | 
				
			||||||
 | 
									### Params
 | 
				
			||||||
 | 
									| Name | Type | Optional | Description |
 | 
				
			||||||
 | 
									| ---- | ---- | -------- | ----------- |
 | 
				
			||||||
 | 
									#{doc_params(params)}
 | 
				
			||||||
 | 
									""")
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									doc
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							doc <> """
 | 
				
			||||||
 | 
							### Backend
 | 
				
			||||||
 | 
							- Method:           `#{doc_method(method)}`
 | 
				
			||||||
 | 
							- Path:             `/v1/#{path}`
 | 
				
			||||||
 | 
							- API Key:          `#{doc_api_key(api_key)}`
 | 
				
			||||||
 | 
							- Required Access:  `#{doc_required_access(required_access)}`
 | 
				
			||||||
 | 
							"""
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defp doc_param(param), do: """
 | 
				
			||||||
 | 
						| `#{String.downcase(param.name)}` | #{param.type_string} | #{doc_optional_default(param.optional, param.default)} | #{param.desc |> String.replace("\n", "<br>")} |
 | 
				
			||||||
 | 
						"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defp doc_params(params), do: params |> Enum.map(&doc_param/1) |> Enum.join("")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defp doc_optional_default(optional, default) do
 | 
				
			||||||
 | 
							if optional do
 | 
				
			||||||
 | 
								optional = "Yes"
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								if default == nil do
 | 
				
			||||||
 | 
									optional
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
									optional <> "<br>(Default `#{inspect default}`)"
 | 
				
			||||||
 | 
								end
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
								"No"
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defp doc_api_key(nil), do: "No"
 | 
				
			||||||
 | 
						defp doc_api_key(atm), do: atom_to_word(atm)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defp doc_required_access(nil), do: "None"
 | 
				
			||||||
 | 
						defp doc_required_access(atm), do: Atom.to_string(atm)
 | 
				
			||||||
 | 
						
 | 
				
			||||||
 | 
						defp atom_to_word(atm), do: atm |> Atom.to_string |> String.capitalize
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defp doc_method(method) do
 | 
				
			||||||
 | 
							if !Enum.any?([:get, :post], fn supported -> method == supported end) do
 | 
				
			||||||
 | 
								raise ArgumentError, message: "Bad method"
 | 
				
			||||||
 | 
							end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							method |> Atom.to_string |> String.upcase()
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										2002
									
								
								lib/vultr.ex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2002
									
								
								lib/vultr.ex
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										42
									
								
								mix.exs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								mix.exs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,42 @@
 | 
				
			|||||||
 | 
					defmodule Vultr.Mixfile do
 | 
				
			||||||
 | 
						use Mix.Project
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						@description """
 | 
				
			||||||
 | 
						Simple wrapper for the Vultr API
 | 
				
			||||||
 | 
						"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						def project do
 | 
				
			||||||
 | 
							[
 | 
				
			||||||
 | 
								app: :vultr,
 | 
				
			||||||
 | 
								version: "0.1.0",
 | 
				
			||||||
 | 
								elixir: "~> 1.3",
 | 
				
			||||||
 | 
								deps: deps(),
 | 
				
			||||||
 | 
								description: @description,
 | 
				
			||||||
 | 
								package: package(),
 | 
				
			||||||
 | 
							]
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						# Configuration for the OTP application
 | 
				
			||||||
 | 
						def application do
 | 
				
			||||||
 | 
							[applications: [:tesla, :ibrowse]]
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defp deps do
 | 
				
			||||||
 | 
							[
 | 
				
			||||||
 | 
								{:inch_ex, "~> 0.5", only: :dev},
 | 
				
			||||||
 | 
								{:ex_doc, "~> 0.14", only: :dev, runtime: false},
 | 
				
			||||||
 | 
								{:tesla, "~> 0.7.0"},
 | 
				
			||||||
 | 
								{:ibrowse, "~> 4.2"},
 | 
				
			||||||
 | 
								{:poison, ">= 1.0.0"}
 | 
				
			||||||
 | 
							]
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						defp package do
 | 
				
			||||||
 | 
							[
 | 
				
			||||||
 | 
								name: :vultr,
 | 
				
			||||||
 | 
								maintainers: ["James Dyson"],
 | 
				
			||||||
 | 
								licenses: ["MIT"],
 | 
				
			||||||
 | 
								links: %{"GitHub" => "https://github.com/avitex/elixir-vultr"},
 | 
				
			||||||
 | 
							]
 | 
				
			||||||
 | 
						end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
							
								
								
									
										12
									
								
								mix.lock
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								mix.lock
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
				
			|||||||
 | 
					%{"certifi": {:hex, :certifi, "1.0.0", "1c787a85b1855ba354f0b8920392c19aa1d06b0ee1362f9141279620a5be2039", [:rebar3], []},
 | 
				
			||||||
 | 
					  "earmark": {:hex, :earmark, "1.1.1", "433136b7f2e99cde88b745b3a0cfc3fbc81fe58b918a09b40fce7f00db4d8187", [:mix], []},
 | 
				
			||||||
 | 
					  "ex_doc": {:hex, :ex_doc, "0.14.5", "c0433c8117e948404d93ca69411dd575ec6be39b47802e81ca8d91017a0cf83c", [:mix], [{:earmark, "~> 1.0", [hex: :earmark, optional: false]}]},
 | 
				
			||||||
 | 
					  "hackney": {:hex, :hackney, "1.6.6", "5564b4695d48fd87859e9df77a7fa4b4d284d24519f0cd7cc898f09e8fbdc8a3", [:rebar3], [{:certifi, "1.0.0", [hex: :certifi, optional: false]}, {:idna, "4.0.0", [hex: :idna, optional: false]}, {:metrics, "1.0.1", [hex: :metrics, optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, optional: false]}]},
 | 
				
			||||||
 | 
					  "ibrowse": {:hex, :ibrowse, "4.4.0", "2d923325efe0d2cb09b9c6a047b2835a5eda69d8a47ed6ff8bc03628b764e991", [:rebar3], []},
 | 
				
			||||||
 | 
					  "idna": {:hex, :idna, "4.0.0", "10aaa9f79d0b12cf0def53038547855b91144f1bfcc0ec73494f38bb7b9c4961", [:rebar3], []},
 | 
				
			||||||
 | 
					  "inch_ex": {:hex, :inch_ex, "0.5.6", "418357418a553baa6d04eccd1b44171936817db61f4c0840112b420b8e378e67", [:mix], [{:poison, "~> 1.5 or ~> 2.0 or ~> 3.0", [hex: :poison, optional: false]}]},
 | 
				
			||||||
 | 
					  "metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], []},
 | 
				
			||||||
 | 
					  "mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [:rebar3], []},
 | 
				
			||||||
 | 
					  "poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [:mix], []},
 | 
				
			||||||
 | 
					  "ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [:make, :rebar], []},
 | 
				
			||||||
 | 
					  "tesla": {:hex, :tesla, "0.7.1", "0a13d25f35632928f36b9042c5051813cc392992f63ad55436c72162a2d8de02", [:mix], [{:exjsx, ">= 0.1.0", [hex: :exjsx, optional: true]}, {:fuse, "~> 2.4", [hex: :fuse, optional: true]}, {:hackney, "~> 1.6", [hex: :hackney, optional: true]}, {:ibrowse, "~> 4.2", [hex: :ibrowse, optional: true]}, {:poison, ">= 1.0.0", [hex: :poison, optional: true]}]}}
 | 
				
			||||||
							
								
								
									
										1
									
								
								test/test_helper.exs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								test/test_helper.exs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					ExUnit.start()
 | 
				
			||||||
							
								
								
									
										8
									
								
								test/vultr_test.exs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								test/vultr_test.exs
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					defmodule VultrTest do
 | 
				
			||||||
 | 
					  use ExUnit.Case
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  test "requests work" do
 | 
				
			||||||
 | 
					  	response = Vultr.app_list()
 | 
				
			||||||
 | 
					    assert response.status === 200
 | 
				
			||||||
 | 
					  end
 | 
				
			||||||
 | 
					end
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user