RabbitMQ exchange bind replicating messages published to one exchange across two other exchanges - binding

I have 3 different exchanges in my rabbitMQ i am trying to route all the messages sent to mainex across the other two exchanges dmyex and monex i tried to use the channel.exchngeBind method to bind the exchanges.
I am still not able to see the messages published to mainex going to dmyex and monex.
Is this possible in RabbitMq?
Is there any mistake in what i am doing here?
ch.exchangeDeclare("mainex", DIRECT_EXCHANGE_TYPE, true, false, null);
ch.exchangeDeclare("dmyex", CONSISTENT_HASH_EXCHANGE_TYPE, true, false, null);
ch.exchangeDeclare("monex", CONSISTENT_HASH_EXCHANGE_TYPE, true, false, null);
ch.exchangeBind("dmyex","mainex","abcd_KEY");
ch.exchangeBind("monex","mainex","abcd_KEY");

I think that the exchange mainex will need to be a Topic exchange in order for wildcard routing to work, as Direct exchanges do their routing based on exact matching of the routing key. Per this CloudAMQP blog post on exchange types and routing:
A direct exchange delivers messages to queues based on a message routing key. The routing key is a message attribute added to the message header by the producer. Think of the routing key as an "address" that the exchange is using to decide how to route the message. A message goes to the queue(s) with the binding key that exactly matches the routing key of the message.
(This is also touched on in this answer to a question about wildcard routing keys on SO)
That should be enough to get your routing working. Perhaps even more simply, if you are going to match any routing key for all of your exchanges that are bound to mainex, you could just make mainex a Fanout exchange.

Just figured out the below model is working.
ch.exchangeDeclare("mainex", DIRECT_EXCHANGE_TYPE, true, false, null);
ch.exchangeDeclare("dmyex", CONSISTENT_HASH_EXCHANGE_TYPE, true, false, null);
ch.exchangeDeclare("mongoex", CONSISTENT_HASH_EXCHANGE_TYPE, true, false, null);
ch.exchangeBind("dmyex","mainex", "abcd_KEY");
ch.exchangeBind("monex","mainex", "abcd_KEY");
for (String q : Arrays.asList("sharding: dmyex - rabbit#node1 - 0", "sharding: dmyex - rabbit#node2 - 0","sharding: dmyex - rabbit#node3 - 0","sharding: dmyex - rabbit#node4 - 0","sharding: dmyex - rabbit#node5 - 0","sharding: dmyex - rabbit#node6 - 0")) {
ch.queueBind(q, "dmyex", "1");
}
for (String q : Arrays.asList("sharding: mongoex - rabbit#node1 - 0", "sharding: mongoex - rabbit#node2 - 0","sharding: mongoex - rabbit#node3 - 0","sharding: mongoex - rabbit#node4- 0","sharding: mongoex - rabbit#node5 - 0","sharding: mongoex - rabbit#node6 - 0")) {
ch.queueBind(q, "mongoex", "1");
}
AMQP.BasicProperties.Builder bldr = new AMQP.BasicProperties.Builder();
for (int i = 0; i < 10; i++) {
ch.basicPublish("mainex", "abcd_KEY", bldr.build(), "TestMessage".getBytes("UTF-8"));````

Related

How to add PTR record for EC2 Instance's Private IP in CDK?

I've two private hosted zones created for populating A records and PTR records corresponding to my EC2 instance's private ip. Yes, it's the private ip that I need. This subnet is routed to our corporate data center, so we need non-cryptic hostnames and consistent reverse lookup on them within the account.
I've got the forward lookup working well, however I'm confused how exactly it should be for the reverse lookup on the IP. Assume, my CIDR is 192.168.10.0/24 where the EC2 instances will get created.
const fwdZone = new aws_route53.PrivateHostedZone(
this, "myFwdZone", {
zoneName: "example.com",
vpc: myVpc,
});
const revZone = new aws_route53.PrivateHostedZone(
this, "myRevZone", {
zoneName: "10.168.192.in-addr.arpa",
vpc: myVpc,
}
);
I'm later creating the A record by referencing the EC2 instance's privateIp property. This worked well.
const myEc2 = new aws_ec2.Instance(this, 'myEC2', {...})
new aws_route53.RecordSet(this, "fwdRecord", {
zone: fwdZone,
recordName: "myec2.example.com",
recordType: aws_route53.RecordType.A,
target: aws_route53.RecordTarget.fromIpAddresses(
myEc2.instancePrivateIp
),
});
However, when I try to create the PTR record for the same, I've got some trouble. I needed to extract the fourth octet and specify as the recordName
new aws_route53.RecordSet(this, "revRecord", {
zone: revZone,
recordName: myEc2.instancePrivateIp.split('.')[3],
recordType: aws_route53.RecordType.PTR,
target: aws_route53.RecordTarget.fromValues("myec2.example.com"),
});
The CDK synthesized CloudFormation template looks odd as well, especially the token syntax.
revRecordDEADBEEF:
Type: AWS::Route53::RecordSet
Properties:
Name: ${Token[TOKEN.10.168.192.in-addr.arpa.
Type: PTR
HostedZoneId: A12345678B00CDEFGHIJ3
ResourceRecords:
- myec2.example.com
TTL: "1800"
Is this the right way to achieve this ? If I specified the recordName as just the privateIp, then the synthesized template ends up doing something else, which I see is incorrect too.
revRecordDEADBEEF:
Type: AWS::Route53::RecordSet
Properties:
Name:
Fn::Join:
- ""
- - Fn::GetAtt:
- myEC2123A01BC
- PrivateIp
- .10.168.192.in-addr.arpa.
Type: PTR
HostedZoneId: A12345678B00CDEFGHIJ3
ResourceRecords:
- myec2.example.com
TTL: "1800"
Answering the CDK part of your question: the original error was because you were performing string manipulation on an unresolved token. Your CDK code runs before any resources are provisioned. This has to be the case, since it generates the CloudFormation template that will be submitted to CloudFormation to provision the resources. So when the code runs, the instance does not exist, and its IP address is not knowable.
CDK still allows you to access unresolved properties, returning a Token instead. You can pass this token around and it will be resolved to the actual value during deployment.
To perform string manipulation on a token, you can use CloudFormation's bult-in functions, since they run during deployment, after the token has been resolved.
Here's what it would look like:
recordName: Fn.select(0, Fn.split('.', myEc2.instancePrivateIp))
As you found out yourself, you were also selecting the wrong octet of the IP address, so the actual solution would include replacing 0 with 3 in the call.
References:
https://docs.aws.amazon.com/cdk/v2/guide/tokens.html
https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib-readme.html#intrinsic-functions-and-condition-expressions

Open Api swagger docs with service names of the format ***-service

I have a java spring boot service mesh of services.
I am using open api for swagger documentation.
When I run my spring cloud gateway and access http://localhost:{my-port}/swagger-ui.html, it works fine and loads the swagger ui which mentions /v3/api-docs in the "Explore" title bar.
Also, when I add the service name to the url like so /v3/api-docs/my-service, it works fine.
However, I want to try a list of dropdown services instead of manually appending the service name for each service. I have tried this grouping code in my gateway:
#Bean
fun apis(): List<GroupedOpenApi> {
val groups = ArrayList<GroupedOpenApi>()
val definitions = locator!!.routeDefinitions.collectList().block()
definitions!!.stream().filter { routeDefinition -> routeDefinition.id.matches(".*-service".toRegex()) }.forEach { routeDefinition ->
val name = routeDefinition.id.replace("-service".toRegex(), "")
GroupedOpenApi.builder().pathsToMatch("/$name/**").setGroup(name).build()
}
return groups
}
Now, after this when I access http://localhost:{my-port}/swagger-ui.html, it shows a drop down list of all the service with the "-service" removed. But after selection, the docs don't show up.
Although, if I access it in a separate tab with http://localhost:{my-port}/v3/api-docs/my-service, it shows me the json of all the paths and works fine. Just doesn't load in the swagger ui.
Here's gateway route for one of the service and openapi:
- id: my-service
uri: lb://my-service
predicates:
- Path=/api/v1/my/**
filters:
- name: CircuitBreaker
args:
name: my-service
fallbackuri: forward:/myServiceFallBack

Redirect www to non-www not working in Traefik 2

I sett up Traefik to manage my docker containers but I can redirect www to non-www for my domain. I've tried everything in the forums but no luck
labels:
- "traefik.enable=true"
- "traefik.http.routers.node.entrypoints=http"
- "traefik.http.routers.node.rule=Host(`awebsite.com`) || Host(`www.awebsite.com`)"
- "traefik.http.middlewares.vk-https-redirect.redirectscheme.scheme=https"
- "traefik.http.middlewares.test-redirectregex.redirectregex.regex=^https://www.awebsite.com/(.*)"
- "traefik.http.middlewares.test-redirectregex.redirectregex.replacement=https://awebsite.com/$${1}"
- "traefik.http.routers.node.middlewares=vk-https-redirect"
- "traefik.http.routers.node-secure.entrypoints=https"
- "traefik.http.routers.node-secure.rule=Host(`awebsite.com`) || Host(`www.awebsite.com`)"
- "traefik.http.routers.node-secure.tls=true"
- "traefik.http.routers.node-secure.tls.certresolver=http"
- "traefik.http.routers.node-secure.service=node"
- "traefik.http.services.node.loadbalancer.server.port=8000"
- "traefik.docker.network=proxy"
It not enough to define the redirect middleware, you also need to use it with the defined routers
here is you middleware definitions
- "traefik.http.middlewares.test-redirectregex.redirectregex.regex=^https://www.awebsite.com/(.*)"
- "traefik.http.middlewares.test-redirectregex.redirectregex.replacement=https://awebsite.com/$${1}"
you may need to add this lable too
traefik.http.middlewares.test-redirectregex.redirectregex.permanent=true
but you never used it in any of the defined routers. For instance, if you want this to apply to node-secure router, you need to add this label
- "traefik.http.routers.node-secure.middlewares=test-redirectregex"
More information, details, and examples can be found in this article
- "traefik.http.routers.node-secure.middlewares=test-redirectregex"

Zapier StoreClient undefined

I'm trying to store state between calls similar to the documentation here: https://zapier.com/apps/code/help#code-examples
However, I try to run the code from a Zap, I get:
StoreClient is not defined
The documentation states that I shouldn't have to require anything to use StoreClient: "There is no need to require it - it comes pre-imported in your Code environment."
I'm on the latest version of zapier-platform-core (8.3.0).
I'm using the exact code from the example linked above.
const count = await store.get('some counter')
const newCount = (count || 0) + 1;
await store.set('some counter', count);
return {count: newCount};
David here, from the Zapier Platform team. Great question!
This is a little bit unclear based on the docs - StoreClient is only available in the Code app (aka Code by Zapier). If you're using zapier-platform-core, you're creating a cli app, which is a vanilla node.js environment. If you want to interact with Storage by Zapier from within a cli app, you can use the docs on the site: https://store.zapier.com. Namely:
{
"how does it work?": {
"always provide either `?secret=12345` or `X-Secret: 12345`": "",
"GET /api/secret": [
"will return a random secret for you to use if you need one."
],
"GET /api/records": [
"will return a full object of all values stored by default.",
"you can also specify only the keys you want via the",
"querystring like`?key=color&key=age`."
],
"POST /api/records": [
"provide a body with a json object with keys/values you want",
"to store like `{\"color\": \"blue\", \"age\": 29}`."
],
"DELETE /api/records": ["completely clear all the records in this account"],
"PATCH /api/records": [
"A data with a particular schema needs to be received.",
"The schema specifies which action to do and with what parameters.",
"For example {\"action\": \"increment_by\", \"data\": {\"key\": \"<key_name>\", \"amount\": 1}} to increment the value specified by \"key\"."
]
}
}
Requests to those endpoints can be made using the standard z.request, which is well-documented here: https://github.com/zapier/zapier-platform/tree/master/packages/cli#making-http-requests

Dropwizard admin security

Is there a way of adding login security to the admin servlet?
Seems like in V0.7 you could add the following two to your yaml file :
adminUsername: user1234
adminPassword: pass5678
However I tried that in the latest version (0.9.2) and it gives me an error saying :
server.yaml has an error:
* Unrecognized field at: server.adminConnectors.[0].adminUsername
Did you mean?:
- soLingerTime
- bindHost
- idleTimeout
- useServerHeader
- useDateHeader
[14 more]
This is what I have :
adminConnectors:
- type: http
port: 9180
adminUsername: user1234
adminPassword: pass5678
I run an app on Heroku which only allows the application to make a single port available. I attach the AdminServlet to the main HTTP port (8080) with this in the run() method of my Application (Kotlin):
environment.applicationContext.apply {
setAttribute(MetricsServlet.METRICS_REGISTRY, environment.metrics())
setAttribute(HealthCheckServlet.HEALTH_CHECK_REGISTRY, environment.healthChecks())
addServlet(NonblockingServletHolder(AdminServlet()), "/admin/*")
}
Then, I protect this path with a BasicAuthFilter (still Kotlin, you should use it):
val basicAuthFilter = BasicAuthFilter("admin", configuration.adminUsername, configuration.adminPassword)
val adminFilter = environment.servlets().addFilter("AdminFilter", basicAuthFilter)
adminFilter.addMappingForUrlPatterns(EnumSet.of(DispatcherType.REQUEST), false, "/admin/*")

Resources