From 782104a0f8794853152d5444c0a7c13bf2982b85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20Hedenstro=CC=88m?= <erik@hedenstroem.com> Date: Wed, 27 Jan 2016 11:27:11 +0100 Subject: [PATCH] Skeleton in place --- .gitignore | 4 +- .gitlab-ci.yml | 67 +++++++++++++++++++++ LICENSE | 42 ++++++------- Makefile | 38 ++++++++++++ apps/consul-proxy/include/consul-proxy.hrl | 1 + apps/consul-proxy/priv/Dockerfile | 20 ++++++ apps/consul-proxy/priv/consul-proxy-wrapper | 28 +++++++++ apps/consul-proxy/src/consul-proxy.app.src | 36 ++++++----- apps/consul-proxy/src/consul-proxy_app.erl | 5 +- apps/consul-proxy/src/consul-proxy_sup.erl | 17 ++++-- apps/consul-proxy/test/features_test.erl | 16 +++++ config/sys.config | 30 ++++++++- config/test-sys.config | 29 +++++++++ config/test-vm.args | 19 ++++++ config/vm.args | 19 +++++- rebar.config | 49 ++++++++++----- 16 files changed, 352 insertions(+), 68 deletions(-) create mode 100644 .gitlab-ci.yml create mode 100644 Makefile create mode 100644 apps/consul-proxy/include/consul-proxy.hrl create mode 100644 apps/consul-proxy/priv/Dockerfile create mode 100755 apps/consul-proxy/priv/consul-proxy-wrapper create mode 100644 apps/consul-proxy/test/features_test.erl create mode 100644 config/test-sys.config create mode 100644 config/test-vm.args diff --git a/.gitignore b/.gitignore index a939dce..d1be8c7 100644 --- a/.gitignore +++ b/.gitignore @@ -16,4 +16,6 @@ _deps _plugins _tdeps logs -_build \ No newline at end of file +_build +rebar3 +rebar.lock diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..9488840 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,67 @@ +before_script: + - rebar3 update + +stages: + - compile + - test + - publish + - docker + +compile: + stage: compile + script: + - rebar3 as production do compile + +test: + stage: test + script: + - ERL_AFLAGS="-args_file config/test-vm.args -config config/test-sys.config" rebar3 as test do eunit --cover --application=consul-proxy --dir=apps/consul-proxy/test, cover --verbose + - coverage.escript _build/test/cover/eunit.coverdata + +publish_hex: + stage: publish + only: + - /^\d+[.]\d+[.]\d+$/ # Only publish HEAD tagged with semantic version + script: + - mkdir -p ~/.hex && printf "{key,<<\"$HEX_KEY\">>}.\n{username,<<\"$HEX_USERNAME\">>}.\n" > ~/.hex/hex.config + - mkdir -p ~/.config/rebar3 && printf "{plugins, [rebar3_hex]}.\n" > ~/.config/rebar3/rebar.config + - echo "Y" | rebar3 hex publish + +publish_aws: + stage: publish + only: + - /^\d+[.]\d+[.]\d+$/ # Only publish HEAD tagged with semantic version + script: + - rebar3 edoc + - aws s3 cp doc s3://s3.erlang.ninja/consul-proxy/$CI_BUILD_REF_NAME/ --recursive + - rebar3 as production do tar + - aws s3 cp _build/production/rel/consul-proxy/consul-proxy-$CI_BUILD_REF_NAME.tar.gz s3://s3.erlang.ninja/consul-proxy/ + - aws s3 cp s3://s3.erlang.ninja/consul-proxy/consul-proxy-$CI_BUILD_REF_NAME.tar.gz s3://s3.erlang.ninja/consul-proxy/consul-proxy-latest.tar.gz + +docker_x86: + stage: docker + only: + - master # Only master branch + script: + - rebar3 as production do release + - PLATFORM=x86 envsubst '$PLATFORM' < apps/consul-proxy/priv/Dockerfile > _build/production/Dockerfile + - docker build --no-cache=true -t ehedenst/consul-proxy:x86 -f _build/production/Dockerfile _build/production + - if [ ! -f ~/.docker/config.json ]; then docker login --username=$DOCKER_HUB_USERNAME --password=$DOCKER_HUB_PASSWORD --email=$DOCKER_HUB_EMAIL; fi + - docker push ehedenst/consul-proxy:x86 + tags: + - docker + - x86_64 + +docker_arm: + stage: docker + only: + - master # Only master branch + script: + - rebar3 as production do release + - PLATFORM=arm envsubst '$PLATFORM' < apps/consul-proxy/priv/Dockerfile > _build/production/Dockerfile + - docker build --no-cache=true -t ehedenst/consul-proxy:arm -f _build/production/Dockerfile _build/production + - if [ ! -f ~/.docker/config.json ]; then docker login --username=$DOCKER_HUB_USERNAME --password=$DOCKER_HUB_PASSWORD --email=$DOCKER_HUB_EMAIL; fi + - docker push ehedenst/consul-proxy:arm + tags: + - docker + - armv7l diff --git a/LICENSE b/LICENSE index 4f8d9dc..2bf1f48 100644 --- a/LICENSE +++ b/LICENSE @@ -1,29 +1,21 @@ -Copyright (c) 2016, Erik Hedenström <erik@hedenstroem.com>. -All rights reserved. +The MIT License (MIT) -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: +Copyright (c) 2016 Erik Hedenström <erik@democra.se> -* Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -* Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. -* The names of its contributors may not be used to endorse or promote - products derived from this software without specific prior written - permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6670b44 --- /dev/null +++ b/Makefile @@ -0,0 +1,38 @@ +REBAR_VERSION := $(shell rebar3 --version 2>/dev/null) +ifdef REBAR_VERSION +REBAR := rebar3 +else +REBAR := $(CURDIR)/rebar3 +$(shell if ! [ -e "$(REBAR)" ]; then curl -jksSL -o $(REBAR) https://s3.amazonaws.com/rebar3/rebar3; chmod +x $(REBAR); fi) +endif + +all: eunit + +compile: + @$(REBAR) compile + +eunit: + @ERL_AFLAGS="-args_file config/test-vm.args -config config/test-sys.config" $(REBAR) as test do eunit --cover --application=consul-proxy --dir=apps/consul-proxy/test, cover --verbose + +dialyzer: + @$(REBAR) dialyzer + +release: + @$(REBAR) release + +image: + @$(REBAR) release -d false + PLATFORM=x86 envsubst '$$PLATFORM' < apps/consul-proxy/priv/Dockerfile > _build/default/Dockerfile + docker build --no-cache=true -t ehedenst/consul-proxy:x86 -f _build/default/Dockerfile _build/default + +edoc: + @$(REBAR) edoc + +clean: + @$(REBAR) clean + +distclean: + @rm -rf _build rebar.lock log $(REBAR) + +shell: + @$(REBAR) shell --config=config/test-sys.config diff --git a/apps/consul-proxy/include/consul-proxy.hrl b/apps/consul-proxy/include/consul-proxy.hrl new file mode 100644 index 0000000..7a96c87 --- /dev/null +++ b/apps/consul-proxy/include/consul-proxy.hrl @@ -0,0 +1 @@ +-define(APPLICATION, 'consul-proxy'). diff --git a/apps/consul-proxy/priv/Dockerfile b/apps/consul-proxy/priv/Dockerfile new file mode 100644 index 0000000..3692242 --- /dev/null +++ b/apps/consul-proxy/priv/Dockerfile @@ -0,0 +1,20 @@ +FROM ehedenst/erlang:${PLATFORM} +MAINTAINER Erik Hedenström <erik@hedenstroem.com> + +ENV NAME_PREFIX consul-proxy +ENV COOKIE Nax7jEj7bay6ril + +RUN apk --update add \ + erlang-inets=$ERLANG_VERSION \ + erlang-ssl=$ERLANG_VERSION \ + erlang-asn1=$ERLANG_VERSION \ + erlang-observer=$ERLANG_VERSION \ + erlang-public-key=$ERLANG_VERSION && \ + rm -rf /var/cache/apk/* + +COPY rel/consul-proxy /opt/consul-proxy + +EXPOSE 80 443 + +ENTRYPOINT [ "/opt/consul-proxy/bin/consul-proxy-wrapper" ] +CMD [ "foreground" ] diff --git a/apps/consul-proxy/priv/consul-proxy-wrapper b/apps/consul-proxy/priv/consul-proxy-wrapper new file mode 100755 index 0000000..4173351 --- /dev/null +++ b/apps/consul-proxy/priv/consul-proxy-wrapper @@ -0,0 +1,28 @@ +#!/bin/sh + +set -e + +SCRIPT=$(readlink $0 || true) +if [ -z $SCRIPT ]; then + SCRIPT=$0 +fi; +SCRIPT_DIR="$(cd `dirname "$SCRIPT"` && pwd -P)" + +if [ -z "$NAME_PREFIX" ]; then + NAME_PREFIX="consul-proxy-$(openssl rand -hex 4)" +fi + +if [ -z "$COOKIE" ]; then + export COOKIE=$(openssl rand -hex 16) +fi + +if [ -z "$HOST_IP" ]; then + HOST_IP=$(ifconfig | sed -En 's/127.0.0.1//;s/.*inet (addr:)?(([0-9]*\.){3}[0-9]*).*/\2/p' | head -n 1) +fi + +export RELX_REPLACE_OS_VARS=true +export NODE_NAME=${NAME_PREFIX}@${HOST_IP} + +echo "Starting ${NODE_NAME} with cookie ${COOKIE}" + +${SCRIPT_DIR}/consul-proxy $@ diff --git a/apps/consul-proxy/src/consul-proxy.app.src b/apps/consul-proxy/src/consul-proxy.app.src index 928a047..865972d 100644 --- a/apps/consul-proxy/src/consul-proxy.app.src +++ b/apps/consul-proxy/src/consul-proxy.app.src @@ -1,16 +1,20 @@ -{application, 'consul-proxy', - [{description, "An OTP application"}, - {vsn, "0.1.0"}, - {registered, []}, - {mod, {'consul-proxy_app', []}}, - {applications, - [kernel, - stdlib - ]}, - {env,[]}, - {modules, []}, - - {contributors, []}, - {licenses, []}, - {links, []} - ]}. +{application, 'consul-proxy', [ + {description, "Proxy for docker swarm using consul and vegur"}, + {vsn, "0.1.0"}, + {registered, []}, + {mod, {'consul-proxy_app', []}}, + {applications, [ + kernel, + stdlib, + sasl, + inets, + lager, + tsuru + ]}, + {env, []}, + {modules, []}, + {maintainers, ["Erik Hedenstrom"]}, + {contributors, []}, + {licenses, ["MIT"]}, + {links, [{"GitLab", "https://gitlab.hedenstroem.com/erlang-ninja/consul-proxy"}]} +]}. diff --git a/apps/consul-proxy/src/consul-proxy_app.erl b/apps/consul-proxy/src/consul-proxy_app.erl index af8717e..c4d65d5 100644 --- a/apps/consul-proxy/src/consul-proxy_app.erl +++ b/apps/consul-proxy/src/consul-proxy_app.erl @@ -15,8 +15,9 @@ %% API %%==================================================================== -start(_StartType, _StartArgs) -> - 'consul-proxy_sup':start_link(). +start(_StartType, StartArgs) -> + tsuru_application:set_env('consul-proxy'), + 'consul-proxy_sup':start_link(StartArgs). %%-------------------------------------------------------------------- stop(_State) -> diff --git a/apps/consul-proxy/src/consul-proxy_sup.erl b/apps/consul-proxy/src/consul-proxy_sup.erl index 5310530..afdf97b 100644 --- a/apps/consul-proxy/src/consul-proxy_sup.erl +++ b/apps/consul-proxy/src/consul-proxy_sup.erl @@ -8,7 +8,7 @@ -behaviour(supervisor). %% API --export([start_link/0]). +-export([start_link/1]). %% Supervisor callbacks -export([init/1]). @@ -19,16 +19,23 @@ %% API functions %%==================================================================== -start_link() -> - supervisor:start_link({local, ?SERVER}, ?MODULE, []). +start_link(Args) -> + supervisor:start_link({local, ?SERVER}, ?MODULE, Args). %%==================================================================== %% Supervisor callbacks %%==================================================================== %% Child :: {Id,StartFunc,Restart,Shutdown,Type,Modules} -init([]) -> - {ok, { {one_for_all, 0, 1}, []} }. +init(_Args) -> + + SupFlags = #{ + strategy => one_for_one, + intensity => 10, + period => 10 + }, + + {ok, {SupFlags, []}}. %%==================================================================== %% Internal functions diff --git a/apps/consul-proxy/test/features_test.erl b/apps/consul-proxy/test/features_test.erl new file mode 100644 index 0000000..457c303 --- /dev/null +++ b/apps/consul-proxy/test/features_test.erl @@ -0,0 +1,16 @@ +-module(features_test). + +-include_lib("eunit/include/eunit.hrl"). + +features_test_() -> + setup(), + Features = fun() -> + filelib:fold_files("features", ".*[.]feature", true, fun(File, Files) -> [File | Files] end, []) + end, + gurka_eunit:setup(Features, fun teardown/1). + +setup() -> + lager:start(). + +teardown(_) -> + ok. diff --git a/config/sys.config b/config/sys.config index 266026b..b590738 100644 --- a/config/sys.config +++ b/config/sys.config @@ -1,3 +1,31 @@ [ - {'consul-proxy', []} + {kernel, [ + {start_timer, true}, + {inet_default_listen_options, [{nodelay, true}, {sndbuf, 32768}, {recbuf, 32768}]}, + {inet_default_connect_options, [{delay_send, true}]} + ]}, + {sasl, [ + {sasl_error_logger, {file, "log/sasl-error.log"}}, + {errlog_type, error}, + {error_logger_mf_dir, "log/sasl"}, + {error_logger_mf_maxbytes, 10485760}, + {error_logger_mf_maxfiles, 5}, + {utc_log, true} + ]}, + {lager, [ + {colored, true}, + {handlers, [ + {lager_console_backend, [info, {lager_default_formatter, [color, time, " {", {module, "?"}, ":", {line, "?"}, "} ", pid, " [", severity, "] ", message, "\n"]}]}, + {lager_file_backend, [{file, "log/error.log"}, {level, error}, {size, 10485760}, {date, "$D0"}, {count, 5}]}, + {lager_file_backend, [{file, "log/console.log"}, {level, info}, {size, 10485760}, {date, "$D0"}, {count, 5}]} + ]}, + {crash_log, "log/crash.log"}, + {crash_log_msg_size, 65536}, + {crash_log_size, 10485760}, + {crash_log_date, "$D0"}, + {crash_log_count, 5}, + {error_logger_redirect, true} + ]}, + {'consul-proxy', [ + ]} ]. diff --git a/config/test-sys.config b/config/test-sys.config new file mode 100644 index 0000000..ab62773 --- /dev/null +++ b/config/test-sys.config @@ -0,0 +1,29 @@ +[ + {kernel, [ + {start_timer, true}, + {inet_default_listen_options, [{nodelay, true}, {sndbuf, 32768}, {recbuf, 32768}]}, + {inet_default_connect_options, [{delay_send, true}]} + ]}, + {sasl, [ + {sasl_error_logger, {file, "log/sasl-error.log"}}, + {errlog_type, error}, + {error_logger_mf_dir, "log/sasl"}, + {error_logger_mf_maxbytes, 10485760}, + {error_logger_mf_maxfiles, 5}, + {utc_log, true} + ]}, + {lager, [ + {colored, true}, + {handlers, [ + {lager_console_backend, [debug, {lager_default_formatter, [color, time, " {", {module, "?"}, ":", {line, "?"}, "} ", pid, " [", severity, "] ", message, "\n"]}]} + ]}, + {crash_log, "log/crash.log"}, + {crash_log_msg_size, 65536}, + {crash_log_size, 10485760}, + {crash_log_date, "$D0"}, + {crash_log_count, 5}, + {error_logger_redirect, true} + ]}, + {'consul-proxy', [ + ]} +]. diff --git a/config/test-vm.args b/config/test-vm.args new file mode 100644 index 0000000..dbfc87f --- /dev/null +++ b/config/test-vm.args @@ -0,0 +1,19 @@ +## Name of the node +-name consul-proxy@127.0.01 + +## Cookie for distributed erlang +-setcookie Nax7jEj7bay6ril + +## Enable kernel poll and a few async threads ++K true ++A 64 ++P 262144 + +## enable smp support +-smp auto + +## Increase number of concurrent ports/sockets +-env ERL_MAX_PORTS 16384 + +## Tweak GC to run more often +-env ERL_FULLSWEEP_AFTER 10 diff --git a/config/vm.args b/config/vm.args index 7f923d1..3394a1a 100644 --- a/config/vm.args +++ b/config/vm.args @@ -1,6 +1,19 @@ --sname consul-proxy +## Name of the node +-name ${NODE_NAME} --setcookie consul-proxy_cookie +## Cookie for distributed erlang +-setcookie ${COOKIE} +## Enable kernel poll and a few async threads +K true -+A30 ++A 64 ++P 262144 + +## enable smp support +-smp auto + +## Increase number of concurrent ports/sockets +-env ERL_MAX_PORTS 16384 + +## Tweak GC to run more often +-env ERL_FULLSWEEP_AFTER 10 diff --git a/rebar.config b/rebar.config index dee631f..506cd39 100644 --- a/rebar.config +++ b/rebar.config @@ -1,20 +1,39 @@ -{erl_opts, [debug_info]}. -{deps, []}. +{erl_opts, [{parse_transform, lager_transform}]}. -{relx, [{release, {'consul-proxy', "0.1.0"}, - ['consul-proxy', - sasl]}, +{eunit_opts, [{report, {eunit_surefire, [{dir, "_build/test"}]}}]}. - {sys_config, "./config/sys.config"}, - {vm_args, "./config/vm.args"}, +{edoc_opts, []}. - {dev_mode, true}, - {include_erts, false}, +{deps, [ + {lager, "3.0.2"}, + {tsuru, "1.0.2"}, + {vegur, {git, "https://github.com/heroku/vegur.git", {branch, "master"}}} +]}. - {extended_start_script, true}] -}. +{relx, [ + {release, {'consul-proxy', "0.1.0"}, ['consul-proxy']}, + {sys_config, "./config/sys.config"}, + {vm_args, "./config/vm.args"}, + {dev_mode, true}, + {include_erts, false}, + {extended_start_script, true}, + {overlay, [ + {copy, "apps/consul-proxy/priv/consul-proxy-wrapper", "bin/consul-proxy-wrapper"} + ]} +]}. -{profiles, [{prod, [{relx, [{dev_mode, false}, - {include_erts, true}]}] - }] -}. +{profiles, [ + {test, [ + {deps, [ + {gurka, "0.1.3"} + ]}, + {erl_opts, [debug_info, nowarn_unused_vars]} + ]}, + {prod, [ + {relx, [ + {dev_mode, false}, + {include_erts, false} + ]}, + {erl_opts, [no_debug_info, warnings_as_errors]} + ]} +]}. -- GitLab