Is there a way to copy directories into the Terragrunt workspace?
I've come across the include_in_copy attritube, and I've tried something like this
terraform {
source = "git#gitlab.foo"
include_in_copy = [
"${get_parent_terragrunt_dir()}/foo-dir/"
]
}
But, it looks like this only copies content from whatever the source location is
However, in my case, I want to copy in an entire directory that's in the absolute path to the first terragrunt.hcl file, hence the use of the get_parent_terragrunt_dir() function.
This is what my file structure looks like.
├── deploy
│ └── bar
│ └── terragrunt.hcl
├── foo-dir
└── terragrunt.hcl
I'm calling terragrunt from inside the deploy/bar directory and I would like to include the foo-dir directory as well, but it looks like I'm doing something wrong.
Is there a function that might be able to do this?
Related
I have created the following project structure using NestJS
.
├── app.controller.ts
├── app.module.ts
├── app.service.ts
├── config
│ ├── config.controller.ts
│ ├── config.module.ts
│ └── config.service.ts
├── handlers
│ ├── handler1.ts
│ ├── handler2.ts
│ └── handlers.module.ts
├── main.ts
└── producer
└── producer.ts
Both the handler files wiz. handler1.ts & handler2.ts look something like this:
export const handler = async (args) {
...
...
}
I've ConfigModule in which I've registered ConfigService as a provider. What I want to do is I want to somehow use ConfigService in handler1.ts & handler2.ts. Now mind you, these handlers are not classes, but just normal function expressions. I know if they were classes, I could have injected ConfigService in the handler's constructor using Dependency Injection. But, unfortunately, declaring these handlers as classes is no more an option now. The reason behind that is that these handler files are being consumed by producer.ts and producer.ts reads the entire file and expects an exported function.
I went through the NestJS documentation and found about property-based injection, module-ref, but they were of no help. I also found this link which I think is very close to my problem, But after going through the comments I found out this is not possible.
I don't have much liberty in changing the existing code but I'd still like to know what options do I have here. A solution that would require fewer changes and solve my problem. Thanks!
Note: File handlers.module.ts is serving no purpose in this scenario.
I created a NodeJS module, written in typescript (though it shouldn't change anything).
Here's how it's organized:
.
├── data/
│ └── MY_DATA_FILES.json
│
├── src/
│ ├── data/
│ │ └── data.ts
│ │
│ └── OTHER_TYPESCRIPT_FILES.ts
│
├── dist/
│ ├── data/
│ │ └── data.js
│ │
│ └── OTHER_JAVASCRIPT_FILES.ts
│
├── package.json
└── tsconfig.json
My goal is to read the data files from the data.ts file. When my current working directory in on the root of the module it's not a problem (then it would be ./data/...) but when I use this as a module, and it's placed in the nodes_modules/ directory, I'm not sure how to handle the situation.
I'm currently reading the files as follow:
import fs from 'fs';
const basePath = './data';
const filesPath = 'subdirectory/my_data.json';
export function getData(): any {
const fileFullPath = basePath + '/' + filesPath;
const contents = fs.readFileSync(fileFullPath);
// [...]
}
But here, my basePath is dependent on my working directory. I could set it as ./node_modules/my_module/data, but I know that's not the right approach..
Any help would be appreciated, thanks!
You would typically build a path for each location that is relative to the directory where your code is located and access the desired location in a relative way from that. The location of your code will be passed to the code's module as __dirname. You can then combine that relative path with __dirname to build a full path to the target location without making any assumptions about where or how the module is installed.
So, assuming your code is in the src directory, that would be where __dirname points to. To, get access to the data directory below the src directory, you would use:
let srcDataDir = path.join(__dirname, "data");
To get access to the dist/data directory, you would use:
let distDataDir = path.join(__dirname, '../dist/data');
To get access to the higher level data directory where MY_DATA_FILES.json is, you would use:
let topDataDir = path.join(__dirname, '../data');
As, you can see, the key is to build everything relative from the location you do know which is __dirname passed to the code as the location of the code's own directory.
In Javascript's modules, you don't ever want to make any assumptions about the current working directory because that can literally be anything. That's controlled by the top level program itself and how the program was started and is not anything the module itself can rely on or make assumptions about. But __dirname will always be the full path to the directory where your module's code is running from.
I have my own Yeoman generator.
I created a sub-generator to create a new view folder.
Basically, the usage is:
open a new terminal
cd into the parent folder
run the yeoman command yo my-generator:view
follow the instructions
This view sub-generator prompt a folder name.
For example:
If I want to create the view authentication on the default views directory.
cd views
yo my-generator:view
The result should be:
views //- Already created by the main generator
├── authentication
│ ├── authentication.controller.js
│ ├── authentication.template.html
Now, if I want to create a sub-view login for the authentication view.
cd views/authentication
yo my-generator:view
The result should be:
views //- Already created by the main generator
├── authentication
│ ├── authentication.controller.js
│ ├── authentication.template.html
│ ├── login
│ │ ├── login.controller.js
│ │ ├── login.template.html
Instead, the current (wrong) result is:
views //- Already created by the main generator
├── authentication
│ ├── authentication.controller.js
│ ├── authentication.template.html
├── login
│ ├── login.controller.js
│ ├── login.template.html
My struggle here is that I don't know how to get the current path when I run the command.
Actually, I just create the new folder with a default prefix path which is app/views/.
This is why Authentication example works.
However when my current path is deeper in the views folder, it will add the new folder at the root of the views folder.
If I could get the current path (of the cmd), I should be able to add this path as the prefix instead of setting a default and not static one.
This is why Login example doesn't works.
Some code example:
$that is the current generator object
$that.viewNameCamel is the name of the folder set by the user
I use a .txt file as template and then create the controller.js file.
const filePrefix = 'app/views/' + $that.viewNameCamel + '/' + $that.viewNameCamel + '.';
const exampleData = {
controllerAlias: 'vm',
otherVar: 'example'
};
$that.fs.copyTpl(
$that.templatePath('controller.txt'),
filePrefix + 'controller.js',
exampleData
);
Tried:
$that.env.cwd
process.cwd()
__dirname
path.js library
Similar:
Issue 1037
Question 28481715
So guys, do you have a clue on how do I get the current folder path ?
Is there an alternative solution here ?
Thanks !
EDIT 1:
The problem here is the .yo-rc.json present on the root directory of the projet.
The file rewrite the path so I should delete it to fix the problem.
However if I delete this file, the user configuration will no longer be saved.
And I need it for later sub-generator usage.
Is there another way to save the user configuration ?
Or once again, is there another way to get the current real path ?
I know this is kinda old but for any one who comes later,
from the documentation https://yeoman.io/authoring/file-system.html
If you want to know from where the user is running yo, then you can get the path with this.contextRoot. This is the raw path where yo was invoked from; before we determine the project root with .yo-rc.json.
from my experience removing the .yo-rc.json would mean that you need to manually check if the path provided is ok, having a fixed root point is something helpful.
Just remove the .yo-rc.json file from your root directory. This is the file that is responsible for locating your root irrespective of where you are in the file system.
I am not sure about the repercussions of removing it but nothing seem to have happened to the generators I built.
Now you can use process.cwd() and it will get the correct working directory.
For your use case to have a prefix app/views, you probably need to write some Javascript to append or not append the prefix based on where you are, which should be trivial.
With three different environments, I want to be able to dynamically set variables based on the environment. In my example below, let's say the instance type is different between dev and prod. I'm not able to reference instance_type within the module UNLESS I have a vars.tf file alongside my terraform.tfvars.
The error I get is:
unknown variable referenced: 'instance_type'. define it with 'variable' blocks
If that's the case, then wouldn't this file be the same exact file under modules/apollo/vars.tf?
I thought modules/apollo/vars.tf defines the necessary variables needed for the module. I didn't think it was necessary within the "root" level under env-dev/services/apollo/. If there's a "better" way of doing this, I'm all ears.
├── env-dev
│ └── services
│ └── apollo
│ ├── main.tf
│ ├── terraform.tfvars
│ └── vars.tf # Do i need this?
├── env-test
├── global
├── mgmt
└── modules
├── apollo
│ ├── main.tf
│ ├── user_data.tpl
│ └── vars.tf
└── defaults
└── main.tf
env-dev/services/apollo/terraform.tfvars
instance_type = "t2.medium"
env-prod/services/apollo/terraform.tfvars
instance_type = "t2.large"
modules/apollo/vars.tf
variable "instance_type" {
description = "EC2 Instance Type"
}
modules/apollo/main.tf
resource "aws_instance" "instance" {
...
instance_type = "${var.instance_type}"
...
}
Adjust the structure, this is my understand for your applications.
├── dev
│ └── apollo_terraform.tfvars
├── test
│ └── apollo_terraform.tfvars
├── global
│ └── apollo_terraform.tfvars
├── mgmt
│ └── apollo_terraform.tfvars
├── main.tf, vars.tf, output.tf, apollo.tf, default.tf, etc
└── modules
├── apollo
│ ├── main.tf
│ ├── user_data.tpl
│ └── vars.tf
└── defaults
└── main.tf
apollo.tf will have source module code to use the share module apollo. Same setting for default.tf
your plan/apply command should be like this:
terraform plan -var-file=${env}/apollo_terraform.tfvars
I've been trying to achieve something similar as intuitively it seems this is how it should work, however I am coming to the conclusion that modules are simply not designed for this use case.
Basically you are assigning values to variables that do not exist in your test/prod, to work around this instead of providing assignments in .tfvars you could try to declare them with default values:
env-dev/services/apollo/variables.tf
variable "instance_type" {
default = "t2.medium"
}
env-prod/services/apollo/variables.tf
variable "instance_type" {
default = "t2.large"
}
having those declared and assigned with default values still does not automatically link them to the input variables declared in your module, so
additionally in env-dev/services/apollo/main.tf and env-prod/services/apollo/main.tf you would still need to fill in properties for your module:
module "aws_inst" {
source = "..\\..\\..\\modules\\apollo"
instance_type = "${var.instance_type}"
}
You can quickly see how this defeats the purpose of modules in this scenario.
To elaborate, I think that modules were not designed for defining single resource per module to be able to fill in it's values dynamically, but rather to create "collections" of resources within a module where they can share/reuse same variables.
Note that when you are assigning value to instance_type key in module call, you are actually passing that value to modules input variable which is is then assigned to resource key by the same name.
I have a folder structure like so:
.
└── client
├── components
└── routes
├── index.js
├── Login
│ ├── index.js
│ ├── assets
│ ├── components
│ ├── container
│ └── modules
└── UpdatePassword
├── index.js
├── assets
├── components
├── container
└── modules
I would like to see if anyone is importing files from the UpdatePassword folder to the Login folder and vice versa.
Basically I'm following a fractal project structure where I want components that are related to the UpdatePassword or Login route to only exist in their respective folders. Shared components would exist in the client/components subdirectory. To maintain a structure like this, I would like to write a test that fails when an 'unacceptable' imports or require is used. I.e. if a file in UpdatePassword imports from Login/components.
Is there a way to test or check whether an import is coming from specific folders?
Try madge: I usually run it as madge --image /path-to-folder/dependencies.png routes (There is also a exclude option if you need it)
You'll get a visual graph which shows you dependencies between files.
I have no idea about native way to do it.But you can wrap "require" function:
function myRequire(fromPath, requiredPath) {
//code to judge whether or not can load requiredPath from fromPath
var can = ...
if(can) {
return require(requiredPath);
}
else {
throw new Error(`you can not load ${requiredPath} from ${fromPath}`);
}
}