Get rid of shell-out and invoke kubetcl directly via exec

pull/334/head
“Anton 4 years ago
parent bd2df01b12
commit 4989826124

@ -150,15 +150,14 @@ func generateInstallManifests(targetPath, namespace, tmpDir string, localManifes
} }
func applyInstallManifests(ctx context.Context, manifestPath string, components []string) error { func applyInstallManifests(ctx context.Context, manifestPath string, components []string) error {
command := fmt.Sprintf("kubectl apply -f %s", manifestPath) kubectlArgs := []string{"apply", "-f", manifestPath}
if _, err := utils.execCommand(ctx, ModeOS, command); err != nil { if _, err := utils.execKubectlCommand(ctx, ModeOS, kubectlArgs...); err != nil {
return fmt.Errorf("install failed") return fmt.Errorf("install failed")
} }
for _, deployment := range components { for _, deployment := range components {
command = fmt.Sprintf("kubectl -n %s rollout status deployment %s --timeout=%s", kubectlArgs = []string{"-n", namespace, "rollout", "status", "deployment", deployment, "--timeout", timeout.String()}
namespace, deployment, timeout.String()) if _, err := utils.execKubectlCommand(ctx, ModeOS, kubectlArgs...); err != nil {
if _, err := utils.execCommand(ctx, ModeOS, command); err != nil {
return fmt.Errorf("install failed") return fmt.Errorf("install failed")
} }
} }
@ -239,8 +238,8 @@ func generateSyncManifests(url, branch, name, namespace, targetPath, tmpDir stri
} }
func applySyncManifests(ctx context.Context, kubeClient client.Client, name, namespace, targetPath, tmpDir string) error { func applySyncManifests(ctx context.Context, kubeClient client.Client, name, namespace, targetPath, tmpDir string) error {
command := fmt.Sprintf("kubectl apply -k %s", filepath.Join(tmpDir, targetPath, namespace)) kubectlArgs := []string{"apply", "-k", filepath.Join(tmpDir, targetPath, namespace)}
if _, err := utils.execCommand(ctx, ModeStderrOS, command); err != nil { if _, err := utils.execKubectlCommand(ctx, ModeStderrOS, kubectlArgs...); err != nil {
return err return err
} }

@ -18,13 +18,14 @@ package main
import ( import (
"context" "context"
"fmt" "encoding/json"
"os" "os"
"os/exec" "os/exec"
"strings" "strings"
"github.com/blang/semver/v4" "github.com/blang/semver/v4"
"github.com/spf13/cobra" "github.com/spf13/cobra"
apimachineryversion "k8s.io/apimachinery/pkg/version"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd" "k8s.io/client-go/tools/clientcmd"
) )
@ -48,6 +49,10 @@ var (
checkComponents []string checkComponents []string
) )
type kubectlVersion struct {
ClientVersion *apimachineryversion.Info `json:"clientVersion"`
}
func init() { func init() {
checkCmd.Flags().BoolVarP(&checkPre, "pre", "", false, checkCmd.Flags().BoolVarP(&checkPre, "pre", "", false,
"only run pre-installation checks") "only run pre-installation checks")
@ -97,14 +102,20 @@ func kubectlCheck(ctx context.Context, version string) bool {
return false return false
} }
command := "kubectl version --client --short | awk '{ print $3 }'" kubectlArgs := []string{"version", "--client", "--output", "json"}
output, err := utils.execCommand(ctx, ModeCapture, command) output, err := utils.execKubectlCommand(ctx, ModeCapture, kubectlArgs...)
if err != nil { if err != nil {
logger.Failuref("kubectl version can't be determined") logger.Failuref("kubectl version can't be determined")
return false return false
} }
v, err := semver.ParseTolerant(output) kv := &kubectlVersion{}
if err = json.Unmarshal([]byte(output), kv); err != nil {
logger.Failuref("kubectl version output can't be unmarshaled")
return false
}
v, err := semver.ParseTolerant(kv.ClientVersion.GitVersion)
if err != nil { if err != nil {
logger.Failuref("kubectl version can't be parsed") logger.Failuref("kubectl version can't be parsed")
return false return false
@ -161,9 +172,8 @@ func componentsCheck() bool {
ok := true ok := true
for _, deployment := range checkComponents { for _, deployment := range checkComponents {
command := fmt.Sprintf("kubectl -n %s rollout status deployment %s --timeout=%s", kubectlArgs := []string{"-n", namespace, "rollout", "status", "deployment", deployment, "--timeout", timeout.String()}
namespace, deployment, timeout.String()) if output, err := utils.execKubectlCommand(ctx, ModeCapture, kubectlArgs...); err != nil {
if output, err := utils.execCommand(ctx, ModeCapture, command); err != nil {
logger.Failuref("%s: %s", deployment, strings.TrimSuffix(output, "\n")) logger.Failuref("%s: %s", deployment, strings.TrimSuffix(output, "\n"))
ok = false ok = false
} else { } else {

@ -158,14 +158,13 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
if verbose { if verbose {
applyOutput = ModeOS applyOutput = ModeOS
} }
dryRun := ""
kubectlArgs := []string{"apply", "-f", manifest}
if installDryRun { if installDryRun {
dryRun = "--dry-run=client" args = append(args, "--dry-run=client")
applyOutput = ModeOS applyOutput = ModeOS
} }
if _, err := utils.execKubectlCommand(ctx, applyOutput, kubectlArgs...); err != nil {
command := fmt.Sprintf("kubectl apply -f %s %s", manifest, dryRun)
if _, err := utils.execCommand(ctx, applyOutput, command); err != nil {
return fmt.Errorf("install failed") return fmt.Errorf("install failed")
} }
@ -178,9 +177,8 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
logger.Waitingf("verifying installation") logger.Waitingf("verifying installation")
for _, deployment := range installComponents { for _, deployment := range installComponents {
command = fmt.Sprintf("kubectl -n %s rollout status deployment %s --timeout=%s", kubectlArgs = []string{"-n", namespace, "rollout", "status", "deployment", deployment, "--timeout", timeout.String()}
namespace, deployment, timeout.String()) if _, err := utils.execKubectlCommand(ctx, applyOutput, kubectlArgs...); err != nil {
if _, err := utils.execCommand(ctx, applyOutput, command); err != nil {
return fmt.Errorf("install failed") return fmt.Errorf("install failed")
} else { } else {
logger.Successf("%s ready", deployment) logger.Successf("%s ready", deployment)

@ -71,10 +71,8 @@ func uninstallCmdRun(cmd *cobra.Command, args []string) error {
return err return err
} }
dryRun := "" dryRun := "--dry-run=server"
if uninstallDryRun { if !uninstallDryRun && !uninstallSilent {
dryRun = "--dry-run=server"
} else if !uninstallSilent {
prompt := promptui.Prompt{ prompt := promptui.Prompt{
Label: fmt.Sprintf("Are you sure you want to delete the %s namespace", namespace), Label: fmt.Sprintf("Are you sure you want to delete the %s namespace", namespace),
IsConfirm: true, IsConfirm: true,
@ -105,9 +103,15 @@ func uninstallCmdRun(cmd *cobra.Command, args []string) error {
sourcev1.HelmRepositoryKind, sourcev1.HelmRepositoryKind,
helmv2.HelmReleaseKind, helmv2.HelmReleaseKind,
} { } {
command := fmt.Sprintf("kubectl -n %s delete %s --all --ignore-not-found --timeout=%s %s", kubectlArgs := []string{
namespace, kind, timeout.String(), dryRun) "-n", namespace,
if _, err := utils.execCommand(ctx, ModeOS, command); err != nil { "delete", kind, "--all", "--ignore-not-found",
"--timeout", timeout.String(),
}
if uninstallDryRun {
kubectlArgs = append(kubectlArgs, dryRun)
}
if _, err := utils.execKubectlCommand(ctx, ModeOS, kubectlArgs...); err != nil {
return fmt.Errorf("uninstall failed: %w", err) return fmt.Errorf("uninstall failed: %w", err)
} }
} }
@ -123,9 +127,15 @@ func uninstallCmdRun(cmd *cobra.Command, args []string) error {
logger.Actionf("uninstalling components") logger.Actionf("uninstalling components")
for _, kind := range kinds { for _, kind := range kinds {
command := fmt.Sprintf("kubectl delete %s -l app.kubernetes.io/instance=%s --ignore-not-found --timeout=%s %s", kubectlArgs := []string{
kind, namespace, timeout.String(), dryRun) "delete", kind,
if _, err := utils.execCommand(ctx, ModeOS, command); err != nil { "-l", fmt.Sprintf("app.kubernetes.io/instance=%s", namespace),
"--ignore-not-found", "--timeout", timeout.String(),
}
if uninstallDryRun {
kubectlArgs = append(kubectlArgs, dryRun)
}
if _, err := utils.execKubectlCommand(ctx, ModeOS, kubectlArgs...); err != nil {
return fmt.Errorf("uninstall failed: %w", err) return fmt.Errorf("uninstall failed: %w", err)
} }
} }

@ -60,9 +60,10 @@ const (
ModeCapture ExecMode = "capture.stderr|stdout" ModeCapture ExecMode = "capture.stderr|stdout"
) )
func (*Utils) execCommand(ctx context.Context, mode ExecMode, command string) (string, error) { func (*Utils) execKubectlCommand(ctx context.Context, mode ExecMode, args ...string) (string, error) {
var stdoutBuf, stderrBuf bytes.Buffer var stdoutBuf, stderrBuf bytes.Buffer
c := exec.CommandContext(ctx, "/bin/sh", "-c", command)
c := exec.CommandContext(ctx, "kubectl", args...)
if mode == ModeStderrOS { if mode == ModeStderrOS {
c.Stderr = io.MultiWriter(os.Stderr, &stderrBuf) c.Stderr = io.MultiWriter(os.Stderr, &stderrBuf)

Loading…
Cancel
Save