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

CR-4773 - add repo uninstall command #122

Merged
merged 14 commits into from
Jul 5, 2021
24 changes: 5 additions & 19 deletions cmd/commands/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"time"

"github.com/argoproj-labs/argocd-autopilot/pkg/application"
"github.com/argoproj-labs/argocd-autopilot/pkg/argocd"
"github.com/argoproj-labs/argocd-autopilot/pkg/fs"
"github.com/argoproj-labs/argocd-autopilot/pkg/git"
"github.com/argoproj-labs/argocd-autopilot/pkg/kube"
Expand Down Expand Up @@ -199,13 +198,14 @@ func RunAppCreate(ctx context.Context, opts *AppCreateOptions) error {

if opts.AppsCloneOpts != opts.CloneOpts {
log.G(ctx).Info("committing changes to apps repo...")
if err = appsRepo.Persist(ctx, &git.PushOptions{CommitMsg: getCommitMsg(opts, appsfs)}); err != nil {
if _, err = appsRepo.Persist(ctx, &git.PushOptions{CommitMsg: getCommitMsg(opts, appsfs)}); err != nil {
return fmt.Errorf("failed to push to apps repo: %w", err)
}
}

log.G(ctx).Info("committing changes to gitops repo...")
if err = r.Persist(ctx, &git.PushOptions{CommitMsg: getCommitMsg(opts, repofs)}); err != nil {
revision, err := r.Persist(ctx, &git.PushOptions{CommitMsg: getCommitMsg(opts, repofs)})
if err != nil {
return fmt.Errorf("failed to push to gitops repo: %w", err)
}

Expand All @@ -219,7 +219,7 @@ func RunAppCreate(ctx context.Context, opts *AppCreateOptions) error {
fullName := fmt.Sprintf("%s-%s", opts.ProjectName, opts.AppOpts.AppName)
// wait for argocd to be ready before applying argocd-apps
stop := util.WithSpinner(ctx, fmt.Sprintf("waiting for '%s' to be ready", fullName))
if err = waitAppSynced(ctx, opts.KubeFactory, opts.Timeout, fullName, namespace); err != nil {
if err = waitAppSynced(ctx, opts.KubeFactory, opts.Timeout, fullName, namespace, revision); err != nil {
stop()
return fmt.Errorf("failed waiting for application to sync: %w", err)
}
Expand Down Expand Up @@ -298,20 +298,6 @@ func getCommitMsg(opts *AppCreateOptions, repofs fs.FS) string {
return commitMsg
}

func waitAppSynced(ctx context.Context, f kube.Factory, timeout time.Duration, appName, namespace string) error {
return f.Wait(ctx, &kube.WaitOptions{
Interval: store.Default.WaitInterval,
Timeout: timeout,
Resources: []kube.Resource{
{
Name: appName,
Namespace: namespace,
WaitFunc: argocd.CheckAppSynced,
},
},
})
}

func NewAppListCommand(cloneOpts *git.CloneOptions) *cobra.Command {
cmd := &cobra.Command{
Use: "list [PROJECT_NAME]",
Expand Down Expand Up @@ -490,7 +476,7 @@ func RunAppDelete(ctx context.Context, opts *AppDeleteOptions) error {
}

log.G(ctx).Info("committing changes to gitops repo...")
if err = r.Persist(ctx, &git.PushOptions{CommitMsg: commitMsg}); err != nil {
if _, err = r.Persist(ctx, &git.PushOptions{CommitMsg: commitMsg}); err != nil {
return fmt.Errorf("failed to push to repo: %w", err)
}

Expand Down
17 changes: 17 additions & 0 deletions cmd/commands/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import (
_ "embed"
"fmt"
"os"
"time"

"github.com/argoproj-labs/argocd-autopilot/pkg/argocd"
"github.com/argoproj-labs/argocd-autopilot/pkg/fs"
"github.com/argoproj-labs/argocd-autopilot/pkg/git"
"github.com/argoproj-labs/argocd-autopilot/pkg/kube"
"github.com/argoproj-labs/argocd-autopilot/pkg/log"
"github.com/argoproj-labs/argocd-autopilot/pkg/store"
"github.com/argoproj-labs/argocd-autopilot/pkg/util"
Expand Down Expand Up @@ -141,6 +144,20 @@ func createApp(opts *createAppOptions) ([]byte, error) {
return yaml.Marshal(app)
}

func waitAppSynced(ctx context.Context, f kube.Factory, timeout time.Duration, appName, namespace, revision string) error {
return f.Wait(ctx, &kube.WaitOptions{
Interval: store.Default.WaitInterval,
Timeout: timeout,
Resources: []kube.Resource{
{
Name: appName,
Namespace: namespace,
WaitFunc: argocd.GetAppSyncFn(revision),
},
},
})
}

type createAppSetOptions struct {
name string
namespace string
Expand Down
4 changes: 2 additions & 2 deletions cmd/commands/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -214,7 +214,7 @@ func RunProjectCreate(ctx context.Context, opts *ProjectCreateOptions) error {
}

log.G().Infof("pushing new project manifest to repo")
if err = r.Persist(ctx, &git.PushOptions{CommitMsg: fmt.Sprintf("Added project '%s'", opts.ProjectName)}); err != nil {
if _, err = r.Persist(ctx, &git.PushOptions{CommitMsg: fmt.Sprintf("Added project '%s'", opts.ProjectName)}); err != nil {
return err
}

Expand Down Expand Up @@ -441,7 +441,7 @@ func RunProjectDelete(ctx context.Context, opts *ProjectDeleteOptions) error {
}

log.G().Info("committing changes to gitops repo...")
if err = r.Persist(ctx, &git.PushOptions{CommitMsg: fmt.Sprintf("Deleted project '%s'", opts.ProjectName)}); err != nil {
if _, err = r.Persist(ctx, &git.PushOptions{CommitMsg: fmt.Sprintf("Deleted project '%s'", opts.ProjectName)}); err != nil {
return fmt.Errorf("failed to push to repo: %w", err)
}

Expand Down
140 changes: 137 additions & 3 deletions cmd/commands/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ type (
CloneOptions *git.CloneOptions
}

RepoUninstallOptions struct {
Namespace string
KubeContext string
Timeout time.Duration
KubeFactory kube.Factory
CloneOptions *git.CloneOptions
}

bootstrapManifests struct {
bootstrapApp []byte
rootApp []byte
Expand All @@ -79,6 +87,7 @@ func NewRepoCommand() *cobra.Command {
}

cmd.AddCommand(NewRepoBootstrapCommand())
cmd.AddCommand(NewRepoUninstallCommand())

return cmd
}
Expand Down Expand Up @@ -112,8 +121,8 @@ func NewRepoBootstrapCommand() *cobra.Command {

<BIN> repo bootstrap --repo https://github.com/example/repo

# Install argo-cd on the current kubernetes context in the argocd namespace
# and persists the bootstrap manifests to a specific folder in the gitops repository
# Install argo-cd on the current kubernetes context in the argocd namespace
# and persists the bootstrap manifests to a specific folder in the gitops repository

<BIN> repo bootstrap --repo https://github.com/example/repo/path/to/installation_root
`),
Expand Down Expand Up @@ -233,7 +242,7 @@ func RunRepoBootstrap(ctx context.Context, opts *RepoBootstrapOptions) error {
commitMsg = "Autopilot Bootstrap at " + opts.CloneOptions.Path()
}

if err = r.Persist(ctx, &git.PushOptions{CommitMsg: commitMsg}); err != nil {
if _, err = r.Persist(ctx, &git.PushOptions{CommitMsg: commitMsg}); err != nil {
return err
}

Expand Down Expand Up @@ -266,6 +275,96 @@ func RunRepoBootstrap(ctx context.Context, opts *RepoBootstrapOptions) error {
return nil
}

func NewRepoUninstallCommand() *cobra.Command {
var (
cloneOpts *git.CloneOptions
f kube.Factory
)

cmd := &cobra.Command{
Use: "uninstall",
Short: "Uninstalls an installation",
Example: util.Doc(`
# To run this command you need to create a personal access token for your git provider
# and provide it using:

export GIT_TOKEN=<token>

# or with the flag:

--git-token <token>

# Uninstall argo-cd from the current kubernetes context in the argocd namespace
# and delete all manifests rom the root of gitops repository

<BIN> repo uninstall --repo https://github.com/example/repo

# Uninstall argo-cd from the current kubernetes context in the argocd namespace
# and delete all manifests from a specific folder in the gitops repository

<BIN> repo uninstall --repo https://github.com/example/repo/path/to/installation_root
`),
PreRun: func(_ *cobra.Command, _ []string) { cloneOpts.Parse() },
RunE: func(cmd *cobra.Command, args []string) error {
return RunRepoUninstall(cmd.Context(), &RepoUninstallOptions{
Namespace: cmd.Flag("namespace").Value.String(),
KubeContext: cmd.Flag("context").Value.String(),
Timeout: util.MustParseDuration(cmd.Flag("request-timeout").Value.String()),
KubeFactory: f,
CloneOptions: cloneOpts,
})
},
}

cloneOpts = git.AddFlags(cmd, &git.AddFlagsOptions{
FS: memfs.New(),
})
f = kube.AddFlags(cmd.Flags())

return cmd
}

func RunRepoUninstall(ctx context.Context, opts *RepoUninstallOptions) error {
var err error

if opts, err = setUninstallOptsDefaults(*opts); err != nil {
return err
}

log.G().WithFields(log.Fields{
"repo-url": opts.CloneOptions.URL(),
"revision": opts.CloneOptions.Revision(),
"namespace": opts.Namespace,
"kube-context": opts.KubeContext,
}).Debug("starting with options: ")

log.G().Infof("cloning repo: %s", opts.CloneOptions.URL())

// clone GitOps repo
r, repofs, err := getRepo(ctx, opts.CloneOptions)
if err != nil {
return err
}

if err = clearBootstrapFolder(repofs); err != nil {
return err
}

revision, err := r.Persist(ctx, &git.PushOptions{CommitMsg: "Autopilot Uninstall"})
if err != nil {
return err
}

if err = waitAppSynced(ctx, opts.KubeFactory, opts.Timeout, store.Default.BootsrtrapAppName, opts.Namespace, revision); err != nil {
return err
}

// delete bootstrap app
// delete bootstrap|projects|apps folders + commit/push

return nil
}

func setBootstrapOptsDefaults(opts RepoBootstrapOptions) (*RepoBootstrapOptions, error) {
var err error

Expand Down Expand Up @@ -570,3 +669,38 @@ func createCreds(repoUrl string) ([]byte, error) {

return yaml.Marshal(creds)
}

func setUninstallOptsDefaults(opts RepoUninstallOptions) (*RepoUninstallOptions, error) {
var err error

if opts.Namespace == "" {
opts.Namespace = store.Default.ArgoCDNamespace
}

if opts.KubeContext == "" {
if opts.KubeContext, err = currentKubeContext(); err != nil {
return nil, err
}
}

return &opts, nil
}

func clearBootstrapFolder(repofs fs.FS) error {
files, err := repofs.ReadDir(store.Default.BootsrtrapDir)
if err != nil {
return err
}

for _, f := range files {
if f.IsDir() {
continue
}

if err = repofs.Remove(repofs.Join(store.Default.BootsrtrapDir, f.Name())); err != nil {
return err
}
}

return nil
}
1 change: 1 addition & 0 deletions docs/commands/argocd-autopilot_repo.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,5 @@ argocd-autopilot repo [flags]
* [argocd-autopilot](argocd-autopilot.md) - argocd-autopilot is used for installing and managing argo-cd installations and argo-cd
applications using gitops
* [argocd-autopilot repo bootstrap](argocd-autopilot_repo_bootstrap.md) - Bootstrap a new installation
* [argocd-autopilot repo uninstall](argocd-autopilot_repo_uninstall.md) - Uninstalls an installation

4 changes: 2 additions & 2 deletions docs/commands/argocd-autopilot_repo_bootstrap.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ argocd-autopilot repo bootstrap [flags]

argocd-autopilot repo bootstrap --repo https://github.com/example/repo

# Install argo-cd on the current kubernetes context in the argocd namespace
# and persists the bootstrap manifests to a specific folder in the gitops repository
# Install argo-cd on the current kubernetes context in the argocd namespace
# and persists the bootstrap manifests to a specific folder in the gitops repository

argocd-autopilot repo bootstrap --repo https://github.com/example/repo/path/to/installation_root

Expand Down
61 changes: 61 additions & 0 deletions docs/commands/argocd-autopilot_repo_uninstall.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
## argocd-autopilot repo uninstall

Uninstalls an installation

```
argocd-autopilot repo uninstall [flags]
```

### Examples
noam-codefresh marked this conversation as resolved.
Show resolved Hide resolved

```

# To run this command you need to create a personal access token for your git provider
# and provide it using:

export GIT_TOKEN=<token>

# or with the flag:

--git-token <token>

# Uninstall argo-cd from the current kubernetes context in the argocd namespace
# and delete all manifests rom the root of gitops repository

argocd-autopilot repo uninstall --repo https://github.com/example/repo

# Uninstall argo-cd from the current kubernetes context in the argocd namespace
# and delete all manifests from a specific folder in the gitops repository

argocd-autopilot repo uninstall --repo https://github.com/example/repo/path/to/installation_root

```

### Options

```
--as string Username to impersonate for the operation
--as-group stringArray Group to impersonate for the operation, this flag can be repeated to specify multiple groups.
--cache-dir string Default cache directory (default "/home/user/.kube/cache")
--certificate-authority string Path to a cert file for the certificate authority
--client-certificate string Path to a client certificate file for TLS
--client-key string Path to a client key file for TLS
--cluster string The name of the kubeconfig cluster to use
--context string The name of the kubeconfig context to use
-t, --git-token string Your git provider api token [GIT_TOKEN]
-h, --help help for uninstall
--insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
-n, --namespace string If present, the namespace scope for this CLI request
--repo string Repository URL [GIT_REPO]
--request-timeout string The length of time to wait before giving up on a single server request. Non-zero values should contain a corresponding time unit (e.g. 1s, 2m, 3h). A value of zero means don't timeout requests. (default "0")
-s, --server string The address and port of the Kubernetes API server
--tls-server-name string Server name to use for server certificate validation. If it is not provided, the hostname used to contact the server is used
--token string Bearer token for authentication to the API server
--user string The name of the kubeconfig user to use
```

### SEE ALSO

* [argocd-autopilot repo](argocd-autopilot_repo.md) - Manage gitops repositories

1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/argoproj-labs/applicationset v0.1.0
github.com/argoproj/argo-cd v1.8.7
github.com/argoproj/argo-cd/v2 v2.0.3
github.com/argoproj/gitops-engine v0.3.3
github.com/briandowns/spinner v1.13.0
github.com/ghodss/yaml v1.0.0
github.com/go-git/go-billy/v5 v5.3.1
Expand Down
3 changes: 2 additions & 1 deletion go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ github.com/argoproj/argo-cd/v2 v2.0.3 h1:9KK9u5wegvBhUQIrK+dfsGiJglPNlzFGoUFM/5i
github.com/argoproj/argo-cd/v2 v2.0.3/go.mod h1:eg4iTfTUICd6o6ZpbPElWGcHSHWOsgXIQM13+HzhIYE=
github.com/argoproj/gitops-engine v0.2.1/go.mod h1:OxXp8YaT73rw9gEBnGBWg55af80nkV/uIjWCbJu1Nw0=
github.com/argoproj/gitops-engine v0.2.2/go.mod h1:OxXp8YaT73rw9gEBnGBWg55af80nkV/uIjWCbJu1Nw0=
github.com/argoproj/gitops-engine v0.3.2 h1:m5bjOk/bWwMsFBGFpurdK31/hC5UuLMQn0hAd51TlEk=
github.com/argoproj/gitops-engine v0.3.2/go.mod h1:IBHhAkqlC+3r/wBWUitWSidQhPzlLoSTWp2htq3dyQk=
github.com/argoproj/gitops-engine v0.3.3 h1:zRNwKRj3h+EBpciy/+Eyo4vW2GTG3UG4HXAdWn0mQRI=
github.com/argoproj/gitops-engine v0.3.3/go.mod h1:IBHhAkqlC+3r/wBWUitWSidQhPzlLoSTWp2htq3dyQk=
github.com/argoproj/pkg v0.2.0 h1:ETgC600kr8WcAi3MEVY5sA1H7H/u1/IysYOobwsZ8No=
github.com/argoproj/pkg v0.2.0/go.mod h1:F4TZgInLUEjzsWFB/BTJBsewoEy0ucnKSq6vmQiD/yc=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
Expand Down
Loading