Cannot pass two Output callback values in Pulumi - pulumi

Im having trouble passing two Output callback values into a container definition. I am doing this:
redis_url = redis.cache_nodes.apply(lambda cache_nodes: cache_nodes[0].get('address'))
task_definition = aws.ecs.TaskDefinition('task',
family='task-definition',
cpu='256',
memory='512',
network_mode='awsvpc',
requires_compatibilities=['FARGATE'],
execution_role_arn=role.arn,
container_definitions=cloudwatchgroup.name.apply(generate_container_definition)
)
def generate_container_definition(log_group_name):
return json.dumps([{
'name': 'api',
'image': 'api/api:latest',
'portMappings': [{
'containerPort': 80,
'hostPort': 80,
'protocol': 'tcp'
}],
'logConfiguration': {
'logDriver': 'awslogs',
'options': {
'awslogs-group': log_group_name,
'awslogs-region': aws.get_region().name,
}
},
'environment' : [
{ 'name' : 'ENV', 'value' : config.get('ENV') },
{ 'name' : 'REDIS_URL', 'value' : redis_url }
]
}])
but then Im getting: TypeError: Object of type Output is not JSON serializable
Is there a way to pass two output values into that function definition or am I doing something wrong?

You can use Output.all to combine multiple outputs. Something like
def generate_container_definition(log_group_name, redis_url):
...
container_definitions = Output.all(cloudwatchgroup.name, redis.cache_nodes)
.apply(lambda args: generate_container_definition(args[0], args[1][0].get('address')))

Related

RDSDataService not recognizing `typeHint` in `batchExecuteStatement` method

I'm trying to run the batchExecuteStatement method. For some kind of reason, passing as parameter (besides the sql string and the resource configuration)
[
[
{ name: 'id', value: { stringValue: 'uuidString' }, typeHint: 'UUID' },
{ name: 'meta', value: { stringValue: '{}' }, typeHint: 'JSON' }
]
]
results in the method throwing this exception UnexpectedParameter: Unexpected key 'typeHint' found in params.parameterSets[0][0].
I do not understand why, since the query parameters look the same as in the aws doc.
The query is a simple INSERT INTO alarms_log VALUES(:id, :meta); statement
Source doc link: https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/RDSDataService.html#batchExecuteStatement-property

Mongodb empty object Object.keys(myObj).length return wrong values

I have an object inside collection called "childLimit".
Schema:
user: { name: {type: String}, childLimit: {dailyLimit: {type: Number} }
Now if I haven't inset any info in this object (childLimit) while creating user so it should not be there as mongo work, that fine. but when I console this it return {} empty object which is fine.
But when I console.log(Object.values(childLimit)) it console [ true, undefined, undefined, undefined ] which is strange????
Object.keys(childLimit).length return 2 but it should be 0??
Now how can I check if the object is empty?? OR if the object exist??
This seems to be about Mongoose, am I right?
Just log the keys which you count, and you will see something like follows: Mongoose-internal properties, but not your document's keys:
console.log(Object.keys(doc));
// [ '$__', 'isNew', 'errors', '$locals', '$op', '_doc' ]
What you actually want are the properties of the document. You can do this as follows:
console.log(Object.keys(doc.toObject()));
// [ 'foo', 'bar', 'baz' ]
Or alternatively (this doesn't seem to be a public API though!):
console.log(Object.keys(doc._doc));
// [ 'foo', 'bar', 'baz' ]
Note that sometimes, both can return different results.

mailchimp3 (Python-mailchimp-api) How to set tags

I tried:
client.lists.members.create('1111111', {
'email_address' : 'frogger116#gmail.com',
'status' : 'subscribed',
"tags": [{'name': 'frogger', 'status' : 'active'}],
})
and get:
mailchimp3.mailchimpclient.MailChimpError: {
'type': 'http://developer.mailchimp.com/documentation/mailchimp/guides/error-glossary/',
'title': 'Invalid Resource',
'status': 400,
'detail': 'Expected argument of type "string", "stdClass" given',
'instance': '5ae1b966-ed35-49f1-ad32-0a39c3d63593'
}
Without the "tags" line the satement works
This works for me (you need hash the email address)
hash = get_subscriber_hash(email_address)
data = {
'tags': [
{'name': 'foo', 'status': 'active'},
{'name': 'bar', 'status': 'inactive'}
]
}
client.lists.members.tags.update(list_id=list_id, subscriber_hash=hash, data=data)
I think in the latest version the tags are just strings. At least, this is what I use.
client.lists.members.create('1111111', {
'email_address' : 'frogger116#gmail.com',
'status' : 'subscribed',
'tags': ['frogger','invaders']
})
Also, to be certain, make sure tags exist in the system. Especially if doing an update rather than insert. Its not super consistant about dealing with unknown tags.
Also of course, make sure the '1111111' audience id exists.
SUPPLEMENTAL CODE
Of course, I've found a better way to ensure what you want is to use other methods to add to tags rather than on insert. You may have to tweak the below functions as they are part of a class, but they should give you other ideas on how to add and remove tags from users
def bulkUpdateTagNamesForEmails(self, emailsToUpdate, tagNames, remove=False):
audienceId = self.audienceId
if remove:
data = {'members_to_remove':emailsToUpdate}
else:
data = {'members_to_add':emailsToUpdate}
segments = None
for tagName in tagNames:
segId,segments = self.getSegmentIdFromTagName(tagName,segments)
if segId:
self.brResponse = self.mcClient.lists.segments.update_members(list_id=audienceId, segment_id=segId, data=data)
def createTagNameIfNeeded(self, tagName):
audienceId = self.audienceId
# Check for tag name
found = False
segments = self.mcClient.lists.segments.all(list_id=audienceId, get_all=False)
for segment in segments['segments']:
if segment['name'] == tagName:
found = True
print("Found tag")
# If not found, create it
if not found:
print(f"Creating new tag {tagName}")
data = {'name': tagName,'static_segment': []}
self.mcClient.lists.segments.create(list_id=audienceId, data=data)
def getSegmentIdFromTagName(self,reqTagName,segments=None):
audienceId = self.audienceId
reqId = None
if not segments:
segments = self.mcClient.lists.segments.all(list_id=audienceId, get_all=True)
for segment in segments['segments']:
segName = segment['name']
segId = segment['id']
if segName == reqTagName:
reqId = segId
break
return reqId,segments

Joi when sibling then add extra rules at root

I have a complex validation which changes depending on the a value in the JSON.
{ type: 'a', thing: 1, foo: 'abc' }
{ type: 'b', thing: 2, bar: 123 }
I want to validate that if the type is a, then use one set of siblings, if b then use another set of siblings
I would like to use the when switch, but cant work out how to do this at the root.
Joi.object({
type: Joi.string().valid('a','b').required(),
thing: Joi.number().required()
}).when('type', {
switch: [
{ is: 'a', then: Joi.object({ foo: Joi.string() }) },
{ is: 'b', then: Joi.object({ bar: Joi.number() }) },
],
otherwise: Joi.forbidden(),
});
However this gives the following error:
Error: Invalid reference exceeds the schema root: ref:type
This kinda makes sense as an error but I don't know how to restructure this to get it to apply the selector at the root.
Im using latest JOI (16.0.1)
This can be resolved by prefixing the key name passed to .when() with a ., to denote the key as being relative to the object being validated:
Joi.object({
type: Joi.string().valid('a','b').required(),
thing: Joi.number().required()
})
.when('.type', { /* <-- prefix with . */
switch : [
{ is: 'a', then: Joi.object({ foo: Joi.string() }) },
{ is: 'b', then: Joi.object({ bar: Joi.number() }) },]
})
Here's a working example - hope that helps :-)

sequelize group by result undefined

i'm trying to get the result from sequelize query group by
but when i want to get the value of count , it shows undefined
var models = require('../../config/sequelize');
models.device.findAll({
attributes: [
'type',
[models.sequelize.fn('count', models.sequelize.col('deviceId')),'count']
],
group: ["device.type"]
}).then(function (result) {
result.forEach( function(e){
console.log( e.count ) ;
})
}).catch(function(err) {
console.log( "test group :"+JSON.stringify(err.message)) ;
}); ;
Assuming type and deviceId are the actual column name and not the aliases, try using raw: true and set columns using sequelize:
device.findAll({
raw: true,
attributes:[
Sequelize.col('type'),
[Sequelize.fn('count', Sequelize.col('deviceId')), 'count']
],
group: [
'device.type'
]
})
.then( devices => {
console.log(devices.count); // or
console.log(devices['count'])
})
.catch(/* */);