Skip to content

Commit

Permalink
feat(dismiss): add two ways to run without git
Browse files Browse the repository at this point in the history
Either specify --release and --namespace or use --use-deploy-report.

Signed-off-by: Ilya Lesikov <ilya@lesikov.com>
  • Loading branch information
ilya-lesikov committed Feb 10, 2023
1 parent 163961d commit f2e1d16
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 45 deletions.
1 change: 1 addition & 0 deletions cmd/werf/common/cmd_data.go
Expand Up @@ -98,6 +98,7 @@ type CmdData struct {
BuildReportPath *string

SaveDeployReport *bool
UseDeployReport *bool
DeployReportPath *string

VirtualMerge *bool
Expand Down
22 changes: 21 additions & 1 deletion cmd/werf/common/common.go
Expand Up @@ -41,9 +41,16 @@ const (
DefaultBuildReportPathJSON = ".werf-build-report.json"

DefaultSaveDeployReport = false
DefaultUseDeployReport = false
DefaultDeployReportPathJSON = ".werf-deploy-report.json"
)

type GitWorktreeNotFoundError struct{}

func (e *GitWorktreeNotFoundError) Error() string {
return fmt.Sprintf("werf requires a git work tree for the project to exist: unable to find a valid .git in the current directory %q or parent directories, you may also specify git work tree explicitly with --git-work-tree option (or WERF_GIT_WORK_TREE env var)", util.GetAbsoluteFilepath("."))
}

func GetLongCommandDescription(text string) string {
return logboek.FitText(text, types.FitTextOptions{MaxWidth: 100})
}
Expand Down Expand Up @@ -270,6 +277,19 @@ func GetDeployReportPath(cmdData *CmdData) (string, error) {
}
}

func SetupUseDeployReport(cmdData *CmdData, cmd *cobra.Command) {
cmdData.UseDeployReport = new(bool)
cmd.Flags().BoolVarP(cmdData.UseDeployReport, "use-deploy-report", "", util.GetBoolEnvironmentDefaultFalse("WERF_USE_DEPLOY_REPORT"), fmt.Sprintf("Use previously saved deploy report (by default $WERF_USE_DEPLOY_REPORT or %t)", DefaultUseDeployReport))
}

func GetUseDeployReport(cmdData *CmdData) bool {
if cmdData.UseDeployReport == nil {
return false
}

return *cmdData.UseDeployReport
}

func SetupWithoutKube(cmdData *CmdData, cmd *cobra.Command) {
cmdData.WithoutKube = new(bool)
cmd.Flags().BoolVarP(cmdData.WithoutKube, "without-kube", "", util.GetBoolEnvironmentDefaultFalse("WERF_WITHOUT_KUBE"), "Do not skip deployed Kubernetes images (default $WERF_WITHOUT_KUBE)")
Expand Down Expand Up @@ -1050,7 +1070,7 @@ func GetGitWorkTree(ctx context.Context, cmdData *CmdData, workingDir string) (s
return res, nil
}

return "", fmt.Errorf("werf requires a git work tree for the project to exist: unable to find a valid .git in the current directory %q or parent directories, you may also specify git work tree explicitly with --git-work-tree option (or WERF_GIT_WORK_TREE env var)", util.GetAbsoluteFilepath("."))
return "", &GitWorktreeNotFoundError{}
}

func LookupGitWorkTree(ctx context.Context, workingDir string) (string, error) {
Expand Down
126 changes: 82 additions & 44 deletions cmd/werf/dismiss/dismiss.go
Expand Up @@ -2,21 +2,24 @@ package dismiss

import (
"context"
"encoding/json"
"errors"
"fmt"
"os"
"time"

"github.com/spf13/cobra"
helm_v3 "helm.sh/helm/v3/cmd/helm"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/registry"
helmrelease "helm.sh/helm/v3/pkg/release"
"helm.sh/helm/v3/pkg/storage/driver"

"github.com/werf/kubedog/pkg/kube"
"github.com/werf/logboek"
"github.com/werf/werf/cmd/werf/common"
"github.com/werf/werf/pkg/config/deploy_params"
"github.com/werf/werf/pkg/deploy/helm"
"github.com/werf/werf/pkg/deploy/helm/chart_extender"
"github.com/werf/werf/pkg/deploy/helm/command_helpers"
"github.com/werf/werf/pkg/deploy/lock_manager"
"github.com/werf/werf/pkg/git_repo"
Expand Down Expand Up @@ -91,6 +94,9 @@ func NewCmd(ctx context.Context) *cobra.Command {
common.SetupRelease(&commonCmdData, cmd)
common.SetupNamespace(&commonCmdData, cmd)

common.SetupUseDeployReport(&commonCmdData, cmd)
common.SetupDeployReportPath(&commonCmdData, cmd)

common.SetupKubeConfig(&commonCmdData, cmd)
common.SetupKubeConfigBase64(&commonCmdData, cmd)
common.SetupKubeContext(&commonCmdData, cmd)
Expand Down Expand Up @@ -159,32 +165,85 @@ func runDismiss(ctx context.Context) error {

common.LogKubeContext(kube.Context)

var gitNotFoundErr *common.GitWorktreeNotFoundError
giterminismManager, err := common.GetGiterminismManager(ctx, &commonCmdData)
if err != nil {
return err
}

common.ProcessLogProjectDir(&commonCmdData, giterminismManager.ProjectDir())

werfConfigPath, werfConfig, err := common.GetRequiredWerfConfig(ctx, &commonCmdData, giterminismManager, common.GetWerfConfigOptions(&commonCmdData, true))
if err != nil {
return fmt.Errorf("unable to load werf config: %w", err)
if !errors.As(err, &gitNotFoundErr) {
return err
}
}
logboek.LogOptionalLn()

common.SetupOndemandKubeInitializer(*commonCmdData.KubeContext, *commonCmdData.KubeConfig, *commonCmdData.KubeConfigBase64, *commonCmdData.KubeConfigPathMergeList)
if err := common.GetOndemandKubeInitializer().Init(ctx); err != nil {
return err
}

namespace, err := deploy_params.GetKubernetesNamespace(*commonCmdData.Namespace, *commonCmdData.Environment, werfConfig)
if err != nil {
return err
}
namespaceSpecified := *commonCmdData.Namespace != ""
releaseSpecified := *commonCmdData.Release != ""

var namespace string
var release string
var helmRegistryClient *registry.Client
if namespaceSpecified || releaseSpecified {
if namespaceSpecified && !releaseSpecified {
return fmt.Errorf("--namespace specified, but not --release, while should be specified both or none")
} else if !namespaceSpecified && releaseSpecified {
return fmt.Errorf("--release specified, but not --namespace, while should be specified both or none")
}

releaseName, err := deploy_params.GetHelmRelease(*commonCmdData.Release, *commonCmdData.Environment, namespace, werfConfig)
if err != nil {
return err
namespace = *commonCmdData.Namespace
release = *commonCmdData.Release
} else if common.GetUseDeployReport(&commonCmdData) {
deployReportPath, err := common.GetDeployReportPath(&commonCmdData)
if err != nil {
return fmt.Errorf("unable to get deploy report path: %w", err)
}

deployReportByte, err := os.ReadFile(deployReportPath)
if err != nil {
return fmt.Errorf("unable to read deploy report file %q: %w", deployReportPath, err)
}

var deployReport helmrelease.DeployReport
if err := json.Unmarshal(deployReportByte, &deployReport); err != nil {
return fmt.Errorf("unable to unmarshal deploy report file %q: %w", deployReportPath, err)
}

if deployReport.Namespace == "" {
return fmt.Errorf("unable to get namespace from deploy report file %q", deployReportPath)
}

if deployReport.Release == "" {
return fmt.Errorf("unable to get release from deploy report file %q", deployReportPath)
}

namespace = deployReport.Namespace
release = deployReport.Release
} else if gitNotFoundErr != nil {
return fmt.Errorf("dismiss should either be executed in a git repository or with --namespace and --release specified, or with --use-deploy-report")
} else {
common.ProcessLogProjectDir(&commonCmdData, giterminismManager.ProjectDir())

_, werfConfig, err := common.GetRequiredWerfConfig(ctx, &commonCmdData, giterminismManager, common.GetWerfConfigOptions(&commonCmdData, true))
if err != nil {
return fmt.Errorf("unable to load werf config: %w", err)
}
logboek.LogOptionalLn()

namespace, err = deploy_params.GetKubernetesNamespace(*commonCmdData.Namespace, *commonCmdData.Environment, werfConfig)
if err != nil {
return err
}

release, err = deploy_params.GetHelmRelease(*commonCmdData.Release, *commonCmdData.Environment, namespace, werfConfig)
if err != nil {
return err
}

helmRegistryClient, err = common.NewHelmRegistryClient(ctx, *commonCmdData.DockerConfig, *commonCmdData.InsecureHelmDependencies)
if err != nil {
return fmt.Errorf("unable to create helm registry client: %w", err)
}
}

var lockManager *lock_manager.LockManager
Expand All @@ -196,27 +255,6 @@ func runDismiss(ctx context.Context) error {
}
}

chartDir, err := common.GetHelmChartDir(werfConfigPath, werfConfig, giterminismManager)
if err != nil {
return fmt.Errorf("getting helm chart dir failed: %w", err)
}

helmRegistryClient, err := common.NewHelmRegistryClient(ctx, *commonCmdData.DockerConfig, *commonCmdData.InsecureHelmDependencies)
if err != nil {
return fmt.Errorf("unable to create helm registry client: %w", err)
}

wc := chart_extender.NewWerfChart(ctx, giterminismManager, nil, chartDir, helm_v3.Settings, helmRegistryClient, chart_extender.WerfChartOptions{
IgnoreInvalidAnnotationsAndLabels: true,
})

if err := wc.SetEnv(*commonCmdData.Environment); err != nil {
return err
}
if err := wc.SetWerfConfig(werfConfig); err != nil {
return err
}

actionConfig := new(action.Configuration)
if err := helm.InitActionConfig(ctx, common.GetOndemandKubeInitializer(), namespace, helm_v3.Settings, actionConfig, helm.InitActionConfigOptions{
StatusProgressPeriod: time.Duration(*commonCmdData.StatusProgressPeriodSeconds) * time.Second,
Expand All @@ -241,19 +279,19 @@ func runDismiss(ctx context.Context) error {
})

logboek.Context(ctx).Default().LogFDetails("Using namespace: %s\n", namespace)
logboek.Context(ctx).Default().LogFDetails("Using release: %s\n", releaseName)
logboek.Context(ctx).Default().LogFDetails("Using release: %s\n", release)

if cmdData.WithNamespace {
// TODO: solve lock release + delete-namespace case
return helmUninstallCmd.RunE(helmUninstallCmd, []string{releaseName})
return helmUninstallCmd.RunE(helmUninstallCmd, []string{release})
} else {
if _, err := actionConfig.Releases.History(releaseName); errors.Is(err, driver.ErrReleaseNotFound) {
logboek.Context(ctx).Default().LogFDetails("No such release %q\n", releaseName)
if _, err := actionConfig.Releases.History(release); errors.Is(err, driver.ErrReleaseNotFound) {
logboek.Context(ctx).Default().LogFDetails("No such release %q\n", release)
return nil
}

return command_helpers.LockReleaseWrapper(ctx, releaseName, lockManager, func() error {
return helmUninstallCmd.RunE(helmUninstallCmd, []string{releaseName})
return command_helpers.LockReleaseWrapper(ctx, release, lockManager, func() error {
return helmUninstallCmd.RunE(helmUninstallCmd, []string{release})
})
}
}

0 comments on commit f2e1d16

Please sign in to comment.