github.com/argoproj/argo-cd/v3@v3.2.1/cmd/argocd/commands/admin/repo.go (about)

     1  package admin
     2  
     3  import (
     4  	stderrors "errors"
     5  	"os"
     6  
     7  	log "github.com/sirupsen/logrus"
     8  	"github.com/spf13/cobra"
     9  	corev1 "k8s.io/api/core/v1"
    10  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    11  	"k8s.io/client-go/kubernetes/fake"
    12  
    13  	cmdutil "github.com/argoproj/argo-cd/v3/cmd/util"
    14  	"github.com/argoproj/argo-cd/v3/common"
    15  	"github.com/argoproj/argo-cd/v3/util/cli"
    16  	"github.com/argoproj/argo-cd/v3/util/db"
    17  	"github.com/argoproj/argo-cd/v3/util/errors"
    18  	"github.com/argoproj/argo-cd/v3/util/git"
    19  	"github.com/argoproj/argo-cd/v3/util/settings"
    20  )
    21  
    22  const (
    23  	ArgoCDNamespace  = "argocd"
    24  	repoSecretPrefix = "repo"
    25  )
    26  
    27  func NewRepoCommand() *cobra.Command {
    28  	command := &cobra.Command{
    29  		Use:   "repo",
    30  		Short: "Manage repositories configuration",
    31  		Run: func(c *cobra.Command, args []string) {
    32  			c.HelpFunc()(c, args)
    33  		},
    34  	}
    35  	command.AddCommand(NewGenRepoSpecCommand())
    36  
    37  	return command
    38  }
    39  
    40  func NewGenRepoSpecCommand() *cobra.Command {
    41  	var (
    42  		repoOpts     cmdutil.RepoOptions
    43  		outputFormat string
    44  	)
    45  
    46  	// For better readability and easier formatting
    47  	repoAddExamples := `  
    48    # Add a Git repository via SSH using a private key for authentication, ignoring the server's host key:
    49    argocd admin repo generate-spec git@git.example.com:repos/repo --insecure-ignore-host-key --ssh-private-key-path ~/id_rsa
    50  
    51    # Add a Git repository via SSH on a non-default port - need to use ssh:// style URLs here
    52    argocd admin repo generate-spec ssh://git@git.example.com:2222/repos/repo --ssh-private-key-path ~/id_rsa
    53  
    54    # Add a private Git repository via HTTPS using username/password and TLS client certificates:
    55    argocd admin repo generate-spec https://git.example.com/repos/repo --username git --password secret --tls-client-cert-path ~/mycert.crt --tls-client-cert-key-path ~/mycert.key
    56  
    57    # Add a private Git BitBucket Data Center repository via HTTPS using bearer token:
    58    argocd admin repo generate-spec https://bitbucket.example.com/scm/proj/repo --bearer-token secret-token
    59  
    60    # Add a private Git repository via HTTPS using username/password without verifying the server's TLS certificate
    61    argocd admin repo generate-spec https://git.example.com/repos/repo --username git --password secret --insecure-skip-server-verification
    62  
    63    # Add a public Helm repository named 'stable' via HTTPS
    64    argocd admin repo generate-spec https://charts.helm.sh/stable --type helm --name stable  
    65  
    66    # Add a private Helm repository named 'stable' via HTTPS
    67    argocd admin repo generate-spec https://charts.helm.sh/stable --type helm --name stable --username test --password test
    68  
    69    # Add a private Helm OCI-based repository named 'stable' via HTTPS
    70    argocd admin repo generate-spec helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type helm --name stable --enable-oci --username test --password test
    71  
    72    # Add a private HTTPS OCI repository named 'stable'
    73    argocd admin repo generate-spec oci://helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type oci --name stable --username test --password test
    74    
    75    # Add a private OCI repository named 'stable' without verifying the server's TLS certificate
    76    argocd admin repo generate-spec oci://helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type oci --name stable --username test --password test --insecure-skip-server-verification
    77    
    78    # Add a private HTTP OCI repository named 'stable'
    79    argocd admin repo generate-spec oci://helm-oci-registry.cn-zhangjiakou.cr.aliyuncs.com --type oci --name stable --username test --password test --insecure-oci-force-http
    80  `
    81  
    82  	command := &cobra.Command{
    83  		Use:     "generate-spec REPOURL",
    84  		Short:   "Generate declarative config for a repo",
    85  		Example: repoAddExamples,
    86  		Run: func(c *cobra.Command, args []string) {
    87  			ctx := c.Context()
    88  
    89  			log.SetLevel(log.WarnLevel)
    90  			if len(args) != 1 {
    91  				c.HelpFunc()(c, args)
    92  				os.Exit(1)
    93  			}
    94  
    95  			// Repository URL
    96  			repoOpts.Repo.Repo = args[0]
    97  
    98  			// Specifying ssh-private-key-path is only valid for SSH repositories
    99  			if repoOpts.SshPrivateKeyPath != "" {
   100  				if ok, _ := git.IsSSHURL(repoOpts.Repo.Repo); ok {
   101  					keyData, err := os.ReadFile(repoOpts.SshPrivateKeyPath)
   102  					if err != nil {
   103  						log.Fatal(err)
   104  					}
   105  					repoOpts.Repo.SSHPrivateKey = string(keyData)
   106  				} else {
   107  					err := stderrors.New("--ssh-private-key-path is only supported for SSH repositories")
   108  					errors.CheckError(err)
   109  				}
   110  			}
   111  
   112  			// tls-client-cert-path and tls-client-cert-key-key-path must always be
   113  			// specified together
   114  			if (repoOpts.TlsClientCertPath != "" && repoOpts.TlsClientCertKeyPath == "") || (repoOpts.TlsClientCertPath == "" && repoOpts.TlsClientCertKeyPath != "") {
   115  				err := stderrors.New("--tls-client-cert-path and --tls-client-cert-key-path must be specified together")
   116  				errors.CheckError(err)
   117  			}
   118  
   119  			// Specifying tls-client-cert-path is only valid for HTTPS repositories
   120  			if repoOpts.TlsClientCertPath != "" {
   121  				if git.IsHTTPSURL(repoOpts.Repo.Repo) {
   122  					tlsCertData, err := os.ReadFile(repoOpts.TlsClientCertPath)
   123  					errors.CheckError(err)
   124  					tlsCertKey, err := os.ReadFile(repoOpts.TlsClientCertKeyPath)
   125  					errors.CheckError(err)
   126  					repoOpts.Repo.TLSClientCertData = string(tlsCertData)
   127  					repoOpts.Repo.TLSClientCertKey = string(tlsCertKey)
   128  				} else {
   129  					err := stderrors.New("--tls-client-cert-path is only supported for HTTPS repositories")
   130  					errors.CheckError(err)
   131  				}
   132  			}
   133  
   134  			// Set repository connection properties only when creating repository, not
   135  			// when creating repository credentials.
   136  			// InsecureIgnoreHostKey is deprecated and only here for backwards compat
   137  			repoOpts.Repo.InsecureIgnoreHostKey = repoOpts.InsecureIgnoreHostKey
   138  			repoOpts.Repo.Insecure = repoOpts.InsecureSkipServerVerification
   139  			repoOpts.Repo.EnableLFS = repoOpts.EnableLfs
   140  			repoOpts.Repo.EnableOCI = repoOpts.EnableOci
   141  			repoOpts.Repo.UseAzureWorkloadIdentity = repoOpts.UseAzureWorkloadIdentity
   142  			repoOpts.Repo.InsecureOCIForceHttp = repoOpts.InsecureOCIForceHTTP
   143  
   144  			if repoOpts.Repo.Type == "helm" && repoOpts.Repo.Name == "" {
   145  				errors.CheckError(stderrors.New("must specify --name for repos of type 'helm'"))
   146  			}
   147  
   148  			// If the user set a username, but didn't supply password via --password,
   149  			// then we prompt for it
   150  			if repoOpts.Repo.Username != "" && repoOpts.Repo.Password == "" {
   151  				repoOpts.Repo.Password = cli.PromptPassword(repoOpts.Repo.Password)
   152  			}
   153  
   154  			err := cmdutil.ValidateBearerTokenAndPasswordCombo(repoOpts.Repo.BearerToken, repoOpts.Repo.Password)
   155  			errors.CheckError(err)
   156  			err = cmdutil.ValidateBearerTokenForHTTPSRepoOnly(repoOpts.Repo.BearerToken, git.IsHTTPSURL(repoOpts.Repo.Repo))
   157  			errors.CheckError(err)
   158  			err = cmdutil.ValidateBearerTokenForGitOnly(repoOpts.Repo.BearerToken, repoOpts.Repo.Type)
   159  			errors.CheckError(err)
   160  
   161  			argoCDCM := &corev1.ConfigMap{
   162  				TypeMeta: metav1.TypeMeta{
   163  					Kind:       "ConfigMap",
   164  					APIVersion: "v1",
   165  				},
   166  				ObjectMeta: metav1.ObjectMeta{
   167  					Name:      common.ArgoCDConfigMapName,
   168  					Namespace: ArgoCDNamespace,
   169  					Labels: map[string]string{
   170  						"app.kubernetes.io/part-of": "argocd",
   171  					},
   172  				},
   173  			}
   174  			kubeClientset := fake.NewClientset(argoCDCM)
   175  			settingsMgr := settings.NewSettingsManager(ctx, kubeClientset, ArgoCDNamespace)
   176  			argoDB := db.NewDB(ArgoCDNamespace, settingsMgr, kubeClientset)
   177  
   178  			_, err = argoDB.CreateRepository(ctx, &repoOpts.Repo)
   179  			errors.CheckError(err)
   180  
   181  			secret, err := kubeClientset.CoreV1().Secrets(ArgoCDNamespace).Get(ctx, db.RepoURLToSecretName(repoSecretPrefix, repoOpts.Repo.Repo, repoOpts.Repo.Project), metav1.GetOptions{})
   182  			errors.CheckError(err)
   183  
   184  			errors.CheckError(PrintResources(outputFormat, os.Stdout, secret))
   185  		},
   186  	}
   187  	command.Flags().StringVarP(&outputFormat, "output", "o", "yaml", "Output format. One of: json|yaml")
   188  	cmdutil.AddRepoFlags(command, &repoOpts)
   189  	return command
   190  }