Skip to content

Commit

Permalink
Add e2e tests via GitHub actions post merge
Browse files Browse the repository at this point in the history
Signed-off-by: Carlos Eduardo Arango Gutierrez <[email protected]>
  • Loading branch information
ArangoGutierrez committed Jul 30, 2024
1 parent 274b7d1 commit fc85838
Show file tree
Hide file tree
Showing 7 changed files with 281 additions and 4 deletions.
55 changes: 55 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Copyright 2024 NVIDIA CORPORATION
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: End-to-end Tests

on:
workflow_run:
workflows: [Go]
types:
- completed
branches:
- main
- release-*

jobs:
e2e-tests:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'success' }} && ${{ github.event.workflow_run.event == 'push' }}
steps:
- uses: actions/checkout@v4
name: Check out code
- name: Calculate build vars
id: vars
run: |
echo "COMMIT_SHORT_SHA=${GITHUB_SHA:0:8}" >> $GITHUB_ENV
- name: Set up Holodeck
uses: NVIDIA/holodeck@main
with:
aws_access_key_id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws_secret_access_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- name: Run e2e tests
env:
LOG_ARTIFACTS: ${{ github.workspace }}/e2e_logs
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: |
make -f tests/Makefile e2e-test
- name: Archive test logs
if: ${{ failure() }}
uses: actions/upload-artifact@v4
with:
name: e2e-test-logs
path: ./e2e_logs/
retention-days: 15
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
kubeconfig
bin
.DS_Store
.DS_Store
e2e_logs
11 changes: 8 additions & 3 deletions internal/logger/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ type FunLogger struct {
Fail chan struct{}
// Wg is a WaitGroup that can be used to wait for the loading animation to finish.
Wg *sync.WaitGroup
// CI is a boolean that is set to true if the logger is running in a CI environment.
CI bool
}

// Info prints an information message with no emoji.
Expand Down Expand Up @@ -130,7 +132,7 @@ func (l *FunLogger) Loading(format string, a ...any) {
defer l.Wg.Done()
message := fmt.Sprintf(format, a...)
// if running in a non-interactive terminal, don't print the loading animation
if !isInteractiveTerminal() && isCILogs() {
if !isInteractiveTerminal() && l.isCILogs() {
// print the message with loading emoji
printMessage(yellowText, loadingEmoji, message)
for {
Expand Down Expand Up @@ -184,8 +186,11 @@ func isTerminal(w fdWriter) bool {
return isatty.IsTerminal(w.Fd())
}

func isCILogs() bool {
return os.Getenv("CI") == "true"
func (l *FunLogger) isCILogs() bool {
if os.Getenv("CI") == "true" {
return true
}
return l.CI
}

func (l *FunLogger) Exit(code int) {
Expand Down
32 changes: 32 additions & 0 deletions tests/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

GO_CMD ?= go

E2E_ENV_FILE ?= $(CURDIR)/tests/test_env.yml
LOG_ARTIFACTS ?= $(CURDIR)/e2e_logs

.PHONY: e2e-test
e2e-test:
@if [ -z ${AWS_SECRET_ACCESS_KEY} ] || [ -z ${AWS_ACCESS_KEY_ID} ]; then \
echo "[ERR] AWS_SECRET_ACCESS_KEY and AWS_ACCESS_KEY_ID must be defined"; \
exit 1; \
fi
@echo "Running e2e tests"
$(GO_CMD) test -v $(CURDIR)/tests -args \
-env-file=$(E2E_ENV_FILE)\
-log-artifacts=$(LOG_ARTIFACTS) \
-ginkgo.focus="Holodeck" \
-test.timeout=1h \
-ginkgo.v
57 changes: 57 additions & 0 deletions tests/e2e_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package e2e

import (
"flag"
"log"
"os"
"testing"

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

"github.com/NVIDIA/k8s-test-infra/pkg/framework"
)

var (
LogArtifactDir = flag.String("log-artifacts", "", "Directory to store logs")
EnvFile = flag.String("env-file", "", "Environment file to use")
)

func TestMain(m *testing.M) {
// Register test flags, then parse flags.
framework.RegisterClusterFlags(flag.CommandLine)
flag.Parse()

// check if flags are set and if not cancel the test run
if *EnvFile == "" {
log.Fatal("Required flags not set. Please set -env-file")
}

os.Exit(m.Run())
}

func TestE2E(t *testing.T) {
gomega.RegisterFailHandler(ginkgo.Fail)
// Run tests through the Ginkgo runner with output to console + JUnit for Jenkins
suiteConfig, reporterConfig := ginkgo.GinkgoConfiguration()
// Randomize specs as well as suites
suiteConfig.RandomizeAllSpecs = true

ginkgo.RunSpecs(t, "nvidia holodeck e2e suite", suiteConfig, reporterConfig)
}
106 changes: 106 additions & 0 deletions tests/holodeck_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Copyright (c) 2024, NVIDIA CORPORATION. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package e2e

import (
"context"
"os"
"path/filepath"

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

"github.com/NVIDIA/holodeck/api/holodeck/v1alpha1"
"github.com/NVIDIA/holodeck/internal/logger"
"github.com/NVIDIA/holodeck/pkg/jyaml"
"github.com/NVIDIA/holodeck/pkg/provider/aws"
"github.com/NVIDIA/holodeck/pkg/provisioner"
)

// Actual test suite
var _ = Describe("Holodeck", func() {
type options struct {
cachePath string
cachefile string

cfg v1alpha1.Environment
}
opts := options{}

// Create a logger
log := logger.NewLogger()
log.CI = true

Context("When testing an environment", Ordered, func() {
BeforeAll(func(ctx context.Context) {
//
// Read the config file
var err error
opts.cfg, err = jyaml.UnmarshalFromFile[v1alpha1.Environment](*EnvFile)
Expect(err).ToNot(HaveOccurred())

// set cache path
if opts.cachePath == "" {
opts.cachePath = filepath.Join(*LogArtifactDir, "holodeck")
}
opts.cachefile = filepath.Join(opts.cachePath, opts.cfg.Name+".yaml")

opts.cfg.Spec.Provider = v1alpha1.ProviderAWS
})

AfterAll(func(ctx context.Context) {
// remove the cache file if the test is successful
if !CurrentGinkgoTestDescription().Failed {
err := os.Remove(opts.cachefile)
Expect(err).ToNot(HaveOccurred())
}
})

Context("and calling dryrun to validate the file", func() {
It("validate the provider", func() {
client, err := aws.New(log, opts.cfg, *EnvFile)
Expect(err).ToNot(HaveOccurred())

err = client.DryRun()
Expect(err).ToNot(HaveOccurred())
})

It("validate the provisioner", func() {
err := provisioner.Dryrun(log, opts.cfg)
Expect(err).ToNot(HaveOccurred())
})
})

Context("and calling provision to create the environment", func() {
AfterAll(func(ctx context.Context) {
// Delete the environment
client, err := aws.New(log, opts.cfg, opts.cachefile)
Expect(err).ToNot(HaveOccurred())

err = client.Delete()
Expect(err).ToNot(HaveOccurred())
})
It("create the environment", func() {
client, err := aws.New(log, opts.cfg, opts.cachefile)
Expect(err).ToNot(HaveOccurred())

err = client.Create()
Expect(err).ToNot(HaveOccurred())
})
})
})
})
21 changes: 21 additions & 0 deletions tests/test_env.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
apiVersion: holodeck.nvidia.com/v1alpha1
kind: Environment
metadata:
name: holodeck
description: "Devel infra environment"
spec:
provider: aws
auth:
keyName: eduardoa
privateKey: "/Users/eduardoa/.ssh/eduardoa.pem"
instance:
type: g4dn.xlarge
region: eu-north-1
ingressIpRanges:
- 213.179.129.0/26
image:
architecture: amd64
imageId: ami-0fe8bec493a81c7da
kubernetes:
install: true
installer: microk8s

0 comments on commit fc85838

Please sign in to comment.