Skip to content

Commit

Permalink
Improve integration tests to execute with tsh and tctl
Browse files Browse the repository at this point in the history
Added a full-cycle integration test to verify client tools
auto-updates within a test cluster by modifying AutoUpdateConfig
and AutoUpdateVersion resources. The test executes the login
command using alias configurations to ensure no recursive
re-execution occurs.

The updater binary used in integration tests has been replaced
with the `Run` logic of tctl and tsh.
  • Loading branch information
vapopov committed Dec 25, 2024
1 parent 8daa3d5 commit 894aab9
Show file tree
Hide file tree
Showing 12 changed files with 385 additions and 131 deletions.
17 changes: 10 additions & 7 deletions integration/autoupdate/tools/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (

"github.com/gravitational/teleport/api/constants"
"github.com/gravitational/teleport/integration/helpers/archive"
"github.com/gravitational/teleport/lib/modules"
)

const (
Expand All @@ -59,6 +60,7 @@ var (
)

func TestMain(m *testing.M) {
modules.SetInsecureTestMode(true)
ctx := context.Background()
tmp, err := os.MkdirTemp(os.TempDir(), testBinaryName)
if err != nil {
Expand Down Expand Up @@ -139,7 +141,7 @@ func buildAndArchiveApps(ctx context.Context, path string, toolsDir string, vers
case constants.DarwinOS:
output = filepath.Join(versionPath, app+".app", "Contents", "MacOS", app)
}
if err := buildBinary(output, toolsDir, version, baseURL); err != nil {
if err := buildBinary(output, toolsDir, version, baseURL, app); err != nil {
return trace.Wrap(err)
}
}
Expand All @@ -156,16 +158,17 @@ func buildAndArchiveApps(ctx context.Context, path string, toolsDir string, vers
}
}

// buildBinary executes command to build binary with updater logic only for testing.
func buildBinary(output string, toolsDir string, version string, baseURL string) error {
// buildBinary executes command to build client tool binary with updater logic for testing.
func buildBinary(output string, toolsDir string, version string, baseURL string, app string) error {
cmd := exec.Command(
"go", "build", "-o", output,
"-ldflags", strings.Join([]string{
fmt.Sprintf("-X 'main.toolsDir=%s'", toolsDir),
fmt.Sprintf("-X 'main.version=%s'", version),
fmt.Sprintf("-X 'main.baseURL=%s'", baseURL),
fmt.Sprintf("-X 'github.com/gravitational/teleport/integration/autoupdate/tools/updater.version=%s'", version),
fmt.Sprintf("-X 'github.com/gravitational/teleport/lib/autoupdate/tools.toolsDir=%s'", toolsDir),
fmt.Sprintf("-X 'github.com/gravitational/teleport/lib/autoupdate/tools.version=%s'", version),
fmt.Sprintf("-X 'github.com/gravitational/teleport/lib/autoupdate/tools.baseURL=%s'", baseURL),
}, " "),
"./updater",
fmt.Sprintf("./updater/%s", app),
)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
Expand Down
78 changes: 0 additions & 78 deletions integration/autoupdate/tools/updater/main.go

This file was deleted.

107 changes: 107 additions & 0 deletions integration/autoupdate/tools/updater/modules.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
* Teleport
* Copyright (C) 2024 Gravitational, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package updater

import (
"context"
"crypto"
"fmt"
"time"

"github.com/gravitational/trace"

"github.com/gravitational/teleport"
"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/api/types/accesslist"
"github.com/gravitational/teleport/api/utils/keys"
"github.com/gravitational/teleport/entitlements"
"github.com/gravitational/teleport/lib/modules"
"github.com/gravitational/teleport/lib/tlsca"
)

const (
TestPassword = "abc123def456"
)

var (
version = teleport.Version
)

type TestModules struct{}

func (p *TestModules) GenerateAccessRequestPromotions(context.Context, modules.AccessResourcesGetter, types.AccessRequest) (*types.AccessRequestAllowedPromotions, error) {
return &types.AccessRequestAllowedPromotions{}, nil
}

func (p *TestModules) GetSuggestedAccessLists(context.Context, *tlsca.Identity, modules.AccessListSuggestionClient, modules.AccessListAndMembersGetter, string) ([]*accesslist.AccessList, error) {
return []*accesslist.AccessList{}, nil
}

// BuildType returns build type (OSS or Enterprise)
func (p *TestModules) BuildType() string {
return "CLI"
}

// IsEnterpriseBuild returns false for [TestModules].
func (p *TestModules) IsEnterpriseBuild() bool {
return false
}

// IsOSSBuild returns false for [TestModules].
func (p *TestModules) IsOSSBuild() bool {
return false
}

// LicenseExpiry returns the expiry date of the enterprise license, if applicable.
func (p *TestModules) LicenseExpiry() time.Time {
return time.Time{}
}

// PrintVersion prints the Teleport version.
func (p *TestModules) PrintVersion() {
fmt.Printf("Teleport v%v git\n", version)
}

// Features returns supported features
func (p *TestModules) Features() modules.Features {
return modules.Features{
Entitlements: map[entitlements.EntitlementKind]modules.EntitlementInfo{},
AdvancedAccessWorkflows: true,
}
}

// IsBoringBinary checks if the binary was compiled with BoringCrypto.
func (p *TestModules) IsBoringBinary() bool {
return false
}

// AttestHardwareKey attests a hardware key.
func (p *TestModules) AttestHardwareKey(context.Context, interface{}, *keys.AttestationStatement, crypto.PublicKey, time.Duration) (*keys.AttestationData, error) {
return nil, trace.NotFound("no attestation data for the given key")
}

func (p *TestModules) EnableRecoveryCodes() {}

func (p *TestModules) EnablePlugins() {}

func (p *TestModules) SetFeatures(f modules.Features) {}

func (p *TestModules) EnableAccessGraph() {}

func (p *TestModules) EnableAccessMonitoring() {}
38 changes: 38 additions & 0 deletions integration/autoupdate/tools/updater/tctl/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
* Teleport
* Copyright (C) 2024 Gravitational, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package main

import (
"context"

"github.com/gravitational/teleport/integration/autoupdate/tools/updater"
"github.com/gravitational/teleport/lib/modules"
stacksignal "github.com/gravitational/teleport/lib/utils/signal"
tctl "github.com/gravitational/teleport/tool/tctl/common"
)

func main() {
ctx, cancel := stacksignal.GetSignalHandler().NotifyContext(context.Background())
defer cancel()

modules.SetInsecureTestMode(true)
modules.SetModules(&updater.TestModules{})

tctl.Run(ctx, tctl.Commands())
}
45 changes: 45 additions & 0 deletions integration/autoupdate/tools/updater/tsh/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Teleport
* Copyright (C) 2024 Gravitational, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package main

import (
"context"
"os"

"github.com/gravitational/teleport/api/utils/prompt"
"github.com/gravitational/teleport/integration/autoupdate/tools/updater"
"github.com/gravitational/teleport/lib/modules"
"github.com/gravitational/teleport/lib/utils"
stacksignal "github.com/gravitational/teleport/lib/utils/signal"
tsh "github.com/gravitational/teleport/tool/tsh/common"
)

func main() {
ctx, cancel := stacksignal.GetSignalHandler().NotifyContext(context.Background())
defer cancel()

modules.SetInsecureTestMode(true)
modules.SetModules(&updater.TestModules{})
prompt.SetStdin(prompt.NewFakeReader().AddString(updater.TestPassword))

err := tsh.Run(ctx, os.Args[1:])
if err != nil {
utils.FatalError(err)
}
}
6 changes: 5 additions & 1 deletion integration/autoupdate/tools/updater_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/gravitational/teleport/api/types"
"github.com/gravitational/teleport/lib/autoupdate/tools"
)

Expand All @@ -44,6 +45,7 @@ var (
// TestUpdate verifies the basic update logic. We first download a lower version, then request
// an update to a newer version, expecting it to re-execute with the updated version.
func TestUpdate(t *testing.T) {
t.Setenv(types.HomeEnvVar, t.TempDir())
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()

Expand All @@ -57,7 +59,7 @@ func TestUpdate(t *testing.T) {
require.NoError(t, err)

// Verify that the installed version is equal to requested one.
cmd := exec.CommandContext(ctx, filepath.Join(toolsDir, "tsh"), "version")
cmd := exec.CommandContext(ctx, filepath.Join(toolsDir, "tctl"), "version")
out, err := cmd.Output()
require.NoError(t, err)

Expand Down Expand Up @@ -85,6 +87,7 @@ func TestUpdate(t *testing.T) {
// first update is complete, other processes should acquire the lock one by one and re-execute
// the command with the updated version without any new downloads.
func TestParallelUpdate(t *testing.T) {
t.Setenv(types.HomeEnvVar, t.TempDir())
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()

Expand Down Expand Up @@ -158,6 +161,7 @@ func TestParallelUpdate(t *testing.T) {

// TestUpdateInterruptSignal verifies the interrupt signal send to the process must stop downloading.
func TestUpdateInterruptSignal(t *testing.T) {
t.Setenv(types.HomeEnvVar, t.TempDir())
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()

Expand Down
Loading

0 comments on commit 894aab9

Please sign in to comment.