Faas: Question: how can I prevent a function from returning the same result even after rebuilding/redeploying?

Created on 10 Jul 2018  路  12Comments  路  Source: openfaas/faas

I built a little function based on the tutorial using nodejs. It returns {"status":"done"} as intended.

After changing the code, it keeps returning this data when it shouldn't.

This is more a question than a bug report: how can I make sure the latest code is used after a rebuild/redeploy?

Expected Behaviour

After changing the code, it should return different data: {"licenseKey":"<something>"}.

Current Behaviour

It keeps returning {"status":"done"} no matter how often I rebuild/redeploy.

Possible Solution

Steps to Reproduce (for bugs)

Context

Your Environment

  • Docker version docker version (e.g. Docker 17.0.05 ):

Docker version 18.06.0-ce-rc1

  • Are you using Docker Swarm or Kubernetes (FaaS-netes)?

Docker swarm

  • Operating System and version (e.g. Linux, Windows, MacOS):

Ubuntu 18.04 LTS

  • Link to your project or a code example to reproduce issue:

The code currently looks like this:

module.exports = (context, callback) => { let licenseKey = null; try { const hosts = JSON.parse(context).hosts; if (hosts.length > 0) { licenseKey = key.generate(hosts); // This simply returns a string } } catch (e) {} callback(undefined, { licenseKey }); };

question

All 12 comments

I've experienced this before as well when running on Swarm. At the time, I was able to find an issue on the docker/swarm repo, but can't seem to find it now.

What I've done to prevent that is to use version tags on the images when you re-deploy.

So, your func.yml would look like this:

functions:
  func:
    lang: node
    image: func:0.1

Then, when you update the code, also update the func.yml to a new version:

functions:
  func:
    lang: node
    image: func:0.2

Also, make sure you're running the build command after you update your code!

faas-cli build -f func.yml

then, re-deploy:

faas-cli deploy -f func.yml

Where func.yml is your function's yml file

Derek add label: question

Thanks. I defs build then deploy:

faas-cli build -f license.yml && faas-cli deploy -f license.yml

I'm gonna give your suggestion a try. It's a bit of a hassle, but if it works I'm happy for now. :)

just making sure! :smile:
I understand that it can be a bit of trouble. It's not consistent either. I haven't had it happen recently, but every once in a while it pops up again...

You're absolutely right for pointing it out. Pet peeve at previous job was 'Did you actually git push?' followed by a pause and answered with 'erm, no.' :)

Unfortunately, your suggestion doesn't prevent the problem. I can see that the image name is actually used in the build:

```Successfully built d9a3cc8f3b70
Successfully tagged license:0.3
Image: license:0.3 built.
[0] < Building license done.
[0] worker done.
Deploying: license.
Function license already exists, attempting rolling-update.

Deployed. 200 OK.
URL: http://127.0.0.1:8080/function/license


But my test command: 

curl http://127.0.0.1:8080/function/license -H 'Content-Type: application/json' --data-binary '{"hosts":["AABBCCCDDDXXX"]}'
```

still returns the old data:

{"status":"done"}

I'm actually glad you've seen this happen before. Means that I'm not going nuts. ;)

I don't know if this is of interest, but I ran a docker ps, and I noticed that the image is available, but the PORTS column is empty for this particular image:

CONTAINER ID        IMAGE                            COMMAND                  CREATED             STATUS                    PORTS                NAMES
1416a05edc29        license:0.3                      "fwatchdog"              11 minutes ago      Up 11 minutes (healthy)                        license.1.mta7jmj4i3sd6fcjao64y808u

I found the problem, and I believe apologies (from me) are in order. Turns out that my main file was called index.js and not handler.js.

It's too late to check, but either I left handler.js after the initial build (from the tutorial) and started working in the copied index.js, or faas somehow remembers it if you've used it once. I'm not sure.

Problem solved, and sorry for wasting your time @burtonr ....

No worries! Glad you got it sorted!

I can quite easily reproduce it. Which begs the question: is it expected behaviour that a faas function keeps working even when it no longer has a handler.js?

Here's how to reproduce it:

$ faas new callme --lang node
$ faas build -f callme.yml
$ faas deploy -f callme.yml

Now invoke the new function. I used curl:

$ curl http://127.0.0.1/function/callme
{"status":"done"}

Now, replace handler.js with 'index.js`, maybe change the value of the return object to 'aaaaallll done' so you would be able to see a difference, rebuild and redeploy:

$ mv callme/handler.js callme/index.js
$ faas build -f callme.yml
$ faas deploy -f callme.yml

Invoke again:

$ curl http://127.0.0.1/function/callme
{"status":"done"}

Nothing's changed...

What do you reckon? I'm happy to open a bug report if you feel that's needed. :)

Update: even removing the build directory for callme and rebuilding does not solve the problem. In fact, it happily creates handler.js, even though it's not in the source directory any more...

I think this is more of a node related thing to look for index.js if you are just specifying a directory for your handler, right? Unless you are being explicit in pointing to handler.js.

provider:
  name: faas
  gateway: http://127.0.0.1:8080

functions:
  hello:
    lang: node
    handler: ./hello <-- directory
    image: hello

Node docs:

If there is no package.json file present in the directory, then Node.js will attempt to load an index.js or index.node file out of that directory.

LOAD_AS_DIRECTORY(X)
1. If X/package.json is a file,
   a. Parse X/package.json, and look for "main" field.
   b. let M = X + (json main field)
   c. LOAD_AS_FILE(M)
   d. LOAD_INDEX(M)

Which the template has a main field pointing to handler.js, but since it isn't available it falls back to index.js.

Maybe you're right. But I honestly can't get my head around the fact that it somehow finds a handler.js and build a working function. Erm. It's no longer in the source directory... However, if everything works as intended, then I'm happy to leave it at that. :)

Was this page helpful?
0 / 5 - 0 ratings

Related issues

alexellis picture alexellis  路  7Comments

alexellis picture alexellis  路  7Comments

rorpage picture rorpage  路  7Comments

alexellis picture alexellis  路  4Comments

alexellis picture alexellis  路  6Comments