Skip to content

Commit

Permalink
Add e2e test with teleport
Browse files Browse the repository at this point in the history
  • Loading branch information
zoetrope committed Sep 20, 2024
1 parent de64a4d commit 3d2c43c
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 5 deletions.
5 changes: 3 additions & 2 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ on:
- 'main'
jobs:
test:
name: Tests
name: E2E Test
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
Expand All @@ -19,7 +19,7 @@ jobs:
- run: make lint
- run: make test-e2e
test-teleport:
name: Test with Teleport
name: E2E Test with Teleport
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
Expand All @@ -29,4 +29,5 @@ jobs:
- uses: ./.github/actions/aqua
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
- run: make setup-teleport-cli
- run: make test-teleport
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ test-e2e: start-kind load-image deploy

.PHONY: test-teleport # Run the e2e tests with Teleport.
test-teleport: start-kind-teleport load-image deploy-teleport
go test ./test/teleport/ -v -ginkgo.v

.PHONY: lint
lint: setup ## Run golangci-lint linter & yamllint
Expand Down Expand Up @@ -198,6 +199,5 @@ deploy-teleport:
kustomize build ./config/teleport | kubectl apply -f -
kubectl -n login-protector-system wait --for=condition=available --timeout=180s --all deployments

login:
kubectl get secret -n login-protector-system identity-output -o json | jq -r .data.identity | base64 -d > identity
./teleport/tsh -i ./identity --proxy --insecure localhost:3080 ssh cybozu@node-demo-0

19 changes: 19 additions & 0 deletions test/teleport/e2e_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package teleport

import (
"fmt"
"testing"
"time"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

// Run e2e tests with teleport using the Ginkgo runner.
func TestE2ETeleport(t *testing.T) {
RegisterFailHandler(Fail)
fmt.Fprintf(GinkgoWriter, "Starting login-protector with teleport suite\n")
SetDefaultEventuallyTimeout(30 * time.Second)
SetDefaultEventuallyPollingInterval(1 * time.Second)
RunSpecs(t, "e2e teleport suite")
}
86 changes: 86 additions & 0 deletions test/teleport/e2e_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package teleport

import (
"fmt"
"os/exec"
"time"

"github.com/creack/pty"
"github.com/cybozu-go/login-protector/test/utils"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
policyv1 "k8s.io/api/policy/v1"
)

const namespace = "login-protector-system"

var _ = Describe("controller", Ordered, func() {
Context("Operator", func() {
It("should run successfully", func() {
By("validating that the controller-manager pod is running as expected")
Eventually(func() error {
// Get pod name
pods := &corev1.PodList{}
err := utils.GetResource(namespace, "", pods, "-l", "control-plane=controller-manager")
ExpectWithOffset(2, err).NotTo(HaveOccurred())
if len(pods.Items) != 1 {
return fmt.Errorf("expect 1 controller pods running, but got %d", len(pods.Items))
}
controllerPod := pods.Items[0]
ExpectWithOffset(2, controllerPod.Name).Should(ContainSubstring("controller-manager"))

// Validate pod status
if string(controllerPod.Status.Phase) != "Running" {
return fmt.Errorf("controller pod in %s status", controllerPod.Status.Phase)
}
return nil
}).Should(Succeed())
})

const configuredPollingIntervalSeconds = 5
const testIntervalSeconds = configuredPollingIntervalSeconds + 2
const testInterval = time.Second * time.Duration(testIntervalSeconds)

It("should create PodDisruptionBudgets", func() {

// prepare a PTY to run ssh
ptmx, err := pty.Start(exec.Command("bash"))
Expect(err).NotTo(HaveOccurred())
defer ptmx.Close()

// make sure no PDB exists
pdbList := &policyv1.PodDisruptionBudgetList{}
err = utils.GetResource("teleport", "", pdbList, "--ignore-not-found")
Expect(err).NotTo(HaveOccurred())
Expect(pdbList.Items).Should(BeEmpty(), "unexpected pdb exists")

// login to node-demo-0 Pod using `tsh ssh`
go func() {
cmd := exec.Command("./teleport/tsh", "-i", "./identity", "--proxy", "localhost:3080", "--insecure", "ssh", "cybozu@node-demo-0", "sleep", fmt.Sprintf("%d", testIntervalSeconds))
cmd.Stdin = ptmx
_, err := utils.Run(cmd)
if err != nil {
panic(err)
}
}()

Eventually(func(g Gomega) {
// a PDB should be created for node-demo-0
err = utils.GetResource("teleport", "", pdbList, "--ignore-not-found")
g.Expect(err).NotTo(HaveOccurred())
g.Expect(pdbList.Items).Should(HaveLen(1), "expected pdb does not exist")
g.Expect(pdbList.Items[0].Name).Should(Equal("node-demo-0"))
g.Expect(pdbList.Items[0].Spec.Selector.MatchLabels["statefulset.kubernetes.io/pod-name"]).Should(Equal("node-demo-0"))
}).WithTimeout(testInterval).Should(Succeed())

Eventually(func(g Gomega) {
// the PDB should be deleted after the logout from the Pod
pdbList = &policyv1.PodDisruptionBudgetList{}
err = utils.GetResource("teleport", "", pdbList, "--ignore-not-found")
g.Expect(err).NotTo(HaveOccurred())
g.Expect(pdbList.Items).Should(BeEmpty(), "unexpected pdb exists")
}).WithTimeout(5 * time.Minute).Should(Succeed()) // Wait 5 minutes. Because it takes more than 3 minutes for teleport-session-tracker change the status.
})
})
})
4 changes: 3 additions & 1 deletion test/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"io"
"os"
"os/exec"
"regexp"
"strings"

"k8s.io/apimachinery/pkg/api/meta"
Expand Down Expand Up @@ -57,7 +58,8 @@ func GetProjectDir() (string, error) {
if err != nil {
return wd, err
}
wd = strings.Replace(wd, "/test/e2e", "", -1)
re := regexp.MustCompile("/test/.*")
wd = re.ReplaceAllString(wd, "")
return wd, nil
}

Expand Down

0 comments on commit 3d2c43c

Please sign in to comment.