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

run_cmd() outputs to terragrunt stdout #3850

Open
ThisGuyCodes opened this issue Feb 7, 2025 · 13 comments · May be fixed by #3851
Open

run_cmd() outputs to terragrunt stdout #3850

ThisGuyCodes opened this issue Feb 7, 2025 · 13 comments · May be fixed by #3851
Labels
bug Something isn't working

Comments

@ThisGuyCodes
Copy link

ThisGuyCodes commented Feb 7, 2025

Describe the bug

Using run_cmd causes the ran commands output to appear on terragrunts stdout.

Steps To Reproduce

Steps to reproduce the behavior, code snippets and examples which can be used to reproduce the issue.

Be sure that the maintainers can actually reproduce the issue. Bug reports that are too vague or hard to reproduce are hard to troubleshoot and fix.

terraform {
  source = "."
}

locals {
  _all_files = run_cmd("ls", "-p")
}

terragrunt plan, or terragrunt show -json $PLANFILE for that matter (which is my issue) will show the output of ls mixed in the stdout from terragrunt.

Demo repo is here: https://github.com/thisguycodes/terragrunt-run_cmd-bug

Expected behavior

The command given to run_cmd() has its output captured, and doesn't show on terragrunts stdout.

Versions

  • Terragrunt version: v0.72.6
  • OpenTofu/Terraform version: irrelevant
  • Environment details (Ubuntu 20.04, Windows 10, etc.): macOS 15.3

Additional context

While this generally muddies the output; specifically when I try to use terragrunt show -json $PLANFILE > tfplan.json it makes the resulting file invalid json.

@yhakbar
Copy link
Collaborator

yhakbar commented Feb 7, 2025

Use "--terragrunt-quiet" as the first argument to suppress that.

https://terragrunt.gruntwork.io/docs/reference/built-in-functions/#run_cmd

@ThisGuyCodes
Copy link
Author

How do I add that flag to terragrunt in pipelines?

Also having the command output in debug logs is useful, and that flag redacts the command output from the debug logs.

Copy link
Collaborator

yhakbar commented Feb 7, 2025

You put it in the HCL for run_cmd.

You can write to stderr from run_cmd and it won't be forwarded to HCL attributes or captured on plans, etc.

@ThisGuyCodes
Copy link
Author

ThisGuyCodes commented Feb 7, 2025

Hold up, this is intended behavior!? What possible process or problem is solved by interleaving the output of a command (whose output is returned as a value) with terragrunt's other output? It doesn't even get the prefix + formatting treatment like the rest of terragrunt's output does.

@odgrim
Copy link

odgrim commented Feb 7, 2025

Fwiw I agree that having raw stdout instead of the wrapped "INFO terraform:" stdout treatment feels inconsistent.

In normal circumstances I would expect subshelled processes to log to a parent process logger.

@ThisGuyCodes
Copy link
Author

Fwiw I agree that having raw stdout instead of the wrapped "INFO terraform:" stdout treatment feels inconsistent.

In normal circumstances I would expect subshelled processes to log to a parent process logger.

It does also do this, though only in debug logs.

@yhakbar
Copy link
Collaborator

yhakbar commented Feb 7, 2025

@ThisGuyCodes @odgrim

I totally agree that it would have been better design to start with, but this is an old HCL function, and removing the need to use "--terragrunt-quiet" as the first argument to run_cmd to get (what all three of us likely believe to be) optimal behavior is a breaking change.

We try really hard to avoid breaking changes, especially in HCL configurations, as it's a lot harder to have people to change those than CLI arguments.

What we've considered doing is simply introducing a new HCL function with better defaults and deprecating run_cmd. Something like exec, where you opt-in to debug logging. Something like:

locals {
  value = exec("echo", "hello")
  debugged_value = exec("--tg-x-debug", "echo", "hello")
}

Where the call to populate value won't trigger debug logging, and debugged_value will.

The time it makes the most sense to start talking about this kind of thing is next week, when we release experimental support for the new exec and run commands. Which are being added as part of the CLI Redesign.

In the interim, I recommend that you just consider the default way to use run_cmd the following:

run_cmd("--terragrunt-quiet", ...)

That's what I do.

@ThisGuyCodes
Copy link
Author

Oh you give the --terragrunt-quiet to run_cmd? That's a bit - unintuitive, but definitely flexible! (Does HCL support key word arguments for functions?

I do want to distinguish the concept of "debug logging" from "interleaving output" though. Currently, terragrunt will also include the output of the command in its debug logs, but with this quiet flag it will suppress the debug logs as well.

I understand not interleaving output would be a breaking change (though I would argue that "breaking changes" to the stdout have been made before. Much more significant ones at that.)

@yhakbar
Copy link
Collaborator

yhakbar commented Feb 7, 2025

@ThisGuyCodes

We really do try to to minimize them 😁

We generally only introduce breaking changes to Terragrunt terminal output if there's a significant change to the QoL of Terragrunt users that is infeasible otherwise. We're also trying to get better about giving users a way to gradually adopt breaking changes, rather than doing it all at once with Strict Mode.

HCL functions end up calling Golang functions, so we can customize the logic for any Terragrunt-native HCL function however we like (within reason)! The only functions we don't have that level of control over are OpenTofu/Terraform-native HCL functions, as we pull those in via a pinned dependency on an old version of Terraform (for now, at least).

Giving flags to the run_cmd function is convenient because it allows multiple run_cmd calls in the same unit to behave differently. That part of the design, I like.

I recommend adding debug logs to the run_cmd function using stderr when necessary.

e.g.

#!/usr/bin/env bash

>&2 echo "DEBUG: run_cmd - This won't write to stdout, and won't be pulled into the attribute run_cmd is assigned to!"

@ThisGuyCodes
Copy link
Author

I understand wanting to avoid breaking changes.

One disconnect I want to clear up: it seems you keep referring to "output on run" as "debug logging", whereas when I have been saying "debug logging" I've been referring to the debug logger, such as here: https://github.com/gruntwork-io/terragrunt/blob/main/config%2Fconfig_helpers.go#L387

Using the proper logger allows folks to enable or disable debug logging at invocation without needing to change source code. However, the way the code is currently written, I cannot suppress this output which is breaking my pipelines without also suppressing the output in debug logs.

@ThisGuyCodes
Copy link
Author

For what it's worth I'm a huge fan of mechanisms like your strict mode to introduce breaking changes! Makes me think of things like from __future__ in Python, which I'm also a big fan of

@yhakbar
Copy link
Collaborator

yhakbar commented Feb 7, 2025

I get where you're coming from, @ThisGuyCodes .

To be clear, I think it would be better design for run_cmd to:

  1. Write nothing to terminal stdout/stderr when used by default.
  2. Write stdout to the DEBUG log level when --terragrunt-log-level (soon to be --log-level) is set to debug, so that users can debug run_cmd invocations without changing HCL.
  3. Write stdout to the INFO log level when users opt in to have the function do that via an HCL flag as the first argument.
  4. Write stderr to the ERROR log level.

I think that would be a smoother and more flexible design.

We'll look to implement something like that in the future for a different HCL function like exec, which gives us the opportunity to avoid introducing any breaking changes to terminal output for existing HCL functions.

For the sake of Pipelines, you can suppress output while debugging, as I understand it. If you use a combination of --terragrunt-quiet and writing to stderr in your scripts, you'll be able to log to GitHub Actions logs, and it won't interfere with GitHub comments, or population of HCL attributes in locals, etc.

@p-hash
Copy link

p-hash commented Feb 11, 2025

I've checked a bunch of releases and it looks like the version v0.46.0 is affected, but v0.45.18 is not.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants