0

In the below code snippet:

IMAGES_TO_DELETE := $(aws ecr list-images --region $(ECR_REGION) --repository-name $(ECR_REPO) --filter "tagStatus=UNTAGGED" --query 'imageIds[*]' --output json)

.PHONY: target1 target2 cleanimage

cleanimage:
    ${DISPLAYINFO} "Clean untagged image from AWS ECR "
    aws ecr batch-delete-image --region $(ECR_REGION) --repository-name $(ECR_REPO) --image-ids "$(IMAGES_TO_DELETE)" || true
    ${DISPLAYINFO} "Done"

target1:
   # do something

target2:
   # do something

IMAGES_TO_DELETE gives imagelist, in JSON format.

IMAGES_TO_DELETE supposed to be assigned when make cleanimage executes

How to assign values to a variable under cleanimage target?

overexchange
  • 15,768
  • 30
  • 152
  • 347

2 Answers2

1

You seem to have a continuing misunderstanding about make variables.

It's not clear why this needs to be a variable at all. Just inline it into the target:

.PHONY: cleanimage

cleanimage:
    ${DISPLAYINFO} "Clean untagged image from AWS ECR "
    aws ecr batch-delete-image --region $(ECR_REGION) --repository-name $(ECR_REPO) \
        --image-ids "$$(aws ecr list-images --region $(ECR_REGION) --repository-name $(ECR_REPO) \
            --filter "tagStatus=UNTAGGED" --query 'imageIds[*]' --output json)" || true
    ${DISPLAYINFO} "Done"

As an aside $(aws...) is not a valid make function; you mean $(shell aws ...); but again, there is no need to evaluate this in make at all if it is only needed in a single target.

Where you have repeated information, that's where it makes sense to refactor that into a variable so you only have to change it in one place.

ECRFLAGS := --region $(ECR_REGION) --repository-name $(ECR_REPO)

.PHONY: cleanimage

cleanimage:
    ${DISPLAYINFO} "Clean untagged image from AWS ECR "
    aws ecr batch-delete-image $(ECRFLAGS) \
        --image-ids "$$(aws ecr list-images $(ECRFLAGS) \
            --filter "tagStatus=UNTAGGED" --query 'imageIds[*]' --output json)" || true
    ${DISPLAYINFO} "Done"

Remember, a single dollar sign is evaluated by make. If you want to pass through a literal dollar sign to the shell, you need to double it.

tripleee
  • 175,061
  • 34
  • 275
  • 318
  • Why `$$(aws...` ? `$(aws...` is used in bash – overexchange Jan 24 '20 at 11:21
  • Because this is not Bash, this is Make. To pass through a literal dollar sign from `make` to the shell, you have to double it. – tripleee Jan 24 '20 at 11:22
  • In bash we use `$?` to get the exit code of any command. In make, how to get the exit code of above AWS command? – overexchange Jan 24 '20 at 14:23
  • We mostly don't (see https://stackoverflow.com/questions/36313216/why-is-testing-to-see-if-a-command-succeeded-or-not-an-anti-pattern) but you cad do something like `if json=$$(aws blah klah); then aws blab blab "$$json"; fi` If you set `SHELL=/bin/bash` you can use `PIPESTATUS` and other Bash extensions but this obviously wrecks the portability of your `Makefile`. – tripleee Jan 24 '20 at 17:14
0

Make variables must always be surrounded with parens or braces. If not, then only the next character is part of the variable.

So when you write $ECR_REGION, make will expand the variable $E (which is probably empty) then append the string CR_REGION. Not what you want.

You must write $(ECR_REGION) (or ${ECR_REGION} if you prefer: they're equivalent to make).

Ditto for $(ECR_REPO) and $(IMAGES_TO_DELETE).

See https://www.gnu.org/software/make/manual/html_node/Reference.html

MadScientist
  • 92,819
  • 9
  • 109
  • 136