test(e2e): configurable tmp dir locally (#25780) (#26339)

Signed-off-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Signed-off-by: dependabot[bot] <support@github.com>
Signed-off-by: reggie-k <regina.voloshin@codefresh.io>
Signed-off-by: shubham singh mahar <shubhammahar1306@gmail.com>
Signed-off-by: CI <ci@argoproj.com>
Signed-off-by: Josh Soref <jsoref@gmail.com>
Signed-off-by: renovate[bot] <renovate[bot]@users.noreply.github.com>
Signed-off-by: Jakub Rudnik <jakub@rudnik.io>
Signed-off-by: ioleksiuk <ioleksiuk@users.noreply.github.com>
Signed-off-by: Illia Oleksiuk <ilya.oleksiuk@gmail.com>
Signed-off-by: Aya <ayia.hosni@gmail.com>
Co-authored-by: Alexandre Gaudreault <alexandre_gaudreault@intuit.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Pasha Kostohrys <pasha.kostohrys@gmail.com>
Co-authored-by: pasha <pasha.k@fyxt.com>
Co-authored-by: Regina Voloshin <regina.voloshin@codefresh.io>
Co-authored-by: Shubham Singh <shubhammahar1306@gmail.com>
Co-authored-by: shubham singh mahar <smahar@obmondo.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: CI <ci@argoproj.com>
Co-authored-by: Josh Soref <2119212+jsoref@users.noreply.github.com>
Co-authored-by: argoproj-renovate[bot] <161757507+argoproj-renovate[bot]@users.noreply.github.com>
Co-authored-by: Jakub Rudnik <jakub@rudnik.io>
Co-authored-by: Illia Oleksiuk <42911468+ioleksiuk@users.noreply.github.com>
Co-authored-by: Aya Hosni <ayia.hosni@gmail.com>
Co-authored-by: Nitish Kumar <justnitish06@gmail.com>
This commit is contained in:
Kanika Rana
2026-02-11 05:05:24 -05:00
committed by GitHub
parent 0038fce14d
commit c4f0cd3e84
17 changed files with 221 additions and 123 deletions

View File

@@ -194,7 +194,7 @@ jobs:
- name: Checkout code
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
- name: Create symlink in GOPATH
run: ln -s $(pwd) ~/go/src/github.com/argoproj/argo-cd
run: ln -s $(pwd) ~/go/src/github.com/argoproj/argo-cd
- name: Setup Golang
uses: actions/setup-go@4dc6199c7b1a012772edbd06daecab0f50c9053c # v6.1.0
with:
@@ -271,13 +271,13 @@ jobs:
# We need to vendor go modules for codegen yet
go mod download
go mod vendor -v
# generalizing repo name for forks: ${{ github.event.repository.name }}
working-directory: /home/runner/go/src/github.com/argoproj/${{ github.event.repository.name }}
# generalizing repo name for forks: ${{ github.event.repository.name }}
working-directory: /home/runner/go/src/github.com/argoproj/${{ github.event.repository.name }}
- name: Install toolchain for codegen
run: |
make install-codegen-tools-local
make install-go-tools-local
# generalizing repo name for forks: ${{ github.event.repository.name }}
# generalizing repo name for forks: ${{ github.event.repository.name }}
working-directory: /home/runner/go/src/github.com/argoproj/${{ github.event.repository.name }}
# We install kustomize in the dist directory
- name: Add dist to PATH
@@ -431,9 +431,6 @@ jobs:
- changes
env:
ARGOCD_FAKE_IN_CLUSTER: 'true'
ARGOCD_SSH_DATA_PATH: '/tmp/argo-e2e/app/config/ssh'
ARGOCD_TLS_DATA_PATH: '/tmp/argo-e2e/app/config/tls'
ARGOCD_E2E_SSH_KNOWN_HOSTS: '../fixture/certs/ssh_known_hosts'
ARGOCD_E2E_K3S: 'true'
ARGOCD_IN_CI: 'true'
ARGOCD_E2E_APISERVER_PORT: '8088'

View File

@@ -76,8 +76,10 @@ ARGOCD_E2E_REDIS_PORT?=6379
ARGOCD_E2E_DEX_PORT?=5556
ARGOCD_E2E_YARN_HOST?=localhost
ARGOCD_E2E_DISABLE_AUTH?=
ARGOCD_E2E_DIR?=/tmp/argo-e2e
ARGOCD_E2E_TEST_TIMEOUT?=90m
ARGOCD_E2E_RERUN_FAILS?=5
ARGOCD_IN_CI?=false
ARGOCD_TEST_E2E?=true
@@ -461,7 +463,7 @@ test-e2e:
test-e2e-local: cli-local
# NO_PROXY ensures all tests don't go out through a proxy if one is configured on the test system
export GO111MODULE=off
DIST_DIR=${DIST_DIR} RERUN_FAILS=5 PACKAGES="./test/e2e" ARGOCD_E2E_RECORD=${ARGOCD_E2E_RECORD} ARGOCD_CONFIG_DIR=$(HOME)/.config/argocd-e2e ARGOCD_GPG_ENABLED=true NO_PROXY=* ./hack/test.sh -timeout $(ARGOCD_E2E_TEST_TIMEOUT) -v -args -test.gocoverdir="$(PWD)/test-results"
DIST_DIR=${DIST_DIR} RERUN_FAILS=$(ARGOCD_E2E_RERUN_FAILS) PACKAGES="./test/e2e" ARGOCD_E2E_RECORD=${ARGOCD_E2E_RECORD} ARGOCD_CONFIG_DIR=$(HOME)/.config/argocd-e2e ARGOCD_GPG_ENABLED=true NO_PROXY=* ./hack/test.sh -timeout $(ARGOCD_E2E_TEST_TIMEOUT) -v -args -test.gocoverdir="$(PWD)/test-results"
# Spawns a shell in the test server container for debugging purposes
debug-test-server: test-tools-image
@@ -485,13 +487,13 @@ start-e2e-local: mod-vendor-local dep-ui-local cli-local
kubectl create ns argocd-e2e-external || true
kubectl create ns argocd-e2e-external-2 || true
kubectl config set-context --current --namespace=argocd-e2e
kustomize build test/manifests/base | kubectl apply --server-side -f -
kustomize build test/manifests/base | kubectl apply --server-side --force-conflicts -f -
kubectl apply -f https://raw.githubusercontent.com/open-cluster-management/api/a6845f2ebcb186ec26b832f60c988537a58f3859/cluster/v1alpha1/0000_04_clusters.open-cluster-management.io_placementdecisions.crd.yaml
# Create GPG keys and source directories
if test -d /tmp/argo-e2e/app/config/gpg; then rm -rf /tmp/argo-e2e/app/config/gpg/*; fi
mkdir -p /tmp/argo-e2e/app/config/gpg/keys && chmod 0700 /tmp/argo-e2e/app/config/gpg/keys
mkdir -p /tmp/argo-e2e/app/config/gpg/source && chmod 0700 /tmp/argo-e2e/app/config/gpg/source
mkdir -p /tmp/argo-e2e/app/config/plugin && chmod 0700 /tmp/argo-e2e/app/config/plugin
if test -d $(ARGOCD_E2E_DIR)/app/config/gpg; then rm -rf $(ARGOCD_E2E_DIR)/app/config/gpg/*; fi
mkdir -p $(ARGOCD_E2E_DIR)/app/config/gpg/keys && chmod 0700 $(ARGOCD_E2E_DIR)/app/config/gpg/keys
mkdir -p $(ARGOCD_E2E_DIR)/app/config/gpg/source && chmod 0700 $(ARGOCD_E2E_DIR)/app/config/gpg/source
mkdir -p $(ARGOCD_E2E_DIR)/app/config/plugin && chmod 0700 $(ARGOCD_E2E_DIR)/app/config/plugin
# create folders to hold go coverage results for each component
mkdir -p /tmp/coverage/app-controller
mkdir -p /tmp/coverage/api-server
@@ -500,13 +502,14 @@ start-e2e-local: mod-vendor-local dep-ui-local cli-local
mkdir -p /tmp/coverage/notification
mkdir -p /tmp/coverage/commit-server
# set paths for locally managed ssh known hosts and tls certs data
ARGOCD_SSH_DATA_PATH=/tmp/argo-e2e/app/config/ssh \
ARGOCD_TLS_DATA_PATH=/tmp/argo-e2e/app/config/tls \
ARGOCD_GPG_DATA_PATH=/tmp/argo-e2e/app/config/gpg/source \
ARGOCD_GNUPGHOME=/tmp/argo-e2e/app/config/gpg/keys \
ARGOCD_E2E_DIR=$(ARGOCD_E2E_DIR) \
ARGOCD_SSH_DATA_PATH=$(ARGOCD_E2E_DIR)/app/config/ssh \
ARGOCD_TLS_DATA_PATH=$(ARGOCD_E2E_DIR)/app/config/tls \
ARGOCD_GPG_DATA_PATH=$(ARGOCD_E2E_DIR)/app/config/gpg/source \
ARGOCD_GNUPGHOME=$(ARGOCD_E2E_DIR)/app/config/gpg/keys \
ARGOCD_GPG_ENABLED=$(ARGOCD_GPG_ENABLED) \
ARGOCD_PLUGINCONFIGFILEPATH=/tmp/argo-e2e/app/config/plugin \
ARGOCD_PLUGINSOCKFILEPATH=/tmp/argo-e2e/app/config/plugin \
ARGOCD_PLUGINCONFIGFILEPATH=$(ARGOCD_E2E_DIR)/app/config/plugin \
ARGOCD_PLUGINSOCKFILEPATH=$(ARGOCD_E2E_DIR)/app/config/plugin \
ARGOCD_GIT_CONFIG=$(PWD)/test/e2e/fixture/gitconfig \
ARGOCD_E2E_DISABLE_AUTH=false \
ARGOCD_ZJWT_FEATURE_FLAG=always \

View File

@@ -3,29 +3,33 @@
The test [directory](https://github.com/argoproj/argo-cd/tree/master/test) contains E2E tests and test applications. The tests assume that Argo CD services are installed into `argocd-e2e` namespace or cluster in current context. A throw-away
namespace `argocd-e2e***` is created prior to the execution of the tests. The throw-away namespace is used as a target namespace for test applications.
The [/test/e2e/testdata](https://github.com/argoproj/argo-cd/tree/master/test/e2e/testdata) directory contains various Argo CD applications. Before test execution, the directory is copied into `/tmp/argo-e2e***` temp directory and used in tests as a
The [/test/e2e/testdata](https://github.com/argoproj/argo-cd/tree/master/test/e2e/testdata) directory contains various Argo CD applications. Before test execution, the directory is copied into `/tmp/argo-e2e***` temp directory (configurable by `ARGOCD_E2E_DIR`) and used in tests as a
Git repository via file url: `file:///tmp/argo-e2e***`.
> [!NOTE]
> You might get an error such as `unable to ls-remote HEAD on repository: failed to list refs: repository not found` when querying the local repository exposed through the e2e server running in a container.
> This is often caused by `/tmp` directoring sharing protection. You can configure a different directory with `ARGOCD_E2E_DIR`, or disable the directory sharing protection.
>
> **Rancher Desktop Volume Sharing**
>
> The e2e git server runs in a container. If you are using Rancher Desktop, you will need to enable volume sharing for
> the e2e container to access the testdata directory. To do this, add the following to
> To do enable `/tmp` sharing, add the following to
> `~/Library/Application\ Support/rancher-desktop/lima/_config/override.yaml` and restart Rancher Desktop:
>
> ```yaml
> mounts:
> - location: /private/tmp
> writable: true
> - location: /private/tmp
> writable: true
> ```
## Running Tests Locally
### With virtualized chain
1. Start the e2e version `make start-e2e`
2. Run the tests: `make test-e2e`
### With local chain
1. Start the e2e version `make start-e2e-local`
2. Run the tests: `make test-e2e-local`
@@ -37,32 +41,32 @@ You can observe the tests by using the UI [http://localhost:4000/applications](h
The Makefile's `start-e2e` target starts instances of ArgoCD on your local machine, of which the most will require a network listener. If, for any reason, your machine already has network services listening on the same ports, then the e2e tests will not run. You can derive from the defaults by setting the following environment variables before you run `make start-e2e`:
* `ARGOCD_E2E_APISERVER_PORT`: Listener port for `argocd-server` (default: `8080`)
* `ARGOCD_E2E_REPOSERVER_PORT`: Listener port for `argocd-reposerver` (default: `8081`)
* `ARGOCD_E2E_DEX_PORT`: Listener port for `dex` (default: `5556`)
* `ARGOCD_E2E_REDIS_PORT`: Listener port for `redis` (default: `6379`)
* `ARGOCD_E2E_YARN_CMD`: Command to use for starting the UI via Yarn (default: `yarn`)
- `ARGOCD_E2E_APISERVER_PORT`: Listener port for `argocd-server` (default: `8080`)
- `ARGOCD_E2E_REPOSERVER_PORT`: Listener port for `argocd-reposerver` (default: `8081`)
- `ARGOCD_E2E_DEX_PORT`: Listener port for `dex` (default: `5556`)
- `ARGOCD_E2E_REDIS_PORT`: Listener port for `redis` (default: `6379`)
- `ARGOCD_E2E_YARN_CMD`: Command to use for starting the UI via Yarn (default: `yarn`)
- `ARGOCD_E2E_DIR`: Local path to the repository to use for ephemeral test data
If you have changed the port for `argocd-server`, be sure to also set `ARGOCD_SERVER` environment variable to point to that port, e.g. `export ARGOCD_SERVER=localhost:8888` before running `make test-e2e` so that the test will communicate to the correct server component.
## Test Isolation
Some effort has been made to balance test isolation with speed. Tests are isolated as follows as each test gets:
* A random 5 character ID.
* A unique Git repository containing the `testdata` in `/tmp/argo-e2e/${id}`.
* A namespace `argocd-e2e-ns-${id}`.
* A primary name for the app `argocd-e2e-${id}`.
- A random 5 character ID.
- A unique Git repository containing the `testdata` in `/tmp/argo-e2e/${id}`.
- A namespace `argocd-e2e-ns-${id}`.
- A primary name for the app `argocd-e2e-${id}`.
## Run only a subset of tests
Running all tests locally is a time-consuming process. To run only a subset of tests, you can set the `TEST_MODULE` environment variable.
For example, to run only the OCI tests, you can set the variable as follows: `make TEST_MODULE=./test/e2e/oci_test.go test-e2e-local`
Running all tests locally is a time-consuming process. To run only a subset of tests, you can set the `TEST_MODULE` environment variable.
For example, to run only the OCI tests, you can set the variable as follows: `make TEST_MODULE=./test/e2e/oci_test.go test-e2e-local`
If you want to get a more fine-grained control over which tests to run, you can also try `make TEST_FLAGS="-run <TEST_METHOD_NAME_REGEXP>" test-e2e-local`
For individual tests you can run them using the IDE run test feature
For individual tests you can run them using the IDE run test feature
## Troubleshooting
**Tests fails to delete `argocd-e2e-ns-*` namespaces.**

View File

@@ -26,7 +26,7 @@ func (c *Context) RunningCMPServer(configFile string) *Context {
// It blocks until the socket file is created or times out after 10 seconds.
func startCMPServer(t *testing.T, configDir string) {
t.Helper()
pluginSockFilePath := path.Join(fixture.TmpDir, fixture.PluginSockFilePath)
pluginSockFilePath := path.Join(fixture.TmpDir(), fixture.PluginSockFilePath)
t.Setenv("ARGOCD_BINARY_NAME", "argocd-cmp-server")
// ARGOCD_PLUGINSOCKFILEPATH should be set as the same value as repo server env var
t.Setenv("ARGOCD_PLUGINSOCKFILEPATH", pluginSockFilePath)

View File

@@ -23,6 +23,10 @@ type Context struct {
func Given(t *testing.T) *Context {
t.Helper()
fixture.EnsureCleanState(t)
// TODO: Appset EnsureCleanState specific logic should be moved to the main EnsureCleanState function (https://github.com/argoproj/argo-cd/issues/24307)
utils.EnsureCleanState(t)
return &Context{t: t}
}

View File

@@ -1,25 +0,0 @@
package utils
import (
"context"
"os"
"os/exec"
"strings"
argoexec "github.com/argoproj/argo-cd/v3/util/exec"
)
func Run(workDir, name string, args ...string) (string, error) {
return RunWithStdin("", workDir, name, args...)
}
func RunWithStdin(stdin, workDir, name string, args ...string) (string, error) {
cmd := exec.CommandContext(context.Background(), name, args...)
if stdin != "" {
cmd.Stdin = strings.NewReader(stdin)
}
cmd.Env = os.Environ()
cmd.Dir = workDir
return argoexec.RunCommandExt(cmd, argoexec.CmdOpts{})
}

View File

@@ -28,7 +28,6 @@ import (
"github.com/argoproj/argo-cd/v3/pkg/apis/application/v1alpha1"
appclientset "github.com/argoproj/argo-cd/v3/pkg/client/clientset/versioned"
"github.com/argoproj/argo-cd/v3/test/e2e/fixture"
"github.com/argoproj/argo-cd/v3/util/errors"
)
type ExternalNamespace string
@@ -49,7 +48,6 @@ const (
// Note: this is NOT the namespace the ApplicationSet controller is deployed to; see ArgoCDNamespace.
ApplicationsResourcesNamespace = "applicationset-e2e"
TmpDir = "/tmp/applicationset-e2e"
TestingLabel = "e2e.argoproj.io"
)
@@ -209,12 +207,6 @@ func EnsureCleanState(t *testing.T) {
require.NoError(t, waitForExpectedClusterState(t))
// remove tmp dir
require.NoError(t, os.RemoveAll(TmpDir))
// create tmp dir
errors.NewHandler(t).FailOnErr(Run("", "mkdir", "-p", TmpDir))
// We can switch user and as result in previous state we will have non-admin user, this case should be reset
require.NoError(t, fixture.LoginAs("admin"))

View File

@@ -29,9 +29,9 @@ func AddCustomCACert(t *testing.T) {
errors.NewHandler(t).FailOnErr(fixture.RunCli(args...))
certData, err := os.ReadFile(caCertPath)
require.NoError(t, err)
err = os.WriteFile(fixture.TmpDir+"/app/config/tls/localhost", certData, 0o644)
err = os.WriteFile(fixture.TmpDir()+"/app/config/tls/localhost", certData, 0o644)
require.NoError(t, err)
err = os.WriteFile(fixture.TmpDir+"/app/config/tls/127.0.0.1", certData, 0o644)
err = os.WriteFile(fixture.TmpDir()+"/app/config/tls/127.0.0.1", certData, 0o644)
require.NoError(t, err)
} else {
args := []string{"cert", "add-tls", "argocd-e2e-server", "--upsert", "--from", caCertPath}
@@ -58,7 +58,7 @@ func AddCustomSSHKnownHostsKeys(t *testing.T) {
if fixture.IsLocal() {
knownHostsData, err := os.ReadFile(knownHostsPath)
require.NoError(t, err)
err = os.WriteFile(fixture.TmpDir+"/app/config/ssh/ssh_known_hosts", knownHostsData, 0o644)
err = os.WriteFile(fixture.TmpDir()+"/app/config/ssh/ssh_known_hosts", knownHostsData, 0o644)
require.NoError(t, err)
} else {
fixture.RestartAPIServer(t)

View File

@@ -53,7 +53,8 @@ const (
defaultNotificationServer = "localhost:9001"
// ensure all repos are in one directory tree, so we can easily clean them up
TmpDir = "/tmp/argo-e2e"
// TmpDir can be overridden via ARGOCD_E2E_DIR environment variable
defaultTmpDir = "/tmp/argo-e2e"
repoDir = "testdata.git"
submoduleDir = "submodule.git"
submoduleParentDir = "submoduleParent.git"
@@ -149,6 +150,12 @@ func AppNamespace() string {
return GetEnvWithDefault("ARGOCD_E2E_APP_NAMESPACE", ArgoCDAppNamespace)
}
// TmpDir returns the base directory for e2e test data.
// It can be overridden via the ARGOCD_E2E_DIR environment variable.
func TmpDir() string {
return GetEnvWithDefault("ARGOCD_E2E_DIR", defaultTmpDir)
}
// getKubeConfig creates new kubernetes client config using specified config path and config overrides variables
func getKubeConfig(configPath string, overrides clientcmd.ConfigOverrides) *rest.Config {
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
@@ -300,15 +307,15 @@ func ShortId() string {
}
func repoDirectory() string {
return path.Join(TmpDir, repoDir)
return path.Join(TmpDir(), repoDir)
}
func submoduleDirectory() string {
return path.Join(TmpDir, submoduleDir)
return path.Join(TmpDir(), submoduleDir)
}
func submoduleParentDirectory() string {
return path.Join(TmpDir, submoduleParentDir)
return path.Join(TmpDir(), submoduleParentDir)
}
const (
@@ -325,16 +332,18 @@ const (
)
func RepoURL(urlType RepoURLType) string {
// SSH URLs use the container path (defaultTmpDir) because sshd runs inside Docker
// where $ARGOCD_E2E_DIR is mounted to /tmp/argo-e2e
switch urlType {
// Git server via SSH
case RepoURLTypeSSH:
return GetEnvWithDefault(EnvRepoURLTypeSSH, "ssh://root@localhost:2222/tmp/argo-e2e/testdata.git")
return GetEnvWithDefault(EnvRepoURLTypeSSH, "ssh://root@localhost:2222"+defaultTmpDir+"/testdata.git")
// Git submodule repo
case RepoURLTypeSSHSubmodule:
return GetEnvWithDefault(EnvRepoURLTypeSSHSubmodule, "ssh://root@localhost:2222/tmp/argo-e2e/submodule.git")
return GetEnvWithDefault(EnvRepoURLTypeSSHSubmodule, "ssh://root@localhost:2222"+defaultTmpDir+"/submodule.git")
// Git submodule parent repo
case RepoURLTypeSSHSubmoduleParent:
return GetEnvWithDefault(EnvRepoURLTypeSSHSubmoduleParent, "ssh://root@localhost:2222/tmp/argo-e2e/submoduleParent.git")
return GetEnvWithDefault(EnvRepoURLTypeSSHSubmoduleParent, "ssh://root@localhost:2222"+defaultTmpDir+"/submoduleParent.git")
// Git server via HTTPS
case RepoURLTypeHTTPS:
return GetEnvWithDefault(EnvRepoURLTypeHTTPS, "https://localhost:9443/argo-e2e/testdata.git")
@@ -898,38 +907,39 @@ func EnsureCleanState(t *testing.T, opts ...TestOption) {
return err
},
func() error {
err := os.RemoveAll(TmpDir)
tmpDir := TmpDir()
err := os.RemoveAll(tmpDir)
if err != nil {
return err
}
_, err = Run("", "mkdir", "-p", TmpDir)
_, err = Run("", "mkdir", "-p", tmpDir)
if err != nil {
return err
}
// create TLS and SSH certificate directories
if IsLocal() {
_, err = Run("", "mkdir", "-p", TmpDir+"/app/config/tls")
_, err = Run("", "mkdir", "-p", tmpDir+"/app/config/tls")
if err != nil {
return err
}
_, err = Run("", "mkdir", "-p", TmpDir+"/app/config/ssh")
_, err = Run("", "mkdir", "-p", tmpDir+"/app/config/ssh")
if err != nil {
return err
}
}
// For signing during the tests
_, err = Run("", "mkdir", "-p", TmpDir+"/gpg")
_, err = Run("", "mkdir", "-p", tmpDir+"/gpg")
if err != nil {
return err
}
_, err = Run("", "chmod", "0700", TmpDir+"/gpg")
_, err = Run("", "chmod", "0700", tmpDir+"/gpg")
if err != nil {
return err
}
prevGnuPGHome := os.Getenv("GNUPGHOME")
t.Setenv("GNUPGHOME", TmpDir+"/gpg")
t.Setenv("GNUPGHOME", tmpDir+"/gpg")
//nolint:errcheck
Run("", "pkill", "-9", "gpg-agent")
_, err = Run("", "gpg", "--import", "../fixture/gpg/signingkey.asc")
@@ -940,23 +950,23 @@ func EnsureCleanState(t *testing.T, opts ...TestOption) {
// recreate GPG directories
if IsLocal() {
_, err = Run("", "mkdir", "-p", TmpDir+"/app/config/gpg/source")
_, err = Run("", "mkdir", "-p", tmpDir+"/app/config/gpg/source")
if err != nil {
return err
}
_, err = Run("", "mkdir", "-p", TmpDir+"/app/config/gpg/keys")
_, err = Run("", "mkdir", "-p", tmpDir+"/app/config/gpg/keys")
if err != nil {
return err
}
_, err = Run("", "chmod", "0700", TmpDir+"/app/config/gpg/keys")
_, err = Run("", "chmod", "0700", tmpDir+"/app/config/gpg/keys")
if err != nil {
return err
}
_, err = Run("", "mkdir", "-p", TmpDir+PluginSockFilePath)
_, err = Run("", "mkdir", "-p", tmpDir+PluginSockFilePath)
if err != nil {
return err
}
_, err = Run("", "chmod", "0700", TmpDir+PluginSockFilePath)
_, err = Run("", "chmod", "0700", tmpDir+PluginSockFilePath)
if err != nil {
return err
}
@@ -1158,7 +1168,7 @@ func AddSignedFile(t *testing.T, path, contents string) {
WriteFile(t, path, contents)
prevGnuPGHome := os.Getenv("GNUPGHOME")
t.Setenv("GNUPGHOME", TmpDir+"/gpg")
t.Setenv("GNUPGHOME", TmpDir()+"/gpg")
errors.NewHandler(t).FailOnErr(Run(repoDirectory(), "git", "diff"))
errors.NewHandler(t).FailOnErr(Run(repoDirectory(), "git", "add", "."))
errors.NewHandler(t).FailOnErr(Run(repoDirectory(), "git", "-c", "user.signingkey="+GpgGoodKeyID, "commit", "-S", "-am", "add file"))
@@ -1171,7 +1181,7 @@ func AddSignedFile(t *testing.T, path, contents string) {
func AddSignedTag(t *testing.T, name string) {
t.Helper()
prevGnuPGHome := os.Getenv("GNUPGHOME")
t.Setenv("GNUPGHOME", TmpDir+"/gpg")
t.Setenv("GNUPGHOME", TmpDir()+"/gpg")
defer t.Setenv("GNUPGHOME", prevGnuPGHome)
errors.NewHandler(t).FailOnErr(Run(repoDirectory(), "git", "-c", "user.signingkey="+GpgGoodKeyID, "tag", "-sm", "add signed tag", name))
if IsRemote() {
@@ -1182,7 +1192,7 @@ func AddSignedTag(t *testing.T, name string) {
func AddTag(t *testing.T, name string) {
t.Helper()
prevGnuPGHome := os.Getenv("GNUPGHOME")
t.Setenv("GNUPGHOME", TmpDir+"/gpg")
t.Setenv("GNUPGHOME", TmpDir()+"/gpg")
defer t.Setenv("GNUPGHOME", prevGnuPGHome)
errors.NewHandler(t).FailOnErr(Run(repoDirectory(), "git", "tag", name))
if IsRemote() {
@@ -1193,7 +1203,7 @@ func AddTag(t *testing.T, name string) {
func AddTagWithForce(t *testing.T, name string) {
t.Helper()
prevGnuPGHome := os.Getenv("GNUPGHOME")
t.Setenv("GNUPGHOME", TmpDir+"/gpg")
t.Setenv("GNUPGHOME", TmpDir()+"/gpg")
defer t.Setenv("GNUPGHOME", prevGnuPGHome)
errors.NewHandler(t).FailOnErr(Run(repoDirectory(), "git", "tag", "-f", name))
if IsRemote() {

View File

@@ -23,7 +23,7 @@ func AddGPGPublicKey(t *testing.T) {
if fixture.IsLocal() {
keyData, err := os.ReadFile(keyPath)
require.NoError(t, err)
err = os.WriteFile(fmt.Sprintf("%s/app/config/gpg/source/%s", fixture.TmpDir, fixture.GpgGoodKeyID), keyData, 0o644)
err = os.WriteFile(fmt.Sprintf("%s/app/config/gpg/source/%s", fixture.TmpDir(), fixture.GpgGoodKeyID), keyData, 0o644)
require.NoError(t, err)
} else {
fixture.RestartRepoServer(t)
@@ -35,7 +35,7 @@ func DeleteGPGPublicKey(t *testing.T) {
args := []string{"gpg", "rm", fixture.GpgGoodKeyID}
errors.NewHandler(t).FailOnErr(fixture.RunCli(args...))
if fixture.IsLocal() {
require.NoError(t, os.Remove(fmt.Sprintf("%s/app/config/gpg/source/%s", fixture.TmpDir, fixture.GpgGoodKeyID)))
require.NoError(t, os.Remove(fmt.Sprintf("%s/app/config/gpg/source/%s", fixture.TmpDir(), fixture.GpgGoodKeyID)))
} else {
fixture.RestartRepoServer(t)
}

View File

@@ -20,6 +20,7 @@ func DnsFriendly(str string, postfix string) string { //nolint:revive //FIXME(va
str = matchFirstCap.ReplaceAllString(str, "${1}-${2}")
str = matchAllCap.ReplaceAllString(str, "${1}-${2}")
str = strings.ToLower(str)
str = strings.ReplaceAll(str, "/", "-")
if diff := len(str) + len(postfix) - 63; diff > 0 {
str = str[:len(str)-diff]

View File

@@ -134,7 +134,7 @@ func TestAnnotatedTagInStatusSyncRevision(t *testing.T) {
Then().
Expect(SyncStatusIs(SyncStatusCodeSynced)).
And(func(app *Application) {
annotatedTagIDOutput, err := fixture.Run(fixture.TmpDir+"/testdata.git", "git", "show-ref", "annotated-tag")
annotatedTagIDOutput, err := fixture.Run(fixture.TmpDir()+"/testdata.git", "git", "show-ref", "annotated-tag")
require.NoError(t, err)
require.NotEmpty(t, annotatedTagIDOutput)
// example command output:
@@ -142,7 +142,7 @@ func TestAnnotatedTagInStatusSyncRevision(t *testing.T) {
annotatedTagIDFields := strings.Fields(string(annotatedTagIDOutput))
require.Len(t, annotatedTagIDFields, 2)
targetCommitID, err := fixture.Run(fixture.TmpDir+"/testdata.git", "git", "rev-parse", "--verify", "annotated-tag^{commit}")
targetCommitID, err := fixture.Run(fixture.TmpDir()+"/testdata.git", "git", "rev-parse", "--verify", "annotated-tag^{commit}")
// example command output:
// "bcd35965e494273355265b9f0bf85075b6bc5163"
require.NoError(t, err)

View File

@@ -1,16 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICijCCAXICAQAwFjEUMBIGA1UEAwwLQXJnbyBDRCBFMkUwggEiMA0GCSqGSIb3
DQEBAQUAA4IBDwAwggEKAoIBAQC03Hb4xACw7Y3K90DZizwtUqyVQ/4HgSUIy6OX
wG0a+CS9x46FnpUc0divhJh/1jcWn1hkWl5EOopDaPW3jkCw18kz+rDikLfqmXgy
bldW92KxoyzSL3wO4VklID6GM6lkdGi0TN/mfNzxNKhjXHm3CbJtkRrrOaUfd5Hj
2cbAQmw7hzbn1QYM3sKyKSOF1ySBgvtkakcVEfVFiSAQivKOnSWTMu92Y/cI0nsH
zTtMZVL+KPBQ2eTdmMaUxNASnl5rDsR5fqD9GIqVszLakU2N8D2PvyjTUyRVtyiU
/et9YBub+/qp7dqKI88nY4tV/sgXpNM+ND8DmbpQFeOZiX0fAgMBAAGgLzAtBgkq
hkiG9w0BCQ4xIDAeMBwGA1UdEQQVMBOCEWFyZ29jZC1lMmUtc2VydmVyMA0GCSqG
SIb3DQEBCwUAA4IBAQATFrqrM91BKAiOTShf+uMlx8VT11pBtZ78Rg3Enp2xEvUX
jEwo3lRD6Fb0T0xi+4O0ScVZFP4yp4ZZ2uqIIzJLSq8F2cko6AhplMPDbxDOVZyq
Z5t6VJnfXOQYwtgyowTWCijA5rOaqhmluCbguTQAJRR6Qk6Oc4Ti4BfbliIbzDBO
QVAA6HoQPn4E314vBolkxicPesnrYFA7F/U8iCD57cyu5FmEQZuTLmplBzc/UmeV
AKcS0+w3Hk+uTgZmqdTWPOzbKXYgF4lU0QNanx4j/H3G4QKujlUspyhid52sFYcq
1b4+U2ashtNzUze9Og0Q6CJv3Nu2fqOIG7OBOJcd
-----END CERTIFICATE REQUEST-----

View File

@@ -1,3 +0,0 @@
[localhost]:2222 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBLle3IiLWy+Cwz6/JT3K8PSGAEZAJnaxiWk0u9wkAvbZ9wHTffctg25coBa8J4Oo1l5GTIkezib2C4PjCE01BZM=
[localhost]:2222 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDhRWyu6rg0Kd0ugLxNGZ8gzUjasF4Z0oT16RUC/L9EkJWATAu4TkkoozZ5AcejlS29jUZXTkKt0La4dmIooeMDNd8b5vg1dWzSDDHwxd8Wa/4XZsUlL6zkUFrnqOPaFc/7EwM3I30064zT/Gt0BVvQUxKoT/TTea2KhQqeLmlWh4cVWJBuhZ8YODUf2VD4TSYfvpcqW/jVw2oG8Pj3WIaaG2+Bcp4Q4sJS2K+2kkiqmZ/hiPK1X/UbMRN2zWQBp5UPWFY2ctuC9B8yhLwAyMkHzuWLfB39dNEdn1jTjDsOUWbC3kDsWHsY5gtBxN30NizBWC+83NpaWbrzAlGb0JV1
[localhost]:2222 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG2t7Tcavp5oUqbbSwEKRaGwEq94b8BFK16AEBbgRCTp

View File

@@ -1,5 +1,6 @@
# To prevent regression of https://github.com/argoproj/argo-cd/pull/6253, we
# start sshd with -o KexAlgorithms=diffie-hellman-group-exchange-sha256
sshd: mkdir -p /var/run/sshd && mkdir -p ~/.ssh && cat ./test/fixture/testrepos/id_rsa.pub > ~/.ssh/authorized_keys && /usr/sbin/sshd -p 2222 -D -e -o KexAlgorithms=diffie-hellman-group-exchange-sha256
# Copy fixed SSH host keys so ssh_known_hosts stays valid across container restarts
sshd: mkdir -p /var/run/sshd && mkdir -p ~/.ssh && cat ./test/fixture/testrepos/id_rsa.pub > ~/.ssh/authorized_keys && cp ./test/fixture/testrepos/ssh_host_*_key /etc/ssh/ && cp ./test/fixture/testrepos/ssh_host_*_key.pub /etc/ssh/ && chmod 600 /etc/ssh/ssh_host_*_key && /usr/sbin/sshd -p 2222 -D -e -o KexAlgorithms=diffie-hellman-group-exchange-sha256
fcgiwrap: fcgiwrap -s unix:/var/run/fcgiwrap.socket & sleep 1 && chmod 777 /var/run/fcgiwrap.socket && wait
nginx: nginx -prefix=$(pwd) -g 'daemon off;' -c $(pwd)/test/fixture/testrepos/nginx.conf

View File

@@ -0,0 +1,121 @@
# Test Repository Server Files
This directory contains configuration and cryptographic keys for running the E2E test Git server in a Docker container. The server provides Git repositories accessible via SSH, HTTP, and HTTPS.
## Overview
The test server runs in Docker (`argoproj/argo-cd-ci-builder:v1.0.0`) using goreman to manage three processes: sshd (port 2222), nginx (ports 9080, 9443-9445), and fcgiwrap (Git HTTP backend).
## Files
### `start-git.sh`
Starts the Docker container with the test Git server. Mounts the current directory and `ARGOCD_E2E_DIR` (default: `/tmp/argo-e2e`), exposing ports for SSH and HTTP/HTTPS access.
### `start-helm-registry.sh` / `start-authenticated-helm-registry.sh`
Start Helm registries for testing Helm chart functionality, with and without authentication.
### `Procfile`
Defines processes managed by goreman:
- **sshd**: Copies fixed SSH host keys to `/etc/ssh/` before starting on port 2222
- **fcgiwrap**: FastCGI wrapper for Git HTTP backend
- **nginx**: Web server for HTTP/HTTPS Git access
### SSH Keys
#### SSH Host Keys
- `ssh_host_rsa_key`, `ssh_host_ecdsa_key`, `ssh_host_ed25519_key` (with `.pub` files)
By copying pre-generated keys before starting sshd, the same keys are used every time, keeping the `ssh_known_hosts` the same on restarts.
#### `ssh_known_hosts`
Contains SSH host key fingerprints for:
- `[localhost]:2222` - Local development/testing
- `[argocd-e2e-server]:2222` - Remote/in-cluster testing
Both entries have identical fingerprints since they use the same keys from this directory.
#### `id_rsa.pub`
Public key added to `~/.ssh/authorized_keys` in the container for SSH authentication.
### `nginx.conf`
Provides HTTP (9080), HTTPS (9443/9444/9445), and Helm repository access. Proxies Git operations to git-http-backend via fcgiwrap.
### `sudoers.conf`
Sudo configuration allowing test users to start services with elevated privileges.
## Regenerating SSH Keys
If you need to regenerate the SSH host keys:
### 1. Generate New Keys
```bash
cd test/fixture/testrepos
# Generate RSA key
ssh-keygen -t rsa -b 2048 -f ssh_host_rsa_key -N "" -C "root@argocd-e2e"
# Generate ECDSA key
ssh-keygen -t ecdsa -f ssh_host_ecdsa_key -N "" -C "root@argocd-e2e"
# Generate Ed25519 key
ssh-keygen -t ed25519 -f ssh_host_ed25519_key -N "" -C "root@argocd-e2e"
```
### 2. Update ssh_known_hosts
```bash
# Start temporary sshd with new keys
sudo mkdir -p /tmp/test-sshd
sudo cp ssh_host_*_key* /tmp/test-sshd/
sudo chmod 600 /tmp/test-sshd/ssh_host_*_key
sudo /usr/sbin/sshd -p 2222 \
-h /tmp/test-sshd/ssh_host_rsa_key \
-h /tmp/test-sshd/ssh_host_ecdsa_key \
-h /tmp/test-sshd/ssh_host_ed25519_key \
-D &
SSHD_PID=$!
# Scan to get new fingerprints
ssh-keyscan -p 2222 localhost > ssh_known_hosts.tmp
# Stop temporary sshd
sudo kill $SSHD_PID
sudo rm -rf /tmp/test-sshd
# Create new ssh_known_hosts with both localhost and argocd-e2e-server entries
cat > ssh_known_hosts << 'EOF'
# localhost:2222 SSH-2.0-OpenSSH_X.Xp1
EOF
cat ssh_known_hosts.tmp >> ssh_known_hosts
echo "# For in-cluster tests" >> ssh_known_hosts
sed 's/\[localhost\]/[argocd-e2e-server]/g' ssh_known_hosts.tmp >> ssh_known_hosts
rm ssh_known_hosts.tmp
```
### 3. Verify
```bash
# Start the test server
./test/fixture/testrepos/start-git.sh
# In another terminal, test SSH connection
ssh -p 2222 -o UserKnownHostsFile=test/fixture/testrepos/ssh_known_hosts root@localhost
```
## Related Documentation
- [TLS Certificates](../certs/README.md) - HTTPS certificates (separate from SSH keys)
- [Remote Testing](../../remote/README.md) - Running tests against remote clusters

View File

@@ -1,6 +1,15 @@
#!/usr/bin/env bash
# ARGOCD_E2E_DIR can be set to customize the e2e test data directory on the host
# This is useful on macOS where Docker doesn't share /tmp with the host
# The host directory is mounted to /tmp/argo-e2e inside the container
ARGOCD_E2E_DIR="${ARGOCD_E2E_DIR:-/tmp/argo-e2e}"
docker run --name e2e-git --rm -i \
-p 2222:2222 -p 9080:9080 -p 9443:9443 -p 9444:9444 -p 9445:9445 \
-w /go/src/github.com/argoproj/argo-cd -v "$(pwd)":/go/src/github.com/argoproj/argo-cd -v /tmp:/tmp docker.io/argoproj/argo-cd-ci-builder:v1.0.0 \
-w /go/src/github.com/argoproj/argo-cd \
-v /tmp:/tmp \
-v "$ARGOCD_E2E_DIR":/tmp/argo-e2e \
-v "$(pwd)":/go/src/github.com/argoproj/argo-cd \
docker.io/argoproj/argo-cd-ci-builder:v1.0.0 \
bash -c "goreman -f ./test/fixture/testrepos/Procfile start"