Skip to content
Open
Changes from 1 commit
Commits
Show all changes
84 commits
Select commit Hold shift + click to select a range
7cd75c1
feat: add create k0s setup from config.yaml
OliverTrautvetter Dec 10, 2025
cdd6ee8
Merge branch 'main' into deploy_k0s_install-config
OliverTrautvetter Dec 10, 2025
5a907ab
chore(docs): Auto-update docs and licenses
OliverTrautvetter Dec 10, 2025
3035990
ref: use deferred functions for cleanup in k0s and node installers
OliverTrautvetter Dec 10, 2025
8892ce0
Merge branch 'deploy_k0s_install-config' of https://github.com/codesp…
OliverTrautvetter Dec 10, 2025
ad86e8e
chore(docs): Auto-update docs and licenses
OliverTrautvetter Dec 10, 2025
c79fc3d
ref: refactor install-config integration tests for improved clarity a…
OliverTrautvetter Dec 15, 2025
071eea9
ref: cleanup
OliverTrautvetter Dec 16, 2025
9de5965
chore(docs): Auto-update docs and licenses
OliverTrautvetter Dec 16, 2025
01d6750
Update internal/installer/node/node.go
OliverTrautvetter Dec 16, 2025
b19ac3b
ref: enhance shell command safety
OliverTrautvetter Dec 16, 2025
41e61da
Merge branch 'deploy_k0s_install-config' of https://github.com/codesp…
OliverTrautvetter Dec 16, 2025
d4d1b5f
test: add tests for NodeManager and Node methods
OliverTrautvetter Dec 16, 2025
97bb3b8
fix: improve passphrase handling in getAuthMethods
OliverTrautvetter Dec 16, 2025
b07c0a8
fix: enforce required flags for remote installation and clean up test…
OliverTrautvetter Dec 16, 2025
8f56476
fix: update EnsureDirectoryExists to accept jumpbox IP
OliverTrautvetter Dec 16, 2025
f674352
test: add tests for InstallK0sCmd
OliverTrautvetter Dec 16, 2025
4e61092
fix: correct sed command syntax for enabling root login
OliverTrautvetter Dec 16, 2025
7a407f0
test: add mock expectations for SSH key file reading in InstallK0sCmd…
OliverTrautvetter Dec 16, 2025
52e8667
test: add tests for K0s configuration filtering
OliverTrautvetter Dec 16, 2025
ef0f96c
test: add tests for Reset functionality in K0s
OliverTrautvetter Dec 16, 2025
4b49bd6
test: add tests for SSH key file handling in InstallK0sRemote method
OliverTrautvetter Dec 16, 2025
e3a9e18
fix: fix k0s installation path and config handling
OliverTrautvetter Dec 17, 2025
e2192fe
fix: k0s config handling to support temporary paths in tests
OliverTrautvetter Dec 17, 2025
bb39c0e
feat: enhance remote k0s installation with user support and SSH instr…
OliverTrautvetter Dec 17, 2025
fdcb214
ref: minor
OliverTrautvetter Dec 17, 2025
2f6fa29
fix: error message for missing install-config in RunE method
OliverTrautvetter Dec 18, 2025
2ad0251
fix: appease make lint
OliverTrautvetter Dec 18, 2025
54ae71c
Update internal/installer/node/node.go
OliverTrautvetter Dec 18, 2025
a5faa2c
fix: improve regex for enabling root login in SSH configuration
OliverTrautvetter Dec 18, 2025
d120484
Update internal/installer/node/node.go
OliverTrautvetter Dec 18, 2025
8e92d3a
fix: update SSH installation notes and remove insecure host key warning
OliverTrautvetter Dec 18, 2025
bb05e55
Merge branch 'deploy_k0s_install-config' of https://github.com/codesp…
OliverTrautvetter Dec 18, 2025
6e80a78
refactor: standardize receiver names in NodeManager methods for consi…
OliverTrautvetter Dec 18, 2025
921e47c
fix: enhance k0s reset process by stopping service before reset and u…
OliverTrautvetter Dec 19, 2025
dfc9deb
ref: extract k0s ClusterConfig keys into constants for improved maint…
OliverTrautvetter Dec 19, 2025
a79cd1a
feat: enhance node Installation and testing
OliverTrautvetter Jan 8, 2026
82fbdbf
Merge branch 'main' into deploy_k0s_install-config
OliverTrautvetter Jan 8, 2026
590ad32
fix: merge errors
OliverTrautvetter Jan 8, 2026
88d365b
chore(docs): Auto-update docs and licenses
OliverTrautvetter Jan 8, 2026
6a88ac1
fix: simplify root login check logic
OliverTrautvetter Jan 9, 2026
40b97d1
Merge branch 'deploy_k0s_install-config' of https://github.com/codesp…
OliverTrautvetter Jan 9, 2026
f2be13a
chore(docs): Auto-update docs and licenses
OliverTrautvetter Jan 9, 2026
aa4222e
ref: enhance k0s installation process and test configuration
OliverTrautvetter Jan 13, 2026
af7f8a1
Merge branch 'main' into deploy_k0s_install-config
OliverTrautvetter Jan 13, 2026
7f3d823
chore(docs): Auto-update docs and licenses
OliverTrautvetter Jan 13, 2026
5da46ec
fix: enhance error handling in NodeManager client connection tests
OliverTrautvetter Jan 13, 2026
f5ba1e8
Merge branch 'deploy_k0s_install-config' of https://github.com/codesp…
OliverTrautvetter Jan 13, 2026
d1c2417
Merge remote-tracking branch 'origin/main' into deploy_k0s_install-co…
OliverTrautvetter Jan 22, 2026
949bbed
fix: merge error
OliverTrautvetter Jan 22, 2026
8b47dfd
fix: node tests
OliverTrautvetter Jan 22, 2026
0086e60
ref: start to update k0s to k0sctl
OliverTrautvetter Jan 28, 2026
8cb0709
chore(docs): Auto-update docs and licenses
OliverTrautvetter Jan 28, 2026
8da565b
Merge branch 'main' into deploy_k0s_install-config
OliverTrautvetter Jan 28, 2026
36febb9
Merge branch 'main' into deploy_k0s_install-config
OliverTrautvetter Jan 28, 2026
ffa3084
chore(docs): Auto-update docs and licenses
OliverTrautvetter Jan 28, 2026
d30c117
ref: mock SSH client and enhance tests for SSH connection failures
OliverTrautvetter Jan 28, 2026
e8f73f8
Merge branch 'deploy_k0s_install-config' of https://github.com/codesp…
OliverTrautvetter Jan 28, 2026
095c55d
chore(docs): Auto-update docs and licenses
OliverTrautvetter Jan 28, 2026
767a005
Update internal/installer/node/node.go
OliverTrautvetter Jan 28, 2026
d0d3adb
Update hack/lima-oms.yaml
OliverTrautvetter Jan 28, 2026
7c6466b
fix: update go mod
OliverTrautvetter Jan 28, 2026
205bca4
ref: simplify host address assignment in k0sctl config generation
OliverTrautvetter Jan 28, 2026
836abc7
ref: remove unused MockSSHClient and related functions
OliverTrautvetter Jan 28, 2026
41f5eac
ref: enhance host key verification to auto-accept new hosts during pr…
OliverTrautvetter Jan 28, 2026
344d3de
fix: k0s bugs
OliverTrautvetter Jan 30, 2026
4167882
ref: update k0sctl config path to use OmsWorkdir and improve error ha…
OliverTrautvetter Jan 30, 2026
456ec52
Update internal/installer/node/node.go
OliverTrautvetter Jan 30, 2026
9e5bd53
Merge remote-tracking branch 'origin/main' into deploy_k0s_install-co…
OliverTrautvetter Jan 30, 2026
8a7ffc1
ref: cleanup
OliverTrautvetter Jan 30, 2026
1d44afc
ref: enhance GetNodeIPAddress logic and simplify GenerateK0sConfig wi…
OliverTrautvetter Feb 2, 2026
c9316f7
ref: simplify k0s config
OliverTrautvetter Feb 2, 2026
a97522f
Update internal/installer/k0sctl_config.go
OliverTrautvetter Feb 2, 2026
ada6983
Update internal/installer/node/node.go
OliverTrautvetter Feb 2, 2026
9905716
ref: implement review suggestions
OliverTrautvetter Feb 2, 2026
fc90a08
fix: new tests
OliverTrautvetter Feb 2, 2026
ff7bfff
Update hack/lima-oms.yaml
OliverTrautvetter Feb 2, 2026
36f193e
ref: implement review suggestions
OliverTrautvetter Feb 2, 2026
a542892
Merge branch 'deploy_k0s_install-config' of https://github.com/codesp…
OliverTrautvetter Feb 2, 2026
0cfbbd8
ref: cleanup
OliverTrautvetter Feb 11, 2026
593fff9
Merge remote-tracking branch 'origin/main' into deploy_k0s_install-co…
OliverTrautvetter Feb 11, 2026
3270731
chore(docs): Auto-update docs and licenses
OliverTrautvetter Feb 11, 2026
e22a299
Merge remote-tracking branch 'origin/main' into deploy_k0s_install-co…
OliverTrautvetter Feb 16, 2026
59f5b84
chore(docs): Auto-update docs and licenses
OliverTrautvetter Feb 16, 2026
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
Prev Previous commit
Next Next commit
Merge remote-tracking branch 'origin/main' into deploy_k0s_install-co…
…nfig
  • Loading branch information
OliverTrautvetter committed Jan 22, 2026
commit d1c2417f42f6a5d032a3b7715dcb8f756426d950
129 changes: 43 additions & 86 deletions internal/installer/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,81 +71,52 @@ func (nm *NodeManager) getHostKeyCallback() (ssh.HostKeyCallback, error) {
return hostKeyCallback, nil
}

func (nm *NodeManager) getAuthMethods() ([]ssh.AuthMethod, error) {
var authMethods []ssh.AuthMethod
// getAuthMethods constructs a slice of ssh.AuthMethod, prioritizing the SSH agent.
func (n *NodeManager) getAuthMethods() ([]ssh.AuthMethod, error) {
var signers []ssh.Signer

// 1. Get Agent Signers
if authSocket := os.Getenv("SSH_AUTH_SOCK"); authSocket != "" {
conn, err := net.Dial("unix", authSocket)
if err == nil {
if conn, err := net.Dial("unix", authSocket); err == nil {
agentClient := agent.NewClient(conn)
if s, err := agentClient.Signers(); err == nil {
signers = append(signers, s...)
}
}
}

if nm.KeyPath != "" {
fmt.Printf("Falling back to private key file authentication (key: %s).\n", nm.KeyPath)

key, err := nm.FileIO.ReadFile(nm.KeyPath)
if err != nil {
return nil, fmt.Errorf("failed to read private key file %s: %v", nm.KeyPath, err)
}

log.Printf("Successfully read %d bytes from key file", len(key))
// 2. Add Private Key (File) if needed
if n.KeyPath != "" {
shouldLoad := true

signer, err := ssh.ParsePrivateKey(key)
if err == nil {
log.Printf("Successfully parsed private key (type: %s)", signer.PublicKey().Type())
authMethods = append(authMethods, ssh.PublicKeys(signer))
return authMethods, nil
// Use cached signer if available
if n.cachedSigner != nil {
signers = append(signers, n.cachedSigner)
shouldLoad = false
}

log.Printf("Failed to parse private key: %v", err)
if _, ok := err.(*ssh.PassphraseMissingError); ok {
// Check if we're in an interactive terminal
if !term.IsTerminal(int(syscall.Stdin)) {
return nil, fmt.Errorf("passphrase-protected key requires interactive terminal. Use ssh-agent or an unencrypted key for automated scenarios")
}

fmt.Printf("Enter passphrase for key '%s': ", nm.KeyPath)

// Read passphrase with a timeout using a channel
type result struct {
password []byte
err error
}
resultChan := make(chan result, 1)
go func() {
passphraseBytes, err := term.ReadPassword(int(syscall.Stdin))
resultChan <- result{password: passphraseBytes, err: err}
}()

// Wait for passphrase input with 30 second timeout
select {
case res := <-resultChan:
fmt.Println()
if res.err != nil {
return nil, fmt.Errorf("failed to read passphrase: %v", res.err)
}

defer func() {
for i := range res.password {
res.password[i] = 0
// Check if key is already in agent (requires .pub file)
if shouldLoad && len(signers) > 0 {
if pubBytes, err := n.FileIO.ReadFile(n.KeyPath + ".pub"); err == nil {
if targetPub, _, _, _, err := ssh.ParseAuthorizedKey(pubBytes); err == nil {
targetMarshaled := string(targetPub.Marshal())
for _, s := range signers {
if string(s.PublicKey().Marshal()) == targetMarshaled {
shouldLoad = false
break
}
}
}()

signer, err = ssh.ParsePrivateKeyWithPassphrase(key, res.password)
if err != nil {
return nil, fmt.Errorf("failed to parse private key with passphrase: %v", err)
}
authMethods = append(authMethods, ssh.PublicKeys(signer))
return authMethods, nil
}
}

case <-time.After(30 * time.Second):
fmt.Println()
return nil, fmt.Errorf("passphrase input timeout after 30 seconds")
// Else load from file with passphrase prompt if needed
if shouldLoad {
if signer, err := n.loadPrivateKey(); err == nil {
n.cachedSigner = signer
signers = append(signers, signer)
} else {
log.Printf("Warning: failed to load private key: %v\n", err)
}
}
}
Expand Down Expand Up @@ -217,8 +188,9 @@ func (nm *NodeManager) connectToJumpbox(ip, username string) (*ssh.Client, error
return nil, fmt.Errorf("failed to dial jumpbox %s: %v", addr, err)
}

// Enable Agent Forwarding on the jumpbox connection
if err := nm.forwardAgent(jumpboxClient, nil); err != nil {
fmt.Printf(" Warning: Agent forwarding setup failed on jumpbox: %v\n", err)
log.Printf(" Warning: Agent forwarding setup failed on jumpbox: %v\n", err)
}

return jumpboxClient, nil
Expand Down Expand Up @@ -262,8 +234,10 @@ func (nm *NodeManager) RunSSHCommand(jumpboxIp string, ip string, username strin

_ = session.Setenv("OMS_PORTAL_API_KEY", os.Getenv("OMS_PORTAL_API_KEY"))

if err := nm.forwardAgent(client, session); err != nil {
fmt.Printf(" Warning: Agent forwarding setup failed on session: %v\n", err)
err = nm.forwardAgent(client, session)

if err != nil {
log.Printf(" Warning: Agent forwarding setup failed on session: %v\n", err)
}

session.Stdout = os.Stdout
Expand All @@ -279,20 +253,19 @@ func (nm *NodeManager) RunSSHCommand(jumpboxIp string, ip string, username strin
return nil
}

func (nm *NodeManager) GetClient(jumpboxIp string, ip string, username string) (*ssh.Client, error) {

authMethods, err := nm.getAuthMethods()
func (n *NodeManager) GetClient(jumpboxIp string, ip string, username string) (*ssh.Client, error) {
authMethods, err := n.getAuthMethods()
if err != nil {
return nil, fmt.Errorf("failed to get authentication methods: %w", err)
}

hostKeyCallback, err := nm.getHostKeyCallback()
hostKeyCallback, err := n.getHostKeyCallback()
if err != nil {
return nil, fmt.Errorf("failed to get host key callback: %w", err)
}

if jumpboxIp != "" {
jbClient, err := nm.connectToJumpbox(jumpboxIp, jumpboxUser)
jbClient, err := n.connectToJumpbox(jumpboxIp, jumpboxUser)
if err != nil {
return nil, fmt.Errorf("failed to connect to jumpbox: %v", err)
}
Expand Down Expand Up @@ -500,30 +473,14 @@ func (n *Node) WaitForSSH(jumpbox *Node, nm *NodeManager, timeout time.Duration)
}

func (n *Node) HasInotifyWatchesConfigured(jumpbox *Node, nm *NodeManager) bool {
return n.HasSysctlLine(jumpbox, "fs.inotify.max_user_watches=1048576", nm)
}

func (n *Node) ConfigureInotifyWatches(jumpbox *Node, nm *NodeManager) error {
return n.ConfigureSysctlLine(jumpbox, "fs.inotify.max_user_watches=1048576", nm)
}

func (n *Node) HasMemoryMapConfigured(jumpbox *Node, nm *NodeManager) bool {
return n.HasSysctlLine(jumpbox, "vm.max_map_count=262144", nm)
}

func (n *Node) ConfigureMemoryMap(jumpbox *Node, nm *NodeManager) error {
return n.ConfigureSysctlLine(jumpbox, "vm.max_map_count=262144", nm)
}

func (n *Node) HasSysctlLine(jumpbox *Node, line string, nm *NodeManager) bool {
checkCommand := fmt.Sprintf("sudo grep -E '^%s' /etc/sysctl.conf >/dev/null 2>&1", line)
checkCommand := "sudo grep -E '^fs.inotify.max_user_watches=1048576' /etc/sysctl.conf >/dev/null 2>&1"
err := n.RunSSHCommand(jumpbox, nm, "root", checkCommand)
return err == nil
}

func (n *Node) ConfigureSysctlLine(jumpbox *Node, line string, nm *NodeManager) error {
func (n *Node) ConfigureInotifyWatches(jumpbox *Node, nm *NodeManager) error {
cmds := []string{
fmt.Sprintf("echo '%s' | sudo tee -a /etc/sysctl.conf", line),
"echo 'fs.inotify.max_user_watches=1048576' | sudo tee -a /etc/sysctl.conf",
"sudo sysctl -p",
}
for _, cmd := range cmds {
Expand Down
Loading
You are viewing a condensed version of this merge commit. You can view the full changes here.