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

[Backport] Google CloudBuild support (#9090) #9165

Merged
merged 6 commits into from
Dec 1, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
8 changes: 8 additions & 0 deletions .cloudbuild/ci/doc-tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
steps:
- name: quay.io/gravitational/next:main
id: docs-test
env:
- WITH_EXTERNAL_LINKS=true
dir: /src
args: ['yarn', 'remark', '/workspace/docs/pages/**/*.mdx', '--frail']
timeout: 10m
29 changes: 29 additions & 0 deletions .cloudbuild/ci/integration-tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
steps:
# Run non-root integration tests. The root user is selected by docker image.
- name: us-docker.pkg.dev/ci-account/teleport/buildbox-root:v0.1.0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose this is fine, but should we create a teleport8-v0.1.0 too?

id: root-integration-test
args: ['make', 'rdpclient', 'integration-root']
timeout: 10m

# Reconfigure the workspace for the non-root user
- name: us-docker.pkg.dev/ci-account/teleport/buildbox-root:v0.1.0
id: reconfigure-for-nonroot-user
args: ['chown', '-R', 'ci:ci', '/workspace']

# Run non-root integration tests. The non-root user is selected by docker image.
- name: us-docker.pkg.dev/ci-account/teleport/buildbox-nonroot:v0.1.0
id: nonroot-integration-test
env:
- TELEPORT_ETCD_TEST="yes"
entrypoint: '/bin/bash'
args:
- '-c'
- '(make run-etcd &); sleep 1; make integration'
timeout: 15m

timeout: 20m
options:
env:
- GOMODCACHE=/workspace/.gomodcacheci
machineType: E2_HIGHCPU_32

6 changes: 6 additions & 0 deletions .cloudbuild/ci/lint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
steps:
- name: us-docker.pkg.dev/ci-account/teleport/buildbox-root:v0.1.0
id: lint
args: ['make', 'lint-go', 'lint-api']
options:
machineType: 'E2_HIGHCPU_32'
14 changes: 14 additions & 0 deletions .cloudbuild/ci/unit-tests.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
steps:
- name: us-docker.pkg.dev/ci-account/teleport/buildbox-root:v0.1.0
id: unit-test
env:
- TELEPORT_ETCD_TEST="yes"
entrypoint: '/bin/bash'
args:
- '-c'
- '(make run-etcd &); sleep 1; make test'
timeout: 15m
timeout: 15m
options:
machineType: 'E2_HIGHCPU_32'

16 changes: 10 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -452,9 +452,9 @@ test-go: FLAGS ?= '-race'
test-go: PACKAGES := $(shell go list ./... | grep -v integration)
test-go: CHAOS_FOLDERS := $(shell find . -type f -name '*chaos*.go' -not -path '*/vendor/*' | xargs dirname | uniq)
test-go: $(VERSRC)
$(CGOFLAG) go test -p 4 -cover -json -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG) $(ROLETESTER_TAG) $(RDPCLIENT_TAG)" $(PACKAGES) $(FLAGS) $(ADDFLAGS) \
$(CGOFLAG) go test -cover -json -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG) $(ROLETESTER_TAG) $(RDPCLIENT_TAG)" $(PACKAGES) $(FLAGS) $(ADDFLAGS) \
| go run build.assets/render-tests/main.go
$(CGOFLAG) go test -p 4 -cover -json -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG) $(ROLETESTER_TAG) $(RDPCLIENT_TAG)" -test.run=TestChaos $(CHAOS_FOLDERS) \
$(CGOFLAG) go test -cover -json -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG) $(ROLETESTER_TAG) $(RDPCLIENT_TAG)" -test.run=TestChaos $(CHAOS_FOLDERS) \
| go run build.assets/render-tests/main.go

#
Expand All @@ -466,7 +466,7 @@ test-go-root: ensure-webassets bpf-bytecode roletester rdpclient
test-go-root: FLAGS ?= '-race'
test-go-root: PACKAGES := $(shell go list $(ADDFLAGS) ./... | grep -v integration)
test-go-root: $(VERSRC)
$(CGOFLAG) go test -p 4 -run "$(UNIT_ROOT_REGEX)" -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG) $(ROLETESTER_TAG) $(RDPCLIENT_TAG)" $(PACKAGES) $(FLAGS) $(ADDFLAGS)
$(CGOFLAG) go test -run "$(UNIT_ROOT_REGEX)" -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG) $(ROLETESTER_TAG) $(RDPCLIENT_TAG)" $(PACKAGES) $(FLAGS) $(ADDFLAGS)

# Runs API Go tests. These have to be run separately as the package name is different.
#
Expand All @@ -475,7 +475,7 @@ test-api:
test-api: FLAGS ?= '-race'
test-api: PACKAGES := $(shell cd api && go list ./...)
test-api: $(VERSRC)
$(CGOFLAG) go test -p 4 -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG) $(ROLETESTER_TAG)" $(PACKAGES) $(FLAGS) $(ADDFLAGS)
$(CGOFLAG) go test -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG) $(ROLETESTER_TAG)" $(PACKAGES) $(FLAGS) $(ADDFLAGS)

# Find and run all shell script unit tests (using https://github.com/bats-core/bats-core)
.PHONY: test-sh
Expand All @@ -487,6 +487,10 @@ test-sh:
fi; \
find . -iname "*.bats" -exec dirname {} \; | uniq | xargs -t -L1 bats $(BATSFLAGS)


.PHONY: run-etcd
run-etcd:
examples/etcd/start-etcd.sh
#
# Integration tests. Need a TTY to work.
# Any tests which need to run as root must be skipped during regular integration testing.
Expand All @@ -496,7 +500,7 @@ integration: FLAGS ?= -v -race
integration: PACKAGES := $(shell go list ./... | grep integration)
integration:
@echo KUBECONFIG is: $(KUBECONFIG), TEST_KUBE: $(TEST_KUBE)
$(CGOFLAG) go test -p 4 -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG) $(ROLETESTER_TAG) $(RDPCLIENT_TAG)" $(PACKAGES) $(FLAGS)
$(CGOFLAG) go test -timeout 30m -tags "$(PAM_TAG) $(FIPS_TAG) $(BPF_TAG) $(ROLETESTER_TAG) $(RDPCLIENT_TAG)" $(PACKAGES) $(FLAGS)

#
# Integration tests which need to be run as root in order to complete successfully
Expand All @@ -507,7 +511,7 @@ INTEGRATION_ROOT_REGEX := ^TestRoot
integration-root: FLAGS ?= -v -race
integration-root: PACKAGES := $(shell go list ./... | grep integration)
integration-root:
$(CGOFLAG) go test -p 4 -run "$(INTEGRATION_ROOT_REGEX)" $(PACKAGES) $(FLAGS)
$(CGOFLAG) go test -run "$(INTEGRATION_ROOT_REGEX)" $(PACKAGES) $(FLAGS)

#
# Lint the source code.
Expand Down
66 changes: 25 additions & 41 deletions integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1359,6 +1359,8 @@ func testTwoClustersTunnel(t *testing.T, suite *integrationTestSuite) {
twoClustersTunnel(t, suite, now, tt.inRecordLocation, tt.outExecCountSiteA, tt.outExecCountSiteB)
})
}

log.Info("Tests done. Cleaning up.")
}

func twoClustersTunnel(t *testing.T, suite *integrationTestSuite, now time.Time, proxyRecordMode string, execCountSiteA, execCountSiteB int) {
Expand Down Expand Up @@ -1409,11 +1411,13 @@ func twoClustersTunnel(t *testing.T, suite *integrationTestSuite, now time.Time,
require.NoError(t, a.Start())

// wait for both sites to see each other via their reverse tunnels (for up to 10 seconds)
abortTime := time.Now().Add(time.Second * 10)
for len(checkGetClusters(t, a.Tunnel)) < 2 && len(checkGetClusters(t, b.Tunnel)) < 2 {
time.Sleep(time.Millisecond * 200)
require.False(t, time.Now().After(abortTime), "Two clusters do not see each other: tunnels are not working.")
clustersAreCrossConnected := func() bool {
return len(checkGetClusters(t, a.Tunnel)) >= 2 && len(checkGetClusters(t, b.Tunnel)) >= 2
}
require.Eventually(t,
clustersAreCrossConnected,
10*time.Second /* waitFor */, 200*time.Millisecond, /* tick */
"Two clusters do not see each other: tunnels are not working.")

var (
outputA bytes.Buffer
Expand Down Expand Up @@ -1453,7 +1457,6 @@ func twoClustersTunnel(t *testing.T, suite *integrationTestSuite, now time.Time,
require.Len(t, parts, 3)

// The certs.pem file should have 2 certificates.

buffer, err = ioutil.ReadFile(keypaths.TLSCAsPath(tc.KeysDir, Host))
require.NoError(t, err)
roots := x509.NewCertPool()
Expand All @@ -1479,64 +1482,45 @@ func twoClustersTunnel(t *testing.T, suite *integrationTestSuite, now time.Time,
require.Equal(t, outputA.String(), outputB.String())

// Stop "site-A" and try to connect to it again via "site-A" (expect a connection error)
err = a.StopAuth(false)
require.NoError(t, err)
require.NoError(t, a.StopAuth(false))
err = tc.SSH(context.TODO(), cmd, false)
require.IsType(t, err, trace.ConnectionProblem(nil, ""))

// Reset and start "Site-A" again
err = a.Reset()
require.NoError(t, err)
err = a.Start()
require.NoError(t, err)
require.NoError(t, a.Reset())
require.NoError(t, a.Start())

// try to execute an SSH command using the same old client to Site-B
// "site-A" and "site-B" reverse tunnels are supposed to reconnect,
// and 'tc' (client) is also supposed to reconnect
for i := 0; i < 10; i++ {
time.Sleep(250 * time.Millisecond)
err = tc.SSH(context.TODO(), cmd, false)
if err == nil {
break
}
tcHasReconnected := func() bool {
return tc.SSH(context.TODO(), cmd, false) == nil
}
require.NoError(t, err)

searchAndAssert := func(site auth.ClientI, count int) error {
tickCh := time.Tick(500 * time.Millisecond)
stopCh := time.After(5 * time.Second)
require.Eventually(t, tcHasReconnected, 2500*time.Millisecond, 250*time.Millisecond,
"Timed out waiting for Site A to restart")

clientHasEvents := func(site auth.ClientI, count int) func() bool {
// only look for exec events
eventTypes := []string{events.ExecEvent}

for {
select {
case <-tickCh:
eventsInSite, _, err := site.SearchEvents(now, now.Add(1*time.Hour), apidefaults.Namespace, eventTypes, 0, types.EventOrderAscending, "")
if err != nil {
return trace.Wrap(err)
}

// found the number of events we were looking for
if got, want := len(eventsInSite), count; got == want {
return nil
}
case <-stopCh:
return trace.BadParameter("unable to find %v events after 5s", count)
}
return func() bool {
eventsInSite, _, err := site.SearchEvents(now, now.Add(1*time.Hour), apidefaults.Namespace, eventTypes, 0, types.EventOrderAscending, "")
require.NoError(t, err)
return len(eventsInSite) == count
}
}

siteA := a.GetSiteAPI(a.Secrets.SiteName)
err = searchAndAssert(siteA, execCountSiteA)
require.NoError(t, err)
require.Eventually(t, clientHasEvents(siteA, execCountSiteA), 5*time.Second, 500*time.Millisecond,
"Failed to find %d events on Site A after 5s", execCountSiteA)

siteB := b.GetSiteAPI(b.Secrets.SiteName)
err = searchAndAssert(siteB, execCountSiteB)
require.NoError(t, err)
require.Eventually(t, clientHasEvents(siteB, execCountSiteB), 5*time.Second, 500*time.Millisecond,
"Failed to find %d events on Site B after 5s", execCountSiteB)

// stop both sites for real
require.NoError(t, b.StopAll())

require.NoError(t, a.StopAll())
}

Expand Down
6 changes: 3 additions & 3 deletions lib/srv/uacc/uacc_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ const userMaxLen = 32
//
// `username`: Name of the user the interactive session is running under.
// `hostname`: Name of the system the user is logged into.
// `remoteAddrV6`: IPv6 address of the remote host.
// `ttyName`: Name of the TTY including the `/dev/` prefix.
// `remote`: IPv6 address of the remote host.
// `tty`: Pointer to the tty stream
func Open(utmpPath, wtmpPath string, username, hostname string, remote [4]int32, tty *os.File) error {
ttyName, err := os.Readlink(tty.Name())
if err != nil {
Expand Down Expand Up @@ -118,7 +118,7 @@ func Open(utmpPath, wtmpPath string, username, hostname string, remote [4]int32,
return trace.NotFound("user accounting files are missing from the system, running in a container?")
default:
if status != 0 {
return trace.Errorf("unknown error with code %d", status)
return trace.Errorf("unknown error with errno %d", C.get_errno())
}

return nil
Expand Down