Skip to content

Commit

Permalink
Merge pull request #47 from nyagamunene/prop-31
Browse files Browse the repository at this point in the history
PROP-31 - Automate propeller startup
  • Loading branch information
drasko authored Jan 17, 2025
2 parents 262524e + 4901399 commit 97b8ab2
Show file tree
Hide file tree
Showing 12 changed files with 685 additions and 78 deletions.
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

0 comments on commit 97b8ab2

Please sign in to comment.