diff --git a/.github/workflows/check_pull_request.yml b/.github/workflows/check_pull_request.yml index a0f9458..edeed0e 100644 --- a/.github/workflows/check_pull_request.yml +++ b/.github/workflows/check_pull_request.yml @@ -36,6 +36,10 @@ jobs: - name: Run tests run: make test + - name: Cleanup after failed + if: failure() + run: clean/test + license_validation: needs: [run_tests] name: "Validate that license added to all files" diff --git a/Makefile b/Makefile index 144c0da..0c4ed51 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,8 @@ SHELL = /usr/bin/env bash GOLANGCI_VERSION = 2.7.2 GOFUMPT_VERSION=0.9.2 -JQ_VERSION=1.7.1 +JQ_VERSION=1.8.1 +KIND_VERSION=0.31.0 PLATFORM_NAME := $(shell uname -m) @@ -33,21 +34,25 @@ endif ifeq ($(OS_NAME), Linux) GOFUMPT_PLATFORM = linux JQ_PLATFORM = linux + KIND_PLATFORM = linux else ifeq ($(OS_NAME), Darwin) GOFUMPT_PLATFORM = darwin JQ_PLATFORM = macos + KIND_PLATFORM = darwin endif # Set arch for deps ifeq ($(PLATFORM_NAME), x86_64) GOFUMPT_ARCH = amd64 JQ_PLATFORM_ARCH = $(JQ_PLATFORM)-amd64 + KIND_ARCH = amd64 else ifeq ($(PLATFORM_NAME), arm64) GOFUMPT_ARCH = arm64 JQ_PLATFORM_ARCH = $(JQ_PLATFORM)-arm64 + KIND_ARCH = arm64 endif -.PHONY: bin/jq bin/gofumpt bin/golangci-lint clean validation/license/download +.PHONY: bin/jq bin/gofumpt bin/golangci-lint clean validation/license/download curl-installed docker-installed go-installed clean/test clean/ssh clean/docker bin: mkdir -p bin @@ -55,26 +60,46 @@ bin: curl-installed: command -v curl > /dev/null +docker-installed: + command -v docker > /dev/null + go-installed: - command -v go + command -v go > /dev/null go version bin/jq: curl-installed bin - curl -sSfL https://github.com/jqlang/jq/releases/download/jq-$(JQ_VERSION)/jq-$(JQ_PLATFORM_ARCH) -o ./bin/jq - @chmod +x "./bin/jq" + if ! ./hack/check_binary.sh "jq" "--version" "$(JQ_VERSION)" ; then \ + echo "Install jq"; \ + curl -sSfL https://github.com/jqlang/jq/releases/download/jq-$(JQ_VERSION)/jq-$(JQ_PLATFORM_ARCH) -o ./bin/jq; \ + chmod +x "./bin/jq"; \ + fi bin/golangci-lint: curl-installed bin - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | BINARY=golangci-lint bash -s -- v${GOLANGCI_VERSION} - @chmod +x "./bin/golangci-lint" + if ! ./hack/check_binary.sh "golangci-lint" "--version" "$(GOLANGCI_VERSION)"; then \ + echo "Install golangci-lint"; \ + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | BINARY=golangci-lint bash -s -- v${GOLANGCI_VERSION}; \ + chmod +x "./bin/golangci-lint"; \ + fi bin/gofumpt: curl-installed bin - curl -sSfLo "bin/gofumpt" https://github.com/mvdan/gofumpt/releases/download/v$(GOFUMPT_VERSION)/gofumpt_v$(GOFUMPT_VERSION)_$(GOFUMPT_PLATFORM)_$(GOFUMPT_ARCH) - @chmod +x "./bin/gofumpt" - -deps: bin bin/jq bin/golangci-lint bin/gofumpt - -test: go-installed + if ! ./hack/check_binary.sh "gofumpt" "-version" "$(GOFUMPT_VERSION)"; then \ + echo "Install gofumpt"; \ + curl -sSfLo "bin/gofumpt" https://github.com/mvdan/gofumpt/releases/download/v$(GOFUMPT_VERSION)/gofumpt_v$(GOFUMPT_VERSION)_$(GOFUMPT_PLATFORM)_$(GOFUMPT_ARCH); \ + chmod +x "./bin/gofumpt"; \ + fi + +bin/kind: curl-installed bin + if ! ./hack/check_binary.sh "kind" "version" "$(KIND_VERSION)"; then \ + echo "Install kind"; \ + curl -sSfLo "bin/kind" https://github.com/kubernetes-sigs/kind/releases/download/v$(KIND_VERSION)/kind-$(KIND_PLATFORM)-$(KIND_ARCH); \ + chmod +x "./bin/kind"; \ + fi + +deps: bin bin/jq bin/golangci-lint bin/gofumpt bin/kind + +test: go-installed docker-installed bin/kind ./hack/run_tests.sh + $(MAKE) clean/test lint: bin/golangci-lint ./bin/golangci-lint run ./... -c .golangci.yaml @@ -104,8 +129,20 @@ validation/license: go-installed validation/license/download # prevent goland ide errors rm -f ./validation/go.mod ./validation/go.sum +clean/ssh: clean/docker + echo "Remove test dir /tmp/test-lib-connection" + rm -rf /tmp/test-lib-connection + +clean/docker: docker-installed + ./hack/clean_docker.sh + +clean/kind: bin/kind + ./hack/clean_kind.sh + +clean/test: clean/kind clean/ssh + all: bin deps validation/license fmt lint test -clean: +clean: clean/test rm -rf ./bin rm -rf ./validation diff --git a/hack/check_binary.sh b/hack/check_binary.sh new file mode 100755 index 0000000..94089f0 --- /dev/null +++ b/hack/check_binary.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash + +# Copyright 2026 Flant JSC +# +# 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. + +binary="$1" +version_arg="$2" +version="$3" + +function not_empty_or_exit() { + if [ -z "$2" ]; then + echo "$1 is empty" + exit 1 + fi + + return 0 +} + +not_empty_or_exit "binary" "$binary" +not_empty_or_exit "version_arg" "$version_arg" +not_empty_or_exit "version" "$version" + +binary_full_path="$(pwd)/bin/${binary}" + +if [ ! -x "$binary_full_path" ]; then + echo "$binary_full_path not exists or not executable" + exit 1 +fi + +if ! "$binary_full_path" "$version_arg" | grep -q "$version" ; then + echo "$binary_full_path version not match ${version}. Version is $("$binary_full_path" "$version_arg")" + exit 1 +fi + +exit 0 diff --git a/hack/clean_docker.sh b/hack/clean_docker.sh new file mode 100755 index 0000000..1efb30e --- /dev/null +++ b/hack/clean_docker.sh @@ -0,0 +1,45 @@ +#!/usr/bin/env bash + +# Copyright 2026 Flant JSC +# +# 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. + +source "$(pwd)/hack/utils.sh" + +check_docker + +function get_tests_containers() { + docker container ls --filter='name=test_lib_connection.*' --format='{{.ID}}' +} + +function rm_containers() { + echo "Remove containers $@" + docker container rm -f "$@" + return $? +} + +function get_tests_networks() { + docker network ls --filter='name=test_lib_connection.*' --format='{{.Name}}' +} + +function rm_networks() { + echo "Remove networks $@" + docker network rm "$@" + return $? +} + +do_in_cycle "remove tests containers" get_tests_containers rm_containers +do_in_cycle "remove tests networks" get_tests_networks rm_networks + +echo "Docker cleanup done!" +exit 0 diff --git a/hack/clean_kind.sh b/hack/clean_kind.sh new file mode 100755 index 0000000..d0bc8a7 --- /dev/null +++ b/hack/clean_kind.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +# Copyright 2026 Flant JSC +# +# 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. + +source "$(pwd)/hack/utils.sh" + +check_all_deps + +kind_bin="$(kind_bin_path)" + +function get_kind_clusters() { + local clusters="$("$kind_bin" get clusters | grep --color=never "test-connection" || true)" + clusters="$(trim_spaces "$clusters")" + if [[ "$clusters" == "No kind clusters found." ]]; then + echo -n "" + return 0 + fi + + echo -n "$clusters" + return 0 +} + +function rm_kind_clusters() { + echo "Remove kind clusters $@" + "$kind_bin" delete clusters "$@" + return $? +} + +do_in_cycle "remove tests kind clusters" get_kind_clusters rm_kind_clusters + +echo "Kind clusters cleanup done!" +exit 0 diff --git a/hack/kind/cluster-kube-proxy.yml b/hack/kind/cluster-kube-proxy.yml new file mode 100644 index 0000000..5449d97 --- /dev/null +++ b/hack/kind/cluster-kube-proxy.yml @@ -0,0 +1,19 @@ +# Copyright 2026 Flant JSC +# +# 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. + +kind: Cluster +apiVersion: kind.x-k8s.io/v1alpha4 +name: test-connection-kube-proxy +nodes: + - role: control-plane \ No newline at end of file diff --git a/hack/run_tests.sh b/hack/run_tests.sh index 7dde07a..8cd0e17 100755 --- a/hack/run_tests.sh +++ b/hack/run_tests.sh @@ -14,6 +14,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +source "$(pwd)/hack/utils.sh" + +check_all_deps +check_go + run_tests="" if [ -n "$RUN_TEST" ]; then @@ -25,6 +30,13 @@ run_dir="$(pwd)" packages="$(go list ./... | grep -v /validation/)" prefix="$(grep -oP 'module .*$' go.mod | sed 's|module ||')" +if [ -z "$(trim_spaces "$packages")" ]; then + echo -e '\033[1;33m!!!\033[0m' + echo -e "\033[1;33mNot found packages in $run_dir with module ${prefix}. Skip go tests\033[0m" + echo -e '\033[1;33m!!!\033[0m' + exit 0 +fi + echo "Found packages: ${packages[@]} in $run_dir with module $prefix" while IFS= read -r p; do diff --git a/hack/utils.sh b/hack/utils.sh new file mode 100644 index 0000000..0c9e887 --- /dev/null +++ b/hack/utils.sh @@ -0,0 +1,101 @@ +#!/usr/bin/env bash + +# Copyright 2026 Flant JSC +# +# 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. + +function trim_spaces() { + local v="$1" + # Remove leading whitespace + v="${v#"${v%%[![:space:]]*}"}" + + # Remove trailing whitespace + v="${v%"${v##*[![:space:]]}"}" + + echo -n "$v" +} + +function do_in_cycle(){ + local msg="$1" + local get_arguments="$2" + local action="$3" + + if [ -z "$msg" ]; then + echo "msg is empty" + exit 1 + fi + + if [ -z "$get_arguments" ]; then + echo "get_arguments is empty" + exit 1 + fi + + if [ -z "$action" ]; then + echo "action is empty" + exit 1 + fi + + local attempts=10 + + echo "Starting $msg with $attempts attempts" + + local sleep_time=2 + local current_attempt=1 + + while [[ -n "$(trim_spaces "$("$get_arguments")")" ]]; do + if [[ "$current_attempt" == "$attempts" ]]; then + echo "All attempts $attempts failed for ${msg}. Exit" + exit 1 + fi + + if ! $action $("$get_arguments"); then + echo "Attempt ${current_attempt}: $msg failed. Sleep ${sleep_time} before next attempt" + sleep "$sleep_time" + fi + + ((current_attempt++)) + done + + echo "$msg done!" + return 0 +} + +function check_go() { + if ! command -v go; then + echo "Go not found!" + exit 1 + fi +} + +function check_docker() { + if ! command -v docker; then + echo "Docker not found!" + exit 1 + fi +} + +function kind_bin_path() { + echo -n "$(pwd)/bin/kind" +} + +function check_kind() { + local bin_path="$(kind_bin_path)" + if ! [ -x "$bin_path" ]; then + echo "Kind not installed! You should run 'make bin/kind' before" + exit 1 + fi +} + +function check_all_deps() { + check_docker && check_kind +} \ No newline at end of file