Skip to content

Commit

Permalink
refactor: Move code from main.go to other files
Browse files Browse the repository at this point in the history
* Card ID: CCT-950
* Initial step of refactoring main.go.
* Code moved from main.go to other files
* Introduced new files for connect and disconnect
  commands
* Added several other files for interactive mode,
  logging
* Some code was moved to existing files
  • Loading branch information
jirihnidek committed Nov 5, 2024
1 parent 4650008 commit 9a7f4e7
Show file tree
Hide file tree
Showing 13 changed files with 890 additions and 918 deletions.
23 changes: 23 additions & 0 deletions canonical_facts_cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package main

import (
"encoding/json"
"fmt"
"github.com/urfave/cli/v2"
)

// canonicalFactAction tries to gather canonical facts about system,
// and it prints JSON with facts to stdout.
func canonicalFactAction(_ *cli.Context) error {
// NOTE: CLI context is not useful for anything
facts, err := GetCanonicalFacts()
if err != nil {
return cli.Exit(err, 1)
}
data, err := json.MarshalIndent(facts, "", " ")
if err != nil {
return err
}
fmt.Println(string(data))
return nil
}
6 changes: 4 additions & 2 deletions conf.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,10 @@ type Conf struct {
CADir string
}

// Create a TLSConfig using the rhsm certificates
func (conf *Conf) CreateTLSClientConfig() (*tls.Config, error) {
var config = Conf{}

// createTLSClientConfig Create a TLSConfig using the rhsm certificates
func (conf *Conf) createTLSClientConfig() (*tls.Config, error) {

Check failure on line 28 in conf.go

View workflow job for this annotation

GitHub Actions / Lint code

func `(*Conf).createTLSClientConfig` is unused (unused)
var certData, keyData []byte
var err error
rootCAs := make([][]byte, 0)
Expand Down
215 changes: 215 additions & 0 deletions connect_cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
package main

import (
"encoding/json"
"fmt"
"github.com/subpop/go-log"
"github.com/urfave/cli/v2"
"os"
"time"
)

// ConnectResult is structure holding information about results
// of connect command. The result could be printed in machine-readable format.
type ConnectResult struct {
Hostname string `json:"hostname"`
HostnameError string `json:"hostname_error,omitempty"`
UID int `json:"uid"`
UIDError string `json:"uid_error,omitempty"`
RHSMConnected bool `json:"rhsm_connected"`
RHSMConnectError string `json:"rhsm_connect_error,omitempty"`
InsightsConnected bool `json:"insights_connected"`
InsightsError string `json:"insights_connect_error,omitempty"`
YggdrasilStarted bool `json:"yggdrasil_started"`
YggdrasilStartedError string `json:"yggdrasil_started_error,omitempty"`
format string
}

// Error implement error interface for structure ConnectResult
func (connectResult ConnectResult) Error() string {
var result string
switch connectResult.format {
case "json":
data, err := json.MarshalIndent(connectResult, "", " ")
if err != nil {
return err.Error()
}
result = string(data)
case "":
break
default:
result = "error: unsupported document format: " + connectResult.format
}
return result
}

// beforeConnectAction ensures that user has supplied a correct CLI options
// and there is no conflict between provided options
func beforeConnectAction(ctx *cli.Context) error {
// First check if machine-readable format is used
err := setupFormatOption(ctx)
if err != nil {
return err
}

username := ctx.String("username")
password := ctx.String("password")
organization := ctx.String("organization")
activationKeys := ctx.StringSlice("activation-key")

if len(activationKeys) > 0 {
if username != "" {
return fmt.Errorf("--username and --activation-key can not be used together")
}
if organization == "" {
return fmt.Errorf("--organization is required, when --activation-key is used")
}
}

// When machine-readable format is used, then additional requirements have to be met
if uiSettings.isMachineReadable {
if username == "" || password == "" {
return fmt.Errorf("--username/--password or --organization/--activation-key are required when a machine-readable format is used")
}
}

return checkForUnknownArgs(ctx)
}

// connectAction tries to register system against Red Hat Subscription Management,
// gather the profile information that the system will configure
// connect system to Red Hat Insights, and it also tries to start rhcd service
func connectAction(ctx *cli.Context) error {
var connectResult ConnectResult
connectResult.format = ctx.String("format")

uid := os.Getuid()
if uid != 0 {
errMsg := "non-root user cannot connect system"
exitCode := 1
if uiSettings.isMachineReadable {
connectResult.UID = uid
connectResult.UIDError = errMsg
return cli.Exit(connectResult, exitCode)
} else {
return cli.Exit(fmt.Errorf("error: %s", errMsg), exitCode)
}
}

hostname, err := os.Hostname()
if uiSettings.isMachineReadable {
connectResult.Hostname = hostname
}
if err != nil {
exitCode := 1
if uiSettings.isMachineReadable {
connectResult.HostnameError = err.Error()
return cli.Exit(connectResult, exitCode)
} else {
return cli.Exit(err, exitCode)
}
}

interactivePrintf("Connecting %v to %v.\nThis might take a few seconds.\n\n", hostname, Provider)

var start time.Time
durations := make(map[string]time.Duration)
errorMessages := make(map[string]LogMessage)
/* 1. Register to RHSM, because we need to get consumer certificate. This blocks following action */
start = time.Now()
var returnedMsg string
returnedMsg, err = registerRHSM(ctx)
if err != nil {
connectResult.RHSMConnected = false
errorMessages["rhsm"] = LogMessage{
level: log.LevelError,
message: fmt.Errorf("cannot connect to Red Hat Subscription Management: %w",
err)}
if uiSettings.isMachineReadable {
connectResult.RHSMConnectError = errorMessages["rhsm"].message.Error()
} else {
fmt.Printf(
"%v Cannot connect to Red Hat Subscription Management\n",
uiSettings.iconError,
)
}
} else {
connectResult.RHSMConnected = true
interactivePrintf("%v %v\n", uiSettings.iconOK, returnedMsg)
}
durations["rhsm"] = time.Since(start)

/* 2. Register insights-client */
if errors, exist := errorMessages["rhsm"]; exist {
if errors.level == log.LevelError {
interactivePrintf(
"%v Skipping connection to Red Hat Insights\n",
uiSettings.iconError,
)
}
} else {
start = time.Now()
err = showProgress(" Connecting to Red Hat Insights...", registerInsights)
if err != nil {
connectResult.InsightsConnected = false
errorMessages["insights"] = LogMessage{
level: log.LevelError,
message: fmt.Errorf("cannot connect to Red Hat Insights: %w", err)}
if uiSettings.isMachineReadable {
connectResult.InsightsError = errorMessages["insights"].message.Error()
} else {
fmt.Printf("%v Cannot connect to Red Hat Insights\n", uiSettings.iconError)
}
} else {
connectResult.InsightsConnected = true
interactivePrintf("%v Connected to Red Hat Insights\n", uiSettings.iconOK)
}
durations["insights"] = time.Since(start)
}

/* 3. Start yggdrasil (rhcd) service */
if rhsmErrMsg, exist := errorMessages["rhsm"]; exist && rhsmErrMsg.level == log.LevelError {
connectResult.YggdrasilStarted = false
interactivePrintf(
"%v Skipping activation of %v service\n",
uiSettings.iconError,
ServiceName,
)
} else {
start = time.Now()
progressMessage := fmt.Sprintf(" Activating the %v service", ServiceName)
err = showProgress(progressMessage, activateService)
if err != nil {
connectResult.YggdrasilStarted = false
errorMessages[ServiceName] = LogMessage{
level: log.LevelError,
message: fmt.Errorf("cannot activate %s service: %w",
ServiceName, err)}
if uiSettings.isMachineReadable {
connectResult.YggdrasilStartedError = errorMessages[ServiceName].message.Error()
} else {
fmt.Printf("%v Cannot activate the %v service\n", uiSettings.iconError, ServiceName)
}
} else {
connectResult.YggdrasilStarted = true
interactivePrintf("%v Activated the %v service\n", uiSettings.iconOK, ServiceName)
}
durations[ServiceName] = time.Since(start)
interactivePrintf("\nSuccessfully connected to Red Hat!\n")
}

if !uiSettings.isMachineReadable {
/* 5. Show footer message */
fmt.Printf("\nManage your connected systems: https://red.ht/connector\n")

/* 6. Optionally display duration time of each sub-action */
showTimeDuration(durations)
}

err = showErrorMessages("connect", errorMessages)
if err != nil {
return err
}

return cli.Exit(connectResult, 0)
}
Loading

0 comments on commit 9a7f4e7

Please sign in to comment.