summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHentioe <me@bluerain.io>2020-10-28 11:07:30 +0800
committerHentioe <me@bluerain.io>2020-10-28 11:07:30 +0800
commit030fb5e70fe6e3be8bfcedf64ed10e2567891d48 (patch)
tree22ba9f678c0dddb397f4fb5ee618b83d6ec94850
parentSimplify the calling process (diff)
Optimize DSL
-rw-r--r--lib/azure_ex.ex11
-rw-r--r--lib/azure_ex/dsl.ex36
-rw-r--r--lib/azure_ex/request.ex29
3 files changed, 55 insertions, 21 deletions
diff --git a/lib/azure_ex.ex b/lib/azure_ex.ex
index 7dce3c9..d8fa55d 100644
--- a/lib/azure_ex.ex
+++ b/lib/azure_ex.ex
@@ -8,13 +8,16 @@ defmodule AzureEx do
defendpoint(
"ListAllVirtualMachines",
- "https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Compute/virtualMachines",
- {:get, "2020-06-01"}
+ "GET https://management.azure.com/subscriptions/{subscriptionId}/providers/Microsoft.Compute/virtualMachines?api-version=2020-06-01"
)
defendpoint(
"GetNetworkInterface",
- "https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/networkInterfaces/{networkInterfaceName}",
- {:get, "2020-06-01"}
+ "GET https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Network/networkInterfaces/{networkInterfaceName}?api-version=2020-06-01"
+ )
+
+ defendpoint(
+ "PowerOffVirtualMachines",
+ "POST https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Compute/virtualMachines/{vmName}/powerOff?api-version=2020-06-01"
)
end
diff --git a/lib/azure_ex/dsl.ex b/lib/azure_ex/dsl.ex
index 49647f3..1da39a0 100644
--- a/lib/azure_ex/dsl.ex
+++ b/lib/azure_ex/dsl.ex
@@ -2,11 +2,27 @@ defmodule AzureEx.DSL do
@moduledoc false
@path_var_re ~r/\{([^\}]+)\}/
+ @api_version_query_re ~r/api\-version=(.+)$/
- defmacro defendpoint(name, raw_uri, {method, last_api_version}) do
- # 扫描原始 URI 中的路径变量
- r = Regex.scan(@path_var_re, raw_uri)
- # 处理并得到路径变量名称列表
+ defmacro defendpoint(name, raw_api) do
+ # 解析并获取请求方法
+ method_s = raw_api |> String.split(" ") |> List.first() |> Macro.underscore()
+
+ # +1 是为了消除空格
+ uri_begin_pos = String.length(method_s) + 1
+
+ method = String.to_atom(method_s)
+ # 解析并获取 API 版本
+ [_, api_version] = Regex.run(@api_version_query_re, raw_api)
+
+ [{query_begin_pos, _}, _] = Regex.run(@api_version_query_re, raw_api, return: :index)
+
+ # 截断获取 URI
+ uri = String.slice(raw_api, uri_begin_pos..(query_begin_pos - 2))
+
+ # 扫描 URI 中的路径变量
+ r = Regex.scan(@path_var_re, uri)
+ # 处理并得到路径变量的名称列表
path_vars =
r
|> Enum.map(&List.last/1)
@@ -25,12 +41,12 @@ defmodule AzureEx.DSL do
}
# 使用变量分割 URI
- raw_segments = Regex.split(@path_var_re, raw_uri)
+ raw_segments = Regex.split(@path_var_re, uri)
unless length(raw_segments) == length(path_vars) + 1 do
raise """
Error parsing raw URI, wrong number of path variables.\n
- URI: #{raw_uri}
+ URI: #{uri}
Vars: #{inspect(path_vars)}
"""
end
@@ -56,18 +72,18 @@ defmodule AzureEx.DSL do
end
end)
- # 函数体 AST(拼接字符串)
- fun_body_ast = {:<<>>, [], splicing_args_ast}
+ # <<>> 宏的调用 AST
+ splicing_call_ast = {:<<>>, [], splicing_args_ast}
quote do
def unquote(fun_sign_ast) do
api_version =
- Keyword.get(unquote({:options, [], Elixir}), :"api-version", unquote(last_api_version))
+ Keyword.get(unquote({:options, [], Elixir}), :"api-version", unquote(api_version))
params = Keyword.get(unquote({:options, [], Elixir}), :params)
data = Keyword.get(unquote({:options, [], Elixir}), :data)
- endpoint = unquote(fun_body_ast) <> "?" <> "api-version=#{api_version}"
+ endpoint = unquote(splicing_call_ast) <> "?" <> "api-version=#{api_version}"
endpoint =
if params do
diff --git a/lib/azure_ex/request.ex b/lib/azure_ex/request.ex
index c9908f7..bf8277d 100644
--- a/lib/azure_ex/request.ex
+++ b/lib/azure_ex/request.ex
@@ -5,26 +5,41 @@ defmodule AzureEx.Request do
alias AzureEx.{Config, TokenHosting}
- @type body :: map
+ @type method :: :get | :post
+ @type data :: map
@type result :: any
@type error :: any
@type httpoison_result :: {:ok, HTTPoison.Response.t()} | {:error, HTTPoison.Error.t()}
- @spec call(binary, atom, body) ::
- {:ok, result} | {:error, error}
+ @spec call(binary, method, data) :: {:ok, result} | {:error, error}
def call(endpoint, method, body \\ %{}) do
method |> send(endpoint, body) |> handle_response()
end
@spec handle_response({:ok, HTTPoison.Response.t()}) :: {:ok, result} | {:error, error}
- def handle_response({:ok, %HTTPoison.Response{body: body}}) do
- {:ok, Jason.decode!(body, keys: :atoms)}
+ def handle_response({:ok, %HTTPoison.Response{body: body, status_code: status_code}}) do
+ if body == "" do
+ {:ok, status_code}
+ else
+ {:ok, Jason.decode!(body, keys: :atoms)}
+ end
end
- @spec send(:get, String.t(), body) :: httpoison_result
- def send(:get, endpoint, _body \\ %{}) do
+ @spec send(method, String.t(), data) :: httpoison_result
+ defp send(:get, endpoint, _data) do
headers = [Authorization: "Bearer #{TokenHosting.get_token()}"]
HTTPoison.get(endpoint, headers, Config.timeouts())
end
+
+ defp send(:post, endpoint, data) do
+ headers = [
+ Authorization: "Bearer #{TokenHosting.get_token()}",
+ "Content-Type": "application/json"
+ ]
+
+ body = Jason.encode!(data || %{})
+
+ HTTPoison.post(endpoint, body, headers, Config.timeouts())
+ end
end