mirror of
https://github.com/absmach/supermq.git
synced 2026-06-23 07:40:17 +00:00
NOISSUE - Remove SuperMQ duplicates (#23)
* Update docker-compose to use SuperMQ Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Remove duplicate services Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Update Bootstrap Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Update other services to use SMQ Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Switch config prefix to SMQ Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Remove leftovers Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Remove duplicate interface definitions Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Remove unused actions Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Remove unused API docs Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Resolve linter comments Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> * Fix provision Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com> --------- Signed-off-by: Dusan Borovcanin <borovcanindusan1@gmail.com>
This commit is contained in:
@@ -24,15 +24,18 @@ linters-settings:
|
||||
alias:
|
||||
- pkg: github.com/absmach/callhome/pkg/client
|
||||
alias: chclient
|
||||
- pkg: github.com/absmach/magistrala/logger
|
||||
alias: mglog
|
||||
- pkg: github.com/absmach/magistrala/pkg/errors/service
|
||||
- pkg: github.com/absmach/supermq/logger
|
||||
alias: smqlog
|
||||
- pkg: github.com/absmach/supermq/pkg/errors/service
|
||||
alias: svcerr
|
||||
- pkg: github.com/absmach/magistrala/pkg/errors/repository
|
||||
- pkg: github.com/absmach/supermq/pkg/errors/repository
|
||||
alias: repoerr
|
||||
- pkg: github.com/absmach/magistrala/pkg/sdk/mocks
|
||||
- pkg: github.com/absmach/supermq/pkg/sdk/mocks
|
||||
alias: sdkmocks
|
||||
|
||||
- pkg: github.com/absmach/supermq/api/http/util
|
||||
alias: apiutil
|
||||
- pkg: github.com/absmach/supermq/api/http
|
||||
alias: api
|
||||
gocritic:
|
||||
enabled-checks:
|
||||
- importShadow
|
||||
|
||||
@@ -6,25 +6,50 @@ filename: "{{.InterfaceName}}.go"
|
||||
outpkg: "mocks"
|
||||
boilerplate-file: "./tools/config/boilerplate.txt"
|
||||
packages:
|
||||
github.com/absmach/magistrala:
|
||||
github.com/absmach/supermq/api/grpc/clients/v1:
|
||||
interfaces:
|
||||
ThingsServiceClient:
|
||||
ClientsServiceClient:
|
||||
config:
|
||||
dir: "./things/mocks"
|
||||
mockname: "ThingsServiceClient"
|
||||
filename: "things_client.go"
|
||||
dir: "./clients/mocks"
|
||||
mockname: "ClientsServiceClient"
|
||||
filename: "clients_client.go"
|
||||
github.com/absmach/supermq/api/grpc/domains/v1:
|
||||
interfaces:
|
||||
DomainsServiceClient:
|
||||
config:
|
||||
dir: "./auth/mocks"
|
||||
dir: "./domains/mocks"
|
||||
mockname: "DomainsServiceClient"
|
||||
filename: "domains_client.go"
|
||||
github.com/absmach/supermq/api/grpc/token/v1:
|
||||
interfaces:
|
||||
TokenServiceClient:
|
||||
config:
|
||||
dir: "./auth/mocks"
|
||||
mockname: "TokenServiceClient"
|
||||
filename: "token_client.go"
|
||||
github.com/absmach/supermq/api/grpc/channels/v1:
|
||||
interfaces:
|
||||
ChannelsServiceClient:
|
||||
config:
|
||||
dir: "./channels/mocks"
|
||||
mockname: "ChannelsServiceClient"
|
||||
filename: "channels_client.go"
|
||||
github.com/absmach/supermq/api/grpc/groups/v1:
|
||||
interfaces:
|
||||
GroupsServiceClient:
|
||||
config:
|
||||
dir: "./groups/mocks"
|
||||
mockname: "GroupsServiceClient"
|
||||
filename: "groups_client.go"
|
||||
github.com/absmach/supermq/pkg/sdk:
|
||||
interfaces:
|
||||
SDK:
|
||||
config:
|
||||
dir: "./pkg/sdk/mocks"
|
||||
mockname: "SDK"
|
||||
filename: "sdk.go"
|
||||
|
||||
github.com/absmach/magistrala/certs/pki/amcerts:
|
||||
github.com/absmach/supermq/certs/pki/amcerts:
|
||||
interfaces:
|
||||
Agent:
|
||||
config:
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package tools contains tools for Magistrala.
|
||||
// Package tools contains tools for SuperMQ.
|
||||
package tools
|
||||
|
||||
+17
-17
@@ -1,6 +1,6 @@
|
||||
# Magistrala Users Groups Things and Channels E2E Testing Tool
|
||||
# SuperMQ Users Groups Clients and Channels E2E Testing Tool
|
||||
|
||||
A simple utility to create a list of groups and users connected to these groups and channels and things connected to these channels.
|
||||
A simple utility to create a list of groups and users connected to these groups and channels and clients connected to these channels.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -13,11 +13,11 @@ make
|
||||
|
||||
```bash
|
||||
./e2e --help
|
||||
Tool for testing end-to-end flow of Magistrala by doing a couple of operations namely:
|
||||
1. Creating, viewing, updating and changing status of users, groups, things and channels.
|
||||
2. Connecting users and groups to each other and things and channels to each other.
|
||||
3. Sending messages from things to channels on all 4 protocol adapters (HTTP, WS, CoAP and MQTT).
|
||||
Complete documentation is available at https://docs.magistrala.abstractmachines.fr
|
||||
Tool for testing end-to-end flow of SuperMQ by doing a couple of operations namely:
|
||||
1. Creating, viewing, updating and changing status of users, groups, clients and channels.
|
||||
2. Connecting users and groups to each other and clients and channels to each other.
|
||||
3. Sending messages from clients to channels on all 4 protocol adapters (HTTP, WS, CoAP and MQTT).
|
||||
Complete documentation is available at https://docs.supermq.abstractmachines.fr
|
||||
|
||||
|
||||
Usage:
|
||||
@@ -28,7 +28,7 @@ Usage:
|
||||
Examples:
|
||||
|
||||
Here is a simple example of using e2e tool.
|
||||
Use the following commands from the root Magistrala directory:
|
||||
Use the following commands from the root SuperMQ directory:
|
||||
|
||||
go run tools/e2e/cmd/main.go
|
||||
go run tools/e2e/cmd/main.go --host 142.93.118.47
|
||||
@@ -38,19 +38,19 @@ go run tools/e2e/cmd/main.go --host localhost --num 10 --num_of_messages 100 --p
|
||||
Flags:
|
||||
|
||||
-h, --help help for e2e
|
||||
-H, --host string address for a running Magistrala instance (default "localhost")
|
||||
-n, --num uint number of users, groups, channels and things to create and connect (default 10)
|
||||
-H, --host string address for a running SuperMQ instance (default "localhost")
|
||||
-n, --num uint number of users, groups, channels and clients to create and connect (default 10)
|
||||
-N, --num_of_messages uint number of messages to send (default 10)
|
||||
-p, --prefix string name prefix for users, groups, things and channels
|
||||
-p, --prefix string name prefix for users, groups, clients and channels
|
||||
```
|
||||
|
||||
To use `-H` option, you can specify the address for the Magistrala instance as an argument when running the program. For example, if the Magistrala instance is running on another computer with the IP address 192.168.0.1, you could use the following command:
|
||||
To use `-H` option, you can specify the address for the SuperMQ instance as an argument when running the program. For example, if the SuperMQ instance is running on another computer with the IP address 192.168.0.1, you could use the following command:
|
||||
|
||||
```bash
|
||||
go run tools/e2e/cmd/main.go --host 142.93.118.47
|
||||
```
|
||||
|
||||
This will tell the program to connect to the Magistrala instance running on the specified IP address.
|
||||
This will tell the program to connect to the SuperMQ instance running on the specified IP address.
|
||||
|
||||
If you want to create a list of channels with certificates:
|
||||
|
||||
@@ -74,7 +74,7 @@ c8fe4d9d-3ad6-4687-83c0-171356f3e4f6
|
||||
513f7295-0923-4e21-b41a-3cfd1cb7b9b9
|
||||
54bd71ea-3c22-401e-89ea-d58162b983c0
|
||||
ae91b327-4c40-4e68-91fe-cd6223ee4e99
|
||||
created things of ids:
|
||||
created clients of ids:
|
||||
5909a907-7413-47d4-b793-e1eb36988a5f
|
||||
f9b6bc18-1862-4a24-8973-adde11cb3303
|
||||
c2bd6eed-6f38-464c-989c-fe8ec8c084ba
|
||||
@@ -86,8 +86,8 @@ d654948d-d6c1-4eae-b69a-29c853282c3d
|
||||
2c2a5496-89cf-47e6-9d38-5fd5542337bd
|
||||
7ab3319d-269c-4b07-9dc5-f9906693e894
|
||||
5d8fa139-10e7-4683-94f3-4e881b4db041
|
||||
created policies for users, groups, things and channels
|
||||
viewed users, groups, things and channels
|
||||
updated users, groups, things and channels
|
||||
created policies for users, groups, clients and channels
|
||||
viewed users, groups, clients and channels
|
||||
updated users, groups, clients and channels
|
||||
sent messages to channels
|
||||
```
|
||||
|
||||
+12
-12
@@ -1,13 +1,13 @@
|
||||
// Copyright (c) Abstract Machines
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package main contains e2e tool for testing Magistrala.
|
||||
// Package main contains e2e tool for testing SuperMQ.
|
||||
package main
|
||||
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/absmach/magistrala/tools/e2e"
|
||||
"github.com/absmach/supermq/tools/e2e"
|
||||
cc "github.com/ivanpirog/coloredcobra"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -19,14 +19,14 @@ func main() {
|
||||
|
||||
rootCmd := &cobra.Command{
|
||||
Use: "e2e",
|
||||
Short: "e2e is end-to-end testing tool for Magistrala",
|
||||
Long: "Tool for testing end-to-end flow of magistrala by doing a couple of operations namely:\n" +
|
||||
"1. Creating, viewing, updating and changing status of users, groups, things and channels.\n" +
|
||||
"2. Connecting users and groups to each other and things and channels to each other.\n" +
|
||||
"3. Sending messages from things to channels on all 4 protocol adapters (HTTP, WS, CoAP and MQTT).\n" +
|
||||
"Complete documentation is available at https://docs.magistrala.abstractmachines.fr",
|
||||
Short: "e2e is end-to-end testing tool for SuperMQ",
|
||||
Long: "Tool for testing end-to-end flow of supermq by doing a couple of operations namely:\n" +
|
||||
"1. Creating, viewing, updating and changing status of users, groups, clients and channels.\n" +
|
||||
"2. Connecting users and groups to each other and clients and channels to each other.\n" +
|
||||
"3. Sending messages from clients to channels on all 4 protocol adapters (HTTP, WS, CoAP and MQTT).\n" +
|
||||
"Complete documentation is available at https://docs.supermq.abstractmachines.fr",
|
||||
Example: "Here is a simple example of using e2e tool.\n" +
|
||||
"Use the following commands from the root magistrala directory:\n\n" +
|
||||
"Use the following commands from the root supermq directory:\n\n" +
|
||||
"go run tools/e2e/cmd/main.go\n" +
|
||||
"go run tools/e2e/cmd/main.go --host 142.93.118.47\n" +
|
||||
"go run tools/e2e/cmd/main.go --host localhost --num 10 --num_of_messages 100 --prefix e2e",
|
||||
@@ -47,9 +47,9 @@ func main() {
|
||||
})
|
||||
|
||||
// Root Flags
|
||||
rootCmd.PersistentFlags().StringVarP(&econf.Host, "host", "H", "localhost", "address for a running magistrala instance")
|
||||
rootCmd.PersistentFlags().StringVarP(&econf.Prefix, "prefix", "p", "", "name prefix for users, groups, things and channels")
|
||||
rootCmd.PersistentFlags().Uint64VarP(&econf.Num, "num", "n", defNum, "number of users, groups, channels and things to create and connect")
|
||||
rootCmd.PersistentFlags().StringVarP(&econf.Host, "host", "H", "localhost", "address for a running supermq instance")
|
||||
rootCmd.PersistentFlags().StringVarP(&econf.Prefix, "prefix", "p", "", "name prefix for users, groups, clients and channels")
|
||||
rootCmd.PersistentFlags().Uint64VarP(&econf.Num, "num", "n", defNum, "number of users, groups, channels and clients to create and connect")
|
||||
rootCmd.PersistentFlags().Uint64VarP(&econf.NumOfMsg, "num_of_messages", "N", defNum, "number of messages to send")
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
|
||||
+101
-100
@@ -14,7 +14,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/0x6flab/namegenerator"
|
||||
sdk "github.com/absmach/magistrala/pkg/sdk/go"
|
||||
sdk "github.com/absmach/supermq/pkg/sdk"
|
||||
"github.com/gookit/color"
|
||||
"github.com/gorilla/websocket"
|
||||
"golang.org/x/sync/errgroup"
|
||||
@@ -26,7 +26,7 @@ const (
|
||||
numAdapters = 4
|
||||
batchSize = 99
|
||||
usersPort = "9002"
|
||||
thingsPort = "9000"
|
||||
clientsPort = "9000"
|
||||
domainsPort = "8189"
|
||||
)
|
||||
|
||||
@@ -55,17 +55,17 @@ type Config struct {
|
||||
// - Create groups using hierarchy
|
||||
// - Do Read, Update and Change of Status operations on groups.
|
||||
|
||||
// - Create things
|
||||
// - Do Read, Update and Change of Status operations on things.
|
||||
// - Create clients
|
||||
// - Do Read, Update and Change of Status operations on clients.
|
||||
|
||||
// - Create channels
|
||||
// - Do Read, Update and Change of Status operations on channels.
|
||||
|
||||
// - Connect thing to channel
|
||||
// - Connect client to channel
|
||||
// - Publish message from HTTP, MQTT, WS and CoAP Adapters.
|
||||
func Test(conf Config) {
|
||||
sdkConf := sdk.Config{
|
||||
ThingsURL: fmt.Sprintf("http://%s:%s", conf.Host, thingsPort),
|
||||
ClientsURL: fmt.Sprintf("http://%s:%s", conf.Host, clientsPort),
|
||||
UsersURL: fmt.Sprintf("http://%s:%s", conf.Host, usersPort),
|
||||
DomainsURL: fmt.Sprintf("http://%s:%s", conf.Host, domainsPort),
|
||||
HTTPAdapterURL: fmt.Sprintf("http://%s/http", conf.Host),
|
||||
@@ -95,11 +95,11 @@ func Test(conf Config) {
|
||||
}
|
||||
color.Success.Printf("created groups of ids:\n%s\n", magenta(getIDS(groups)))
|
||||
|
||||
things, err := createThings(s, conf, domainID, token)
|
||||
clients, err := createClients(s, conf, domainID, token)
|
||||
if err != nil {
|
||||
errExit(fmt.Errorf("unable to create things: %w", err))
|
||||
errExit(fmt.Errorf("unable to create clients: %w", err))
|
||||
}
|
||||
color.Success.Printf("created things of ids:\n%s\n", magenta(getIDS(things)))
|
||||
color.Success.Printf("created clients of ids:\n%s\n", magenta(getIDS(clients)))
|
||||
|
||||
channels, err := createChannels(s, conf, domainID, token)
|
||||
if err != nil {
|
||||
@@ -107,20 +107,20 @@ func Test(conf Config) {
|
||||
}
|
||||
color.Success.Printf("created channels of ids:\n%s\n", magenta(getIDS(channels)))
|
||||
|
||||
// List users, groups, things and channels
|
||||
if err := read(s, conf, domainID, token, users, groups, things, channels); err != nil {
|
||||
errExit(fmt.Errorf("unable to read users, groups, things and channels: %w", err))
|
||||
// List users, groups, clients and channels
|
||||
if err := read(s, conf, domainID, token, users, groups, clients, channels); err != nil {
|
||||
errExit(fmt.Errorf("unable to read users, groups, clients and channels: %w", err))
|
||||
}
|
||||
color.Success.Println("viewed users, groups, things and channels")
|
||||
color.Success.Println("viewed users, groups, clients and channels")
|
||||
|
||||
// Update users, groups, things and channels
|
||||
if err := update(s, domainID, token, users, groups, things, channels); err != nil {
|
||||
errExit(fmt.Errorf("unable to update users, groups, things and channels: %w", err))
|
||||
// Update users, groups, clients and channels
|
||||
if err := update(s, domainID, token, users, groups, clients, channels); err != nil {
|
||||
errExit(fmt.Errorf("unable to update users, groups, clients and channels: %w", err))
|
||||
}
|
||||
color.Success.Println("updated users, groups, things and channels")
|
||||
color.Success.Println("updated users, groups, clients and channels")
|
||||
|
||||
// Send messages to channels
|
||||
if err := messaging(s, conf, domainID, token, things, channels); err != nil {
|
||||
if err := messaging(s, conf, domainID, token, clients, channels); err != nil {
|
||||
errExit(fmt.Errorf("unable to send messages to channels: %w", err))
|
||||
}
|
||||
color.Success.Println("sent messages to channels")
|
||||
@@ -149,8 +149,8 @@ func createUser(s sdk.SDK, conf Config) (string, string, error) {
|
||||
}
|
||||
|
||||
login := sdk.Login{
|
||||
Identity: user.Credentials.Username,
|
||||
Secret: user.Credentials.Secret,
|
||||
Username: user.Credentials.Username,
|
||||
Password: user.Credentials.Secret,
|
||||
}
|
||||
token, err := s.CreateToken(login)
|
||||
if err != nil {
|
||||
@@ -170,8 +170,8 @@ func createUser(s sdk.SDK, conf Config) (string, string, error) {
|
||||
}
|
||||
|
||||
login = sdk.Login{
|
||||
Identity: user.Credentials.Username,
|
||||
Secret: user.Credentials.Secret,
|
||||
Username: user.Credentials.Username,
|
||||
Password: user.Credentials.Secret,
|
||||
}
|
||||
token, err = s.CreateToken(login)
|
||||
if err != nil {
|
||||
@@ -227,50 +227,50 @@ func createGroups(s sdk.SDK, conf Config, domainID, token string) ([]sdk.Group,
|
||||
return groups, nil
|
||||
}
|
||||
|
||||
func createThingsInBatch(s sdk.SDK, conf Config, domainID, token string, num uint64) ([]sdk.Thing, error) {
|
||||
func createClientsInBatch(s sdk.SDK, conf Config, domainID, token string, num uint64) ([]sdk.Client, error) {
|
||||
var err error
|
||||
things := make([]sdk.Thing, num)
|
||||
clients := make([]sdk.Client, num)
|
||||
|
||||
for i := uint64(0); i < num; i++ {
|
||||
things[i] = sdk.Thing{
|
||||
clients[i] = sdk.Client{
|
||||
Name: fmt.Sprintf("%s%s", conf.Prefix, namesgenerator.Generate()),
|
||||
}
|
||||
}
|
||||
|
||||
things, err = s.CreateThings(things, domainID, token)
|
||||
clients, err = s.CreateClients(clients, domainID, token)
|
||||
if err != nil {
|
||||
return []sdk.Thing{}, fmt.Errorf("failed to create the things: %w", err)
|
||||
return []sdk.Client{}, fmt.Errorf("failed to create the clients: %w", err)
|
||||
}
|
||||
|
||||
return things, nil
|
||||
return clients, nil
|
||||
}
|
||||
|
||||
func createThings(s sdk.SDK, conf Config, domainID, token string) ([]sdk.Thing, error) {
|
||||
things := []sdk.Thing{}
|
||||
func createClients(s sdk.SDK, conf Config, domainID, token string) ([]sdk.Client, error) {
|
||||
clients := []sdk.Client{}
|
||||
|
||||
if conf.Num > batchSize {
|
||||
batches := int(conf.Num) / batchSize
|
||||
for i := 0; i < batches; i++ {
|
||||
ths, err := createThingsInBatch(s, conf, domainID, token, batchSize)
|
||||
ths, err := createClientsInBatch(s, conf, domainID, token, batchSize)
|
||||
if err != nil {
|
||||
return []sdk.Thing{}, fmt.Errorf("failed to create the things: %w", err)
|
||||
return []sdk.Client{}, fmt.Errorf("failed to create the clients: %w", err)
|
||||
}
|
||||
things = append(things, ths...)
|
||||
clients = append(clients, ths...)
|
||||
}
|
||||
ths, err := createThingsInBatch(s, conf, domainID, token, conf.Num%uint64(batchSize))
|
||||
ths, err := createClientsInBatch(s, conf, domainID, token, conf.Num%uint64(batchSize))
|
||||
if err != nil {
|
||||
return []sdk.Thing{}, fmt.Errorf("failed to create the things: %w", err)
|
||||
return []sdk.Client{}, fmt.Errorf("failed to create the clients: %w", err)
|
||||
}
|
||||
things = append(things, ths...)
|
||||
clients = append(clients, ths...)
|
||||
} else {
|
||||
ths, err := createThingsInBatch(s, conf, domainID, token, conf.Num)
|
||||
ths, err := createClientsInBatch(s, conf, domainID, token, conf.Num)
|
||||
if err != nil {
|
||||
return []sdk.Thing{}, fmt.Errorf("failed to create the things: %w", err)
|
||||
return []sdk.Client{}, fmt.Errorf("failed to create the clients: %w", err)
|
||||
}
|
||||
things = append(things, ths...)
|
||||
clients = append(clients, ths...)
|
||||
}
|
||||
|
||||
return things, nil
|
||||
return clients, nil
|
||||
}
|
||||
|
||||
func createChannelsInBatch(s sdk.SDK, conf Config, domainID, token string, num uint64) ([]sdk.Channel, error) {
|
||||
@@ -318,7 +318,7 @@ func createChannels(s sdk.SDK, conf Config, domainID, token string) ([]sdk.Chann
|
||||
return channels, nil
|
||||
}
|
||||
|
||||
func read(s sdk.SDK, conf Config, domainID, token string, users []sdk.User, groups []sdk.Group, things []sdk.Thing, channels []sdk.Channel) error {
|
||||
func read(s sdk.SDK, conf Config, domainID, token string, users []sdk.User, groups []sdk.Group, clients []sdk.Client, channels []sdk.Channel) error {
|
||||
for _, user := range users {
|
||||
if _, err := s.User(user.ID, token); err != nil {
|
||||
return fmt.Errorf("failed to get user %w", err)
|
||||
@@ -343,17 +343,17 @@ func read(s sdk.SDK, conf Config, domainID, token string, users []sdk.User, grou
|
||||
if gp.Total < conf.Num {
|
||||
return fmt.Errorf("returned groups %d less than created groups %d", gp.Total, conf.Num)
|
||||
}
|
||||
for _, thing := range things {
|
||||
if _, err := s.Thing(thing.ID, domainID, token); err != nil {
|
||||
return fmt.Errorf("failed to get thing %w", err)
|
||||
for _, c := range clients {
|
||||
if _, err := s.Client(c.ID, domainID, token); err != nil {
|
||||
return fmt.Errorf("failed to get client %w", err)
|
||||
}
|
||||
}
|
||||
tp, err := s.Things(sdk.PageMetadata{}, domainID, token)
|
||||
tp, err := s.Clients(sdk.PageMetadata{}, domainID, token)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get things %w", err)
|
||||
return fmt.Errorf("failed to get clients %w", err)
|
||||
}
|
||||
if tp.Total < conf.Num {
|
||||
return fmt.Errorf("returned things %d less than created things %d", tp.Total, conf.Num)
|
||||
return fmt.Errorf("returned clients %d less than created clients %d", tp.Total, conf.Num)
|
||||
}
|
||||
for _, channel := range channels {
|
||||
if _, err := s.Channel(channel.ID, domainID, token); err != nil {
|
||||
@@ -371,7 +371,7 @@ func read(s sdk.SDK, conf Config, domainID, token string, users []sdk.User, grou
|
||||
return nil
|
||||
}
|
||||
|
||||
func update(s sdk.SDK, domainID, token string, users []sdk.User, groups []sdk.Group, things []sdk.Thing, channels []sdk.Channel) error {
|
||||
func update(s sdk.SDK, domainID, token string, users []sdk.User, groups []sdk.Group, clients []sdk.Client, channels []sdk.Channel) error {
|
||||
for _, user := range users {
|
||||
user.FirstName = namesgenerator.Generate()
|
||||
user.Metadata = sdk.Metadata{"Update": namesgenerator.Generate()}
|
||||
@@ -458,48 +458,48 @@ func update(s sdk.SDK, domainID, token string, users []sdk.User, groups []sdk.Gr
|
||||
return fmt.Errorf("failed to enable group before %s after %s", group.Status, rGroup.Status)
|
||||
}
|
||||
}
|
||||
for _, thing := range things {
|
||||
thing.Name = namesgenerator.Generate()
|
||||
thing.Metadata = sdk.Metadata{"Update": namesgenerator.Generate()}
|
||||
rThing, err := s.UpdateThing(thing, domainID, token)
|
||||
for _, t := range clients {
|
||||
t.Name = namesgenerator.Generate()
|
||||
t.Metadata = sdk.Metadata{"Update": namesgenerator.Generate()}
|
||||
rClient, err := s.UpdateClient(t, domainID, token)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update thing %w", err)
|
||||
return fmt.Errorf("failed to update client %w", err)
|
||||
}
|
||||
if rThing.Name != thing.Name {
|
||||
return fmt.Errorf("failed to update thing name before %s after %s", thing.Name, rThing.Name)
|
||||
if rClient.Name != t.Name {
|
||||
return fmt.Errorf("failed to update client name before %s after %s", t.Name, rClient.Name)
|
||||
}
|
||||
if rThing.Metadata["Update"] != thing.Metadata["Update"] {
|
||||
return fmt.Errorf("failed to update thing metadata before %s after %s", thing.Metadata["Update"], rThing.Metadata["Update"])
|
||||
if rClient.Metadata["Update"] != t.Metadata["Update"] {
|
||||
return fmt.Errorf("failed to update client metadata before %s after %s", t.Metadata["Update"], rClient.Metadata["Update"])
|
||||
}
|
||||
thing = rThing
|
||||
rThing, err = s.UpdateThingSecret(thing.ID, thing.Credentials.Secret, domainID, token)
|
||||
t = rClient
|
||||
rClient, err = s.UpdateClientSecret(t.ID, t.Credentials.Secret, domainID, token)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update thing secret %w", err)
|
||||
return fmt.Errorf("failed to update client secret %w", err)
|
||||
}
|
||||
thing = rThing
|
||||
thing.Tags = []string{namesgenerator.Generate()}
|
||||
rThing, err = s.UpdateThingTags(thing, domainID, token)
|
||||
t = rClient
|
||||
t.Tags = []string{namesgenerator.Generate()}
|
||||
rClient, err = s.UpdateClientTags(t, domainID, token)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update thing tags %w", err)
|
||||
return fmt.Errorf("failed to update client tags %w", err)
|
||||
}
|
||||
if rThing.Tags[0] != thing.Tags[0] {
|
||||
return fmt.Errorf("failed to update thing tags before %s after %s", thing.Tags[0], rThing.Tags[0])
|
||||
if rClient.Tags[0] != t.Tags[0] {
|
||||
return fmt.Errorf("failed to update client tags before %s after %s", t.Tags[0], rClient.Tags[0])
|
||||
}
|
||||
thing = rThing
|
||||
rThing, err = s.DisableThing(thing.ID, domainID, token)
|
||||
t = rClient
|
||||
rClient, err = s.DisableClient(t.ID, domainID, token)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to disable thing %w", err)
|
||||
return fmt.Errorf("failed to disable client %w", err)
|
||||
}
|
||||
if rThing.Status != sdk.DisabledStatus {
|
||||
return fmt.Errorf("failed to disable thing before %s after %s", thing.Status, rThing.Status)
|
||||
if rClient.Status != sdk.DisabledStatus {
|
||||
return fmt.Errorf("failed to disable client before %s after %s", t.Status, rClient.Status)
|
||||
}
|
||||
thing = rThing
|
||||
rThing, err = s.EnableThing(thing.ID, domainID, token)
|
||||
t = rClient
|
||||
rClient, err = s.EnableClient(t.ID, domainID, token)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to enable thing %w", err)
|
||||
return fmt.Errorf("failed to enable client %w", err)
|
||||
}
|
||||
if rThing.Status != sdk.EnabledStatus {
|
||||
return fmt.Errorf("failed to enable thing before %s after %s", thing.Status, rThing.Status)
|
||||
if rClient.Status != sdk.EnabledStatus {
|
||||
return fmt.Errorf("failed to enable client before %s after %s", t.Status, rClient.Status)
|
||||
}
|
||||
}
|
||||
for _, channel := range channels {
|
||||
@@ -536,15 +536,16 @@ func update(s sdk.SDK, domainID, token string, users []sdk.User, groups []sdk.Gr
|
||||
return nil
|
||||
}
|
||||
|
||||
func messaging(s sdk.SDK, conf Config, domainID, token string, things []sdk.Thing, channels []sdk.Channel) error {
|
||||
for _, thing := range things {
|
||||
func messaging(s sdk.SDK, conf Config, domainID, token string, clients []sdk.Client, channels []sdk.Channel) error {
|
||||
for _, c := range clients {
|
||||
for _, channel := range channels {
|
||||
conn := sdk.Connection{
|
||||
ThingID: thing.ID,
|
||||
ChannelID: channel.ID,
|
||||
ClientIDs: []string{c.ID},
|
||||
ChannelIDs: []string{channel.ID},
|
||||
Types: []string{"publish", "subscribe"},
|
||||
}
|
||||
if err := s.Connect(conn, domainID, token); err != nil {
|
||||
return fmt.Errorf("failed to connect thing %s to channel %s", thing.ID, channel.ID)
|
||||
return fmt.Errorf("failed to connect client %s to channel %s", c.ID, channel.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -553,26 +554,26 @@ func messaging(s sdk.SDK, conf Config, domainID, token string, things []sdk.Thin
|
||||
|
||||
bt := time.Now().Unix()
|
||||
for i := uint64(0); i < conf.NumOfMsg; i++ {
|
||||
for _, thing := range things {
|
||||
for _, client := range clients {
|
||||
for _, channel := range channels {
|
||||
func(num int64, thing sdk.Thing, channel sdk.Channel) {
|
||||
func(num int64, client sdk.Client, channel sdk.Channel) {
|
||||
g.Go(func() error {
|
||||
msg := fmt.Sprintf(msgFormat, num+1, rand.Int())
|
||||
return sendHTTPMessage(s, msg, thing, channel.ID)
|
||||
return sendHTTPMessage(s, msg, client, channel.ID)
|
||||
})
|
||||
g.Go(func() error {
|
||||
msg := fmt.Sprintf(msgFormat, num+2, rand.Int())
|
||||
return sendCoAPMessage(msg, thing, channel.ID)
|
||||
return sendCoAPMessage(msg, client, channel.ID)
|
||||
})
|
||||
g.Go(func() error {
|
||||
msg := fmt.Sprintf(msgFormat, num+3, rand.Int())
|
||||
return sendMQTTMessage(msg, thing, channel.ID)
|
||||
return sendMQTTMessage(msg, client, channel.ID)
|
||||
})
|
||||
g.Go(func() error {
|
||||
msg := fmt.Sprintf(msgFormat, num+4, rand.Int())
|
||||
return sendWSMessage(conf, msg, thing, channel.ID)
|
||||
return sendWSMessage(conf, msg, client, channel.ID)
|
||||
})
|
||||
}(bt, thing, channel)
|
||||
}(bt, client, channel)
|
||||
bt += numAdapters
|
||||
}
|
||||
}
|
||||
@@ -581,42 +582,42 @@ func messaging(s sdk.SDK, conf Config, domainID, token string, things []sdk.Thin
|
||||
return g.Wait()
|
||||
}
|
||||
|
||||
func sendHTTPMessage(s sdk.SDK, msg string, thing sdk.Thing, chanID string) error {
|
||||
if err := s.SendMessage(chanID, msg, thing.Credentials.Secret); err != nil {
|
||||
return fmt.Errorf("HTTP failed to send message from thing %s to channel %s: %w", thing.ID, chanID, err)
|
||||
func sendHTTPMessage(s sdk.SDK, msg string, client sdk.Client, chanID string) error {
|
||||
if err := s.SendMessage(chanID, msg, client.Credentials.Secret); err != nil {
|
||||
return fmt.Errorf("HTTP failed to send message from client %s to channel %s: %w", client.ID, chanID, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func sendCoAPMessage(msg string, thing sdk.Thing, chanID string) error {
|
||||
cmd := exec.Command("coap-cli", "post", fmt.Sprintf("channels/%s/messages", chanID), "--auth", thing.Credentials.Secret, "-d", msg)
|
||||
func sendCoAPMessage(msg string, client sdk.Client, chanID string) error {
|
||||
cmd := exec.Command("coap-cli", "post", fmt.Sprintf("channels/%s/messages", chanID), "--auth", client.Credentials.Secret, "-d", msg)
|
||||
if _, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("CoAP failed to send message from thing %s to channel %s: %w", thing.ID, chanID, err)
|
||||
return fmt.Errorf("CoAP failed to send message from client %s to channel %s: %w", client.ID, chanID, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func sendMQTTMessage(msg string, thing sdk.Thing, chanID string) error {
|
||||
cmd := exec.Command("mosquitto_pub", "--id-prefix", "magistrala", "-u", thing.ID, "-P", thing.Credentials.Secret, "-t", fmt.Sprintf("channels/%s/messages", chanID), "-h", "localhost", "-m", msg)
|
||||
func sendMQTTMessage(msg string, client sdk.Client, chanID string) error {
|
||||
cmd := exec.Command("mosquitto_pub", "--id-prefix", "supermq", "-u", client.ID, "-P", client.Credentials.Secret, "-t", fmt.Sprintf("channels/%s/messages", chanID), "-h", "localhost", "-m", msg)
|
||||
if _, err := cmd.CombinedOutput(); err != nil {
|
||||
return fmt.Errorf("MQTT failed to send message from thing %s to channel %s: %w", thing.ID, chanID, err)
|
||||
return fmt.Errorf("MQTT failed to send message from client %s to channel %s: %w", client.ID, chanID, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func sendWSMessage(conf Config, msg string, thing sdk.Thing, chanID string) error {
|
||||
func sendWSMessage(conf Config, msg string, client sdk.Client, chanID string) error {
|
||||
socketURL := fmt.Sprintf("ws://%s:%s/channels/%s/messages", conf.Host, defWSPort, chanID)
|
||||
header := http.Header{"Authorization": []string{thing.Credentials.Secret}}
|
||||
header := http.Header{"Authorization": []string{client.Credentials.Secret}}
|
||||
conn, _, err := websocket.DefaultDialer.Dial(socketURL, header)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to connect to websocket: %w", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
if err := conn.WriteMessage(websocket.TextMessage, []byte(msg)); err != nil {
|
||||
return fmt.Errorf("WS failed to send message from thing %s to channel %s: %w", thing.ID, chanID, err)
|
||||
return fmt.Errorf("WS failed to send message from client %s to channel %s: %w", client.ID, chanID, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
+13
-13
@@ -1,11 +1,11 @@
|
||||
# MQTT Benchmarking Tool
|
||||
|
||||
A simple MQTT benchmarking tool for Magistrala platform.
|
||||
A simple MQTT benchmarking tool for SuperMQ platform.
|
||||
|
||||
It connects Magistrala things as subscribers over a number of channels and
|
||||
uses other Magistrala things to publish messages and create MQTT load.
|
||||
It connects SuperMQ clients as subscribers over a number of channels and
|
||||
uses other SuperMQ clients to publish messages and create MQTT load.
|
||||
|
||||
Magistrala things used must be pre-provisioned first, and Magistrala `provision` tool can be used for this purpose.
|
||||
SuperMQ clients used must be pre-provisioned first, and SuperMQ `provision` tool can be used for this purpose.
|
||||
|
||||
## Installation
|
||||
|
||||
@@ -20,8 +20,8 @@ The tool supports multiple concurrent clients, publishers and subscribers config
|
||||
|
||||
```
|
||||
./mqtt-bench --help
|
||||
Tool for extensive load and benchmarking of MQTT brokers used within Magistrala platform.
|
||||
Complete documentation is available at https://docs.magistrala.abstractmachines.fr
|
||||
Tool for extensive load and benchmarking of MQTT brokers used within SuperMQ platform.
|
||||
Complete documentation is available at https://docs.supermq.abstractmachines.fr
|
||||
|
||||
Usage:
|
||||
mqtt-bench [flags]
|
||||
@@ -33,7 +33,7 @@ Flags:
|
||||
-n, --count int Number of messages sent per publisher (default 100)
|
||||
-f, --format string Output format: text|json (default "text")
|
||||
-h, --help help for mqtt-bench
|
||||
-m, --magistrala string config file for Magistrala connections (default "connections.toml")
|
||||
-m, --supermq string config file for SuperMQ connections (default "connections.toml")
|
||||
--mtls Use mtls for connection
|
||||
-p, --pubs int Number of publishers (default 10)
|
||||
-q, --qos int QoS for published messages, values 0 1 2
|
||||
@@ -46,11 +46,11 @@ Flags:
|
||||
|
||||
Two output formats supported: human-readable plain text and JSON.
|
||||
|
||||
Before use you need a `mgconn.toml` - a TOML file that describes Magistrala connection data (channels, thingIDs, thingKeys, certs).
|
||||
Before use you need a `mgconn.toml` - a TOML file that describes SuperMQ connection data (channels, clientIDs, clientKeys, certs).
|
||||
You can use `provision` tool (in tools/provision) to create this TOML config file.
|
||||
|
||||
```bash
|
||||
go run tools/mqtt-bench/cmd/main.go -u test@magistrala.com -p test1234 --host http://127.0.0.1 --num 100 > tools/mqtt-bench/mgconn.toml
|
||||
go run tools/mqtt-bench/cmd/main.go -u test@supermq.com -p test1234 --host http://127.0.0.1 --num 100 > tools/mqtt-bench/mgconn.toml
|
||||
```
|
||||
|
||||
Example use and output
|
||||
@@ -58,11 +58,11 @@ Example use and output
|
||||
Without mtls:
|
||||
|
||||
```
|
||||
go run tools/mqtt-bench/cmd/main.go --broker tcp://localhost:1883 --count 100 --size 100 --qos 0 --format text --pubs 10 --magistrala tools/mqtt-bench/mgconn.toml
|
||||
go run tools/mqtt-bench/cmd/main.go --broker tcp://localhost:1883 --count 100 --size 100 --qos 0 --format text --pubs 10 --supermq tools/mqtt-bench/mgconn.toml
|
||||
```
|
||||
|
||||
With mtls
|
||||
go run tools/mqtt-bench/cmd/main.go --broker tcps://localhost:8883 --count 100 --size 100 --qos 0 --format text --pubs 10 --magistrala tools/mqtt-bench/mgconn.toml --mtls -ca docker/ssl/certs/ca.crt
|
||||
go run tools/mqtt-bench/cmd/main.go --broker tcps://localhost:8883 --count 100 --size 100 --qos 0 --format text --pubs 10 --supermq tools/mqtt-bench/mgconn.toml --mtls -ca docker/ssl/certs/ca.crt
|
||||
|
||||
```
|
||||
|
||||
@@ -100,8 +100,8 @@ count = 100
|
||||
[log]
|
||||
quiet = false
|
||||
|
||||
[magistrala]
|
||||
connections_file = "mgconn.toml"
|
||||
[supermq]
|
||||
connections_file = "smqconn.toml"
|
||||
|
||||
```
|
||||
|
||||
|
||||
+11
-11
@@ -14,7 +14,7 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
mglog "github.com/absmach/magistrala/logger"
|
||||
smqlog "github.com/absmach/supermq/logger"
|
||||
"github.com/pelletier/go-toml"
|
||||
)
|
||||
|
||||
@@ -23,7 +23,7 @@ func Benchmark(cfg Config) error {
|
||||
if err := checkConnection(cfg.MQTT.Broker.URL, 1); err != nil {
|
||||
return err
|
||||
}
|
||||
logger, err := mglog.New(os.Stdout, "debug")
|
||||
logger, err := smqlog.New(os.Stdout, "debug")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -44,14 +44,14 @@ func Benchmark(cfg Config) error {
|
||||
caByte, _ = io.ReadAll(caFile)
|
||||
}
|
||||
|
||||
data, err := os.ReadFile(cfg.Mg.ConnFile)
|
||||
data, err := os.ReadFile(cfg.Smq.ConnFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error loading connections file: %s", err)
|
||||
}
|
||||
|
||||
mg := magistrala{}
|
||||
mg := superMQ{}
|
||||
if err := toml.Unmarshal(data, &mg); err != nil {
|
||||
return fmt.Errorf("cannot load Magistrala connections config %s \nUse tools/provision to create file", cfg.Mg.ConnFile)
|
||||
return fmt.Errorf("cannot load SuperMQ connections config %s \nUse tools/provision to create file", cfg.Smq.ConnFile)
|
||||
}
|
||||
|
||||
resCh := make(chan *runResults)
|
||||
@@ -72,16 +72,16 @@ func Benchmark(cfg Config) error {
|
||||
go func(i int) {
|
||||
defer wg.Done()
|
||||
mgChan := mg.Channels[i%n]
|
||||
mgThing := mg.Things[i%n]
|
||||
mgCli := mg.Clients[i%n]
|
||||
|
||||
if cfg.MQTT.TLS.MTLS {
|
||||
cert, err = tls.X509KeyPair([]byte(mgThing.MTLSCert), []byte(mgThing.MTLSKey))
|
||||
cert, err = tls.X509KeyPair([]byte(mgCli.MTLSCert), []byte(mgCli.MTLSKey))
|
||||
if err != nil {
|
||||
errorChan <- err
|
||||
return
|
||||
}
|
||||
}
|
||||
c, err := makeClient(i, cfg, mgChan, mgThing, startStamp, caByte, cert)
|
||||
c, err := makeClient(i, cfg, mgChan, mgCli, startStamp, caByte, cert)
|
||||
if err != nil {
|
||||
errorChan <- fmt.Errorf("unable to create message payload %s", err.Error())
|
||||
return
|
||||
@@ -171,12 +171,12 @@ func getBytePayload(size int, m message) (handler, error) {
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func makeClient(i int, cfg Config, mgChan mgChannel, mgThing mgThing, start time.Time, caCert []byte, clientCert tls.Certificate) (*Client, error) {
|
||||
func makeClient(i int, cfg Config, mgChan channel, cli client, start time.Time, caCert []byte, clientCert tls.Certificate) (*Client, error) {
|
||||
c := &Client{
|
||||
ID: strconv.Itoa(i),
|
||||
BrokerURL: cfg.MQTT.Broker.URL,
|
||||
BrokerUser: mgThing.ThingID,
|
||||
BrokerPass: mgThing.ThingKey,
|
||||
BrokerUser: cli.ClientID,
|
||||
BrokerPass: cli.ClientSecret,
|
||||
MsgTopic: fmt.Sprintf("channels/%s/messages/%d/test", mgChan.ChannelID, start.UnixNano()),
|
||||
MsgSize: cfg.MQTT.Message.Size,
|
||||
MsgCount: cfg.Test.Count,
|
||||
|
||||
@@ -7,7 +7,7 @@ package main
|
||||
import (
|
||||
"log"
|
||||
|
||||
bench "github.com/absmach/magistrala/tools/mqtt-bench"
|
||||
bench "github.com/absmach/supermq/tools/mqtt-bench"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
@@ -19,9 +19,9 @@ func main() {
|
||||
// Command
|
||||
rootCmd := &cobra.Command{
|
||||
Use: "mqtt-bench",
|
||||
Short: "mqtt-bench is MQTT benchmark tool for Magistrala",
|
||||
Long: `Tool for exctensive load and benchmarking of MQTT brokers used within the Magistrala platform.
|
||||
Complete documentation is available at https://docs.magistrala.abstractmachines.fr`,
|
||||
Short: "mqtt-bench is MQTT benchmark tool for SuperMQ",
|
||||
Long: `Tool for exctensive load and benchmarking of MQTT brokers used within the SuperMQ platform.
|
||||
Complete documentation is available at https://docs.supermq.abstractmachines.fr`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if confFile != "" {
|
||||
viper.SetConfigFile(confFile)
|
||||
@@ -69,7 +69,7 @@ Complete documentation is available at https://docs.magistrala.abstractmachines.
|
||||
|
||||
// Config file
|
||||
rootCmd.PersistentFlags().StringVarP(&confFile, "config", "c", "config.toml", "config file for mqtt-bench")
|
||||
rootCmd.PersistentFlags().StringVarP(&bconf.Mg.ConnFile, "magistrala", "m", "connections.toml", "config file for Magistrala connections")
|
||||
rootCmd.PersistentFlags().StringVarP(&bconf.Smq.ConnFile, "supermq", "m", "connections.toml", "config file for SuperMQ connections")
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
log.Fatal(err)
|
||||
|
||||
+14
-14
@@ -39,30 +39,30 @@ type logConfig struct {
|
||||
Quiet bool `toml:"quiet" mapstructure:"quiet"`
|
||||
}
|
||||
|
||||
type magistralaFile struct {
|
||||
type smqFile struct {
|
||||
ConnFile string `toml:"connections_file" mapstructure:"connections_file"`
|
||||
}
|
||||
|
||||
type mgThing struct {
|
||||
ThingID string `toml:"thing_id" mapstructure:"thing_id"`
|
||||
ThingKey string `toml:"thing_key" mapstructure:"thing_key"`
|
||||
MTLSCert string `toml:"mtls_cert" mapstructure:"mtls_cert"`
|
||||
MTLSKey string `toml:"mtls_key" mapstructure:"mtls_key"`
|
||||
type client struct {
|
||||
ClientID string `toml:"client_id" mapstructure:"client_id"`
|
||||
ClientSecret string `toml:"client_secret" mapstructure:"client_secret"`
|
||||
MTLSCert string `toml:"mtls_cert" mapstructure:"mtls_cert"`
|
||||
MTLSKey string `toml:"mtls_key" mapstructure:"mtls_key"`
|
||||
}
|
||||
|
||||
type mgChannel struct {
|
||||
type channel struct {
|
||||
ChannelID string `toml:"channel_id" mapstructure:"channel_id"`
|
||||
}
|
||||
|
||||
type magistrala struct {
|
||||
Things []mgThing `toml:"things" mapstructure:"things"`
|
||||
Channels []mgChannel `toml:"channels" mapstructure:"channels"`
|
||||
type superMQ struct {
|
||||
Clients []client `toml:"clients" mapstructure:"clients"`
|
||||
Channels []channel `toml:"channels" mapstructure:"channels"`
|
||||
}
|
||||
|
||||
// Config struct holds benchmark configuration.
|
||||
type Config struct {
|
||||
MQTT mqttConfig `toml:"mqtt" mapstructure:"mqtt"`
|
||||
Test testConfig `toml:"test" mapstructure:"test"`
|
||||
Log logConfig `toml:"log" mapstructure:"log"`
|
||||
Mg magistralaFile `toml:"magistrala" mapstructure:"magistrala"`
|
||||
MQTT mqttConfig `toml:"mqtt" mapstructure:"mqtt"`
|
||||
Test testConfig `toml:"test" mapstructure:"test"`
|
||||
Log logConfig `toml:"log" mapstructure:"log"`
|
||||
Smq smqFile `toml:"supermq" mapstructure:"supermq"`
|
||||
}
|
||||
|
||||
@@ -25,5 +25,5 @@ count = 70
|
||||
[log]
|
||||
quiet = true
|
||||
|
||||
[magistrala]
|
||||
[supermq]
|
||||
connections_file = "../provision/mgconn.toml"
|
||||
|
||||
+31
-29
@@ -1,61 +1,63 @@
|
||||
# Magistrala Things and Channels Provisioning Tool
|
||||
# SuperMQ Clients and Channels Provisioning Tool
|
||||
|
||||
A simple utility to create a list of channels and things connected to these channels with possibility to create certificates for mTLS use case.
|
||||
A simple utility to create a list of channels and clients connected to these channels with possibility to create certificates for mTLS use case.
|
||||
|
||||
This tool is useful for testing, and it creates a TOML format output (on stdout, can be redirected into the file as needed)
|
||||
that can be used by Magistrala MQTT benchmarking tool (`mqtt-bench`).
|
||||
that can be used by SuperMQ MQTT benchmarking tool (`mqtt-bench`).
|
||||
|
||||
## Installation
|
||||
```
|
||||
|
||||
```bash
|
||||
cd tools/provision
|
||||
make
|
||||
```
|
||||
|
||||
### Usage
|
||||
```
|
||||
|
||||
```bash
|
||||
./provision --help
|
||||
Tool for provisioning series of Magistrala channels and things and connecting them together.
|
||||
Complete documentation is available at https://docs.magistrala.abstractmachines.fr
|
||||
Tool for provisioning series of SuperMQ channels and clients and connecting them together.
|
||||
Complete documentation is available at https://docs.supermq.abstractmachines.fr
|
||||
|
||||
Usage:
|
||||
provision [flags]
|
||||
|
||||
Flags:
|
||||
--ca string CA for creating and signing things certificate (default "ca.crt")
|
||||
--cakey string ca.key for creating and signing things certificate (default "ca.key")
|
||||
--ca string CA for creating and signing clients certificate (default "ca.crt")
|
||||
--cakey string ca.key for creating and signing clients certificate (default "ca.key")
|
||||
-h, --help help for provision
|
||||
--host string address for magistrala instance (default "https://localhost")
|
||||
--num int number of channels and things to create and connect (default 10)
|
||||
-p, --password string magistrala users password
|
||||
--host string address for supermq instance (default "https://localhost")
|
||||
--num int number of channels and clients to create and connect (default 10)
|
||||
-p, --password string supermq users password
|
||||
--ssl create certificates for mTLS access
|
||||
-u, --username string magistrala user
|
||||
--prefix string name prefix for things and channels
|
||||
-u, --username string supermq user
|
||||
--prefix string name prefix for clients and channels
|
||||
```
|
||||
|
||||
Example:
|
||||
```
|
||||
go run tools/provision/cmd/main.go -u test@magistrala.com -p test1234 --host https://142.93.118.47
|
||||
|
||||
```bash
|
||||
go run tools/provision/cmd/main.go -u test@supermq.com -p test1234 --host https://142.93.118.47
|
||||
```
|
||||
|
||||
If you want to create a list of channels with certificates:
|
||||
|
||||
```
|
||||
go run tools/provision/cmd/main.go --host http://localhost --num 10 -u test@magistrala.com -p test1234 --ssl true --ca docker/ssl/certs/ca.crt --cakey docker/ssl/certs/ca.key
|
||||
```bash
|
||||
go run tools/provision/cmd/main.go --host http://localhost --num 10 -u test@supermq.com -p test1234 --ssl true --ca docker/ssl/certs/ca.crt --cakey docker/ssl/certs/ca.key
|
||||
|
||||
```
|
||||
|
||||
>`ca.crt` and `ca.key` are used for creating things certificate and for HTTPS,
|
||||
> `ca.crt` and `ca.key` are used for creating clients certificate and for HTTPS,
|
||||
> if you are provisioning on remote server you will have to get these files to your local
|
||||
> directory so that you can create certificates for things
|
||||
|
||||
> directory so that you can create certificates for clients
|
||||
|
||||
Example of output:
|
||||
|
||||
```
|
||||
# List of things that can be connected to MQTT broker
|
||||
[[things]]
|
||||
thing_id = "0eac601b-6d54-4767-b8b7-594aaf9990d3"
|
||||
thing_key = "07713103-513f-43c7-b7fe-500c1af23d7d"
|
||||
```bash
|
||||
# List of clients that can be connected to MQTT broker
|
||||
[[clients]]
|
||||
client_id = "0eac601b-6d54-4767-b8b7-594aaf9990d3"
|
||||
client_key = "07713103-513f-43c7-b7fe-500c1af23d7d"
|
||||
mtls_cert = """-----BEGIN CERTIFICATE-----
|
||||
MIIEmTCCA4GgAwIBAgIRAO50qOfXsU+cHm/QY2NYu+0wDQYJKoZIhvcNAQELBQAw
|
||||
VzESMBAGA1UEAwwJbG9jYWxob3N0MREwDwYDVQQKDAhNYWluZmx1eDEMMAoGA1UE
|
||||
@@ -137,9 +139,9 @@ uCRt+TFMyEfqilipmNsV7esgbroiyEGXGMI8JdBY9OsnK6ZSlXaMnQ9vq2kK
|
||||
-----END RSA PRIVATE KEY-----
|
||||
"""
|
||||
|
||||
# List of channels that things can publish to
|
||||
# each channel is connected to each thing from things list
|
||||
# Things connected to channel 1f18afa1-29c4-4634-99d1-68dfa1b74e6a: 0eac601b-6d54-4767-b8b7-594aaf9990d3
|
||||
# List of channels that clients can publish to
|
||||
# each channel is connected to each client from clients list
|
||||
# Clients connected to channel 1f18afa1-29c4-4634-99d1-68dfa1b74e6a: 0eac601b-6d54-4767-b8b7-594aaf9990d3
|
||||
[[channels]]
|
||||
channel_id = "1f18afa1-29c4-4634-99d1-68dfa1b74e6a"
|
||||
|
||||
|
||||
+11
-11
@@ -7,7 +7,7 @@ package main
|
||||
import (
|
||||
"log"
|
||||
|
||||
"github.com/absmach/magistrala/tools/provision"
|
||||
"github.com/absmach/supermq/tools/provision"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -16,9 +16,9 @@ func main() {
|
||||
|
||||
rootCmd := &cobra.Command{
|
||||
Use: "provision",
|
||||
Short: "provision is provisioning tool for Magistrala",
|
||||
Long: `Tool for provisioning series of Magistrala channels and things and connecting them together.
|
||||
Complete documentation is available at https://docs.magistrala.abstractmachines.fr`,
|
||||
Short: "provision is provisioning tool for SuperMQ",
|
||||
Long: `Tool for provisioning series of SuperMQ channels and clients and connecting them together.
|
||||
Complete documentation is available at https://docs.supermq.abstractmachines.fr`,
|
||||
Run: func(_ *cobra.Command, _ []string) {
|
||||
if err := provision.Provision(pconf); err != nil {
|
||||
log.Fatal(err)
|
||||
@@ -27,14 +27,14 @@ Complete documentation is available at https://docs.magistrala.abstractmachines.
|
||||
}
|
||||
|
||||
// Root Flags
|
||||
rootCmd.PersistentFlags().StringVarP(&pconf.Host, "host", "", "https://localhost", "address for magistrala instance")
|
||||
rootCmd.PersistentFlags().StringVarP(&pconf.Prefix, "prefix", "", "", "name prefix for things and channels")
|
||||
rootCmd.PersistentFlags().StringVarP(&pconf.Username, "username", "u", "", "magistrala user")
|
||||
rootCmd.PersistentFlags().StringVarP(&pconf.Password, "password", "p", "", "magistrala users password")
|
||||
rootCmd.PersistentFlags().IntVarP(&pconf.Num, "num", "", 10, "number of channels and things to create and connect")
|
||||
rootCmd.PersistentFlags().StringVarP(&pconf.Host, "host", "", "https://localhost", "address for supermq instance")
|
||||
rootCmd.PersistentFlags().StringVarP(&pconf.Prefix, "prefix", "", "", "name prefix for clients and channels")
|
||||
rootCmd.PersistentFlags().StringVarP(&pconf.Username, "username", "u", "", "supermq user")
|
||||
rootCmd.PersistentFlags().StringVarP(&pconf.Password, "password", "p", "", "supermq users password")
|
||||
rootCmd.PersistentFlags().IntVarP(&pconf.Num, "num", "", 10, "number of channels and clients to create and connect")
|
||||
rootCmd.PersistentFlags().BoolVarP(&pconf.SSL, "ssl", "", false, "create certificates for mTLS access")
|
||||
rootCmd.PersistentFlags().StringVarP(&pconf.CAKey, "cakey", "", "ca.key", "ca.key for creating and signing things certificate")
|
||||
rootCmd.PersistentFlags().StringVarP(&pconf.CA, "ca", "", "ca.crt", "CA for creating and signing things certificate")
|
||||
rootCmd.PersistentFlags().StringVarP(&pconf.CAKey, "cakey", "", "ca.key", "ca.key for creating and signing clients certificate")
|
||||
rootCmd.PersistentFlags().StringVarP(&pconf.CA, "ca", "", "ca.crt", "CA for creating and signing clients certificate")
|
||||
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
log.Fatal(err)
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
// Package provision is a simple utility to create
|
||||
// a list of channels and things connected to these channels
|
||||
// a list of channels and clients connected to these channels
|
||||
// with possibility to create certificates for mTLS use case.
|
||||
package provision
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/0x6flab/namegenerator"
|
||||
sdk "github.com/absmach/magistrala/pkg/sdk/go"
|
||||
sdk "github.com/absmach/supermq/pkg/sdk"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -31,13 +31,13 @@ const (
|
||||
|
||||
var namesgenerator = namegenerator.NewGenerator()
|
||||
|
||||
// MgConn - structure describing Magistrala connection set.
|
||||
// MgConn - structure describing SuperMQ connection set.
|
||||
type MgConn struct {
|
||||
ChannelID string
|
||||
ThingID string
|
||||
ThingKey string
|
||||
MTLSCert string
|
||||
MTLSKey string
|
||||
ClientID string
|
||||
ClinetSecret string
|
||||
ChannelID string
|
||||
MTLSCert string
|
||||
MTLSKey string
|
||||
}
|
||||
|
||||
// Config - provisioning configuration.
|
||||
@@ -62,7 +62,7 @@ func Provision(conf Config) error {
|
||||
|
||||
msgContentType := string(sdk.CTJSONSenML)
|
||||
sdkConf := sdk.Config{
|
||||
ThingsURL: conf.Host,
|
||||
ClientsURL: conf.Host,
|
||||
UsersURL: conf.Host,
|
||||
ReaderURL: defReaderURL,
|
||||
HTTPAdapterURL: fmt.Sprintf("%s/http", conf.Host),
|
||||
@@ -95,7 +95,7 @@ func Provision(conf Config) error {
|
||||
var err error
|
||||
|
||||
// Login user
|
||||
token, err := s.CreateToken(sdk.Login{Identity: user.Credentials.Username, Secret: user.Credentials.Secret})
|
||||
token, err := s.CreateToken(sdk.Login{Username: user.Credentials.Username, Password: user.Credentials.Secret})
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to login user: %s", err.Error())
|
||||
}
|
||||
@@ -114,8 +114,8 @@ func Provision(conf Config) error {
|
||||
}
|
||||
// Login to domain
|
||||
token, err = s.CreateToken(sdk.Login{
|
||||
Identity: user.Credentials.Username,
|
||||
Secret: user.Credentials.Secret,
|
||||
Username: user.Credentials.Username,
|
||||
Password: user.Credentials.Secret,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to login user: %w", err)
|
||||
@@ -146,22 +146,22 @@ func Provision(conf Config) error {
|
||||
}
|
||||
}
|
||||
|
||||
// Create things and channels
|
||||
things := make([]sdk.Thing, conf.Num)
|
||||
// Create clients and channels
|
||||
clients := make([]sdk.Client, conf.Num)
|
||||
channels := make([]sdk.Channel, conf.Num)
|
||||
cIDs := []string{}
|
||||
tIDs := []string{}
|
||||
|
||||
fmt.Println("# List of things that can be connected to MQTT broker")
|
||||
fmt.Println("# List of clients that can be connected to MQTT broker")
|
||||
|
||||
for i := 0; i < conf.Num; i++ {
|
||||
things[i] = sdk.Thing{Name: fmt.Sprintf("%s-thing-%d", conf.Prefix, i)}
|
||||
clients[i] = sdk.Client{Name: fmt.Sprintf("%s-client-%d", conf.Prefix, i)}
|
||||
channels[i] = sdk.Channel{Name: fmt.Sprintf("%s-channel-%d", conf.Prefix, i)}
|
||||
}
|
||||
|
||||
things, err = s.CreateThings(things, domain.ID, token.AccessToken)
|
||||
clients, err = s.CreateClients(clients, domain.ID, token.AccessToken)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create the things: %s", err.Error())
|
||||
return fmt.Errorf("failed to create the clients: %s", err.Error())
|
||||
}
|
||||
|
||||
var chs []sdk.Channel
|
||||
@@ -174,7 +174,7 @@ func Provision(conf Config) error {
|
||||
}
|
||||
channels = chs
|
||||
|
||||
for _, t := range things {
|
||||
for _, t := range clients {
|
||||
tIDs = append(tIDs, t.ID)
|
||||
}
|
||||
|
||||
@@ -206,9 +206,9 @@ func Provision(conf Config) error {
|
||||
tmpl := x509.Certificate{
|
||||
SerialNumber: serialNumber,
|
||||
Subject: pkix.Name{
|
||||
Organization: []string{"Magistrala"},
|
||||
CommonName: things[i].Credentials.Secret,
|
||||
OrganizationalUnit: []string{"magistrala"},
|
||||
Organization: []string{"SuperMQ"},
|
||||
CommonName: clients[i].Credentials.Secret,
|
||||
OrganizationalUnit: []string{"supermq"},
|
||||
},
|
||||
NotBefore: notBefore,
|
||||
NotAfter: notAfter,
|
||||
@@ -241,7 +241,7 @@ func Provision(conf Config) error {
|
||||
}
|
||||
|
||||
// Print output
|
||||
fmt.Printf("[[things]]\nthing_id = \"%s\"\nthing_key = \"%s\"\n", things[i].ID, things[i].Credentials.Secret)
|
||||
fmt.Printf("[[clients]]\nclient_id = \"%s\"\nclient_key = \"%s\"\n", clients[i].ID, clients[i].Credentials.Secret)
|
||||
if conf.SSL {
|
||||
fmt.Printf("mtls_cert = \"\"\"%s\"\"\"\n", cert)
|
||||
fmt.Printf("mtls_key = \"\"\"%s\"\"\"\n", key)
|
||||
@@ -249,8 +249,8 @@ func Provision(conf Config) error {
|
||||
fmt.Println("")
|
||||
}
|
||||
|
||||
fmt.Printf("# List of channels that things can publish to\n" +
|
||||
"# each channel is connected to each thing from things list\n")
|
||||
fmt.Printf("# List of channels that clients can publish to\n" +
|
||||
"# each channel is connected to each client from clients list\n")
|
||||
for i := 0; i < conf.Num; i++ {
|
||||
fmt.Printf("[[channels]]\nchannel_id = \"%s\"\n\n", cIDs[i])
|
||||
}
|
||||
@@ -258,11 +258,12 @@ func Provision(conf Config) error {
|
||||
for _, cID := range cIDs {
|
||||
for _, tID := range tIDs {
|
||||
conIDs := sdk.Connection{
|
||||
ThingID: tID,
|
||||
ChannelID: cID,
|
||||
ClientIDs: []string{tID},
|
||||
ChannelIDs: []string{cID},
|
||||
Types: []string{"publish", "subscribe"},
|
||||
}
|
||||
if err := s.Connect(conIDs, domain.ID, token.AccessToken); err != nil {
|
||||
log.Fatalf("Failed to connect things %s to channels %s: %s", tID, cID, err)
|
||||
log.Fatalf("Failed to connect clients %s to channels %s: %s", tID, cID, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user