Cannot create node group via sdk - aws-sdk

I am trying to create a nodegroup via the aws sdk for node.js I'd prefer to do this than via the eksctl.
This is a simple question but there are just no code examples of this in the aws docs and I can't figure out the correct name spaces so unfortunately I am asking here:
My code is as follows with node.js
const AWS = require('aws-sdk');
AWS.config.update({region: 'us-west-2'});
const eks = new AWS.EKS();
AWS.config.update({region: 'us-west-2'});
// Name must be cluster
eks.CreateNodegroup({name:'openstudio-server',
instanceTypes:["t2.xlarge"],
"nodegroupName":'openstudio-node',
"scalingConfig": {
"desiredSize": 3,
"maxSize": 10,
"minSize": 3
}
})
I am consistently getting the error
What am I doing wrong?

I'm guessing you've resolved this already but it looks like you just need to change eks.CreateNodegroup() to eks.createNodegroup() and it should work.
source: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/EKS.html

Related

AWS-CDK : CNAMEPrefix is not getting set in the elasticbeanstalk.CfnEnvironment

I am trying to deploy a NodeJS app to elastic beanstalk using AWS CDK, things are working fine, deployment and redeployment works fine.However, the final URL which is generated has random string like 'MyDeployEnv1.eba-5vjzkdss.us-east-1.elasticbeanstalk.com'. While reading through various AWS documentation I came across the property CNAMEPrefix.
So I added the CNAMEPrefix in the elasticbeanstalk.CfnEnvironment call as below :
const elbEnv = new elasticbeanstalk.CfnEnvironment(this, 'Environment', {
environmentName: 'MyDeployEnv1',
CNAMEPrefix: 'myapi14',
applicationName: app.applicationName || appName,
solutionStackName: '64bit Amazon Linux 2018.03 v4.17.0 running Node.js',
optionSettings: optionSettingProperties,
versionLabel: appVersionProps.ref,
});
CNAMEPrefix is not working, any help to change/remove the random alphanumeric string in the URL would be helpful 'MyDeployEnv1.eba-5vjzkdss.us-east-1.elasticbeanstalk.com'
Version details :
aws-cli 2.1.1 Windows/10 exe/AMD64
CDK version : 1.75.0 (build 7708242)

How to convert Pulumi Output<t> to string?

I am dealing with creating AWS API Gateway. I am trying to create CloudWatch Log group and name it API-Gateway-Execution-Logs_${restApiId}/${stageName}. I have no problem in Rest API creation.
My issue is in converting restApi.id which is of type pulumi.Outout to string.
I have tried these 2 versions which are proposed in their PR#2496
const restApiId = apiGatewayToSqsQueueRestApi.id.apply((v) => `${v}`);
const restApiId = pulumi.interpolate `${apiGatewayToSqsQueueRestApi.id}`
here is the code where it is used
const cloudWatchLogGroup = new aws.cloudwatch.LogGroup(
`API-Gateway-Execution-Logs_${restApiId}/${stageName}`,
{},
);
stageName is just a string.
I have also tried to apply again like
const restApiIdStrign = restApiId.apply((v) => v);
I always got this error from pulumi up
aws:cloudwatch:LogGroup API-Gateway-Execution-Logs_Calling [toString] on an [Output<T>] is not supported.
Please help me convert Output to string
#Cameron answered the naming question, I want to answer your question in the title.
It's not possible to convert an Output<string> to string, or any Output<T> to T.
Output<T> is a container for a future value T which may not be resolved even after the program execution is over. Maybe, your restApiId is generated by AWS at deployment time, so if you run your program in preview, there's no value for restApiId.
Output<T> is like a Promise<T> which will be eventually resolved, potentially after some resources are created in the cloud.
Therefore, the only operations with Output<T> are:
Convert it to another Output<U> with apply(f), where f: T -> U
Assign it to an Input<T> to pass it to another resource constructor
Export it from the stack
Any value manipulation has to happen within an apply call.
So long as the Output is resolvable while the Pulumi script is still running, you can use an approach like the below:
import {Output} from "#pulumi/pulumi";
import * as fs from "fs";
// create a GCP registry
const registry = new gcp.container.Registry("my-registry");
const registryUrl = registry.id.apply(_=>gcp.container.getRegistryRepository().then(reg=>reg.repositoryUrl));
// create a GCP storage bucket
const bucket = new gcp.storage.Bucket("my-bucket");
const bucketURL = bucket.url;
function GetValue<T>(output: Output<T>) {
return new Promise<T>((resolve, reject)=>{
output.apply(value=>{
resolve(value);
});
});
}
(async()=>{
fs.writeFileSync("./PulumiOutput_Public.json", JSON.stringify({
registryURL: await GetValue(registryUrl),
bucketURL: await GetValue(bucketURL),
}, null, "\t"));
})();
To clarify, this approach only works when you're doing an actual deployment (ie. pulumi up), not merely a preview. (as explained here)
That's good enough for my use-case though, as I just want a way to store the registry-url and such after each deployment, for other scripts in my project to know where to find the latest version.
Short Answer
You can specify the physical name of your LogGroup by specifying the name input and you can construct this from the API Gateway id output using pulumi.interpolate. You must use a static string as the first argument to your resource. I would recommend using the same name you're providing to your API Gateway resource as the name for your Log Group. Here's an example:
const apiGatewayToSqsQueueRestApi = new aws.apigateway.RestApi("API-Gateway-Execution");
const cloudWatchLogGroup = new aws.cloudwatch.LogGroup(
"API-Gateway-Execution", // this is the logical name and must be a static string
{
name: pulumi.interpolate`API-Gateway-Execution-Logs_${apiGatewayToSqsQueueRestApi.id}/${stageName}` // this the physical name and can be constructed from other resource outputs
},
);
Longer Answer
The first argument to every resource type in Pulumi is the logical name and is used for Pulumi to track the resource internally from one deployment to the next. By default, Pulumi auto-names the physical resources from this logical name. You can override this behavior by specifying your own physical name, typically via a name input to the resource. More information on resource names and auto-naming is here.
The specific issue here is that logical names cannot be constructed from other resource outputs. They must be static strings. Resource inputs (such as name) can be constructed from other resource outputs.
Encountered a similar issue recently. Adding this for anyone that comes looking.
For pulumi python, some policies requires the input to be stringified json. Say you're writing an sqs queue and a dlq for it, you may initially write something like this:
import pulumi_aws
dlq = aws.sqs.Queue()
queue = pulumi_aws.sqs.Queue(
redrive_policy=json.dumps({
"deadLetterTargetArn": dlq.arn,
"maxReceiveCount": "3"
})
)
The issue we see here is that the json lib errors out stating type Output cannot be parsed. When you print() dlq.arn, you'd see a memory address for it like <pulumi.output.Output object at 0x10e074b80>
In order to work around this, we have to leverage the Outputs lib and write a callback function
import pulumi_aws
def render_redrive_policy(arn):
return json.dumps({
"deadLetterTargetArn": arn,
"maxReceiveCount": "3"
})
dlq = pulumi_aws.sqs.Queue()
queue = pulumi_aws.sqs.Queue(
redrive_policy=Output.all(arn=dlq.arn).apply(
lambda args: render_redrive_policy(args["arn"])
)
)

Quicksight Dashboard Embed url showing us-east-1 not eu-west-1

Problem:
I want to programmatically fetch a quicksight dashboard URL through the SDK, (dashboard in region: eu-west-1) however whenever I use the following regions I get the following errors when I use the following regions:
eu-west-1: Error: Operation is being called from endpoint eu-west-1, but your identity region is us-east-1. Please use the us-east-1 endpoint.
us-east-1: No error, but the embed url is us-east-1 and results in a us-east-1.quicksight.aws.amazon.com refused to connect error in the browser, eg: https://us-east-1.quicksight.aws.amazon.com/embed/XXXXXX&identityprovider=quicksight&isauthcode=true',
Example Code:
Note: Credentials added for brevity, but are loaded from profile. Have also tried in Java SDK.
const AWS = require('aws-sdk')
const dotenv = require('dotenv').config()
const init = async () => {
AWS.config.credentials = {accessKeyId: process.env.ACCESS_KEY_ID, secretAccessKey: process.env.SECRET_ACCESS_KEY}
AWS.config.region = 'us-east-1'
// AWS.config.region = 'eu-west-1'
const quicksight = new AWS.QuickSight()
const embedUrlParams = {
AwsAccountId: '111122223333',
DashboardId: '11111111-2222-3333-4444-555555555555',
IdentityType: 'QUICKSIGHT',
UserArn: 'arn:aws:quicksight:us-east-1:111122223333:user/default/quicksight-user-1111'
}
const embedUrlRes = await quicksight.getDashboardEmbedUrl(embedUrlParams).promise()
console.log('embedUrlRes', embedUrlRes)
}
init()
CLI:
When I envoke exactly the same through CLI, eg:
aws quicksight get-dashboard-embed-url --aws-account-id 111122223333 --dashboard-id 11111111-2222-3333-4444-555555555555 --identity-type QUICKSIGHT --user-arn "arn:aws:quicksight:us-east-1:111122223333:user/default/quicksight-user-1111" --profile my-quicksight-profile
I get the a perfectly valid embed url in eu-west-1 that embeds perfect through the browser:
https://eu-west-1.quicksight.aws.amazon.com/embed/XXXXXXXX&identityprovider=quicksight&isauthcode=true
So:
I imaging that the SDK is not behaving as the CLI is in the respect of assuming roles, but I've tried this with little success, as well as pointing to quicksight regional endpoints.
Before I go down the rabbit hole, it would be good to see if anyone has experienced the same and how they resolved it.
Thanks!
For people who endup here, While generating and embedded link using sdk if your dashboard is in a different region you have to update quicksight parameters of the sdk to that region
something like the following
// Previous code blocks..
quicksight = new AWS.QuickSight({ region: targetRegion })
quicksight.getDashboardEmbedUrl(Params,function (error, embeddedLink){})
Also you have to whitelist domain on each region since quicksight considers each region as seperate entity

How to do post filter with couchnode / couchbase server?

I've been developing using Couchbase Server 4.0 and upgrading to 5.0 is down the road but not at the moment.
But for now I do need to search views (map/reduce) using text search, on Couchbase Lite .Net there is PostFilter that serve the purpose.
But I could not find the same settings on Couchnode, checking the Couchbase Lite .Net told me that a query option might help.
I tried couple of things like this:
query.options.filter = r => {
console.log('******', r)
return true
}
query.options.post_filter = r => {
console.log('******', r)
return true
}
query.options.postFilter = r => {
console.log('******', r)
return true
}
but nothing seems to work. Anyone experienced this before please help!!
On Couchbase server, map/reduce queries are created on the Server cluster itself, not created in the SDK like with Couchbase Lite. An example:
function(doc, meta)
{
emit(doc.name, [doc.city, doc.salary]);
}
When you create a view, you give it a name. You can call these view from the Node SDK (couchnode) by name like so:
var couchbase = require('couchbase');
var ViewQuery = couchbase.ViewQuery;
var query = ViewQuery.from('beer', 'by_name');
See the documentation: https://docs.couchbase.com/server/4.0/developer-guide/views-writing.html and https://docs.couchbase.com/nodejs-sdk/2.6/view-queries-with-sdk.html

How to use aws athena using nodejs?

Athena is analytics service for retrieving data from s3 using sql query.
I have queried data in s3 using t aws console
Need access to aws athena using nodejs code
I am using athena like following way in my nodejs project :
download JDBC driver from AWS.
Create a connector.js file.
npm install jdbc NPM.
Paste followings:
var JDBC = require('jdbc');
var jinst = require('jdbc/lib/jinst');
if (!jinst.isJvmCreated()) {
jinst.addOption("-Xrs");
jinst.setupClasspath(['./AthenaJDBC41-*.jar']);
}
var config = {
// Required
url: 'jdbc:awsathena://athena.*.amazonaws.com:443',
// Optional
drivername: 'com.amazonaws.athena.jdbc.AthenaDriver',
minpoolsize: 10,
maxpoolsize: 100,
properties: {
s3_staging_dir: 's3://aws-athena-query-results-*/',
log_path: '/logs/athenajdbc.log',
user: 'access_key',
password: 'secret_key'
}
};
var hsqldb = new JDBC(config);
hsqldb.initialize(function(err) {
if (err) {
console.log(err);
}
});
Just use the Athena Service on the JS SDK.
Athena JS Documentation
AWS JS SDK
You could use the athena-express module from here, as documented by AWS here
You need to use aws-sdk and athena-express dependencies,
There's a full working tutorial in this video I made:
https://www.youtube.com/watch?v=aBf5Qo9GZ1Yac