Skip to content

Commit

Permalink
Add user step to setup and add prompt user with lookup and validation
Browse files Browse the repository at this point in the history
  • Loading branch information
tnederlof committed Apr 29, 2023
1 parent a6190e4 commit 785d4f6
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 13 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ You can also pass the `--step` flag to begin at a certain spot in the interactiv
sudo wbi setup --step workbench
```

The following steps are valid options: start, prereqs, firewall, security, languages, r, python, workbench, license, jupyter, prodrivers, ssl, packagemanager, connect, restart, status, verify.
The following steps are valid options: start, prereqs, user, firewall, security, languages, r, python, workbench, license, jupyter, prodrivers, ssl, packagemanager, connect, restart, status, verify.

## Assumptions
- Single server
Expand Down
21 changes: 18 additions & 3 deletions cmd/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,15 @@ func newSetup(setupOpts setupOpts) error {
if err != nil {
return err
}
step = "user"
}

var username string
if step == "user" {
username, err = operatingsystem.PromptAndVerifyUser()
if err != nil {
return err
}
step = "firewall"
}

Expand Down Expand Up @@ -273,7 +282,13 @@ func newSetup(setupOpts setupOpts) error {
return fmt.Errorf("issue selecting if verification is to be run: %w", err)
}
if verifyChoice {
err = workbench.VerifyInstallation()
if username == "" {
username, err = operatingsystem.PromptAndVerifyUser()
if err != nil {
return err
}
}
err = workbench.VerifyInstallation(username)
if err != nil {
return fmt.Errorf("issue running verification: %w", err)
}
Expand Down Expand Up @@ -311,7 +326,7 @@ func (opts *setupOpts) Validate(args []string) error {
return fmt.Errorf("no arguments are supported for this command")
}
// ensure step is valid
validSteps := []string{"start", "prereqs", "firewall", "security", "languages", "r", "python", "workbench", "license", "jupyter", "prodrivers", "ssl", "packagemanager", "connect", "restart", "status", "verify"}
validSteps := []string{"start", "prereqs", "user", "firewall", "security", "languages", "r", "python", "workbench", "license", "jupyter", "prodrivers", "ssl", "packagemanager", "connect", "restart", "status", "verify"}
if opts.step != "" && !lo.Contains(validSteps, opts.step) {
return fmt.Errorf("invalid step: %s", opts.step)
}
Expand Down Expand Up @@ -353,7 +368,7 @@ func newSetupCmd() *setupCmd {
SilenceUsage: true,
}

stepHelp := `The step to start at. Valid steps are: start, prereqs, firewall, security, languages, r, python, workbench, license, jupyter, prodrivers, ssl, packagemanager, connect, restart, status, verify.`
stepHelp := `The step to start at. Valid steps are: start, prereqs, user, firewall, security, languages, r, python, workbench, license, jupyter, prodrivers, ssl, packagemanager, connect, restart, status, verify.`

cmd.Flags().StringP("step", "s", "", stepHelp)
viper.BindPFlag("step", cmd.Flags().Lookup("step"))
Expand Down
9 changes: 9 additions & 0 deletions internal/operatingsystem/detect.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package operatingsystem
import (
"errors"
"os"
"os/user"
"runtime"
"strings"

Expand Down Expand Up @@ -49,3 +50,11 @@ func DetectOS() (config.OperatingSystem, error) {
return config.Unknown, errors.New("unsupported operating system")
}
}

func UserLookup(username string) (*user.User, error) {
user, err := user.Lookup(username)
if err != nil {
return nil, err
}
return user, nil
}
29 changes: 23 additions & 6 deletions internal/operatingsystem/prompt.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,13 @@ func PromptInstallPrereqs() (bool, error) {
var name bool
messageText := "In order to install Workbench from start to finish, you will need the following things\n" +
"1. Internet access for this server\n" +
"2. The versions of R and Python you would like to install\n" +
"3. The version of R and Python you would like to set as defaults\n" +
"4. Your Workbench license key string in this form: XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX\n" +
"5. The location on this server of your SSL key and certificate files (optional)\n" +
"6. The URL and repo name for your instance of Posit Package Manager (optional)\n" +
"7. The URL for your instance of Posit Connect (optional)\n\n" +
"2. At least one non-root local Linux user account with a home directory\n" +
"3. The versions of R and Python you would like to install\n" +
"4. The version of R and Python you would like to set as defaults\n" +
"5. Your Workbench license key string in this form: XXXX-XXXX-XXXX-XXXX-XXXX-XXXX-XXXX\n" +
"6. The location on this server of your SSL key and certificate files (optional)\n" +
"7. The URL and repo name for your instance of Posit Package Manager (optional)\n" +
"8. The URL for your instance of Posit Connect (optional)\n\n" +
"Please confirm that you're ready to install Workbench"
prompt := &survey.Confirm{
Message: messageText,
Expand All @@ -79,3 +80,19 @@ func PromptInstallPrereqs() (bool, error) {
log.Info(fmt.Sprintf("%v", name))
return name, nil
}

// PromptUserAccount prompts the user for the name of a local Linux user account to use for verifying the installation
func PromptUserAccount() (string, error) {
target := ""
messageText := "Enter a non-root local Linux account username to use for testing the Workbench installation:"
prompt := &survey.Input{
Message: messageText,
}
err := survey.AskOne(prompt, &target)
if err != nil {
return "", fmt.Errorf("issue prompting for a local user account: %w", err)
}
log.Info(messageText)
log.Info(target)
return target, nil
}
29 changes: 29 additions & 0 deletions internal/operatingsystem/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package operatingsystem

import (
"fmt"

"github.com/sol-eng/wbi/internal/system"
)

func PromptAndVerifyUser() (string, error) {
userAccount, err := PromptUserAccount()
if err != nil {
return "", err
}
// lookup user account details
user, err := UserLookup(userAccount)
if err != nil {
return "", fmt.Errorf("user %s account not found", userAccount)
}
// verify non-root and a home directory exists
if user.Uid == "0" {
return "", fmt.Errorf("user %s account is root. A non-root user is required", userAccount)
}
if user.HomeDir == "" {
return "", fmt.Errorf("user %s account does not have a home directory. A home directory is required", userAccount)
}
system.PrintAndLogInfo(fmt.Sprintf("user %s account found and validated", userAccount))

return user.Username, nil
}
7 changes: 4 additions & 3 deletions internal/workbench/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,17 @@ func VerifyWorkbench() bool {
}

// Runs verify-installation command
func VerifyInstallation() error {
func VerifyInstallation(username string) error {
// stop rstudio-server
err := StopRStudioServer()
if err != nil {
return fmt.Errorf("issue stopping rstudio-server: %w", err)
}
// run verify-installation
err = system.RunCommand("rstudio-server verify-installation", true, 1)
verifyCommand := "rstudio-server verify-installation --verify-user=" + username
err = system.RunCommand(verifyCommand, true, 1)
if err != nil {
return fmt.Errorf("issue running verify-installation command 'rstudio-server verify-installation': %w", err)
return fmt.Errorf("issue running verify-installation command '%s': %w", verifyCommand, err)
}
// start rstudio-server
err = StartRStudioServer()
Expand Down

0 comments on commit 785d4f6

Please sign in to comment.