Skip to content

Commit

Permalink
start adding tests
Browse files Browse the repository at this point in the history
  • Loading branch information
tinyzimmer committed Oct 3, 2023
1 parent d36de29 commit 01a5876
Show file tree
Hide file tree
Showing 9 changed files with 300 additions and 30 deletions.
33 changes: 32 additions & 1 deletion .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,41 @@ jobs:
version: ${{ env.GOLANGCI_LINT_VERSION }}
args: --timeout ${{ env.LINT_TIMEOUT }}

tests:
name: Unit Tests
needs: [lint]
runs-on: ubuntu-latest
permissions:
contents: "read"
steps:
- name: Checkout Code
uses: actions/checkout@v4

- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: ${{ env.GO_VERSION }}
check-latest: true
cache: false

- name: Setup Test Cache
uses: actions/cache@v3
with:
key: ${{ runner.os }}-ci-tests-go-${{ env.GO_VERSION }}-${{ hashFiles(env.CACHE_DEP_PATH) }}
restore-keys: ${{ runner.os }}-ci-tests-go-${{ env.GO_VERSION }}-
path: |
~/go/pkg
~/go/bin
~/.cache/go-build
- name: Run Unit Tests
shell: bash
run: make ci-test

build-containers:
name: Build Containers
runs-on: ubuntu-latest
needs: [lint]
needs: [tests]
permissions:
contents: "write"
id-token: "write"
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*.dll
*.so
*.dylib
bin/*
bin/
Dockerfile.cross

# Test binary, build with `go test -c`
Expand Down
20 changes: 17 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ GOBIN=$(shell go env GOPATH)/bin
else
GOBIN=$(shell go env GOBIN)
endif
LOCALBIN := $(CURDIR)/bin

# CONTAINER_TOOL defines the container tool to be used for building images.
# Be aware that the target commands are only tested with Docker which is
Expand Down Expand Up @@ -71,14 +72,27 @@ fmt: ## Run go fmt against code.
vet: ## Run go vet against code.
go vet ./...

.PHONY: test
test: manifests generate fmt vet envtest ## Run tests.
KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test ./... -coverprofile cover.out
SETUP := go run sigs.k8s.io/controller-runtime/tools/setup-envtest@latest use $(K8S_VERSION) --bin-dir $(LOCALBIN) -p path
setup-envtest: ## Setup envtest. This is automatically run by the test target.
$(SETUP) 1> /dev/null

RICHGO ?= go run github.com/kyoh86/[email protected]
TEST_TIMEOUT ?= 300s
TEST_ARGS ?= -v -cover -covermode=atomic -coverprofile=cover.out -timeout=$(TEST_TIMEOUT)
test: manifests generate setup-envtest ## Run tests.
KUBEBUILDER_ASSETS="$(shell $(SETUP))" $(RICHGO) test $(TEST_ARGS) ./...
go tool cover -func=cover.out

LINT_TIMEOUT := 10m
lint: ## Run linters.
go run github.com/golangci/golangci-lint/cmd/golangci-lint@latest run --timeout=$(LINT_TIMEOUT)

CI_TARGETS := fmt vet lint test
ifeq ($(CI),true)
CI_TARGETS := vet test
endif
ci-test: $(CI_TARGETS) ## Run all CI tests.

##@ Build

PARALLEL ?= $(shell nproc)
Expand Down
6 changes: 3 additions & 3 deletions internal/cmd/plugin/plugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ func cmdAdd(args *skel.CmdArgs) (err error) {
os.Exit(1)
}
}()
conf, err := types.LoadConfigFromArgs(args)
conf, err := types.LoadNetConfFromArgs(args)
if err != nil {
err = fmt.Errorf("failed to load config: %w", err)
return
Expand Down Expand Up @@ -276,7 +276,7 @@ func cmdCheck(args *skel.CmdArgs) (err error) {
os.Exit(1)
}
}()
conf, err := types.LoadConfigFromArgs(args)
conf, err := types.LoadNetConfFromArgs(args)
if err != nil {
err = fmt.Errorf("failed to load config: %w", err)
return
Expand Down Expand Up @@ -318,7 +318,7 @@ func cmdDel(args *skel.CmdArgs) (err error) {
os.Exit(1)
}
}()
conf, err := types.LoadConfigFromArgs(args)
conf, err := types.LoadNetConfFromArgs(args)
if err != nil {
err = fmt.Errorf("failed to load config: %w", err)
return
Expand Down
21 changes: 8 additions & 13 deletions internal/types/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ import (
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"

meshcniv1 "github.com/webmeshproj/webmesh-cni/api/v1"
Expand All @@ -52,21 +51,17 @@ func IsPeerContainerNotFound(err error) bool {
// Client is the client for the CNI plugin.
type Client struct {
client.Client
conf NetConf
conf *NetConf
}

// NewClientOrDie creates a new client from the given kubeconfig or panics.
func NewClientOrDie(conf NetConf) *Client {
cfg := ctrl.GetConfigOrDie()
client, err := NewClientForConfig(cfg, conf)
if err != nil {
panic(err)
}
return client
// ClientConfig is the configuration for the CNI client.
type ClientConfig struct {
NetConf *NetConf
RestConfig *rest.Config
}

// NewClientForConfig creates a new client from the given configuration.
func NewClientForConfig(cfg *rest.Config, conf NetConf) (*Client, error) {
func NewClientForConfig(conf ClientConfig) (*Client, error) {
scheme := runtime.NewScheme()
err := clientgoscheme.AddToScheme(scheme)
if err != nil {
Expand All @@ -84,7 +79,7 @@ func NewClientForConfig(cfg *rest.Config, conf NetConf) (*Client, error) {
if err != nil {
return nil, err
}
client, err := client.New(cfg, client.Options{
client, err := client.New(conf.RestConfig, client.Options{
Scheme: scheme,
Cache: &client.CacheOptions{
DisableFor: storagev1.CustomObjects,
Expand All @@ -95,7 +90,7 @@ func NewClientForConfig(cfg *rest.Config, conf NetConf) (*Client, error) {
}
return &Client{
Client: client,
conf: conf,
conf: conf.NetConf,
}, nil
}

Expand Down
17 changes: 17 additions & 0 deletions internal/types/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
Copyright 2023 Avi Zimmerman <[email protected]>.
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 types
17 changes: 17 additions & 0 deletions internal/types/install_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
Copyright 2023 Avi Zimmerman <[email protected]>.
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 types
67 changes: 58 additions & 9 deletions internal/types/netconf.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,11 +43,11 @@ type NetConf struct {
// NetConf is the typed configuration for the CNI plugin.
cnitypes.NetConf `json:",inline"`

// Interface is the configuration for container interfaces.
Interface Interface `json:"interface"`
// Kubernetes is the configuration for the Kubernetes API server and
// information about the node we are running on.
Kubernetes Kubernetes `json:"kubernetes"`
// Interface is the configuration for the interface.
Interface Interface `json:"interface"`
// LogLevel is the log level for the plugin and managed interfaces.
LogLevel string `json:"logLevel"`
}
Expand All @@ -63,6 +63,19 @@ func (n *NetConf) SetDefaults() *NetConf {
return n
}

// DeepEqual returns whether the configuration is equal to the given configuration.
func (n *NetConf) DeepEqual(other *NetConf) bool {
if n == nil && other == nil {
return true
}
if n == nil || other == nil {
return false
}
return n.Kubernetes.DeepEqual(&other.Kubernetes) &&
n.Interface.DeepEqual(&other.Interface) &&
n.LogLevel == other.LogLevel
}

// Interface is the configuration for a single interface.
type Interface struct {
// MTU is the MTU to set on interfaces.
Expand All @@ -73,12 +86,26 @@ type Interface struct {
DisableIPv6 bool `json:"disableIPv6"`
}

// Default sets the default values for the interface configuration.
func (i *Interface) Default() {
if i.MTU <= 0 {
i.MTU = meshsys.DefaultMTU
}
}

// DeepEqual returns whether the interface is equal to the given interface.
func (i *Interface) DeepEqual(other *Interface) bool {
if i == nil && other == nil {
return true
}
if i == nil || other == nil {
return false
}
return i.MTU == other.MTU &&
i.DisableIPv4 == other.DisableIPv4 &&
i.DisableIPv6 == other.DisableIPv6
}

// Kubernetes is the configuration for the Kubernetes API server and
// information about the node we are running on.
type Kubernetes struct {
Expand All @@ -99,21 +126,40 @@ func (k *Kubernetes) Default() {
}
}

// LoadConfigFromFile loads the configuration from the given file.
func LoadConfigFromFile(path string) (*NetConf, error) {
// DeepEqual returns whether the Kubernetes configuration is equal to the given configuration.
func (k *Kubernetes) DeepEqual(other *Kubernetes) bool {
if k == nil && other == nil {
return true
}
if k == nil || other == nil {
return false
}
return k.Kubeconfig == other.Kubeconfig &&
k.NodeName == other.NodeName &&
k.K8sAPIRoot == other.K8sAPIRoot &&
k.Namespace == other.Namespace
}

// LoadNetConfFromFile loads the configuration from the given file.
func LoadNetConfFromFile(path string) (*NetConf, error) {
data, err := os.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("failed to read config file: %w", err)
}
return LoadConfigFromArgs(&skel.CmdArgs{StdinData: data})
return DecodeNetConf(data)
}

// LoadConfigFromArgs loads the configuration from the given CNI arguments.
func LoadConfigFromArgs(cmd *skel.CmdArgs) (*NetConf, error) {
func LoadNetConfFromArgs(cmd *skel.CmdArgs) (*NetConf, error) {
return DecodeNetConf(cmd.StdinData)
}

// DecodeNetConf loads the configuration from the given JSON data.
func DecodeNetConf(data []byte) (*NetConf, error) {
var conf NetConf
err := json.Unmarshal(cmd.StdinData, &conf)
err := json.Unmarshal(data, &conf)
if err != nil {
return nil, fmt.Errorf("failed to load netconf from stdin data: %w", err)
return nil, fmt.Errorf("failed to load netconf from data: %w", err)
}
return conf.SetDefaults(), nil
}
Expand Down Expand Up @@ -198,7 +244,10 @@ func (n *NetConf) NewClient(pingTimeout time.Duration) (*Client, error) {
err = fmt.Errorf("failed to create REST config: %w", err)
return nil, err
}
cli, err := NewClientForConfig(restCfg, *n)
cli, err := NewClientForConfig(ClientConfig{
RestConfig: restCfg,
NetConf: n,
})
if err != nil {
err = fmt.Errorf("failed to create client: %w", err)
return nil, err
Expand Down
Loading

0 comments on commit 01a5876

Please sign in to comment.