0

I am writing a Deployment Manager script which creates a Cloud Function and sets some environment variables.

Everything works well apart from the fact that one of my properties/variables is not recognized by the Deployment Manager correctly. I keep on getting an error.

I have a property is-local that I supply from CMD line.

Its value needs to be false/true or I can also live with yes/no.

In the schema file if I specify the property as boolean and supply the value as false/true then the deployment starts and only the Cloud Function component fails with an error. I have specified the error as Error#1 below.

if I specify the property as string and supply the value as false/true then the deployment starts but fails immediately with an error. I have specified the error as Error#2 below.

main.jinja

{% set PROJECT_NAME = env['project'] %}
{% set CODE_BUCKET = properties['code-bucket'] %}
{% set IS_LOCAL = properties['is-local'] %}

resources:
- name: create-cf
  type: create_cloud_function.jinja
  properties:
    name: test-cf
    project: {{ PROJECT_NAME }}
    region: europe-west1
    bucket: {{ CODE_BUCKET }}
    runtime: nodejs10
    entryPoint: test
    topic: test
    environmentVariables: { 'CODE_BUCKET': {{ CODE_BUCKET }}, 'IS_LOCAL': {{IS_LOCAL}} }

main.jinja.schema

imports:
- path: create_cloud_function.jinja

required:
- code-bucket
- is-local

properties:
  code-bucket:
    type: string
    description: Name of the code bucket to host the code for Cloud Function.
  is-local:
    type: boolean
    description: Will Cloud Function run locally or in cloud.

create_cloud_function.jinja

{% set codeFolder = properties['name'] %}
{% set environmentVariables = properties['environmentVariables'] %}

resources:
#- type: cloudfunctions.v1.function
- type: gcp-types/cloudfunctions-v1:projects.locations.functions
  name: {{ properties['name'] }}
  properties:
    parent: projects/{{ properties['project'] }}/locations/{{ properties['region'] }}
    location: {{ properties['region'] }}
    function: {{ properties['name'] }}
    sourceArchiveUrl: gs://$(ref.{{ properties['bucket'] }}.name)/{{ codeFolder }}.zip
    entryPoint: {{ properties['entryPoint'] }}
    runtime: {{properties['runtime']}}
    eventTrigger:
      resource: $(ref.{{ properties['topic'] }}.name)
      eventType: providers/cloud.pubsub/eventTypes/topic.publish
    environmentVariables:
      {% for key, value in environmentVariables.items() %}
        {{ key }} : {{ value }}
      {% endfor %}

Deployment Manager CMD

gcloud deployment-manager deployments create setup --template main.jinja --properties code-bucket:something-random-test-code-bucket,is-local:false

Error#1: - when the property type is boolean in schema file

{"ResourceType":"gcp-types/cloudfunctions-v1:projects.locations.functions","ResourceErrorCode":"400","ResourceErrorMessage":{"code":400,"message":"Invalid value at 'function.environment_variables[1].value' (TYPE_STRING), false","status":"INVALID_ARGUMENT","details":[{"@type":"type.googleapis.com/google.rpc.BadRequest","fieldViolations":[{"field":"function.environment_variables[1].value","description":"Invalid value at 'function.environment_variables[1].value' (TYPE_STRING), false"}]}],"statusMessage":"Bad Request","requestPath":"https://cloudfunctions.googleapis.com/v1/projects/someproject/locations/europe-west1/functions","httpMethod":"POST"}}

Error#2: - when the property type is string in schema file

errors:
- code: MANIFEST_EXPANSION_USER_ERROR
  location: /deployments/setup/manifests/manifest-1571821997285
  message: |-
    Manifest expansion encountered the following errors: Invalid properties for 'main.jinja':
    True is not of type 'string' at ['is-local']
     Resource: main-jinja Resource: config

Any idea whats the issue here...

niklodeon
  • 1,320
  • 5
  • 20
  • 51

4 Answers4

0

I'm unfamiliar with jinja but from my understanding, environment variables cannot be anything else but strings.

Said this, reading Error#1 I'd conclude that, effectively, the var type has to be string.

Then, at the second error we can clearly see that you are trying to put a boolean into a string.

So yeah, you have to play with true / false as strings.

Jesús Fuentes
  • 919
  • 2
  • 11
  • 33
  • I have tried `true`, `'true'`, `"true"`, `yes`, `"yes"`, `'yes'`, 0, `"0"`, `'0'` but nothing seems to be working... It seems to be detecting everything as Boolean and gived the Error#2 – niklodeon Oct 23 '19 at 14:49
  • If you try 'false' it shows exactly `True is not of type 'string' at ['is-local']` ? – Jesús Fuentes Oct 23 '19 at 15:25
  • What I meant was that I have tried all possible combination of true/false, yes/no, 0/1 but they all fail with the error that they are not of type string... Not sure how to fix this... If I make the property Boolean it still fails and if it's string it fails as well. Seems pretty strange to me... – niklodeon Oct 23 '19 at 16:48
  • using the double quotes should have worked within jinja. I suspect that the gcloud command is not passing the double quotes to the jinja temlplate. If you edit the main.jinja template and use double quotes for the value (such as "true"), do you still get the same error? – Patrick W Nov 01 '19 at 18:35
0

You can define set the value as a string within the jinja file itself. See this post for some details and this page that provides different methods you can use.

In your case, you can edit the create_cloud_function.jinja file and change:

    environmentVariables:
      {% for key, value in environmentVariables.items() %}
        {{ key }} : {{ value }}

to:

    environmentVariables:
      {% for key, value in environmentVariables.items() %}
        {{ key }} : {{ value|string }}

Once the manifest is fully expanded, the value should be considered a string for the purpose of the API call to the Cloud Functions API

Patrick W
  • 4,603
  • 1
  • 12
  • 26
  • doesn't seems to be working. Now I have `is_local` as **Boolean** in **main.jinja.schema** & updated the code as per ur suggestion but getting the same **Error#1**. – niklodeon Nov 04 '19 at 09:00
0

Eventually what I had 2 do was pass IS_LOCAL: '''false'''from the command line and {{ key }} : {{ value }} in my jinja file.

niklodeon
  • 1,320
  • 5
  • 20
  • 51
-1

According to this documentation about Using environment variables in Jinja, you should use the following syntax to add an environment var to your templates:

{{ env["deployment"] }} # Jinja

And they show the following example:

- type: compute.v1.instance name: vm-{{ env["deployment"] }} properties: machineType: zones/us-central1-a/machineTypes/f1-micro serviceAccounts: - email: {{ env['project_number'] }}-compute@developer.gserviceaccount.com scopes: - ...

Given that you are providing the value of is-local from CMD line, and according to this documentation:

Boolean values are case insensitive, so TRUE, true, and True are treated the same.

AND

To specify multiple properties, provide comma-separated key:value pairs. It does not matter in what order you specify the pairs. For example:

`gcloud deployment-manager deployments create my-igm

--template vm_template.jinja 

--properties zone:us-central1-a,machineType:n1-standard-1,image:debian-9`

You should use TRUE, true, or True for is-local param.

Joss Baron
  • 1,441
  • 10
  • 13
  • 1) I talked about having problems in setting up environment variable for Cloud Functions and not problem with using environment variables in my jinja script. 2) As I have explained in my question that if I set the property type to Boolean and supply any form of true it doesn't work. If I change the property type to string and supply any form of true it also doesn't work... – niklodeon Oct 24 '19 at 03:23