diff options
author | Hentioe <me@bluerain.io> | 2020-10-28 11:07:30 +0800 |
---|---|---|
committer | Hentioe <me@bluerain.io> | 2020-10-28 11:07:30 +0800 |
commit | 030fb5e70fe6e3be8bfcedf64ed10e2567891d48 (patch) | |
tree | 22ba9f678c0dddb397f4fb5ee618b83d6ec94850 | |
parent | Simplify the calling process (diff) |
Optimize DSL
-rw-r--r-- | lib/azure_ex.ex | 11 | ||||
-rw-r--r-- | lib/azure_ex/dsl.ex | 36 | ||||
-rw-r--r-- | lib/azure_ex/request.ex | 29 |
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 |