Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[teleport-update] Add link subcommand #48712

Merged
merged 16 commits into from
Nov 15, 2024
406 changes: 342 additions & 64 deletions lib/autoupdate/agent/installer.go

Large diffs are not rendered by default.

281 changes: 267 additions & 14 deletions lib/autoupdate/agent/installer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,15 +194,17 @@ func testTGZ(t *testing.T, version string) (tgz *bytes.Buffer, shasum string) {
func TestLocalInstaller_Link(t *testing.T) {
t.Parallel()
const version = "new-version"
servicePath := filepath.Join(serviceDir, serviceName)

tests := []struct {
name string
installDirs []string
installFiles []string
existingLinks []string
existingFiles []string
name string
installDirs []string
installFiles []string
installFileMode os.FileMode
existingLinks []string
existingFiles []string

resultLinks []string
resultPaths []string
errMatch string
}{
{
Expand All @@ -222,14 +224,36 @@ func TestLocalInstaller_Link(t *testing.T) {
servicePath,
"README",
},
installFileMode: os.ModePerm,

resultLinks: []string{
resultPaths: []string{
"bin/teleport",
"bin/tsh",
"bin/tbot",
"lib/systemd/system/teleport.service",
},
},
{
name: "present with non-executable files",
installDirs: []string{
"bin",
"bin/somedir",
"etc",
"etc/systemd",
"etc/systemd/somedir",
"somedir",
},
installFiles: []string{
"bin/teleport",
"bin/tsh",
"bin/tbot",
servicePath,
"README",
},
installFileMode: 0644,

errMatch: "executable",
},
{
name: "present with existing links",
installDirs: []string{
Expand All @@ -247,14 +271,17 @@ func TestLocalInstaller_Link(t *testing.T) {
servicePath,
"README",
},
installFileMode: os.ModePerm,
existingLinks: []string{
"bin/teleport",
"bin/tsh",
"bin/tbot",
},
existingFiles: []string{
"lib/systemd/system/teleport.service",
},

resultLinks: []string{
resultPaths: []string{
"bin/teleport",
"bin/tsh",
"bin/tbot",
Expand All @@ -278,12 +305,11 @@ func TestLocalInstaller_Link(t *testing.T) {
servicePath,
"README",
},
installFileMode: os.ModePerm,
existingLinks: []string{
"bin/teleport",
"bin/tsh",
"bin/tbot",
},
existingFiles: []string{
"lib/systemd/system/teleport.service",
},

Expand All @@ -306,6 +332,7 @@ func TestLocalInstaller_Link(t *testing.T) {
servicePath,
"README",
},
installFileMode: os.ModePerm,
existingLinks: []string{
"bin/teleport",
"bin/tbot",
Expand Down Expand Up @@ -346,7 +373,7 @@ func TestLocalInstaller_Link(t *testing.T) {
require.NoError(t, err)
}
for _, n := range tt.installFiles {
err := os.WriteFile(filepath.Join(versionDir, n), []byte(filepath.Base(n)), os.ModePerm)
err := os.WriteFile(filepath.Join(versionDir, n), []byte(filepath.Base(n)), tt.installFileMode)
require.NoError(t, err)
}

Expand Down Expand Up @@ -397,7 +424,7 @@ func TestLocalInstaller_Link(t *testing.T) {
require.NoError(t, err)

// verify links
for _, link := range tt.resultLinks {
for _, link := range tt.resultPaths {
v, err := os.ReadFile(filepath.Join(linkDir, link))
require.NoError(t, err)
require.Equal(t, filepath.Base(link), string(v))
Expand All @@ -420,9 +447,235 @@ func TestLocalInstaller_Link(t *testing.T) {
}
}

func TestLocalInstaller_TryLink(t *testing.T) {
t.Parallel()
const version = "new-version"
servicePath := filepath.Join(serviceDir, serviceName)

tests := []struct {
name string
installDirs []string
installFiles []string
installFileMode os.FileMode
existingLinks []string
existingFiles []string

resultPaths []string
errMatch string
}{
{
name: "present with new links",
installDirs: []string{
"bin",
"bin/somedir",
"etc",
"etc/systemd",
"etc/systemd/somedir",
"somedir",
},
installFiles: []string{
"bin/teleport",
"bin/tsh",
"bin/tbot",
servicePath,
"README",
},
installFileMode: os.ModePerm,

resultPaths: []string{
"bin/teleport",
"bin/tsh",
"bin/tbot",
"lib/systemd/system/teleport.service",
},
},
{
name: "present with non-executable files",
installDirs: []string{
"bin",
"bin/somedir",
"etc",
"etc/systemd",
"etc/systemd/somedir",
"somedir",
},
installFiles: []string{
"bin/teleport",
"bin/tsh",
"bin/tbot",
servicePath,
"README",
},
installFileMode: 0644,

errMatch: "executable",
},
{
name: "present with existing links",
installDirs: []string{
"bin",
"bin/somedir",
"etc",
"etc/systemd",
"etc/systemd/somedir",
"somedir",
},
installFiles: []string{
"bin/teleport",
"bin/tsh",
"bin/tbot",
servicePath,
"README",
},
installFileMode: os.ModePerm,
existingLinks: []string{
"bin/teleport",
"bin/tsh",
"bin/tbot",
},
existingFiles: []string{
"lib/systemd/system/teleport.service",
},

errMatch: "refusing",
},
{
name: "conflicting systemd files",
installDirs: []string{
"bin",
"bin/somedir",
"etc",
"etc/systemd",
"etc/systemd/somedir",
"somedir",
},
installFiles: []string{
"bin/teleport",
"bin/tsh",
"bin/tbot",
servicePath,
"README",
},
installFileMode: os.ModePerm,
existingLinks: []string{
"lib/systemd/system/teleport.service",
},

errMatch: "replace irregular file",
},
{
name: "conflicting bin files",
installDirs: []string{
"bin",
"bin/somedir",
"etc",
"etc/systemd",
"etc/systemd/somedir",
"somedir",
},
installFiles: []string{
"bin/teleport",
"bin/tsh",
"bin/tbot",
servicePath,
"README",
},
installFileMode: os.ModePerm,
existingFiles: []string{
"bin/tsh",
},

errMatch: "replace file",
},
{
name: "no links",
installFiles: []string{"README"},
installDirs: []string{"bin"},

errMatch: "no binaries",
},
{
name: "no bin directory",
installFiles: []string{"README"},

errMatch: "binary directory",
},
}

for _, tt := range tests {
tt := tt
sclevine marked this conversation as resolved.
Show resolved Hide resolved
t.Run(tt.name, func(t *testing.T) {
versionsDir := t.TempDir()
versionDir := filepath.Join(versionsDir, version)
err := os.MkdirAll(versionDir, 0o755)
require.NoError(t, err)

// setup files in version directory
for _, d := range tt.installDirs {
err := os.Mkdir(filepath.Join(versionDir, d), os.ModePerm)
require.NoError(t, err)
}
for _, n := range tt.installFiles {
err := os.WriteFile(filepath.Join(versionDir, n), []byte(filepath.Base(n)), tt.installFileMode)
require.NoError(t, err)
}

// setup files in system links directory
linkDir := t.TempDir()
for _, n := range tt.existingLinks {
err := os.MkdirAll(filepath.Dir(filepath.Join(linkDir, n)), os.ModePerm)
require.NoError(t, err)
err = os.Symlink(filepath.Base(n)+".old", filepath.Join(linkDir, n))
require.NoError(t, err)
}
for _, n := range tt.existingFiles {
err := os.MkdirAll(filepath.Dir(filepath.Join(linkDir, n)), os.ModePerm)
require.NoError(t, err)
err = os.WriteFile(filepath.Join(linkDir, n), []byte(filepath.Base(n)), os.ModePerm)
require.NoError(t, err)
}

installer := &LocalInstaller{
InstallDir: versionsDir,
LinkBinDir: filepath.Join(linkDir, "bin"),
LinkServiceDir: filepath.Join(linkDir, "lib/systemd/system"),
Log: slog.Default(),
}
ctx := context.Background()
err = installer.TryLink(ctx, version)
if tt.errMatch != "" {
require.Error(t, err)
assert.Contains(t, err.Error(), tt.errMatch)

// verify no changes
for _, link := range tt.existingLinks {
v, err := os.Readlink(filepath.Join(linkDir, link))
require.NoError(t, err)
require.Equal(t, filepath.Base(link)+".old", v)
}
for _, n := range tt.existingFiles {
v, err := os.ReadFile(filepath.Join(linkDir, n))
require.NoError(t, err)
require.Equal(t, filepath.Base(n), string(v))
}
return
}
require.NoError(t, err)

// verify links
for _, link := range tt.resultPaths {
v, err := os.ReadFile(filepath.Join(linkDir, link))
require.NoError(t, err)
require.Equal(t, filepath.Base(link), string(v))
}
})
}
}

func TestLocalInstaller_Remove(t *testing.T) {
t.Parallel()
const version = "existing-version"
servicePath := filepath.Join(serviceDir, serviceName)

tests := []struct {
name string
Expand Down Expand Up @@ -457,8 +710,8 @@ func TestLocalInstaller_Remove(t *testing.T) {
},
{
name: "version linked",
dirs: []string{"bin", "bin/somedir", "somedir"},
files: []string{checksumType, "bin/teleport", "bin/tsh", "bin/tbot", "README"},
dirs: []string{"bin", "bin/somedir", "somedir", "etc", serviceDir},
files: []string{checksumType, "bin/teleport", "bin/tsh", "bin/tbot", "README", servicePath},
createVersion: version,
linkedVersion: version,
removeVersion: version,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: v1
kind: update_config
spec:
proxy: ""
group: ""
url_template: ""
enabled: false
status:
active_version: ""
backup_version: ""
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
version: v1
kind: update_config
spec:
proxy: ""
group: ""
url_template: ""
enabled: false
status:
active_version: ""
backup_version: ""
Loading
Loading