Skip to content

Commit

Permalink
[Elastic Agent] Don't perform install until after enroll (#21772)
Browse files Browse the repository at this point in the history
* Flip install and enroll.

* Update order.

* Always perform uninstall of service.

* Fix issue with no enrolling.

* Fix enrollment no.

* Add changelog.
  • Loading branch information
blakerouse authored Oct 14, 2020
1 parent 116d767 commit 34da9c9
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 59 deletions.
1 change: 1 addition & 0 deletions x-pack/elastic-agent/CHANGELOG.next.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -36,5 +36,6 @@
- Add `elastic.agent.id` and `elastic.agent.version` to published events from filebeat and metricbeat {pull}21543[21543]
- Add `upgrade` subcommand to perform upgrade of installed Elastic Agent {pull}21425[21425]
- Update `fleet.yml` and Kibana hosts when a policy change updates the Kibana hosts {pull}21599[21599]
- Update `install` command to perform enroll before starting Elastic Agent {pull}21772[21772]
- Update `fleet.kibana.path` from a POLICY_CHANGE {pull}21804[21804]
- Removed `install-service.ps1` and `uninstall-service.ps1` from Windows .zip packaging {pull}21694[21694]
4 changes: 2 additions & 2 deletions x-pack/elastic-agent/pkg/agent/cmd/enroll.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func newEnrollCommandWithArgs(flags *globalFlags, _ []string, streams *cli.IOStr
Args: cobra.ExactArgs(2),
Run: func(c *cobra.Command, args []string) {
if err := enroll(streams, c, flags, args); err != nil {
fmt.Fprintf(streams.Err, "%v\n", err)
fmt.Fprintf(streams.Err, "Error: %v\n", err)
os.Exit(1)
}
},
Expand Down Expand Up @@ -193,7 +193,7 @@ func enroll(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags, args

// skip restarting
noRestart, _ := cmd.Flags().GetBool("no-restart")
if noRestart {
if noRestart || fromInstall {
return nil
}

Expand Down
116 changes: 69 additions & 47 deletions x-pack/elastic-agent/pkg/agent/cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import (
"os"
"os/exec"

"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/application"
"github.com/elastic/beats/v7/x-pack/elastic-agent/pkg/agent/application/paths"

"github.com/spf13/cobra"

c "github.com/elastic/beats/v7/libbeat/common/cli"
Expand All @@ -28,7 +31,7 @@ would like the Agent to operate.
`,
Run: func(c *cobra.Command, args []string) {
if err := installCmd(streams, c, flags, args); err != nil {
fmt.Fprintf(streams.Err, "%v\n", err)
fmt.Fprintf(streams.Err, "Error: %v\n", err)
os.Exit(1)
}
},
Expand All @@ -43,6 +46,7 @@ would like the Agent to operate.
}

func installCmd(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags, args []string) error {
var err error
if !install.HasRoot() {
return fmt.Errorf("unable to perform install command, not executed with %s permissions", install.PermissionUser)
}
Expand All @@ -51,14 +55,24 @@ func installCmd(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags,
return fmt.Errorf("already installed at: %s", install.InstallPath)
}

// check the lock to ensure that elastic-agent is not already running in this directory
locker := application.NewAppLocker(paths.Data())
if err := locker.TryLock(); err != nil {
if err == application.ErrAppAlreadyRunning {
return fmt.Errorf("cannot perform installation as Elastic Agent is already running from this directory")
}
return err
}
locker.Unlock()

warn.PrintNotGA(streams.Out)
force, _ := cmd.Flags().GetBool("force")
if status == install.Broken {
if !force {
fmt.Fprintf(streams.Out, "Elastic Agent is installed but currently broken: %s\n", reason)
confirm, err := c.Confirm(fmt.Sprintf("Continuing will re-install Elastic Agent over the current installation at %s. Do you want to continue?", install.InstallPath), true)
if err != nil {
return fmt.Errorf("Error: problem reading prompt response")
return fmt.Errorf("problem reading prompt response")
}
if !confirm {
return fmt.Errorf("installation was cancelled by the user")
Expand All @@ -68,25 +82,15 @@ func installCmd(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags,
if !force {
confirm, err := c.Confirm(fmt.Sprintf("Elastic Agent will be installed at %s and will run as a service. Do you want to continue?", install.InstallPath), true)
if err != nil {
return fmt.Errorf("Error: problem reading prompt response")
return fmt.Errorf("problem reading prompt response")
}
if !confirm {
return fmt.Errorf("installation was cancelled by the user")
}
}
}

err := install.Install()
if err != nil {
return fmt.Errorf("Error: %s", err)
}
err = install.StartService()
if err != nil {
fmt.Fprintf(streams.Out, "Installation of required system files was successful, but starting of the service failed.\n")
return err
}
fmt.Fprintf(streams.Out, "Installation was successful and Elastic Agent is running.\n")

enroll := true
askEnroll := true
kibana, _ := cmd.Flags().GetString("kibana-url")
token, _ := cmd.Flags().GetString("enrollment-token")
Expand All @@ -102,53 +106,71 @@ func installCmd(streams *cli.IOStreams, cmd *cobra.Command, flags *globalFlags,
return fmt.Errorf("problem reading prompt response")
}
if !confirm {
// not enrolling, all done (standalone mode)
return nil
// not enrolling
enroll = false
}
}
if !askEnroll && (kibana == "" || token == "") {
// force was performed without required enrollment arguments, all done (standalone mode)
return nil
enroll = false
}

if kibana == "" {
kibana, err = c.ReadInput("Kibana URL you want to enroll this Agent into:")
if err != nil {
return fmt.Errorf("problem reading prompt response")
}
if enroll {
if kibana == "" {
fmt.Fprintf(streams.Out, "Enrollment cancelled because no URL was provided.\n")
return nil
}
}
if token == "" {
token, err = c.ReadInput("Fleet enrollment token:")
if err != nil {
return fmt.Errorf("problem reading prompt response")
kibana, err = c.ReadInput("Kibana URL you want to enroll this Agent into:")
if err != nil {
return fmt.Errorf("problem reading prompt response")
}
if kibana == "" {
fmt.Fprintf(streams.Out, "Enrollment cancelled because no URL was provided.\n")
return nil
}
}
if token == "" {
fmt.Fprintf(streams.Out, "Enrollment cancelled because no enrollment token was provided.\n")
return nil
token, err = c.ReadInput("Fleet enrollment token:")
if err != nil {
return fmt.Errorf("problem reading prompt response")
}
if token == "" {
fmt.Fprintf(streams.Out, "Enrollment cancelled because no enrollment token was provided.\n")
return nil
}
}
}

enrollArgs := []string{"enroll", kibana, token, "--from-install"}
enrollArgs = append(enrollArgs, buildEnrollmentFlags(cmd)...)
enrollCmd := exec.Command(install.ExecutablePath(), enrollArgs...)
enrollCmd.Stdin = os.Stdin
enrollCmd.Stdout = os.Stdout
enrollCmd.Stderr = os.Stderr
err = enrollCmd.Start()
err = install.Install()
if err != nil {
return fmt.Errorf("failed to execute enroll command: %s", err)
return err
}
err = enrollCmd.Wait()
if err == nil {
return nil

if enroll {
enrollArgs := []string{"enroll", kibana, token, "--from-install"}
enrollArgs = append(enrollArgs, buildEnrollmentFlags(cmd)...)
enrollCmd := exec.Command(install.ExecutablePath(), enrollArgs...)
enrollCmd.Stdin = os.Stdin
enrollCmd.Stdout = os.Stdout
enrollCmd.Stderr = os.Stderr
err = enrollCmd.Start()
if err != nil {
install.Uninstall()
return fmt.Errorf("failed to execute enroll command: %s", err)
}
err = enrollCmd.Wait()
if err != nil {
install.Uninstall()
exitErr, ok := err.(*exec.ExitError)
if ok {
return fmt.Errorf("enroll command failed with exit code: %d", exitErr.ExitCode())
}
return fmt.Errorf("enroll command failed for unknown reason: %s", err)
}
}
exitErr, ok := err.(*exec.ExitError)
if ok {
return fmt.Errorf("enroll command failed with exit code: %d", exitErr.ExitCode())

err = install.StartService()
if err != nil {
fmt.Fprintf(streams.Out, "Installation of required system files was successful, but starting of the service failed.\n")
return err
}
return fmt.Errorf("enroll command failed for unknown reason: %s", err)
fmt.Fprintf(streams.Out, "Installation was successful and Elastic Agent is running.\n")
return nil
}
2 changes: 1 addition & 1 deletion x-pack/elastic-agent/pkg/agent/cmd/uninstall.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Unless -f is used this command will ask confirmation before performing removal.
`,
Run: func(c *cobra.Command, args []string) {
if err := uninstallCmd(streams, c, flags, args); err != nil {
fmt.Fprintf(streams.Err, "%v\n", err)
fmt.Fprintf(streams.Err, "Error: %v\n", err)
os.Exit(1)
}
},
Expand Down
10 changes: 1 addition & 9 deletions x-pack/elastic-agent/pkg/agent/install/uninstall.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,7 @@ func Uninstall() error {
}
status = service.StatusStopped
}
if status == service.StatusStopped {
err := svc.Uninstall()
if err != nil {
return errors.New(
err,
fmt.Sprintf("failed to uninstall service (%s)", ServiceName),
errors.M("service", ServiceName))
}
}
_ = svc.Uninstall()

// remove, if present on platform
if ShellWrapperPath != "" {
Expand Down

0 comments on commit 34da9c9

Please sign in to comment.