diff --git a/cmd/commands/repo.go b/cmd/commands/repo.go index a286de2e..d7bc02eb 100644 --- a/cmd/commands/repo.go +++ b/cmd/commands/repo.go @@ -49,7 +49,7 @@ type ( AppSpecifier string InstallationMode string Namespace string - KubeContext string + KubeConfig string Namespaced bool DryRun bool HidePassword bool @@ -60,7 +60,6 @@ type ( RepoUninstallOptions struct { Namespace string - KubeContext string Timeout time.Duration CloneOptions *git.CloneOptions KubeFactory kube.Factory @@ -135,7 +134,7 @@ func NewRepoBootstrapCommand() *cobra.Command { AppSpecifier: appSpecifier, InstallationMode: installationMode, Namespace: cmd.Flag("namespace").Value.String(), - KubeContext: cmd.Flag("context").Value.String(), + KubeConfig: cmd.Flag("kubeconfig").Value.String(), Namespaced: namespaced, DryRun: dryRun, HidePassword: hidePassword, @@ -171,11 +170,16 @@ func RunRepoBootstrap(ctx context.Context, opts *RepoBootstrapOptions) error { return err } + kubeContext, err := currentKubeContext() + if err != nil { + return err + } + log.G(ctx).WithFields(log.Fields{ "repo-url": opts.CloneOptions.URL(), "revision": opts.CloneOptions.Revision(), "namespace": opts.Namespace, - "kube-context": opts.KubeContext, + "kube-context": kubeContext, }).Debug("starting with options: ") manifests, err := buildBootstrapManifests( @@ -217,7 +221,7 @@ func RunRepoBootstrap(ctx context.Context, opts *RepoBootstrapOptions) error { log.G(ctx).Debug("repository is ok") // apply built manifest to k8s cluster - log.G(ctx).Infof("using context: \"%s\", namespace: \"%s\"", opts.KubeContext, opts.Namespace) + log.G(ctx).Infof("using context: \"%s\", namespace: \"%s\"", kubeContext, opts.Namespace) log.G(ctx).Infof("applying bootstrap manifests to cluster...") if err = opts.KubeFactory.Apply(ctx, opts.Namespace, util.JoinManifests(manifests.namespace, manifests.applyManifests, manifests.repoCreds)); err != nil { return fmt.Errorf("failed to apply bootstrap manifests to cluster: %w", err) @@ -262,9 +266,10 @@ func RunRepoBootstrap(ctx context.Context, opts *RepoBootstrapOptions) error { log.G(ctx).Infof("running argocd login to initialize argocd config") err = argocdLogin(&argocd.LoginOptions{ - Namespace: opts.Namespace, - Username: "admin", - Password: passwd, + Namespace: opts.Namespace, + Username: "admin", + Password: passwd, + KubeConfig: opts.KubeConfig, }) if err != nil { return err @@ -313,7 +318,6 @@ func NewRepoUninstallCommand() *cobra.Command { return RunRepoUninstall(cmd.Context(), &RepoUninstallOptions{ Namespace: cmd.Flag("namespace").Value.String(), Timeout: util.MustParseDuration(cmd.Flag("request-timeout").Value.String()), - KubeContext: cmd.Flag("context").Value.String(), CloneOptions: cloneOpts, KubeFactory: f, }) @@ -331,7 +335,9 @@ func NewRepoUninstallCommand() *cobra.Command { func RunRepoUninstall(ctx context.Context, opts *RepoUninstallOptions) error { var err error - if opts, err = setUninstallOptsDefaults(*opts); err != nil { + opts = setUninstallOptsDefaults(*opts) + kubeContext, err := currentKubeContext() + if err != nil { return err } @@ -339,7 +345,7 @@ func RunRepoUninstall(ctx context.Context, opts *RepoUninstallOptions) error { "repo-url": opts.CloneOptions.URL(), "revision": opts.CloneOptions.Revision(), "namespace": opts.Namespace, - "kube-context": opts.KubeContext, + "kube-context": kubeContext, }).Debug("starting with options: ") log.G(ctx).Infof("cloning repo: %s", opts.CloneOptions.URL()) @@ -388,8 +394,6 @@ func RunRepoUninstall(ctx context.Context, opts *RepoUninstallOptions) error { } func setBootstrapOptsDefaults(opts RepoBootstrapOptions) (*RepoBootstrapOptions, error) { - var err error - switch opts.InstallationMode { case installationModeFlat, installationModeNormal: case "": @@ -411,12 +415,6 @@ func setBootstrapOptsDefaults(opts RepoBootstrapOptions) (*RepoBootstrapOptions, opts.InstallationMode = installationModeFlat } - if opts.KubeContext == "" { - if opts.KubeContext, err = currentKubeContext(); err != nil { - return nil, err - } - } - return &opts, nil } @@ -695,20 +693,12 @@ func createCreds(repoUrl string) ([]byte, error) { return yaml.Marshal(creds) } -func setUninstallOptsDefaults(opts RepoUninstallOptions) (*RepoUninstallOptions, error) { - var err error - +func setUninstallOptsDefaults(opts RepoUninstallOptions) *RepoUninstallOptions { if opts.Namespace == "" { opts.Namespace = store.Default.ArgoCDNamespace } - if opts.KubeContext == "" { - if opts.KubeContext, err = currentKubeContext(); err != nil { - return nil, err - } - } - - return &opts, nil + return &opts } func deleteGitOpsFiles(repofs fs.FS) error { diff --git a/cmd/commands/repo_test.go b/cmd/commands/repo_test.go index 4be2615b..fc5ac65c 100644 --- a/cmd/commands/repo_test.go +++ b/cmd/commands/repo_test.go @@ -47,24 +47,17 @@ func Test_setBootstrapOptsDefaults(t *testing.T) { opts: &RepoBootstrapOptions{ CloneOptions: &git.CloneOptions{}, }, - preFn: func() { - currentKubeContext = func() (string, error) { - return "fooctx", nil - } - }, assertFn: func(t *testing.T, opts *RepoBootstrapOptions, ret error) { assert.NoError(t, ret) assert.Equal(t, "argocd", opts.Namespace) assert.Equal(t, false, opts.Namespaced) assert.Equal(t, "manifests", opts.AppSpecifier) - assert.Equal(t, "fooctx", opts.KubeContext) }, }, "With App specifier": { opts: &RepoBootstrapOptions{ CloneOptions: &git.CloneOptions{}, AppSpecifier: "https://github.com/foo/bar", - KubeContext: "fooctx", }, assertFn: func(t *testing.T, opts *RepoBootstrapOptions, ret error) { assert.NoError(t, ret) @@ -72,14 +65,12 @@ func Test_setBootstrapOptsDefaults(t *testing.T) { assert.Equal(t, false, opts.Namespaced) assert.Equal(t, installationModeNormal, opts.InstallationMode) assert.Equal(t, "https://github.com/foo/bar", opts.AppSpecifier) - assert.Equal(t, "fooctx", opts.KubeContext) }, }, "Namespaced": { opts: &RepoBootstrapOptions{ CloneOptions: &git.CloneOptions{}, InstallationMode: installationModeFlat, - KubeContext: "fooctx", Namespaced: true, Namespace: "bar", }, @@ -89,7 +80,6 @@ func Test_setBootstrapOptsDefaults(t *testing.T) { assert.Equal(t, true, opts.Namespaced) assert.Equal(t, installationModeFlat, opts.InstallationMode) assert.Equal(t, "manifests/namespace-install", opts.AppSpecifier) - assert.Equal(t, "fooctx", opts.KubeContext) }, }, } @@ -248,7 +238,6 @@ func TestRunRepoBootstrap(t *testing.T) { opts: &RepoBootstrapOptions{ DryRun: true, InstallationMode: installationModeFlat, - KubeContext: "foo", Namespace: "bar", CloneOptions: &git.CloneOptions{ Repo: "https://github.com/foo/bar/installation1?ref=main", @@ -264,7 +253,6 @@ func TestRunRepoBootstrap(t *testing.T) { "Flat installation": { opts: &RepoBootstrapOptions{ InstallationMode: installationModeFlat, - KubeContext: "foo", Namespace: "bar", CloneOptions: &git.CloneOptions{ Repo: "https://github.com/foo/bar/installation1?ref=main", @@ -321,7 +309,6 @@ func TestRunRepoBootstrap(t *testing.T) { "Normal installation": { opts: &RepoBootstrapOptions{ InstallationMode: installationModeNormal, - KubeContext: "foo", Namespace: "bar", CloneOptions: &git.CloneOptions{ Repo: "https://github.com/foo/bar/installation1?ref=main", @@ -413,45 +400,20 @@ func Test_setUninstallOptsDefaults(t *testing.T) { tests := map[string]struct { opts RepoUninstallOptions want *RepoUninstallOptions - wantErr string currentKubeContext func() (string, error) }{ "Should not change anything, if all options are set": { opts: RepoUninstallOptions{ - Namespace: "namespace", - KubeContext: "context", + Namespace: "namespace", }, want: &RepoUninstallOptions{ - Namespace: "namespace", - KubeContext: "context", + Namespace: "namespace", }, }, "Should set default argocd namespace, if it is not set": { - opts: RepoUninstallOptions{ - KubeContext: "context", - }, + opts: RepoUninstallOptions{}, want: &RepoUninstallOptions{ - Namespace: store.Default.ArgoCDNamespace, - KubeContext: "context", - }, - }, - "Should get current kube context, if it is not set": { - opts: RepoUninstallOptions{ - Namespace: "namespace", - }, - want: &RepoUninstallOptions{ - Namespace: "namespace", - KubeContext: "currentContext", - }, - currentKubeContext: func() (string, error) { - return "currentContext", nil - }, - }, - "Should fail, if getting current context fails": { - opts: RepoUninstallOptions{}, - wantErr: "some error", - currentKubeContext: func() (string, error) { - return "", errors.New("some error") + Namespace: store.Default.ArgoCDNamespace, }, }, } @@ -463,17 +425,7 @@ func Test_setUninstallOptsDefaults(t *testing.T) { currentKubeContext = tt.currentKubeContext } - got, err := setUninstallOptsDefaults(tt.opts) - if err != nil { - if tt.wantErr != "" { - assert.EqualError(t, err, tt.wantErr) - } else { - t.Errorf("setUninstallOptsDefaults() error = %v", err) - } - - return - } - + got := setUninstallOptsDefaults(tt.opts) assert.Equal(t, tt.want, got) }) } diff --git a/docs/commands/argocd-autopilot_application_create.md b/docs/commands/argocd-autopilot_application_create.md index c105703f..6af59a75 100644 --- a/docs/commands/argocd-autopilot_application_create.md +++ b/docs/commands/argocd-autopilot_application_create.md @@ -48,32 +48,19 @@ argocd-autopilot application create [APP_NAME] [flags] ### Options ``` - --app string The application specifier (e.g. github.com/argoproj/argo-workflows/manifests/cluster-install/?ref=v3.0.3) - --apps-git-token string Your git provider api token [APPS_GIT_TOKEN] - --apps-repo string Repository URL [APPS_GIT_REPO] - --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 - --dest-namespace string K8s target namespace (overrides the namespace specified in the kustomization.yaml) - --dest-server string K8s cluster URL (e.g. https://kubernetes.default.svc) (default "https://kubernetes.default.svc") - -h, --help help for create - --insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure - --installation-mode string One of: normal|flat. If flat, will commit the application manifests (after running kustomize build), otherwise will commit the kustomization.yaml (default "normal") - --kubeconfig string Path to the kubeconfig file to use for CLI requests. - -n, --namespace string If present, the namespace scope for this CLI request - -p, --project string Project name - --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 - --type string The application type (kustomize|dir) - --user string The name of the kubeconfig user to use - --wait-timeout duration If not '0s', will try to connect to the cluster and wait until the application is in 'Synced' status for the specified timeout period + --app string The application specifier (e.g. github.com/argoproj/argo-workflows/manifests/cluster-install/?ref=v3.0.3) + --apps-git-token string Your git provider api token [APPS_GIT_TOKEN] + --apps-repo string Repository URL [APPS_GIT_REPO] + --dest-namespace string K8s target namespace (overrides the namespace specified in the kustomization.yaml) + --dest-server string K8s cluster URL (e.g. https://kubernetes.default.svc) (default "https://kubernetes.default.svc") + -h, --help help for create + --installation-mode string One of: normal|flat. If flat, will commit the application manifests (after running kustomize build), otherwise will commit the kustomization.yaml (default "normal") + --kubeconfig string Path to the kubeconfig file to use for CLI requests. + -n, --namespace string If present, the namespace scope for this CLI request + -p, --project string Project name + --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") + --type string The application type (kustomize|dir) + --wait-timeout duration If not '0s', will try to connect to the cluster and wait until the application is in 'Synced' status for the specified timeout period ``` ### Options inherited from parent commands diff --git a/docs/commands/argocd-autopilot_repo_bootstrap.md b/docs/commands/argocd-autopilot_repo_bootstrap.md index b8eed603..1a31c4e5 100644 --- a/docs/commands/argocd-autopilot_repo_bootstrap.md +++ b/docs/commands/argocd-autopilot_repo_bootstrap.md @@ -34,31 +34,18 @@ argocd-autopilot repo bootstrap [flags] ### Options ``` - --app string The application specifier (e.g. github.com/argoproj-labs/argocd-autopilot/manifests?ref=v0.2.5), overrides the default installation argo-cd manifests - --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 - --dry-run If true, print manifests instead of applying them to the cluster (nothing will be commited to git) - -t, --git-token string Your git provider api token [GIT_TOKEN] - -h, --help help for bootstrap - --hide-password If true, will not print initial argo cd password - --insecure-skip-tls-verify If true, the server's certificate will not be checked for validity. This will make your HTTPS connections insecure - --installation-mode string One of: normal|flat. If flat, will commit the bootstrap manifests, otherwise will commit the bootstrap kustomization.yaml (default "normal") - --kubeconfig string Path to the kubeconfig file to use for CLI requests. - -n, --namespace string If present, the namespace scope for this CLI request - --namespaced If true, install a namespaced version of argo-cd (no need for cluster-role) - --provider string The git provider, one of: github - --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 + --app string The application specifier (e.g. github.com/argoproj-labs/argocd-autopilot/manifests?ref=v0.2.5), overrides the default installation argo-cd manifests + --dry-run If true, print manifests instead of applying them to the cluster (nothing will be commited to git) + -t, --git-token string Your git provider api token [GIT_TOKEN] + -h, --help help for bootstrap + --hide-password If true, will not print initial argo cd password + --installation-mode string One of: normal|flat. If flat, will commit the bootstrap manifests, otherwise will commit the bootstrap kustomization.yaml (default "normal") + --kubeconfig string Path to the kubeconfig file to use for CLI requests. + -n, --namespace string If present, the namespace scope for this CLI request + --namespaced If true, install a namespaced version of argo-cd (no need for cluster-role) + --provider string The git provider, one of: github + --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") ``` ### SEE ALSO diff --git a/docs/commands/argocd-autopilot_repo_uninstall.md b/docs/commands/argocd-autopilot_repo_uninstall.md index 41d2b3f9..7db6abc8 100644 --- a/docs/commands/argocd-autopilot_repo_uninstall.md +++ b/docs/commands/argocd-autopilot_repo_uninstall.md @@ -34,25 +34,12 @@ argocd-autopilot repo uninstall [flags] ### 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 + -t, --git-token string Your git provider api token [GIT_TOKEN] + -h, --help help for uninstall + --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") ``` ### SEE ALSO diff --git a/pkg/argocd/argocd.go b/pkg/argocd/argocd.go index e082f88a..1b2bd373 100644 --- a/pkg/argocd/argocd.go +++ b/pkg/argocd/argocd.go @@ -2,6 +2,8 @@ package argocd import ( "context" + "fmt" + "os" "github.com/argoproj-labs/argocd-autopilot/pkg/kube" "github.com/argoproj-labs/argocd-autopilot/pkg/log" @@ -31,9 +33,10 @@ type ( } LoginOptions struct { - Namespace string - Username string - Password string + Namespace string + Username string + Password string + KubeConfig string } ) @@ -103,13 +106,20 @@ func Login(opts *LoginOptions) error { "--port-forward", "--port-forward-namespace", opts.Namespace, - "--password", - opts.Password, "--username", opts.Username, + "--password", + opts.Password, "--name", "autopilot", } + if opts.KubeConfig != "" { + origKubeConfig := os.Getenv("KUBECONFIG") + defer func() { os.Setenv("KUBECONFIG", origKubeConfig) }() + if err := os.Setenv("KUBECONFIG", opts.KubeConfig); err != nil { + return fmt.Errorf("failed to set KUBECONFIG env var: %w", err) + } + } root.SetArgs(args) return root.Execute() diff --git a/pkg/kube/kube.go b/pkg/kube/kube.go index cea80e03..3e2d4709 100644 --- a/pkg/kube/kube.go +++ b/pkg/kube/kube.go @@ -103,7 +103,14 @@ type ( ) func AddFlags(flags *pflag.FlagSet) Factory { - confFlags := genericclioptions.NewConfigFlags(true) + timeout := "0" + kubeConfig := "" + namespace := "" + confFlags := &genericclioptions.ConfigFlags{ + Timeout: &timeout, + KubeConfig: &kubeConfig, + Namespace: &namespace, + } confFlags.AddFlags(flags) mvFlags := cmdutil.NewMatchVersionFlags(confFlags)