Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ func run(cfg *Config) error {
cfg.RenderMethod,
cfg.ArgocdAuthToken,
cfg.ArgocdConfigPath,
cfg.RepoServerAddress,
)

// Ensure cleanup is performed when we exit (e.g., stopping port forwards)
Expand Down
11 changes: 11 additions & 0 deletions cmd/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ var (
DefaultOutputBranchManifests = false
DefaultTraverseAppOfApps = false
DefaultFailOnDuplicateGeneratedApplications = false
DefaultRepoServerAddress = ""
)

// RawOptions holds the raw CLI/env inputs - used only for parsing
Expand Down Expand Up @@ -140,6 +141,7 @@ type RawOptions struct {
OutputBranchManifests bool `mapstructure:"output-branch-manifests"`
TraverseAppOfApps bool `mapstructure:"traverse-app-of-apps"`
FailOnDuplicateGeneratedApplications bool `mapstructure:"fail-on-duplicate-generated-applications"`
RepoServerAddress string `mapstructure:"repo-server-address"`
}

// Config is the final, validated, ready-to-use configuration
Expand Down Expand Up @@ -186,6 +188,7 @@ type Config struct {
OutputBranchManifests bool
TraverseAppOfApps bool
FailOnDuplicateGeneratedApplications bool
RepoServerAddress string

// Parsed/processed fields - no "parsed" prefix needed
FileRegex *regexp.Regexp
Expand Down Expand Up @@ -284,6 +287,7 @@ func Parse() *Config {
viper.SetDefault("output-branch-manifests", DefaultOutputBranchManifests)
viper.SetDefault("traverse-app-of-apps", DefaultTraverseAppOfApps)
viper.SetDefault("fail-on-duplicate-generated-applications", DefaultFailOnDuplicateGeneratedApplications)
viper.SetDefault("repo-server-address", DefaultRepoServerAddress)

// Basic flags
rootCmd.Flags().BoolP("debug", "d", false, "Activate debug mode")
Expand Down Expand Up @@ -345,6 +349,7 @@ func Parse() *Config {
rootCmd.Flags().Bool("output-branch-manifests", DefaultOutputBranchManifests, "Write all application manifests per branch to a single file (output/base-branch.yaml and output/target-branch.yaml)")
rootCmd.Flags().Bool("traverse-app-of-apps", DefaultTraverseAppOfApps, "Recursively render child Applications discovered in rendered manifests (app-of-apps pattern). Only supported with --render-method=repo-server-api")
rootCmd.Flags().Bool("fail-on-duplicate-generated-applications", DefaultFailOnDuplicateGeneratedApplications, "Fail when a single ApplicationSet generates multiple Applications with the same name")
rootCmd.Flags().String("repo-server-address", DefaultRepoServerAddress, "Address of the Argo CD repo server (host:port). Connects directly instead of port-forwarding. Requires --render-method=repo-server-api")

// Check if version flag was specified directly
for _, arg := range os.Args[1:] {
Expand Down Expand Up @@ -432,6 +437,7 @@ func (o *RawOptions) ToConfig() (*Config, error) {
OutputBranchManifests: o.OutputBranchManifests,
TraverseAppOfApps: o.TraverseAppOfApps,
FailOnDuplicateGeneratedApplications: o.FailOnDuplicateGeneratedApplications,
RepoServerAddress: o.RepoServerAddress,
}

var err error
Expand Down Expand Up @@ -502,6 +508,11 @@ func (o *RawOptions) ToConfig() (*Config, error) {
}
}

// --repo-server-address is only supported with repo-server-api render method
if cfg.RepoServerAddress != "" && cfg.RenderMethod != RenderMethodRepoServerAPI {
return nil, fmt.Errorf("--repo-server-address requires --render-method=repo-server-api (current: %s)", cfg.RenderMethod)
}

return cfg, nil
}

Expand Down
1 change: 1 addition & 0 deletions docs/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ argocd-diff-preview [FLAGS] [OPTIONS] (--repo <repo> | --repo-regex <regex>) --t
| `--redirect-target-revisions <revs>` | `REDIRECT_TARGET_REVISIONS` | - | Comma-separated source targetRevision values to redirect to the target branch. Example: main,HEAD. By default, every targetRevision in matching repositories is redirected |
| `--render-method <method>` | `RENDER_METHOD` | `server-api` | Manifest rendering method. Options: `cli`, `server-api`, `repo-server-api` |
| `--repo-regex <regex>` | `REPO_REGEX` | - | Advanced repository matcher for templated Argo CD repoURL values. Mutually exclusive with `--repo` |
| `--repo-server-address <address>` | `REPO_SERVER_ADDRESS` | - | Address of the Argo CD repo server (host:port). Connects directly instead of port-forwarding. Requires --render-method=repo-server-api" |
| `--secrets-folder <folder>`, `-s` | `SECRETS_FOLDER` | `./secrets` | Secrets folder where the secrets are read from |
| `--selector <selector>`, `-l` | `SELECTOR` | - | Label selector to filter on (e.g., `key1=value1,key2=value2`) |
| `--timeout <seconds>` | `TIMEOUT` | `180` | Set timeout in seconds |
Expand Down
4 changes: 3 additions & 1 deletion pkg/argocd/argocd.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,10 @@ type ArgoCDInstallation struct {
LoginOptions string
renderMode vars.RenderMethod
operations Operations // CLI or API implementation
RepoServerAddress string
}

func New(client *k8s.Client, namespace string, version string, repoName string, repoURL string, repoUsername string, repoPassword string, loginOptions string, renderMode vars.RenderMethod, authToken string, configPath string) *ArgoCDInstallation {
func New(client *k8s.Client, namespace string, version string, repoName string, repoURL string, repoUsername string, repoPassword string, loginOptions string, renderMode vars.RenderMethod, authToken string, configPath string, repoServerAddress string) *ArgoCDInstallation {
return &ArgoCDInstallation{
K8sClient: client,
Namespace: namespace,
Expand All @@ -73,6 +74,7 @@ func New(client *k8s.Client, namespace string, version string, repoName string,
LoginOptions: loginOptions,
renderMode: renderMode,
operations: NewOperations(renderMode, client, namespace, loginOptions, authToken),
RepoServerAddress: repoServerAddress,
}
}

Expand Down
14 changes: 9 additions & 5 deletions pkg/reposerverextract/appofapps.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,16 @@ func RenderApplicationsFromBothBranchesWithAppOfApps(

// Create a single repo server client shared across all goroutines.
// EnsurePortForward is idempotent and mutex-protected inside the client.
repoClient := reposerver.NewClient(argocd.K8sClient, argocd.Namespace)
defer repoClient.Cleanup()

if err := repoClient.EnsurePortForward(); err != nil {
return nil, nil, time.Since(startTime), fmt.Errorf("failed to set up port forward to repo server: %w", err)
var repoClient *reposerver.Client
if argocd.RepoServerAddress != "" {
repoClient = reposerver.NewClientWithAddress(argocd.RepoServerAddress, false, true)
} else {
repoClient = reposerver.NewClient(argocd.K8sClient, argocd.Namespace)
if err := repoClient.EnsurePortForward(); err != nil {
return nil, nil, time.Since(startTime), fmt.Errorf("failed to set up port forward to repo server: %w", err)
}
}
defer repoClient.Cleanup()

log.Info().Msgf("🤖 Rendering Applications via repo server with app-of-apps traversal (timeout in %d seconds)", timeout)

Expand Down
14 changes: 9 additions & 5 deletions pkg/reposerverextract/extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,12 +131,16 @@ func RenderApplicationsFromBothBranches(

// Create a single repo server client shared across all goroutines.
// EnsurePortForward is idempotent and mutex-protected inside the client.
repoClient := reposerver.NewClient(argocd.K8sClient, argocd.Namespace)
defer repoClient.Cleanup()

if err := repoClient.EnsurePortForward(); err != nil {
return nil, nil, time.Since(startTime), fmt.Errorf("failed to set up port forward to repo server: %w", err)
var repoClient *reposerver.Client
if argocd.RepoServerAddress != "" {
repoClient = reposerver.NewClientWithAddress(argocd.RepoServerAddress, false, true)
} else {
repoClient = reposerver.NewClient(argocd.K8sClient, argocd.Namespace)
if err := repoClient.EnsurePortForward(); err != nil {
return nil, nil, time.Since(startTime), fmt.Errorf("failed to set up port forward to repo server: %w", err)
}
}
defer repoClient.Cleanup()

allApps := append(baseApps, targetApps...)

Expand Down
Loading