Cannot seem to fetch SSM Parameter at deploy with CDK - node.js

I'm currently trying a fetch a parameter for my pipeline through the CDK SSM Parameter library, however I seem to face a weird issue:
CfnParameter at 'nonProdAccountId.Parameter' should be created in the scope of a Stack, but no Stack found
However, I'm rather confident that I am fetching my Parameter value in the Scope of a Stack (the BackendPipelineStack).
//cdk.ts aka my entrypoint
const app = new cdk.App()
...
new BackendPipelineStack(app, "BackendPipelineStack", {
nonProdAccountId: StringParameter.fromStringParameterName(app, "nonProdAccountId", "nonProdAccountId").stringValue,
apiStack,
commonInfraStack,
deploymentStack,
})
Am I missing something?
TIA

Right now, you're importing the StringParameter in the scope of the App. The first argument in every Stack or Construct is the scope.
You can create stacks in the scope of an App, but you can't create constructs in the scope of an App - they have to be created in the scope of a Stack.
You need to move the import into the stack, and use the stack as the scope for the import (passing this instead of app).
So you would change
nonProdAccountId: StringParameter.fromStringParameterName(app, "nonProdAccountId", "nonProdAccountId").stringValue,
to
nonProdAccountIdParamName: "nonProdAccountId",
And import the parameter inside of the stack with
const nonProdAccountId = new StringParameter.fromStringParameterName(this, "nonProdAccountId", nonProdAccountIdParamName).stringValue;

Related

terragrunt cannot access module outputs

I'm struggling with Terragrunt (I'm still quite new).
I can describe my problem even using pure Terragrunt repo examples:
Looking here(https://github.com/gruntwork-io/terragrunt-infrastructure-live-example/tree/master/prod/us-east-1/prod/webserver-cluster) we can see terragrunt.hcl that imports a module asg-elb-service taken from particular URL (also terragrunt example)
Now my point is that everything is fine untill module solves all my needs. But using mentioned example let's say that I want to add something on top of this module (e.g listener rule for ALB or anything) - then I would like to rely on module outputs and as we can check "used" module exposes those: outputs (https://github.com/gruntwork-io/terragrunt-infrastructure-modules-example/blob/master/asg-elb-service/outputs.tf)
But how even if I add tf file inside my structure - continuing my example, it would be something like:
I'm just not able to anyhow "interpolate" and get access to those outputs from module :(
terragrunt is a thin wrapper that just provides some extra tools for configuration. terragrunt is used to make management of multiple terraform modules easier, it takes care about remote state and so on. But it does not extend terraform modules by adding some functionality on top of it.
Coming back to your example, common approach is to create a new terraform module, probably on top of the existing one and add missing functionality there. You should consider terraform module as a function that does particular job on a certain level of abstraction. With that said, it's completely valid to create modules that use another modules. Consider following example: you need to provision an infrastructure that can send Slack notifications if AWS CloudWatch alarm is triggered. To simplify it a little bit, let's imagine, that Alarm is already created. The missing part is a Lambda function that will send notification, SNS topic that will trigger Lambda function.
This is something, that can be created using terraform module, but under the hood it will most probably rely on another terraform modules (one that provisions Lambda and another one that provisions SNS topic). Those "internal" modules are on another level of abstraction and you still can reuse them in other cases individually. Pseudo code might look like this:
module "sns_topic" {
source = "git::https://github.com/..."
name = "trigger_lambda_to_send_notification_to_slack"
}
module "labmda_function" {
source = "git::https://github.com/..."
name = "SendMessageToSlack"
...
}
# Invoke Lambda by SNS
resource "aws_sns_topic_subscription" "sns_subscriptions" {
endpoint = module.labmda_function.lambda_endpoint # this is how you reference module output
protocol = "lambda"
topic_arn = module.sns_topic.sns_topic_arn
}
And then, you can simply use this module in terragrunt.

How to pass arguments to openai-gym environments upon init

Following this (unreadable) forum post, I thought it was fitting to post it up on stack overflow for future generations who search for it.
How to pass arguments for gym environments on init?
In the meantime the support for arguments in gym.make has been implemented, so you can pass key word arguments to make right after environment name:
your_env = gym.make('YourEnv', some_kwarg=your_vars)
The gym version that I'm running is 0.12.4.
UPDATE: This is supported from version 0.10.10.. Reference. Thanks #Wojciech.
Method 1 - Use the built in register functionality:
Re-register the environment with a new name
For example:
'Blackjack-natural-v0'
Instead of the original
'Blackjack-v0'
First you need to import the register function:
from gym.envs.registration import register
Then you use the register function like this:
register( id='Blackjack-natural-v0', entry_point='gym.envs.toy_text:BlackjackEnv', kwargs={'natural': True} )
Method 2 - Add an extra method to your env:
If you can just call another init method after gym.make, then you can just do:
your_env = gym.make("YourEnv")
your_env.env.your_init(your_vars)

In Javascript (Node.js), Is It Possible To Pass an Already Instantiated Class Object into Another Code Module

I'm probably missing a larger point of Javascript here, but I wanted to ask the community if the answer is 'NO!'.
Let's say you have an index.js that requires a udp port module:
index.js:
let port1 = require(udp_port.js);
port1.start( { port: 1234, classObj: new myClassObj() } );
udp_port.js:
let dgram = require('dgram');
let msgProcessor; // This is the class obj I'm trying to pass in from index.js
let server = dgram.createSocket('udp4');
exports.start = function(configObj) {
msgProcessor = configObj.classObj; // Can I do this???
}
Any advice would be great at this point, thanks.
In Javascript (Node.js), Is It Possible To Pass an Already Instantiated Class Object into Another Code Module
Yes, it is perfectly possible to pass an instantiated object created in one module to another module. That is done all the time.
Integers and Strings absolutely, but can you pass in a class object? Something you instantiated with the keyword 'new'?
Yes, something instantiated with new can be passed. There are no limitations on what you can pass. Any Javascript type of data. Separate modules loaded into the same nodejs program all run in the same Javascript interpreter. There are no limitations at all on how they can share data with each other.
#James Yep, I had code that I ran before posting but saw mixed results. The code I put in this post was code I cut out of my program. I ended up solving the problem though. What I thought was a limitation of passing variables, was actually a problem related to globals inside a container module (that the instantiated class object was getting passed into).
I was declaring multiple container variables and the global inside was getting reassigned/overwrote with each instantiated class object I passed in.
port1.start(...);
port2.start(...);
had 'msgProcessor' getting assigned twice. Yikes!

how to pass a shared variable to downstream modules?

I have a node toplevel myapp variable that contains some key application state - loggers, db handlers and some other data. The modules downstream in directory hierarchy need access to these data. How can I set up a key/value system in node to do that?
A highly upticked and accepted answer in Express: How to pass app-instance to routes from a different file? suggests using, in a lower level module
//in routes/index.js
var app = require("../app");
But this injects a hard-coded knowledge of the directory structure and file names which should be a bigger no-no jimho. Is there some other method, like something native in JavaScript? Nor do I relish the idea of declaring variables without var.
What is the node way of making a value available to objects created in lower scopes? (I am very much new to node and all-things-node aren't yet obvious to me)
Thanks a lot.
Since using node global (docs here) seems to be the solution that OP used, thought I'd add it as an official answer to collect my valuable points.
I strongly suggest that you namespace your variables, so something like
global.myApp.logger = { info here }
global.myApp.db = {
url: 'mongodb://localhost:27017/test',
connectOptions : {}
}
If you are in app.js and just want to allow access to it
global.myApp = this;
As always, use globals with care...
This is not really related to node but rather general software architecture decisions.
When you have a client and a server module/packages/classes (call them whichever way you like) one way is to define routines on the server module that takes as arguments whichever state data your client keeps on the 'global' scope, completes its tasks and reports back to the client with results.
This way, it is perfectly decoupled and you have a strict control of what data goes where.
Hope this helps :)
One way to do this is in an anonymous function - i.e. instead of returning an object with module.exports, return a function that returns an appropriate value.
So, let's say we want to pass var1 down to our two modules, ./module1.js and ./module2.js. This is how the module code would look:
module.exports = function(var1) {
return {
doSomething: function() { return var1; }
};
}
Then, we can call it like so:
var downstream = require('./module1')('This is var1');
Giving you exactly what you want.
I just created an empty module and installed it under node_modules as appglobals.js
// index.js
module.exports = {};
// package.json too is barebones
{ "name": "appGlobals" }
And then strut it around as without fearing refactoring in future:
var g = require("appglobals");
g.foo = "bar";
I wish it came built in as setter/getter, but the flexibility has to be admired.
(Now I only need to figure out how to package it for production)

node.js setting a global variable

I'm new to node js. I searched a lot on stack overflow on this question below, none what I need.
I have an app.js file which initiates node server and a router file. I want to be able to store a global value once and shared across other server side .js files which contains my functions. I also want this variable to be accessible in my .jade file. (I use express BTW)
Is there a way to accomplish this?
Thanks.
The Node.js documentation says under Module Caching
Caching Modules are cached after the first time they are loaded. This means (among other things) that every call to require('foo') will
get exactly the same object returned, if it would resolve to the same
file.
Multiple calls to require('foo') may not cause the module code to be
executed multiple times. This is an important feature. With it,
"partially done" objects can be returned, thus allowing transitive
dependencies to be loaded even when they would cause cycles.
If you want to have a module execute code multiple times, then export
a function, and call that function.
Which means you can easily expose a global object simply by putting it in its own module.
//config.js
var config = {
dbUrl: 'mogodb://localhost:2107/persons'
};
module.exports = config;
And then when you want to gain access to that object, you simply do:
var config = require('./config');
And that's done, you get access to the same instance everywhere.
You'll want to limit the usage of global vars in Node. This is because unlike any other server side language, Node is a persistent process that share all request. So you cannot setup user state globally as those will be shared across all user accessing your site.
In raw node, there's two global context:
global.foo = 'bar';
// and the process object
process.some_var = 1;
In Express, you can setup application wide vars using app.set
But, most of the time you'll want to share data by adding them to the request or the response objects. That is because those objects are "user" specifics, unlike the global namespace.
For the template, you'll always want to pass in the context:
app.render('email', Object.assign( aSharedObject, {
specific: 'values'
}));
i would use process.env or if you are using nconf put it into the app configuration as Jordan said, globals are BAD idea, also if you don't want to include nconf or any other conf module or use process.env then you can create a module and export a set of getters and setters to handle the value

Resources