AWS/CDK: How to create ARecord Target, having CfnEIPAssociation? - amazon-ec2

For a newly allocated IP, it would be something like this in C# (using .Ref):
var arNewPublic = new ARecord(this, $"ARecord_Public_NewAlloc", new ARecordProps
{
...
Target = RecordTarget.FromValues(newElasticIPs.Select(eip => eip.Ref).ToArray())
...
But how to create ARecord target for a CfnEIPAssociation?
Doing it like that:
Target = RecordTarget.FromValues(elasticIPAssociations.Select(eipa => eipa.Eip).ToArray()),
throws:
Unhandled exception. Amazon.JSII.Runtime.JsiiException:
Got 'undefined' for non-optional instance of {"name":"values","type":{"primitive":"string"},"variadic":true}
or crashes CF deployment:
Target = RecordTarget.FromValues(elasticIPAssociations.Select(eipa => eipa.Ref).ToArray()),
9/12 | 1:58:11 PM | CREATE_FAILED | AWS::Route53::RecordSet | ARecord-Public-PreAlloc (ARecordPublicPreAllocCB385358) [Invalid Resource Record: FATAL problem: ARRDATAIllegalIPv4Address (Value is not a valid IPv4 address) encountered with 'eipassoc-0f9299c9975d21e6e']
new RecordSet (...#aws-cdk\aws-route53\lib\record-set.js:134:27)

Related

Grails spock test fails with "GroovyCastException: Cannot cast object"

I have a simple class that I'm writing a test for. Something weird happens when I call validate() on an instance of that class, which relates to my custom validator for my date property. If my custom validator calls a static method, everything seems to work fine. However, if I call a non-static method (which I need to as I need to check some other properties of my instance) I get the following error:
Condition failed with Exception:
testDate.validate(['date']) == valid
| |
| org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'class hegardt.backend.grails.model.person.TestDate' with class 'java.lang.Class' to class 'hegardt.backend.grails.model.person.TestDate'
| at hegardt.backend.grails.model.person.TestDate._clinit__closure1$_closure2(TestDate.groovy:20)
| at groovy.lang.Closure.call(Closure.java:405)
| at org.grails.datastore.gorm.validation.constraints.ValidatorConstraint.processValidate(ValidatorConstraint.java:100)
| at org.grails.datastore.gorm.validation.constraints.AbstractConstraint.validate(AbstractConstraint.java:88)
| at grails.gorm.validation.DefaultConstrainedProperty.validate(DefaultConstrainedProperty.groovy:601)
| at grails.validation.Validateable$Trait$Helper.doValidate(Validateable.groovy:192)
| at grails.validation.Validateable$Trait$Helper.validate(Validateable.groovy:163)
| at grails.validation.Validateable$Trait$Helper.validate(Validateable.groovy:129)
| at hegardt.backend.grails.model.person.TestDateSpec.test(TestDateSpec.groovy:15)
<hegardt.backend.grails.model.person.TestDate#48bb8764 date=null privateVar=false grails_validation_Validateable__beforeValidateHelper=org.grails.datastore.gorm.support.BeforeValidateHelper#1624fd07 grails_validation_Validateable__errors=grails.validation.ValidationErrors: 0 errors>
Here's my class definition:
#GrailsCompileStatic
class TestDate implements Validateable {
LocalDate date
boolean privateVar
static constraints = {
date nullable: true, validator: {LocalDate val -> validateDate(val)}
}
private validateDate(LocalDate val) { // If this method is static, everything works fine
return privateVar
}
}
and here's my test class
class TestDateSpec extends Specification {
#Unroll
void "test"() {
given:
TestDate testDate = new TestDate(date: date)
expect:
testDate.validate(['date']) == valid // This call fails for all 4 test cases...
where:
date | valid
null | true
LocalDate.now().plusDays(1) | false
LocalDate.now() | false
LocalDate.now() | true
}
}
PS
I have also tried without #GrailsCompileStatic but this just generates a different "cast" related error:
Condition failed with Exception:
testDate.validate(['date']) == valid
| |
| java.lang.IllegalArgumentException: object is not an instance of declaring class
| at org.grails.datastore.gorm.validation.constraints.builder.ConstrainedPropertyBuilder.doInvokeMethod(ConstrainedPropertyBuilder.java:65)
| at groovy.util.BuilderSupport.invokeMethod(BuilderSupport.java:64)
| at groovy.lang.GroovyObjectSupport.invokeMethod(GroovyObjectSupport.java:44)
| at hegardt.backend.grails.model.person.TestDate._clinit__closure1$_closure2(TestDate.groovy:19)
| at groovy.lang.Closure.call(Closure.java:405)
| at org.grails.datastore.gorm.validation.constraints.ValidatorConstraint.processValidate(ValidatorConstraint.java:100)
| at org.grails.datastore.gorm.validation.constraints.AbstractConstraint.validate(AbstractConstraint.java:88)
| at grails.gorm.validation.DefaultConstrainedProperty.validate(DefaultConstrainedProperty.groovy:601)
| at grails.validation.Validateable$Trait$Helper.doValidate(Validateable.groovy:192)
| at grails.validation.Validateable$Trait$Helper.validate(Validateable.groovy:163)
| at grails.validation.Validateable$Trait$Helper.validate(Validateable.groovy:129)
| at hegardt.backend.grails.model.person.TestDateSpec.test(TestDateSpec.groovy:15)
<hegardt.backend.grails.model.person.TestDate#1e742012 date=null privateVar=false grails_validation_Validateable__beforeValidateHelper=org.grails.datastore.gorm.support.BeforeValidateHelper#4f3967c7 grails_validation_Validateable__errors=grails.validation.ValidationErrors: 0 errors>
You are attempting to invoke an instance method (validateDate) from a static context (static constraints block) which is not allowed. You could mark validateDate as static but that moves the problem to privateVar which is an instance variable so you would not be able to reach that from a static method. It isn't clear what role that field plays so it isn't clear how best to deal with that, but the problem described in the question is caused because you are attempting to invoke an instance method from a static context.

Error: Code="VMExtensionProvisioningError" JsonADDomainExtension

I have terraform script which make a domain join with the code below:
resource "azurerm_virtual_machine_extension" "join-domain" {
name = azurerm_virtual_machine.client.name
virtual_machine_id = azurerm_virtual_machine.client.id
// resource_group_name = var.resource_group_name
//virtual_machine_name = azurerm_virtual_machine.client.name
publisher = "Microsoft.Compute"
type = "JsonADDomainExtension"
type_handler_version = "1.3"
# NOTE: the `OUPath` field is intentionally blank, to put it in the Computers OU
settings = <<SETTINGS
{
"Name": "${var.active_directory_domain}",
"OUPath": "",
"User": "${var.active_directory_domain}\\${var.active_directory_username}",
"Restart": "true",
"Options": "3"
}
SETTINGS
protected_settings = <<SETTINGS
{
"Password": "${var.active_directory_password}"
}
SETTINGS
depends_on = ["null_resource.wait-for-domain-to-provision"]
}
After the code run, it gets the error below in Terraform:
Error: Code="VMExtensionProvisioningError" Message="VM has reported a failure when processing extension 'pocvde-client'. Error message: \"Exception(s) occured while joining Domain 'pocvde.local'\"\r\n\r\nMore information on troubleshooting is available at https://aka.ms/vmextensionwindowstroubleshoot "
on modules/windows-client/4-join-domain.tf line 1, in resource "azurerm_virtual_machine_extension" "join-domain":
1: resource "azurerm_virtual_machine_extension" "join-domain" {
I have checked the windows client logs in C:\WindowsAzure\Logs\Plugins\Microsoft.Compute.JsonADDomainExtension, i got the trace below:
2020-06-23T06:30:54.1176834Z [Info]: Get Domain/Workgroup Information
2020-06-23T06:30:54.1645880Z [Info]: Current domain: (), current workgroup: WORKGROUP, IsDomainJoin: True, Target Domain/Workgroup: pocvde.local.
2020-06-23T06:30:54.1802137Z [Info]: Domain Join Path.
2020-06-23T06:30:54.1802137Z [Info]: Current Domain name is empty/null. Try to get Local domain name.
2020-06-23T06:30:54.1958114Z [Info]: In AD Domain extension process, the local domain is: ''.
2020-06-23T06:30:54.1958114Z [Info]: Domain Join will be performed.
2020-06-23T06:30:54.3460994Z [Error]: Try join: domain='pocvde.local', ou='', user='pocvde.local\AdminAls', option='NetSetupJoinDomain, NetSetupAcctCreate' (#3:User Specified), errCode='1355'.
2020-06-23T06:30:54.3621879Z [Error]: Setting error code to 53 while joining domain
2020-06-23T06:30:54.4085771Z [Error]: Try join: domain='pocvde.local', ou='', user='pocvde.local\AdminAls', option='NetSetupJoinDomain' (#1:User Specified without NetSetupAcctCreate), errCode='1355'.
2020-06-23T06:30:54.4085771Z [Error]: Setting error code to 53 while joining domain
2020-06-23T06:30:54.4241709Z [Error]: Computer failed to join domain 'pocvde.local' from workgroup 'WORKGROUP'.
I have changed the client vm OS from DataCenter-16 to Windows 10, i got still same error. Increased the waiting time before domain join operation from 12 minutes to 24 minutes, nothing changed.
Do you have any idea?
I saw that the Domain Controller was not set correctly, after solving that domain join operation is done correctly and that solved my problem

The "error_marshaling_enabled" setting seems to be always enabled

When I run this code:
$client->evaluate('
box.session.settings.error_marshaling_enabled = false
box.error{code = 42, reason = "Foobar", type = "MyError"}
');
regardless of the value of error_marshaling_enabled I always get a response with a new (extended) error format:
[
49 => 'Foobar',
82 => [
0 => [
0 => [
0 => 'CustomError',
2 => 3,
1 => 'eval',
3 => 'Foobar',
4 => 0,
5 => 42,
6 => [
'custom_type' => 'MyError',
],
],
],
],
],
Why is that?
Short answer.
error_marshaling_enabled option affects only how error objects are encoded in response body (48, IPROTO_DATA). It does not affect how they are returned as exceptions, in the response header (82, IPROTO_ERROR).
Long answer.
In Tarantool an error object can be returned in 2 ways: as an exception and as an object. For example, this is how to throw an error as exception:
function throw_error()
box.error({code = 1000, reason = "Error message"})
-- Or
error('Some error string')
end
This is how to return it as an object:
function return_error()
return box.error.new({code = 1000, reason = "Error message"})
end
If the function was called remotely, using IPROTO protocol via a connector like netbox, or PHP connector, or any other one, the error return way affects how it is encoded into MessagePack response packet. When the function throws, and the error reaches the top stack frame without being caught, it is encoded as IPROTO_ERROR (82) and IPROTO_ERROR_24 (49).
When the error object is returned as a regular value, not as an exception, it is encoded also as a regular value, inside IPROTO_DATA (48). Just like a string, a number, a tuple, etc.
With encoding as IPROTO_ERROR/IPROTO_ERROR_24 there is no much of a configuration space. Format of these values can't be changed. IPROTO_ERROR is always returned as a MessagePack map, with a stack of errors in it. IPROTO_ERROR_24 is always an error message. The IPROTO_ERROR_24 field is kept for compatibility with connectors to Tarantool versions < 2.4.1.
With encoding as a part of IPROTO_DATA you can choose serialization way using error_marshaling_enabled option. When it is true, errors are encoded as MessagePack extension type MP_EXT, and contain the whole error stack, encoded exactly like IPROTO_ERROR value. When the option is false (default behaviour in 2.4.1), the error is encoded as a string, MP_STR, which is the error's message. If there is a stack of errors, only the newest error is encoded.
error_marshaling_enabled option exists for backward compatibility, in case your application on Tarantool wants to be compatible with old connectors, which don't support MP_EXT encoded errors.
In Tarantool < 2.4.1 errors were encoded into result MessagePack as a string with error message, and error stacks didn't exist at all. So when the new format and the error stacks feature were introduced, making the new format default would be a too radical change breaking the old connectors.
Consider these examples of how error marshaling affects results. I use Tarantool 2.4.1 console here, and built-in netbox connector. The code below can be copy pasted into the console.
First instance:
box.cfg{listen = 3313}
box.schema.user.grant('guest', 'super')
function throw_error()
box.error({code = 1000, reason = "Error message"})
end
function return_error()
return box.error.new({code = 1000, reason = "Error message"})
end
Second instance:
netbox = require('net.box')
c = netbox.connect(3313)
Now I try to call the function on the second instance:
tarantool> c:call('throw_error')
---
- error: Error message
...
The c:call('throw_error') threw an exception. If I catch it using pcall() Lua function, I will see the error object.
tarantool> ok, err = pcall(c.call, c, 'throw_error')
tarantool> err:unpack()
---
- code: 1000
base_type: ClientError
type: ClientError
message: Error message
trace:
- file: '[string "function throw_error()..."]'
line: 2
...
As you can see, I didn't set error_marshaling_enabled, but got the full error. Now I will call the other function, without exceptions. But the error object won't be full.
tarantool> err = c:call('return_error')
tarantool> err
---
- Error message
...
tarantool> err:unpack()
---
- error: '[string "return err:unpack()"]:1: attempt to call method ''unpack'' (a nil
value)'
...
The error was returned as a mere string, error message. Not as an error object. Now I will turn on the marshaling:
tarantool> c:eval('box.session.settings.error_marshaling_enabled = true')
---
...
tarantool> err = c:call('return_error')
---
...
tarantool> err:unpack()
---
- code: 1000
base_type: ClientError
type: ClientError
message: Error message
trace:
- file: '[C]'
line: 4294967295
...
Now the same function returned the error in the new format, more featured.
On the summary: error_marshaling_enabled affects only returned errors. Not thrown errors.

Empty Object for a variable when debugging node

For my node project I have a dependency for the module node-config.
At the very beginning of my project's entry point I set global.conf = require('config').
When I start the debugger in vs-code and check the value of conf it seems to be an empty object.
But when my project starts without debugger attached and just console.log for conf it has the value expected.
For example:
api.js
...
global.conf = require('config');
const utils = require('./lib/utils');
...
utils.js
...
exports.redisClient = new Redis(conf.session.connection);
...
Although when running the project conf.session.connection has the expected value when running the debugger it throws the above error:
Exception has occurred: TypeError
TypeError: Cannot read property 'connection' of undefined

How to iterate over a string to construct nagios_service check as exported resource?

I wrote a custom fact, which returns a comma separated list of addr:port, like this:
sb_intl_conn => sbcms-t:22,sbsql05-wvuk-inst5:1434,sborc07-uk-t:1533,..,..,..
The number of elements in the string varies from node to node. I need to do a Nagios tcp-port-check on each of them. I think sb_intl_conn.split(",") will turn this string into an array and then how can I iterate over it to do something like this?
##nagios_service { "check_stat_${::fqdn}_${addr}_${port}":
use => 'generic-service',
check_command => "remote-nrpe-tcp-check!${addr}!${port}",
service_description => "V2::CON: ${addr} [Palms]",
display_name => "Connection check: ${addr}:${port}",
servicegroups => 'batch-worker',
hostgroup_name => 'batch-job',
}
Any help would be greatly appreciated. Cheers!!
Update: 1
I was tying to simulator iamauser's suggestion but not been able to get my head around it yet. This is what I did: in my foo.pp:
class test::foo {
define bar {
$var1 = inline_template("<%= scope.lookupvar($name).split(':').first.to_s.chomp %>")
$var2 = inline_template("<%= scope.lookupvar($name).split(':').last.to_s.chomp %>")
notify {"${var1}_${var2}": }
}
}
and then in my node.pp:
$ifs = ['abc.com:80','xyz.co.uk:1512']
test::foo::bar {$ifs:}
which throws in these error on the node:
err: Could not retrieve catalog from remote server: Error 400 on SERVER: Failed to parse inline template: Could not find value for 'abc' in 65 at /etc/puppet/services/test/manifests/foo.pp:4 on node jobserver-01.local.cloud.uk
warning: Not using cache on failed catalog
err: Could not retrieve catalog; skipping run
Don't understand what I'm doing wrong. And why is Could not find value for 'abc'; not abc.com? Any idea?? Cheers!!
Update: 2
I ended up using heira and decided to give a try to the original "array of hashes" idea and having some problem implementing:
This is what I have in heira:
hiera -d -c /etc/puppet/hiera.yaml nag_chk m_env=talend s_env=local
[ ... ]
DEBUG: Thu Mar 21 12:28:02 +0000 2013: Got answer for key nagi_chk, final answer
DEBUG: Thu Mar 21 12:28:02 +0000 2013: Answer after outer loop = archimedes-db-02.svc.ft.com:1521 ftftp01-uvln-uk-p:22 www.google.com:80 ftaps01-lvpr-uk-local:8080
archimedes-db-02:1521 ftftp01-uvln-uk-p:22 google.com:80
Then, in my foo.pp
class test::foo {
define bar2 () {
$var1 = $name['addr']
$var2 = $name['port']
notify {"*** ${var1}_${var2} *********": }
}
}
and my node.pp:
$array_chk = hiera('nag_chk')
$urls = inline_template("<%= '$array_chk'.split(' ').map{|kv| v1,v2 = kv.split(':'); {'addr' => v1, 'port' => v2}} -%>")
test::foo::bar2 {$urls:}
and as usual, I get an error:
err: Could not retrieve catalog from remote server: Error 400 on
SERVER: name is not an hash or array when accessing it with 0 at
/etc/puppet/services/talend/talend/manifests/foo.pp:10 on node
talend-jobserver-01.local.cloud.ft.com warning: Not using cache on
failed catalog err: Could not retrieve catalog; skipping run
What's am I doing wrong? As far as I can see, the "array of hash" in right format in the irb console:
irb(main):001:0> STRING = "archimedes-db-02:1521 ftftp01-uvln-uk-p:22 google.com:80"
=> "archimedes-db-02:1521 ftftp01-uvln-uk-p:22 google.com:80"
irb(main):003:0>
irb(main):002:0> STRING.split(' ').map{|kv| v1,v2 = kv.split(':'); {'addr' => v1, 'port' => v2}}
=> [{"addr"=>"archimedes-db-02", "port"=>"1521"}, {"addr"=>"ftftp01-uvln-uk-p", "port"=>"22"}, {"addr"=>"google.com", "port"=>"80"}]
any further thought(s)? Cheers!!
This example may help solve your particular case.
$foo = [{"addr" => "bar", "port" => "1"},
{"addr" => "bat", "port" => "2"}]
testmod::bar {$foo:}
define testmod::bar () {
$var1 = $name["addr"]
$var2 = $name["port"]
notify {"${var1}_${var2}": }
}
Put the nagios type inside the define type. You may have to change the csv to a hash.
UPDATE: Added after #MacUsers update. The following works for me :
$foo = ["abc.com:80","xyz.co.uk:1512"]
testmod::bar {$foo:}
define testmod::bar () {
$var1 = inline_template("<%= '$name'.split(':').first.to_s.chomp %>")
$var2 = inline_template("<%= '$name'.split(':').last.to_s.chomp %>")
notify {"${var1}_${var2}": }
}
Running puppet agent gives me this :
Notice: /Stage[main]/Testmodule/Testmodule::Testmod::Bar[abc.com:80]/Notify[abc.com_80]/message: defined 'message' as 'abc.com_80'
Notice: xyz.co.uk_1512
Notice: /Stage[main]/Testmodule/Testmodule::Testmod::Bar[xyz.co.uk:1512]/Notify[xyz.co.uk_1512]/message: defined 'message' as 'xyz.co.uk_1512'

Resources