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

Test e2e fixes #694

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
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
268 changes: 268 additions & 0 deletions .github/workflows/test_e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
name: CI
on:
pull_request:
types:
- labeled
- opened
- synchronize
- reopened
paths-ignore:
- 'config/**'
- '**.md'
push:
tags:
- '*'

env:
GO_VERSION: '1.22'
REGISTRY_REPO: 'oci://ghcr.io/mirantis/hmc/charts-ci'

jobs:
build:
concurrency:
group: build-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
name: Build and Unit Test
runs-on: ubuntu-latest
outputs:
version: ${{ steps.vars.outputs.version }}
clustername: ${{ steps.vars.outputs.clustername }}
pr: ${{ steps.pr.outputs.result }}
steps:
- name: Get PR ref
uses: actions/github-script@v7
id: pr
with:
script: |
const { data: pullRequest } = await github.rest.pulls.get({
...context.repo,
pull_number: context.payload.pull_request.number,
});
return pullRequest
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: ${{fromJSON(steps.pr.outputs.result).merge_commit_sha}}
fetch-depth: 0
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache: false
- name: Lint
run: GOLANGCI_LINT_TIMEOUT=10m make lint
- name: Verify all generated pieces are up-to-date
run: make generate-all && git add -N . && git diff --exit-code
- name: Unit tests
run: |
make test
- name: Set up Buildx
uses: docker/setup-buildx-action@v3
- name: Login to GHCR
uses: docker/[email protected]
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Get outputs
id: vars
run: |
GIT_VERSION=$(git describe --tags --always)
echo "version=${GIT_VERSION:1}" >> $GITHUB_OUTPUT
echo "clustername=ci-$(date +%s | cut -b6-10)" >> $GITHUB_OUTPUT
- name: Build and push HMC controller image
uses: docker/build-push-action@v6
with:
build-args: |
LD_FLAGS=-s -w -X github.com/Mirantis/hmc/internal/build.Version=${{ steps.vars.outputs.version }}
context: .
platforms: linux/amd64
tags: |
ghcr.io/mirantis/hmc/controller-ci:${{ steps.vars.outputs.version }}
push: true
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Prepare and push HMC template charts
run: |
make hmc-chart-release
make helm-push

controller-e2etest:
name: E2E Controller
runs-on: ubuntu-latest
needs: build
concurrency:
group: controller-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
outputs:
clustername: ${{ needs.build.outputs.clustername }}
version: ${{ needs.build.outputs.version }}
pr: ${{ needs.build.outputs.pr }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{fromJSON(needs.build.outputs.pr).merge_commit_sha}}
- name: Setup kubectl
uses: azure/setup-kubectl@v4
- name: Run E2E tests
env:
GINKGO_LABEL_FILTER: 'controller'
MANAGED_CLUSTER_NAME: ${{ needs.build.outputs.clustername }}
IMG: 'ghcr.io/mirantis/hmc/controller-ci:${{ needs.build.outputs.version }}'
VERSION: ${{ needs.build.outputs.version }}
run: |
make test-e2e
- name: Archive test results
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: cloud-e2etest-logs
path: |
test/e2e/*.log

provider-cloud-e2etest:
name: E2E Cloud Providers
runs-on: ubuntu-latest
if: ${{ contains( github.event.pull_request.labels.*.name, 'test e2e') }}
needs: build
concurrency:
group: cloud-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
outputs:
clustername: ${{ needs.build.outputs.clustername }}
version: ${{ needs.build.outputs.version }}
pr: ${{ needs.build.outputs.pr }}
env:
AWS_REGION: us-west-2
AWS_ACCESS_KEY_ID: ${{ secrets.CI_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CI_AWS_SECRET_ACCESS_KEY }}
AZURE_REGION: westus2
AZURE_SUBSCRIPTION_ID: ${{ secrets.CI_AZURE_SUBSCRIPTION_ID }}
AZURE_TENANT_ID: ${{ secrets.CI_AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.CI_AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.CI_AZURE_CLIENT_SECRET }}
steps:
- name: Setup tmate session
uses: mxschmitt/action-tmate@v3
with:
detached: true
timeout-minutes: 90
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{fromJSON(needs.build.outputs.pr).merge_commit_sha}}
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Setup kubectl
uses: azure/setup-kubectl@v4
- uses: actions/checkout@v4
- name: Run E2E tests
env:
GINKGO_LABEL_FILTER: 'provider:cloud'
MANAGED_CLUSTER_NAME: ${{ needs.build.outputs.clustername }}
IMG: 'ghcr.io/mirantis/hmc/controller-ci:${{ needs.build.outputs.version }}'
VERSION: ${{ needs.build.outputs.version }}
run: |
make test-e2e
- name: Archive test results
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: cloud-e2etest-logs
path: |
test/e2e/*.log

provider-onprem-e2etest:
name: E2E On-Prem Providers
runs-on: self-hosted
if: ${{ contains( github.event.pull_request.labels.*.name, 'test e2e') }}
needs: build
concurrency:
group: onprem-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
outputs:
clustername: ${{ needs.build.outputs.clustername }}
version: ${{ needs.build.outputs.version }}
pr: ${{ needs.build.outputs.pr }}
env:
VSPHERE_USER: ${{ secrets.CI_VSPHERE_USER }}
VSPHERE_PASSWORD: ${{ secrets.CI_VSPHERE_PASSWORD }}
VSPHERE_SERVER: ${{ secrets.CI_VSPHERE_SERVER }}
VSPHERE_THUMBPRINT: ${{ secrets.CI_VSPHERE_THUMBPRINT }}
VSPHERE_DATACENTER: ${{ secrets.CI_VSPHERE_DATACENTER }}
VSPHERE_DATASTORE: ${{ secrets.CI_VSPHERE_DATASTORE }}
VSPHERE_RESOURCEPOOL: ${{ secrets.CI_VSPHERE_RESOURCEPOOL }}
VSPHERE_FOLDER: ${{ secrets.CI_VSPHERE_FOLDER }}
VSPHERE_CONTROL_PLANE_ENDPOINT: ${{ secrets.CI_VSPHERE_CONTROL_PLANE_ENDPOINT }}
VSPHERE_VM_TEMPLATE: ${{ secrets.CI_VSPHERE_VM_TEMPLATE }}
VSPHERE_NETWORK: ${{ secrets.CI_VSPHERE_NETWORK }}
VSPHERE_SSH_KEY: ${{ secrets.CI_VSPHERE_SSH_KEY }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{fromJSON(needs.build.outputs.pr).merge_commit_sha}}
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: Setup kubectl
uses: azure/setup-kubectl@v4
- name: Run E2E tests
env:
GINKGO_LABEL_FILTER: 'provider:onprem'
MANAGED_CLUSTER_NAME: ${{ needs.build.outputs.clustername }}
IMG: 'ghcr.io/mirantis/hmc/controller-ci:${{ needs.build.outputs.version }}'
VERSION: ${{ needs.build.outputs.version }}
run: |
make test-e2e
- name: Archive test results
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: onprem-e2etest-logs
path: |
test/e2e/*.log

cleanup:
name: Cleanup
needs:
- build
- provider-cloud-e2etest
runs-on: ubuntu-latest
if: ${{ always() && !contains(needs.provider-cloud-e2etest.result, 'skipped') && contains(needs.build.result, 'success') }}
timeout-minutes: 15
outputs:
clustername: ${{ needs.build.outputs.clustername }}
version: ${{ needs.build.outputs.version }}
pr: ${{ needs.build.outputs.pr }}
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
ref: ${{fromJSON(needs.build.outputs.pr).merge_commit_sha}}
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
- name: AWS Test Resources
env:
AWS_REGION: us-west-2
AWS_ACCESS_KEY_ID: ${{ secrets.CI_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CI_AWS_SECRET_ACCESS_KEY }}
AZURE_REGION: westus2
AZURE_SUBSCRIPTION_ID: ${{ secrets.CI_AZURE_SUBSCRIPTION_ID }}
AZURE_TENANT_ID: ${{ secrets.CI_AZURE_TENANT_ID }}
AZURE_CLIENT_ID: ${{ secrets.CI_AZURE_CLIENT_ID }}
AZURE_CLIENT_SECRET: ${{ secrets.CI_AZURE_CLIENT_SECRET }}
CLUSTER_NAME: '${{ needs.build.outputs.clustername }}'
run: |
make dev-aws-nuke
make dev-azure-nuke
31 changes: 28 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,33 @@ set-hmc-version: yq
$(YQ) eval '.metadata.name = "hmc-$(FQDN_VERSION)"' -i $(PROVIDER_TEMPLATES_DIR)/hmc-templates/files/release.yaml
$(YQ) eval '.spec.hmc.template = "hmc-$(FQDN_VERSION)"' -i $(PROVIDER_TEMPLATES_DIR)/hmc-templates/files/release.yaml

.PHONY: test-hmc-version
test-hmc-version: yq
@TEMPLATE_DIR=templates/provider/hmc-templates/files/templates/*; \
cutversion=$$(echo $(VERSION) | sed "s/.*-//g"); \
echo "cutversion = $cutversion"; \
for template in $$TEMPLATE_DIR; do \
if [ $$($(YQ) eval '.kind' $$template) = 'ClusterTemplate' ]; then \
if grep --quiet "chartVersion:.*-"$$cutversion $$template; then \
echo "skipping already processed templates $$template"; \
else \
echo $$template; \
sed -i "s/chartVersion:.*[^$$cutversion].*/&-$$cutversion/g" "$$template"; \
fi \
fi; \
done; \
CHART_DIR=templates/cluster/**/Chart.yaml; \
for chart in $$CHART_DIR; do \
if grep --quiet "version:.*-$$cutversion" $$chart; then \
echo "skipping already processed templates $$chart"; \
else \
echo $$chart; \
sed -i "s/version:.*[^$$cutversion]*./&-$$cutversion/g" "$$chart"; \
fi \
done

.PHONY: hmc-chart-release
hmc-chart-release: set-hmc-version templates-generate ## Generate hmc helm chart
hmc-chart-release: set-hmc-version test-hmc-version templates-generate ## Generate hmc helm chart

.PHONY: hmc-dist-release
hmc-dist-release: $(HELM) $(YQ)
Expand Down Expand Up @@ -110,7 +135,7 @@ test: generate-all fmt vet envtest tidy external-crd ## Run tests.

# Utilize Kind or modify the e2e tests to load the image locally, enabling
# compatibility with other vendors.
.PHONY: test-e2e # Run the e2e tests using a Kind k8s instance as the management cluster.
.PHONY: test-e2e test-hmc-version# Run the e2e tests using a Kind k8s instance as the management cluster.
test-e2e: cli-install
@if [ "$$GINKGO_LABEL_FILTER" ]; then \
ginkgo_label_flag="-ginkgo.label-filter=$$GINKGO_LABEL_FILTER"; \
Expand Down Expand Up @@ -347,7 +372,7 @@ dev-eks-creds: dev-aws-creds
dev-apply: kind-deploy registry-deploy dev-push dev-deploy dev-templates dev-release

.PHONY: test-apply
test-apply: set-hmc-version helm-package dev-deploy dev-templates dev-release
test-apply: set-hmc-version test-hmc-version helm-package dev-deploy dev-templates dev-release

.PHONY: dev-destroy
dev-destroy: kind-undeploy registry-undeploy ## Destroy the development environment by deleting the kind cluster and local registry.
Expand Down
24 changes: 20 additions & 4 deletions test/e2e/e2e_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
. "github.com/onsi/gomega"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/utils/env"
"k8s.io/utils/ptr"

internalutils "github.com/Mirantis/hmc/internal/utils"
Expand All @@ -48,12 +49,15 @@ func TestE2E(t *testing.T) {
var _ = BeforeSuite(func() {
GinkgoT().Setenv(managedcluster.EnvVarNamespace, internalutils.DefaultSystemNamespace)

By("building and deploying the controller-manager")
By(fmt.Sprintf("building and deploying the controller-manager - Version: %s",
env.GetString("VERSION", "")))
cmd := exec.Command("make", "kind-deploy")
_, err := utils.Run(cmd)
output, err := utils.Run(cmd)
_, _ = fmt.Fprint(GinkgoWriter, string(output))
Expect(err).NotTo(HaveOccurred())
cmd = exec.Command("make", "test-apply")
_, err = utils.Run(cmd)
cmd = exec.Command("make", fmt.Sprintf("VERSION=%s", env.GetString("VERSION", "")), "test-apply")
output, err = utils.Run(cmd)
_, _ = fmt.Fprint(GinkgoWriter, string(output))
Expect(err).NotTo(HaveOccurred())

By("validating that the hmc-controller and CAPI provider controllers are running and ready")
Expand All @@ -66,6 +70,15 @@ var _ = BeforeSuite(func() {
}
return nil
}).WithTimeout(15 * time.Minute).WithPolling(10 * time.Second).Should(Succeed())

Eventually(func() error {
err = managedcluster.ValidateClusterTemplates(context.Background(), kc)
if err != nil {
_, _ = fmt.Fprintf(GinkgoWriter, "cluster tempolate validation failed: %v\n", err)
return err
}
return nil
}).WithTimeout(15 * time.Minute).WithPolling(10 * time.Second).Should(Succeed())
})

var _ = AfterSuite(func() {
Expand Down Expand Up @@ -93,6 +106,9 @@ func verifyControllersUp(kc *kubeclient.KubeClient) error {
managedcluster.ProviderAWS,
managedcluster.ProviderAzure,
managedcluster.ProviderVSphere,
managedcluster.ProviderK0smotron,
managedcluster.ProviderK0smotronBootstrap,
managedcluster.ProviderK0smotronControlPlane,
}

for _, provider := range providers {
Expand Down
15 changes: 15 additions & 0 deletions test/e2e/kubeclient/kubeclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,21 @@ func (kc *KubeClient) listResource(
return resources.Items, nil
}

func (kc *KubeClient) ListClusterTemplates(ctx context.Context) ([]unstructured.Unstructured, error) {
client := kc.GetDynamicClient(schema.GroupVersionResource{
Group: "hmc.mirantis.com",
Version: "v1alpha1",
Resource: "clustertemplates",
}, true)

resources, err := client.List(ctx, metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("failed to list cluster templates")
}

return resources.Items, nil
}

// ListMachines returns a list of Machine resources for the given cluster.
func (kc *KubeClient) ListMachines(ctx context.Context, clusterName string) ([]unstructured.Unstructured, error) {
GinkgoHelper()
Expand Down
Loading
Loading