├── .ci ├── hack │ ├── component_descriptor │ ├── doc.go │ ├── generate-controller-registration.sh │ ├── prepare_release │ └── set_dependency_version ├── pipeline_definitions └── verify ├── .dockerignore ├── .github ├── ISSUE_TEMPLATE │ ├── bug.md │ ├── feature.md │ └── support.md ├── dependabot.yaml ├── pull_request_template.md └── workflows │ └── vendor_gardener.yaml ├── .gitignore ├── .reuse └── dep5 ├── CODEOWNERS ├── CONTRIBUTING.md ├── LICENSE ├── LICENSES ├── Apache-2.0.txt └── CC-BY-4.0.txt ├── Makefile ├── README.md ├── VERSION ├── cmd ├── Dockerfile └── apiserver-proxy-sidecar │ └── main.go ├── go.mod ├── go.sum ├── hack ├── cherry-pick-pull.sh ├── sast.sh ├── tools.go └── tools │ └── bin │ └── .gitkeep └── internal ├── app ├── app.go └── config.go ├── netif ├── mocks_test.go ├── netif.go └── netif_suite_test.go └── version └── version.go /.ci/hack/component_descriptor: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Gardener contributors 4 | # 5 | # SPDX-License-Identifier: Apache-2.0 6 | 7 | # Configuration Options: 8 | # 9 | # COMPONENT_PREFIXES: Set the image prefix that should be used to 10 | # determine if an image is defined by another component. 11 | # Defaults to "europe-docker.pkg.dev/gardener-project/releases/gardener" 12 | # 13 | # COMPONENT_CLI_ARGS: Set all component-cli arguments. 14 | # This should be used with care as all defaults are overwritten. 15 | # 16 | 17 | set -e 18 | 19 | repo_root_dir="$1" 20 | repo_name="${2:-github.com/gardener/gardener}" 21 | descriptor_out_file="${COMPONENT_DESCRIPTOR_PATH}" 22 | 23 | resources_file="$repo_root_dir/.ci/resources.yaml" 24 | if [[ -f ${resources_file} ]]; then 25 | echo "Adding additional resources from ${resources_file}" 26 | 27 | # component-cli expects a directory where the component descriptor file is named component-descriptor.yaml. 28 | # however the pre-rendered component descriptors of the pipeline have different filenames. 29 | # therefore create a tempdir and copy the pre-rendered component descriptor to it with the correct filename. 30 | tmp_dir="$(mktemp -d)" 31 | tmp_cd="${tmp_dir}/component-descriptor.yaml" 32 | cp "${BASE_DEFINITION_PATH}" "${tmp_cd}" 33 | echo "${tmp_cd}" 34 | 35 | # read the component version. 36 | if [[ -z ${EFFECTIVE_VERSION} ]]; then 37 | echo "The env variable EFFECTIVE_VERSION must be set" 38 | exit 1 39 | fi 40 | 41 | # adds all resources defined in the resources file to the component descriptor. 42 | component-cli component-archive resources add ${tmp_dir} ${resources_file} -v=3 -- COMPONENT_VERSION=${EFFECTIVE_VERSION} 43 | 44 | # move modified component descriptor back to the original file. 45 | mv "${tmp_cd}" "${BASE_DEFINITION_PATH}" 46 | else 47 | echo "Resources file ${resources_file} not found. Skip adding additional resources." 48 | fi 49 | 50 | echo "Enriching component descriptor from ${BASE_DEFINITION_PATH}" 51 | 52 | image_vector_path="" 53 | if [[ -f "$repo_root_dir/charts/images.yaml" ]]; then 54 | image_vector_path="$repo_root_dir/charts/images.yaml" 55 | elif [[ -f "$repo_root_dir/imagevector/images.yaml" ]]; then 56 | image_vector_path="$repo_root_dir/imagevector/images.yaml" 57 | elif [[ -f "$repo_root_dir/imagevector/containers.yaml" ]]; then 58 | image_vector_path="$repo_root_dir/imagevector/containers.yaml" 59 | fi 60 | 61 | if [[ ! -z "$image_vector_path" ]]; then 62 | # default environment variables 63 | if [[ -z "${COMPONENT_PREFIXES}" ]]; then 64 | COMPONENT_PREFIXES="europe-docker.pkg.dev/gardener-project/releases/gardener,europe-docker.pkg.dev/gardener-project/snapshots/gardener" 65 | fi 66 | 67 | if [[ -z "${COMPONENT_CLI_ARGS}" ]]; then 68 | COMPONENT_CLI_ARGS=" 69 | --comp-desc ${BASE_DEFINITION_PATH} \ 70 | --image-vector "$image_vector_path" \ 71 | --component-prefixes "${COMPONENT_PREFIXES}" \ 72 | " 73 | fi 74 | 75 | # translates all images defined the containers.yaml into component descriptor resources. 76 | # For detailed documentation see https://github.com/gardener/component-cli/blob/main/docs/reference/components-cli_image-vector_add.md 77 | component-cli image-vector add ${COMPONENT_CLI_ARGS} 78 | fi 79 | 80 | cp "${BASE_DEFINITION_PATH}" "${descriptor_out_file}" 81 | -------------------------------------------------------------------------------- /.ci/hack/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | * SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Gardener contributors 3 | * 4 | * SPDX-License-Identifier: Apache-2.0 5 | */ 6 | 7 | // This package imports CI related scripts - it is to force `go mod` to see them as dependencies. 8 | package ci 9 | -------------------------------------------------------------------------------- /.ci/hack/generate-controller-registration.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Gardener contributors 4 | # 5 | # SPDX-License-Identifier: Apache-2.0 6 | 7 | set -e 8 | set -o pipefail 9 | 10 | function usage { 11 | cat < [kinds-and-types ...] 14 | 15 | -h, --help Display this help and exit. 16 | --optional Sets 'globallyEnabled: false' for controller resources of the controller registration. 17 | -e, --pod-security-enforce[=pod-security-standard] 18 | Sets 'security.gardener.cloud/pod-security-enforce' annotation in the 19 | controller registration. Defaults to 'baseline'. 20 | Name of the controller registration to generate. 21 | Location of the chart directory. 22 | Version to use for the Helm chart and the tag in the ControllerDeployment. 23 | The destination file to write the registration YAML to. 24 | A tuple of kind and type of the controller registration to generate. 25 | Separated by ':'. 26 | Example: OperatingSystemConfig:foobar 27 | Further tuples of kind and type of the controller registration to generate. 28 | Separated by ':'. 29 | EOM 30 | exit 0 31 | } 32 | 33 | POD_SECURITY_ENFORCE="baseline" 34 | while :; do 35 | case $1 in 36 | -h|--help) 37 | usage 38 | ;; 39 | --optional) 40 | MODE=$'\n globallyEnabled: false' 41 | ;; 42 | -e|--pod-security-enforce) 43 | POD_SECURITY_ENFORCE=$2 44 | shift 45 | ;; 46 | --pod-security-enforce=*) 47 | POD_SECURITY_ENFORCE=${1#*=} 48 | ;; 49 | --) 50 | shift 51 | break 52 | ;; 53 | *) 54 | break 55 | esac 56 | shift 57 | done 58 | 59 | NAME="$1" 60 | CHART_DIR="$2" 61 | VERSION="$3" 62 | DEST="$4" 63 | KIND_AND_TYPE="$5" 64 | 65 | ( [[ -z "$NAME" ]] || [[ -z "$CHART_DIR" ]] || [[ -z "$DEST" ]] || [[ -z "$KIND_AND_TYPE" ]]) && usage 66 | 67 | KINDS_AND_TYPES=("$KIND_AND_TYPE" "${@:6}") 68 | 69 | # The following code is to make `helm package` idempotent: Usually, everytime `helm package` is invoked, 70 | # it produces a different `.tgz` due to modification timestamps and some special shasums of gzip. We 71 | # resolve this by unarchiving the `.tgz`, compressing it again with a constant `mtime` and no gzip 72 | # checksums. 73 | temp_dir="$(mktemp -d)" 74 | temp_helm_home="$(mktemp -d)" 75 | temp_extract_dir="$(mktemp -d)" 76 | function cleanup { 77 | rm -rf "$temp_dir" 78 | rm -rf "$temp_helm_home" 79 | rm -rf "$temp_extract_dir" 80 | } 81 | trap cleanup EXIT ERR INT TERM 82 | 83 | export HELM_HOME="$temp_helm_home" 84 | [ "$(helm version --client --template "{{.Version}}" | head -c2 | tail -c1)" = "3" ] || helm init --client-only > /dev/null 2>&1 85 | helm package "$CHART_DIR" --destination "$temp_dir" > /dev/null 86 | tar -xzm -C "$temp_extract_dir" -f "$temp_dir"/* 87 | chart="$(tar --sort=name -c --owner=root:0 --group=root:0 --mtime='UTC 2019-01-01' -C "$temp_extract_dir" "$(basename "$temp_extract_dir"/*)" | gzip -n | base64 | tr -d '\n')" 88 | 89 | mkdir -p "$(dirname "$DEST")" 90 | 91 | cat < "$DEST" 92 | --- 93 | apiVersion: core.gardener.cloud/v1 94 | kind: ControllerDeployment 95 | metadata: 96 | name: $NAME 97 | helm: 98 | rawChart: $chart 99 | values: 100 | EOM 101 | 102 | if [ -n "$(yq '.image.repository' "$CHART_DIR"/values.yaml)" ] ; then 103 | # image value specifies repository and tag separately, output the image stanza with the given version as tag value 104 | cat <> "$DEST" 105 | image: 106 | tag: $VERSION 107 | EOM 108 | else 109 | # image value specifies a fully-qualified image reference, output the default image plus the given version as tag 110 | default_image="$(yq '.image' "$CHART_DIR"/values.yaml)" 111 | if [ -n "$VERSION" ] ; then 112 | # if a version is given, replace the default tag 113 | default_image="${default_image%%:*}:$VERSION" 114 | fi 115 | 116 | cat <> "$DEST" 117 | image: $default_image 118 | EOM 119 | fi 120 | cat <> "$DEST" 121 | --- 122 | apiVersion: core.gardener.cloud/v1beta1 123 | kind: ControllerRegistration 124 | metadata: 125 | name: $NAME 126 | annotations: 127 | security.gardener.cloud/pod-security-enforce: $POD_SECURITY_ENFORCE 128 | spec: 129 | deployment: 130 | deploymentRefs: 131 | - name: $NAME 132 | resources: 133 | EOM 134 | 135 | for kind_and_type in "${KINDS_AND_TYPES[@]}"; do 136 | KIND="$(echo "$kind_and_type" | cut -d ':' -f 1)" 137 | TYPE="$(echo "$kind_and_type" | cut -d ':' -f 2)" 138 | cat <> "$DEST" 139 | - kind: $KIND 140 | type: $TYPE$MODE 141 | EOM 142 | done 143 | 144 | echo "Successfully generated controller registration at $DEST" 145 | -------------------------------------------------------------------------------- /.ci/hack/prepare_release: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # 3 | # SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Gardener contributors 4 | # 5 | # SPDX-License-Identifier: Apache-2.0 6 | 7 | set -e 8 | 9 | repo_root_dir="$(realpath $1)" 10 | repo_base="$2" 11 | repo_name="$3" 12 | 13 | apk update 14 | apk add --no-cache \ 15 | ca-certificates \ 16 | make \ 17 | bash \ 18 | git \ 19 | curl \ 20 | openssl \ 21 | tar \ 22 | gzip \ 23 | sed \ 24 | jq 25 | 26 | # create virtual package with the dev tools 27 | echo "Installing dev tools in a virtual package" 28 | apk add --no-cache --virtual .build-deps \ 29 | gcc \ 30 | go \ 31 | musl-dev 32 | 33 | GOLANG_VERSION="$(sed -rn 's/FROM (eu\.gcr\.io\/gardener-project\/3rd\/golang|golang):([^ ]+).*/\2/p' < "$repo_root_dir/Dockerfile")" 34 | 35 | # As we cannot expect alpine to provide and maintain all golang versions via apk, we need to find another way to install the required golang version. 36 | # Alpine is using musl-libc instead of glibc, therefore we cannot use the available pre-built binaries from golang, but have to build them ourselves from source. 37 | # refs: 38 | # - https://stackoverflow.com/a/45987284 39 | # - https://github.com/docker-library/golang/blob/f300e60ca19c3b98cfcf01ca112af2ac10104320/1.16/alpine3.14/Dockerfile 40 | echo "Downloading go src $GOLANG_VERSION" 41 | rm -rf /usr/local/go 42 | wget -q -O - "https://golang.org/dl/go$GOLANG_VERSION.src.tar.gz" | tar zx -C /usr/local 43 | 44 | # Configure golang environment 45 | echo "Building and installing go $GOLANG_VERSION" 46 | export \ 47 | PATH="/usr/local/go/bin":$PATH \ 48 | GOARCH="$(go env GOARCH)" \ 49 | GOOS="$(go env GOOS)" \ 50 | GOROOT_BOOTSTRAP="$(go env GOROOT)" 51 | export GOHOSTOS="$GOOS" \ 52 | GOHOSTARCH="$GOARCH" 53 | cd /usr/local/go/src 54 | echo "Executing make on go $GOLANG_VERSION" 55 | ./make.bash 56 | 57 | echo "Deleting the virtual package for go" 58 | apk del --no-network .build-deps 59 | 60 | export GOROOT="/usr/local/go" 61 | export GOPATH="$(mktemp -d)" 62 | export GOBIN="$GOPATH/bin" 63 | export PATH="$GOBIN:$PATH" 64 | 65 | REPO_BASE="$GOPATH/src/$repo_base" 66 | mkdir -p "$REPO_BASE" 67 | REPO_PATH="$REPO_BASE/$repo_name" 68 | cp -R "$repo_root_dir" "$REPO_PATH" 69 | 70 | current_dir="$(pwd)" 71 | cd "$REPO_PATH" 72 | 73 | if make -n install-requirements &>/dev/null; then 74 | make install-requirements 75 | else 76 | echo "skipping optional 'make install-requirements' as it is not present" 77 | fi 78 | 79 | cd "$current_dir" 80 | 81 | echo "$EFFECTIVE_VERSION" > "$REPO_PATH/VERSION" 82 | cur_dir="$(pwd)" 83 | cd "$REPO_PATH" 84 | if ! make generate; then 85 | cd "$cur_dir" 86 | exit 1 87 | fi 88 | cd "$cur_dir" 89 | cp -RT "$REPO_PATH/" "$repo_root_dir/" 90 | -------------------------------------------------------------------------------- /.ci/hack/set_dependency_version: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Gardener contributors 4 | # 5 | # SPDX-License-Identifier: Apache-2.0 6 | 7 | import json 8 | import pathlib 9 | import sys 10 | 11 | import ci.util 12 | 13 | 14 | dependency_type = ci.util.check_env('DEPENDENCY_TYPE') 15 | if not dependency_type == 'component': 16 | ci.util.fail( 17 | "don't know how to upgrade dependency type: " 18 | f'{dependency_type}' 19 | ) 20 | 21 | dependency_name = ci.util.check_env('DEPENDENCY_NAME') 22 | dependency_version = ci.util.check_env('DEPENDENCY_VERSION') 23 | 24 | images_file = pathlib.Path( 25 | ci.util.check_env('REPO_DIR'), 26 | 'imagevector', 27 | 'images.yaml', 28 | ) 29 | 30 | 31 | class ImagesParser(object): 32 | ''' 33 | a naive YAML-parser crafted for the special case of processing 34 | gardener's images.yaml file; crafted that way to preserve 35 | comments/empty lines 36 | ''' 37 | def __init__( 38 | self, 39 | images_file, 40 | names, 41 | target_version, 42 | ): 43 | self.images_file = images_file 44 | self.lines = images_file.read_text().split('\n') 45 | self.names = names 46 | self.target_version = target_version 47 | self._line_idx = 0 48 | 49 | def _line(self): 50 | return self.lines[self._line_idx] 51 | 52 | def _next_line(self): 53 | self._line_idx += 1 54 | return self._line() 55 | 56 | def _skip_to_next_entry(self, names): 57 | while not self._line().startswith('-'): 58 | self._next_line() 59 | name = self._line().strip().split(':')[-1].strip() 60 | 61 | if name not in names: 62 | self._next_line() 63 | return self._skip_to_next_entry(names) 64 | 65 | # found one of the entries: 66 | return name 67 | 68 | def _skip_to_next_tag(self): 69 | self._next_line() 70 | while not self._line().startswith('-'): 71 | if self._line().strip().startswith('tag:'): 72 | return 73 | self._next_line() 74 | raise RuntimeError('did not find tag attribute') 75 | 76 | def set_versions(self): 77 | while self.names: 78 | try: 79 | name = self._skip_to_next_entry(self.names) 80 | except IndexError: 81 | print(str(self.names)) 82 | ci.util.fail('don\'t know how to update ' + str(self.names)) 83 | self.names.remove(name) 84 | self._skip_to_next_tag() 85 | tag_line = self._line() 86 | indent = len(tag_line) - len(tag_line.lstrip()) 87 | patched_line = ' ' * indent + 'tag: "{version}"'.format( 88 | version=self.target_version, 89 | ) 90 | self.lines[self._line_idx] = patched_line 91 | 92 | def write_updated_file(self): 93 | self.images_file.write_text( 94 | '\n'.join(self.lines) 95 | ) 96 | 97 | 98 | # optionally load special cases from first argument given as JSON 99 | injectedSpecialCases = {} 100 | if len(sys.argv) == 2: 101 | injectedSpecialCases = json.loads(sys.argv[1]) 102 | 103 | # handle special cases 104 | name = dependency_name.split('/')[-1] 105 | if name in injectedSpecialCases: 106 | names = injectedSpecialCases[name] 107 | elif name == 'autoscaler': 108 | names = ['cluster-autoscaler'] 109 | elif name == 'vpn2': 110 | names = ['vpn-server', 'vpn-client'] 111 | elif name == 'external-dns-management': 112 | names = ['dns-controller-manager'] 113 | elif name == 'logging': 114 | names = ['fluent-bit-plugin-installer', 'vali-curator', 'telegraf', 'event-logger', 'tune2fs'] 115 | elif name == 'etcd-custom-image': 116 | names = ['etcd'] 117 | elif name == 'egress-filter-refresher': 118 | names = ['egress-filter'] 119 | elif name == 'apiserver-proxy': 120 | names = ['apiserver-proxy-sidecar'] 121 | else: 122 | names = [name] 123 | 124 | 125 | parser = ImagesParser( 126 | images_file=images_file, 127 | names=names, 128 | target_version=dependency_version, 129 | ) 130 | 131 | parser.set_versions() 132 | parser.write_updated_file() 133 | -------------------------------------------------------------------------------- /.ci/pipeline_definitions: -------------------------------------------------------------------------------- 1 | apiserver-proxy: 2 | base_definition: 3 | repo: 4 | source_labels: 5 | - name: cloud.gardener.cnudie/dso/scanning-hints/source_analysis/v1 6 | value: 7 | policy: skip 8 | comment: | 9 | we use gosec for sast scanning. See attached log. 10 | steps: 11 | verify: 12 | image: 'golang:1.23.1' 13 | traits: 14 | component_descriptor: 15 | ocm_repository: europe-docker.pkg.dev/gardener-project/snapshots 16 | component_labels: 17 | - name: 'cloud.gardener.cnudie/responsibles' 18 | value: 19 | - type: 'codeowners' 20 | retention_policy: 'clean-snapshots' 21 | version: 22 | preprocess: 'inject-commit-hash' 23 | publish: 24 | oci-builder: docker-buildx 25 | platforms: 26 | - linux/amd64 27 | - linux/arm64 28 | dockerimages: 29 | apiserver-proxy: 30 | image: europe-docker.pkg.dev/gardener-project/snapshots/gardener/apiserver-proxy 31 | dockerfile: 'cmd/Dockerfile' 32 | target: apiserver-proxy 33 | resource_labels: 34 | - name: 'gardener.cloud/cve-categorisation' 35 | value: 36 | network_exposure: 'private' 37 | authentication_enforced: false 38 | user_interaction: 'end-user' 39 | confidentiality_requirement: 'low' 40 | integrity_requirement: 'high' 41 | availability_requirement: 'high' 42 | jobs: 43 | head-update: 44 | traits: 45 | draft_release: ~ 46 | component_descriptor: 47 | ocm_repository_mappings: 48 | - repository: europe-docker.pkg.dev/gardener-project/releases 49 | pull-request: 50 | traits: 51 | pull-request: ~ 52 | release: 53 | traits: 54 | version: 55 | preprocess: 'finalize' 56 | release: 57 | nextversion: 'bump_minor' 58 | assets: 59 | - type: build-step-log 60 | step_name: verify 61 | purposes: 62 | - lint 63 | - sast 64 | - gosec 65 | comment: | 66 | we use gosec (linter) for SAST scans 67 | see: https://github.com/securego/gosec 68 | enabled by https://github.com/gardener/apiserver-proxy/pull/143 69 | component_descriptor: 70 | ocm_repository: europe-docker.pkg.dev/gardener-project/releases 71 | slack: 72 | default_channel: 'internal_scp_workspace' 73 | channel_cfgs: 74 | internal_scp_workspace: 75 | channel_name: 'C9CEBQPGE' #sap-tech-gardener 76 | slack_cfg_name: 'scp_workspace' 77 | publish: 78 | oci-builder: docker-buildx 79 | platforms: 80 | - linux/amd64 81 | - linux/arm64 82 | dockerimages: 83 | apiserver-proxy: 84 | image: europe-docker.pkg.dev/gardener-project/releases/gardener/apiserver-proxy 85 | tag_as_latest: true 86 | -------------------------------------------------------------------------------- /.ci/verify: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | set -o pipefail 6 | 7 | cd "$(dirname $0)/.." 8 | 9 | git config --global user.email "gardener@sap.com" 10 | git config --global user.name "Gardener CI/CD" 11 | 12 | make verify-extended 13 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .github 3 | .reuse 4 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug Report 3 | about: Report a bug encountered while working with this Gardener extension 4 | labels: kind/bug 5 | 6 | --- 7 | 8 | **What happened**: 9 | 10 | **What you expected to happen**: 11 | 12 | **How to reproduce it (as minimally and precisely as possible)**: 13 | 14 | **Anything else we need to know?**: 15 | 16 | **Environment**: 17 | 18 | - Gardener version (if relevant): 19 | - Extension version: 20 | - Kubernetes version (use `kubectl version`): 21 | - Cloud provider or hardware configuration: 22 | - Others: 23 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Enhancement Request 3 | about: Suggest an enhancement for this extension 4 | labels: kind/enhancement 5 | 6 | --- 7 | 8 | **What would you like to be added**: 9 | 10 | **Why is this needed**: 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/support.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Support Request 3 | about: Support request or question relating to this extension 4 | labels: kind/question 5 | 6 | --- 7 | 8 | 15 | -------------------------------------------------------------------------------- /.github/dependabot.yaml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | # Create PRs for github.com/gardener/gardener dependency updates 4 | - package-ecosystem: gomod 5 | directory: / 6 | schedule: 7 | interval: daily 8 | open-pull-requests-limit: 5 9 | allow: 10 | - dependency-name: "github.com/gardener/gardener" 11 | # Create PRs for golang version updates 12 | - package-ecosystem: docker 13 | directory: /cmd 14 | schedule: 15 | interval: daily -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | **What this PR does / why we need it**: 2 | 3 | **Which issue(s) this PR fixes**: 4 | Fixes # 5 | 6 | **Special notes for your reviewer**: 7 | 8 | **Release note**: 9 | 18 | ```improvement operator 19 | 20 | ``` 21 | -------------------------------------------------------------------------------- /.github/workflows/vendor_gardener.yaml: -------------------------------------------------------------------------------- 1 | name: Vendor Gardener 2 | on: 3 | push: 4 | branches: 5 | - dependabot/go_modules/github.com/gardener/** 6 | permissions: write-all 7 | jobs: 8 | run: 9 | name: Run make tidy 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v3 13 | - uses: actions/setup-go@v3 14 | with: 15 | go-version-file: go.mod 16 | 17 | - name: Make tidy 18 | run: make tidy 19 | - name: Commit changes 20 | run: | 21 | # Exit early if there is nothing to commit. This can happen if someone pushes to the dependabot's PR (for example has to adapt to a breaking change). 22 | if [[ -z $(git status --porcelain) ]]; then 23 | echo "Nothing to commit, working tree clean. Exiting..." 24 | exit 0 25 | fi 26 | 27 | git config user.name gardener-robot-ci-1 28 | git config user.email gardener.ci.user@gmail.com 29 | git add . 30 | git commit -m "[dependabot skip] make tidy" 31 | git push origin -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /bin 2 | /.kube-secrets 3 | /tmp/* 4 | /dev 5 | hack/tools/bin 6 | 7 | .vscode 8 | .idea 9 | .DS_Store 10 | .cache_ggshield 11 | 12 | TODO 13 | 14 | # gosec 15 | gosec-report.sarif 16 | -------------------------------------------------------------------------------- /.reuse/dep5: -------------------------------------------------------------------------------- 1 | Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: Gardener apiserver-proxy 3 | Upstream-Contact: The Gardener project 4 | Source: https://github.com/gardener/apiserver-proxy 5 | 6 | # -------------------------------------------------- 7 | # source code 8 | 9 | Files: * 10 | Copyright: 2017-2024 SAP SE or an SAP affiliate company and Gardener contributors 11 | License: Apache-2.0 12 | 13 | # -------------------------------------------------- 14 | # documentation 15 | 16 | Files: *.md 17 | Copyright: 2017-2024 SAP SE or an SAP affiliate company and Gardener contributors 18 | License: CC-BY-4.0 19 | 20 | # -------------------------------------------------- 21 | # third-party 22 | 23 | # --- copied source code --- 24 | # Files: 25 | # Copyright: 26 | # License: 27 | 28 | # --- vendor folder dependencies --- 29 | # Files: 30 | # Copyright: 31 | # License: -------------------------------------------------------------------------------- /CODEOWNERS: -------------------------------------------------------------------------------- 1 | # gardener maintainers 2 | * @gardener/apiserver-proxy-maintainers 3 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | Please refer to the [Gardener contributor guide](https://gardener.cloud/docs/contribute). -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /LICENSES/Apache-2.0.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /LICENSES/CC-BY-4.0.txt: -------------------------------------------------------------------------------- 1 | Creative Commons Attribution 4.0 International 2 | 3 | Creative Commons Corporation (“Creative Commons”) is not a law firm and does 4 | not provide legal services or legal advice. Distribution of Creative Commons 5 | public licenses does not create a lawyer-client or other relationship. Creative 6 | Commons makes its licenses and related information available on an “as-is” 7 | basis. Creative Commons gives no warranties regarding its licenses, any material 8 | licensed under their terms and conditions, or any related information. Creative 9 | Commons disclaims all liability for damages resulting from their use to the 10 | fullest extent possible. 11 | 12 | Using Creative Commons Public Licenses 13 | 14 | Creative Commons public licenses provide a standard set of terms and conditions 15 | that creators and other rights holders may use to share original works of 16 | authorship and other material subject to copyright and certain other rights 17 | specified in the public license below. The following considerations are for 18 | informational purposes only, are not exhaustive, and do not form part of our 19 | licenses. 20 | 21 | Considerations for licensors: Our public licenses are intended for use by 22 | those authorized to give the public permission to use material in ways otherwise 23 | restricted by copyright and certain other rights. Our licenses are irrevocable. 24 | Licensors should read and understand the terms and conditions of the license 25 | they choose before applying it. Licensors should also secure all rights necessary 26 | before applying our licenses so that the public can reuse the material as 27 | expected. Licensors should clearly mark any material not subject to the license. 28 | This includes other CC-licensed material, or material used under an exception 29 | or limitation to copyright. More considerations for licensors. 30 | 31 | Considerations for the public: By using one of our public licenses, a licensor 32 | grants the public permission to use the licensed material under specified 33 | terms and conditions. If the licensor’s permission is not necessary for any 34 | reason–for example, because of any applicable exception or limitation to copyright–then 35 | that use is not regulated by the license. Our licenses grant only permissions 36 | under copyright and certain other rights that a licensor has authority to 37 | grant. Use of the licensed material may still be restricted for other reasons, 38 | including because others have copyright or other rights in the material. A 39 | licensor may make special requests, such as asking that all changes be marked 40 | or described. Although not required by our licenses, you are encouraged to 41 | respect those requests where reasonable. More considerations for the public. 42 | 43 | Creative Commons Attribution 4.0 International Public License 44 | 45 | By exercising the Licensed Rights (defined below), You accept and agree to 46 | be bound by the terms and conditions of this Creative Commons Attribution 47 | 4.0 International Public License ("Public License"). To the extent this Public 48 | License may be interpreted as a contract, You are granted the Licensed Rights 49 | in consideration of Your acceptance of these terms and conditions, and the 50 | Licensor grants You such rights in consideration of benefits the Licensor 51 | receives from making the Licensed Material available under these terms and 52 | conditions. 53 | 54 | Section 1 – Definitions. 55 | 56 | a. Adapted Material means material subject to Copyright and Similar Rights 57 | that is derived from or based upon the Licensed Material and in which the 58 | Licensed Material is translated, altered, arranged, transformed, or otherwise 59 | modified in a manner requiring permission under the Copyright and Similar 60 | Rights held by the Licensor. For purposes of this Public License, where the 61 | Licensed Material is a musical work, performance, or sound recording, Adapted 62 | Material is always produced where the Licensed Material is synched in timed 63 | relation with a moving image. 64 | 65 | b. Adapter's License means the license You apply to Your Copyright and Similar 66 | Rights in Your contributions to Adapted Material in accordance with the terms 67 | and conditions of this Public License. 68 | 69 | c. Copyright and Similar Rights means copyright and/or similar rights closely 70 | related to copyright including, without limitation, performance, broadcast, 71 | sound recording, and Sui Generis Database Rights, without regard to how the 72 | rights are labeled or categorized. For purposes of this Public License, the 73 | rights specified in Section 2(b)(1)-(2) are not Copyright and Similar Rights. 74 | 75 | d. Effective Technological Measures means those measures that, in the absence 76 | of proper authority, may not be circumvented under laws fulfilling obligations 77 | under Article 11 of the WIPO Copyright Treaty adopted on December 20, 1996, 78 | and/or similar international agreements. 79 | 80 | e. Exceptions and Limitations means fair use, fair dealing, and/or any other 81 | exception or limitation to Copyright and Similar Rights that applies to Your 82 | use of the Licensed Material. 83 | 84 | f. Licensed Material means the artistic or literary work, database, or other 85 | material to which the Licensor applied this Public License. 86 | 87 | g. Licensed Rights means the rights granted to You subject to the terms and 88 | conditions of this Public License, which are limited to all Copyright and 89 | Similar Rights that apply to Your use of the Licensed Material and that the 90 | Licensor has authority to license. 91 | 92 | h. Licensor means the individual(s) or entity(ies) granting rights under this 93 | Public License. 94 | 95 | i. Share means to provide material to the public by any means or process that 96 | requires permission under the Licensed Rights, such as reproduction, public 97 | display, public performance, distribution, dissemination, communication, or 98 | importation, and to make material available to the public including in ways 99 | that members of the public may access the material from a place and at a time 100 | individually chosen by them. 101 | 102 | j. Sui Generis Database Rights means rights other than copyright resulting 103 | from Directive 96/9/EC of the European Parliament and of the Council of 11 104 | March 1996 on the legal protection of databases, as amended and/or succeeded, 105 | as well as other essentially equivalent rights anywhere in the world. 106 | 107 | k. You means the individual or entity exercising the Licensed Rights under 108 | this Public License. Your has a corresponding meaning. 109 | 110 | Section 2 – Scope. 111 | 112 | a. License grant. 113 | 114 | 1. Subject to the terms and conditions of this Public License, the Licensor 115 | hereby grants You a worldwide, royalty-free, non-sublicensable, non-exclusive, 116 | irrevocable license to exercise the Licensed Rights in the Licensed Material 117 | to: 118 | 119 | A. reproduce and Share the Licensed Material, in whole or in part; and 120 | 121 | B. produce, reproduce, and Share Adapted Material. 122 | 123 | 2. Exceptions and Limitations. For the avoidance of doubt, where Exceptions 124 | and Limitations apply to Your use, this Public License does not apply, and 125 | You do not need to comply with its terms and conditions. 126 | 127 | 3. Term. The term of this Public License is specified in Section 6(a). 128 | 129 | 4. Media and formats; technical modifications allowed. The Licensor authorizes 130 | You to exercise the Licensed Rights in all media and formats whether now known 131 | or hereafter created, and to make technical modifications necessary to do 132 | so. The Licensor waives and/or agrees not to assert any right or authority 133 | to forbid You from making technical modifications necessary to exercise the 134 | Licensed Rights, including technical modifications necessary to circumvent 135 | Effective Technological Measures. For purposes of this Public License, simply 136 | making modifications authorized by this Section 2(a)(4) never produces Adapted 137 | Material. 138 | 139 | 5. Downstream recipients. 140 | 141 | A. Offer from the Licensor – Licensed Material. Every recipient of the Licensed 142 | Material automatically receives an offer from the Licensor to exercise the 143 | Licensed Rights under the terms and conditions of this Public License. 144 | 145 | B. No downstream restrictions. You may not offer or impose any additional 146 | or different terms or conditions on, or apply any Effective Technological 147 | Measures to, the Licensed Material if doing so restricts exercise of the Licensed 148 | Rights by any recipient of the Licensed Material. 149 | 150 | 6. No endorsement. Nothing in this Public License constitutes or may be construed 151 | as permission to assert or imply that You are, or that Your use of the Licensed 152 | Material is, connected with, or sponsored, endorsed, or granted official status 153 | by, the Licensor or others designated to receive attribution as provided in 154 | Section 3(a)(1)(A)(i). 155 | 156 | b. Other rights. 157 | 158 | 1. Moral rights, such as the right of integrity, are not licensed under this 159 | Public License, nor are publicity, privacy, and/or other similar personality 160 | rights; however, to the extent possible, the Licensor waives and/or agrees 161 | not to assert any such rights held by the Licensor to the limited extent necessary 162 | to allow You to exercise the Licensed Rights, but not otherwise. 163 | 164 | 2. Patent and trademark rights are not licensed under this Public License. 165 | 166 | 3. To the extent possible, the Licensor waives any right to collect royalties 167 | from You for the exercise of the Licensed Rights, whether directly or through 168 | a collecting society under any voluntary or waivable statutory or compulsory 169 | licensing scheme. In all other cases the Licensor expressly reserves any right 170 | to collect such royalties. 171 | 172 | Section 3 – License Conditions. 173 | 174 | Your exercise of the Licensed Rights is expressly made subject to the following 175 | conditions. 176 | 177 | a. Attribution. 178 | 179 | 1. If You Share the Licensed Material (including in modified form), You must: 180 | 181 | A. retain the following if it is supplied by the Licensor with the Licensed 182 | Material: 183 | 184 | i. identification of the creator(s) of the Licensed Material and any others 185 | designated to receive attribution, in any reasonable manner requested by the 186 | Licensor (including by pseudonym if designated); 187 | 188 | ii. a copyright notice; 189 | 190 | iii. a notice that refers to this Public License; 191 | 192 | iv. a notice that refers to the disclaimer of warranties; 193 | 194 | v. a URI or hyperlink to the Licensed Material to the extent reasonably practicable; 195 | 196 | B. indicate if You modified the Licensed Material and retain an indication 197 | of any previous modifications; and 198 | 199 | C. indicate the Licensed Material is licensed under this Public License, and 200 | include the text of, or the URI or hyperlink to, this Public License. 201 | 202 | 2. You may satisfy the conditions in Section 3(a)(1) in any reasonable manner 203 | based on the medium, means, and context in which You Share the Licensed Material. 204 | For example, it may be reasonable to satisfy the conditions by providing a 205 | URI or hyperlink to a resource that includes the required information. 206 | 207 | 3. If requested by the Licensor, You must remove any of the information required 208 | by Section 3(a)(1)(A) to the extent reasonably practicable. 209 | 210 | 4. If You Share Adapted Material You produce, the Adapter's License You apply 211 | must not prevent recipients of the Adapted Material from complying with this 212 | Public License. 213 | 214 | Section 4 – Sui Generis Database Rights. 215 | 216 | Where the Licensed Rights include Sui Generis Database Rights that apply to 217 | Your use of the Licensed Material: 218 | 219 | a. for the avoidance of doubt, Section 2(a)(1) grants You the right to extract, 220 | reuse, reproduce, and Share all or a substantial portion of the contents of 221 | the database; 222 | 223 | b. if You include all or a substantial portion of the database contents in 224 | a database in which You have Sui Generis Database Rights, then the database 225 | in which You have Sui Generis Database Rights (but not its individual contents) 226 | is Adapted Material; and 227 | 228 | c. You must comply with the conditions in Section 3(a) if You Share all or 229 | a substantial portion of the contents of the database. 230 | For the avoidance of doubt, this Section 4 supplements and does not replace 231 | Your obligations under this Public License where the Licensed Rights include 232 | other Copyright and Similar Rights. 233 | 234 | Section 5 – Disclaimer of Warranties and Limitation of Liability. 235 | 236 | a. Unless otherwise separately undertaken by the Licensor, to the extent possible, 237 | the Licensor offers the Licensed Material as-is and as-available, and makes 238 | no representations or warranties of any kind concerning the Licensed Material, 239 | whether express, implied, statutory, or other. This includes, without limitation, 240 | warranties of title, merchantability, fitness for a particular purpose, non-infringement, 241 | absence of latent or other defects, accuracy, or the presence or absence of 242 | errors, whether or not known or discoverable. Where disclaimers of warranties 243 | are not allowed in full or in part, this disclaimer may not apply to You. 244 | 245 | b. To the extent possible, in no event will the Licensor be liable to You 246 | on any legal theory (including, without limitation, negligence) or otherwise 247 | for any direct, special, indirect, incidental, consequential, punitive, exemplary, 248 | or other losses, costs, expenses, or damages arising out of this Public License 249 | or use of the Licensed Material, even if the Licensor has been advised of 250 | the possibility of such losses, costs, expenses, or damages. Where a limitation 251 | of liability is not allowed in full or in part, this limitation may not apply 252 | to You. 253 | 254 | c. The disclaimer of warranties and limitation of liability provided above 255 | shall be interpreted in a manner that, to the extent possible, most closely 256 | approximates an absolute disclaimer and waiver of all liability. 257 | 258 | Section 6 – Term and Termination. 259 | 260 | a. This Public License applies for the term of the Copyright and Similar Rights 261 | licensed here. However, if You fail to comply with this Public License, then 262 | Your rights under this Public License terminate automatically. 263 | 264 | b. Where Your right to use the Licensed Material has terminated under Section 265 | 6(a), it reinstates: 266 | 267 | 1. automatically as of the date the violation is cured, provided it is cured 268 | within 30 days of Your discovery of the violation; or 269 | 270 | 2. upon express reinstatement by the Licensor. 271 | 272 | c. For the avoidance of doubt, this Section 6(b) does not affect any right 273 | the Licensor may have to seek remedies for Your violations of this Public 274 | License. 275 | 276 | d. For the avoidance of doubt, the Licensor may also offer the Licensed Material 277 | under separate terms or conditions or stop distributing the Licensed Material 278 | at any time; however, doing so will not terminate this Public License. 279 | 280 | e. Sections 1, 5, 6, 7, and 8 survive termination of this Public License. 281 | 282 | Section 7 – Other Terms and Conditions. 283 | 284 | a. The Licensor shall not be bound by any additional or different terms or 285 | conditions communicated by You unless expressly agreed. 286 | 287 | b. Any arrangements, understandings, or agreements regarding the Licensed 288 | Material not stated herein are separate from and independent of the terms 289 | and conditions of this Public License. 290 | 291 | Section 8 – Interpretation. 292 | 293 | a. For the avoidance of doubt, this Public License does not, and shall not 294 | be interpreted to, reduce, limit, restrict, or impose conditions on any use 295 | of the Licensed Material that could lawfully be made without permission under 296 | this Public License. 297 | 298 | b. To the extent possible, if any provision of this Public License is deemed 299 | unenforceable, it shall be automatically reformed to the minimum extent necessary 300 | to make it enforceable. If the provision cannot be reformed, it shall be severed 301 | from this Public License without affecting the enforceability of the remaining 302 | terms and conditions. 303 | 304 | c. No term or condition of this Public License will be waived and no failure 305 | to comply consented to unless expressly agreed to by the Licensor. 306 | 307 | d. Nothing in this Public License constitutes or may be interpreted as a limitation 308 | upon, or waiver of, any privileges and immunities that apply to the Licensor 309 | or You, including from the legal processes of any jurisdiction or authority. 310 | 311 | Creative Commons is not a party to its public licenses. Notwithstanding, Creative 312 | Commons may elect to apply one of its public licenses to material it publishes 313 | and in those instances will be considered the “Licensor.” Except for the limited 314 | purpose of indicating that material is shared under a Creative Commons public 315 | license or as otherwise permitted by the Creative Commons policies published 316 | at creativecommons.org/policies, Creative Commons does not authorize the use 317 | of the trademark “Creative Commons” or any other trademark or logo of Creative 318 | Commons without its prior written consent including, without limitation, in 319 | connection with any unauthorized modifications to any of its public licenses 320 | or any other arrangements, understandings, or agreements concerning use of 321 | licensed material. For the avoidance of doubt, this paragraph does not form 322 | part of the public licenses. 323 | 324 | Creative Commons may be contacted at creativecommons.org. 325 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-FileCopyrightText: 2020 SAP SE or an SAP affiliate company and Gardener contributors 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | ENSURE_GARDENER_MOD := $(shell go get github.com/gardener/gardener@$$(go list -m -f "{{.Version}}" github.com/gardener/gardener)) 5 | GARDENER_HACK_DIR := $(shell go list -m -f "{{.Dir}}" github.com/gardener/gardener)/hack 6 | REGISTRY := europe-docker.pkg.dev/gardener-project/public/gardener 7 | APISERVER_PROXY_SIDECAR_IMAGE_REPOSITORY := $(REGISTRY)/apiserver-proxy 8 | REPO_ROOT := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) 9 | HACK_DIR := $(REPO_ROOT)/hack 10 | VERSION := $(shell cat VERSION) 11 | EFFECTIVE_VERSION := $(VERSION)-$(shell git rev-parse HEAD) 12 | LD_FLAGS := "-X github.com/gardener/apiserver-proxy/internal/version.version=$(EFFECTIVE_VERSION)" 13 | GOARCH := amd64 14 | ######################################### 15 | # Tools # 16 | ######################################### 17 | 18 | TOOLS_DIR := hack/tools 19 | include $(GARDENER_HACK_DIR)/tools.mk 20 | 21 | ################################################################# 22 | # Rules related to binary build, Docker image build and release # 23 | ################################################################# 24 | 25 | .PHONY: build 26 | build: 27 | @CGO_ENABLED=0 GOARCH=$(GOARCH) GO111MODULE=on go build -ldflags $(LD_FLAGS) -o bin/apiserver-proxy-sidecar ./cmd/apiserver-proxy-sidecar 28 | 29 | .PHONY: docker-images 30 | docker-images: 31 | @echo "Building docker images with version and tag $(EFFECTIVE_VERSION)" 32 | @docker build --build-arg EFFECTIVE_VERSION=$(EFFECTIVE_VERSION) -t $(APISERVER_PROXY_SIDECAR_IMAGE_REPOSITORY):$(EFFECTIVE_VERSION) --platform=linux/$(GOARCH) -f cmd/Dockerfile --target apiserver-proxy . 33 | 34 | ##################################################################### 35 | # Rules for verification, formatting, linting, testing and cleaning # 36 | ##################################################################### 37 | 38 | 39 | .PHONY: tidy 40 | tidy: 41 | @go mod tidy 42 | @mkdir -p $(REPO_ROOT)/.ci/hack && cp $(GARDENER_HACK_DIR)/.ci/* $(GARDENER_HACK_DIR)/generate-controller-registration.sh $(REPO_ROOT)/.ci/hack/ && chmod +xw $(REPO_ROOT)/.ci/hack/* 43 | @cp $(GARDENER_HACK_DIR)/cherry-pick-pull.sh $(HACK_DIR)/cherry-pick-pull.sh && chmod +xw $(HACK_DIR)/cherry-pick-pull.sh 44 | @cp $(GARDENER_HACK_DIR)/sast.sh $(HACK_DIR)/sast.sh && chmod +xw $(HACK_DIR)/sast.sh 45 | 46 | .PHONY: check 47 | check: $(GOIMPORTS) $(GOLANGCI_LINT) 48 | @bash $(GARDENER_HACK_DIR)//check.sh ./cmd/... ./internal/... 49 | 50 | .PHONY: format 51 | format: $(GOIMPORTS) $(GOIMPORTSREVISER) 52 | @bash $(GARDENER_HACK_DIR)/format.sh ./cmd ./internal 53 | 54 | # TODO(scheererj): Remove once https://github.com/gardener/gardener/pull/10642 is available as release. 55 | TOOLS_PKG_PATH := $(shell go list -tags tools -f '{{ .Dir }}' github.com/gardener/gardener/hack/tools 2>/dev/null) 56 | .PHONY: adjust-install-gosec.sh 57 | adjust-install-gosec.sh: 58 | @chmod +xw $(TOOLS_PKG_PATH)/install-gosec.sh 59 | 60 | .PHONY: sast 61 | sast: adjust-install-gosec.sh $(GOSEC) 62 | @./hack/sast.sh 63 | 64 | .PHONY: sast-report 65 | sast-report: adjust-install-gosec.sh $(GOSEC) 66 | @./hack/sast.sh --gosec-report true 67 | 68 | .PHONY: test 69 | test: 70 | @bash $(GARDENER_HACK_DIR)/test.sh ./cmd/... ./internal/... 71 | 72 | .PHONY: test-cov 73 | test-cov: 74 | @bash $(GARDENER_HACK_DIR)/test-cover.sh ./cmd/... ./internal/... 75 | 76 | .PHONY: test-cov-clean 77 | test-cov-clean: 78 | @bash $(GARDENER_HACK_DIR)/test-cover-clean.sh 79 | 80 | .PHONY: verify 81 | verify: check format test sast 82 | 83 | .PHONY: verify-extended 84 | verify-extended: check format test-cov test-cov-clean sast-report 85 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # API Server proxy 2 | [![REUSE status](https://api.reuse.software/badge/github.com/gardener/apiserver-proxy)](https://api.reuse.software/info/github.com/gardener/apiserver-proxy) 3 | 4 | This repository contains the API Server proxy sidecar. 5 | 6 | The API Server proxy pod webhook is now included in the [Gardener Resource Manager](https://github.com/gardener/gardener/blob/master/docs/concepts/resource-manager.md#kubernetes-service-host-injection). 7 | 8 | ## API Server proxy sidecar 9 | 10 | This component consists of `apiserver-proxy-sidecar` which runs on every `Node` in a `Shoot` cluster. 11 | It does the following: 12 | 13 | 1. adds the IP Address (`--ip-address` flag) to the loopback interface (`--interface` flag). 14 | 15 | 1. Every 1 min repeats the process and starts from `1.` 16 | 17 | After this, the actual `apiserver-proxy` can listen on this IP address (`10.96.0.2`) and send traffic to the correct kube-apiserver. 18 | The implementation of that proxy is fully transparent and can be replaced at any given moment without any modifications to the `apiserver-proxy-sidecar`. 19 | 20 | ### Sidecar command line options 21 | 22 | ```console 23 | go run ./cmd/apiserver-proxy-sidecar --help 24 | --add_dir_header If true, adds the file directory to the header 25 | --alsologtostderr log to standard error as well as files 26 | --cleanup [optional] indicates whether created interface should be removed on exit. 27 | --daemon [optional] indicates if the sidecar should run as a daemon (default true) 28 | --interface string [optional] name of the interface to add address to. (default "lo") 29 | --ip-address string ip-address on which the proxy is listening. 30 | --log_backtrace_at traceLocation when logging hits line file:N, emit a stack trace (default :0) 31 | --log_dir string If non-empty, write log files in this directory 32 | --log_file string If non-empty, use this log file 33 | --log_file_max_size uint Defines the maximum size a log file can grow to. Unit is megabytes. If the value is 0, the maximum file size is unlimited. (default 1800) 34 | --logtostderr log to standard error instead of files (default true) 35 | --port string [optional] port on which the proxy is listening. (default "443") 36 | --skip_headers If true, avoid header prefixes in the log messages 37 | --skip_log_headers If true, avoid headers when opening log files 38 | --stderrthreshold severity logs at or above this threshold go to stderr (default 2) 39 | --sync-interval duration [optional] interval to check for the added interface. (default 1m0s) 40 | -v, --v Level number for the log level verbosity 41 | --vmodule moduleSpec comma-separated list of pattern=N settings for file-filtered logging 42 | ``` 43 | 44 | ## Development 45 | 46 | ### Update dependencies 47 | 48 | ```shell 49 | make tidy 50 | ``` 51 | 52 | ### Building container images 53 | 54 | ```shell 55 | make docker-images 56 | ``` 57 | 58 | ### Testing 59 | 60 | ```shell 61 | make test 62 | ``` 63 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | v0.20.0-dev -------------------------------------------------------------------------------- /cmd/Dockerfile: -------------------------------------------------------------------------------- 1 | ############# builder ############# 2 | FROM --platform=${BUILDPLATFORM} golang:1.23.6 AS builder 3 | 4 | WORKDIR /go/src/github.com/gardener/apiserver-proxy 5 | COPY . . 6 | 7 | ARG BUILDPLATFORM 8 | ARG TARGETARCH 9 | ARG EFFECTIVE_VERSION 10 | 11 | # Copy go mod and sum files 12 | COPY go.mod go.sum ./ 13 | # Download all dependencies. Dependencies will be cached if the go.mod and go.sum files are not changed 14 | RUN go mod download 15 | 16 | RUN make build GOARCH=$TARGETARCH EFFECTIVE_VERSION=$EFFECTIVE_VERSION 17 | 18 | ############# apiserver-proxy-builder ############# 19 | FROM alpine:3.21.3 AS apiserver-proxy-builder 20 | 21 | RUN apk add --no-cache iproute2-minimal 22 | 23 | WORKDIR /volume 24 | 25 | COPY --from=builder /go/src/github.com/gardener/apiserver-proxy/bin/apiserver-proxy-sidecar ./apiserver-proxy-sidecar 26 | 27 | RUN mkdir -p ./sbin ./lib ./usr/lib ./tmp ./run ./etc/iproute2 \ 28 | && cp -d /lib/ld-musl-* ./lib && echo "package musl" \ 29 | && cp -d /lib/libc.musl-* ./lib && echo "package musl" \ 30 | && cp -d /usr/lib/libcap.* ./usr/lib && echo "package libcap2" \ 31 | && cp -d /usr/lib/libpsx.* ./usr/lib && echo "package libcap2" \ 32 | && cp -d /usr/lib/libz.* ./lib && echo "package zlib" \ 33 | && cp -d /usr/lib/libzstd.* ./lib && echo "package zstd-libs" \ 34 | && cp -d /usr/lib/libelf* ./usr/lib && echo "package libelf" \ 35 | && cp -d /usr/lib/libmnl.* ./usr/lib && echo "package libmnl" \ 36 | && cp -d /sbin/ip ./sbin && echo "package iproute2-minimal" 37 | 38 | ############# apiserver-proxy ############# 39 | FROM scratch AS apiserver-proxy 40 | 41 | WORKDIR / 42 | 43 | COPY --from=apiserver-proxy-builder /volume / 44 | 45 | USER 0:0 46 | 47 | ENTRYPOINT ["/apiserver-proxy-sidecar"] 48 | -------------------------------------------------------------------------------- /cmd/apiserver-proxy-sidecar/main.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2020 SAP SE or an SAP affiliate company and Gardener contributors 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package main 5 | 6 | import ( 7 | goflag "flag" 8 | "fmt" 9 | "os" 10 | "time" 11 | 12 | flag "github.com/spf13/pflag" 13 | "k8s.io/klog/v2" 14 | "sigs.k8s.io/controller-runtime/pkg/manager/signals" 15 | 16 | "github.com/gardener/apiserver-proxy/internal/app" 17 | "github.com/gardener/apiserver-proxy/internal/version" 18 | ) 19 | 20 | func parseAndValidateFlags() *app.ConfigParams { 21 | params := &app.ConfigParams{} 22 | 23 | cmd := goflag.CommandLine 24 | klog.InitFlags(cmd) 25 | flag.CommandLine.AddGoFlagSet(cmd) 26 | 27 | flag.StringVar(¶ms.Interface, "interface", "lo", "[optional] name of the interface to add address to.") 28 | flag.DurationVar(¶ms.Interval, "sync-interval", time.Minute, "[optional] interval to check for the added interface.") 29 | flag.BoolVar(¶ms.Cleanup, "cleanup", false, 30 | "[optional] indicates whether created interface should be removed on exit.") 31 | flag.BoolVar(¶ms.Daemon, "daemon", true, 32 | "[optional] indicates if the sidecar should run as a daemon") 33 | flag.StringVar(¶ms.IPAddress, "ip-address", "", "ip-address on which the proxy is listening (e.g. 1.2.3.4).") 34 | flag.StringVar(¶ms.LocalPort, "port", "9443", "[optional] port on which the proxy is listening.") 35 | 36 | flag.Usage = func() { 37 | fmt.Fprintf(os.Stderr, "Usage of %s (%s):\n", os.Args[0], version.Version()) 38 | flag.PrintDefaults() 39 | } 40 | 41 | flag.Parse() 42 | 43 | if params.IPAddress == "" { 44 | klog.Errorln("--ip-address is required") 45 | os.Exit(1) 46 | } 47 | 48 | return params 49 | } 50 | 51 | func main() { 52 | params := parseAndValidateFlags() 53 | 54 | app, err := app.NewSidecarApp(params) 55 | if err != nil { 56 | klog.Fatalf("Failed to create sidecar application, err %v", err) 57 | } 58 | 59 | app.RunApp(signals.SetupSignalHandler()) 60 | } 61 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/gardener/apiserver-proxy 2 | 3 | go 1.23.0 4 | 5 | toolchain go1.23.1 6 | 7 | require ( 8 | github.com/gardener/gardener v1.112.2 9 | github.com/onsi/ginkgo v1.16.5 10 | github.com/onsi/gomega v1.36.2 11 | github.com/spf13/pflag v1.0.6 12 | github.com/vishvananda/netlink v1.0.0 13 | go.uber.org/mock v0.5.0 14 | golang.org/x/tools v0.29.0 15 | golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 16 | k8s.io/klog/v2 v2.130.1 17 | sigs.k8s.io/controller-runtime v0.19.5 18 | ) 19 | 20 | require ( 21 | github.com/ahmetb/gen-crd-api-reference-docs v0.3.0 // indirect 22 | github.com/emicklei/go-restful/v3 v3.12.1 // indirect 23 | github.com/fatih/color v1.18.0 // indirect 24 | github.com/fsnotify/fsnotify v1.8.0 // indirect 25 | github.com/fxamacker/cbor/v2 v2.7.0 // indirect 26 | github.com/go-logr/logr v1.4.2 // indirect 27 | github.com/go-logr/zapr v1.3.0 // indirect 28 | github.com/go-openapi/jsonpointer v0.21.0 // indirect 29 | github.com/go-openapi/jsonreference v0.21.0 // indirect 30 | github.com/go-openapi/swag v0.23.0 // indirect 31 | github.com/go-task/slim-sprig/v3 v3.0.0 // indirect 32 | github.com/gobuffalo/flect v1.0.3 // indirect 33 | github.com/gogo/protobuf v1.3.2 // indirect 34 | github.com/google/gnostic-models v0.6.9 // indirect 35 | github.com/google/go-cmp v0.6.0 // indirect 36 | github.com/google/gofuzz v1.2.0 // indirect 37 | github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad // indirect 38 | github.com/inconshreveable/mousetrap v1.1.0 // indirect 39 | github.com/ironcore-dev/vgopath v0.1.5 // indirect 40 | github.com/josharian/intern v1.0.0 // indirect 41 | github.com/json-iterator/go v1.1.12 // indirect 42 | github.com/mailru/easyjson v0.7.7 // indirect 43 | github.com/mattn/go-colorable v0.1.13 // indirect 44 | github.com/mattn/go-isatty v0.0.20 // indirect 45 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 46 | github.com/modern-go/reflect2 v1.0.2 // indirect 47 | github.com/nxadm/tail v1.4.8 // indirect 48 | github.com/onsi/ginkgo/v2 v2.22.1 // indirect 49 | github.com/pkg/errors v0.9.1 // indirect 50 | github.com/russross/blackfriday/v2 v2.1.0 // indirect 51 | github.com/spf13/afero v1.12.0 // indirect 52 | github.com/spf13/cobra v1.8.1 // indirect 53 | github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f // indirect 54 | github.com/x448/float16 v0.8.4 // indirect 55 | go.uber.org/multierr v1.11.0 // indirect 56 | go.uber.org/zap v1.27.0 // indirect 57 | golang.org/x/mod v0.22.0 // indirect 58 | golang.org/x/net v0.34.0 // indirect 59 | golang.org/x/sync v0.11.0 // indirect 60 | golang.org/x/sys v0.29.0 // indirect 61 | golang.org/x/text v0.22.0 // indirect 62 | google.golang.org/protobuf v1.36.1 // indirect 63 | gopkg.in/inf.v0 v0.9.1 // indirect 64 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect 65 | gopkg.in/yaml.v2 v2.4.0 // indirect 66 | gopkg.in/yaml.v3 v3.0.1 // indirect 67 | k8s.io/api v0.31.5 // indirect 68 | k8s.io/apiextensions-apiserver v0.31.5 // indirect 69 | k8s.io/apimachinery v0.31.5 // indirect 70 | k8s.io/code-generator v0.31.5 // indirect 71 | k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 // indirect 72 | k8s.io/gengo/v2 v2.0.0-20240826214909-a7b603a56eb7 // indirect 73 | k8s.io/klog v1.0.0 // indirect 74 | k8s.io/kube-openapi v0.0.0-20241127205056-99599406b04f // indirect 75 | k8s.io/utils v0.0.0-20241210054802-24370beab758 // indirect 76 | sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20231015215740-bf15e44028f9 // indirect 77 | sigs.k8s.io/controller-tools v0.16.5 // indirect 78 | sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 // indirect 79 | sigs.k8s.io/structured-merge-diff/v4 v4.4.3 // indirect 80 | sigs.k8s.io/yaml v1.4.0 // indirect 81 | ) 82 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/ahmetb/gen-crd-api-reference-docs v0.3.0 h1:+XfOU14S4bGuwyvCijJwhhBIjYN+YXS18jrCY2EzJaY= 2 | github.com/ahmetb/gen-crd-api-reference-docs v0.3.0/go.mod h1:TdjdkYhlOifCQWPs1UdTma97kQQMozf5h26hTuG70u8= 3 | github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 4 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 5 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 6 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= 7 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 8 | github.com/emicklei/go-restful/v3 v3.12.1 h1:PJMDIM/ak7btuL8Ex0iYET9hxM3CI2sjZtzpL63nKAU= 9 | github.com/emicklei/go-restful/v3 v3.12.1/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= 10 | github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= 11 | github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= 12 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 13 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 14 | github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M= 15 | github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= 16 | github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= 17 | github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= 18 | github.com/gardener/gardener v1.112.2 h1:w05YMkhaunEspn17leqUoxBEhAGnIoiDHwHLMZ68hCg= 19 | github.com/gardener/gardener v1.112.2/go.mod h1:UsM1VdFiXGc4zhWhNRNAO3fH+9YPcYp/BIe2wXuHDd0= 20 | github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= 21 | github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= 22 | github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= 23 | github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 24 | github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= 25 | github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= 26 | github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= 27 | github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= 28 | github.com/go-openapi/jsonreference v0.21.0 h1:Rs+Y7hSXT83Jacb7kFyjn4ijOuVGSvOdF2+tg1TRrwQ= 29 | github.com/go-openapi/jsonreference v0.21.0/go.mod h1:LmZmgsrTkVg9LG4EaHeY8cBDslNPMo06cago5JNLkm4= 30 | github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= 31 | github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= 32 | github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= 33 | github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= 34 | github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= 35 | github.com/gobuffalo/flect v1.0.3 h1:xeWBM2nui+qnVvNM4S3foBhCAL2XgPU+a7FdpelbTq4= 36 | github.com/gobuffalo/flect v1.0.3/go.mod h1:A5msMlrHtLqh9umBSnvabjsMrCcCpAyzglnDvkbYKHs= 37 | github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= 38 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 39 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 40 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 41 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 42 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 43 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 44 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 45 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 46 | github.com/google/gnostic-models v0.6.9 h1:MU/8wDLif2qCXZmzncUQ/BOfxWfthHi63KqpoNbWqVw= 47 | github.com/google/gnostic-models v0.6.9/go.mod h1:CiWsm0s6BSQd1hRn8/QmxqB6BesYcbSZxsz9b0KuDBw= 48 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 49 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 50 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 51 | github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 52 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 53 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 54 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 55 | github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 56 | github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= 57 | github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 58 | github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad h1:a6HEuzUHeKH6hwfN/ZoQgRgVIWFJljSWa/zetS2WTvg= 59 | github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad/go.mod h1:vavhavw2zAxS5dIdcRluK6cSGGPlZynqzFM8NdvU144= 60 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 61 | github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= 62 | github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 63 | github.com/ironcore-dev/vgopath v0.1.5 h1:+I46zEFfbmNIGIGylqedT2bMXw8V7yVP16GJkG64gAw= 64 | github.com/ironcore-dev/vgopath v0.1.5/go.mod h1:qbSUA7Eg0SO97OYfkG0DH+DxaPrH6XCiAQHqqs9R63Q= 65 | github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= 66 | github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= 67 | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 68 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 69 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 70 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 71 | github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 72 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 73 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 74 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 75 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 76 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 77 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 78 | github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= 79 | github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= 80 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 81 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 82 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 83 | github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= 84 | github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= 85 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 86 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 87 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 88 | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 89 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 90 | github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= 91 | github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= 92 | github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= 93 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 94 | github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= 95 | github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= 96 | github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= 97 | github.com/onsi/ginkgo/v2 v2.22.1 h1:QW7tbJAUDyVDVOM5dFa7qaybo+CRfR7bemlQUN6Z8aM= 98 | github.com/onsi/ginkgo/v2 v2.22.1/go.mod h1:S6aTpoRsSq2cZOd+pssHAlKW/Q/jZt6cPrPlnj4a1xM= 99 | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 100 | github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= 101 | github.com/onsi/gomega v1.36.2 h1:koNYke6TVk6ZmnyHrCXba/T/MoLBXFjeC1PtvYgw0A8= 102 | github.com/onsi/gomega v1.36.2/go.mod h1:DdwyADRjrc825LhMEkD76cHR5+pUnjhUN8GlHlRPHzY= 103 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 104 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 105 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 106 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 107 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= 108 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 109 | github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= 110 | github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= 111 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 112 | github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= 113 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 114 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= 115 | github.com/spf13/afero v1.12.0 h1:UcOPyRBYczmFn6yvphxkn9ZEOY65cpwGKb5mL36mrqs= 116 | github.com/spf13/afero v1.12.0/go.mod h1:ZTlWwG4/ahT8W7T0WQ5uYmjI9duaLQGy3Q2OAl4sk/4= 117 | github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= 118 | github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= 119 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 120 | github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= 121 | github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 122 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 123 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 124 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 125 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 126 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 127 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 128 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 129 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 130 | github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= 131 | github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 132 | github.com/vishvananda/netlink v1.0.0 h1:bqNY2lgheFIu1meHUFSH3d7vG93AFyqg3oGbJCOJgSM= 133 | github.com/vishvananda/netlink v1.0.0/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= 134 | github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f h1:nBX3nTcmxEtHSERBJaIo1Qa26VwRaopnZmfDQUXsF4I= 135 | github.com/vishvananda/netns v0.0.0-20190625233234-7109fa855b0f/go.mod h1:ZjcWmFBXmLKZu9Nxj3WKYEafiSqer2rnvPr0en9UNpI= 136 | github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= 137 | github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= 138 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 139 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 140 | go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= 141 | go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= 142 | go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= 143 | go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= 144 | go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= 145 | go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= 146 | go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= 147 | go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= 148 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 149 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 150 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 151 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 152 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 153 | golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= 154 | golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= 155 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 156 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 157 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 158 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 159 | golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 160 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 161 | golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0= 162 | golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k= 163 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 164 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 165 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 166 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 167 | golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= 168 | golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= 169 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 170 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 171 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 172 | golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 173 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 174 | golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 175 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 176 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 177 | golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 178 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 179 | golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 180 | golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= 181 | golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 182 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 183 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 184 | golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= 185 | golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= 186 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 187 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 188 | golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 189 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 190 | golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 191 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 192 | golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE= 193 | golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= 194 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 195 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 196 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 197 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 198 | golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= 199 | golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= 200 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 201 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 202 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 203 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 204 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 205 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 206 | google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= 207 | google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= 208 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 209 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 210 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 211 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 212 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 213 | gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= 214 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 215 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= 216 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 217 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 218 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 219 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 220 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 221 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 222 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 223 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 224 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 225 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 226 | k8s.io/api v0.31.5 h1:7jP74egbPUOCLJV5KheUnwo9gz3zzUsMIj2EPkuYK1E= 227 | k8s.io/api v0.31.5/go.mod h1:RMyMdZG1kJjou2ng5buEti0OHlo0uFXgSzTZ/k5LeVk= 228 | k8s.io/apiextensions-apiserver v0.31.5 h1:50+b/hHx4nyvQ+gaFH7p5myPEZyekGhGGAQb4vnBUlQ= 229 | k8s.io/apiextensions-apiserver v0.31.5/go.mod h1:6vZ7IIlk3l7GSFcbaNz5CEYpUBLsQ0ee+LgLGOsExWQ= 230 | k8s.io/apimachinery v0.31.5 h1:NxhAVGcfrSdTMx3M2v1OnvcMS7h1ZnWyt2x2z8CJJBU= 231 | k8s.io/apimachinery v0.31.5/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= 232 | k8s.io/code-generator v0.31.5 h1:nEvmAhA0tiaoHqS3ZsW/SjbGdzex4TzOlicVPoSVG8E= 233 | k8s.io/code-generator v0.31.5/go.mod h1:svmu9SPsjrNeC/T/nilkqsI0KWnC8XUandi9ECMNqRo= 234 | k8s.io/gengo v0.0.0-20201203183100-97869a43a9d9/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= 235 | k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01 h1:pWEwq4Asjm4vjW7vcsmijwBhOr1/shsbSYiWXmNGlks= 236 | k8s.io/gengo v0.0.0-20230829151522-9cce18d56c01/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= 237 | k8s.io/gengo/v2 v2.0.0-20240826214909-a7b603a56eb7 h1:cErOOTkQ3JW19o4lo91fFurouhP8NcoBvb7CkvhZZpk= 238 | k8s.io/gengo/v2 v2.0.0-20240826214909-a7b603a56eb7/go.mod h1:EJykeLsmFC60UQbYJezXkEsG2FLrt0GPNkU5iK5GWxU= 239 | k8s.io/klog v0.2.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= 240 | k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= 241 | k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= 242 | k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= 243 | k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= 244 | k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= 245 | k8s.io/kube-openapi v0.0.0-20241127205056-99599406b04f h1:nLHvOvs1CZ+FAEwR4EqLeRLfbtWQNlIu5g393Hq/1UM= 246 | k8s.io/kube-openapi v0.0.0-20241127205056-99599406b04f/go.mod h1:iZjdMQzunI7O/sUrf/5WRX1gvaAIam32lKx9+paoLbU= 247 | k8s.io/utils v0.0.0-20241210054802-24370beab758 h1:sdbE21q2nlQtFh65saZY+rRM6x6aJJI8IUa1AmH/qa0= 248 | k8s.io/utils v0.0.0-20241210054802-24370beab758/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= 249 | sigs.k8s.io/controller-runtime v0.19.5 h1:rsE2cRYe0hK/rAAwiS1bwqgEcgCxTz9lavs3FMgLW0c= 250 | sigs.k8s.io/controller-runtime v0.19.5/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= 251 | sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20231015215740-bf15e44028f9 h1:O27fSMHw4u0h+Rj8bNzcZk5jY0iZCO0J8/mCpigpnbw= 252 | sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20231015215740-bf15e44028f9/go.mod h1:TF/lVLWS+JNNaVqJuDDictY2hZSXSsIHCx4FClMvqFg= 253 | sigs.k8s.io/controller-tools v0.16.5 h1:5k9FNRqziBPwqr17AMEPPV/En39ZBplLAdOwwQHruP4= 254 | sigs.k8s.io/controller-tools v0.16.5/go.mod h1:8vztuRVzs8IuuJqKqbXCSlXcw+lkAv/M2sTpg55qjMY= 255 | sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8 h1:gBQPwqORJ8d8/YNZWEjoZs7npUVDpVXUUOFfW6CgAqE= 256 | sigs.k8s.io/json v0.0.0-20241014173422-cfa47c3a1cc8/go.mod h1:mdzfpAEoE6DHQEN0uh9ZbOCuHbLK5wOm7dK4ctXE9Tg= 257 | sigs.k8s.io/structured-merge-diff/v4 v4.4.3 h1:sCP7Vv3xx/CWIuTPVN38lUPx0uw0lcLfzaiDa8Ja01A= 258 | sigs.k8s.io/structured-merge-diff/v4 v4.4.3/go.mod h1:N8f93tFZh9U6vpxwRArLiikrE5/2tiu1w1AGfACIGE4= 259 | sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= 260 | sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= 261 | sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= 262 | -------------------------------------------------------------------------------- /hack/cherry-pick-pull.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2015 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # This file was copied from the kubernetes/kubernetes project 18 | # https://github.com/kubernetes/kubernetes/blob/v1.20.0/hack/cherry_pick_pull.sh 19 | # 20 | # Modifications Copyright SAP SE or an SAP affiliate company and Gardener contributors 21 | 22 | # Usage Instructions: https://github.com/gardener/gardener/blob/master/docs/development/process.md#cherry-picks 23 | 24 | # Checkout a PR from GitHub. (Yes, this is sitting in a Git tree. How 25 | # meta.) Assumes you care about pulls from remote "upstream" and 26 | # checks them out to a branch named: 27 | # automated-cherry-pick-of--- 28 | 29 | set -o errexit 30 | set -o nounset 31 | set -o pipefail 32 | 33 | REPO_ROOT="$(git rev-parse --show-toplevel)" 34 | declare -r REPO_ROOT 35 | cd "${REPO_ROOT}" 36 | 37 | STARTINGBRANCH=$(git symbolic-ref --short HEAD) 38 | declare -r STARTINGBRANCH 39 | declare -r REBASEMAGIC="${REPO_ROOT}/.git/rebase-apply" 40 | DRY_RUN=${DRY_RUN:-""} 41 | UPSTREAM_REMOTE=${UPSTREAM_REMOTE:-upstream} 42 | FORK_REMOTE=${FORK_REMOTE:-origin} 43 | MAIN_REPO_ORG=${MAIN_REPO_ORG:-$(git remote get-url "$UPSTREAM_REMOTE" | awk '{gsub(/http[s]:\/\/|git@/,"")}1' | awk -F'[@:./]' 'NR==1{print $3}')} 44 | MAIN_REPO_NAME=${MAIN_REPO_NAME:-$(git remote get-url "$UPSTREAM_REMOTE" | awk '{gsub(/http[s]:\/\/|git@/,"")}1' | awk -F'[@:./]' 'NR==1{print $4}')} 45 | DEPRECATED_RELEASE_NOTE_CATEGORY="|noteworthy|improvement|action" 46 | RELEASE_NOTE_CATEGORY="(breaking|feature|bugfix|doc|other${DEPRECATED_RELEASE_NOTE_CATEGORY})" 47 | RELEASE_NOTE_TARGET_GROUP="(user|operator|developer|dependency)" 48 | 49 | if [[ -z ${GITHUB_USER:-} ]]; then 50 | echo "Please export GITHUB_USER= (or GH organization, if that's where your fork lives)" 51 | exit 1 52 | fi 53 | 54 | if ! which hub > /dev/null; then 55 | echo "Can't find 'hub' tool in PATH, please install from https://github.com/github/hub" 56 | exit 1 57 | fi 58 | 59 | if [[ "$#" -lt 2 ]]; then 60 | echo "${0} / ...: cherry pick one or more onto and leave instructions for proposing pull request" 61 | echo 62 | echo " Checks out / and handles the cherry-pick of (possibly multiple) for you." 63 | echo " Examples:" 64 | echo " $0 ${UPSTREAM_REMOTE}/release-3.14 12345 # Cherry-picks PR 12345 onto ${UPSTREAM_REMOTE}/release-3.14 and proposes that as a PR." 65 | echo " $0 ${UPSTREAM_REMOTE}/release-3.14 12345 56789 # Cherry-picks PR 12345, then 56789 and proposes the combination as a single PR." 66 | echo 67 | echo " Set the DRY_RUN environment var to skip git push and creating PR." 68 | echo " This is useful for creating patches to a release branch without making a PR." 69 | echo " When DRY_RUN is set the script will leave you in a branch containing the commits you cherry-picked." 70 | echo 71 | echo " Set UPSTREAM_REMOTE (default: upstream) and FORK_REMOTE (default: origin)" 72 | echo " to override the default remote names to what you have locally." 73 | exit 2 74 | fi 75 | 76 | if git_status=$(git status --porcelain --untracked=no 2>/dev/null) && [[ -n "${git_status}" ]]; then 77 | echo "!!! Dirty tree. Clean up and try again." 78 | exit 1 79 | fi 80 | 81 | if [[ -e "${REBASEMAGIC}" ]]; then 82 | echo "!!! 'git rebase' or 'git am' in progress. Clean up and try again." 83 | exit 1 84 | fi 85 | 86 | declare -r BRANCH="$1" 87 | shift 1 88 | declare -r PULLS=( "$@" ) 89 | 90 | function join { local IFS="$1"; shift; echo "$*"; } 91 | PULLDASH=$(join - "${PULLS[@]/#/#}") # Generates something like "#12345-#56789" 92 | declare -r PULLDASH 93 | PULLSUBJ=$(join " " "${PULLS[@]/#/#}") # Generates something like "#12345 #56789" 94 | declare -r PULLSUBJ 95 | 96 | echo "+++ Updating remotes..." 97 | git remote update "${UPSTREAM_REMOTE}" "${FORK_REMOTE}" 98 | 99 | if ! git log -n1 --format=%H "${BRANCH}" >/dev/null 2>&1; then 100 | echo "!!! '${BRANCH}' not found. The second argument should be something like ${UPSTREAM_REMOTE}/release-0.21." 101 | echo " (In particular, it needs to be a valid, existing remote branch that I can 'git checkout'.)" 102 | exit 1 103 | fi 104 | 105 | NEWBRANCHREQ="automated-cherry-pick-of-${PULLDASH}" # "Required" portion for tools. 106 | declare -r NEWBRANCHREQ 107 | NEWBRANCH="$(echo "${NEWBRANCHREQ}-${BRANCH}" | sed 's/\//-/g')" 108 | declare -r NEWBRANCH 109 | NEWBRANCHUNIQ="${NEWBRANCH}-$(date +%s)" 110 | declare -r NEWBRANCHUNIQ 111 | echo "+++ Creating local branch ${NEWBRANCHUNIQ}" 112 | 113 | cleanbranch="" 114 | prtext="" 115 | gitamcleanup=false 116 | function return_to_kansas { 117 | if [[ "${gitamcleanup}" == "true" ]]; then 118 | echo 119 | echo "+++ Aborting in-progress git am." 120 | git am --abort >/dev/null 2>&1 || true 121 | fi 122 | 123 | # return to the starting branch and delete the PR text file 124 | if [[ -z "${DRY_RUN}" ]]; then 125 | echo 126 | echo "+++ Returning you to the ${STARTINGBRANCH} branch and cleaning up." 127 | git checkout -f "${STARTINGBRANCH}" >/dev/null 2>&1 || true 128 | if [[ -n "${cleanbranch}" ]]; then 129 | git branch -D "${cleanbranch}" >/dev/null 2>&1 || true 130 | fi 131 | if [[ -n "${prtext}" ]]; then 132 | rm "${prtext}" 133 | fi 134 | fi 135 | } 136 | trap return_to_kansas EXIT 137 | 138 | SUBJECTS=() 139 | RELEASE_NOTES=() 140 | LABELS=() 141 | function make-a-pr() { 142 | local rel 143 | rel="$(basename "${BRANCH}")" 144 | echo 145 | echo "+++ Creating a pull request on GitHub at ${GITHUB_USER}:${NEWBRANCH}" 146 | 147 | # This looks like an unnecessary use of a tmpfile, but it avoids 148 | # https://github.com/github/hub/issues/976 Otherwise stdin is stolen 149 | # when we shove the heredoc at hub directly, tickling the ioctl 150 | # crash. 151 | prtext="$(mktemp -t prtext.XXXX)" # cleaned in return_to_kansas 152 | local numandtitle 153 | numandtitle=$(printf '%s\n' "${SUBJECTS[@]}") 154 | relnotes=$(printf "${RELEASE_NOTES[@]}") 155 | labels=$(printf "${LABELS[@]}") 156 | cat >"${prtext}" <&2 199 | exit 1 200 | fi 201 | done 202 | 203 | if [[ "${conflicts}" != "true" ]]; then 204 | echo "!!! git am failed, likely because of an in-progress 'git am' or 'git rebase'" 205 | exit 1 206 | fi 207 | } 208 | 209 | # set the subject 210 | pr_info=$(curl "https://api.github.com/repos/${MAIN_REPO_ORG}/${MAIN_REPO_NAME}/pulls/${pull}" -sS) 211 | subject=$(echo ${pr_info} | jq -cr '.title') 212 | SUBJECTS+=("#${pull}: ${subject}") 213 | labels=$(echo ${pr_info} | jq '.labels[].name' -cr | grep -P '^(area|kind)' | sed -e 's|/| |' -e 's|^|/|g') 214 | LABELS+=("${labels}") 215 | 216 | # remove the patch file from /tmp 217 | rm -f "/tmp/${pull}.patch" 218 | 219 | # get the release notes 220 | notes=$(echo ${pr_info} | jq '.body' | grep -Po "\`\`\` *${RELEASE_NOTE_CATEGORY} ${RELEASE_NOTE_TARGET_GROUP}.*?\`\`\`" || true) 221 | RELEASE_NOTES+=("${notes}") 222 | done 223 | gitamcleanup=false 224 | 225 | if [[ -n "${DRY_RUN}" ]]; then 226 | echo "!!! Skipping git push and PR creation because you set DRY_RUN." 227 | echo "To return to the branch you were in when you invoked this script:" 228 | echo 229 | echo " git checkout ${STARTINGBRANCH}" 230 | echo 231 | echo "To delete this branch:" 232 | echo 233 | echo " git branch -D ${NEWBRANCHUNIQ}" 234 | exit 0 235 | fi 236 | 237 | if git remote -v | grep ^"${FORK_REMOTE}" | grep "${MAIN_REPO_ORG}/${MAIN_REPO_NAME}.git"; then 238 | echo "!!! You have ${FORK_REMOTE} configured as your ${MAIN_REPO_ORG}/${MAIN_REPO_NAME}.git" 239 | echo "This isn't normal. Leaving you with push instructions:" 240 | echo 241 | echo "+++ First manually push the branch this script created:" 242 | echo 243 | echo " git push REMOTE ${NEWBRANCHUNIQ}:${NEWBRANCH}" 244 | echo 245 | echo "where REMOTE is your personal fork (maybe ${UPSTREAM_REMOTE}? Consider swapping those.)." 246 | echo "OR consider setting UPSTREAM_REMOTE and FORK_REMOTE to different values." 247 | echo 248 | make-a-pr 249 | cleanbranch="" 250 | exit 0 251 | fi 252 | 253 | echo 254 | echo "+++ I'm about to do the following to push to GitHub (and I'm assuming ${FORK_REMOTE} is your personal fork):" 255 | echo 256 | echo " git push ${FORK_REMOTE} ${NEWBRANCHUNIQ}:${NEWBRANCH}" 257 | echo 258 | read -p "+++ Proceed (anything but 'y' aborts the cherry-pick)? [y/n] " -r 259 | if ! [[ "${REPLY}" =~ ^[yY]$ ]]; then 260 | echo "Aborting." >&2 261 | exit 1 262 | fi 263 | 264 | git push "${FORK_REMOTE}" -f "${NEWBRANCHUNIQ}:${NEWBRANCH}" 265 | make-a-pr 266 | -------------------------------------------------------------------------------- /hack/sast.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # 3 | # SPDX-FileCopyrightText: 2024 SAP SE or an SAP affiliate company and Gardener contributors 4 | # 5 | # SPDX-License-Identifier: Apache-2.0 6 | 7 | set -e 8 | 9 | report_dir="$(git rev-parse --show-toplevel)" 10 | 11 | gosec_report="false" 12 | gosec_report_parse_flags="" 13 | exclude_dirs="hack" 14 | 15 | parse_flags() { 16 | while test $# -gt 1; do 17 | case "$1" in 18 | --gosec-report) 19 | shift; gosec_report="$1" 20 | ;; 21 | --report-dir) 22 | shift; report_dir="$1" 23 | ;; 24 | --exclude-dirs) 25 | shift; exclude_dirs="$1" 26 | ;; 27 | *) 28 | echo "Unknown argument: $1" 29 | exit 1 30 | ;; 31 | esac 32 | shift 33 | done 34 | } 35 | 36 | parse_flags "$@" 37 | 38 | echo "> Running gosec" 39 | gosec --version 40 | if [[ "$gosec_report" != "false" ]]; then 41 | echo "Exporting report to ${report_dir}/gosec-report.sarif" 42 | gosec_report_parse_flags="-track-suppressions -fmt=sarif -out=${report_dir}/gosec-report.sarif -stdout" 43 | fi 44 | 45 | # Gardener uses code-generators https://github.com/kubernetes/code-generator and https://github.com/protocolbuffers/protobuf 46 | # which create lots of G103 (CWE-242: Use of unsafe calls should be audited) & G104 (CWE-703: Errors unhandled) errors. 47 | # However, those generators are best-practice in Kubernetes environment and their results are tested well. 48 | # Thus, generated code is excluded from gosec scan. 49 | # Nested go modules are not supported by gosec (see https://github.com/securego/gosec/issues/501), so the ./hack folder 50 | # is excluded too. It does not contain productive code anyway. 51 | gosec -exclude-generated $(echo "$exclude_dirs" | awk -v RS=',' '{printf "-exclude-dir %s ", $1}') $gosec_report_parse_flags ./... 52 | -------------------------------------------------------------------------------- /hack/tools.go: -------------------------------------------------------------------------------- 1 | //go:build tools 2 | // +build tools 3 | 4 | // SPDX-FileCopyrightText: 2023 SAP SE or an SAP affiliate company and Gardener contributors 5 | // SPDX-License-Identifier: Apache-2.0 6 | 7 | 8 | // This package imports things required by build scripts, to force `go mod` to see them as dependencies 9 | package tools 10 | 11 | import ( 12 | _ "github.com/gardener/gardener/hack" 13 | _ "golang.org/x/tools/cmd/goimports" 14 | ) 15 | -------------------------------------------------------------------------------- /hack/tools/bin/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gardener/apiserver-proxy/5072f4ff876afe3b26ac26f1baf9d7762b76eaf1/hack/tools/bin/.gitkeep -------------------------------------------------------------------------------- /internal/app/app.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2020 SAP SE or an SAP affiliate company and Gardener contributors 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package app 5 | 6 | import ( 7 | "context" 8 | "fmt" 9 | "net/netip" 10 | "time" 11 | 12 | "github.com/vishvananda/netlink" 13 | "golang.org/x/xerrors" 14 | "k8s.io/klog/v2" 15 | 16 | "github.com/gardener/apiserver-proxy/internal/netif" 17 | ) 18 | 19 | // NewSidecarApp returns a new instance of SidecarApp by applying the specified config params. 20 | func NewSidecarApp(params *ConfigParams) (*SidecarApp, error) { 21 | c := &SidecarApp{params: params} 22 | 23 | ip, err := netip.ParseAddr(c.params.IPAddress) 24 | if err != nil { 25 | return nil, xerrors.Errorf("unable to parse IP address %q - %v", c.params.IPAddress, err) 26 | } 27 | 28 | addr, err := netlink.ParseAddr(fmt.Sprintf("%s/%d", c.params.IPAddress, ip.BitLen())) 29 | if err != nil || addr == nil { 30 | return nil, xerrors.Errorf("unable to parse IP address %q - %v", c.params.IPAddress, err) 31 | } 32 | 33 | c.localIP = addr 34 | 35 | klog.Infof("Using IP address %q", params.IPAddress) 36 | 37 | return c, nil 38 | } 39 | 40 | // TeardownNetworking removes the network interface added by apiserver-proxy 41 | func (c *SidecarApp) TeardownNetworking() error { 42 | klog.Infof("Cleaning up") 43 | err := c.netManager.RemoveIPAddress() 44 | if err != nil { 45 | return err 46 | } 47 | return c.netManager.CleanupDevice() 48 | } 49 | 50 | func (c *SidecarApp) runPeriodic(ctx context.Context) { 51 | tick := time.NewTicker(c.params.Interval) 52 | defer tick.Stop() 53 | 54 | for { 55 | select { 56 | case <-ctx.Done(): 57 | klog.Warningf("Exiting interface check goroutine") 58 | 59 | return 60 | case <-tick.C: 61 | c.runChecks() 62 | } 63 | } 64 | } 65 | 66 | func (c *SidecarApp) runChecks() { 67 | 68 | klog.V(2).Infoln("Ensuring ip address") 69 | 70 | if err := c.netManager.EnsureIPAddress(); err != nil { 71 | klog.Errorf("Error ensuring ip address: %v", err) 72 | } 73 | 74 | klog.V(2).Infoln("Ensured ip address") 75 | } 76 | 77 | // RunApp invokes the background checks and runs coreDNS as a cache 78 | func (c *SidecarApp) RunApp(ctx context.Context) { 79 | c.netManager = netif.NewNetifManager(c.localIP, c.params.Interface) 80 | 81 | if c.params.Cleanup { 82 | defer func() { 83 | if err := c.TeardownNetworking(); err != nil { 84 | klog.Fatalf("Failed to clean up - %v", err) 85 | } 86 | 87 | klog.Infoln("Successfully cleaned up everything. Bye!") 88 | }() 89 | } 90 | 91 | c.runChecks() 92 | 93 | if c.params.Daemon { 94 | klog.Infoln("Running as a daemon") 95 | // run periodic blocks 96 | c.runPeriodic(ctx) 97 | } 98 | 99 | klog.Infoln("Exiting... Bye!") 100 | } 101 | -------------------------------------------------------------------------------- /internal/app/config.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2020 SAP SE or an SAP affiliate company and Gardener contributors 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package app 5 | 6 | import ( 7 | "time" 8 | 9 | "github.com/vishvananda/netlink" 10 | 11 | "github.com/gardener/apiserver-proxy/internal/netif" 12 | ) 13 | 14 | // ConfigParams lists the configuration options that can be provided to sidecar proxy 15 | type ConfigParams struct { 16 | // LocalPort specifies the port to listen for DNS requests 17 | LocalPort string 18 | // Interface specifies the name of the interface to be created 19 | Interface string 20 | // Interval specifies how often to run iptables rules check 21 | Interval time.Duration 22 | // SetupIptables enables iptables setup 23 | SetupIptables bool 24 | // Cleanup specifies whether to clean the created interface and iptables 25 | Cleanup bool 26 | // Daemon specifies whether to run as daemon 27 | Daemon bool 28 | // IPAddress specifies the IP address on which the proxy is listening 29 | IPAddress string 30 | } 31 | 32 | // SidecarApp contains all the config required to run sidecar proxy. 33 | type SidecarApp struct { 34 | params *ConfigParams 35 | netManager netif.Manager 36 | localIP *netlink.Addr 37 | } 38 | -------------------------------------------------------------------------------- /internal/netif/mocks_test.go: -------------------------------------------------------------------------------- 1 | // Code generated by MockGen. DO NOT EDIT. 2 | // Source: internal/netif/netif.go 3 | // 4 | // Generated by this command: 5 | // 6 | // mockgen -source internal/netif/netif.go -destination internal/netif/mocks_test.go -package netif 7 | // 8 | 9 | // Package netif is a generated GoMock package. 10 | package netif 11 | 12 | import ( 13 | reflect "reflect" 14 | 15 | netlink "github.com/vishvananda/netlink" 16 | gomock "go.uber.org/mock/gomock" 17 | ) 18 | 19 | // MockHandle is a mock of Handle interface. 20 | type MockHandle struct { 21 | ctrl *gomock.Controller 22 | recorder *MockHandleMockRecorder 23 | } 24 | 25 | // MockHandleMockRecorder is the mock recorder for MockHandle. 26 | type MockHandleMockRecorder struct { 27 | mock *MockHandle 28 | } 29 | 30 | // NewMockHandle creates a new mock instance. 31 | func NewMockHandle(ctrl *gomock.Controller) *MockHandle { 32 | mock := &MockHandle{ctrl: ctrl} 33 | mock.recorder = &MockHandleMockRecorder{mock} 34 | return mock 35 | } 36 | 37 | // EXPECT returns an object that allows the caller to indicate expected use. 38 | func (m *MockHandle) EXPECT() *MockHandleMockRecorder { 39 | return m.recorder 40 | } 41 | 42 | // AddrAdd mocks base method. 43 | func (m *MockHandle) AddrAdd(link netlink.Link, addr *netlink.Addr) error { 44 | m.ctrl.T.Helper() 45 | ret := m.ctrl.Call(m, "AddrAdd", link, addr) 46 | ret0, _ := ret[0].(error) 47 | return ret0 48 | } 49 | 50 | // AddrAdd indicates an expected call of AddrAdd. 51 | func (mr *MockHandleMockRecorder) AddrAdd(link, addr any) *gomock.Call { 52 | mr.mock.ctrl.T.Helper() 53 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddrAdd", reflect.TypeOf((*MockHandle)(nil).AddrAdd), link, addr) 54 | } 55 | 56 | // AddrDel mocks base method. 57 | func (m *MockHandle) AddrDel(link netlink.Link, addr *netlink.Addr) error { 58 | m.ctrl.T.Helper() 59 | ret := m.ctrl.Call(m, "AddrDel", link, addr) 60 | ret0, _ := ret[0].(error) 61 | return ret0 62 | } 63 | 64 | // AddrDel indicates an expected call of AddrDel. 65 | func (mr *MockHandleMockRecorder) AddrDel(link, addr any) *gomock.Call { 66 | mr.mock.ctrl.T.Helper() 67 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AddrDel", reflect.TypeOf((*MockHandle)(nil).AddrDel), link, addr) 68 | } 69 | 70 | // LinkAdd mocks base method. 71 | func (m *MockHandle) LinkAdd(arg0 netlink.Link) error { 72 | m.ctrl.T.Helper() 73 | ret := m.ctrl.Call(m, "LinkAdd", arg0) 74 | ret0, _ := ret[0].(error) 75 | return ret0 76 | } 77 | 78 | // LinkAdd indicates an expected call of LinkAdd. 79 | func (mr *MockHandleMockRecorder) LinkAdd(arg0 any) *gomock.Call { 80 | mr.mock.ctrl.T.Helper() 81 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LinkAdd", reflect.TypeOf((*MockHandle)(nil).LinkAdd), arg0) 82 | } 83 | 84 | // LinkByName mocks base method. 85 | func (m *MockHandle) LinkByName(name string) (netlink.Link, error) { 86 | m.ctrl.T.Helper() 87 | ret := m.ctrl.Call(m, "LinkByName", name) 88 | ret0, _ := ret[0].(netlink.Link) 89 | ret1, _ := ret[1].(error) 90 | return ret0, ret1 91 | } 92 | 93 | // LinkByName indicates an expected call of LinkByName. 94 | func (mr *MockHandleMockRecorder) LinkByName(name any) *gomock.Call { 95 | mr.mock.ctrl.T.Helper() 96 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LinkByName", reflect.TypeOf((*MockHandle)(nil).LinkByName), name) 97 | } 98 | 99 | // LinkDel mocks base method. 100 | func (m *MockHandle) LinkDel(arg0 netlink.Link) error { 101 | m.ctrl.T.Helper() 102 | ret := m.ctrl.Call(m, "LinkDel", arg0) 103 | ret0, _ := ret[0].(error) 104 | return ret0 105 | } 106 | 107 | // LinkDel indicates an expected call of LinkDel. 108 | func (mr *MockHandleMockRecorder) LinkDel(arg0 any) *gomock.Call { 109 | mr.mock.ctrl.T.Helper() 110 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LinkDel", reflect.TypeOf((*MockHandle)(nil).LinkDel), arg0) 111 | } 112 | 113 | // LinkSetUp mocks base method. 114 | func (m *MockHandle) LinkSetUp(arg0 netlink.Link) error { 115 | m.ctrl.T.Helper() 116 | ret := m.ctrl.Call(m, "LinkSetUp", arg0) 117 | ret0, _ := ret[0].(error) 118 | return ret0 119 | } 120 | 121 | // LinkSetUp indicates an expected call of LinkSetUp. 122 | func (mr *MockHandleMockRecorder) LinkSetUp(arg0 any) *gomock.Call { 123 | mr.mock.ctrl.T.Helper() 124 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LinkSetUp", reflect.TypeOf((*MockHandle)(nil).LinkSetUp), arg0) 125 | } 126 | 127 | // MockManager is a mock of Manager interface. 128 | type MockManager struct { 129 | ctrl *gomock.Controller 130 | recorder *MockManagerMockRecorder 131 | } 132 | 133 | // MockManagerMockRecorder is the mock recorder for MockManager. 134 | type MockManagerMockRecorder struct { 135 | mock *MockManager 136 | } 137 | 138 | // NewMockManager creates a new mock instance. 139 | func NewMockManager(ctrl *gomock.Controller) *MockManager { 140 | mock := &MockManager{ctrl: ctrl} 141 | mock.recorder = &MockManagerMockRecorder{mock} 142 | return mock 143 | } 144 | 145 | // EXPECT returns an object that allows the caller to indicate expected use. 146 | func (m *MockManager) EXPECT() *MockManagerMockRecorder { 147 | return m.recorder 148 | } 149 | 150 | // EnsureIPAddress mocks base method. 151 | func (m *MockManager) EnsureIPAddress() error { 152 | m.ctrl.T.Helper() 153 | ret := m.ctrl.Call(m, "EnsureIPAddress") 154 | ret0, _ := ret[0].(error) 155 | return ret0 156 | } 157 | 158 | // EnsureIPAddress indicates an expected call of EnsureIPAddress. 159 | func (mr *MockManagerMockRecorder) EnsureIPAddress() *gomock.Call { 160 | mr.mock.ctrl.T.Helper() 161 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnsureIPAddress", reflect.TypeOf((*MockManager)(nil).EnsureIPAddress)) 162 | } 163 | 164 | // RemoveIPAddress mocks base method. 165 | func (m *MockManager) RemoveIPAddress() error { 166 | m.ctrl.T.Helper() 167 | ret := m.ctrl.Call(m, "RemoveIPAddress") 168 | ret0, _ := ret[0].(error) 169 | return ret0 170 | } 171 | 172 | // RemoveIPAddress indicates an expected call of RemoveIPAddress. 173 | func (mr *MockManagerMockRecorder) RemoveIPAddress() *gomock.Call { 174 | mr.mock.ctrl.T.Helper() 175 | return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RemoveIPAddress", reflect.TypeOf((*MockManager)(nil).RemoveIPAddress)) 176 | } 177 | -------------------------------------------------------------------------------- /internal/netif/netif.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2020 SAP SE or an SAP affiliate company and Gardener contributors 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package netif 5 | 6 | import ( 7 | "errors" 8 | "os" 9 | 10 | "github.com/vishvananda/netlink" 11 | "golang.org/x/xerrors" 12 | "k8s.io/klog/v2" 13 | ) 14 | 15 | type Handle interface { 16 | AddrAdd(link netlink.Link, addr *netlink.Addr) error 17 | AddrDel(link netlink.Link, addr *netlink.Addr) error 18 | LinkByName(name string) (netlink.Link, error) 19 | LinkSetUp(netlink.Link) error 20 | LinkAdd(netlink.Link) error 21 | LinkDel(netlink.Link) error 22 | } 23 | 24 | // Manager ensures that the dummy device is created or removed. 25 | type Manager interface { 26 | EnsureIPAddress() error 27 | RemoveIPAddress() error 28 | CleanupDevice() error 29 | } 30 | 31 | // netifManagerDefault is the default implementation handling creating 32 | // and removing of the dummy interface. 33 | type netifManagerDefault struct { 34 | Handle 35 | addr *netlink.Addr 36 | devName string 37 | } 38 | 39 | // NewNetifManager returns a new instance of NetifManager with the ip address set to the provided values 40 | // These ip addresses will be bound to any devices created by this instance. 41 | func NewNetifManager(addr *netlink.Addr, devName string) Manager { 42 | 43 | return &netifManagerDefault{ 44 | &netlink.Handle{}, 45 | addr, 46 | devName, 47 | } 48 | } 49 | 50 | // EnsureIPAddress makes sure to have the device running as desired. 51 | func (m *netifManagerDefault) EnsureIPAddress() error { 52 | klog.V(4).Infof("Getting interface %q", m.devName) 53 | 54 | l, err := m.LinkByName(m.devName) 55 | if err != nil { 56 | var linkNotFoundErr netlink.LinkNotFoundError 57 | if !errors.As(err, &linkNotFoundErr) { 58 | return xerrors.Errorf("could not get interface %s:\n%v", m.devName, err) 59 | } 60 | 61 | dummyLink := &netlink.Dummy{ 62 | LinkAttrs: netlink.LinkAttrs{ 63 | Name: m.devName, 64 | }, 65 | } 66 | err = m.LinkAdd(dummyLink) 67 | if err != nil { 68 | return xerrors.Errorf("could add dummy interface %s:\n%v", m.devName, err) 69 | } 70 | 71 | err = m.LinkSetUp(dummyLink) 72 | if err != nil { 73 | return xerrors.Errorf("could set interface %s up:\n%v", m.devName, err) 74 | } 75 | 76 | l = dummyLink 77 | } 78 | 79 | klog.V(6).Infof("Got interface %+v", l) 80 | 81 | if err := m.AddrAdd(l, m.addr); err != nil { 82 | if os.IsExist(err) { 83 | klog.V(4).Infof("Address %q already exists. Skipping", m.addr.String()) 84 | return nil 85 | } 86 | 87 | return xerrors.Errorf("could not add IPV4 addresses %v", err) 88 | } 89 | 90 | klog.Infof("Successfully added %q to %q", m.addr.String(), m.devName) 91 | 92 | return nil 93 | } 94 | 95 | // EnsureIPAddress makes sure to have the device running as desired. 96 | func (m *netifManagerDefault) RemoveIPAddress() error { 97 | klog.V(4).Infof("Getting interface %q", m.devName) 98 | 99 | l, err := m.LinkByName(m.devName) 100 | if err != nil { 101 | return xerrors.Errorf("could not get interface %s:\n%v", m.devName, err) 102 | } 103 | 104 | klog.V(6).Infof("Got interface %+v", l) 105 | 106 | if err := m.AddrDel(l, m.addr); err != nil { 107 | if os.IsNotExist(err) { 108 | klog.V(4).Infof("Address %q already removed. Skipping", m.addr.String()) 109 | return nil 110 | } 111 | 112 | return xerrors.Errorf("could not delete ip address %v", err) 113 | } 114 | 115 | klog.Infof("Successfully removed %q from %q", m.addr.String(), m.devName) 116 | 117 | return nil 118 | } 119 | 120 | func (m *netifManagerDefault) CleanupDevice() error { 121 | link, err := netlink.LinkByName(m.devName) 122 | if err != nil { 123 | var linkNotFoundErr netlink.LinkNotFoundError 124 | if !errors.As(err, &linkNotFoundErr) { 125 | return xerrors.Errorf("could not get interface %s:\n%v", m.devName, err) 126 | } 127 | // link already gone 128 | return nil 129 | } 130 | err = netlink.LinkDel(link) 131 | if err != nil { 132 | return xerrors.Errorf("could not delete interface %s:\n%v", m.devName, err) 133 | } 134 | return nil 135 | } 136 | -------------------------------------------------------------------------------- /internal/netif/netif_suite_test.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2020 SAP SE or an SAP affiliate company and Gardener contributors 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package netif 5 | 6 | import ( 7 | "fmt" 8 | "net" 9 | "syscall" 10 | "testing" 11 | 12 | . "github.com/onsi/ginkgo" 13 | . "github.com/onsi/gomega" 14 | "github.com/vishvananda/netlink" 15 | gomock "go.uber.org/mock/gomock" 16 | ) 17 | 18 | func TestNetif(t *testing.T) { 19 | RegisterFailHandler(Fail) 20 | RunSpecs(t, "Netif Suite") 21 | } 22 | 23 | var _ = Describe("Manager", func() { 24 | 25 | var ( 26 | ctrl *gomock.Controller 27 | mh *MockHandle 28 | addr *netlink.Addr 29 | interfaceName string 30 | manager Manager 31 | dm *netifManagerDefault 32 | dummy *netlink.Dummy 33 | ip = "192.168.0.3" 34 | ) 35 | 36 | BeforeEach(func() { 37 | addr, _ = netlink.ParseAddr(ip + "/32") 38 | interfaceName = "foo" 39 | ctrl = gomock.NewController(GinkgoT()) 40 | mh = NewMockHandle(ctrl) 41 | dummy = &netlink.Dummy{ 42 | LinkAttrs: netlink.LinkAttrs{Name: interfaceName}, 43 | } 44 | }) 45 | 46 | AfterEach(func() { 47 | 48 | mh.EXPECT().AddrAdd(gomock.Any(), gomock.Any()).Times(0) 49 | mh.EXPECT().AddrDel(gomock.Any(), gomock.Any()).Times(0) 50 | mh.EXPECT().LinkByName(gomock.Any()).Times(0) 51 | 52 | ctrl.Finish() 53 | }) 54 | 55 | JustBeforeEach(func() { 56 | manager = NewNetifManager(addr, interfaceName) 57 | dm = manager.(*netifManagerDefault) 58 | // override the default handler 59 | dm.Handle = mh 60 | Expect(dm).NotTo(BeNil()) 61 | }) 62 | 63 | Describe("NewNetifManager", func() { 64 | It("should return a valid Manager", func() { 65 | Expect(manager).NotTo(BeNil()) 66 | }) 67 | 68 | Context("address", func() { 69 | JustBeforeEach(func() { 70 | Expect(dm.addr).NotTo(BeNil(), "addr should always be set") 71 | }) 72 | 73 | It("should set point to the corrext IP", func() { 74 | Expect(dm.addr.IPNet).To(Equal(&net.IPNet{IP: net.ParseIP(ip), Mask: net.CIDRMask(32, 32)})) 75 | }) 76 | 77 | }) 78 | 79 | It("should set the correct device name", func() { 80 | Expect(dm.devName).To(Equal(interfaceName)) 81 | }) 82 | }) 83 | 84 | Describe("RemoveIPAddress", func() { 85 | 86 | It("should return error when getting link", func() { 87 | mh.EXPECT(). 88 | LinkByName(gomock.Eq("foo")). 89 | Return(nil, fmt.Errorf("err")). 90 | Times(1) 91 | 92 | err := manager.RemoveIPAddress() 93 | Expect(err).To(HaveOccurred()) 94 | }) 95 | 96 | Context("LinkByName succeeds", func() { 97 | 98 | BeforeEach(func() { 99 | mh.EXPECT(). 100 | LinkByName(gomock.Eq("foo")). 101 | Return(dummy, nil). 102 | Times(1) 103 | }) 104 | 105 | It("should return error when deleting ip address", func() { 106 | mh.EXPECT(). 107 | AddrDel(gomock.Eq(dummy), gomock.Eq(addr)). 108 | Return(fmt.Errorf("err")). 109 | Times(1) 110 | 111 | err := manager.RemoveIPAddress() 112 | Expect(err).To(HaveOccurred()) 113 | }) 114 | 115 | It("should return already removed error", func() { 116 | mh.EXPECT(). 117 | AddrDel(gomock.Eq(dummy), gomock.Eq(addr)). 118 | // Return(syscall.EEXIST). 119 | Return(syscall.ENOENT). 120 | Times(1) 121 | 122 | err := manager.RemoveIPAddress() 123 | Expect(err).ToNot(HaveOccurred()) 124 | }) 125 | 126 | It("should return no error when deleting link", func() { 127 | mh.EXPECT(). 128 | AddrDel(gomock.Eq(dummy), gomock.Eq(addr)). 129 | Return(nil). 130 | Times(1) 131 | 132 | err := manager.RemoveIPAddress() 133 | Expect(err).ToNot(HaveOccurred()) 134 | }) 135 | }) 136 | }) 137 | 138 | Describe("EnsureIPAddress", func() { 139 | 140 | It("should return error when getting link", func() { 141 | mh.EXPECT(). 142 | LinkByName(gomock.Eq("foo")). 143 | Return(nil, fmt.Errorf("err")). 144 | Times(1) 145 | 146 | err := manager.EnsureIPAddress() 147 | Expect(err).To(HaveOccurred()) 148 | }) 149 | 150 | Context("LinkByName errors with LinkNotFoundError", func() { 151 | BeforeEach(func() { 152 | mh.EXPECT(). 153 | LinkByName(gomock.Eq("foo")). 154 | Return(dummy, netlink.LinkNotFoundError{}). 155 | Times(1) 156 | 157 | }) 158 | 159 | It("should return error when adding ip address", func() { 160 | mh.EXPECT(). 161 | LinkAdd(gomock.Any()). 162 | Return(nil). 163 | Times(1) 164 | 165 | mh.EXPECT(). 166 | LinkSetUp(gomock.Any()). 167 | Return(nil). 168 | Times(1) 169 | 170 | mh.EXPECT(). 171 | AddrAdd(gomock.Eq(dummy), gomock.Eq(addr)). 172 | Return(fmt.Errorf("err")). 173 | Times(1) 174 | 175 | err := manager.EnsureIPAddress() 176 | Expect(err).To(HaveOccurred()) 177 | }) 178 | 179 | It("should return already exists error", func() { 180 | mh.EXPECT(). 181 | LinkAdd(gomock.Any()). 182 | Return(nil). 183 | Times(1) 184 | 185 | mh.EXPECT(). 186 | LinkSetUp(gomock.Any()). 187 | Return(nil). 188 | Times(1) 189 | 190 | mh.EXPECT(). 191 | AddrAdd(gomock.Eq(dummy), gomock.Eq(addr)). 192 | Return(syscall.EEXIST). 193 | Times(1) 194 | 195 | err := manager.EnsureIPAddress() 196 | Expect(err).ToNot(HaveOccurred()) 197 | }) 198 | 199 | It("should return error when set up of link fails", func() { 200 | mh.EXPECT(). 201 | LinkAdd(gomock.Any()). 202 | Return(nil). 203 | Times(1) 204 | 205 | mh.EXPECT(). 206 | LinkSetUp(gomock.Any()). 207 | Return(fmt.Errorf("err")). 208 | Times(1) 209 | 210 | err := manager.EnsureIPAddress() 211 | Expect(err).To(HaveOccurred()) 212 | }) 213 | 214 | }) 215 | 216 | Context("LinkByName succeeds", func() { 217 | BeforeEach(func() { 218 | mh.EXPECT(). 219 | LinkByName(gomock.Eq("foo")). 220 | Return(dummy, nil). 221 | Times(1) 222 | }) 223 | 224 | It("should return error when adding ip address", func() { 225 | mh.EXPECT(). 226 | AddrAdd(gomock.Eq(dummy), gomock.Eq(addr)). 227 | Return(fmt.Errorf("err")). 228 | Times(1) 229 | 230 | err := manager.EnsureIPAddress() 231 | Expect(err).To(HaveOccurred()) 232 | }) 233 | 234 | It("should return already exists error", func() { 235 | mh.EXPECT(). 236 | AddrAdd(gomock.Eq(dummy), gomock.Eq(addr)). 237 | Return(syscall.EEXIST). 238 | Times(1) 239 | 240 | err := manager.EnsureIPAddress() 241 | Expect(err).ToNot(HaveOccurred()) 242 | }) 243 | 244 | It("should return no error when deleting link", func() { 245 | mh.EXPECT(). 246 | AddrAdd(gomock.Eq(dummy), gomock.Eq(addr)). 247 | Return(nil). 248 | Times(1) 249 | 250 | err := manager.EnsureIPAddress() 251 | Expect(err).ToNot(HaveOccurred()) 252 | }) 253 | }) 254 | }) 255 | 256 | }) 257 | -------------------------------------------------------------------------------- /internal/version/version.go: -------------------------------------------------------------------------------- 1 | // SPDX-FileCopyrightText: 2020 SAP SE or an SAP affiliate company and Gardener contributors 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | package version 5 | 6 | var version = "v0.0.0-dev" 7 | 8 | // Version returs the codebase version. It's for detecting 9 | // what code a binary was built from. 10 | func Version() string { 11 | return version 12 | } 13 | --------------------------------------------------------------------------------