diff --git a/ansible/ansible.cfg b/ansible/ansible.cfg index aee8654..c8818d2 100644 --- a/ansible/ansible.cfg +++ b/ansible/ansible.cfg @@ -7,3 +7,14 @@ host_key_checking = False [ssh_connection] scp_if_ssh = smart pipelining =True + +[colors] +changed = purple +debug = dark gray +deprecate = purple +error = bright red +ok = green +skip = cyan +unreachable = red +verbose = blue +warn = bright purple diff --git a/ansible/def.ansible.mk b/ansible/def.ansible.mk index 8889927..2ac576e 100644 --- a/ansible/def.ansible.mk +++ b/ansible/def.ansible.mk @@ -27,7 +27,7 @@ ANSIBLE_SERVER_NAME ?= $(SERVER_NAME) ANSIBLE_USERNAME ?= $(USER) ANSIBLE_VERBOSE ?= $(if $(DEBUG),-vvvv,$(if $(VERBOSE),-v)) CMDS += ansible ansible-playbook -DOCKER_RUN_OPTIONS += --add-host=host.docker.internal:$(DOCKER_INTERNAL_DOCKER_HOST) +DOCKER_RUN_OPTIONS += $(if $(DOCKER_INTERNAL_DOCKER_HOST),--add-host=host.docker.internal:$(DOCKER_INTERNAL_DOCKER_HOST)) ENV_VARS += ANSIBLE_AWS_ACCESS_KEY_ID ANSIBLE_AWS_DEFAULT_OUTPUT ANSIBLE_AWS_DEFAULT_REGION ANSIBLE_AWS_SECRET_ACCESS_KEY ANSIBLE_CONFIG ANSIBLE_DISKS_NFS_DISK ANSIBLE_DISKS_NFS_OPTIONS ANSIBLE_DISKS_NFS_PATH ANSIBLE_DOCKER_IMAGE_TAG ANSIBLE_DOCKER_REGISTRY ANSIBLE_EXTRA_VARS ANSIBLE_GIT_DIRECTORY ANSIBLE_GIT_KEY_FILE ANSIBLE_GIT_REPOSITORY ANSIBLE_GIT_VERSION ANSIBLE_INVENTORY ANSIBLE_PLAYBOOK ANSIBLE_SSH_AUTHORIZED_KEYS ANSIBLE_SSH_BASTION_HOSTNAME ANSIBLE_SSH_BASTION_USERNAME ANSIBLE_SSH_PRIVATE_IP_RANGE ANSIBLE_SSH_PRIVATE_KEYS ANSIBLE_SSH_PUBLIC_HOSTS ANSIBLE_SSH_USERNAME ANSIBLE_USERNAME ANSIBLE_VERBOSE # function ansible: Call run ansible ANSIBLE_ARGS with arg 1 diff --git a/ansible/roles/docker/tasks/myos.yml b/ansible/roles/docker/tasks/myos.yml index e0d7f7b..e2e306e 100644 --- a/ansible/roles/docker/tasks/myos.yml +++ b/ansible/roles/docker/tasks/myos.yml @@ -1,10 +1,14 @@ --- # file: tasks/myos.yml -- name: myos - register myos - lookup: - file: ~/.env - register: myos +- name: myos - register myos.tags + set_fact: + myos_tags: "{{ lookup('env', 'MYOS_TAGS_JSON')|from_json or lookup('file', '~/.env') }}" + tags: debug + +- debug: + msg: "{{myos_tags|to_nice_json}}" + tags: debug - name: myos - check AWS meta-data URI uri: diff --git a/ansible/roles/hosts/files/etc/profile.d/rc_functions.sh b/ansible/roles/hosts/files/etc/profile.d/rc_functions.sh index 915e853..fadf001 100644 --- a/ansible/roles/hosts/files/etc/profile.d/rc_functions.sh +++ b/ansible/roles/hosts/files/etc/profile.d/rc_functions.sh @@ -2,7 +2,7 @@ # file rc_functions.sh: Define shell functions ## author: Yann "aya" Autissier ## license: MIT -## version: 20210620 +## version: 20210711 # function force: Run a command sine die force() { @@ -213,7 +213,7 @@ ssh_add() { else GREP_RECURSIVE_CHAR="*" fi - SSH_PRIVATE_KEYS="${SSH_PRIVATE_KEYS:-} ${dir}/id_rsa $(grep -l${GREP_RECURSIVE_FLAG:-} 'PRIVATE KEY' "${dir}"/"${GREP_RECURSIVE_CHAR:-}" 2>/dev/null |grep -vw "${dir}"/id_rsa)" + SSH_PRIVATE_KEYS="${SSH_PRIVATE_KEYS:-} ${dir}/id_rsa $(grep -l${GREP_RECURSIVE_FLAG:-} 'PRIVATE KEY' "${dir}/"${GREP_RECURSIVE_CHAR:-} 2>/dev/null |grep -vw "${dir}"/id_rsa)" done # shellcheck disable=SC2086 printf '%s\n' ${SSH_PRIVATE_KEYS} |while read -r file; do @@ -239,7 +239,7 @@ ssh_del() { else GREP_RECURSIVE_CHAR="*" fi - SSH_PRIVATE_KEYS="${SSH_PRIVATE_KEYS:-} ${dir}/id_rsa $(grep -l${GREP_RECURSIVE_FLAG:-} 'PRIVATE KEY' "${dir}"/"${GREP_RECURSIVE_CHAR:-}" 2>/dev/null |grep -vw "${dir}"/id_rsa)" + SSH_PRIVATE_KEYS="${SSH_PRIVATE_KEYS:-} ${dir}/id_rsa $(grep -l${GREP_RECURSIVE_FLAG:-} 'PRIVATE KEY' "${dir}/"${GREP_RECURSIVE_CHAR:-} 2>/dev/null |grep -vw "${dir}"/id_rsa)" done # shellcheck disable=SC2086 printf '%s\n' ${SSH_PRIVATE_KEYS} |while read -r file; do diff --git a/ansible/roles/hosts/tasks/group.yml b/ansible/roles/hosts/tasks/group.yml new file mode 100644 index 0000000..5696557 --- /dev/null +++ b/ansible/roles/hosts/tasks/group.yml @@ -0,0 +1,12 @@ +--- +# file: tasks/group.yml + +- name: group - create dns group + group: gid="11" name="dns" state="present" system="yes" + become: yes + when: ansible_os_family|lower != "alpine" + +- name: group - add me to the dns group + user: name="{{ansible_user_id}}" groups=dns append=yes + become: yes + when: ansible_os_family|lower != "alpine" and ansible_user_uid != "0" diff --git a/ansible/roles/hosts/tasks/user.yml b/ansible/roles/hosts/tasks/user.yml index b5f97c2..417df64 100644 --- a/ansible/roles/hosts/tasks/user.yml +++ b/ansible/roles/hosts/tasks/user.yml @@ -52,6 +52,7 @@ - name: user - update ~/.bashrc with_items: - PS1="╭∩╮$PS1" + - source .shrc - unset user_count process_count lineinfile: dest=~/.bashrc create=yes line='{{item}}' diff --git a/ansible/roles/hosts/tests/goss/package_alpine.yml b/ansible/roles/hosts/tests/goss/package_alpine.yml index 1738434..1deec15 100644 --- a/ansible/roles/hosts/tests/goss/package_alpine.yml +++ b/ansible/roles/hosts/tests/goss/package_alpine.yml @@ -5,6 +5,8 @@ package: installed: true groff: installed: true + ncurses: + installed: true openssh-client: installed: true py3-pip: diff --git a/ansible/roles/hosts/tests/goss/package_debian.yml b/ansible/roles/hosts/tests/goss/package_debian.yml index 31d0a0f..95b4dc2 100644 --- a/ansible/roles/hosts/tests/goss/package_debian.yml +++ b/ansible/roles/hosts/tests/goss/package_debian.yml @@ -7,8 +7,12 @@ package: installed: true openssh-client: installed: true + pass: + installed: true python-pip: installed: true + rclone: + installed: true util-linux: installed: true vim-nox: diff --git a/ansible/roles/hosts/vars/alpine.yml b/ansible/roles/hosts/vars/alpine.yml index c657076..3071f43 100644 --- a/ansible/roles/hosts/vars/alpine.yml +++ b/ansible/roles/hosts/vars/alpine.yml @@ -4,6 +4,7 @@ hosts_packages_distro: - { "name": "coreutils", "state": "present" } - { "name": "groff", "state": "present" } + - { "name": "ncurses", "state": "present" } - { "name": "openssh-client", "state": "present" } - { "name": "py3-pip", "state": "present" } - { "name": "util-linux", "state": "present" } diff --git a/ansible/roles/hosts/vars/debian.yml b/ansible/roles/hosts/vars/debian.yml index 249f521..f858e47 100644 --- a/ansible/roles/hosts/vars/debian.yml +++ b/ansible/roles/hosts/vars/debian.yml @@ -5,7 +5,9 @@ hosts_packages_distro: - { "name": "coreutils", "state": "present" } - { "name": "groff", "state": "present" } - { "name": "openssh-client", "state": "present" } + - { "name": "pass", "state": "present" } - { "name": "python-pip", "state": "present" } + - { "name": "rclone", "state": "present" } - { "name": "util-linux", "state": "present" } - { "name": "vim-nox", "state": "present" } diff --git a/make/apps/common.mk b/make/apps/common.mk index 16f5427..bd2dd02 100644 --- a/make/apps/common.mk +++ b/make/apps/common.mk @@ -62,7 +62,7 @@ connect@%: # target deploy: Fire deploy@% for ENV .PHONY: deploy -deploy: deploy@$(ENV) ## Deploy application dockers +deploy: $(if $(filter $(ENV),$(ENV_DEPLOY)),deploy-localhost,deploy@$(ENV)) ## Deploy application dockers # target down: Remove application dockers # on local host diff --git a/make/apps/def.docker.mk b/make/apps/def.docker.mk index 171b2ff..688de3c 100644 --- a/make/apps/def.docker.mk +++ b/make/apps/def.docker.mk @@ -63,8 +63,8 @@ endif ifeq ($(OPERATING_SYSTEM),Darwin) DOCKER_HOST_IFACE ?= $(shell docker run --rm -it --net=host alpine /sbin/ip -4 route list match 0/0 2>/dev/null |awk '{print $$5}' |awk '!seen[$$0]++' |head -1) DOCKER_HOST_INET ?= $(shell docker run --rm -it --net=host alpine /sbin/ip -4 addr show $(DOCKER_HOST_IFACE) 2>/dev/null |awk '$$1 == "inet" {sub(/\/.*/,"",$$2); print $$2}') -DOCKER_INTERNAL_DOCKER_GATEWAY ?= $(shell docker run --rm -it alpine getent hosts gateway.docker.internal |awk '{print $$1}' |head -1) -DOCKER_INTERNAL_DOCKER_HOST ?= $(shell docker run --rm -it alpine getent hosts host.docker.internal |awk '{print $$1}' |head -1) +DOCKER_INTERNAL_DOCKER_GATEWAY ?= $(shell docker run --rm -it alpine getent hosts gateway.docker.internal 2>/dev/null |awk '{print $$1}' |head -1) +DOCKER_INTERNAL_DOCKER_HOST ?= $(shell docker run --rm -it alpine getent hosts host.docker.internal 2>/dev/null |awk '{print $$1}' |head -1) else DOCKER_HOST_IFACE ?= $(shell /sbin/ip -4 route list match 0/0 2>/dev/null |awk '{print $$5}' |awk '!seen[$$0]++' |head -1) DOCKER_HOST_INET ?= $(shell /sbin/ip -4 addr show $(DOCKER_HOST_IFACE) 2>/dev/null |awk '$$1 == "inet" {sub(/\/.*/,"",$$2); print $$2}') diff --git a/make/apps/deploy.mk b/make/apps/deploy.mk index 2aef2f9..b1222cb 100644 --- a/make/apps/deploy.mk +++ b/make/apps/deploy.mk @@ -8,7 +8,7 @@ .PHONY: deploy@% deploy@%: myos-base build@% ## Deploy application docker images $(call make,docker-login docker-tag docker-push) - $(call make,myos-ansible-pull@$(ENV) ANSIBLE_DOCKER_IMAGE_TAG=$(VERSION) ANSIBLE_TAGS=aws AWS_ACCESS_KEY_ID=$(AWS_ACCESS_KEY_ID) AWS_SECRET_ACCESS_KEY=$(AWS_SECRET_ACCESS_KEY),,APP) + $(call make,myos-ansible-pull@$(ENV) ANSIBLE_DOCKER_IMAGE_TAG=$(VERSION) ANSIBLE_TAGS=deploy AWS_ACCESS_KEY_ID=$(AWS_ACCESS_KEY_ID) AWS_SECRET_ACCESS_KEY=$(AWS_SECRET_ACCESS_KEY),,APP) $(call make,docker-tag-latest docker-push-latest) # target deploy-hook: Fire app-deploy deploy-hook-ping @@ -27,3 +27,14 @@ deploy-hook-ping-curl: 'payload={"text": "$(DEPLOY_HOOK_TEXT)"}' \ $(DEPLOY_HOOK_URL) \ ||: ) + +# target deploy-localhost@%: Deploy application docker images +## it tags and pushes docker images to docker registry +## it runs ansible-pull on localhost to pull docker images from the registry +## it tags and pushes docker images as latest to docker registry +.PHONY: deploy-localhost +deploy-localhost: myos-base build@$(ENV) ## Deploy application docker images + $(call make,docker-login docker-tag docker-push) + $(call make,myos-ansible-pull ANSIBLE_DOCKER_IMAGE_TAG=$(VERSION) ANSIBLE_TAGS=deploy,,APP MYOS_TAGS_JSON) + $(call make,docker-tag-latest docker-push-latest) +deploy-localhost: app-deploy deploy-hook-ping diff --git a/make/apps/myos/def.mk b/make/apps/myos/def.mk index 30f315b..d7332c0 100644 --- a/make/apps/myos/def.mk +++ b/make/apps/myos/def.mk @@ -1,9 +1,15 @@ CMDS += ssh-run COMPOSE_IGNORE_ORPHANS := true -ENV_VARS += COMPOSE_IGNORE_ORPHANS DOCKER_IMAGE_CLI DOCKER_IMAGE_SSH DOCKER_NAME_CLI DOCKER_NAME_SSH +ENV_VARS += COMPOSE_IGNORE_ORPHANS MYOS_TAGS_JSON HOME ?= /home/$(USER) +MYOS_TAGS_VARS ?= env user +MYOS_TAGS_ARGS ?= $(foreach var,$(filter $(MYOS_TAGS_VARS),$(MAKE_FILE_VARS)),$(if $($(var)),$(var)='$($(var))')) +MYOS_TAGS_JSON ?= "{$(foreach var,$(filter $(MYOS_TAGS_VARS),$(MAKE_FILE_VARS)),$(if $($(var)), '$(var)': '$($(var))'$(comma))) }" NFS_DISK ?= $(NFS_HOST):/$(notdir $(SHARED)) NFS_OPTIONS ?= rw,rsize=8192,wsize=8192,bg,hard,intr,nfsvers=3,noatime,nodiratime,actimeo=3 NFS_PATH ?= /srv/$(subst $(space),/,$(strip $(call reverse,$(subst ., ,$(NFS_HOST)))))$(subst ..,,$(SHARED)) SHELL ?= /bin/sh STACK ?= base + +env ?= $(ENV) +user ?= $(USER) diff --git a/make/debug.mk b/make/debug.mk index 46c858e..834ed9d 100644 --- a/make/debug.mk +++ b/make/debug.mk @@ -8,7 +8,7 @@ debug: # target debug-%: Print value of % .PHONY: debug-% -debug-%: context-% ; +debug-%: $(if $(DEBUG),context-%) ; # target profile: Print timing informations .PHONY: profile diff --git a/make/def.docker.mk b/make/def.docker.mk index 3b7cea9..c1b0dcc 100644 --- a/make/def.docker.mk +++ b/make/def.docker.mk @@ -1,7 +1,7 @@ COMPOSE_PROJECT_NAME_MYOS ?= $(USER_ENV)_myos COMPOSE_PROJECT_NAME_NODE ?= node COMPOSE_VERSION ?= 1.29.2 -DOCKER_ENV ?= $(env.docker) +DOCKER_ENV_ARGS ?= $(docker_env_args) DOCKER_EXEC_OPTIONS ?= DOCKER_GID ?= $(call gid,docker) DOCKER_IMAGE ?= $(DOCKER_IMAGE_CLI) @@ -21,7 +21,7 @@ DOCKER_RUN_OPTIONS += --rm -it DOCKER_RUN_VOLUME += -v /var/run/docker.sock:/var/run/docker.sock DOCKER_RUN_WORKDIR ?= -w $(PWD) DOCKER_VOLUME_SSH ?= $(COMPOSE_PROJECT_NAME_MYOS)_ssh -ENV_VARS += DOCKER_NETWORK_PRIVATE DOCKER_NETWORK_PUBLIC DOCKER_REPOSITORY_MYOS DOCKER_REPOSITORY_NODE DOCKER_VOLUME_SSH +ENV_VARS += DOCKER_IMAGE_CLI DOCKER_IMAGE_SSH DOCKER_NAME_CLI DOCKER_NAME_SSH DOCKER_NETWORK_PRIVATE DOCKER_NETWORK_PUBLIC DOCKER_REPOSITORY_MYOS DOCKER_REPOSITORY_NODE DOCKER_VOLUME_SSH ifeq ($(DRONE), true) DOCKER_RUN_OPTIONS := --rm --network $(DOCKER_NETWORK) @@ -52,14 +52,14 @@ else # function exec: Exec arg 1 in docker DOCKER_NAME define exec $(call INFO,exec,$(1)) - $(RUN) docker exec $(DOCKER_ENV) $(DOCKER_EXEC_OPTIONS) $(DOCKER_RUN_WORKDIR) $(DOCKER_NAME) $(or $(1),$(SHELL)) + $(RUN) docker exec $(DOCKER_ENV_ARGS) $(DOCKER_EXEC_OPTIONS) $(DOCKER_RUN_WORKDIR) $(DOCKER_NAME) $(or $(1),$(SHELL)) endef endif # function run: Run docker run with arg 1 and docker repository 2 ## attention: arg 2 should end with slash or space define run $(call INFO,run,$(1)$(comma) $(2)) - $(RUN) docker run $(DOCKER_ENV) $(DOCKER_RUN_OPTIONS) $(DOCKER_RUN_VOLUME) $(DOCKER_RUN_WORKDIR) $(DOCKER_SSH_AUTH) $(2)$(1) + $(RUN) docker run $(DOCKER_ENV_ARGS) $(DOCKER_RUN_OPTIONS) $(DOCKER_RUN_VOLUME) $(DOCKER_RUN_WORKDIR) $(DOCKER_SSH_AUTH) $(2)$(1) endef else @@ -68,7 +68,7 @@ SHELL := /bin/bash # function docker-run DOCKER=false: Run docker image 2 with arg 1 define docker-run $(call INFO,docker-run,$(1)$(comma) $(2)) - $(RUN) docker run $(DOCKER_ENV) $(DOCKER_RUN_OPTIONS) $(DOCKER_RUN_VOLUME) $(DOCKER_RUN_WORKDIR) $(or $(2),$(DOCKER_IMAGE)) $(1) + $(RUN) docker run $(DOCKER_ENV_ARGS) $(DOCKER_RUN_OPTIONS) $(DOCKER_RUN_VOLUME) $(DOCKER_RUN_WORKDIR) $(or $(2),$(DOCKER_IMAGE)) $(1) endef # function exec DOCKER=false: Call env-exec with arg 1 or SHELL define exec @@ -92,15 +92,3 @@ define docker-volume-copy $(RUN) docker volume inspect $(to) >/dev/null 2>&1 || $(RUN) docker volume create $(to) >/dev/null $(RUN) docker run --rm -v $(from):/from -v $(to):/to alpine ash -c "cd /from; cp -a . /to" endef - -# function env-run: Call env-exec with arg 1 -define env-run - $(call INFO,env-run,$(1)) - $(call env-exec,$(or $(1),$(SHELL))) -endef - -# function env-exec: Exec arg 1 with custom env -define env-exec - $(call INFO,env-exec,$(1)) - IFS=$$'\n'; env $(env_reset) $(env) $(1) -endef diff --git a/make/def.mk b/make/def.mk index 8139cb3..793018c 100644 --- a/make/def.mk +++ b/make/def.mk @@ -40,7 +40,7 @@ CONFIG_REPOSITORY_SCHEME ?= $(shell printf '$(CONFIG_REPOSITORY_URL)\n' | CONFIG_REPOSITORY_URI ?= $(shell printf '$(CONFIG_REPOSITORY_URL)\n' |sed 's|.*://||;') CONFIG_REPOSITORY_URL ?= $(call pop,$(APP_UPSTREAM_REPOSITORY))/$(notdir $(CONFIG)) CONTEXT ?= ENV $(shell awk 'BEGIN {FS="="}; $$1 !~ /^(\#|$$)/ {print $$1}' .env.dist 2>/dev/null) -CONTEXT_DEBUG ?= MAKEFILE_LIST env env.docker APPS GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME MAKE_DIR MAKE_SUBDIRS MAKE_CMD_ARGS MAKE_ENV_ARGS UID USER +CONTEXT_DEBUG ?= MAKEFILE_LIST DOCKER_ENV_ARGS ENV_ARGS APPS GIT_AUTHOR_EMAIL GIT_AUTHOR_NAME MAKE_DIR MAKE_SUBDIRS MAKE_CMD_ARGS MAKE_ENV_ARGS UID USER DEBUG ?= DOCKER ?= $(shell type -p docker) DOCKER_RUN ?= $(if $(filter-out false False FALSE,$(DOCKER)),$(DOCKER)) @@ -50,7 +50,7 @@ DRYRUN ?= false DRYRUN_RECURSIVE ?= false ELAPSED_TIME = $(shell $(call TIME)) ENV ?= local -ENV_ARGS = $(if $(DOCKER_RUN),$(env.docker.args) $(env.docker.dist),$(env.args) $(env.dist)) +ENV_ARGS ?= $(env_args) ENV_FILE ?= $(wildcard $(CONFIG)/$(ENV)/$(APP)/.env .env) ENV_LIST ?= $(shell ls .git/refs/heads/ 2>/dev/null) ENV_RESET ?= false @@ -143,35 +143,6 @@ endif # include .env files include $(wildcard $(ENV_FILE)) -# function conf: Extract variable=value line from configuration files -## it prints the line with variable 3 definition from block 2 in file 1 -define conf - $(call INFO,conf,$(1)$(comma) $(2)$(comma) $(3)) - $(eval file := $(1)) - $(eval block := $(2)) - $(eval variable := $(3)) - [ -r "$(file)" ] && while IFS='=' read -r key value; do \ - case $${key} in \ - \#*) \ - continue; \ - ;; \ - \[*\]) \ - current_bloc="$${key##\[}"; \ - current_bloc="$${current_bloc%%\]}"; \ - [ -z "$(block)" ] && [ -z "$(variable)" ] && printf '%s\n' "$${current_bloc}" ||:; \ - ;; \ - *) \ - key=$${key%$${key##*[![:space:]]}}; \ - value=$${value#$${value%%[![:space:]]*}}; \ - if [ "$(block)" = "$${current_bloc}" ] && [ "$${key}" ]; then \ - [ -z "$(variable)" ] && printf '%s=%s\n' "$${key}" "$${value}" ||:; \ - [ "$(variable)" = "$${key}" ] && printf '%s\n' "$${value}" ||:; \ - fi \ - ;; \ - esac \ - done < "$(file)" -endef - ERROR_FD := 2 # macro ERROR: print colorized warning ERROR = \ @@ -221,6 +192,69 @@ INFO = $(if $(VERBOSE),$(if $(filter-out true,$(IGNORE_VERBOSE)), \ && printf '\n' >&$(INFO_FD) \ )) +# macro pop: Return last word of string 1 according to separator 2 +pop = $(patsubst %$(or $(2),/)$(lastword $(subst $(or $(2),/), ,$(1))),%,$(1)) + +# macro sed: Run sed script 1 on file 2 +sed = $(RUN) sed -i $(SED_SUFFIX) '$(1)' $(2) + +# macro TIME: Print time elapsed since unixtime 1 +TIME = awk '{printf "%02d:%02d:%02d\n",int($$1/3600),int(($$1%3600)/60),int($$1%60)}' \ + <<< $(shell awk 'BEGIN {current=$(or $(2),$(MAKE_UNIXTIME_CURRENT)); start=$(or $(1),$(MAKE_UNIXTIME_START)); print (current - start)}' 2>/dev/null) + +WARNING_FD := 2 +# macro WARNING: print colorized warning +WARNING = \ +printf '${COLOR_WARNING}WARNING:${COLOR_RESET} ${COLOR_INFO}$(APP)${COLOR_RESET}[${COLOR_VALUE}$(MAKELEVEL)${COLOR_RESET}]$(if $@, ${COLOR_VALUE}$@${COLOR_RESET}):${COLOR_RESET} ' >&$(WARNING_FD) \ + $(if $(2), \ + && printf '$(1) ${COLOR_HIGHLIGHT}$(2)${COLOR_RESET}' >&$(WARNING_FD) \ + $(if $(3),&& printf ' $(3)$(if $(4), ${COLOR_VALUE}$(4)${COLOR_RESET})' >&$(WARNING_FD)) \ + , \ + && $(strip $(call PRINTF,$(1)) >&$(WARNING_FD)) \ + ) \ + && printf '\n' >&$(WARNING_FD) + +# function conf: Extract variable=value line from configuration files +## it prints the line with variable 3 definition from block 2 in file 1 +define conf + $(call INFO,conf,$(1)$(comma) $(2)$(comma) $(3)) + $(eval file := $(1)) + $(eval block := $(2)) + $(eval variable := $(3)) + [ -r "$(file)" ] && while IFS='=' read -r key value; do \ + case $${key} in \ + \#*) \ + continue; \ + ;; \ + \[*\]) \ + current_bloc="$${key##\[}"; \ + current_bloc="$${current_bloc%%\]}"; \ + [ -z "$(block)" ] && [ -z "$(variable)" ] && printf '%s\n' "$${current_bloc}" ||:; \ + ;; \ + *) \ + key=$${key%$${key##*[![:space:]]}}; \ + value=$${value#$${value%%[![:space:]]*}}; \ + if [ "$(block)" = "$${current_bloc}" ] && [ "$${key}" ]; then \ + [ -z "$(variable)" ] && printf '%s=%s\n' "$${key}" "$${value}" ||:; \ + [ "$(variable)" = "$${key}" ] && printf '%s\n' "$${value}" ||:; \ + fi \ + ;; \ + esac \ + done < "$(file)" +endef + +# function env-exec: Exec arg 1 with custom env +define env-exec + $(call INFO,env-exec,$(1)) + IFS=$$'\n'; env $(env_reset) $(env_args) $(1) +endef + +# function env-run: Call env-exec with arg 1 +define env-run + $(call INFO,env-run,$(1)) + $(call env-exec,$(or $(1),$(SHELL))) +endef + # function install-app: Run 'git clone url 1 dir 2' or Call update-app with url 1 dir 2 define install-app $(call INFO,install-app,$(1)$(comma) $(2)) @@ -258,16 +292,6 @@ define make $(if $(filter true,$(DRYRUN_RECURSIVE)),$(MAKE) $(MAKE_DIR) $(patsubst %,-o %,$(MAKE_OLDFILE)) MAKE_OLDFILE="$(MAKE_OLDFILE)" DRYRUN=$(DRYRUN) RECURSIVE=$(RECURSIVE) $(MAKE_ARGS) $(cmd)) endef -# macro pop: Return last word of string 1 according to separator 2 -pop = $(patsubst %$(or $(2),/)$(lastword $(subst $(or $(2),/), ,$(1))),%,$(1)) - -# macro sed: Run sed script 1 on file 2 -sed = $(RUN) sed -i $(SED_SUFFIX) '$(1)' $(2) - -# macro TIME: Print time elapsed since unixtime 1 -TIME = awk '{printf "%02d:%02d:%02d\n",int($$1/3600),int(($$1%3600)/60),int($$1%60)}' \ - <<< $(shell awk 'BEGIN {current=$(or $(2),$(MAKE_UNIXTIME_CURRENT)); start=$(or $(1),$(MAKE_UNIXTIME_START)); print (current - start)}' 2>/dev/null) - # function update-app: Run 'cd dir 1 && git pull' or Call install-app define update-app $(call INFO,update-app,$(1)$(comma) $(2)) @@ -289,18 +313,6 @@ $(TARGET): $$(call make,$$*,,ENV_FILE) endef -WARNING_FD := 2 -# macro WARNING: print colorized warning -WARNING = \ -printf '${COLOR_WARNING}WARNING:${COLOR_RESET} ${COLOR_INFO}$(APP)${COLOR_RESET}[${COLOR_VALUE}$(MAKELEVEL)${COLOR_RESET}]$(if $@, ${COLOR_VALUE}$@${COLOR_RESET}):${COLOR_RESET} ' >&$(WARNING_FD) \ - $(if $(2), \ - && printf '$(1) ${COLOR_HIGHLIGHT}$(2)${COLOR_RESET}' >&$(WARNING_FD) \ - $(if $(3),&& printf ' $(3)$(if $(4), ${COLOR_VALUE}$(4)${COLOR_RESET})' >&$(WARNING_FD)) \ - , \ - && $(strip $(call PRINTF,$(1)) >&$(WARNING_FD)) \ - ) \ - && printf '\n' >&$(WARNING_FD) - # set ENV=env for targets ending with :env ## for each env in ENV_LIST ## it overrides value of ENV with env diff --git a/make/env.mk b/make/env.mk index 558730b..9120c4f 100644 --- a/make/env.mk +++ b/make/env.mk @@ -18,15 +18,14 @@ ifneq (,$(filter true,$(ENV_RESET))) env_reset := -i endif -env = $(env.args) $(env.dist) $(env.file) -env.docker = $(env.docker.args) $(env.docker.dist) $(env.docker.file) - -env.args = $(foreach var,$(ENV_VARS),$(if $($(var)),$(var)='$($(var))')) -env.dist ?= $(shell printenv |awk -F '=' 'NR == FNR { if($$1 !~ /^(\#|$$)/) { A[$$1]; next } } ($$1 in A)' .env.dist - 2>/dev/null) -env.file ?= $(shell cat $(or $(ENV_FILE),/dev/null) 2>/dev/null |sed '/^[ \t]*$$/d;/^[ \t]*\#/d;s/='\''/=/;s/'\''$$//;s/='\"'/=/;s/'\"'$$//;' |awk -F '=' '{print $$1"='\''"$$2"'\''"}') -env.docker.args = $(foreach var,$(ENV_VARS),$(if $($(var)),-e $(var)='$($(var))')) -env.docker.dist ?= $(shell printenv |awk -F '=' 'NR == FNR { if($$1 !~ /^(\#|$$)/) { A[$$1]; next } } ($$1 in A) {print "-e "$$0}' .env.dist - 2>/dev/null) -env.docker.file ?= $(patsubst %,--env-file %,$(wildcard $(ENV_FILE))) +docker.env.args = $(foreach var,$(ENV_VARS),$(if $($(var)),-e $(var)='$($(var))')) +docker.env.dist ?= $(shell printenv |awk -F '=' 'NR == FNR { if($$1 !~ /^(\#|$$)/) { A[$$1]; next } } ($$1 in A) {print "-e "$$0}' .env.dist - 2>/dev/null) +docker.env.file ?= $(patsubst %,--env-file %,$(wildcard $(ENV_FILE))) +docker_env_args = $(docker.env.args) $(docker.env.dist) $(docker.env.file) +env.args = $(foreach var,$(ENV_VARS),$(if $($(var)),$(var)='$($(var))')) +env.dist ?= $(shell printenv |awk -F '=' 'NR == FNR { if($$1 !~ /^(\#|$$)/) { A[$$1]; next } } ($$1 in A)' .env.dist - 2>/dev/null) +env.file ?= $(shell cat $(or $(ENV_FILE),/dev/null) 2>/dev/null |sed '/^[ \t]*$$/d;/^[ \t]*\#/d;s/='\''/=/;s/'\''$$//;s/='\"'/=/;s/'\"'$$//;' |awk -F '=' '{print $$1"='\''"$$2"'\''"}') +env_args = $(env.args) $(env.dist) $(env.file) SHELL:=/bin/bash diff --git a/make/help.mk b/make/help.mk index 9275d16..ddb41d2 100644 --- a/make/help.mk +++ b/make/help.mk @@ -9,20 +9,20 @@ blank1 blank2: # target context: Print Context and Call contexts target .PHONY: context context: - printf "${COLOR_INFO}Context:${COLOR_RESET}\n" + @printf "${COLOR_INFO}Context:${COLOR_RESET}\n" $(MAKE) contexts # target context: Fire context-% target for each CONTEXT .PHONY: contexts contexts: $(foreach var,$(CONTEXT),context-$(var)) -# target context-%: Print % value -.PHONY: context-% -context-%: - printf "${COLOR_HIGHLIGHT}%-37s${COLOR_RESET}" $* - printf "${COLOR_VALUE}" - $(call PRINTF,$($*)) - printf "${COLOR_RESET}\n" +# target context-% print-%: Print % value +.PHONY: context-% print-% +context-% print-%: + @printf "${COLOR_HIGHLIGHT}%-37s${COLOR_RESET}" $* + @printf "${COLOR_VALUE}" + @$(call PRINTF,$($*)) + @printf "${COLOR_RESET}\n" # target doc: Fire functions macros target variables doc: functions macros targets variables ; diff --git a/stack/default.mk b/stack/default.mk new file mode 100644 index 0000000..e7c6d38 --- /dev/null +++ b/stack/default.mk @@ -0,0 +1,4 @@ +default ?= memcached mysql rabbitmq redis + +# target default: Fire stack-default-up +default: stack-default-up; diff --git a/stack/services.mk b/stack/services.mk deleted file mode 100644 index e00cccd..0000000 --- a/stack/services.mk +++ /dev/null @@ -1,4 +0,0 @@ -services ?= elastic memcached mysql rabbitmq redis - -# target services: Fire stack-service-up -services: stack-services-up;