This is an automated email from the ASF dual-hosted git repository.

albumenj pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/dubbo-go-pixiu.git


The following commit(s) were added to refs/heads/develop by this push:
     new 5851a877 Add dubbo-pilot deploy and doc (#504)
5851a877 is described below

commit 5851a87701d4b5af76a8ba84101f75143a4fcc9f
Author: bobtthp <[email protected]>
AuthorDate: Mon Oct 17 10:44:36 2022 +0800

    Add dubbo-pilot deploy and doc (#504)
---
 .licenserc.yaml                        |  10 +
 Makefile                               |   8 +
 Makefile.core.mk                       | 522 +++++++++++++++++++++++++++++++++
 istioctl/docker/Dockerfile.istioctl    |  37 ++-
 pilot/docker/Dockerfile.pilot          |  46 ++-
 pkg/kube/client.go                     |   1 +
 tools/Makefile.common.mk               | 128 ++++++++
 tools/scripts/check_clean_repo.sh      |  45 +++
 tools/scripts/copyright-banner-go.txt  |  14 +
 tools/scripts/fix_copyright_banner.sh  |  39 +++
 tools/scripts/format_go.sh             |  24 ++
 tools/scripts/gobuild.sh               |  89 ++++++
 tools/scripts/kind_provisioner.sh      | 431 +++++++++++++++++++++++++++
 tools/scripts/lint_copyright_banner.sh |  39 +++
 tools/scripts/lint_go.sh               |  28 ++
 tools/scripts/metallb.yaml             | 399 +++++++++++++++++++++++++
 tools/scripts/report_build_info.sh     |  47 +++
 tools/scripts/run.sh                   |  78 +++++
 tools/scripts/setup_env.sh             | 234 +++++++++++++++
 19 files changed, 2207 insertions(+), 12 deletions(-)

diff --git a/.licenserc.yaml b/.licenserc.yaml
index fe3e62c6..e6193916 100644
--- a/.licenserc.yaml
+++ b/.licenserc.yaml
@@ -1771,6 +1771,16 @@ header:
     - 'tools/packaging/deb_test.sh'
     - 'tools/packaging/postinst.sh'
     - 'tools/skip-image.sh'
+    - 'tools/scripts/check_clean_repo.sh'
+    - 'tools/scripts/fix_copyright_banner.sh'
+    - 'tools/scripts/format_go.sh'
+    - 'tools/scripts/gobuild.sh'
+    - 'tools/scripts/kind_provisioner.sh'
+    - 'tools/scripts/lint_copyright_banner.sh'
+    - 'tools/scripts/lint_go.sh'
+    - 'tools/scripts/report_build_info.sh'
+    - 'tools/scripts/run.sh'
+    - 'tools/scripts/setup_env.sh'
     - 'istioctl/cmd/version_test.go'
     - 'pilot/cmd/pilot-agent/main_test.go'
     - 'pilot/cmd/pilot-agent/request.go'
diff --git a/Makefile b/Makefile
index 3ed38924..05284842 100644
--- a/Makefile
+++ b/Makefile
@@ -73,3 +73,11 @@ integrate-test:
 
 clean:
        @rm -rf ./dubbo-go-pixiu
+
+# build pilot by docker-builder
+
+export
+RUN = ./tools/scripts/run.sh
+MAKE_DOCKER = $(RUN) make --no-print-directory -e -f Makefile.core.mk
+%:
+       @$(MAKE_DOCKER) $@
diff --git a/Makefile.core.mk b/Makefile.core.mk
new file mode 100644
index 00000000..743ad311
--- /dev/null
+++ b/Makefile.core.mk
@@ -0,0 +1,522 @@
+## Copyright Istio Authors
+##
+## Licensed under the Apache License, Version 2.0 (the "License");
+## you may not use this file except in compliance with the License.
+## You may obtain a copy of the License at
+##
+##     http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing, software
+## distributed under the License is distributed on an "AS IS" BASIS,
+## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+## See the License for the specific language governing permissions and
+## limitations under the License.
+
+#-----------------------------------------------------------------------------
+# Global Variables
+#-----------------------------------------------------------------------------
+ISTIO_GO := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
+export ISTIO_GO
+SHELL := /bin/bash -o pipefail
+
+export VERSION ?= 1.14-dev
+
+# Base version of Istio image to use
+BASE_VERSION ?= latest
+
+export GO111MODULE ?= on
+export GOPROXY ?= https://proxy.golang.org
+export GOSUMDB ?= sum.golang.org
+
+# If GOPATH is not set by the env, set it to a sane value
+GOPATH ?= $(shell cd ${ISTIO_GO}/../../..; pwd)
+export GOPATH
+
+# If GOPATH is made up of several paths, use the first one for our targets in 
this Makefile
+GO_TOP := $(shell echo ${GOPATH} | cut -d ':' -f1)
+export GO_TOP
+
+GO ?= go
+
+GOARCH_LOCAL := $(TARGET_ARCH)
+GOOS_LOCAL := $(TARGET_OS)
+
+#-----------------------------------------------------------------------------
+# Output control
+#-----------------------------------------------------------------------------
+# Invoke make VERBOSE=1 to enable echoing of the command being executed
+export VERBOSE ?= 0
+# Place the variable Q in front of a command to control echoing of the command 
being executed.
+Q = $(if $(filter 1,$VERBOSE),,@)
+# Use the variable H to add a header (equivalent to =>) to informational output
+H = $(shell printf "\033[34;1m=>\033[0m")
+
+ifeq ($(origin DEBUG), undefined)
+  BUILDTYPE_DIR:=release
+else ifeq ($(DEBUG),0)
+  BUILDTYPE_DIR:=release
+else
+  BUILDTYPE_DIR:=debug
+  export GCFLAGS:=all=-N -l
+  $(info $(H) Build with debugger information)
+endif
+
+# Optional file including user-specific settings (HUB, TAG, etc)
+-include .istiorc.mk
+
+# Environment for tests, the directory containing istio and deps binaries.
+# Typically same as GOPATH/bin, so tests work seemlessly with IDEs.
+
+export ISTIO_BIN=$(GOBIN)
+# Using same package structure as pkg/
+
+# If we are running in the Linux build container on non Linux hosts, we add the
+# linux binaries to the build dependencies, BUILD_DEPS, which can be added to 
other targets
+# that would need the Linux binaries (ex. tests).
+BUILD_DEPS:=
+ifeq ($(IN_BUILD_CONTAINER),1)
+  ifneq ($(GOOS_LOCAL),"linux")
+    BUILD_DEPS += build-linux
+  endif
+endif
+
+export ARTIFACTS ?= $(TARGET_OUT)
+export JUNIT_OUT ?= $(ARTIFACTS)/junit.xml
+export REPO_ROOT := $(shell git rev-parse --show-toplevel)
+
+# Make directories needed by the build system
+$(shell mkdir -p $(TARGET_OUT_LINUX))
+$(shell mkdir -p $(TARGET_OUT_LINUX)/logs)
+$(shell mkdir -p $(dir $(JUNIT_OUT)))
+
+# Need seperate target for init:
+$(TARGET_OUT):
+       @mkdir -p $@
+
+# scratch dir: this shouldn't be simply 'docker' since that's used for 
docker.save to store tar.gz files
+ISTIO_DOCKER:=${TARGET_OUT_LINUX}/docker_temp
+
+# scratch dir for building isolated images. Please don't remove it again - 
using
+# ISTIO_DOCKER results in slowdown, all files (including multiple copies of 
envoy) will be
+# copied to the docker temp container - even if you add only a tiny file, >1G 
of data will
+# be copied, for each docker image.
+DOCKER_BUILD_TOP:=${TARGET_OUT_LINUX}/docker_build
+DOCKERX_BUILD_TOP:=${TARGET_OUT_LINUX}/dockerx_build
+
+# dir where tar.gz files from docker.save are stored
+ISTIO_DOCKER_TAR:=${TARGET_OUT_LINUX}/release/docker
+
+# Populate the git version for istio/proxy (i.e. Envoy)
+ifeq ($(PROXY_REPO_SHA),)
+  export PROXY_REPO_SHA:=$(shell grep PROXY_REPO_SHA istio.deps  -A 4 | grep 
lastStableSHA | cut -f 4 -d '"')
+endif
+
+# Envoy binary variables Keep the default URLs up-to-date with the latest push 
from istio/proxy.
+
+export ISTIO_ENVOY_BASE_URL ?= https://storage.googleapis.com/istio-build/proxy
+
+# Use envoy as the sidecar by default
+export SIDECAR ?= envoy
+
+# OS-neutral vars. These currently only work for linux.
+export ISTIO_ENVOY_VERSION ?= ${PROXY_REPO_SHA}
+export ISTIO_ENVOY_DEBUG_URL ?= 
$(ISTIO_ENVOY_BASE_URL)/envoy-debug-$(ISTIO_ENVOY_VERSION).tar.gz
+export ISTIO_ENVOY_CENTOS_DEBUG_URL ?= 
$(ISTIO_ENVOY_BASE_URL)/envoy-centos-debug-$(ISTIO_ENVOY_VERSION).tar.gz
+export ISTIO_ENVOY_RELEASE_URL ?= 
$(ISTIO_ENVOY_BASE_URL)/envoy-alpha-$(ISTIO_ENVOY_VERSION).tar.gz
+export ISTIO_ENVOY_CENTOS_RELEASE_URL ?= 
$(ISTIO_ENVOY_BASE_URL)/envoy-centos-alpha-$(ISTIO_ENVOY_VERSION).tar.gz
+
+# Envoy Linux vars.
+export ISTIO_ENVOY_LINUX_VERSION ?= ${ISTIO_ENVOY_VERSION}
+export ISTIO_ENVOY_LINUX_DEBUG_URL ?= ${ISTIO_ENVOY_DEBUG_URL}
+export ISTIO_ENVOY_LINUX_RELEASE_URL ?= ${ISTIO_ENVOY_RELEASE_URL}
+# Variables for the extracted debug/release Envoy artifacts.
+export ISTIO_ENVOY_LINUX_DEBUG_DIR ?= ${TARGET_OUT_LINUX}/debug
+export ISTIO_ENVOY_LINUX_DEBUG_NAME ?= envoy-debug-${ISTIO_ENVOY_LINUX_VERSION}
+export ISTIO_ENVOY_LINUX_DEBUG_PATH ?= 
${ISTIO_ENVOY_LINUX_DEBUG_DIR}/${ISTIO_ENVOY_LINUX_DEBUG_NAME}
+export ISTIO_ENVOY_CENTOS_LINUX_DEBUG_NAME ?= 
envoy-centos-debug-${ISTIO_ENVOY_LINUX_VERSION}
+export ISTIO_ENVOY_CENTOS_LINUX_DEBUG_PATH ?= 
${ISTIO_ENVOY_LINUX_DEBUG_DIR}/${ISTIO_ENVOY_CENTOS_LINUX_DEBUG_NAME}
+
+export ISTIO_ENVOY_LINUX_RELEASE_DIR ?= ${TARGET_OUT_LINUX}/release
+export ISTIO_ENVOY_LINUX_RELEASE_NAME ?= ${SIDECAR}-${ISTIO_ENVOY_VERSION}
+export ISTIO_ENVOY_LINUX_RELEASE_PATH ?= 
${ISTIO_ENVOY_LINUX_RELEASE_DIR}/${ISTIO_ENVOY_LINUX_RELEASE_NAME}
+export ISTIO_ENVOY_CENTOS_LINUX_RELEASE_NAME ?= 
envoy-centos-${ISTIO_ENVOY_LINUX_VERSION}
+export ISTIO_ENVOY_CENTOS_LINUX_RELEASE_PATH ?= 
${ISTIO_ENVOY_LINUX_RELEASE_DIR}/${ISTIO_ENVOY_CENTOS_LINUX_RELEASE_NAME}
+
+# Envoy macOS vars.
+# TODO Change url when official envoy release for macOS is available
+export ISTIO_ENVOY_MACOS_VERSION ?= 1.0.2
+export ISTIO_ENVOY_MACOS_RELEASE_URL ?= 
https://github.com/istio/proxy/releases/download/${ISTIO_ENVOY_MACOS_VERSION}/istio-proxy-${ISTIO_ENVOY_MACOS_VERSION}-macos.tar.gz
+# Variables for the extracted debug/release Envoy artifacts.
+export ISTIO_ENVOY_MACOS_RELEASE_DIR ?= ${TARGET_OUT}/release
+export ISTIO_ENVOY_MACOS_RELEASE_NAME ?= envoy-${ISTIO_ENVOY_MACOS_VERSION}
+export ISTIO_ENVOY_MACOS_RELEASE_PATH ?= 
${ISTIO_ENVOY_MACOS_RELEASE_DIR}/${ISTIO_ENVOY_MACOS_RELEASE_NAME}
+
+# Allow user-override envoy bootstrap config path.
+export ISTIO_ENVOY_BOOTSTRAP_CONFIG_PATH ?= 
${ISTIO_GO}/tools/packaging/common/envoy_bootstrap.json
+export ISTIO_ENVOY_BOOTSTRAP_CONFIG_DIR = $(dir 
${ISTIO_ENVOY_BOOTSTRAP_CONFIG_PATH})
+
+# If the hub is not explicitly set, use default to istio.
+HUB ?=istio
+ifeq ($(HUB),)
+  $(error "HUB cannot be empty")
+endif
+
+# For dockerx builds, allow HUBS which is a space seperated list of hubs. 
Default to HUB.
+HUBS ?= $(HUB)
+
+# If tag not explicitly set in users' .istiorc.mk or command line, default to 
the git sha.
+TAG ?= $(shell git rev-parse --verify HEAD)
+ifeq ($(TAG),)
+  $(error "TAG cannot be empty")
+endif
+
+VARIANT :=
+ifeq ($(VARIANT),)
+  TAG_VARIANT:=${TAG}
+else
+  TAG_VARIANT:=${TAG}-${VARIANT}
+endif
+
+PULL_POLICY ?= IfNotPresent
+ifeq ($(TAG),latest)
+  PULL_POLICY = Always
+endif
+ifeq ($(PULL_POLICY),)
+  $(error "PULL_POLICY cannot be empty")
+endif
+
+include tools/proto/proto.mk
+
+.PHONY: default
+default: init build test
+
+.PHONY: init
+# Downloads envoy, based on the SHA defined in the base pilot Dockerfile
+#init: $(TARGET_OUT)/istio_is_init
+#      @mkdir -p ${TARGET_OUT}/logs
+#      @mkdir -p ${TARGET_OUT}/release
+
+# I tried to make this dependent on what I thought was the appropriate
+# lock file, but it caused the rule for that file to get run (which
+# seems to be about obtaining a new version of the 3rd party libraries).
+#$(TARGET_OUT)/istio_is_init: bin/init.sh istio.deps | $(TARGET_OUT)
+#      @# Add a retry, as occasionally we see transient connection failures to 
GCS
+#      @# Like `curl: (56) OpenSSL SSL_read: SSL_ERROR_SYSCALL, errno 104`
+#      TARGET_OUT=$(TARGET_OUT) ISTIO_BIN=$(ISTIO_BIN) 
GOOS_LOCAL=$(GOOS_LOCAL) bin/retry.sh SSL_ERROR_SYSCALL bin/init.sh
+#      touch $(TARGET_OUT)/istio_is_init
+
+# init.sh downloads envoy and webassembly plugins
+${TARGET_OUT}/${SIDECAR}: init
+${ISTIO_ENVOY_LINUX_DEBUG_PATH}: init
+${ISTIO_ENVOY_LINUX_RELEASE_PATH}: init
+${ISTIO_ENVOY_MACOS_RELEASE_PATH}: init
+
+# Pull dependencies, based on the checked in Gopkg.lock file.
+# Developers must manually run `dep ensure` if adding new deps
+depend: init | $(TARGET_OUT)
+
+DIRS_TO_CLEAN := $(TARGET_OUT)
+DIRS_TO_CLEAN += $(TARGET_OUT_LINUX)
+
+$(OUTPUT_DIRS):
+       @mkdir -p $@
+
+.PHONY: ${GEN_CERT}
+GEN_CERT := ${ISTIO_BIN}/generate_cert
+${GEN_CERT}:
+       GOOS=$(GOOS_LOCAL) && GOARCH=$(GOARCH_LOCAL) && 
tools/scripts/gobuild.sh $@ ./security/tools/generate_cert
+
+#-----------------------------------------------------------------------------
+# Target: precommit
+#-----------------------------------------------------------------------------
+.PHONY: precommit format lint
+
+# Target run by the pre-commit script, to automate formatting and lint
+# If pre-commit script is not used, please run this manually.
+precommit: format lint
+
+format: fmt ## Auto formats all code. This should be run before sending a PR.
+
+fmt: format-go format-python tidy-go
+
+ifeq ($(DEBUG),1)
+# gobuild script uses custom linker flag to set the variables.
+RELEASE_LDFLAGS=''
+else
+RELEASE_LDFLAGS='-extldflags -static -s -w'
+endif
+
+# List of all binaries to build
+# We split the binaries into "agent" binaries and standard ones. This 
corresponds to build "agent".
+# This allows conditional compilation to avoid pulling in costly dependencies 
to the agent, such as XDS and k8s.
+AGENT_BINARIES:=./pilot/cmd/pilot-agent
+STANDARD_BINARIES:=./istioctl/cmd/istioctl \
+  ./pilot/cmd/pilot-discovery 
+#  ./pkg/test/echo/cmd/client \
+#  ./pkg/test/echo/cmd/server \
+#  ./samples/extauthz/cmd/extauthz \
+#  ./operator/cmd/operator \
+#  ./cni/cmd/istio-cni \
+#  ./cni/cmd/istio-cni-taint \
+#  ./cni/cmd/install-cni \
+#  ./tools/istio-iptables \
+#  ./tools/bug-report
+BINARIES:=$(STANDARD_BINARIES) $(AGENT_BINARIES)
+
+# List of binaries included in releases
+RELEASE_BINARIES:=pilot-discovery pilot-agent istioctl bug-report
+
+.PHONY: build
+build: depend ## Builds all go binaries.
+       GOPROXY=https://goproxy.cn GOOS=$(GOOS_LOCAL) GOARCH=$(GOARCH_LOCAL) 
LDFLAGS=$(RELEASE_LDFLAGS) tools/scripts/gobuild.sh $(TARGET_OUT)/ 
$(STANDARD_BINARIES)
+       GOPROXY=https://goproxy.cn GOOS=$(GOOS_LOCAL) GOARCH=$(GOARCH_LOCAL) 
LDFLAGS=$(RELEASE_LDFLAGS) tools/scripts/gobuild.sh $(TARGET_OUT)/ -tags=agent 
$(AGENT_BINARIES)
+
+# The build-linux target is responsible for building binaries used within 
containers.
+# This target should be expanded upon as we add more Linux architectures: i.e. 
build-arm64.
+# Then a new build target can be created such as build-container-bin that 
builds these
+# various platform images.
+.PHONY: build-linux
+build-linux: depend
+       GOOS=linux GOARCH=$(GOARCH_LOCAL) LDFLAGS=$(RELEASE_LDFLAGS) 
tools/scripts/gobuild.sh $(TARGET_OUT_LINUX)/ $(STANDARD_BINARIES)
+       GOOS=linux GOARCH=$(GOARCH_LOCAL) LDFLAGS=$(RELEASE_LDFLAGS) 
tools/scripts/gobuild.sh $(TARGET_OUT_LINUX)/ -tags=agent $(AGENT_BINARIES)
+
+# Create targets for TARGET_OUT_LINUX/binary
+# There are two use cases here:
+# * Building all docker images (generally in CI). In this case we want to 
build everything at once, so they share work
+# * Building a single docker image (generally during dev). In this case we 
just want to build the single binary alone
+BUILD_ALL ?= true
+define build-linux
+.PHONY: $(TARGET_OUT_LINUX)/$(shell basename $(1))
+ifeq ($(BUILD_ALL),true)
+$(TARGET_OUT_LINUX)/$(shell basename $(1)): build-linux
+       @:
+else
+$(TARGET_OUT_LINUX)/$(shell basename $(1)): $(TARGET_OUT_LINUX)
+       GOOS=linux GOARCH=$(GOARCH_LOCAL) LDFLAGS=$(RELEASE_LDFLAGS) 
tools/scripts/gobuild.sh $(TARGET_OUT_LINUX)/ -tags=$(2) $(1)
+endif
+endef
+
+$(foreach bin,$(STANDARD_BINARIES),$(eval $(call build-linux,$(bin),"")))
+$(foreach bin,$(AGENT_BINARIES),$(eval $(call build-linux,$(bin),"agent")))
+
+# Create helper targets for each binary, like "pilot-discovery"
+# As an optimization, these still build everything
+$(foreach bin,$(BINARIES),$(shell basename $(bin))): build
+ifneq ($(TARGET_OUT_LINUX),$(LOCAL_OUT))
+# if we are on linux already, then this rule is handled by build-linux above, 
which handles BUILD_ALL variable
+$(foreach bin,$(BINARIES),${LOCAL_OUT}/$(shell basename $(bin))): build
+endif
+
+MARKDOWN_LINT_ALLOWLIST=localhost:8080,storage.googleapis.com/istio-artifacts/pilot/,http://ratings.default.svc.cluster.local:9080/ratings
+
+lint-helm-global:
+       find manifests -name 'Chart.yaml' -print0 | ${XARGS} -L 1 dirname | 
xargs -r helm lint
+
+lint: lint-python lint-copyright-banner lint-scripts lint-go lint-dockerfiles 
lint-markdown lint-yaml lint-licenses lint-helm-global ## Runs all linters.
+       @bin/check_samples.sh
+       @testlinter
+       @envvarlinter istioctl pilot security
+
+go-gen:
+       @mkdir -p /tmp/bin
+       @PATH="${PATH}":/tmp/bin go generate ./...
+
+refresh-goldens:
+       @REFRESH_GOLDEN=true go test ${GOBUILDFLAGS} ./operator/...
+       @REFRESH_GOLDEN=true go test ${GOBUILDFLAGS} ./pkg/kube/inject/...
+       @REFRESH_GOLDEN=true go test ${GOBUILDFLAGS} 
./pilot/pkg/security/authz/builder/...
+       @REFRESH_GOLDEN=true go test ${GOBUILDFLAGS} ./cni/pkg/plugin/...
+
+update-golden: refresh-goldens
+
+# Keep dummy target since some build pipelines depend on this
+gen-charts:
+       @echo "This target is no longer required and will be removed in the 
future"
+
+gen: \
+       mod-download-go \
+       go-gen \
+       mirror-licenses \
+       format \
+       update-crds \
+       proto \
+       copy-templates \
+       gen-kustomize \
+       update-golden ## Update all generated code.
+
+gen-check: gen check-clean-repo
+
+copy-templates:
+       rm manifests/charts/istiod-remote/templates/*
+       rm manifests/charts/gateways/istio-egress/templates/*
+
+       # gateway charts
+       cp -r manifests/charts/gateways/istio-ingress/templates/* 
manifests/charts/gateways/istio-egress/templates
+       find ./manifests/charts/gateways/istio-egress/templates -type f -exec 
sed -i -e 's/ingress/egress/g' {} \;
+       find ./manifests/charts/gateways/istio-egress/templates -type f -exec 
sed -i -e 's/Ingress/Egress/g' {} \;
+
+       # external istiod remote cluster charts
+       cp manifests/charts/base/templates/services.yaml 
manifests/charts/istiod-remote/templates
+       cp manifests/charts/base/templates/endpoints.yaml 
manifests/charts/istiod-remote/templates
+       cp manifests/charts/base/templates/reader-serviceaccount.yaml 
manifests/charts/istiod-remote/templates
+       cp 
manifests/charts/istio-control/istio-discovery/templates/mutatingwebhook.yaml 
manifests/charts/istiod-remote/templates
+       cp 
manifests/charts/istio-control/istio-discovery/templates/reader-clusterrole.yaml
 manifests/charts/istiod-remote/templates
+       cp 
manifests/charts/istio-control/istio-discovery/templates/reader-clusterrolebinding.yaml
 manifests/charts/istiod-remote/templates
+
+       # external istiod config cluster charts
+       cp 
manifests/charts/istio-control/istio-discovery/files/injection-template.yaml 
manifests/charts/istiod-remote/files
+       cp 
manifests/charts/istio-control/istio-discovery/files/gateway-injection-template.yaml
 manifests/charts/istiod-remote/files
+       cp 
manifests/charts/istio-control/istio-discovery/templates/istiod-injector-configmap.yaml
 manifests/charts/istiod-remote/templates
+       cp 
manifests/charts/istio-control/istio-discovery/templates/configmap.yaml 
manifests/charts/istiod-remote/templates
+       cp 
manifests/charts/istio-control/istio-discovery/templates/telemetryv2_*.yaml 
manifests/charts/istiod-remote/templates
+       sed -e '1 i {{- if .Values.global.configCluster }}' -e '$$ a {{- end 
}}' manifests/charts/base/crds/crd-all.gen.yaml > 
manifests/charts/istiod-remote/templates/crd-all.gen.yaml
+       sed -e '1 i {{- if .Values.global.configCluster }}' -e '$$ a {{- end 
}}' manifests/charts/base/crds/crd-operator.yaml > 
manifests/charts/istiod-remote/templates/crd-operator.yaml
+       sed -e '1 i {{- if .Values.global.configCluster }}' -e '$$ a {{- end 
}}' 
manifests/charts/istio-control/istio-discovery/templates/validatingwebhookconfiguration.yaml
 > manifests/charts/istiod-remote/templates/validatingwebhookconfiguration.yaml
+       sed -e '1 i {{- if .Values.global.configCluster }}' -e '$$ a {{- end 
}}' 
manifests/charts/istio-control/istio-discovery/templates/serviceaccount.yaml > 
manifests/charts/istiod-remote/templates/serviceaccount.yaml
+       sed -e '1 i {{- if .Values.global.configCluster }}' -e '$$ a {{- end 
}}' manifests/charts/istio-control/istio-discovery/templates/role.yaml > 
manifests/charts/istiod-remote/templates/role.yaml
+       sed -e '1 i {{- if .Values.global.configCluster }}' -e '$$ a {{- end 
}}' manifests/charts/istio-control/istio-discovery/templates/rolebinding.yaml > 
manifests/charts/istiod-remote/templates/rolebinding.yaml
+       sed -e '1 i {{- if .Values.global.configCluster }}' -e '$$ a {{- end 
}}' manifests/charts/istio-control/istio-discovery/templates/clusterrole.yaml > 
manifests/charts/istiod-remote/templates/clusterrole.yaml
+       sed -e '1 i {{- if .Values.global.configCluster }}' -e '$$ a {{- end 
}}' 
manifests/charts/istio-control/istio-discovery/templates/clusterrolebinding.yaml
 > manifests/charts/istiod-remote/templates/clusterrolebinding.yaml
+
+       # copy istio-discovery values, but apply some local customizations
+       cp manifests/charts/istio-control/istio-discovery/values.yaml 
manifests/charts/istiod-remote/
+       yq -i '.telemetry.enabled=false | .global.externalIstiod=true | 
.global.omitSidecarInjectorConfigMap=true | .pilot.configMap=false' 
manifests/charts/istiod-remote/values.yaml
+# Generate kustomize templates.
+gen-kustomize:
+       helm3 template istio --namespace istio-system --include-crds 
manifests/charts/base > manifests/charts/base/files/gen-istio-cluster.yaml
+       helm3 template istio --namespace istio-system 
manifests/charts/istio-control/istio-discovery \
+               > 
manifests/charts/istio-control/istio-discovery/files/gen-istio.yaml
+       helm3 template operator --namespace istio-operator 
manifests/charts/istio-operator \
+               --set hub=gcr.io/istio-testing --set tag=${VERSION} > 
manifests/charts/istio-operator/files/gen-operator.yaml
+
+#-----------------------------------------------------------------------------
+# Target: go build
+#-----------------------------------------------------------------------------
+
+# Non-static istioctl targets. These are typically a build artifact.
+${TARGET_OUT}/release/istioctl-linux-amd64: depend
+       GOOS=linux GOARCH=amd64 LDFLAGS=$(RELEASE_LDFLAGS) 
tools/scripts/gobuild.sh $@ ./istioctl/cmd/istioctl
+${TARGET_OUT}/release/istioctl-linux-armv7: depend
+       GOOS=linux GOARCH=arm GOARM=7 LDFLAGS=$(RELEASE_LDFLAGS) 
tools/scripts/gobuild.sh $@ ./istioctl/cmd/istioctl
+${TARGET_OUT}/release/istioctl-linux-arm64: depend
+       GOOS=linux GOARCH=arm64 LDFLAGS=$(RELEASE_LDFLAGS) 
tools/scripts/gobuild.sh $@ ./istioctl/cmd/istioctl
+${TARGET_OUT}/release/istioctl-osx: depend
+       GOOS=darwin GOARCH=amd64 LDFLAGS=$(RELEASE_LDFLAGS) 
tools/scripts/gobuild.sh $@ ./istioctl/cmd/istioctl
+${TARGET_OUT}/release/istioctl-osx-arm64: depend
+       GOOS=darwin GOARCH=arm64 LDFLAGS=$(RELEASE_LDFLAGS) 
tools/scripts/gobuild.sh $@ ./istioctl/cmd/istioctl
+${TARGET_OUT}/release/istioctl-win.exe: depend
+       GOOS=windows LDFLAGS=$(RELEASE_LDFLAGS) tools/scripts/gobuild.sh $@ 
./istioctl/cmd/istioctl
+
+# generate the istioctl completion files
+${TARGET_OUT}/release/istioctl.bash: ${LOCAL_OUT}/istioctl
+       ${LOCAL_OUT}/istioctl completion bash > 
${TARGET_OUT}/release/istioctl.bash
+
+${TARGET_OUT}/release/_istioctl: ${LOCAL_OUT}/istioctl
+       ${LOCAL_OUT}/istioctl completion zsh > ${TARGET_OUT}/release/_istioctl
+
+.PHONY: binaries-test
+binaries-test:
+       go test ${GOBUILDFLAGS} ./tests/binary/... -v --base-dir ${TARGET_OUT} 
--binaries="$(RELEASE_BINARIES)"
+
+# istioctl-all makes all of the non-static istioctl executables for each 
supported OS
+.PHONY: istioctl-all
+istioctl-all: ${TARGET_OUT}/release/istioctl-linux-amd64 
${TARGET_OUT}/release/istioctl-linux-armv7 
${TARGET_OUT}/release/istioctl-linux-arm64 \
+       ${TARGET_OUT}/release/istioctl-osx \
+       ${TARGET_OUT}/release/istioctl-osx-arm64 \
+       ${TARGET_OUT}/release/istioctl-win.exe
+
+.PHONY: istioctl.completion
+istioctl.completion: ${TARGET_OUT}/release/istioctl.bash 
${TARGET_OUT}/release/_istioctl
+
+# istioctl-install builds then installs istioctl into $GOPATH/BIN
+# Used for debugging istioctl during dev work
+.PHONY: istioctl-install-container
+istioctl-install-container: istioctl
+
+#-----------------------------------------------------------------------------
+# Target: test
+#-----------------------------------------------------------------------------
+
+.PHONY: test
+
+# This target sets JUNIT_REPORT to the location of the  go-junit-report binary.
+# This binary is provided in the build container. If it is not found, the build
+# container is not being used, so ask the user to install go-junit-report.
+JUNIT_REPORT := $(shell which go-junit-report 2> /dev/null || echo 
"${ISTIO_BIN}/go-junit-report")
+
+${ISTIO_BIN}/go-junit-report:
+       @echo "go-junit-report was not found in the build environment."
+       @echo "Please install go-junit-report (ex. go install 
github.com/jstemmer/go-junit-report@latest)"
+       @exit 1
+
+# This is just an alias for racetest now
+test: racetest ## Runs all unit tests
+
+# For now, keep a minimal subset. This can be expanded in the future.
+BENCH_TARGETS ?= ./pilot/...
+
+.PHONY: racetest
+racetest: $(JUNIT_REPORT)
+       go test ${GOBUILDFLAGS} ${T} -race ./... 2>&1 | tee >($(JUNIT_REPORT) > 
$(JUNIT_OUT))
+
+.PHONY: benchtest
+benchtest: $(JUNIT_REPORT) ## Runs all benchmarks
+       prow/benchtest.sh run $(BENCH_TARGETS)
+       prow/benchtest.sh compare
+
+report-benchtest:
+       prow/benchtest.sh report
+
+#-----------------------------------------------------------------------------
+# Target: clean
+#-----------------------------------------------------------------------------
+.PHONY: clean
+
+clean: ## Cleans all the intermediate files and folders previously generated.
+       rm -rf $(DIRS_TO_CLEAN)
+
+#-----------------------------------------------------------------------------
+# Target: docker
+#-----------------------------------------------------------------------------
+.PHONY: push
+
+# for now docker is limited to Linux compiles - why ?
+include tools/istio-docker.mk
+
+push: docker.push ## Build and push docker images to registry defined by $HUB 
and $TAG
+
+#-----------------------------------------------------------------------------
+# Target: environment and tools
+#-----------------------------------------------------------------------------
+.PHONY: show.env show.goenv
+
+show.env: ; $(info $(H) environment variables...)
+       $(Q) printenv
+
+show.goenv: ; $(info $(H) go environment...)
+       $(Q) $(GO) version
+       $(Q) $(GO) env
+
+# show makefile variables. Usage: make show.<variable-name>
+show.%: ; $(info $* $(H) $($*))
+       $(Q) true
+
+#-----------------------------------------------------------------------------
+# Target: custom resource definitions
+#-----------------------------------------------------------------------------
+
+update-crds:
+       bin/update_crds.sh
+
+#-----------------------------------------------------------------------------
+# Target: artifacts and distribution
+#-----------------------------------------------------------------------------
+# deb, rpm, etc packages
+include tools/packaging/packaging.mk
+
+#-----------------------------------------------------------------------------
+# Target: integration tests
+#-----------------------------------------------------------------------------
+include tests/integration/tests.mk
+
+include tools/Makefile.common.mk
diff --git a/istioctl/docker/Dockerfile.istioctl 
b/istioctl/docker/Dockerfile.istioctl
index 39ee615c..88ba15bd 100644
--- a/istioctl/docker/Dockerfile.istioctl
+++ b/istioctl/docker/Dockerfile.istioctl
@@ -1,6 +1,39 @@
+FROM ubuntu:jammy
+
+ENV DEBIAN_FRONTEND=noninteractive
+
+# Do not add more stuff to this list that isn't small or critically useful.
+# If you occasionally need something on the container do
+# sudo apt-get update && apt-get whichever
+
+# hadolint ignore=DL3005,DL3008
+RUN apt-get update && \
+  apt-get install --no-install-recommends -y \
+  ca-certificates \
+  curl \
+  iptables \
+  iproute2 \
+  iputils-ping \
+  knot-dnsutils \
+  netcat \
+  tcpdump \
+  conntrack \
+  bsdmainutils \
+  net-tools \
+  lsof \
+  sudo \
+  && update-ca-certificates \
+  && apt-get upgrade -y \
+  && apt-get clean \
+  && rm -rf  /var/log/*log /var/lib/apt/lists/* /var/log/apt/* 
/var/lib/dpkg/*-old /var/cache/debconf/*-old \
+  && update-alternatives --set iptables /usr/sbin/iptables-legacy \
+  && update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
+
+# Sudoers used to allow tcpdump and other debug utilities.
+RUN useradd -m --uid 1337 istio-proxy && \
+  echo "istio-proxy ALL=NOPASSWD: ALL" >> /etc/sudoers
+
 # Version is the base image version from the TLD Makefile
-ARG BASE_VERSION=latest
-FROM gcr.io/istio-release/base:${BASE_VERSION}
 USER 1000:1000
 ARG TARGETARCH
 COPY ${TARGETARCH:-amd64}/istioctl /usr/local/bin/istioctl
diff --git a/pilot/docker/Dockerfile.pilot b/pilot/docker/Dockerfile.pilot
index fe2c87ee..4e1e2eee 100644
--- a/pilot/docker/Dockerfile.pilot
+++ b/pilot/docker/Dockerfile.pilot
@@ -1,21 +1,47 @@
+FROM ubuntu:jammy
+
+ENV DEBIAN_FRONTEND=noninteractive
+
+# Do not add more stuff to this list that isn't small or critically useful.
+# If you occasionally need something on the container do
+# sudo apt-get update && apt-get whichever
+
+# hadolint ignore=DL3005,DL3008
+RUN apt-get update && \
+  apt-get install --no-install-recommends -y \
+  ca-certificates \
+  curl \
+  iptables \
+  iproute2 \
+  iputils-ping \
+  knot-dnsutils \
+  netcat \
+  tcpdump \
+  conntrack \
+  bsdmainutils \
+  net-tools \
+  lsof \
+  sudo \
+  && update-ca-certificates \
+  && apt-get upgrade -y \
+  && apt-get clean \
+  && rm -rf  /var/log/*log /var/lib/apt/lists/* /var/log/apt/* 
/var/lib/dpkg/*-old /var/cache/debconf/*-old \
+  && update-alternatives --set iptables /usr/sbin/iptables-legacy \
+  && update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
+
+# Sudoers used to allow tcpdump and other debug utilities.
+RUN useradd -m --uid 1337 istio-proxy && \
+  echo "istio-proxy ALL=NOPASSWD: ALL" >> /etc/sudoers
+
 # BASE_DISTRIBUTION is used to switch between the old base distribution and 
distroless base images
 ARG BASE_DISTRIBUTION=debug
 
 # Version is the base image version from the TLD Makefile
 ARG BASE_VERSION=latest
 
-# The following section is used as base image if BASE_DISTRIBUTION=debug
-FROM gcr.io/istio-release/base:${BASE_VERSION} as debug
-
-# The following section is used as base image if BASE_DISTRIBUTION=distroless
-FROM gcr.io/istio-release/distroless:${BASE_VERSION} as distroless
-
-# This will build the final image based on either debug or distroless from 
above
-# hadolint ignore=DL3006
-FROM ${BASE_DISTRIBUTION:-debug}
-
 ARG TARGETARCH
 COPY ${TARGETARCH:-amd64}/pilot-discovery /usr/local/bin/pilot-discovery
+#COPY ${TARGETARCH:-amd64}/dlv /usr/local/bin/dlv
 
 # Copy templates for bootstrap generation.
 COPY envoy_bootstrap.json /var/lib/istio/envoy/envoy_bootstrap_tmpl.json
diff --git a/pkg/kube/client.go b/pkg/kube/client.go
index 1cc405fd..64b2b8ed 100644
--- a/pkg/kube/client.go
+++ b/pkg/kube/client.go
@@ -943,6 +943,7 @@ func (c *client) applyYAMLFile(namespace string, dryRun 
bool, file string) error
        }
        opts.DynamicClient = c.dynamic
        opts.DryRunVerifier = resource.NewQueryParamVerifier(c.dynamic, 
c.discoveryClient, resource.QueryParamDryRun)
+       opts.FieldValidationVerifier = 
resource.NewQueryParamVerifier(c.dynamic, c.clientFactory.OpenAPIGetter(), 
resource.QueryParamFieldValidation)
        opts.FieldManager = fieldManager
        if dryRun {
                opts.DryRunStrategy = util.DryRunServer
diff --git a/tools/Makefile.common.mk b/tools/Makefile.common.mk
new file mode 100644
index 00000000..b3a7528e
--- /dev/null
+++ b/tools/Makefile.common.mk
@@ -0,0 +1,128 @@
+# WARNING: DO NOT EDIT, THIS FILE IS PROBABLY A COPY
+#
+# The original version of this file is located in the 
https://github.com/istio/common-files repo.
+# If you're looking at this file in a different repo and want to make a 
change, please go to the
+# common-files repo, make the change there and check it in. Then come back to 
this repo and run
+# "make update-common".
+
+# Copyright Istio Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+FINDFILES=find . \( -path ./common-protos -o -path ./.git -o -path ./out -o 
-path ./.github -o -path ./licenses -o -path ./vendor \) -prune -o -type f
+XARGS = xargs -0 -r
+
+lint-dockerfiles:
+       @${FINDFILES} -name 'Dockerfile*' -print0 | ${XARGS} hadolint -c 
./common/config/.hadolint.yml
+
+lint-scripts:
+       @${FINDFILES} -name '*.sh' -print0 | ${XARGS} shellcheck
+
+lint-yaml:
+       @${FINDFILES} \( -name '*.yml' -o -name '*.yaml' \) -not -exec grep -q 
-e "{{" {} \; -print0 | ${XARGS} yamllint -c ./common/config/.yamllint.yml
+
+lint-helm:
+       @${FINDFILES} -name 'Chart.yaml' -print0 | ${XARGS} -L 1 dirname | 
xargs -r helm lint --strict
+
+lint-copyright-banner:
+       @${FINDFILES} \( -name '*.go' -o -name '*.cc' -o -name '*.h' -o -name 
'*.proto' -o -name '*.py' -o -name '*.sh' \) \( ! \( -name '*.gen.go' -o -name 
'*.pb.go' -o -name '*_pb2.py' \) \) -print0 |\
+               ${XARGS} common/scripts/lint_copyright_banner.sh
+
+fix-copyright-banner:
+       @${FINDFILES} \( -name '*.go' -o -name '*.cc' -o -name '*.h' -o -name 
'*.proto' -o -name '*.py' -o -name '*.sh' \) \( ! \( -name '*.gen.go' -o -name 
'*.pb.go' -o -name '*_pb2.py' \) \) -print0 |\
+               ${XARGS} common/scripts/fix_copyright_banner.sh
+
+lint-go:
+       @${FINDFILES} -name '*.go' \( ! \( -name '*.gen.go' -o -name '*.pb.go' 
\) \) -print0 | ${XARGS} common/scripts/lint_go.sh
+
+lint-python:
+       @${FINDFILES} -name '*.py' \( ! \( -name '*_pb2.py' \) \) -print0 | 
${XARGS} autopep8 --max-line-length 160 --exit-code -d
+
+lint-markdown:
+       @${FINDFILES} -name '*.md' -print0 | ${XARGS} mdl --ignore-front-matter 
--style common/config/mdl.rb
+
+lint-links:
+       @${FINDFILES} -name '*.md' -print0 | ${XARGS} awesome_bot 
--skip-save-results --allow_ssl --allow-timeout --allow-dupe --allow-redirect 
--white-list ${MARKDOWN_LINT_ALLOWLIST}
+
+lint-sass:
+       @${FINDFILES} -name '*.scss' -print0 | ${XARGS} sass-lint -c 
common/config/sass-lint.yml --verbose
+
+lint-typescript:
+       @${FINDFILES} -name '*.ts' -print0 | ${XARGS} tslint -c 
common/config/tslint.json
+
+lint-protos:
+       @if test -d common-protos; then $(FINDFILES) -name '*.proto' -print0 | 
$(XARGS) -L 1 prototool lint --protoc-bin-path=/usr/bin/protoc 
--protoc-wkt-path=common-protos; fi
+
+lint-licenses:
+       @if test -d licenses; then license-lint --config 
common/config/license-lint.yml; fi
+
+lint-all: lint-dockerfiles lint-scripts lint-yaml lint-helm 
lint-copyright-banner lint-go lint-python lint-markdown lint-sass 
lint-typescript lint-protos lint-licenses
+
+tidy-go:
+       @find -name go.mod -execdir go mod tidy \;
+
+mod-download-go:
+       @-GOFLAGS="-mod=readonly" find -name go.mod -execdir go mod download \;
+# go mod tidy is needed with Golang 1.16+ as go mod download affects go.sum
+# https://github.com/golang/go/issues/43994
+       @find -name go.mod -execdir go mod tidy \;
+
+format-go: tidy-go
+       @${FINDFILES} -name '*.go' \( ! \( -name '*.gen.go' -o -name '*.pb.go' 
\) \) -print0 | ${XARGS} common/scripts/format_go.sh
+
+format-python:
+       @${FINDFILES} -name '*.py' -print0 | ${XARGS} autopep8 
--max-line-length 160 --aggressive --aggressive -i
+
+format-protos:
+       @$(FINDFILES) -name '*.proto' -print0 | $(XARGS) -L 1 prototool format 
-w
+
+dump-licenses: mod-download-go
+       @license-lint --config common/config/license-lint.yml --report
+
+dump-licenses-csv: mod-download-go
+       @license-lint --config common/config/license-lint.yml --csv
+
+mirror-licenses: mod-download-go
+       @rm -fr licenses
+       @license-lint --mirror
+
+TMP := $(shell mktemp -d -u)
+UPDATE_BRANCH ?= "release-1.14"
+
+update-common:
+       @mkdir -p $(TMP)
+       @git clone -q --depth 1 --single-branch --branch $(UPDATE_BRANCH) 
https://github.com/istio/common-files $(TMP)/common-files
+       @cd $(TMP)/common-files ; git rev-parse HEAD 
>files/common/.commonfiles.sha
+       @rm -fr common
+       @cp -a $(TMP)/common-files/files/* $(shell pwd)
+       @rm -fr $(TMP)/common-files
+
+update-common-protos:
+       @mkdir -p $(TMP)
+       @git clone -q --depth 1 --single-branch --branch $(UPDATE_BRANCH) 
https://github.com/istio/common-files $(TMP)/common-files
+       @cd $(TMP)/common-files ; git rev-parse HEAD > 
common-protos/.commonfiles.sha
+       @rm -fr common-protos
+       @cp -a $(TMP)/common-files/common-protos $(shell pwd)
+       @rm -fr $(TMP)/common-files
+
+check-clean-repo:
+       @common/scripts/check_clean_repo.sh
+
+tidy-docker:
+       @docker image prune --all --force 
--filter="label=io.istio.repo=https://github.com/istio/tools"; 
--filter="label!=io.istio.version=$(IMAGE_VERSION)"
+
+# help works by looking over all Makefile includes matching `target: ## 
comment` regex and outputting them
+help: ## Show this help
+       @egrep -h '^[a-zA-Z_\.-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort  | awk 
'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
+
+.PHONY: lint-dockerfiles lint-scripts lint-yaml lint-copyright-banner lint-go 
lint-python lint-helm lint-markdown lint-sass lint-typescript lint-protos 
lint-all format-go format-python format-protos update-common 
update-common-protos lint-licenses dump-licenses dump-licenses-csv 
check-clean-repo tidy-docker help tidy-go mod-download-go
diff --git a/tools/scripts/check_clean_repo.sh 
b/tools/scripts/check_clean_repo.sh
new file mode 100755
index 00000000..075c9fa6
--- /dev/null
+++ b/tools/scripts/check_clean_repo.sh
@@ -0,0 +1,45 @@
+#!/bin/bash
+
+# Copyright Istio Authors
+
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+function write_patch_file() {
+    if [ -z "${ARTIFACTS}" ]; then
+      return 0
+    fi
+
+    PATCH_NAME="check-clean-repo-diff.patch"
+    PATCH_OUT="${ARTIFACTS}/${PATCH_NAME}"
+    git diff > "${PATCH_OUT}"
+
+    [ -n "${JOB_NAME}" ] && [ -n "${BUILD_ID}" ]
+    IN_PROW="$?"
+
+    # Don't persist large diffs (30M+) on CI
+    LARGE_FILE="$(find "${ARTIFACTS}" -name "${PATCH_NAME}" -type 'f' -size 
+30M)"
+    if [ "${IN_PROW}" -eq 0 ] && [ -n "${LARGE_FILE}" ]; then
+      rm "${PATCH_OUT}"
+      echo "WARNING: patch file was too large to persist ($(du -h 
"${PATCH_OUT}"))"
+      return 0
+    fi
+    echo "You can also try applying the patch file from the build artifacts."
+}
+
+if [[ -n $(git status --porcelain) ]]; then
+  git status
+  git diff
+  echo "ERROR: Some files need to be updated, please run 'make gen' and 
include any changed files in your PR"
+  write_patch_file
+  exit 1
+fi
diff --git a/tools/scripts/copyright-banner-go.txt 
b/tools/scripts/copyright-banner-go.txt
new file mode 100644
index 00000000..ffac692d
--- /dev/null
+++ b/tools/scripts/copyright-banner-go.txt
@@ -0,0 +1,14 @@
+// Copyright Istio Authors
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
diff --git a/tools/scripts/fix_copyright_banner.sh 
b/tools/scripts/fix_copyright_banner.sh
new file mode 100755
index 00000000..e4945be1
--- /dev/null
+++ b/tools/scripts/fix_copyright_banner.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+# WARNING: DO NOT EDIT, THIS FILE IS PROBABLY A COPY
+#
+# The original version of this file is located in the 
https://github.com/istio/common-files repo.
+# If you're looking at this file in a different repo and want to make a 
change, please go to the
+# common-files repo, make the change there and check it in. Then come back to 
this repo and run
+# "make update-common".
+
+# Copyright Istio Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -e
+
+WD=$(dirname "$0")
+WD=$(cd "$WD"; pwd)
+
+for fn in "$@"; do
+  if ! grep -L -q -e "Apache License, Version 2" -e "Copyright" "${fn}"; then
+    if [[ "${fn}" == *.go ]]; then
+      newfile=$(cat "${WD}/copyright-banner-go.txt" "${fn}")
+      echo "${newfile}" > "${fn}"
+      echo "Fixing license: ${fn}"
+    else
+      echo "Cannot fix license: ${fn}. Unknown file type"
+    fi
+  fi
+done
diff --git a/tools/scripts/format_go.sh b/tools/scripts/format_go.sh
new file mode 100755
index 00000000..18605270
--- /dev/null
+++ b/tools/scripts/format_go.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+# WARNING: DO NOT EDIT, THIS FILE IS PROBABLY A COPY
+#
+# The original version of this file is located in the 
https://github.com/istio/common-files repo.
+# If you're looking at this file in a different repo and want to make a 
change, please go to the
+# common-files repo, make the change there and check it in. Then come back to 
this repo and run
+# "make update-common".
+
+# Copyright Istio Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+golangci-lint run --fix -c ./common/config/.golangci-format.yml
diff --git a/tools/scripts/gobuild.sh b/tools/scripts/gobuild.sh
new file mode 100755
index 00000000..774faab7
--- /dev/null
+++ b/tools/scripts/gobuild.sh
@@ -0,0 +1,89 @@
+#!/bin/bash
+
+# WARNING: DO NOT EDIT, THIS FILE IS PROBABLY A COPY
+#
+# The original version of this file is located in the 
https://github.com/istio/common-files repo.
+# If you're looking at this file in a different repo and want to make a 
change, please go to the
+# common-files repo, make the change there and check it in. Then come back to 
this repo and run
+# "make update-common".
+
+# Copyright Istio Authors. All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This script builds and version stamps the output
+
+VERBOSE=${VERBOSE:-"0"}
+V=""
+if [[ "${VERBOSE}" == "1" ]];then
+    V="-x"
+    set -x
+fi
+
+SCRIPTPATH="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+
+OUT=${1:?"output path"}
+shift
+
+set -e
+
+BUILD_GOOS=${GOOS:-linux}
+BUILD_GOARCH=${GOARCH:-amd64}
+GOBINARY=${GOBINARY:-go}
+GOPKG="$GOPATH/pkg"
+BUILDINFO=${BUILDINFO:-""}
+STATIC=${STATIC:-1}
+LDFLAGS=${LDFLAGS:--extldflags -static}
+GOBUILDFLAGS=${GOBUILDFLAGS:-""}
+# Split GOBUILDFLAGS by spaces into an array called GOBUILDFLAGS_ARRAY.
+IFS=' ' read -r -a GOBUILDFLAGS_ARRAY <<< "$GOBUILDFLAGS"
+
+GCFLAGS=${GCFLAGS:-}
+export CGO_ENABLED=${CGO_ENABLED:-0}
+
+if [[ "${STATIC}" !=  "1" ]];then
+    LDFLAGS=""
+fi
+
+# gather buildinfo if not already provided
+# For a release build BUILDINFO should be produced
+# at the beginning of the build and used throughout
+if [[ -z ${BUILDINFO} ]];then
+    BUILDINFO=$(mktemp)
+    "${SCRIPTPATH}/report_build_info.sh" > "${BUILDINFO}"
+fi
+
+# BUILD LD_EXTRAFLAGS
+LD_EXTRAFLAGS=""
+
+while read -r line; do
+    LD_EXTRAFLAGS="${LD_EXTRAFLAGS} -X ${line}"
+done < "${BUILDINFO}"
+
+OPTIMIZATION_FLAGS=(-trimpath)
+if [ "${DEBUG}" == "1" ]; then
+    OPTIMIZATION_FLAGS=()
+fi
+
+echo GOOS=${BUILD_GOOS} GOARCH=${BUILD_GOARCH} ${GOBINARY} build \
+        ${V} "${GOBUILDFLAGS_ARRAY[@]}" ${GCFLAGS:+-gcflags "${GCFLAGS}"} \
+        -o "${OUT}" \
+        "${OPTIMIZATION_FLAGS[@]}" \
+        -pkgdir="${GOPKG}/${BUILD_GOOS}_${BUILD_GOARCH}" \
+        -ldflags "${LDFLAGS} ${LD_EXTRAFLAGS}" "${@}"
+time GOOS=${BUILD_GOOS} GOARCH=${BUILD_GOARCH} ${GOBINARY} build \
+        ${V} "${GOBUILDFLAGS_ARRAY[@]}" ${GCFLAGS:+-gcflags "${GCFLAGS}"} \
+        -o "${OUT}" \
+        "${OPTIMIZATION_FLAGS[@]}" \
+        -pkgdir="${GOPKG}/${BUILD_GOOS}_${BUILD_GOARCH}" \
+        -ldflags "${LDFLAGS} ${LD_EXTRAFLAGS}" "${@}"
diff --git a/tools/scripts/kind_provisioner.sh 
b/tools/scripts/kind_provisioner.sh
new file mode 100644
index 00000000..0839df8d
--- /dev/null
+++ b/tools/scripts/kind_provisioner.sh
@@ -0,0 +1,431 @@
+#!/bin/bash
+
+# WARNING: DO NOT EDIT, THIS FILE IS PROBABLY A COPY
+#
+# The original version of this file is located in the 
https://github.com/istio/common-files repo.
+# If you're looking at this file in a different repo and want to make a 
change, please go to the
+# common-files repo, make the change there and check it in. Then come back to 
this repo and run
+# "make update-common".
+
+# Copyright Istio Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -e
+set -x
+
+# The purpose of this file is to unify prow/lib.sh in both istio and istio.io
+# repos to avoid code duplication.
+
+####################################################################
+#################   COMMON SECTION   ###############################
+####################################################################
+
+# DEFAULT_KIND_IMAGE is used to set the Kubernetes version for KinD unless 
overridden in params to setup_kind_cluster(s)
+DEFAULT_KIND_IMAGE="gcr.io/istio-testing/kind-node:v1.21.1"
+
+# COMMON_SCRIPTS contains the directory this file is in.
+COMMON_SCRIPTS=$(dirname "${BASH_SOURCE:-$0}")
+
+function log() {
+  echo -e "$(date -u '+%Y-%m-%dT%H:%M:%S.%NZ')\t$*"
+}
+
+function retry() {
+  local n=1
+  local max=5
+  local delay=5
+  while true; do
+    "$@" && break
+    if [[ $n -lt $max ]]; then
+      ((n++))
+      log "Command failed. Attempt $n/$max:"
+      sleep $delay;
+    else
+      log "The command has failed after $n attempts."  >&2
+      return 2
+    fi
+  done
+}
+
+# load_cluster_topology function reads cluster configuration topology file and
+# sets up environment variables used by other functions. So this should be 
called
+# before anything else.
+#
+# Note: Cluster configuration topology file specifies basic configuration of 
each
+# KinD cluster like its name, pod and service subnets and network_id. If two 
cluster
+# have the same network_id then they belong to the same network and their pods 
can
+# talk to each other directly.
+#
+# [{ "cluster_name": "cluster1","pod_subnet": "10.10.0.0/16","svc_subnet": 
"10.255.10.0/24","network_id": "0" },
+#  { "cluster_name": "cluster2","pod_subnet": "10.20.0.0/16","svc_subnet": 
"10.255.20.0/24","network_id": "0" },
+#  { "cluster_name": "cluster3","pod_subnet": "10.30.0.0/16","svc_subnet": 
"10.255.30.0/24","network_id": "1" }]
+function load_cluster_topology() {
+  CLUSTER_TOPOLOGY_CONFIG_FILE="${1}"
+
+  if [[ ! -f "${CLUSTER_TOPOLOGY_CONFIG_FILE}" ]]; then
+    log 'cluster topology configuration file is not specified'
+    exit 1
+  fi
+
+  export CLUSTER_NAMES
+  export CLUSTER_POD_SUBNETS
+  export CLUSTER_SVC_SUBNETS
+  export CLUSTER_NETWORK_ID
+
+  KUBE_CLUSTERS=$(jq '.[] | select(.kind == "Kubernetes" or .kind == null)' 
"${CLUSTER_TOPOLOGY_CONFIG_FILE}")
+
+  while read -r value; do
+    CLUSTER_NAMES+=("$value")
+  done < <(echo "${KUBE_CLUSTERS}" | jq -r '.cluster_name // .clusterName')
+
+  while read -r value; do
+    CLUSTER_POD_SUBNETS+=("$value")
+  done < <(echo "${KUBE_CLUSTERS}" | jq -r '.pod_subnet // .podSubnet')
+
+  while read -r value; do
+    CLUSTER_SVC_SUBNETS+=("$value")
+  done < <(echo "${KUBE_CLUSTERS}" | jq -r '.svc_subnet // .svcSubnet')
+
+  while read -r value; do
+    CLUSTER_NETWORK_ID+=("$value")
+  done < <(echo "${KUBE_CLUSTERS}" | jq -r '.network_id // .network')
+
+  export NUM_CLUSTERS
+  NUM_CLUSTERS=$(echo "${KUBE_CLUSTERS}" | jq -s 'length')
+
+  echo "${CLUSTER_NAMES[@]}"
+  echo "${CLUSTER_POD_SUBNETS[@]}"
+  echo "${CLUSTER_SVC_SUBNETS[@]}"
+  echo "${CLUSTER_NETWORK_ID[@]}"
+  echo "${NUM_CLUSTERS}"
+}
+
+#####################################################################
+###################   SINGLE-CLUSTER SECTION   ######################
+#####################################################################
+
+# cleanup_kind_cluster takes a single parameter NAME
+# and deletes the KinD cluster with that name
+function cleanup_kind_cluster() {
+  echo "Test exited with exit code $?."
+  NAME="${1}"
+  kind export logs --name "${NAME}" "${ARTIFACTS}/kind" -v9 || true
+  if [[ -z "${SKIP_CLEANUP:-}" ]]; then
+    echo "Cleaning up kind cluster"
+    kind delete cluster --name "${NAME}" -v9 || true
+  fi
+}
+
+# check_default_cluster_yaml checks the presence of default cluster YAML
+# It returns 1 if it is not present
+function check_default_cluster_yaml() {
+  if [[ -z "${DEFAULT_CLUSTER_YAML}" ]]; then
+    echo 'DEFAULT_CLUSTER_YAML file must be specified. Exiting...'
+    return 1
+  fi
+}
+
+function setup_kind_cluster_retry() {
+  retry setup_kind_cluster "$@"
+}
+
+# setup_kind_cluster creates new KinD cluster with given name, image and 
configuration
+# 1. NAME: Name of the Kind cluster (optional)
+# 2. IMAGE: Node image used by KinD (optional)
+# 3. CONFIG: KinD cluster configuration YAML file. If not specified then 
DEFAULT_CLUSTER_YAML is used
+# 4. NOMETALBINSTALL: Dont install matllb if set.
+# This function returns 0 when everything goes well, or 1 otherwise
+# If Kind cluster was already created then it would be cleaned up in case of 
errors
+function setup_kind_cluster() {
+  NAME="${1:-istio-testing}"
+  IMAGE="${2:-"${DEFAULT_KIND_IMAGE}"}"
+  CONFIG="${3:-}"
+  NOMETALBINSTALL="${4:-}"
+
+  check_default_cluster_yaml
+
+  # Delete any previous KinD cluster
+  echo "Deleting previous KinD cluster with name=${NAME}"
+  if ! (kind delete cluster --name="${NAME}" -v9) > /dev/null; then
+    echo "No existing kind cluster with name ${NAME}. Continue..."
+  fi
+
+  # explicitly disable shellcheck since we actually want $NAME to expand now
+  # shellcheck disable=SC2064
+  trap "cleanup_kind_cluster ${NAME}" EXIT
+
+    # If config not explicitly set, then use defaults
+  if [[ -z "${CONFIG}" ]]; then
+    # Kubernetes 1.15+
+    CONFIG=${DEFAULT_CLUSTER_YAML}
+    # Configure the cluster IP Family only for default configs
+    if [ "${IP_FAMILY}" != "ipv4" ]; then
+      grep "ipFamily: ${IP_FAMILY}" "${CONFIG}" || \
+      cat <<EOF >> "${CONFIG}"
+networking:
+  ipFamily: ${IP_FAMILY}
+EOF
+    fi
+  fi
+
+  # Create KinD cluster
+  if ! (kind create cluster --name="${NAME}" --config "${CONFIG}" -v4 --retain 
--image "${IMAGE}" --wait=180s); then
+    echo "Could not setup KinD environment. Something wrong with KinD setup. 
Exporting logs."
+    return 9
+  fi
+  # Workaround kind issue causing taints to not be removed in 1.24
+  kubectl taint nodes "${NAME}"-control-plane 
node-role.kubernetes.io/control-plane- || true
+
+  # If metrics server configuration directory is specified then deploy in
+  # the cluster just created
+  if [[ -n ${METRICS_SERVER_CONFIG_DIR} ]]; then
+    retry kubectl apply -f "${METRICS_SERVER_CONFIG_DIR}"
+  fi
+
+  # Install Metallb if not set to install explicitly
+  if [[ -z "${NOMETALBINSTALL}" ]]; then
+    retry install_metallb ""
+  fi
+
+  # IPv6 clusters need some CoreDNS changes in order to work in CI:
+  # Istio CI doesn't offer IPv6 connectivity, so CoreDNS should be configured
+  # to work in an offline environment:
+  # https://github.com/coredns/coredns/issues/2494#issuecomment-457215452
+  # CoreDNS should handle those domains and answer with NXDOMAIN instead of 
SERVFAIL
+  # otherwise pods stops trying to resolve the domain.
+  if [ "${IP_FAMILY}" = "ipv6" ] || [ "${IP_FAMILY}" = "dual" ]; then
+    # Get the current config
+    original_coredns=$(kubectl get -oyaml -n=kube-system configmap/coredns)
+    echo "Original CoreDNS config:"
+    echo "${original_coredns}"
+    # Patch it
+    fixed_coredns=$(
+      printf '%s' "${original_coredns}" | sed \
+        -e 's/^.*kubernetes cluster\.local/& internal/' \
+        -e '/^.*upstream$/d' \
+        -e '/^.*fallthrough.*$/d' \
+        -e '/^.*forward . \/etc\/resolv.conf$/d' \
+        -e '/^.*loop$/d' \
+    )
+    echo "Patched CoreDNS config:"
+    echo "${fixed_coredns}"
+    printf '%s' "${fixed_coredns}" | kubectl apply -f -
+  fi
+
+  # On Ubuntu Jammy, the trap runs when this function exits. Remove trap to 
prevent
+  # cluster shutdown here.
+  trap EXIT
+}
+
+###############################################################################
+####################    MULTICLUSTER SECTION    ###############################
+###############################################################################
+
+# Cleans up the clusters created by setup_kind_clusters
+# It expects CLUSTER_NAMES to be present which means that
+# load_cluster_topology must be called before invoking it
+function cleanup_kind_clusters() {
+  echo "Test exited with exit code $?."
+  for c in "${CLUSTER_NAMES[@]}"; do
+    cleanup_kind_cluster "${c}"
+  done
+}
+
+# setup_kind_clusters sets up a given number of kind clusters with given 
topology
+# as specified in cluster topology configuration file.
+# 1. IMAGE = docker image used as node by KinD
+# 2. IP_FAMILY = either ipv4 or ipv6
+#
+# NOTE: Please call load_cluster_topology before calling this method as it 
expects
+# cluster topology information to be loaded in advance
+function setup_kind_clusters() {
+  IMAGE="${1:-"${DEFAULT_KIND_IMAGE}"}"
+  KUBECONFIG_DIR="${ARTIFACTS:-$(mktemp -d)}/kubeconfig"
+  IP_FAMILY="${2:-ipv4}"
+
+  check_default_cluster_yaml
+
+  # Trap replaces any previous trap's, so we need to explicitly cleanup 
clusters here
+  trap cleanup_kind_clusters EXIT
+
+  function deploy_kind() {
+    IDX="${1}"
+    CLUSTER_NAME="${CLUSTER_NAMES[$IDX]}"
+    CLUSTER_POD_SUBNET="${CLUSTER_POD_SUBNETS[$IDX]}"
+    CLUSTER_SVC_SUBNET="${CLUSTER_SVC_SUBNETS[$IDX]}"
+    CLUSTER_YAML="${ARTIFACTS}/config-${CLUSTER_NAME}.yaml"
+    if [ ! -f "${CLUSTER_YAML}" ]; then
+      cp "${DEFAULT_CLUSTER_YAML}" "${CLUSTER_YAML}"
+      cat <<EOF >> "${CLUSTER_YAML}"
+networking:
+  podSubnet: ${CLUSTER_POD_SUBNET}
+  serviceSubnet: ${CLUSTER_SVC_SUBNET}
+EOF
+    fi
+
+    CLUSTER_KUBECONFIG="${KUBECONFIG_DIR}/${CLUSTER_NAME}"
+
+    # Create the clusters.
+    KUBECONFIG="${CLUSTER_KUBECONFIG}" setup_kind_cluster "${CLUSTER_NAME}" 
"${IMAGE}" "${CLUSTER_YAML}" "true"
+
+    # Kind currently supports getting a kubeconfig for internal or external 
usage. To simplify our tests,
+    # its much simpler if we have a single kubeconfig that can be used 
internally and externally.
+    # To do this, we can replace the server with the IP address of the docker 
container
+    # https://github.com/kubernetes-sigs/kind/issues/1558 tracks this upstream
+    CONTAINER_IP=$(docker inspect "${CLUSTER_NAME}-control-plane" --format "{{ 
.NetworkSettings.Networks.kind.IPAddress }}")
+    n=0
+    until [ $n -ge 10 ]; do
+      n=$((n+1))
+      kind get kubeconfig --name "${CLUSTER_NAME}" --internal | \
+        sed "s/${CLUSTER_NAME}-control-plane/${CONTAINER_IP}/g" > 
"${CLUSTER_KUBECONFIG}"
+      [ -s "${CLUSTER_KUBECONFIG}" ] && break
+      sleep 3
+    done
+
+    # Enable core dumps
+    retry docker exec "${CLUSTER_NAME}"-control-plane bash -c "sysctl -w 
kernel.core_pattern=/var/lib/istio/data/core.proxy && ulimit -c unlimited"
+  }
+
+  # Now deploy the specified number of KinD clusters and
+  # wait till they are provisioned successfully.
+  declare -a DEPLOY_KIND_JOBS
+  for i in "${!CLUSTER_NAMES[@]}"; do
+    deploy_kind "${i}" & DEPLOY_KIND_JOBS+=("${!}")
+  done
+
+  for pid in "${DEPLOY_KIND_JOBS[@]}"; do
+    wait "${pid}" || exit 1
+  done
+
+  # Install MetalLB for LoadBalancer support. Must be done synchronously since 
METALLB_IPS is shared.
+  # and keep track of the list of Kubeconfig files that will be exported later
+  export KUBECONFIGS
+  for CLUSTER_NAME in "${CLUSTER_NAMES[@]}"; do
+    KUBECONFIG_FILE="${KUBECONFIG_DIR}/${CLUSTER_NAME}"
+    if [[ ${NUM_CLUSTERS} -gt 1 ]]; then
+      retry install_metallb "${KUBECONFIG_FILE}"
+    fi
+    KUBECONFIGS+=("${KUBECONFIG_FILE}")
+  done
+
+  ITER_END=$((NUM_CLUSTERS-1))
+  for i in $(seq 0 "$ITER_END"); do
+    for j in $(seq 0 "$ITER_END"); do
+      if [[ "${j}" -gt "${i}" ]]; then
+        NETWORK_ID_I="${CLUSTER_NETWORK_ID[i]}"
+        NETWORK_ID_J="${CLUSTER_NETWORK_ID[j]}"
+        if [[ "$NETWORK_ID_I" == "$NETWORK_ID_J" ]]; then
+          POD_TO_POD_AND_SERVICE_CONNECTIVITY=1
+        else
+          POD_TO_POD_AND_SERVICE_CONNECTIVITY=0
+        fi
+        connect_kind_clusters \
+          "${CLUSTER_NAMES[i]}" "${KUBECONFIGS[i]}" \
+          "${CLUSTER_NAMES[j]}" "${KUBECONFIGS[j]}" \
+          "${POD_TO_POD_AND_SERVICE_CONNECTIVITY}"
+      fi
+    done
+  done
+}
+
+function connect_kind_clusters() {
+  C1="${1}"
+  C1_KUBECONFIG="${2}"
+  C2="${3}"
+  C2_KUBECONFIG="${4}"
+  POD_TO_POD_AND_SERVICE_CONNECTIVITY="${5}"
+
+  C1_NODE="${C1}-control-plane"
+  C2_NODE="${C2}-control-plane"
+  C1_DOCKER_IP=$(docker inspect -f "{{ 
.NetworkSettings.Networks.kind.IPAddress }}" "${C1_NODE}")
+  C2_DOCKER_IP=$(docker inspect -f "{{ 
.NetworkSettings.Networks.kind.IPAddress }}" "${C2_NODE}")
+  if [ "${POD_TO_POD_AND_SERVICE_CONNECTIVITY}" -eq 1 ]; then
+    # Set up routing rules for inter-cluster direct pod to pod & service 
communication
+    C1_POD_CIDR=$(KUBECONFIG="${C1_KUBECONFIG}" kubectl get node 
-ojsonpath='{.items[0].spec.podCIDR}')
+    C2_POD_CIDR=$(KUBECONFIG="${C2_KUBECONFIG}" kubectl get node 
-ojsonpath='{.items[0].spec.podCIDR}')
+    C1_SVC_CIDR=$(KUBECONFIG="${C1_KUBECONFIG}" kubectl cluster-info dump | 
sed -n 's/^.*--service-cluster-ip-range=\([^"]*\).*$/\1/p' | head -n 1)
+    C2_SVC_CIDR=$(KUBECONFIG="${C2_KUBECONFIG}" kubectl cluster-info dump | 
sed -n 's/^.*--service-cluster-ip-range=\([^"]*\).*$/\1/p' | head -n 1)
+    docker exec "${C1_NODE}" ip route add "${C2_POD_CIDR}" via 
"${C2_DOCKER_IP}"
+    docker exec "${C1_NODE}" ip route add "${C2_SVC_CIDR}" via 
"${C2_DOCKER_IP}"
+    docker exec "${C2_NODE}" ip route add "${C1_POD_CIDR}" via 
"${C1_DOCKER_IP}"
+    docker exec "${C2_NODE}" ip route add "${C1_SVC_CIDR}" via 
"${C1_DOCKER_IP}"
+  fi
+}
+
+function install_metallb() {
+  KUBECONFIG="${1}"
+  kubectl apply --kubeconfig="$KUBECONFIG" -f "${COMMON_SCRIPTS}/metallb.yaml"
+  kubectl create --kubeconfig="$KUBECONFIG" secret generic -n metallb-system 
memberlist --from-literal=secretkey="$(openssl rand -base64 128)"
+
+  if [ -z "${METALLB_IPS4[*]}" ]; then
+    # Take IPs from the end of the docker kind network subnet to use for 
MetalLB IPs
+    DOCKER_KIND_SUBNET="$(docker inspect kind | jq 
'.[0].IPAM.Config[0].Subnet' -r)"
+    METALLB_IPS4=()
+    while read -r ip; do
+      METALLB_IPS4+=("$ip")
+    done < <(cidr_to_ips "$DOCKER_KIND_SUBNET" | tail -n 100)
+    METALLB_IPS6=()
+    if [[ "$(docker inspect kind | jq '.[0].IPAM.Config | length' -r)" == 2 
]]; then
+      # Two configs? Must be dual stack.
+      DOCKER_KIND_SUBNET="$(docker inspect kind | jq 
'.[0].IPAM.Config[1].Subnet' -r)"
+      while read -r ip; do
+        METALLB_IPS6+=("$ip")
+      done < <(cidr_to_ips "$DOCKER_KIND_SUBNET" | tail -n 100)
+    fi
+  fi
+
+  # Give this cluster of those IPs
+  RANGE="["
+  for i in {0..9}; do
+    RANGE+="${METALLB_IPS4[1]},"
+    METALLB_IPS4=("${METALLB_IPS4[@]:1}")
+    if [[ "${#METALLB_IPS6[@]}" != 0 ]]; then
+      RANGE+="${METALLB_IPS6[1]},"
+      METALLB_IPS6=("${METALLB_IPS6[@]:1}")
+    fi
+  done
+  RANGE="${RANGE%?}]"
+
+  echo 'apiVersion: v1
+kind: ConfigMap
+metadata:
+  namespace: metallb-system
+  name: config
+data:
+  config: |
+    address-pools:
+    - name: default
+      protocol: layer2
+      addresses: '"$RANGE" | kubectl apply --kubeconfig="$KUBECONFIG" -f -
+}
+
+function cidr_to_ips() {
+    CIDR="$1"
+    # cidr_to_ips returns a list of single IPs from a CIDR. We skip 1000 
(since they are likely to be allocated
+    # already to other services), then pick the next 100.
+    python3 - <<EOF
+from ipaddress import ip_network;
+from itertools import islice;
+[print(str(ip) + "/" + str(ip.max_prefixlen)) for ip in 
islice(ip_network('$CIDR').hosts(), 1000, 1100)]
+EOF
+}
+
+function ips_to_cidrs() {
+  IP_RANGE_START="$1"
+  IP_RANGE_END="$2"
+  python3 - <<EOF
+from ipaddress import summarize_address_range, IPv4Address
+[ print(n.compressed) for n in 
summarize_address_range(IPv4Address(u'$IP_RANGE_START'), 
IPv4Address(u'$IP_RANGE_END')) ]
+EOF
+}
diff --git a/tools/scripts/lint_copyright_banner.sh 
b/tools/scripts/lint_copyright_banner.sh
new file mode 100755
index 00000000..7ffdada8
--- /dev/null
+++ b/tools/scripts/lint_copyright_banner.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+# WARNING: DO NOT EDIT, THIS FILE IS PROBABLY A COPY
+#
+# The original version of this file is located in the 
https://github.com/istio/common-files repo.
+# If you're looking at this file in a different repo and want to make a 
change, please go to the
+# common-files repo, make the change there and check it in. Then come back to 
this repo and run
+# "make update-common".
+
+# Copyright Istio Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -e
+
+ec=0
+for fn in "$@"; do
+  if ! grep -L -q -e "Apache License, Version 2" "${fn}"; then
+    echo "Missing license: ${fn}"
+    ec=1
+  fi
+
+  if ! grep -L -q -e "Copyright" "${fn}"; then
+    echo "Missing copyright: ${fn}"
+    ec=1
+  fi
+done
+
+exit $ec
diff --git a/tools/scripts/lint_go.sh b/tools/scripts/lint_go.sh
new file mode 100755
index 00000000..df465a98
--- /dev/null
+++ b/tools/scripts/lint_go.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+# WARNING: DO NOT EDIT, THIS FILE IS PROBABLY A COPY
+#
+# The original version of this file is located in the 
https://github.com/istio/common-files repo.
+# If you're looking at this file in a different repo and want to make a 
change, please go to the
+# common-files repo, make the change there and check it in. Then come back to 
this repo and run
+# "make update-common".
+
+# Copyright Istio Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+if [[ "${ARTIFACTS}" != "" ]]; then
+  golangci-lint run -v -c ./common/config/.golangci.yml --out-format 
colored-line-number,junit-xml:"${ARTIFACTS}"/junit-lint.xml
+else
+  golangci-lint run -v -c ./common/config/.golangci.yml
+fi
diff --git a/tools/scripts/metallb.yaml b/tools/scripts/metallb.yaml
new file mode 100644
index 00000000..c1bd60f6
--- /dev/null
+++ b/tools/scripts/metallb.yaml
@@ -0,0 +1,399 @@
+# from https://github.com/metallb/metallb/tree/v0.9.3/manifests namespace.yaml 
and metallb.yaml
+apiVersion: v1
+kind: Namespace
+metadata:
+  name: metallb-system
+  labels:
+    app: metallb
+---
+apiVersion: policy/v1beta1
+kind: PodSecurityPolicy
+metadata:
+  labels:
+    app: metallb
+  name: controller
+  namespace: metallb-system
+spec:
+  allowPrivilegeEscalation: false
+  allowedCapabilities: []
+  allowedHostPaths: []
+  defaultAddCapabilities: []
+  defaultAllowPrivilegeEscalation: false
+  fsGroup:
+    ranges:
+      - max: 65535
+        min: 1
+    rule: MustRunAs
+  hostIPC: false
+  hostNetwork: false
+  hostPID: false
+  privileged: false
+  readOnlyRootFilesystem: true
+  requiredDropCapabilities:
+    - ALL
+  runAsUser:
+    ranges:
+      - max: 65535
+        min: 1
+    rule: MustRunAs
+  seLinux:
+    rule: RunAsAny
+  supplementalGroups:
+    ranges:
+      - max: 65535
+        min: 1
+    rule: MustRunAs
+  volumes:
+    - configMap
+    - secret
+    - emptyDir
+---
+apiVersion: policy/v1beta1
+kind: PodSecurityPolicy
+metadata:
+  labels:
+    app: metallb
+  name: speaker
+  namespace: metallb-system
+spec:
+  allowPrivilegeEscalation: false
+  allowedCapabilities:
+    - NET_ADMIN
+    - NET_RAW
+    - SYS_ADMIN
+  allowedHostPaths: []
+  defaultAddCapabilities: []
+  defaultAllowPrivilegeEscalation: false
+  fsGroup:
+    rule: RunAsAny
+  hostIPC: false
+  hostNetwork: true
+  hostPID: false
+  hostPorts:
+    - max: 7472
+      min: 7472
+  privileged: true
+  readOnlyRootFilesystem: true
+  requiredDropCapabilities:
+    - ALL
+  runAsUser:
+    rule: RunAsAny
+  seLinux:
+    rule: RunAsAny
+  supplementalGroups:
+    rule: RunAsAny
+  volumes:
+    - configMap
+    - secret
+    - emptyDir
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    app: metallb
+  name: controller
+  namespace: metallb-system
+---
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  labels:
+    app: metallb
+  name: speaker
+  namespace: metallb-system
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  labels:
+    app: metallb
+  name: metallb-system:controller
+rules:
+  - apiGroups:
+      - ''
+    resources:
+      - services
+    verbs:
+      - get
+      - list
+      - watch
+      - update
+  - apiGroups:
+      - ''
+    resources:
+      - services/status
+    verbs:
+      - update
+  - apiGroups:
+      - ''
+    resources:
+      - events
+    verbs:
+      - create
+      - patch
+  - apiGroups:
+      - policy
+    resourceNames:
+      - controller
+    resources:
+      - podsecuritypolicies
+    verbs:
+      - use
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  labels:
+    app: metallb
+  name: metallb-system:speaker
+rules:
+  - apiGroups:
+      - ''
+    resources:
+      - services
+      - endpoints
+      - nodes
+    verbs:
+      - get
+      - list
+      - watch
+  - apiGroups:
+      - ''
+    resources:
+      - events
+    verbs:
+      - create
+      - patch
+  - apiGroups:
+      - policy
+    resourceNames:
+      - speaker
+    resources:
+      - podsecuritypolicies
+    verbs:
+      - use
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+  labels:
+    app: metallb
+  name: config-watcher
+  namespace: metallb-system
+rules:
+  - apiGroups:
+      - ''
+    resources:
+      - configmaps
+    verbs:
+      - get
+      - list
+      - watch
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: Role
+metadata:
+  labels:
+    app: metallb
+  name: pod-lister
+  namespace: metallb-system
+rules:
+  - apiGroups:
+      - ''
+    resources:
+      - pods
+    verbs:
+      - list
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  labels:
+    app: metallb
+  name: metallb-system:controller
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: metallb-system:controller
+subjects:
+  - kind: ServiceAccount
+    name: controller
+    namespace: metallb-system
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  labels:
+    app: metallb
+  name: metallb-system:speaker
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: metallb-system:speaker
+subjects:
+  - kind: ServiceAccount
+    name: speaker
+    namespace: metallb-system
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  labels:
+    app: metallb
+  name: config-watcher
+  namespace: metallb-system
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: config-watcher
+subjects:
+  - kind: ServiceAccount
+    name: controller
+  - kind: ServiceAccount
+    name: speaker
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: RoleBinding
+metadata:
+  labels:
+    app: metallb
+  name: pod-lister
+  namespace: metallb-system
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: pod-lister
+subjects:
+  - kind: ServiceAccount
+    name: speaker
+---
+apiVersion: apps/v1
+kind: DaemonSet
+metadata:
+  labels:
+    app: metallb
+    component: speaker
+  name: speaker
+  namespace: metallb-system
+spec:
+  selector:
+    matchLabels:
+      app: metallb
+      component: speaker
+  template:
+    metadata:
+      annotations:
+        prometheus.io/port: '7472'
+        prometheus.io/scrape: 'true'
+      labels:
+        app: metallb
+        component: speaker
+    spec:
+      containers:
+        - args:
+            - --port=7472
+            - --config=config
+          env:
+            - name: METALLB_NODE_NAME
+              valueFrom:
+                fieldRef:
+                  fieldPath: spec.nodeName
+            - name: METALLB_HOST
+              valueFrom:
+                fieldRef:
+                  fieldPath: status.hostIP
+            - name: METALLB_ML_BIND_ADDR
+              valueFrom:
+                fieldRef:
+                  fieldPath: status.podIP
+            - name: METALLB_ML_LABELS
+              value: "app=metallb,component=speaker"
+            - name: METALLB_ML_NAMESPACE
+              valueFrom:
+                fieldRef:
+                  fieldPath: metadata.namespace
+            - name: METALLB_ML_SECRET_KEY
+              valueFrom:
+                secretKeyRef:
+                  name: memberlist
+                  key: secretkey
+          image: metallb/speaker:v0.9.3
+          imagePullPolicy: Always
+          name: speaker
+          ports:
+            - containerPort: 7472
+              name: monitoring
+          resources:
+            limits:
+              cpu: 100m
+              memory: 100Mi
+          securityContext:
+            allowPrivilegeEscalation: false
+            capabilities:
+              add:
+                - NET_ADMIN
+                - NET_RAW
+                - SYS_ADMIN
+              drop:
+                - ALL
+            readOnlyRootFilesystem: true
+      hostNetwork: true
+      nodeSelector:
+        beta.kubernetes.io/os: linux
+      serviceAccountName: speaker
+      terminationGracePeriodSeconds: 2
+      tolerations:
+        - effect: NoSchedule
+          key: node-role.kubernetes.io/master
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  labels:
+    app: metallb
+    component: controller
+  name: controller
+  namespace: metallb-system
+spec:
+  revisionHistoryLimit: 3
+  selector:
+    matchLabels:
+      app: metallb
+      component: controller
+  template:
+    metadata:
+      annotations:
+        prometheus.io/port: '7472'
+        prometheus.io/scrape: 'true'
+      labels:
+        app: metallb
+        component: controller
+    spec:
+      containers:
+        - args:
+            - --port=7472
+            - --config=config
+          image: metallb/controller:v0.9.3
+          imagePullPolicy: Always
+          name: controller
+          ports:
+            - containerPort: 7472
+              name: monitoring
+          resources:
+            limits:
+              cpu: 100m
+              memory: 100Mi
+          securityContext:
+            allowPrivilegeEscalation: false
+            capabilities:
+              drop:
+                - all
+            readOnlyRootFilesystem: true
+      nodeSelector:
+        beta.kubernetes.io/os: linux
+      securityContext:
+        runAsNonRoot: true
+        runAsUser: 65534
+      serviceAccountName: controller
+      terminationGracePeriodSeconds: 0
\ No newline at end of file
diff --git a/tools/scripts/report_build_info.sh 
b/tools/scripts/report_build_info.sh
new file mode 100755
index 00000000..313c6e55
--- /dev/null
+++ b/tools/scripts/report_build_info.sh
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+# WARNING: DO NOT EDIT, THIS FILE IS PROBABLY A COPY
+#
+# The original version of this file is located in the 
https://github.com/istio/common-files repo.
+# If you're looking at this file in a different repo and want to make a 
change, please go to the
+# common-files repo, make the change there and check it in. Then come back to 
this repo and run
+# "make update-common".
+
+# Copyright Istio Authors
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+
+if BUILD_GIT_REVISION=$(git rev-parse HEAD 2> /dev/null); then
+  if [[ -z "${IGNORE_DIRTY_TREE}" ]] && [[ -n "$(git status --porcelain 
2>/dev/null)" ]]; then
+    BUILD_GIT_REVISION=${BUILD_GIT_REVISION}"-dirty"
+  fi
+else
+  BUILD_GIT_REVISION=unknown
+fi
+
+# Check for local changes
+tree_status="Clean"
+if [[ -z "${IGNORE_DIRTY_TREE}" ]] && ! git diff-index --quiet HEAD --; then
+  tree_status="Modified"
+fi
+
+GIT_DESCRIBE_TAG=$(git describe --tags)
+HUB=${HUB:-"docker.io/istio"}
+
+
+# used by common/scripts/gobuild.sh
+echo "istio.io/pkg/version.buildVersion=${VERSION:-$BUILD_GIT_REVISION}"
+echo "istio.io/pkg/version.buildGitRevision=${BUILD_GIT_REVISION}"
+echo "istio.io/pkg/version.buildStatus=${tree_status}"
+echo "istio.io/pkg/version.buildTag=${GIT_DESCRIBE_TAG}"
+echo "istio.io/pkg/version.buildHub=${HUB}"
diff --git a/tools/scripts/run.sh b/tools/scripts/run.sh
new file mode 100755
index 00000000..0101d1a0
--- /dev/null
+++ b/tools/scripts/run.sh
@@ -0,0 +1,78 @@
+#!/bin/bash
+
+# WARNING: DO NOT EDIT, THIS FILE IS PROBABLY A COPY
+#
+# The original version of this file is located in the 
https://github.com/istio/common-files repo.
+# If you're looking at this file in a different repo and want to make a 
change, please go to the
+# common-files repo, make the change there and check it in. Then come back to 
this repo and run
+# "make update-common".
+
+# Copyright Istio Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -e
+
+WD=$(dirname "$0")
+WD=$(cd "$WD"; pwd)
+
+export FOR_BUILD_CONTAINER=1
+# shellcheck disable=SC1090,SC1091
+source "${WD}/setup_env.sh"
+
+
+MOUNT_SOURCE="${MOUNT_SOURCE:-${PWD}}"
+MOUNT_DEST="${MOUNT_DEST:-/work}"
+
+read -ra DOCKER_RUN_OPTIONS <<< "${DOCKER_RUN_OPTIONS:-}"
+
+[[ -t 1 ]] && DOCKER_RUN_OPTIONS+=("-i")
+
+# $CONTAINER_OPTIONS becomes an empty arg when quoted, so SC2086 is disabled 
for the
+# following command only
+# shellcheck disable=SC2086
+echo "${CONTAINER_CLI}" run \
+    --rm \
+    "${DOCKER_RUN_OPTIONS[@]}" \
+    -u "${UID}:${DOCKER_GID}" \
+    --init \
+    --sig-proxy=true \
+    ${DOCKER_SOCKET_MOUNT:--v /var/run/docker.sock:/var/run/docker.sock} \
+    $CONTAINER_OPTIONS \
+    --env-file <(env | grep -v ${ENV_BLOCKLIST}) \
+    -e IN_BUILD_CONTAINER=1 \
+    -e TZ="${TIMEZONE:-$TZ}" \
+    --mount "type=bind,source=${MOUNT_SOURCE},destination=/work" \
+    --mount "type=volume,source=go,destination=/go" \
+    --mount "type=volume,source=gocache,destination=/gocache" \
+    --mount "type=volume,source=cache,destination=/home/.cache" \
+    ${CONDITIONAL_HOST_MOUNTS} \
+    -w "${MOUNT_DEST}" "${IMG}" "$@"
+
+"${CONTAINER_CLI}" run \
+    --rm \
+    "${DOCKER_RUN_OPTIONS[@]}" \
+    -u "${UID}:${DOCKER_GID}" \
+    --init \
+    --sig-proxy=true \
+    ${DOCKER_SOCKET_MOUNT:--v /var/run/docker.sock:/var/run/docker.sock} \
+    $CONTAINER_OPTIONS \
+    --env-file <(env | grep -v ${ENV_BLOCKLIST}) \
+    -e IN_BUILD_CONTAINER=1 \
+    -e TZ="${TIMEZONE:-$TZ}" \
+    --mount "type=bind,source=${MOUNT_SOURCE},destination=/work" \
+    --mount "type=volume,source=go,destination=/go" \
+    --mount "type=volume,source=gocache,destination=/gocache" \
+    --mount "type=volume,source=cache,destination=/home/.cache" \
+    ${CONDITIONAL_HOST_MOUNTS} \
+    -w "${MOUNT_DEST}" "${IMG}" "$@"
diff --git a/tools/scripts/setup_env.sh b/tools/scripts/setup_env.sh
new file mode 100755
index 00000000..a1ae3e1f
--- /dev/null
+++ b/tools/scripts/setup_env.sh
@@ -0,0 +1,234 @@
+#!/bin/bash
+# shellcheck disable=SC2034
+
+# WARNING: DO NOT EDIT, THIS FILE IS PROBABLY A COPY
+#
+# The original version of this file is located in the 
https://github.com/istio/common-files repo.
+# If you're looking at this file in a different repo and want to make a 
change, please go to the
+# common-files repo, make the change there and check it in. Then come back to 
this repo and run
+# "make update-common".
+
+# Copyright Istio Authors
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set -e
+
+# 
https://stackoverflow.com/questions/59895/how-can-i-get-the-source-directory-of-a-bash-script-from-within-the-script-itsel
+# Note: the normal way we use in other scripts in Istio do not work when 
`source`d, which is why we use this approach
+SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
+REPO_ROOT="$(dirname "$(dirname "${SCRIPT_DIR}")")"
+
+LOCAL_ARCH=$(uname -m)
+
+# Pass environment set target architecture to build system
+if [[ ${TARGET_ARCH} ]]; then
+    # Target explicitly set
+    :
+elif [[ ${LOCAL_ARCH} == x86_64 ]]; then
+    TARGET_ARCH=amd64
+elif [[ ${LOCAL_ARCH} == armv8* ]]; then
+    TARGET_ARCH=arm64
+elif [[ ${LOCAL_ARCH} == arm64* ]]; then
+    TARGET_ARCH=arm64
+elif [[ ${LOCAL_ARCH} == aarch64* ]]; then
+    TARGET_ARCH=arm64
+elif [[ ${LOCAL_ARCH} == armv* ]]; then
+    TARGET_ARCH=arm
+elif [[ ${LOCAL_ARCH} == s390x ]]; then
+    TARGET_ARCH=s390x
+elif [[ ${LOCAL_ARCH} == ppc64le ]]; then
+    TARGET_ARCH=ppc64le
+else
+    echo "This system's architecture, ${LOCAL_ARCH}, isn't supported"
+    exit 1
+fi
+
+LOCAL_OS=$(uname)
+
+# Pass environment set target operating-system to build system
+if [[ ${TARGET_OS} ]]; then
+    # Target explicitly set
+    :
+elif [[ $LOCAL_OS == Linux ]]; then
+    TARGET_OS=linux
+    readlink_flags="-f"
+elif [[ $LOCAL_OS == Darwin ]]; then
+    TARGET_OS=darwin
+    readlink_flags=""
+else
+    echo "This system's OS, $LOCAL_OS, isn't supported"
+    exit 1
+fi
+
+# Build image to use
+if [[ "${IMAGE_VERSION:-}" == "" ]]; then
+  IMAGE_VERSION=latest
+fi
+if [[ "${IMAGE_NAME:-}" == "" ]]; then
+  IMAGE_NAME=golang
+fi
+
+DOCKER_GID="${DOCKER_GID:-$(grep '^docker:' /etc/group | cut -f3 -d:)}"
+
+TIMEZONE=$(readlink "$readlink_flags" /etc/localtime | sed -e 
's/^.*zoneinfo\///')
+
+TARGET_OUT="${TARGET_OUT:-$(pwd)/out/${TARGET_OS}_${TARGET_ARCH}}"
+TARGET_OUT_LINUX="${TARGET_OUT_LINUX:-$(pwd)/out/linux_${TARGET_ARCH}}"
+
+CONTAINER_TARGET_OUT="${CONTAINER_TARGET_OUT:-/work/out/${TARGET_OS}_${TARGET_ARCH}}"
+CONTAINER_TARGET_OUT_LINUX="${CONTAINER_TARGET_OUT_LINUX:-/work/out/linux_${TARGET_ARCH}}"
+
+IMG="${IMG:-docker.io/${IMAGE_NAME}:${IMAGE_VERSION}}"
+
+CONTAINER_CLI="${CONTAINER_CLI:-docker}"
+
+ENV_BLOCKLIST="${ENV_BLOCKLIST:-^_\|^PATH=\|^GOPATH=\|^GOROOT=\|^SHELL=\|^EDITOR=\|^TMUX=\|^USER=\|^HOME=\|^PWD=\|^TERM=\|^rvm=\|^SSH=\|^TMPDIR=\|^CC=\|^CXX=\|^MAKEFILE_LIST=}"
+
+# Remove functions from the list of exported variables, they mess up with the 
`env` command.
+for f in $(declare -F -x | cut -d ' ' -f 3);
+do
+  unset -f "${f}"
+done
+
+# Set conditional host mounts
+CONDITIONAL_HOST_MOUNTS="${CONDITIONAL_HOST_MOUNTS:-} "
+container_kubeconfig=''
+
+# docker conditional host mount (needed for make docker push)
+if [[ -d "${HOME}/.docker" ]]; then
+  CONDITIONAL_HOST_MOUNTS+="--mount 
type=bind,source=${HOME}/.docker,destination=/config/.docker,readonly "
+fi
+
+# gcloud conditional host mount (needed for docker push with the gcloud auth 
configure-docker)
+if [[ -d "${HOME}/.config/gcloud" ]]; then
+  CONDITIONAL_HOST_MOUNTS+="--mount 
type=bind,source=${HOME}/.config/gcloud,destination=/config/.config/gcloud,readonly
 "
+fi
+
+# gitconfig conditional host mount (needed for git commands inside container)
+if [[ -f "${HOME}/.gitconfig" ]]; then
+  CONDITIONAL_HOST_MOUNTS+="--mount 
type=bind,source=${HOME}/.gitconfig,destination=/home/.gitconfig,readonly "
+fi
+
+# .netrc conditional host mount (needed for git commands inside container)
+if [[ -f "${HOME}/.netrc" ]]; then
+  CONDITIONAL_HOST_MOUNTS+="--mount 
type=bind,source=${HOME}/.netrc,destination=/home/.netrc,readonly "
+fi
+
+# echo ${CONDITIONAL_HOST_MOUNTS}
+
+# This function checks if the file exists. If it does, it creates a randomly 
named host location
+# for the file, adds it to the host KUBECONFIG, and creates a mount for it.
+add_KUBECONFIG_if_exists () {
+  if [[ -f "$1" ]]; then
+    kubeconfig_random="$(od -vAn -N4 -tx /dev/random | tr -d '[:space:]' | cut 
-c1-8)"
+    container_kubeconfig+="/config/${kubeconfig_random}:"
+    CONDITIONAL_HOST_MOUNTS+="--mount 
type=bind,source=${1},destination=/config/${kubeconfig_random},readonly "
+  fi
+}
+
+# This function is designed for maximum compatibility with various platforms. 
This runs on
+# any Mac or Linux platform with bash 4.2+. Please take care not to modify 
this function
+# without testing properly.
+#
+# This function will properly handle any type of path including those with 
spaces using the
+# loading pattern specified by *kubectl config*.
+#
+# testcase: "a:b c:d"
+# testcase: "a b:c d:e f"
+# testcase: "a b:c:d e"
+parse_KUBECONFIG () {
+TMPDIR=""
+if [[ "$1" =~ ([^:]*):(.*) ]]; then
+  while true; do
+    rematch=${BASH_REMATCH[1]}
+    add_KUBECONFIG_if_exists "$rematch"
+    remainder="${BASH_REMATCH[2]}"
+    if [[ ! "$remainder" =~ ([^:]*):(.*) ]]; then
+      if [[ -n "$remainder" ]]; then
+        add_KUBECONFIG_if_exists "$remainder"
+        break
+      fi
+    fi
+  done
+else
+  add_KUBECONFIG_if_exists "$1"
+fi
+}
+
+KUBECONFIG=${KUBECONFIG:="$HOME/.kube/config"}
+parse_KUBECONFIG "${KUBECONFIG}"
+if [[ "${FOR_BUILD_CONTAINER:-0}" -eq "1" ]]; then
+  KUBECONFIG="${container_kubeconfig%?}"
+fi
+
+# LOCAL_OUT should point to architecture where we are currently running versus 
the desired.
+# This is used when we need to run a build artifact during tests or later as 
part of another
+# target.
+if [[ "${FOR_BUILD_CONTAINER:-0}" -eq "1" ]]; then
+  LOCAL_OUT="${TARGET_OUT_LINUX}"
+else
+  LOCAL_OUT="${TARGET_OUT}"
+fi
+
+if [[ "${FOR_BUILD_CONTAINER:-0}" -eq "1" ]]; then
+  # Override variables with container specific
+  TARGET_OUT=${CONTAINER_TARGET_OUT}
+  TARGET_OUT_LINUX=${CONTAINER_TARGET_OUT_LINUX}
+  REPO_ROOT=/work
+fi
+
+go_os_arch=${LOCAL_OUT##*/}
+# Golang OS/Arch format
+LOCAL_GO_OS=${go_os_arch%_*}
+LOCAL_GO_ARCH=${go_os_arch##*_}
+
+BUILD_WITH_CONTAINER=0
+
+VARS=(
+      CONTAINER_TARGET_OUT
+      CONTAINER_TARGET_OUT_LINUX
+      TARGET_OUT
+      TARGET_OUT_LINUX
+      LOCAL_GO_OS
+      LOCAL_GO_ARCH
+      LOCAL_OUT
+      LOCAL_OS
+      TARGET_OS
+      LOCAL_ARCH
+      TARGET_ARCH
+      TIMEZONE
+      KUBECONFIG
+      CONDITIONAL_HOST_MOUNTS
+      ENV_BLOCKLIST
+      CONTAINER_CLI
+      DOCKER_GID
+      IMG
+      IMAGE_NAME
+      IMAGE_VERSION
+      REPO_ROOT
+      BUILD_WITH_CONTAINER
+)
+
+# For non container build, we need to write env to file
+if [[ "${1}" == "envfile" ]]; then
+  # ! does a variable-variable https://stackoverflow.com/a/10757531/374797
+  for var in "${VARS[@]}"; do
+    echo "${var}"="${!var}"
+  done
+else
+  for var in "${VARS[@]}"; do
+    # shellcheck disable=SC2163
+    export "${var}"
+  done
+fi

Reply via email to