如何在 Makefile 中启动未知(但有限)数量的 lambda 函数,每个函数都有一个递增的端口号?

How do I start an unknown (but limited) number of lambda functions, each with an incremental port number, in a Makefile?

实际上,我想要这个 Makefile 配方的反面:

.PHONY: stop-lambdas # Stop the lambdas.
stop-lambdas:
    @$(MAKE) --no-print-directory --makefile LastBuildMakefile report-build
    @echo ''
    @$(MAKE) --no-print-directory lambda-stopper
    @echo ''
lambda-stopper: $(patsubst %,-stop-%,$(LAMBDAS))
$(patsubst %,-stop-%,$(LAMBDAS)):
    @$(MAKE) --no-print-directory validate-lambda lambda="$(patsubst -stop-%,%,$@)"
    @echo "Start the lambda function in lambdas/$(patsubst -stop-%,%,$@)."
    @docker stop "lambda_$(patsubst -stop-%,%,$@)">/dev/null
    @echo ''

到目前为止我有:

.PHONY: start-lambdas # Get the lambdas up and running to allow you to make calls to them.
start-lambdas:
    @$(MAKE) --no-print-directory --makefile LastBuildMakefile report-build
    @echo ''
    @$(MAKE) --no-print-directory lambda-starter
    @echo ''
lambda-starter: $(patsubst %,-start-%,$(LAMBDAS))
$(patsubst %,-start-%,$(LAMBDAS)):
    @$(MAKE) --no-print-directory validate-lambda lambda="$(patsubst -start-%,%,$@)"
    @echo "Start the lambda function in lambdas/$(patsubst -start-%,%,$@)."
    @docker run --detach --name "lambda_$(patsubst -start-%,%,$@)" --publish XXXXXXX:8080 --rm "${CONTAINER_GROUP}/lambda_$(patsubst -start-%,%,$@):${LAST_CONTAINER_TAG_BRANCH}_${LAST_CONTAINER_TAG_VERSION}" > /dev/null
    @echo ''

我无法解决的一点是如何定义 XXXXXXX

对此我有 2 个想法。

  1. 简单(我希望)为每个 lambda 函数增加一个从 49900 开始的 var(目前大约有 10 个,还可以向该项目添加更多,但不足以耗尽端口号).

  2. 定义端口号列表(手动定义 - 每个 lambda 函数 1 个),然后以编程方式确定每个 lambda_$(patsubst -start-%,%,$@)

    使用哪个 var

我可以在以下的 Makefile 中硬编码设置:

QUEUE_PORT_NUMBER=49901
QUEUE_ADMIN_PORT_NUMBER=49902
QUEUE_API_PORT_NUMBER=49903
...

在玩:

    LAMBDA_PORT_NUMBER_VAR_NAME=$(patsubst -start-%,%,$@)_PORT_NUMBER; echo $${LAMBDA_PORT_NUMBER_VAR_NAME^^};

输出:

QUEUE_PORT_NUMBER
QUEUE_ADMIN_PORT_NUMBER
QUEUE_API_PORT_NUMBER
...

所以我可以通过编程方式定义具有端口号的变量。 我无法解决的是如何使用变量名称获取变量,然后从中获取值到我的食谱中。

一些额外的想法:

  1. 端口号与 运行 运行 无关。我将显示分配的端口。我希望它们在多个 make start-lambdas.
  2. 之间保持一致
  3. 这仅供本地开发人员在本地执行 lambda 并允许他们 运行 测试...所有本地。
  4. 当我们依次对每个 lambda 进行 运行 单元测试时,已经使用了 docker 附加和分离。目前每次都使用端口 49990。我们向 运行ning(但已分离)lambda 发出大量 curl 请求,验证结果,然后终止 lambda,然后继续下一个。所以这一切都有效。

我们只想同时启动和 运行ning 所有 lambda。

不确定我是否了解所有细节。假设您要为每个 -start-lambda 定义一个从 49901 开始的数字,并且您希望每次调用 make 时此数字都相同。我们可以使用 join GNU make 函数从您的 -start-lambda 列表和计算的数字列表中 assemble 一个 -start-lambda-number 标记列表。我们将令牌列表存储在 make 变量 TOKEN.

在下文中,我们还将使用 make 变量 (STARTER) 和配方中的 shell 变量 (lambda) 分解当前 Makefile 的几个语句。对于后者,有两个重要方面需要记住:

  • make 在将配方传递给 shell 之前对其进行扩展。因此,当使用 shell 变量的值时,我们必须写 $$lambda(或 $$number)而不是 $lambda。在 make 扩展后它将变成 $lambda,我们要传递给 shell,而不仅仅是 ambda.

  • 配方的每一行由不同的shell执行。为了在多个配方行中使用 shell 变量,我们必须将它们与 ;(或 &&,如您所愿)连接在一起,以便它们成为一行,由一个单独执行shell。但为了更好的可读性,我们可以使用行继续(尾随 \)。

给定 -start-lambda 目标的编号在配方中提取并存储在第二个 shell 变量 (number) 和 $(patsubst $@-%,%,$(filter $@-%,$(TOKEN))) 中,即找到具有函数 filter 的相应标记并使用 patsubst.

提取数字
LAMBDAS := a b c d
STARTER := $(patsubst %,-start-%,$(LAMBDAS))
NUMBER  := $(shell seq 49901 `expr 49900 + $(words $(STARTER))`)
TOKEN   := $(join $(addsuffix -,$(STARTER)),$(NUMBER))

.PHONY: start-lambdas # Get the lambdas up and running to allow you to make calls to them.

start-lambdas:
    @$(MAKE) --no-print-directory --makefile LastBuildMakefile report-build
    @echo ''
    @$(MAKE) --no-print-directory lambda-starter
    @echo ''

lambda-starter: $(STARTER)

$(STARTER):
    @lambda="$(patsubst -start-%,%,$@)"; \
    number="$(patsubst $@-%,%,$(filter $@-%,$(TOKEN)))"; \
    $(MAKE) --no-print-directory validate-lambda lambda="$$lambda"; \
    echo "Start the lambda function in lambdas/$$lambda."; \
    docker run --detach --name "lambda_$$lambda" --publish "$$number:8080" --rm "${CONTAINER_GROUP}/lambda_$$lambda:${LAST_CONTAINER_TAG_BRANCH}_${LAST_CONTAINER_TAG_VERSION}" > /dev/null
    @echo ''

请记住,$$ 和续行(尾部 ; \)对于保证 shell 变量 lambda 和 [=29 的正确扩展是必不可少的=],以及它们在食谱所有行中的可用性。

注意:这仅在 $(filter $@-%,$(TOKEN))) returns 只有一个令牌时有效。如果你有两个名为 foofoo-bar 的 lambda,则相应的标记将是,例如,-start-foo-49901-start-foo-bar-49907 并且对于目标 -start-foo 两者都将匹配 $@-%。因此,如果您有这样的 lambda 名称,请更改 -start-lambda 部分和数字之间的分隔符。例如,如果您的 lambda 名称中没有 | 个字符,请使用 | 而不是 -

带有简化虚拟示例的演示:

$ cat Makefile
LAMBDA  := a b c d
STARTER := $(patsubst %,-start-%,$(LAMBDA))
NUMBER  := $(shell seq 49901 `expr 49900 + $(words $(STARTER))`)
TOKEN   := $(join $(addsuffix -,$(STARTER)),$(NUMBER))

.PHONY: lambdas-starter $(STARTER)

lambda-starter: $(STARTER)

$(STARTER):
    @lambda="$(patsubst -start-%,%,$@)"; \
    number="$(patsubst $@-%,%,$(filter $@-%,$(TOKEN)))"; \
    echo "Start the lambda function in lambdas/$$lambda with $$number."

$ make
Start the lambda function in lambdas/a with 49901.
Start the lambda function in lambdas/b with 49902.
Start the lambda function in lambdas/c with 49903.
Start the lambda function in lambdas/d with 49904.

Renaud Pacalet 回答 - 非常感谢。

我采纳了他的回答并根据我的需要对其进行了进一步调整。

下面是一个改编版本,用于显示已记录的 Makefile 目标列表,以及报告 lambda 列表和将用于测试的端口号。

LAMBDAS := $(notdir $(wildcard ./src/lambdas/*))
PORT_NUMBERS := $(shell seq 49901 `expr 49900 + $(words $(LAMBDAS))`)
LAMBDA_TOKENS := $(join $(addsuffix -,$(LAMBDAS)),$(PORT_NUMBERS))

START_LAMBDAS := $(patsubst %,-start-%,$(LAMBDA_TOKENS))
LIST_LAMBDAS := $(patsubst %,-list-%,$(LAMBDA_TOKENS))

.PHONY: list # Generate list of targets
.PHONY: $(LIST_LAMBDAS)
list:
    @grep '^.PHONY: .* #' $(MAKEFILE_LIST) | sort | sed 's/^.*\.PHONY: \(.*\) # \(.*\)/   /' | expand -t16
    @echo ''
    @echo 'The list of lambda functions known to this Makefile are:'
    @echo ''
    @$(MAKE) --no-print-directory list-lambdas
    @echo ''
list-lambdas:$(LIST_LAMBDAS)
$(LIST_LAMBDAS):
    @token=$(filter $(patsubst -list-%,%,$@),$(LAMBDA_TOKENS)); \
    parts=($${token//-/ }); \
    echo "  src/lambdas/$${parts[0]}    Will use port number $${parts[1]} for testing."| expand -t26

这输出:

$ make list
build           Build the containers
list            Generate list of targets
test            Test the containers
check-container Check the version of Node in the AWS NodeJS container
clean           Remove images, logs, NodeJS cache, node_modules, and built distributions
npm-ci          Run `npm ci` for the lambda functions using the AWS NodeJS container
npm-update      Run `npm update` for the lambda functions using the AWS NodeJS container
shell           Get a bash shell prompt using the AWS NodeJS container, with the current directory mounted in /srv/queue

The list of lambda functions known to this Makefile are:

  src/lambdas/api         Will use port number 49901 for testing.
  src/lambdas/queue       Will use port number 49902 for testing.
  src/lambdas/queue_admin Will use port number 49903 for testing.
  src/lambdas/rendering   Will use port number 49904 for testing.
  src/lambdas/reporting   Will use port number 49905 for testing.
  src/lambdas/schedules   Will use port number 49906 for testing.

所以我现在有一对 lambda 和端口号,然后用它来构建 Makefile 的目标。懂Makefile的当然可以理解!