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

More flexible sudo/doas/elevated access usage #192

Merged
merged 12 commits into from
Aug 23, 2021
Merged
4 changes: 2 additions & 2 deletions cmd/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ var applyCommand = &cli.Command{
&phase.PrepareHosts{},
&phase.GatherFacts{},
&phase.DownloadBinaries{},
&phase.UploadBinaries{},
&phase.DownloadK0s{},
&phase.UploadFiles{},
&phase.ValidateHosts{},
&phase.GatherK0sFacts{},
&phase.ValidateFacts{SkipDowngradeCheck: ctx.Bool("disable-downgrade-check")},
&phase.UploadBinaries{},
&phase.DownloadK0s{},
&phase.RunHooks{Stage: "before", Action: "apply"},
&phase.ConfigureK0s{},
&phase.Restore{
Expand Down
39 changes: 32 additions & 7 deletions config/cluster/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,13 @@ func (h *Host) K0sInstallCommand() string {
flags.AddOrReplace(fmt.Sprintf("--kubelet-extra-args=%s", strconv.Quote(extra.Join())))
}

return h.Configurer.K0sCmdf("install %s %s", role, flags.Join())
cmd := h.Configurer.K0sCmdf("install %s %s", role, flags.Join())
sudocmd, err := h.Sudo(cmd)
if err != nil {
log.Warnf("%s: %s", h, err.Error())
return cmd
}
return sudocmd
}

// K0sBackupCommand returns a full command to be used as run k0s backup
Expand Down Expand Up @@ -233,7 +239,7 @@ func (h *Host) K0sServiceName() string {
// UpdateK0sBinary updates the binary on the host either by downloading or uploading, based on the config
func (h *Host) UpdateK0sBinary(version string) error {
if h.K0sBinaryPath != "" {
if err := h.Upload(h.K0sBinaryPath, h.Configurer.K0sBinaryPath()); err != nil {
if err := h.Upload(h.K0sBinaryPath, h.Configurer.K0sBinaryPath(), exec.Sudo(h)); err != nil {
return err
}
if err := h.Configurer.Chmod(h, h.Configurer.K0sBinaryPath(), "0700"); err != nil {
Expand All @@ -244,7 +250,7 @@ func (h *Host) UpdateK0sBinary(version string) error {
return err
}

output, err := h.ExecOutput(h.Configurer.K0sCmdf("version"))
output, err := h.ExecOutput(h.Configurer.K0sCmdf("version"), exec.Sudo(h))
if err != nil {
return fmt.Errorf("downloaded k0s binary is invalid: %s", err.Error())
}
Expand All @@ -270,7 +276,7 @@ type kubeNodeStatus struct {

// KubeNodeReady runs kubectl on the host and returns true if the given node is marked as ready
func (h *Host) KubeNodeReady(node *Host) (bool, error) {
output, err := h.ExecOutput(h.Configurer.KubectlCmdf("get node -l kubernetes.io/hostname=%s -o json", node.Metadata.Hostname), exec.HideOutput())
output, err := h.ExecOutput(h.Configurer.KubectlCmdf("get node -l kubernetes.io/hostname=%s -o json", node.Metadata.Hostname), exec.HideOutput(), exec.Sudo(h))
if err != nil {
return false, err
}
Expand Down Expand Up @@ -314,12 +320,12 @@ func (h *Host) WaitKubeNodeReady(node *Host) error {

// DrainNode drains the given node
func (h *Host) DrainNode(node *Host) error {
return h.Exec(h.Configurer.KubectlCmdf("drain --grace-period=120 --force --timeout=5m --ignore-daemonsets --delete-local-data %s", node.Metadata.Hostname))
return h.Exec(h.Configurer.KubectlCmdf("drain --grace-period=120 --force --timeout=5m --ignore-daemonsets --delete-local-data %s", node.Metadata.Hostname), exec.Sudo(h))
}

// UncordonNode marks the node schedulable again
func (h *Host) UncordonNode(node *Host) error {
return h.Exec(h.Configurer.KubectlCmdf("uncordon %s", node.Metadata.Hostname))
return h.Exec(h.Configurer.KubectlCmdf("uncordon %s", node.Metadata.Hostname), exec.Sudo(h))
}

// CheckHTTPStatus will perform a web request to the url and return an error if the http status is not the expected
Expand Down Expand Up @@ -359,7 +365,26 @@ func (h *Host) WaitK0sServiceRunning() error {
if !h.Configurer.ServiceIsRunning(h, h.K0sServiceName()) {
return fmt.Errorf("not running")
}
return h.Exec(h.Configurer.K0sCmdf("status"))
return h.Exec(h.Configurer.K0sCmdf("status"), exec.Sudo(h))
},
retry.DelayType(retry.CombineDelay(retry.FixedDelay, retry.RandomDelay)),
retry.MaxJitter(time.Second*2),
retry.Delay(time.Second*3),
retry.Attempts(60),
)
}

// WaitK0sServiceStopped blocks until the k0s service is no longer running on the host
func (h *Host) WaitK0sServiceStopped() error {
return retry.Do(
func() error {
if h.Configurer.ServiceIsRunning(h, h.K0sServiceName()) {
return fmt.Errorf("k0s still running")
}
if h.Exec(h.Configurer.K0sCmdf("status"), exec.Sudo(h)) == nil {
return fmt.Errorf("k0s still running")
}
return nil
},
retry.DelayType(retry.CombineDelay(retry.FixedDelay, retry.RandomDelay)),
retry.MaxJitter(time.Second*2),
Expand Down
4 changes: 2 additions & 2 deletions config/cluster/k0s.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func (k *K0s) SetDefaults() {
func (k K0s) GenerateToken(h *Host, role string, expiry time.Duration) (token string, err error) {
err = retry.Do(
func() error {
output, err := h.ExecOutput(h.Configurer.K0sCmdf("token create --config %s --role %s --expiry %s", h.K0sConfigPath(), role, expiry.String()), exec.HideOutput())
output, err := h.ExecOutput(h.Configurer.K0sCmdf("token create --config %s --role %s --expiry %s", h.K0sConfigPath(), role, expiry.String()), exec.HideOutput(), exec.Sudo(h))
if err != nil {
return err
}
Expand All @@ -74,5 +74,5 @@ func (k K0s) GenerateToken(h *Host, role string, expiry time.Duration) (token st

// GetClusterID uses kubectl to fetch the kube-system namespace uid
func (k K0s) GetClusterID(h *Host) (string, error) {
return h.ExecOutput(h.Configurer.KubectlCmdf("get -n kube-system namespace kube-system -o template={{.metadata.uid}}"))
return h.ExecOutput(h.Configurer.KubectlCmdf("get -n kube-system namespace kube-system -o template={{.metadata.uid}}"), exec.Sudo(h))
}
13 changes: 7 additions & 6 deletions configurer/linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strconv"
"strings"

"github.com/k0sproject/rig/exec"
"github.com/k0sproject/rig/os"
)

Expand Down Expand Up @@ -40,12 +41,12 @@ func (l Linux) Arch(h os.Host) (string, error) {

// Chmod changes file permissions
func (l Linux) Chmod(h os.Host, path, chmod string) error {
return h.Execf("sudo chmod %s %s", chmod, path)
return h.Execf("chmod %s %s", chmod, path, exec.Sudo(h))
}

// K0sCmdf can be used to construct k0s commands in sprintf style.
func (l Linux) K0sCmdf(template string, args ...interface{}) string {
return fmt.Sprintf("sudo %s %s", l.K0sBinaryPath(), fmt.Sprintf(template, args...))
return fmt.Sprintf("%s %s", l.K0sBinaryPath(), fmt.Sprintf(template, args...))
}

// K0sBinaryPath returns the location of k0s binary
Expand Down Expand Up @@ -86,7 +87,7 @@ func (l Linux) DownloadK0s(h os.Host, version, arch string) error {
return err
}

return h.Execf(`sudo install -m 0750 -o root -g adm "%s" "%s"`, tmp, l.K0sBinaryPath())
return h.Execf(`install -m 0750 -o root -g adm "%s" "%s"`, tmp, l.K0sBinaryPath(), exec.Sudo(h))
}

// ReplaceK0sTokenPath replaces the config path in the service stub
Expand All @@ -96,17 +97,17 @@ func (l Linux) ReplaceK0sTokenPath(h os.Host, spath string) error {

// FileContains returns true if a file contains the substring
func (l Linux) FileContains(h os.Host, path, s string) bool {
return h.Execf(`sudo grep -q "%s" "%s"`, s, path) == nil
return h.Execf(`grep -q "%s" "%s"`, s, path, exec.Sudo(h)) == nil
}

// MoveFile moves a file on the host
func (l Linux) MoveFile(h os.Host, src, dst string) error {
return h.Execf(`sudo mv "%s" "%s"`, src, dst)
return h.Execf(`mv "%s" "%s"`, src, dst, exec.Sudo(h))
}

// DeleteFile deletes a file on the host
func (l Linux) DeleteFile(h os.Host, path string) error {
return h.Execf(`sudo rm -f "%s"`, path)
return h.Execf(`rm -f "%s"`, path, exec.Sudo(h))
}

// KubeconfigPath returns the path to a kubeconfig on the host
Expand Down
7 changes: 2 additions & 5 deletions configurer/linux/alpine.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (

"github.com/k0sproject/k0sctl/configurer"
"github.com/k0sproject/rig"
"github.com/k0sproject/rig/exec"
"github.com/k0sproject/rig/os"
"github.com/k0sproject/rig/os/registry"
)
Expand Down Expand Up @@ -33,13 +34,9 @@ func init() {

// InstallPackage installs packages via slackpkg
func (l Alpine) InstallPackage(h os.Host, pkg ...string) error {
return h.Execf("sudo apk add --update %s", strings.Join(pkg, " "))
return h.Execf("apk add --update %s", strings.Join(pkg, " "), exec.Sudo(h))
}

func (l Alpine) Prepare(h os.Host) error {
if !l.CommandExist(h, "sudo") {
return h.Exec("apk add --update sudo")
}

return l.InstallPackage(h, "findutils", "coreutils")
}
12 changes: 11 additions & 1 deletion configurer/linux/slackware.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package linux

import (
"fmt"
"strings"

"github.com/k0sproject/rig"
Expand All @@ -27,5 +28,14 @@ func init() {

// InstallPackage installs packages via slackpkg
func (l Slackware) InstallPackage(h os.Host, pkg ...string) error {
return h.Execf("sudo slackpkg update && sudo slackpkg install --priority ADD %s", strings.Join(pkg, " "))
updatecmd, err := h.Sudo("slackpkg update")
if err != nil {
return err
}
installcmd, err := h.Sudo(fmt.Sprintf("slackpkg install --priority ADD %s", strings.Join(pkg, " ")))
if err != nil {
return err
}

return h.Execf("%s && %s", updatecmd, installcmd)
}
13 changes: 11 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,22 @@ go 1.16

require (
github.com/AlecAivazis/survey/v2 v2.2.8
github.com/Azure/go-ntlmssp v0.0.0-20200615164410-66371956d46c // indirect
github.com/ChrisTrenkamp/goxpath v0.0.0-20210404020558-97928f7e12b6 // indirect
github.com/Masterminds/semver v1.5.0
github.com/avast/retry-go v3.0.0+incompatible
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
github.com/creasty/defaults v1.5.1
github.com/denisbrodbeck/machineid v1.0.1
github.com/gammazero/workerpool v1.1.1
github.com/go-playground/validator/v10 v10.4.1
github.com/gofrs/uuid v4.0.0+incompatible // indirect
github.com/hashicorp/go-version v1.2.1
github.com/k0sproject/dig v0.2.0
github.com/k0sproject/rig v0.3.23
github.com/k0sproject/rig v0.4.4
github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786 // indirect
github.com/masterzen/winrm v0.0.0-20210623064412-3b76017826b0 // indirect
github.com/mattn/go-isatty v0.0.12
github.com/segmentio/analytics-go v3.1.0+incompatible
github.com/segmentio/backo-go v0.0.0-20200129164019-23eae7c10bd3 // indirect
Expand All @@ -23,7 +28,11 @@ require (
github.com/stretchr/testify v1.7.0
github.com/urfave/cli/v2 v2.3.0
github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d // indirect
golang.org/x/sys v0.0.0-20210819072135-bce67f096156
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
golang.org/x/text v0.3.7 // indirect
gopkg.in/yaml.v2 v2.4.0
k8s.io/client-go v0.19.3
)
Loading