Please instead of doing negative voting, kindly read complete problem first.
Hi I am new to terraform.
I have 3 modules in terraform.
/module1/eip/main.tf
/module1/eip/output.tf
/module2/eip/main.tf
/module2/eip/output.tf
/module3/eip/main.tf
/module3/eip/output.tf
These all 3 modules create an eip along with showing it in outputs.
From main.tf on root level i am using these functions like this.
module "module-one-eip" {
source = "./modules/module1/eip/"
instance = module.ec2-for-one-module.ec2-one-id
}
module "module-two-eip" {
source = "./modules/module2/eip/"
instance = module.ec2-for-two-module.ec2-two-id
}
module "module-three-eip" {
source = "./modules/module3/eip/"
instance = module.ec2-for-three-module.ec2-three-id
}
Now I want to remove repetitive files and I want to use one file for all modules, like all code from these 3 will reside in one file, and all outputs mentioned above will have in same file, but main problem here is how I will handle different instance variable data being passed and how it will be synced with right code section in same file.
/module/generic-eip/main.tf
/module/generic-eip/outputs.tf
and from main.tf I want to call it like this.
module "module-generic-eip" {
source = "./modules/generic-eip/"
instance = (how to manage different instance names for same file)
}
I know there is for_each and count stuff of terraform, problem is internal configurations are diffrent, i mean how i can make dynamic naming as well.
inside ./modules/eip/main.tf
resource "aws_eip" "(how to manage different names here)" {
instance = var.instance
vpc = true
}
Assuming you keep your inctance module separate, and only want to consolidate EIP module, it would be as follows:
locals {
instance_ids = [module.ec2-for-one-module.ec2-one-id,
module.ec2-for-two-module.ec2-two-id,
module.ec2-for-three-module.ec2-three-id]
}
module "module-generic-eip" {
source = "./modules/generic-eip/"
count = length(local.instance_ids)
instance = local.instance_ids[count.index]
}
Code inside ./modules/eip/main.tf does not change, as for each iteration of count, var.instance will be a single element from local.instance_ids.
Then you access, individual EIPs, using indieces, 0, 1, 2:
module.module-generic-eip[0]
module.module-generic-eip[1]
module.module-generic-eip[2]
Related
module "s3_bucket" {source = "./module/s3_bucket"}
module "s3_bucket_2" {source = "./module/s3_bucket_2"}
These are my two modules which I am calling in the main.tf file, but I want to use some conditions so that I can call any one module which I want at any point of time and only that module gets executed at that time, so is their any way to do that?
I didnt understand quite your question but i guess what you want or at least would be helpfull to answer your question is the following.
You can create a variable in variables.tf called for example create and then pass it to a module.
# Set a variable to know if the resources inside the module should be created
module "s3_bucket" {
source = "./module/s3_bucket"
create = var.create
}
# For every resource inside use the count to create or not each resource
resource "resource_type" "resource_name" {
count = var.create ? 1 : 0
... other resource attributes
}
I want users to be able to create my ScriptableObject assets outside of play mode so they can bind them to their objects in the scene. Since I don't want Zenject creating the ScriptableObjects, a Factory solution is not what I'm looking for. Therefore, I must somehow get the instance of these script objects to the Zenject installer and use 'QueueForInject'. Here are the two approaches I've found:
A) Manually adding these script objects to the Installer via the Inspector Window. Example:
public class GameInstaller : MonoInstaller<GameInstaller>
{
// Visible in the inspector window so user can add Script Objects to List
public List<ScriptableObject> myScriptObjectsToInject;
public override void InstallBindings()
{
foreach (ScriptableObject scriptObject in myScriptObjectsToInject)
{
Container.QueueForInject(scriptObject);
}
}
}
B) Use Unity's AssetDatabase and Resources APIs to find all script object instances then iterate through the list to QueueForInject. Example
// search for all ScriptableObject that reside in the 'Resources' folder
string[] guids = AssetDatabase.FindAssets("t:ScriptableObject");
foreach (string guid in guids)
{
// retrieve the path string to the asset on disk relative to the Unity project folder
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
// retrieve the type of the asset (i.e. the name of the class, which is whatever derives from ScriptableObject)
System.Type myType = AssetDatabase.GetMainAssetTypeAtPath(assetPath);
//Find the relative path of the asset.
string resourcesDirectoryName = $"/Resources/";
int indexOfLastResourceDirectory = assetPath.LastIndexOf(resourcesDirectoryName) + resourcesDirectoryName.Length;
int indexOfExtensionPeriod = assetPath.LastIndexOf(".");
string assetPathRelative = assetPath.Substring(indexOfLastResourceDirectory, indexOfExtensionPeriod - indexOfLastResourceDirectory);
//Grab the instance of the ScriptableObject.
ScriptableObject scriptObject = Resources.Load(assetPathRelative, myType) as ScriptableObject;
if (scriptObject == null)
{
Debug.LogWarning(
"ScriptableObject asset found, but it is not in a 'Resources' folder. Current folder = " +
assetPath);
continue;
}
else
{
Container.QueueForInject(scriptObject);
}
}
With option A) the end user must remember to manually place the script object in the list for every new script object that they create. I'd rather find an automated way so the user doesn't have to know/remember this extra manual process.
With option B) I get an automated solution which, is great. But the end user must remember to store each ScriptableObject asset file in a directory called "Resources" because it's the only way the Resources.Load API will find the instance. I can warn the user if not found, which is nice. But they still are forced to comply to remove the warnings.
I can live with option B if I must, but I'd really like to take it a step further and make it completely invisible to the end user. Has anyone come up with a craftier automated solution for ScriptObjects that exist outside of Play Mode?
I am trying to assign an output variable from a module to a local variable so that I can conveniently use a local variable. Is there another way ?
variable "vpc_id" {
default = "${module.vpc.vpc_id}"
}
Error I am getting is :
Error: Unsupported argument
on main.tf line 22, in variable "subnetid_private":
22: default = "${module.vpc.subnet_private}"
Variables may not be used here..
I spent good amount of time to google this but could not see any example. Am I missing something here. This is a pretty standard convenience feature of any language.
you can replace with locals
https://www.terraform.io/docs/configuration/locals.html
locals {
vpc_id = module.vpc.vpc_id
}
and later reference it as local.vpc_id
I had the same thought when I first started using Terraform.
The problem is naming. A Terraform variable block is more like a final or constant constructor or method parameter in other languages.
From the Local Value documentation, it says this:
A local value assigns a name to an expression, allowing it to be used multiple times within a module without repeating it.
Comparing modules to functions in a traditional programming language: if input variables are analogous to function arguments and outputs values are analogous to function return values, then local values are comparable to a function's local temporary symbols.
When you write:
variable "vpc_id" {
}
Terraform says "ah, you'd like callers of this module to be able to hand a string in called vpc_id". Definitely not what you are looking for.
For the kind of case you have, a Local Value is what Terraform provides:
locals {
vpc_id = module.vpc.vpc_id
}
In terraform 0.12, you can use variables in variables like so:
variable "var1" {
type = string
default = "this is var 1"
}
variable "var2" {
type = string
default = "$${variable.var1}"
}
output of this is:
$ terraform apply
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
the following code is excerpted from an lua file, say file0.lua
local Tags = require('file1')
local Set = require('file2')
local Guidance = {}
highway_classes = {
motorway = road_priority_class.motorway,
motorway_link = road_priority_class.motorway_link,
trunk = road_priority_class.trunk,
trunk_link = road_priority_class.trunk_link,
primary = road_priority_class.primary,
primary_link = road_priority_class.primary_link,
secondary = road_priority_class.secondary,
secondary_link = road_priority_class.secondary_link,
tertiary = road_priority_class.tertiary
}
I have searched through the two required files, i.e., file1 and file2. I did not find any mention of road_priority_class anywhere. I did find it in another lua file, say file3.lua. But this file3.lua is not required at all in file0.lua. I was wondering, do you happen to know under what scenario would this be possible? I'm new to Lua and the code I'm working on is embedded in c++ environment, I guess that would be the reason. Any comments are greatly appreciated.
If road_priority_class is a global variable, then it's available anywhere from the moment it has been declared (i.e. the file is required anywhere)
The main reason why you shouldn't normally do this is precisely because it makes it hard to track where things come from and breaks modularity.
I have a Terraform structure like:
prod
nonprod
applications
+-- continuous/common/iam/iam.tf <-- create the role
+-- dataflow/firehose/firehose.tf <-- want to refer to the role created above
I don't know how to do this. In the iam's .tf file I have:
resource "aws_iam_role" "policy_daily_process_role" {
...
}
output "svc_daily_process_role_arn" {
value = "${aws_iam_role.policy_daily_process_role.arn}"
}
I am not sure how (or if) I can then refer to the svc_daily_process_role_arn from the firehose's .tf.
My understanding that you already use modules to manage terraform codes.
So in your case, there should be two modules at least.
continuous/common
dataflow/firehose
In continuous/common module, you have defined output.tf
output "svc_daily_process_role_arn" {
value = "${aws_iam_role.policy_daily_process_role.arn}"
}
So you create the resources with common module first.
module "common" {
source = "./continuous/common"
...
}
Now you are fine to refer the output from module common with below codes:
module "firehost" {
source = "./dataflow/firehose"
some_variable = "${module.common.svc_daily_process_role_arn}"
...
}
Please go through below documents for better understanding.
https://www.terraform.io/docs/modules/usage.html#outputs
Using Terraform Modules.
https://www.terraform.io/docs/modules/usage.html
From a top level make a call to the two subdirectories.
In module 1 (your IAM role) add an output like you have, but ensure it's outputted from module 1.
In module 2 reference it via ${module..}
If you're not using modules (or even if you are), you can use remote state. This means you will save your state in S3 or Consul and then refer to it from anywhere in your code.