Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvement: allow triple quoted strings within JSON body #317

Open
sparrowt opened this issue Oct 5, 2022 · 2 comments
Open

Improvement: allow triple quoted strings within JSON body #317

sparrowt opened this issue Oct 5, 2022 · 2 comments

Comments

@sparrowt
Copy link

sparrowt commented Oct 5, 2022

Firstly thank you for this excellent provider! I'm filing this to track a desirable feature, but appreciate that (like me!) you may well have no desire or time to implement it. Nevertheless perhaps someone else or one of us will in future.

Summary: it would be really handy if the body of certain resources (e.g. watchers) was allowed to contain triple-quoted strings in the format sometimes returned by Elastic via Kibana dev tools (e.g. to allow multi-line strings within JSON, delimited by """).

For example, to include a non-trivial amount of detail in the email action > body > html then you have to write it all on one line e.g. like this, which gets unwieldy to edit and for source control etc:

resource "elasticsearch_xpack_watch" "my-watcher" {
  watch_id = "my-watcher-id"
  body = <<EOF
{
  ...
  "actions": {
    "email_people": {
      "email": {
        ...
        "body": {
          "html": "<p>Some details:</p><ul>{{#ctx.payload.aggregations.foo.buckets}}<li>{{bar}}</li>{{/ctx.payload.aggregations.foo.buckets}}</ul> \n\n <p>Other details:</p><ul>...</ul> \n\n etc..."
        }
      }
    }
  }
}
EOF
}

It would be amazing if we could instead do this:

resource "elasticsearch_xpack_watch" "my-watcher" {
  watch_id = "my-watcher-id"
  body = <<EOF
{
  ...
  "actions": {
    "email_people": {
      "email": {
        ...
        "body": {
          "html": """
<p>Some details:</p>
<ul>
{{#ctx.payload.aggregations.foo.buckets}}
  <li>{{bar}}</li>
{{/ctx.payload.aggregations.foo.buckets}}
</ul>

<p>Other details:</p>
<ul>...</ul>

etc...
"""
        }
      }
    }
  }
}
EOF
}

Currently this fails due to ValidateFunc being set to validation.StringIsJSON e.g. in the case of elasticsearch_xpack_watch that is here: https://github.com/phillbaker/terraform-provider-elasticsearch/blob/v2.0.4/es/resource_elasticsearch_xpack_watch.go#L27

@sparrowt
Copy link
Author

sparrowt commented Oct 5, 2022

A very similar case is the embedded JSON needed in the body of the webhook action.

Workaround

For now (and this should work for the email html body too I imagine) my workaround is to use templatefile (to load multi-line JSON as a string) followed by Terraform's format with %q` to escape it for inclusion within a string, e.g. like this:

resource "elasticsearch_xpack_watch" "my-watcher" {
  watch_id = "my-watcher-id"
  body = templatefile(
    "${path.module}/my-watcher-template.tftpl",
    {
      secret_teams_webhook_path = ...
      teams_webhook_body_json_escaped = format("%q", templatefile(
        "${path.module}/my-webhook-body-teams.tftpl",
        {
          teams_title = "Thing X went wrong"
        }
      ))
    }
  )
}

with my-watcher-template.tftpl defining the majority of the watcher JSON definition e.g:

{
  ...
  "actions": {
    "webhook_1": {
      "webhook": {
        "host": "...",
        "port": 443,
        "path": "${secret_teams_webhook_path}",
        "method": "post",
        "scheme": "https",
        "body": ${teams_webhook_body_json_escaped}
      }
    }
  }
}

but with the webhook body interpolated from the escaped contents of my-webhook-body-teams.tftpl where you can define your webhook JSON body unescaped and over multiple lines e.g:

{
  "@type": "MessageCard",
  "@context": "https://schema.org/extensions",
  "summary": "${teams_title}",
  "themeColor": "0078D7",
  "sections": [
    {
      "activityTitle": "${teams_title}"
    }
  ],
  ...
}

Note that the string produced by format includes the opening & closing " quotes so in the watcher template you do "body": ${teams_webhook_body_json_escaped} rather than "body": "${teams_webhook_body_json_escaped}".

@phillbaker
Copy link
Owner

@sparrowt thanks for opening the issue - I have wished for the triple quoted strings as well. Your approach is a valid workaround.

I think my general suggestion for a workaround would be to use HCL to build the objects and convert that to JSON, e.g.:

body = jsonencode({
  test = {
    "is_write_index" = true
  }
  foo = <<-EOT
  hello new 
    line world
  EOT
})

One potential way to implement this directly is to use a extension of JSON like JSON5. However, the public go implementations I saw were all archived, e.g. https://github.com/flynn/json5.

I think a helpful outcome of this issue would be to document these two workarounds as suggested approaches.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants