Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PROP-31 - Automate propeller startup #47

Merged
merged 25 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions cli/log.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,7 @@ func logErrorCmd(cmd cobra.Command, err error) {
func logOKCmd(cmd cobra.Command) {
fmt.Fprintf(cmd.OutOrStdout(), "\n%s\n\n", color.BlueString("ok"))
}

func logSuccessCmd(cmd cobra.Command, msg string) {
fmt.Fprintf(cmd.OutOrStdout(), "\n%s\n", color.GreenString(msg))
}
254 changes: 254 additions & 0 deletions cli/provision.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
package cli

import (
"fmt"
"os"
"strings"

"github.com/0x6flab/namegenerator"
smqSDK "github.com/absmach/magistrala/pkg/sdk/go"
"github.com/absmach/supermq/pkg/errors"
"github.com/charmbracelet/huh"
"github.com/spf13/cobra"
)

var (
errFailedToCreateToken = errors.New("failed to create access token")
errFailedToCreateDomain = errors.New("failed to create domain")
errFailedChannelCreation = errors.New("failed to create channel")
errFailedClientCreation = errors.New("failed to create client")
errFailedConnectionCreation = errors.New("failed to create connection")

smqsdk smqSDK.SDK
namegen = namegenerator.NewGenerator()
fileName = "config.toml"
)

const filePermission = 0o644

func SetSuperMQSDK(sdk smqSDK.SDK) {
smqsdk = sdk
}

var provisionCmd = &cobra.Command{
Use: "provision",
Short: "Provision resources",
Long: `Provision necessary resources for Propeller operation.`,
Run: func(cmd *cobra.Command, args []string) {
var (
identity string
secret string
err error
token smqSDK.Token
domainName string
domainAlias string
domainPermission string
domain smqSDK.Domain
managerThingName string
managerThing smqSDK.Thing
propletThingName string
propletThing smqSDK.Thing
managerChannelName string
managerChannel smqSDK.Channel
)
form := huh.NewForm(
huh.NewGroup(
huh.NewInput().
Title("Enter your identity (e-mail)?").
Value(&identity).
Validate(func(str string) error {
if str == "" {
return errors.New("identity is required")
}

return nil
}),
huh.NewInput().
Title("Enter your secret").
EchoMode(huh.EchoModePassword).
Value(&secret).
Validate(func(str string) error {
if str == "" {
return errors.New("secret is required")
}
u := smqSDK.Login{
Identity: identity,
Secret: secret,
}

token, err = smqsdk.CreateToken(u)
if err != nil {
return errors.Wrap(errFailedToCreateToken, err)
}

return nil
}),
),
huh.NewGroup(
huh.NewInput().
Title("Enter your domain name(leave empty to auto generate)").
Value(&domainName),
huh.NewInput().
Title("Enter your domain alias(leave empty to auto generate)").
Value(&domainAlias),
huh.NewSelect[string]().
Title("Select your domain permission").
Options(
huh.NewOption("admin", "admin"),
huh.NewOption("edit", "edit"),
huh.NewOption("view", "view"),
).
Value(&domainPermission).
Validate(func(str string) error {
if domainName == "" {
domainName = namegen.Generate()
}
if domainAlias == "" {
domainAlias = strings.ToLower(domainName)
}
domain = smqSDK.Domain{
Name: domainName,
Alias: domainAlias,
Permission: domainPermission,
}
domain, err = smqsdk.CreateDomain(domain, token.AccessToken)
if err != nil {
return errors.Wrap(errFailedToCreateDomain, err)
}

return nil
}),
),
huh.NewGroup(
huh.NewInput().
Title("Enter your manager thing name(leave empty to auto generate)").
Value(&managerThingName).
Validate(func(str string) error {
if str == "" {
managerThingName = namegen.Generate()
}
managerThing = smqSDK.Thing{
Name: managerThingName,
Tags: []string{"manager", "propeller"},
Status: "enabled",
}
managerThing, err = smqsdk.CreateThing(managerThing, domain.ID, token.AccessToken)
if err != nil {
return errors.Wrap(errFailedClientCreation, err)
}

return nil
}),
),
huh.NewGroup(
huh.NewInput().
Title("Enter your proplet thing name(leave empty to auto generate)").
Value(&propletThingName).
Validate(func(str string) error {
if str == "" {
propletThingName = namegen.Generate()
}
propletThing = smqSDK.Thing{
Name: propletThingName,
Tags: []string{"proplet", "propeller"},
Status: "enabled",
}
propletThing, err = smqsdk.CreateThing(propletThing, domain.ID, token.AccessToken)
if err != nil {
return errors.Wrap(errFailedClientCreation, err)
}

return nil
}),
), huh.NewGroup(
huh.NewInput().
Title("Enter your manager channel name(leave empty to auto generate)").
Value(&managerChannelName).
Validate(func(str string) error {
if str == "" {
managerChannelName = namegen.Generate()
}
managerChannel = smqSDK.Channel{
Name: managerChannelName,
Status: "enabled",
}
managerChannel, err = smqsdk.CreateChannel(managerChannel, domain.ID, token.AccessToken)
if err != nil {
return errors.Wrap(errFailedChannelCreation, err)
}

managerConns := smqSDK.Connection{
ThingID: managerThing.ID,
ChannelID: managerChannel.ID,
}
if err = smqsdk.Connect(managerConns, domain.ID, token.AccessToken); err != nil {
return errors.Wrap(errFailedConnectionCreation, err)
}

propletConns := smqSDK.Connection{
ThingID: propletThing.ID,
ChannelID: managerChannel.ID,
}
if err = smqsdk.Connect(propletConns, domain.ID, token.AccessToken); err != nil {
return errors.Wrap(errFailedConnectionCreation, err)
}

return nil
}),
),
)

if err := form.Run(); err != nil {
logErrorCmd(*cmd, errors.Wrap(errFailedConnectionCreation, err))

return
}

configContent := fmt.Sprintf(`# SuperMQ Configuration

[manager]
thing_id = "%s"
thing_key = "%s"
channel_id = "%s"

[proplet]
thing_id = "%s"
thing_key = "%s"
channel_id = "%s"

[proxy]
thing_id = "%s"
thing_key = "%s"
channel_id = "%s"`,
managerThing.ID,
managerThing.Credentials.Secret,
managerChannel.ID,
propletThing.ID,
propletThing.Credentials.Secret,
managerChannel.ID,
propletThing.ID,
propletThing.Credentials.Secret,
managerChannel.ID,
)

if err := os.WriteFile(fileName, []byte(configContent), filePermission); err != nil {
logErrorCmd(*cmd, errors.New(fmt.Sprintf("failed to create %s file", fileName)))

return
}

logSuccessCmd(*cmd, fmt.Sprintf("Successfully created %s file", fileName))
},
}

func NewProvisionCmd() *cobra.Command {
provisionCmd.PersistentFlags().StringVarP(
&fileName,
"file-name",
"f",
fileName,
"The name of the file to create",
)

return provisionCmd
}
24 changes: 3 additions & 21 deletions cli/tasks.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,13 @@ import (
)

var (
DefTLSVerification = false
DefManagerURL = "http://localhost:7070"
defOffset uint64 = 0
defLimit uint64 = 10
defOffset uint64 = 0
defLimit uint64 = 10
)

var psdk sdk.SDK

func SetSDK(s sdk.SDK) {
func SetPropellerSDK(s sdk.SDK) {
psdk = s
}

Expand Down Expand Up @@ -153,14 +151,6 @@ func NewTasksCmd() *cobra.Command {
cmd.AddCommand(&tasksCmd[i])
}

cmd.PersistentFlags().StringVarP(
&DefManagerURL,
"manager-url",
"m",
DefManagerURL,
"Manager URL",
)

cmd.PersistentFlags().Uint64VarP(
&defOffset,
"offset",
Expand All @@ -177,13 +167,5 @@ func NewTasksCmd() *cobra.Command {
"Limit",
)

cmd.PersistentFlags().BoolVarP(
&DefTLSVerification,
"tls-verification",
"v",
DefTLSVerification,
"TLS Verification",
)

return &cmd
}
Loading
Loading