Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dictionaries/Maps/Lookup Tables in Makefiles

I need to create a lookup table/dictionary/map in my Makefile to look up key-value information.

I have been trying to use ifeq statements to do the same thing but my statements seem to fail:

# this gets the account id from the current user's ARN, you must have the AWS CLI and jq installed
AWS_ACCOUNT_ID:=$(shell aws iam get-user | jq -r '.User.Arn' | awk -F ':' '{print $$5;}')

# define a friendly account name for output
ifeq ($(AWS_ACCOUNT_ID), 123456)
AWS_ACCOUNT_FRIENDLY:=staging
endif

ifeq ($(AWS_ACCOUNT_ID), 789012)
AWS_ACCOUNT_FRIENDLY:=preprod
endif

ifeq ($(AWS_ACCOUNT_ID), 345678)
AWS_ACCOUNT_FRIENDLY:=production
endif

It seems to only work with the first value 123456 but not with others.

Is there a way to define a dictionary/map in Make to simply look up the account friendly name by the key of the account id?

like image 742
Naftuli Kay Avatar asked Dec 01 '16 20:12

Naftuli Kay


2 Answers

Build and configuration management is becoming a programming task on its own. Unluckily the tools to do that are lacking coherency and broadness of acceptance. Teams often end up rolling their own scripting zoo to glue build, test and release together. If you want to avoid some of the dilution coming with make and necessary helper scripts outside of it, you can use gmtt which allows table selection for those kinds of tasks you want to complete with onboard GNUmake calls:

include gmtt/gmtt.mk

AWS_ACCOUNT_ID:=$(shell aws iam get-user | jq -r '.User.Arn' | awk -F ':' '{print $$5;}')

# define a table of 3 columns: <AWS-id> <name> <admin>                                                          
define AWS_ACCOUNT_TBL                                                                                          
3                                                                                                               
123456   staging      kay                                                                                       
789012   preprod      catbert                                                                                   
345678   production   pointyhairedboss                                                                          
endef                                                                                                           

# select column 2 & 3 from table AWS_ACCOUNT_TBL where column 1 string-equals AWS_ACCOUNT_ID                    
AWS_ACCOUNT := $(call select,2 3,$(AWS_ACCOUNT_TBL),$$(call str-eq,$$1,$(AWS_ACCOUNT_ID)))                     

AWS_NAME := $(word 1,$(AWS_ACCOUNT))                                                                            
ADMIN := $(word 2,$(AWS_ACCOUNT))                                                                               

$(info AWS account $(AWS_NAME) administered by $(ADMIN))
like image 98
Vroomfondel Avatar answered Nov 09 '22 03:11

Vroomfondel


I can't explain why you don't see the behavior you expect: I would verify that the value of AWS_ACCOUNT_ID is what you expect: maybe your shell script is not doing what you want. Try adding something like:

AWS_ACCOUNT_ID := $(shell ...)
$(info AWS_ACCOUNT_ID = '$(AWS_ACCOUNT_ID)')

and see what you get.

However related to your more general question, I prefer to use constructed macro names when dealing with situations like this, instead of lots of ifeq values:

AWS_123456_FRIENDLY := staging
AWS_789012_FRIENDLY := preprod
AWS_345678_FRIENDLY := production


AWS_ACCOUNT_ID := $(shell ...)

AWS_ACCOUNT_FRIENDLY := $(AWS_$(AWS_ACCOUNT_ID)_FRIENDLY)
like image 18
MadScientist Avatar answered Nov 09 '22 02:11

MadScientist