Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
31 changes: 20 additions & 11 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,49 @@
# Build with commit: podman build --build-arg GIT_COMMIT=$(git rev-parse HEAD) -t quay.io/hyperfleet/hyperfleet-e2e:latest .
# Run: podman run --rm -e HYPERFLEET_API_URL=<url> quay.io/hyperfleet/hyperfleet-e2e:latest test

ARG BASE_IMAGE=gcr.io/distroless/static-debian12:nonroot
ARG BASE_IMAGE=registry.access.redhat.com/ubi9/go-toolset

# Build stage
FROM golang:1.25-alpine AS builder
FROM golang:1.25 AS builder

# Build arguments passed from build machine
ARG GIT_COMMIT=unknown
WORKDIR /build

# Install build dependencies
RUN apk add --no-cache make curl
RUN apt-get update && apt-get install -y --no-install-recommends make curl && rm -rf /var/lib/apt/lists/*

WORKDIR /build
# Download kubectl (stable version)
RUN mkdir -p /build/bin && \
curl -fsSL "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" \
-o /build/bin/kubectl

# Copy source code
COPY . .

# Build binary using make to include commit and build date
ARG GIT_COMMIT=unknown
RUN make build GIT_COMMIT=${GIT_COMMIT}

RUN chmod +x /build/bin/*

# Runtime stage
FROM ${BASE_IMAGE}

WORKDIR /app
# Install runtime dependencies
USER root
RUN dnf -y install jq gettext && dnf clean all

WORKDIR /e2e

# Copy binary from builder (make build outputs to bin/)
COPY --from=builder /build/bin/hyperfleet-e2e /app/hyperfleet-e2e
COPY --from=builder /build/bin/* /usr/local/bin/

# Copy test payloads and fixtures
COPY --from=builder /build/testdata /app/testdata
COPY --from=builder /build/testdata /e2e/testdata

# Copy default config (fallback if ConfigMap is not mounted)
COPY --from=builder /build/configs /app/configs
COPY --from=builder /build/configs /e2e/configs

ENTRYPOINT ["/app/hyperfleet-e2e"]
ENTRYPOINT ["/usr/local/bin/hyperfleet-e2e"]
CMD ["test", "--help"]

LABEL name="hyperfleet-e2e" \
Expand Down
70 changes: 36 additions & 34 deletions e2e/cluster/creation.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
. "github.com/onsi/gomega" //nolint:staticcheck // dot import for test readability

"github.com/openshift-hyperfleet/hyperfleet-e2e/pkg/api/openapi"
"github.com/openshift-hyperfleet/hyperfleet-e2e/pkg/client"
"github.com/openshift-hyperfleet/hyperfleet-e2e/pkg/helper"
"github.com/openshift-hyperfleet/hyperfleet-e2e/pkg/labels"
)
Expand Down Expand Up @@ -36,39 +35,42 @@ var _ = ginkgo.Describe(lifecycleTestName,

Expect(cluster.Status).NotTo(BeNil(), "cluster status should be present")
Expect(cluster.Status.Phase).To(Equal(openapi.NotReady), "cluster should be in NotReady phase initially")

ginkgo.By("monitoring cluster status - waiting for phase transition to Ready")
err = h.WaitForClusterPhase(ctx, clusterID, openapi.Ready, h.Cfg.Timeouts.Cluster.Ready)
Expect(err).NotTo(HaveOccurred(), "cluster should reach Ready phase")

ginkgo.By("verifying all adapter conditions via /clusters/{id}/statuses endpoint")
const expectedAdapterCount = 1 // GCP cluster expects 1 adapter
Eventually(func(g Gomega) {
statuses, err := h.Client.GetClusterStatuses(ctx, clusterID)
g.Expect(err).NotTo(HaveOccurred(), "failed to get cluster statuses")
g.Expect(statuses.Items).To(HaveLen(expectedAdapterCount),
"expected %d adapter(s), got %d", expectedAdapterCount, len(statuses.Items))

for _, adapter := range statuses.Items {
hasApplied := h.HasCondition(adapter.Conditions, client.ConditionTypeApplied, openapi.True)
g.Expect(hasApplied).To(BeTrue(),
"adapter %s should have Applied=True", adapter.Adapter)

hasAvailable := h.HasCondition(adapter.Conditions, client.ConditionTypeAvailable, openapi.True)
g.Expect(hasAvailable).To(BeTrue(),
"adapter %s should have Available=True", adapter.Adapter)

hasHealth := h.HasCondition(adapter.Conditions, client.ConditionTypeHealth, openapi.True)
g.Expect(hasHealth).To(BeTrue(),
"adapter %s should have Health=True", adapter.Adapter)
}
}, h.Cfg.Timeouts.Adapter.Processing, h.Cfg.Polling.Interval).Should(Succeed())

ginkgo.By("verifying final cluster state")
finalCluster, err := h.Client.GetCluster(ctx, clusterID)
Expect(err).NotTo(HaveOccurred(), "failed to get final cluster state")
Expect(finalCluster.Status).NotTo(BeNil(), "cluster status should be present")
Expect(finalCluster.Status.Phase).To(Equal(openapi.Ready), "cluster phase should be Ready")
/** <TODO>
Cluster final status depends on all deployed adapter result, this is still in progress.
Will update this part once adapter scope is finalized.
ginkgo.By("monitoring cluster status - waiting for phase transition to Ready")
err = h.WaitForClusterPhase(ctx, clusterID, openapi.Ready, h.Cfg.Timeouts.Cluster.Ready)
Expect(err).NotTo(HaveOccurred(), "cluster should reach Ready phase")

ginkgo.By("verifying all adapter conditions via /clusters/{id}/statuses endpoint")
const expectedAdapterCount = 1 // GCP cluster expects 1 adapter
Eventually(func(g Gomega) {
statuses, err := h.Client.GetClusterStatuses(ctx, clusterID)
g.Expect(err).NotTo(HaveOccurred(), "failed to get cluster statuses")
g.Expect(statuses.Items).To(HaveLen(expectedAdapterCount),
"expected %d adapter(s), got %d", expectedAdapterCount, len(statuses.Items))

for _, adapter := range statuses.Items {
hasApplied := h.HasCondition(adapter.Conditions, client.ConditionTypeApplied, openapi.True)
g.Expect(hasApplied).To(BeTrue(),
"adapter %s should have Applied=True", adapter.Adapter)

hasAvailable := h.HasCondition(adapter.Conditions, client.ConditionTypeAvailable, openapi.True)
g.Expect(hasAvailable).To(BeTrue(),
"adapter %s should have Available=True", adapter.Adapter)

hasHealth := h.HasCondition(adapter.Conditions, client.ConditionTypeHealth, openapi.True)
g.Expect(hasHealth).To(BeTrue(),
"adapter %s should have Health=True", adapter.Adapter)
}
}, h.Cfg.Timeouts.Adapter.Processing, h.Cfg.Polling.Interval).Should(Succeed())

ginkgo.By("verifying final cluster state")
finalCluster, err := h.Client.GetCluster(ctx, clusterID)
Expect(err).NotTo(HaveOccurred(), "failed to get final cluster state")
Expect(finalCluster.Status).NotTo(BeNil(), "cluster status should be present")
Expect(finalCluster.Status.Phase).To(Equal(openapi.Ready), "cluster phase should be Ready")
**/
})

ginkgo.AfterEach(func(ctx context.Context) {
Expand Down
2 changes: 1 addition & 1 deletion e2e/nodepool/creation.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
var lifecycleTestName = "[Suite: nodepool] Full NodePool Creation Flow"

var _ = ginkgo.Describe(lifecycleTestName,
ginkgo.Label(labels.Tier0),
ginkgo.Label(labels.Tier1),
func() {
var h *helper.Helper
var clusterID string
Expand Down