Skip to content

Commit

Permalink
Merge pull request #5 from fedepaol/withatest
Browse files Browse the repository at this point in the history
Add the first e2e test
  • Loading branch information
fedepaol authored Jun 29, 2023
2 parents 874ea25 + 667b59f commit c030b32
Show file tree
Hide file tree
Showing 17 changed files with 2,227 additions and 3 deletions.
49 changes: 49 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ jobs:
ENV=host make lint
make bumplicense
go mod tidy
pushd e2etests
go mod tidy
popd
make manifests
make checkuncommitted
Expand Down Expand Up @@ -91,3 +94,49 @@ jobs:
retention-days: 1
name: image-tar-frrk8s
path: /tmp/frrk8s.tar
e2e:
runs-on: ubuntu-22.04
needs:
- unit-tests
- build-test-images
- commitlint
strategy:
fail-fast: false
matrix:
ip-family: [ipv4, ipv6, dual]
steps:
- name: Checkout
uses: actions/checkout@v3

- name: Install kernel modules
run: |
sudo apt-get update
sudo apt-get install linux-modules-extra-$(uname -r)
- name: Download frr8ks images
uses: actions/download-artifact@v3
with:
path: image

- name: Load image
working-directory: image
run: |
docker load -i image-tar-frrk8s/frrk8s.tar
- name: Deploy on kind
run: |
IP_FAMILY="${{ matrix.ip-family }}" IMG=quay.io/metallb/frrk8s:dev-amd64 make deploy
- name: E2E
run: |
SKIP="none"
if [ "${{ matrix.ip-family }}" == "ipv4" ]; then SKIP="$SKIP\|IPV6\|DUALSTACK"; fi
if [ "${{ matrix.ip-family }}" == "dual" ]; then SKIP="$SKIP\|IPV6"; fi
if [ "${{ matrix.ip-family }}" == "ipv6" ]; then SKIP="$SKIP\|IPV4\|DUALSTACK"; fi
GINKGO_ARGS="--skip $SKIP" make e2etests
- name: Collect Logs
if: ${{ failure() }}
uses: ./.github/workflows/composite/collectlogs
with:
artifact-name: kind-logs-${{ matrix.ip-family }}
21 changes: 21 additions & 0 deletions .github/workflows/composite/collectlogs/action.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: "collectlogs"
description: "Collect and upload the logs"

inputs:
artifact-name:
description: "the name of artifacts to store"
required: true

runs:
using: "composite"
steps:
- name: Log permissions
shell: bash
run: |
sudo chmod -R o+r /tmp/kind_logs
- name: Upload logs
uses: actions/upload-artifact@v2
with:
name: ${{ inputs.artifact-name }}
path: /tmp/kind_logs/
19 changes: 16 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ KIND ?= $(LOCALBIN)/kind
KUBECTL ?= $(LOCALBIN)/kubectl
KUSTOMIZE ?= $(LOCALBIN)/kustomize
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
GINKGO ?= $(LOCALBIN)/ginkgo
ENVTEST ?= $(LOCALBIN)/setup-envtest
KUBECONFIG_PATH ?= $(LOCALBIN)/kubeconfig
export KUBECONFIG=$(KUBECONFIG_PATH)
Expand All @@ -123,6 +124,7 @@ export KUBECONFIG=$(KUBECONFIG_PATH)
KUSTOMIZE_VERSION ?= v5.0.0
CONTROLLER_TOOLS_VERSION ?= v0.11.3
KUBECTL_VERSION ?= v1.27.0
GINKGO_VERSION ?= v2.11.0
KIND_VERSION ?= v0.19.0
KIND_CLUSTER_NAME ?= frr-k8s

Expand Down Expand Up @@ -164,29 +166,40 @@ $(CONTROLLER_GEN): $(LOCALBIN)
.PHONY: kubectl
kubectl: $(KUBECTL) ## Download kubectl locally if necessary. If wrong version is installed, it will be overwritten.
$(KUBECTL): $(LOCALBIN)
test -s $(LOCALBIN)/kubectl && $(LOCALBIN)/kubectl --version | grep -q $(CONTROLLER_TOOLS_VERSION) || \
test -s $(LOCALBIN)/kubectl && $(LOCALBIN)/kubectl --version | grep -q $(KUBECTL_VERSION) || \
curl -o $(LOCALBIN)/kubectl -LO https://dl.k8s.io/release/$(KUBECTL_VERSION)/bin/$$(go env GOOS)/$$(go env GOARCH)/kubectl
chmod +x $(LOCALBIN)/kubectl

.PHONY: kind
kind: $(KIND) ## Download kind locally if necessary. If wrong version is installed, it will be overwritten.
$(KIND): $(LOCALBIN)
test -s $(LOCALBIN)/kind && $(LOCALBIN)/kind --version | grep -q $(CONTROLLER_TOOLS_VERSION) || \
test -s $(LOCALBIN)/kind && $(LOCALBIN)/kind --version | grep -q $(KIND_VERSION) || \
GOBIN=$(LOCALBIN) go install sigs.k8s.io/kind@$(KIND_VERSION)

.PHONY: envtest
envtest: $(ENVTEST) ## Download envtest-setup locally if necessary.
$(ENVTEST): $(LOCALBIN)
test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest

.PHONY: ginkgo
ginkgo: $(GINKGO) ## Download ginkgo locally if necessary. If wrong version is installed, it will be overwritten.
$(GINKGO): $(LOCALBIN)
test -s $(LOCALBIN)/ginkgo && $(LOCALBIN)/ginkgo version | grep -q $(GINKGO_VERSION) || \
GOBIN=$(LOCALBIN) go install github.com/onsi/ginkgo/v2/ginkgo@$(GINKGO_VERSION)

.PHONY: e2etests
e2etests: ginkgo
$(GINKGO) -v $(GINKGO_ARGS) ./e2etests


.PHONY: kind-cluster
kind-cluster: kind
KIND_BIN=$(LOCALBIN)/kind hack/kind.sh
@echo 'kind cluster created, to use it please'
@echo 'export KUBECONFIG=${KUBECONFIG_PATH}'

.PHONY: load-on-kind
load-on-kind: docker-build kind-cluster ## Load the docker image into the kind cluster.
load-on-kind: kind-cluster ## Load the docker image into the kind cluster.
kind load docker-image ${IMG} -n ${KIND_CLUSTER_NAME}

.PHONY: lint
Expand Down
4 changes: 4 additions & 0 deletions e2etests/config/frr/bgpd.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
password zebra
log stdout debugging
log file /tmp/frr.log debugging

80 changes: 80 additions & 0 deletions e2etests/config/frr/daemons
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
# This file tells the frr package which daemons to start.
#
# Sample configurations for these daemons can be found in
# /usr/share/doc/frr/examples/.
#
# ATTENTION:
#
# When activating a daemon for the first time, a config file, even if it is
# empty, has to be present *and* be owned by the user and group "frr", else
# the daemon will not be started by /etc/init.d/frr. The permissions should
# be u=rw,g=r,o=.
# When using "vtysh" such a config file is also needed. It should be owned by
# group "frrvty" and set to ug=rw,o= though. Check /etc/pam.d/frr, too.
#
# The watchfrr and zebra daemons are always started.
#
bgpd=yes
ospfd=no
ospf6d=no
ripd=no
ripngd=no
isisd=no
pimd=no
ldpd=no
nhrpd=no
eigrpd=no
babeld=no
sharpd=no
pbrd=no
bfdd=yes
fabricd=no
vrrpd=no

#
# If this option is set the /etc/init.d/frr script automatically loads
# the config via "vtysh -b" when the servers are started.
# Check /etc/pam.d/frr if you intend to use "vtysh"!
#
vtysh_enable=yes
zebra_options=" -A 127.0.0.1 -s 90000000"
bgpd_options=" -A 127.0.0.1 -p {{.BGPPort}}"
ospfd_options=" -A 127.0.0.1"
ospf6d_options=" -A ::1"
ripd_options=" -A 127.0.0.1"
ripngd_options=" -A ::1"
isisd_options=" -A 127.0.0.1"
pimd_options=" -A 127.0.0.1"
ldpd_options=" -A 127.0.0.1"
nhrpd_options=" -A 127.0.0.1"
eigrpd_options=" -A 127.0.0.1"
babeld_options=" -A 127.0.0.1"
sharpd_options=" -A 127.0.0.1"
pbrd_options=" -A 127.0.0.1"
staticd_options="-A 127.0.0.1"
bfdd_options=" -A 127.0.0.1"
fabricd_options="-A 127.0.0.1"
vrrpd_options=" -A 127.0.0.1"

# configuration profile
#
#frr_profile="traditional"
#frr_profile="datacenter"

#
# This is the maximum number of FD's that will be available.
# Upon startup this is read by the control files and ulimit
# is called. Uncomment and use a reasonable value for your
# setup if you are expecting a large number of peers in
# say BGP.
#MAX_FDS=1024

# The list of daemons to watch is automatically generated by the init script.
#watchfrr_options=""

# for debugging purposes, you can specify a "wrap" command to start instead
# of starting the daemon directly, e.g. to use valgrind on ospfd:
# ospfd_wrap="/usr/bin/valgrind"
# or you can use "all_wrap" for all daemons, e.g. to use perf record:
# all_wrap="/usr/bin/perf record --call-graph -"
# the normal daemon command is added to this at the end.
Empty file added e2etests/config/frr/vtysh.conf
Empty file.
2 changes: 2 additions & 0 deletions e2etests/config/frr/zebra.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
password zebra
enable password zebra
116 changes: 116 additions & 0 deletions e2etests/e2etest_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
// SPDX-License-Identifier:Apache-2.0

package e2e

import (
"flag"
"fmt"
"os"
"testing"

"github.com/metallb/frrk8stests/pkg/infra"
_ "github.com/metallb/frrk8stests/tests"
"github.com/onsi/ginkgo/v2"
"github.com/onsi/gomega"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/kubernetes/test/e2e/framework"
e2econfig "k8s.io/kubernetes/test/e2e/framework/config"
)

var (
skipDockerCmd bool
reportPath string
prometheusNamespace string
localNics string
externalContainers string
runOnHost bool
bgpNativeMode bool
frrImage string
)

// handleFlags sets up all flags and parses the command line.
func handleFlags() {
e2econfig.CopyFlags(e2econfig.Flags, flag.CommandLine)
framework.RegisterCommonFlags(flag.CommandLine)
/*
Using framework.RegisterClusterFlags(flag.CommandLine) results in a panic:
"flag redefined: kubeconfig".
This happens because controller-runtime registers the kubeconfig flag as well.
To solve this we set the framework's kubeconfig directly via the KUBECONFIG env var
instead of letting it call the flag. Since we also use the provider flag it is handled manually.
*/
flag.StringVar(&framework.TestContext.Provider, "provider", "", "The name of the Kubernetes provider (gce, gke, local, skeleton (the fallback if not set), etc.)")
framework.TestContext.KubeConfig = os.Getenv(clientcmd.RecommendedConfigPathEnvVar)

flag.BoolVar(&skipDockerCmd, "skip-docker", false, "set this to true if the BGP daemon is running on the host instead of in a container")
flag.StringVar(&reportPath, "report-path", "/tmp/report", "the path to be used to dump test failure information")
flag.StringVar(&prometheusNamespace, "prometheus-namespace", "monitoring", "the namespace prometheus is running in (if running)")
flag.StringVar(&externalContainers, "external-containers", "", "a comma separated list of external containers names to use for the test. (valid parameters are: ibgp-single-hop / ibgp-multi-hop / ebgp-single-hop / ebgp-multi-hop)")
flag.StringVar(&frrImage, "frr-image", "quay.io/frrouting/frr:8.4.2", "the image to use for the external frr containers")

flag.Parse()

if _, res := os.LookupEnv("RUN_FRR_CONTAINER_ON_HOST_NETWORK"); res {
runOnHost = true
}
}

func TestMain(m *testing.M) {
// Register test flags, then parse flags.
handleFlags()
if testing.Short() {
return
}

framework.AfterReadingAllFlags(&framework.TestContext)

os.Exit(m.Run())
}

func TestE2E(t *testing.T) {
if testing.Short() {
return
}

gomega.RegisterFailHandler(framework.Fail)
ginkgo.RunSpecs(t, "E2E Suite")
}

var _ = ginkgo.BeforeSuite(func() {
// Make sure the framework's kubeconfig is set.
framework.ExpectNotEqual(framework.TestContext.KubeConfig, "", fmt.Sprintf("%s env var not set", clientcmd.RecommendedConfigPathEnvVar))

cs, err := framework.LoadClientset()
framework.ExpectNoError(err)

switch {
case externalContainers != "":
infra.FRRContainers, err = infra.ExternalContainersSetup(externalContainers, cs)
framework.ExpectNoError(err)
case runOnHost:
infra.FRRContainers, err = infra.HostContainerSetup(frrImage)
framework.ExpectNoError(err)
default:
infra.FRRContainers, err = infra.KindnetContainersSetup(cs, frrImage)
framework.ExpectNoError(err)
/*
vrfFRRContainers, err := bgptests.VRFContainersSetup(cs)
framework.ExpectNoError(err)
bgptests.FRRContainers = append(bgptests.FRRContainers, vrfFRRContainers...)
*/
}

//reporter := k8s.InitReporter(framework.TestContext.KubeConfig, reportPath, metallb.Namespace)
})

var _ = ginkgo.AfterSuite(func() {
cs, err := framework.LoadClientset()
framework.ExpectNoError(err)

err = infra.InfraTearDown(cs)
framework.ExpectNoError(err)
/*
err = bgptests.InfraTearDownVRF(cs)
framework.ExpectNoError(err)
*/
})
Loading

0 comments on commit c030b32

Please sign in to comment.