Sitelet https://github.com/kubernetes/kops/pull/18699
Skip to content

tests/e2e: determine the SSH user from the cluster when not configured - #18699

Merged
kubernetes-prow[bot] merged 1 commit into
kubernetes:masterfrom
rifelpet:derive-ssh-user
Aug 16, 2026
Merged

kubernetes-prow[bot] merged 1 commit into
kubernetes:masterfrom
rifelpet:derive-ssh-user

Conversation

@rifelpet

Copy link
Copy Markdown
Member

kubetest2-kops takes its SSH user from KUBE_SSH_USER, which the prow jobs set from a hand-maintained per-distro table (aws_distros_ssh_user, and a hardcoded prow for GCE). kops already knows the answer — it registers the SSH key under a username it derives from the image, and reports that as sshUser for every instance in kops toolbox dump:

cloud source
aws guessSSHUser (pkg/resources/aws/aws.go)
gce gce.SSHUsernameForImage (pkg/resources/gce/dump.go)
azure OSProfile.AdminUsername (pkg/resources/azure/dump.go)
digitalocean root (pkg/resources/digitalocean/resources.go)

This uses that, only as a last resort.

Precedence

  1. the --ssh-user flag
  2. the users the deployer assigns itself — azure kops, digitalocean root
  3. KUBE_SSH_USER
  4. only if still empty: the cluster

Putting discovery last is the point. All 2,660 jobs that set KUBE_SSH_USER keep exactly the user they have today, so this changes nothing on merge and costs nothing — the lookup early-returns before shelling out whenever a user is already known. A job opts in by deleting its KUBE_SSH_USER, which keeps the rollout per-job and revertable without touching kops.

Where it runs

The lookup needs instances to exist, so it runs in Up() after the cloud resources are created and before validation — a cluster that comes up but fails to validate is exactly when you want log collection to work. Up() is not the only entry point, so DumpClusterLogs() resolves the user too, for --down invocations in a fresh process.

Without --dir, kops toolbox dump only lists cloud resources; it does not SSH anywhere, so it does not need the credentials it is being used to determine.

The environment handed to the tester is built during init(), before any of this is knowable, so that export is extracted into exportEnvForTester() and run again once the user is known.

When nothing can be determined

An older kops that does not report sshUser, or a cluster that failed before creating instances, leaves the user empty. In that case --ssh-user is omitted entirely rather than passed as "", so kops applies its own default (ubuntu) instead of being handed an unusable empty value. Both toolbox dump call sites do this.

Testing

  • TestSSHUserFromDump: control plane preferred over workers, fallback to any instance, instances with no user skipped, and the two empty cases.
  • TestResolveSSHUserFromClusterKeepsExistingUser: an already-set user survives untouched, with a deliberately bogus KopsBinaryPath so that any attempt to shell out would fail loudly rather than silently pass.
  • go build ./..., go vet ./... and go test ./... in tests/e2e.
  • The GCE presubmits on this PR should log Using SSH user: [prow] exactly as today. That is the assertion — nothing should change.

Rollout

Opting jobs in is a separate test-infra change, and is gated on the kops version a job runs, because gce/dump.go only started reporting sshUser in c6e61af681 (2026-07-12), which is not in release-1.34/1.35/1.36. Of 941 GCE periodics, the 361 on the master marker are eligible; the other 580 become eligible as those branches age out of the matrix. The AWS jobs follow once #18698 (Rocky Linux) reaches the versions they run.

Full plan: docs/plans/gce-ssh-cleanup-step1.md.

🤖 Generated with Claude Code

kubetest2-kops takes its SSH user from KUBE_SSH_USER, which the prow jobs
set from a hand-maintained per-distro table. kops already knows the
answer: it registers the SSH key under a username it derives from the
image, and reports that as sshUser for every instance in "kops toolbox
dump" -- guessSSHUser on AWS, SSHUsernameForImage on GCE, the VMSS admin
username on Azure, root on DigitalOcean.

Use it, but only as a last resort. The order is now the --ssh-user flag,
then the users the deployer assigns itself for azure and digitalocean,
then KUBE_SSH_USER, and only then the cluster. Every job that sets
KUBE_SSH_USER keeps exactly the user it has today, so this changes
nothing on merge; a job opts in by dropping that variable, which keeps
the rollout per-job and revertable without touching kops.

The lookup needs the instances to exist, so it runs in Up() once the
cloud resources are created and before validation, so that a cluster
which comes up but fails to validate is still reachable for log
collection. Up() is not the only entry point, so DumpClusterLogs() also
resolves the user for --down invocations in a fresh process.

The environment handed to the tester is built during init(), before any
of this is knowable, so extract that export and run it again once the
user is known.

Where no user can be determined -- an older kops that does not report
sshUser, or a cluster that failed before creating instances -- leave it
empty and omit --ssh-user entirely, so kops applies its own default
rather than being handed an unusable empty value.
@kubernetes-prow

Copy link
Copy Markdown
Contributor

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@kubernetes-prow kubernetes-prow Bot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Aug 16, 2026
@kubernetes-prow
kubernetes-prow Bot requested review from hakman and olemarkus August 16, 2026 14:51
@rifelpet

Copy link
Copy Markdown
Member Author

/test pull-kops-e2e-k8s-gce-cilium
/test pull-kops-kubernetes-e2e-cos-gce-serial

@kubernetes-prow

Copy link
Copy Markdown
Contributor

@rifelpet: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
pull-kops-kubernetes-e2e-cos-gce-serial fdc3db6 link false /test pull-kops-kubernetes-e2e-cos-gce-serial

Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@hakman

hakman commented Aug 16, 2026

Copy link
Copy Markdown
Member

/test pull-kops-kubernetes-e2e-cos-gce-serial

@rifelpet
rifelpet marked this pull request as ready for review August 16, 2026 19:16
@kubernetes-prow kubernetes-prow Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Aug 16, 2026
@kubernetes-prow
kubernetes-prow Bot requested a review from zetaab August 16, 2026 19:16
@rifelpet

Copy link
Copy Markdown
Member Author

@rifelpet: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:
Test name Commit Details Required Rerun command
pull-kops-kubernetes-e2e-cos-gce-serial fdc3db6 link false /test pull-kops-kubernetes-e2e-cos-gce-serial

Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR.
Details

The failure here was unrelated, the behavior was confirmed with inferring the admin user:

I0816 17:56:02.338611   12845 local.go:42] ⚙️ /home/prow/go/src/k8s.io/kops/.build/dist/linux/amd64/kops toolbox dump --name pr18699-kops-kubernetes-e2e-cos-gce-serial.k8s.local --dir /logs/artifacts --private-key /etc/ssh-key-secret/ssh-private --ssh-user admin
I0816 17:56:03.046643   41824 gce.go:95] Scanning zones: [us-west1-b us-west1-c us-west1-a]
I0816 17:56:07.907292   41824 toolbox_dump.go:211] will SSH using username "admin"
I0816 17:56:07.907308   41824 toolbox_dump.go:212] ssh auth methods [0x5997a00]

@rifelpet

Copy link
Copy Markdown
Member Author

Sorry i disrupted the retry with the temp commit. i can push the temp commit back again if you want.

@hakman

hakman commented Aug 16, 2026

Copy link
Copy Markdown
Member

Sorry i disrupted the retry with the temp commit. i can push the temp commit back again if you want.

No, all good.
/lgtm
/approve

@kubernetes-prow kubernetes-prow Bot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Aug 16, 2026
@kubernetes-prow

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: hakman

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubernetes-prow kubernetes-prow Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Aug 16, 2026
@kubernetes-prow
kubernetes-prow Bot merged commit de4d11b into kubernetes:master Aug 16, 2026
35 checks passed
kubernetes-prow Bot pushed a commit to kubernetes/test-infra that referenced this pull request Aug 17, 2026
kubernetes/kops#18699 lets kubetest2-kops ask the cluster which user kops
registered the SSH key for, but only when the job does not set
KUBE_SSH_USER. Every GCE job sets it to "prow", so nothing exercises the
new path yet.

Add a derive_ssh_user option that omits the variable, and turn it on for
two nftables periodics before touching the rest of GCE:

  e2e-kops-gce-nftables-cos125   expect "admin"
  e2e-kops-gce-nftables-u2404    expect "ubuntu"

cos125 is the load-bearing case. kops defaults --ssh-user to "ubuntu"
when it is not supplied, so a u2404 job cannot distinguish a working
lookup from a broken one, while cos125 derives "admin" and fails visibly
if discovery does not work. Both distros were confirmed to have that user
created with sudo, holding the key kops installs in instance metadata.

Only the user moves: KUBE_SSH_KEY_PATH and preset-k8s-ssh stay, so these
jobs keep the shared CI key. The other 36 nftables jobs keep
KUBE_SSH_USER as controls.

Restricted to jobs on the master kops marker, because GCE only started
reporting sshUser in kops 1.37 (c6e61af681) and that is not in the
release branches. The rest of GCE becomes eligible as those branches age
out of the matrix.
alien1403 pushed a commit to alien1403/test-infra that referenced this pull request Aug 19, 2026
kubernetes/kops#18699 lets kubetest2-kops ask the cluster which user kops
registered the SSH key for, but only when the job does not set
KUBE_SSH_USER. Every GCE job sets it to "prow", so nothing exercises the
new path yet.

Add a derive_ssh_user option that omits the variable, and turn it on for
two nftables periodics before touching the rest of GCE:

  e2e-kops-gce-nftables-cos125   expect "admin"
  e2e-kops-gce-nftables-u2404    expect "ubuntu"

cos125 is the load-bearing case. kops defaults --ssh-user to "ubuntu"
when it is not supplied, so a u2404 job cannot distinguish a working
lookup from a broken one, while cos125 derives "admin" and fails visibly
if discovery does not work. Both distros were confirmed to have that user
created with sudo, holding the key kops installs in instance metadata.

Only the user moves: KUBE_SSH_KEY_PATH and preset-k8s-ssh stay, so these
jobs keep the shared CI key. The other 36 nftables jobs keep
KUBE_SSH_USER as controls.

Restricted to jobs on the master kops marker, because GCE only started
reporting sshUser in kops 1.37 (c6e61af681) and that is not in the
release branches. The rest of GCE becomes eligible as those branches age
out of the matrix.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants