Add a Fn::BashEnvironment function

Registered by Zane Bitter on 2013-02-21

The markup required to insert references to parameters or Fn:: calls into the UserData shell script is ugly and error-prone. An alternative is to add a function such as Fn::BashEnvironment that can be used to set up environment variables at the beginning of the script. After that, regular shell substitution can be used to actually reference the data.

You would use the function a bit like this (in JSON markup):

    { "Fn::BashEnvironment": { "DB_NAME": { "Ref": "DBName"},
                             "DB_USERNAME": {"Ref": "DBUserName"}}}

and it would expand to:

    DB_NAME="wordpress"
    DB_USERNAME="admin"

in the bash script.

The key to getting this right is to correctly escape any characters (especially double quotes) in the value that require escaping.

Blueprint information

Status:
Complete
Approver:
None
Priority:
Undefined
Drafter:
None
Direction:
Needs approval
Assignee:
None
Definition:
Superseded
Series goal:
None
Implementation:
Unknown
Milestone target:
None
Completed by
Steve Baker on 2013-06-27

Related branches

Whiteboard

Nice, a more general version might be Fn::Enviroment (no bash) as you could write your userdata in python/perl.

This works well for userdata, but less so for metadata as we are less in control of the execution of the files (and sometime they are not scripts but config).

How about a Fn::Replace as well?

From:

  "/tmp/setup.mysql" : {
      "content" : { "Fn::Join" : ["", [
      "CREATE DATABASE ", { "Ref" : "DBName" }, ";\n",
      "GRANT ALL PRIVILEGES ON ", { "Ref" : "DBName" },
      ".* TO '", { "Ref" : "DBUsername" }, "'@'localhost'\n",
      "IDENTIFIED BY '", { "Ref" : "DBPassword" }, "';\n",
      "FLUSH PRIVILEGES;\n",
      "EXIT\n"
      ]]},

  "/tmp/setup.mysql" : {
      "content" : { "Fn::Replace" : {"$DBName$", { "Ref" : "DBName"},
                                                    "$DBPassword$", { "Ref" : "DBPassword"},
                                                    "$DBUsername$", { "Ref" : "DBUsername"}},
                                                   { "Fn::Join" : ["\n", [
       "CREATE DATABASE $DBName$",
       "GRANT ALL PRIVILEGES ON $DBName$.* TO $DBUsername$'@'localhost'",
       "IDENTIFIED BY '$DBPassword$;",
       "FLUSH PRIVILEGES;",
       "EXIT"]]}}
      },

This might look bettter in yaml - just an idea.

[ZB] A generic Fn::Environment might be difficult to implement - it would need to get the right syntax and escaping for every language - but I really like the Fn::Replace idea. I'd be inclined to do that instead of the BashEnvironment idea... generic is definitely better.

Gerrit topic: https://review.openstack.org/#q,topic:bp/template-string-function,n,z

Addressed by: https://review.openstack.org/31736
    Add Fn::Variables template function.

(?)

Work Items

This blueprint contains Public information 
Everyone can see this information.

Subscribers

No subscribers.