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

Provide access to module name on runner #165

Closed
anurodh-ti opened this issue Jun 20, 2022 · 12 comments · Fixed by #171
Closed

Provide access to module name on runner #165

anurodh-ti opened this issue Jun 20, 2022 · 12 comments · Fixed by #171
Labels
enhancement New feature or request

Comments

@anurodh-ti
Copy link

Can we get present modules information while parsing through the terraform code through tflint?
We need to find for each resource in which module that resource is made because same resource name can be present in different modules.

@bendrucker bendrucker closed this as not planned Won't fix, can't repro, duplicate, stale Jun 20, 2022
@bendrucker
Copy link
Member

Request is unclear, more info (eg examples) needed. TFLint module inspection already only emits issues tied to module variables and should report the attribute in a module call as the associated range in the code.

@anurodh-ti
Copy link
Author

For each resource in a module, we are trying to map that resource with its AWS ID. Since different modules could have same resource name, for every AWS id we need both resource name and module in which that resource is present (this pair is unique).
Can tflint help us map for all modules present in terraform template, module names with all resources names that module has?

@bendrucker
Copy link
Member

Can you include an example of output you're getting now that's ambiguous?

@sabhya-ti
Copy link

sabhya-ti commented Jun 21, 2022

Hello. I am working alongside Anurodh (the guy that started the thread) in developing a custom plugin for TfLint. I hope to make you better understand the issue that we are facing together.
when tflint is called with --module (i.e. in module inspection mode)
then the list of resources obtained by runner.getResourceContent in the Check function [link] may contain two resources [link1], [link2] with the same terraform reference name ("showcase-1") in this case belonging to different modules [link1], [link2]. My Check function needs to be able to distinguish between resources with the same terraform reference name from multiple modules, and I'm looking for a way to accomplish that.

// The functions below are not available in the check function and I'd like to know how else to accomplish that effect.
// resource.getModuleName() //should return "server-1" and "server-2" respectively if I run module inspection
// resrouce.getModulePath() //should give the path of the directory in which the resource under inspection is present

I hope I have been clear now. Thank you in advance for helping out.

@bendrucker bendrucker transferred this issue from terraform-linters/tflint Jun 21, 2022
@bendrucker bendrucker changed the title Module Name Provide access to module name on runner Jun 21, 2022
@bendrucker bendrucker reopened this Jun 21, 2022
@bendrucker
Copy link
Member

Ok, this is a starting point.

We'd still want to know why you're looking for the address relative to the root module. It could be made available from the runner but it's not obvious why it should be. That's where we need you to make the case.

When errors are emitted for module calls, they must be associated with some var set in the module call. The location that is reported by TFLint is the attribute that sets the variable in the module call itself. This is meant to free rules from needing to embed optional module information in the issues they return.

Additionally, each module gets its own runner. Similar to Terraform providers, in practice each plugin is one process, so if you had a global map[tflint.Runner]interface{} you could track things across modules. But that's a contrived solution to a problem I'm still not understanding.

@sabhya-ti
Copy link

Thank you for taking the time to reach out Ben. The plugin that I am hoping to develop--the conditions that it is going to use to emit issues differs from resource to resource.
For example: module.server-1.showcase-1 should emit an issue when the instance_type is not "t2.micro", but module.server-2.showcase-1 should emit an issue when the instance type is not "t2.large".
I need a way to uniquely identify the resource blocks. Using just the terraform reference name ("showcase-1") in this case does not suffice as it is not unique across all modules, it is only unique across the module. However, server-1.showcase-1 and server-2.showcase-1 is unique. But there is no way that I have been able to find that lets me associate server-1 (the terraform reference name for that module) or server-2 with the resource blocks present in their modules. If I'm able to do that, my job would be done.
Thank you again for writing back.

@bendrucker
Copy link
Member

Per the above explanation, this is already handled. You emit issues on an expression containing a variable in the module, TFLint automatically associates them with the attribute in the calling module.

To continue this discussion I need to hear why the existing functionality is insufficient rather than why your naive solution seems right to you.

@sabhya-ti
Copy link

Ben,

Yes if the issue is emitted the end user will see that issue linked to the calling module. However, our problem is different. It is that in order to emit this issue in the first place my rule evaluation code needs to know what the calling module is. This is because the rule logic is bound to the physical resource id (eg AWS resource ID). The rule needs to lookup information for the corresponding AWS resource that was deployed. eg: A rule that check if the instance is underutilised and recommends that the instance type be changed.

The existing functionality does not provide enough information for my rule to associate the resource block with a physical resource (because resource names are not unique across modules). If both the calling module and the resource name were available, the combination would be unique, allowing the rule logic to map it to a deployed resource.

@bendrucker
Copy link
Member

This still isn't making sense to me as a whole.

How is the address of an object going to get a deployed resource? Are you going into Terraform state and digging it out?

What you're describing, ie validating the state of the underlying resource after creation, is well outside the normal bounds of a linter.

Since the request is reasonable in the abstract we'd review PRs but given the lack of clear general case for this for plugin development it's not something I'd anticipate working on directly. Happy to continue discussion.

@bendrucker bendrucker closed this as not planned Won't fix, can't repro, duplicate, stale Jun 23, 2022
@wata727
Copy link
Member

wata727 commented Jun 23, 2022

Ben, thank you for clarifying the issue. Certainly what they are trying to do may be too difficult for linter. However, this request to be able to get the name of the parent module from a child module seems to make sense.

Perhaps it's better to provide a method like runner.Path(). This is a feature that already exists in runners that are not via plugins, and you can get the module path as follows:
https://github.com/terraform-linters/tflint/blob/a21bdd79b0ff845744b72bb2915f1a6d16adfdfd/tflint/runner_test.go#L182

However, I'm still interested in whether this will meet their demands.

@wata727 wata727 reopened this Jun 23, 2022
@sabhya-ti
Copy link

Thank you again for taking the time to write back to understand more deeply what we are trying to do.

Responding to Ben first, yes. Our current line of thinking does involve going through the Terraform state file and digging out the information that we need from there. And yes, we acknowledge that validating the state like this is indeed out of the bounds of a traditional linter and we would be pushing the boundaries of what a linter is supposed to do.

As for Kazuma's query, assuming that "module1" refers to the terraform reference name for the module,

i.e. the module was declared as

module "module1"{
source = ""
}

in the root module,

then getting that available to us via the runner as we are inspecting the resources of that module should indeed solve our requirements, yes. We can get the reference name for the resources already via the getModuleContent() function of the runner interface as we are inspecting a resource block. If we are able to get the module name as well, together both of them should be enough to ensure uniqueness across the entire terraform template codebase in the project.

Looking forward to hearing back.

@wata727
Copy link
Member

wata727 commented Jun 27, 2022

Understood. Inspection based on the Terraform state is not recommended as it greatly complicates your rules, but you should be able to identify unique resources from the state by using runner.Path ().

@wata727 wata727 added the enhancement New feature or request label Jun 27, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Development

Successfully merging a pull request may close this issue.

4 participants