Skip to content

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
...
Checking mergeability… Don’t worry, you can still create the pull request.
  • 3 commits
  • 7 files changed
  • 0 commit comments
  • 1 contributor
View
1 .gitignore
@@ -0,0 +1 @@
+_build
View
23 README.md
@@ -1,9 +1,28 @@
Odoric
======================================
+## Dependencies
+
+* getopt -- [https://github.com/jcomellas/getopt](https://github.com/jcomellas/getopt)
+* erlcloud -- [https://github.com/gleber/erlcloud](https://github.com/gleber/erlcloud)
+
+## Usage
+
+To use S3 for uploading target systems you must have the environment
+variable AWS_CREDENTIAL_FILE set to the location of your aws
+credentials file. Example:
+
+```shell
+$ export AWS_CREDENTIAL_FILE=~/.aws
+$ cat ~/.aws
+AWSAccessKeyId=<YOUR ACCESS KEY>
+AWSSecretKey=<YOUR SECRET KEY>
+```
+
+Now to create a target system and upload it to S3 we do:
+
```shell
$ sinan escript
-$ ./_build/odoric/escript/odoric help
-Usage: odoric {ping|stop|restart|reboot}
+$ ./_build/odoric/escript/odoric deploy -u git@github.com:Mashape/odoric.git
```
View
2 lib/odoric/src/odoric.app.src
@@ -6,6 +6,6 @@
{modules, [odoric_app,
odoric_sup]},
{registered,[odoric_sup]},
- {applications, [kernel, stdlib]},
+ {applications, [kernel, stdlib, getopt, erlcloud]},
{mod, {odoric_app,[]}},
{start_phases, []}]}.
View
120 lib/odoric/src/odoric.erl
@@ -17,35 +17,66 @@
%%--------------------------------------------------------------------
main(Args) ->
ok = start_epmd(),
+
%% Extract the args
- {RestArgs, TargetNode} = case process_args(Args, [], undefined) of
- {[], undefined} ->
- halt(0);
- Result ->
- Result
- end,
+ {ok, {Options, _RestArgs}} = getopt:parse(opt_spec_list(), Args),
+ TargetNode = case lists:keyfind('sname', 1, Options) of
+ false ->
+ none;
+ undefined ->
+ TN = proplists:get_value('name', Options),
+ ThisNode = append_node_suffix(TN, "_maint_"),
+ {ok, _} = net_kernel:start([ThisNode, longnames]),
+ nodename(TN);
+ {sname, TN} ->
+ io:format("NAME ~p~n", [TN]),
+ ThisNode = append_node_suffix(TN, "_maint_"),
+ {ok, _} = net_kernel:start([ThisNode, shortnames]),
+ nodename(TN)
+ end,
- %% See if the node is currently running -- if it's not, we'll bail
- case {net_kernel:hidden_connect_node(TargetNode), net_adm:ping(TargetNode)} of
- {true, pong} ->
- ok;
- {_, pang} ->
- io:format("Node ~p not responding to pings.\n", [TargetNode]),
- halt(1)
+ case lists:keyfind(cookie, 1, Options) of
+ {cookie, Cookie} ->
+ erlang:set_cookie(node(), Cookie);
+ false ->
+ nothing
+ end,
+
+ case TargetNode of
+ none ->
+ do_nothing;
+ _ ->
+ %% See if the node is currently running -- if it's not, we'll bail
+ case {net_kernel:hidden_connect_node(TargetNode), net_adm:ping(TargetNode)} of
+ {true, pong} ->
+ ok;
+ {_, pang} ->
+ io:format("Node ~p not responding to pings.\n", [TargetNode]),
+ halt(1)
+ end
end,
- case RestArgs of
- ["ping"] ->
+ case lists:keyfind(action, 1, Options) of
+ {action, "deploy"} ->
+ start_erlcloud(),
+ {url, Url} = lists:keyfind(url, 1, Options),
+ Artifacts = odoric_builder:build(Url),
+ odoric_uploader:upload(s3, Artifacts),
+ ok;
+ {action, "ping"} ->
%% If we got this far, the node already responsed to a ping, so just dump
%% a "pong"
io:format("pong\n");
- ["stop"] ->
+ {action, "stop"} ->
io:format("~p\n", [rpc:call(TargetNode, init, stop, [], 60000)]);
- ["restart"] ->
+ {action, "restart"} ->
io:format("~p\n", [rpc:call(TargetNode, init, restart, [], 60000)]);
- ["reboot"] ->
+ {action, "reboot"} ->
io:format("~p\n", [rpc:call(TargetNode, init, reboot, [], 60000)]);
- ["rpc", Module, Function | RpcArgs] ->
+ {action, "rpc"} ->
+ {module, Module} = lists:keyfind(module, 1, Options),
+ {function, Function} = lists:keyfind(function, 1, Options),
+ {args, RpcArgs} = lists:keyfind(args, 1, Options),
case rpc:call(TargetNode, list_to_atom(Module), list_to_atom(Function),
[RpcArgs], 60000) of
ok ->
@@ -56,7 +87,10 @@ main(Args) ->
_ ->
halt(1)
end;
- ["rpcterms", Module, Function, ArgsAsString] ->
+ {action, "rpcterms"} ->
+ {module, Module} = lists:keyfind(module, 1, Options),
+ {function, Function} = lists:keyfind(function, 1, Options),
+ {args, ArgsAsString} = lists:keyfind(args, 1, Options),
case rpc:call(TargetNode, list_to_atom(Module), list_to_atom(Function),
consult(ArgsAsString), 60000) of
{badrpc, Reason} ->
@@ -64,10 +98,7 @@ main(Args) ->
halt(1);
Other ->
io:format("~p\n", [Other])
- end;
- Other ->
- io:format("Other: ~p\n", [Other]),
- io:format("Usage: odoric {ping|stop|restart|reboot}\n")
+ end
end,
net_kernel:stop().
@@ -75,25 +106,14 @@ main(Args) ->
%%% Internal functions
%%%===================================================================
-process_args([], Acc, TargetNode) ->
- {lists:reverse(Acc), TargetNode};
-process_args(["help" | _Rest], _Acc, _TargetNode) ->
- io:format("Usage: odoric {ping|stop|restart|reboot}\n"),
- {[], undefined};
-process_args(["-setcookie", Cookie | Rest], Acc, TargetNode) ->
- erlang:set_cookie(node(), list_to_atom(Cookie)),
- process_args(Rest, Acc, TargetNode);
-process_args(["-name", TargetName | Rest], Acc, _) ->
- ThisNode = append_node_suffix(TargetName, "_maint_"),
- {ok, _} = net_kernel:start([ThisNode, longnames]),
- process_args(Rest, Acc, nodename(TargetName));
-process_args(["-sname", TargetName | Rest], Acc, _) ->
- ThisNode = append_node_suffix(TargetName, "_maint_"),
- {ok, _} = net_kernel:start([ThisNode, shortnames]),
- process_args(Rest, Acc, nodename(TargetName));
-process_args([Arg | Rest], Acc, Opts) ->
- process_args(Rest, [Arg | Acc], Opts).
-
+start_erlcloud() ->
+ ok = application:start(sasl),
+ ok = application:start(crypto),
+ ok = application:start(public_key),
+ ok = application:start(ssl),
+ ok = application:start(inets),
+ ok = application:start(xmerl),
+ ok = application:start(erlcloud).
start_epmd() ->
[] = os:cmd(epmd_path() ++ " -daemon"),
@@ -115,7 +135,6 @@ epmd_path() ->
Epmd
end.
-
nodename(Name) ->
case string:tokens(Name, "@") of
[_Node, _Host] ->
@@ -133,7 +152,6 @@ append_node_suffix(Name, Suffix) ->
list_to_atom(lists:concat([Node, Suffix, os:getpid()]))
end.
-
%%
%% Given a string or binary, parse it into a list of terms, ala file:consult/0
%%
@@ -157,3 +175,15 @@ consult(Cont, Str, Acc) ->
{more, Cont1} ->
consult(Cont1, eof, Acc)
end.
+
+opt_spec_list() ->
+ [
+ {cookie, $c, "set-cookie", atom, "Cookie"},
+ {name, $s, "name", string, "Short node name"},
+ {sname, $s, "sname", string, "Long node name"},
+ {url, $u, "url", string, "Url of git repo"},
+ {action, undefined, undefined, string, "Action"},
+ {module, undefined, undefined, string, "odule to call function of"},
+ {function, undefined, undefined, string, "Function to call"},
+ {args, undefined, undefined, string, "Args to pass function"}
+ ].
View
31 lib/odoric/src/odoric_builder.erl
@@ -0,0 +1,31 @@
+%%%-------------------------------------------------------------------
+%%% @author Tristan Sloughter <>%%% @copyright (C) 2012, Tristan Sloughter
+%%% @doc
+%%%
+%%% @end
+%%% Created : 19 April 2012 by Tristan Sloughter <tristan@mashape.com>
+%%%-------------------------------------------------------------------
+-module(odoric_builder).
+
+%% API
+-export([build/1]).
+
+build(Url) ->
+ {ok, Cwd} = file:get_cwd(),
+ Dir = os:cmd("mktemp -d"),
+ %% remove \n
+ TmpDir = lists:sublist(Dir, 1, length(Dir)-1),
+
+ odoric_git:clone(Url, TmpDir),
+ file:set_cwd(TmpDir),
+
+ io:format("Building with sinan...~n"),
+ os:cmd("sinan dist"),
+
+ file:set_cwd(Cwd),
+
+ {ok, Artifacts} = file:list_dir(filename:join(TmpDir, "_build/tar")),
+ [filename:join([TmpDir, "_build/tar", Artifact]) || Artifact <- Artifacts].
+
+
+
View
16 lib/odoric/src/odoric_git.erl
@@ -0,0 +1,16 @@
+%%%-------------------------------------------------------------------
+%%% @author Tristan Sloughter <>%%% @copyright (C) 2012, Tristan Sloughter
+%%% @doc
+%%%
+%%% @end
+%%% Created : 19 April 2012 by Tristan Sloughter <tristan@mashape.com>
+%%%-------------------------------------------------------------------
+-module(odoric_git).
+
+%% API
+-export([clone/2]).
+
+clone(Url, Dir) ->
+ io:format("Cloning ~s to ~s...~n", [Url, Dir]),
+ Cmd = io_lib:format("git clone ~s ~s", [Url, Dir]),
+ os:cmd(Cmd).
View
52 lib/odoric/src/odoric_uploader.erl
@@ -0,0 +1,52 @@
+%%%-------------------------------------------------------------------
+%%% @author Tristan Sloughter <>%%% @copyright (C) 2012, Tristan Sloughter
+%%% @doc
+%%%
+%%% @end
+%%% Created : 19 April 2012 by Tristan Sloughter <tristan@mashape.com>
+%%%-------------------------------------------------------------------
+-module(odoric_uploader).
+
+%% API
+-export([upload/2,
+ upload/3]).
+
+upload(s3, Artifacts) ->
+ upload(s3, "erlang_target_systems", Artifacts).
+
+upload(s3, Bucket, Artifacts) ->
+ AwsCreds = get_aws_creds(),
+ lists:foreach(fun(Artifact) ->
+ io:format("Uplading ~s to s3 bucket ~s...~n", [Artifact, Bucket]),
+ {ok, Binary} = file:read_file(Artifact),
+ Key = filename:basename(Artifact),
+ erlcloud_s3:put_object(Bucket, Key, Binary, AwsCreds)
+ end, Artifacts).
+
+get_aws_creds() ->
+ CredFilePath = os:getenv("AWS_CREDENTIAL_FILE"),
+ {ok, CredFile} = file:read_file(CredFilePath),
+ AwsCreds =[list_to_tuple(string:tokens(Line, "=")) || Line <- string:tokens(binary_to_list(CredFile), "\n")],
+
+ AccessKeyId = aws_access_key_id(AwsCreds),
+ SecretKey = aws_secret_key(AwsCreds),
+
+ erlcloud_s3:new(AccessKeyId, SecretKey).
+
+aws_access_key_id(AwsCreds) ->
+ {"AWSAccessKeyId", AccessKeyId} = lists:keyfind("AWSAccessKeyId", 1, AwsCreds),
+ AccessKeyId.
+
+aws_secret_key(AwsCreds) ->
+ {"AWSSecretKey", SecretKey} = lists:keyfind("AWSSecretKey", 1, AwsCreds),
+ SecretKey.
+
+
+
+
+
+
+
+
+
+

No commit comments for this range

Something went wrong with that request. Please try again.