tests/connector_enrollment_test.go
Rama master · réplica de lectura del repositorio original.
package main
import (
"context"
"io"
"strings"
"testing"
"github.com/shellhub-io/shellhub/pkg/models"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/testcontainers/testcontainers-go"
)
// TestConnectorEnrollment covers what a connector reports for the containers it serves when they
// ask to join: the identity and name each one carries, and which containers it serves at all.
func TestConnectorEnrollment(t *testing.T) {
t.Parallel()
t.Run("a container asks to join under the first 12 characters of its ID", func(t *testing.T) {
t.Parallel()
compose := newSSHEnvironment(t, t.Context(), legacyNamespace)
name := "identity-" + randomHex(t)
target := startLabelledContainer(t, t.Context(), name)
startConnector(t, t.Context(), compose, connectorLabel+"="+name)
pending := awaitContainerWithStatus(t, compose, models.DeviceStatusPending)
require.NotNil(t, pending.Identity)
assert.Equal(t, target.GetContainerID()[:12], pending.Identity.MAC)
})
t.Run("a connector given a provisioning key enrolls its containers into a new namespace", func(t *testing.T) {
t.Parallel()
compose := newSSHEnvironment(t, t.Context(), newNamespace)
name := "keyed-" + randomHex(t)
startLabelledContainer(t, t.Context(), name)
startConnectorWithEnv(t, t.Context(), compose, connectorLabel+"="+name, map[string]string{
"SHELLHUB_TENANT_ID": "",
"SHELLHUB_PROVISIONING_KEY": requireHarnessProvisioningKey(t, compose),
})
pending := awaitContainerWithStatus(t, compose, models.DeviceStatusPending)
assert.Equal(t, compose.ProvisioningKey(t, harnessProvisioningKeyName).ID, pending.ProvisioningKeyID)
})
t.Run("a container's name has its dots replaced by underscores and is cut to 64 characters", func(t *testing.T) {
t.Parallel()
compose := newSSHEnvironment(t, t.Context(), legacyNamespace)
value := randomHex(t)
name := "sanitized." + value + "." + strings.Repeat("x", 64)
startIdleContainer(t, t.Context(), name, map[string]string{connectorLabel: value})
connector := startConnector(t, t.Context(), compose, connectorLabel+"="+value)
sanitized := "sanitized_" + value + "_" + strings.Repeat("x", 41)
pending := awaitContainerWithStatus(t, compose, models.DeviceStatusPending)
assert.Equal(t, sanitized, pending.Name)
assert.Contains(t, containerLogs(t, t.Context(), connector), "hostname="+sanitized, "the connector left the dots for the server to replace")
})
t.Run("a container without the connector's label is left out", func(t *testing.T) {
t.Parallel()
ctx := t.Context()
compose := newSSHEnvironment(t, ctx, legacyNamespace)
value := randomHex(t)
runningBefore := startIdleContainer(t, ctx, "unlabelled-before-"+value, nil)
otherValue := startIdleContainer(t, ctx, "other-value-"+value, map[string]string{connectorLabel: "other-" + value})
startIdleContainer(t, ctx, "labelled-before-"+value, map[string]string{connectorLabel: value})
connector := startConnector(t, ctx, compose, connectorLabel+"="+value)
awaitContainerWithStatus(t, compose, models.DeviceStatusPending)
startedAfter := startIdleContainer(t, ctx, "unlabelled-after-"+value, nil)
barrier := startIdleContainer(t, ctx, "labelled-after-"+value, map[string]string{connectorLabel: value})
names := []string{}
for _, c := range awaitContainersWithStatus(t, compose, models.DeviceStatusPending, 2) {
names = append(names, c.Name)
}
assert.ElementsMatch(t, []string{"labelled-before-" + value, "labelled-after-" + value}, names)
logs := containerLogs(t, ctx, connector)
require.Contains(t, logs, barrier.GetContainerID()[:12], "the connector never started serving the container started after it")
for _, left := range []testcontainers.Container{runningBefore, otherValue, startedAfter} {
assert.NotContains(t, logs, left.GetContainerID()[:12], "the connector served a container outside its label")
}
})
}
func containerLogs(t *testing.T, ctx context.Context, c testcontainers.Container) string {
t.Helper()
reader, err := c.Logs(ctx)
require.NoError(t, err)
defer reader.Close() //nolint:errcheck // the logs were read in full
logs, err := io.ReadAll(reader)
require.NoError(t, err)
return string(logs)
}