import { displayForm } from './common'
import { getSettings } from './settings'
/**
* Export topology as config.
*
* @param {object} e - Event object
*/
const exportTopology = (e) => {
e.preventDefault()
e.stopPropagation()
document.querySelector('#importBtn').classList.remove('hidden')
const exports = {
description: '',
producers: [],
consumers: [],
exchanges: [],
queues: [],
bindings: []
}
const exchanges = window.scene.getObjectsInScene('Exchange')
exchanges.forEach((val) => {
let alternate = null
if (val.alternate) {
alternate = val.alternate.name
}
exports.exchanges.push({
x: val.x,
y: val.y,
name: val.name,
type: val.type,
alternate
})
})
const queues = window.scene.getObjectsInScene('Queue')
queues.forEach((val) => {
const q = {
x: val.x,
y: val.y,
name: val.name,
ttl: val.ttl,
maxLength: val.maxLength
}
if (val.dlx) {
const exchangeIndex = exchanges.findIndex((e) => e.id === val.dlx.id)
q.dlx = exchangeIndex
}
exports.queues.push(q)
})
const bindings = window.scene.getObjectsInScene('Binding')
bindings.forEach((val) => {
const exchangeIndex = exchanges.findIndex((e) => e.id === val.source.id)
const queueIndex = queues.findIndex((q) => q.id === val.destination.id)
if (exchangeIndex !== -1 && queueIndex !== -1) {
exports.bindings.push({
exchange: exchangeIndex,
queue: queueIndex,
routingKey: val.routingKey
})
}
})
const consumers = window.scene.getObjectsInScene('Consumer')
consumers.forEach((val) => {
const consumes = []
val.queues.forEach((queue) => {
const queueIndex = queues.findIndex((q) => q.id === queue.id)
consumes.push(queueIndex)
})
exports.consumers.push({
x: val.x,
y: val.y,
name: val.name,
consumes,
mode: val.mode
})
})
const producers = window.scene.getObjectsInScene('Producer')
producers.forEach((val) => {
const publishes = {}
for (const key in val.publishes) {
publishes[key] = {
exchange: val.publishes[key].exchange.name,
routingKey: val.publishes[key].routingKey,
message: val.publishes[key].message
}
}
exports.producers.push({
x: val.x,
y: val.y,
name: val.name,
publishes
})
})
document.querySelector('#ImExport').value = JSON.stringify(exports)
document.querySelector('#imexportPanel').classList.add('panel-wrap-out')
}
/**
* Export topology as curl statements.
*
* @param {object} e - Event object
*/
const exportCurl = (e) => {
e.preventDefault()
e.stopPropagation()
displayForm('imexportForm')
document.querySelector('#importBtn').classList.add('hidden')
let generatedString = ''
const brokerSettings = getSettings()
const { management } = brokerSettings
const { username } = brokerSettings
const { password } = brokerSettings
const { vhost } = brokerSettings
const exchanges = window.scene.getObjectsInScene('Exchange')
exchanges.forEach((val) => {
const name = encodeURIComponent(val.name)
const args = {}
if (val.alternate !== null) {
args['alternate-exchange'] = val.alternate.name
}
generatedString += `curl -u ${username}:${password} -i -H "content-type:application/json" -XPUT ${management}/exchanges/${vhost}/${name} -d '{"type": "${val.type}", "auto_delete": false, "durable": true, "internal": false, "arguments": ${JSON.stringify(
args
)}}'\n\n`
})
const queues = window.scene.getObjectsInScene('Queue')
queues.forEach((val) => {
const name = encodeURIComponent(val.name)
const args = {}
if (val.dlx) {
args['x-dead-letter-exchange'] = val.dlx.name
args['x-dead-letter-routing-key'] = val.dlxrk
}
if (val.msgTtl) {
args['x-message-ttl'] = val.msgTtl
}
if (val.maxLength) {
args['x-max-length'] = val.maxLength
}
generatedString += `curl -u ${username}:${password} -i -H "content-type:application/json" -XPUT ${management}/queues/${vhost}/${name} -d '{"auto_delete": false, "durable": true, "arguments": ${JSON.stringify(
args
)}}'\n\n`
})
const bindings = window.scene.getObjectsInScene('Binding')
bindings.forEach((val) => {
const exchangeIndex = exchanges.findIndex((e) => e.id === val.source.id)
const queueIndex = queues.findIndex((q) => q.id === val.destination.id)
if (exchangeIndex !== -1 && queueIndex !== -1) {
const exchange = exchanges[exchangeIndex]
const queue = queues[queueIndex]
generatedString += `curl -u ${username}:${password} -i -H "content-type:application/json" -XPOST ${management}/bindings/${vhost}/e/${encodeURIComponent(
exchange.name
)}/q/${encodeURIComponent(queue.name)} -d '{"routing_key": ${
val.routingKey
}, "arguments": {}}'\n\n`
}
})
document.querySelector('#ImExport').value = generatedString
document.querySelector('#imexportPanel').classList.add('panel-wrap-out')
}
/**
* Export topology as rabbitmqadmin statements.
*
* @param {object} e - Event object
*/
const exportRabbitmqadmin = (e) => {
e.preventDefault()
e.stopPropagation()
displayForm('imexportForm')
document.querySelector('#importBtn').classList.add('hidden')
let generatedString = ''
const brokerSettings = getSettings()
const { management } = brokerSettings
const { username } = brokerSettings
const { password } = brokerSettings
const url = new URL(management)
let { vhost } = brokerSettings
if (vhost === '%2f') {
vhost = '/'
}
const exchanges = window.scene.getObjectsInScene('Exchange')
exchanges.forEach((val) => {
generatedString += `rabbitmqadmin -H ${url.hostname} -u ${username} -p ${password} -V ${vhost} declare exchange `
generatedString += `name="${val.name}" type="${val.type}" durable=true`
if (val.alternate !== null) {
generatedString += ` arguments='${JSON.stringify({"alternate-exchange": val.alternate.name})}'`
}
generatedString += `\n\n`
})
const queues = window.scene.getObjectsInScene('Queue')
queues.forEach((val) => {
const args = {}
if (val.dlx) {
args['x-dead-letter-exchange'] = val.dlx.name
args['x-dead-letter-routing-key'] = val.dlxrk
}
if (val.msgTtl) {
args['x-message-ttl'] = val.msgTtl
}
if (val.maxLength) {
args['x-max-length'] = val.maxLength
}
generatedString += `rabbitmqadmin -H ${url.hostname} -u ${username} -p ${password} -V ${vhost} declare queue name="${val.name}" durable=true`
if (Object.keys(args).length !== 0) {
generatedString += ` arguments='${JSON.stringify(args)}'`
}
generatedString += '\n\n'
})
const bindings = window.scene.getObjectsInScene('Binding')
bindings.forEach((val) => {
const exchangeIndex = exchanges.findIndex((e) => e.id === val.source.id)
const queueIndex = queues.findIndex((q) => q.id === val.destination.id)
if (exchangeIndex !== -1 && queueIndex !== -1) {
const exchange = exchanges[exchangeIndex]
const queue = queues[queueIndex]
generatedString += `rabbitmqadmin -H ${url.hostname} -u ${username} -p ${password} -V ${vhost} declare binding source="${exchange.name}" destination_type="queue" destination="${queue.name}" routing_key="${val.routingKey}"\n\n`
}
})
document.querySelector('#ImExport').value = generatedString
document.querySelector('#imexportPanel').classList.add('panel-wrap-out')
}
/**
* Export topology as Terraform.
*
* @param {object} e - Event object
*/
const exportTerraform = (e) => {
e.preventDefault()
e.stopPropagation()
displayForm('imexportForm')
document.querySelector('#importBtn').classList.add('hidden')
let generatedString = ''
const brokerSettings = getSettings()
const { management } = brokerSettings
const { username } = brokerSettings
const { password } = brokerSettings
const url = new URL(management)
let { vhost } = brokerSettings
if (vhost === '%2f') {
vhost = '/'
}
generatedString += `terraform {
required_providers {
rabbitmq = {
source = "cyrilgdn/rabbitmq"
version = "1.8.0"
}
}
}
provider "rabbitmq" {
endpoint = "${url.origin}"
username = "${username}"
password = "${password}"
}
resource "rabbitmq_vhost" "vhost" {
name = "${vhost}"
}
`
const exchanges = window.scene.getObjectsInScene('Exchange')
exchanges.forEach((val) => {
const name = val.name.replace(/ /g, '-')
generatedString += `resource "rabbitmq_exchange" "${name}" {
name = "${val.name}"
vhost = "\${rabbitmq_vhost.vhost.name}"
settings {
type = "${val.type}"
durable = true
auto_delete = false
}
}
`
})
const queues = window.scene.getObjectsInScene('Queue')
queues.forEach((val) => {
const name = val.name.replace(/ /g, '-')
if (val.dlx || val.msgTtl || val.maxlength) {
generatedString += `variable "${name}args" {
default = <<EOF
{
`
const extra = []
if (val.dlx) {
extra.push(`"x-dead-letter-exchange": "${val.dlx.name}"`)
extra.push(`"x-dead-letter-routing-key": "${val.dlxrk}"`)
}
if (val.msgTtl) {
extra.push(`"x-message-ttl": ${val.msgTtl}`)
}
if (val.maxLength) {
extra.push(`"x-max-length": ${val.maxLength}`)
}
generatedString += ` ${extra.join(',\n ')}`
generatedString += `
}
EOF
}
`
}
generatedString += `resource "rabbitmq_queue" "${name}" {
name = "${val.name}"
vhost = "\${rabbitmq_vhost.vhost.name}"
settings {
durable = true
auto_delete = false`
if (val.dlx || val.msgTtl || val.maxlength) {
generatedString += `
arguments_json = "\${var.${name}args}"`
}
generatedString += `
}
}
`
})
const bindings = window.scene.getObjectsInScene('Binding')
bindings.forEach((val) => {
const srcName = val.source.name.replace(/ /g, '-')
const destName = val.destination.name.replace(/ /g, '-')
generatedString += `resource "rabbitmq_binding" "${srcName}${destName}" {
source = "\${rabbitmq_exchange.${srcName}.name}"
vhost = "\${rabbitmq_vhost.vhost.name}"
destination = "\${rabbitmq_queue.${destName}.name}"
destination_type = "queue"
routing_key = "${val.routingKey}"
}
`
})
document.querySelector('#ImExport').value = generatedString
document.querySelector('#importBtn').classList.add('hidden')
document.querySelector('#imexportPanel').classList.add('panel-wrap-out')
}
/**
* Export topology as AsyncApi.
*
* @param {object} e - Event object
*/
const exportAsyncApi = (e) => {
e.preventDefault()
e.stopPropagation()
displayForm('imexportForm')
document.querySelector('#importBtn').classList.add('hidden')
let generatedString = ''
const brokerSettings = getSettings()
const { host } = brokerSettings
const { title, description, version } = brokerSettings.asyncapi
let { vhost } = brokerSettings
if (vhost === '%2f') {
vhost = '/'
}
const exchanges = window.scene.getObjectsInScene('Exchange')
const queues = window.scene.getObjectsInScene('Queue')
generatedString += `asyncapi: 3.0.0
info:
title: ${title}
description: ${description}
version: ${version}
termsOfService: https://asyncapi.org/terms/
contact:
name: API Support
url: https://www.asyncapi.org/support
email: support@asyncapi.org
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0.htm
servers:
production:
host: ${host}
protocol: amqps
protocolVersion: 0.9.1
description: Production broker.
tags:
- name: env:production
description: This environment is the live environment available for final users
channels:
`
exchanges.forEach((val) => {
if (val.type === 'topic') {
val.bindings.forEach((v) => {
if (v.routingKey !== '#') {
generatedString += ` ${val.name.replaceAll(' ', '_')}_${v.routingKey}:
address: '${v.routingKey}'
messages:
event:
$ref: '#/components/messages/Event'
bindings:
amqp:
is: routingKey
exchange:
name: ${v.source.name}
type: 'topic'
durable: true
autoDelete: false
vhost: ${vhost}
`
}
})
} else {
generatedString += ` ${val.name.replaceAll(' ', '_')}:
messages:
event:
$ref: '#/components/messages/Event'
bindings:
amqp:
is: routingKey
exchange:
name: ${val.name}
type: '${val.type}'
durable: true
autoDelete: false
vhost: ${vhost}
`
}
})
queues.forEach((val) => {
generatedString += ` ${val.name.replaceAll(' ', '_')}:
messages:
event:
$ref: '#/components/messages/Event'
bindings:
amqp:
is: queue
queue:
name: ${val.name}
durable: true
exclusive: true
autoDelete: false
`
})
generatedString += `operations:`
exchanges.forEach((val) => {
val.bindings.forEach((v) => {
if (v.routingKey !== '#') {
generatedString += `
send${val.name}/${v.routingKey}:
channel:
$ref: '#/channels/${val.name.replaceAll(' ', '_')}_${v.routingKey}'
action: send`
}
})
})
queues.forEach((val) => {
generatedString += `
receive${val.name.replaceAll(' ', '_')}:
channel:
$ref: '#/channels/${val.name.replaceAll(' ', '_')}'
action: receive`
})
// remove two to start again
//generatedString = generatedString.slice(0, -2)
generatedString += `
components:
messages:
Event:
name: EventName
title: Event Title
summary: Summary of the event.
description: Event description
contentType: application/json
tags:
- name: message
- name: example
headers:
type: object
properties:
correlationId:
description: Correlation ID set by application
type: string
applicationInstanceId:
description: Unique identifier for a given instance of the publishing application
type: string
payload:
type: object
additionalProperties: false
properties:
created:
type: string
description: The date and time a message was sent.
format: datetime
name:
type: string
description: The name of the message was sent.
value:
type: string
description: The value of the message was sent.`
document.querySelector('#ImExport').value = generatedString
document.querySelector('#imexportPanel').classList.add('panel-wrap-out')
}
export { exportTopology, exportCurl, exportRabbitmqadmin, exportTerraform, exportAsyncApi }