Makefile running export env having issue

5/4/2020

I've created a Makefile to export a kubeconfig from fixed path like:

myproj
 - .kube     //folder
     config    //file which contain the config
 - Makefile.  //same level as .kube folder

Now when I'm running from the terminal the following it works, I mean if I run kubectl get ns I got results which means that it configure successfully!

export KUBECONFIG=/Users/i33333/projects/app-test/v-app/.kube/config

I've created a makefile target like following

kube-cfg:
    export KUBECONFIG=$(PWD)/.kube/config

When execute the target I see in the terminal

export KUBECONFIG=/Users/i33333/projects/app-test/v-app/.kube/config

which exactly the same as doing that manually but when when I run kubectl get ns

I got error:

error: no configuration has been provided, try setting KUBERNETES_MASTER environment variable

I dont understand why it dosent work when I run it from makefile and works when I run it from the terminal manually ? any idea I try to change and use also the $(CURRDIR) which doesnt help

update

I've tried like suggested which doesnt works

KUBECONFIG=$(PWD)/.kube/config


kube-cfg:
    export $(KUBECONFIG)

update2

If I do it like this

KUBECONFIG := $(PWD)/kube/config.yaml
tgt1:
    @export KUBECONFIG=$(KUBECONFIG) && kubectl get ns

I was able to see the ns when running the makefile tgt1: but if now I want to run it from the terminal kubectl get ns I get the same error `error: no configuration has been provided, try setting KUBERNETES_MASTER environment variable, I want to configure it from the makefile

-- Nina S
gnu-make
kubernetes
linux
makefile
shell

2 Answers

5/4/2020

The problem is that makefile recipe creates new environment, which is destroyed after finishing recipe.

If you want to use kubernetes tools after calling make, more appropriate tool in your scenario is using source command. It applies in your current environment all changes made in script passed as parameter:

$ source setupenv.sh
$ kubectl get ns # should be no problem
$ make someting # even using kubectl inside make shouldn't be a problem

However if you want to use kubectl in make scripts, then create something like:

recipe :
      source setupenv.sh && kubectl get ns
# or 
recipe2 :
      export KUBECONFIG=$(PWD)/.kube/config && kubectl get ns

UPDATE:

I thought config file is a script. So you should prepare shell script setting up environment, for example setupenv.sh:

#!/bin/bash
export KUBECONFIG=$(PWD)/.kube/config
-- Nabuchodonozor
Source: StackOverflow

5/4/2020

When you run make the recipe is executed in a shell that is forked from make process. Also-recipes spanning multiple, each line (unless chained over newline escape) also gets its own shell child process. This effectively means, whatever happens (shell variable assignments or exports) in any of these shells, has no impact on the make itself or other recipe lines.

You could define for instance a make variable (as you have done in the update) and then you can set that in an environment for any command (somecmd) you are trying to run, e.g.:

some_target:
    export KUBECONFIG=$(KUBECONFIG); somecmd

or:

some_target:
    KUBECONFIG=$(KUBECONFIG) somecmd

In that case KUBECONFIG refers to a make variable, like the one you've defined above:

KUBECONFIG := $(PWD)/.kube/config

I.e. like this:

KUBECONFIG := $(PWD)/.kube/config

all: tgt1 tgt2

tgt1:
        @export KUBECONFIG=$(KUBECONFIG); echo "KUBECONFIG is $${KUBECONFIG}"

tgt2:
        @KUBECONFIG=$(KUBECONFIG) sh -c 'echo KUBECONFIG is ${KUBECONFIG}'

Yielding:

$ make
KUBECONFIG is /tmp/.kube/config
KUBECONFIG is /tmp/.kube/config

So, if you're after something that does persists also after the make is done, you need to write it out. E.g. a wrapper, such such as:

KUBECONFIG := $(PWD)/kube/config.yaml

.PHONY: call

# run callme.sh being the first prerequisite.
call: callme.sh
    ./
lt; # creates and sets exec bit on rule target here being callme.sh callme.sh: @echo -e '#!/bin/bash\nKUBECONFIG=$(KUBECONFIG) kubectl get ns' > $@ chmod +x $@

This make you can run make and target call calls the wrapper... and you're also left with a wrapper callme.sh you can run after make is done.

-- Ondrej K.
Source: StackOverflow