From 0df45437203cd4c046f3d53ff96a327a074a0bf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Tue, 7 Jan 2020 20:20:38 +0100 Subject: [PATCH 01/50] Change scripts to enable upgrade tests --- test/e2e-common.sh | 47 +++++++++++++++++++++------ test/e2e-tests.sh | 4 ++- test/e2e-upgrade-tests.sh | 67 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 108 insertions(+), 10 deletions(-) create mode 100755 test/e2e-upgrade-tests.sh diff --git a/test/e2e-common.sh b/test/e2e-common.sh index 9cd786837f0..61ff266d64b 100755 --- a/test/e2e-common.sh +++ b/test/e2e-common.sh @@ -19,7 +19,7 @@ source $(dirname $0)/../vendor/knative.dev/test-infra/scripts/e2e-tests.sh # If gcloud is not available make it a no-op, not an error. -which gcloud &> /dev/null || gcloud() { echo "[ignore-gcloud $*]" 1>&2; } +which gcloud &>/dev/null || gcloud() { echo "[ignore-gcloud $*]" 1>&2; } # Use GNU tools on macOS. Requires the 'grep' and 'gnu-sed' Homebrew formulae. if [ "$(uname)" == "Darwin" ]; then @@ -33,18 +33,47 @@ readonly EVENTING_CONFIG="config/" # In-memory channel CRD config. readonly IN_MEMORY_CHANNEL_CRD_CONFIG_DIR="config/channels/in-memory-channel" -# Setup the Knative environment for running tests. -function knative_setup() { - # Install the latest Knative/eventing in the current cluster. - echo ">> Starting Knative Eventing" - echo "Installing Knative Eventing" - ko apply -f ${EVENTING_CONFIG} || return 1 +# Latest release. If user does not supply this as a flag, the latest +# tagged release on the current branch will be used. +readonly LATEST_RELEASE_VERSION=$(git describe --match "v[0-9]*" --abbrev=0) + +# Install Knative Eventing in the current cluster, and waits for it to be ready. +# If no parameters are passed, installs the current source-based build. +# Parameters: $1 - Knative Eventing YAML file +# $2 - Knative Monitoring YAML file (optional) +function install_knative_eventing { + local INSTALL_RELEASE_YAML=$1 + echo ">> Installing Knative Eventing" + if [[ -z "$1" ]]; then + install_head + else + kubectl apply -f "${INSTALL_RELEASE_YAML}" || return $? + fi wait_until_pods_running knative-eventing || fail_test "Knative Eventing did not come up" - echo "Installing Knative Monitoring" + echo ">> Installing Knative Monitoring" start_knative_monitoring "${KNATIVE_MONITORING_RELEASE}" || fail_test "Knative Monitoring did not come up" } +function install_head { + ko apply -f ${EVENTING_CONFIG} || return $? +} + +function install_latest_release { + header "Installing Knative latest public release" + local url="https://github.com/knative/eventing/releases/download/${LATEST_RELEASE_VERSION}" + local yaml="release.yaml" + + install_knative_eventing \ + "${url}/${yaml}" \ + || fail_test "Knative latest release installation failed" + wait_until_pods_running knative-eventing +} + +function knative_setup { + install_knative_eventing +} + # Teardown the Knative environment after tests finish. function knative_teardown() { echo ">> Stopping Knative Eventing" @@ -90,7 +119,7 @@ function dump_extra_cluster_state() { # Collecting logs from all knative's eventing pods. echo "============================================================" local namespace="knative-eventing" - for pod in $(kubectl get pod -n $namespace | grep Running | awk '{print $1}' ); do + for pod in $(kubectl get pod -n $namespace | grep Running | awk '{print $1}'); do for container in $(kubectl get pod "${pod}" -n $namespace -ojsonpath='{.spec.containers[*].name}'); do echo "Namespace, Pod, Container: ${namespace}, ${pod}, ${container}" kubectl logs -n $namespace "${pod}" -c "${container}" || true diff --git a/test/e2e-tests.sh b/test/e2e-tests.sh index 12ba4e8792c..890f1f56326 100755 --- a/test/e2e-tests.sh +++ b/test/e2e-tests.sh @@ -24,10 +24,12 @@ # project $PROJECT_ID, start Knative eventing system, run the tests and # delete the cluster. -source $(dirname $0)/e2e-common.sh +# shellcheck disable=SC1090 +source "$(dirname "$0")/e2e-common.sh" # Script entry point. +# shellcheck disable=SC2068 initialize $@ --skip-istio-addon go_test_e2e -timeout=20m -parallel=12 ./test/e2e ./test/conformance || fail_test diff --git a/test/e2e-upgrade-tests.sh b/test/e2e-upgrade-tests.sh new file mode 100755 index 00000000000..8bf9906cc0f --- /dev/null +++ b/test/e2e-upgrade-tests.sh @@ -0,0 +1,67 @@ +#!/usr/bin/env bash + +# Copyright 2019 The Knative 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. + +# shellcheck disable=SC1090 +source "$(dirname "$0")/e2e-common.sh" + +# Script entry point. + +function knative_setup() { + install_latest_release +} + +# shellcheck disable=SC2068 +initialize $@ --skip-istio-addon + +TIMEOUT=${TIMEOUT:-10m} + +header "Running preupgrade tests" + +go_test_e2e -tags=preupgrade -timeout="${TIMEOUT}" ./test/upgrade \ + --resolvabledomain="$(use_resolvable_domain)" "$(use_https)" || fail_test + +header "Starting prober test" + +# Remove this in case we failed to clean it up in an earlier test. +rm -f /tmp/prober-signal + +go_test_e2e -tags=probe -timeout="${TIMEOUT}" ./test/upgrade \ + --resolvabledomain="$(use_resolvable_domain)" "$(use_https)" & +PROBER_PID=$! +echo "Prober PID is ${PROBER_PID}" + +install_head + +header "Running postupgrade tests" +go_test_e2e -tags=postupgrade -timeout="${TIMEOUT}" ./test/upgrade \ + --resolvabledomain="$(use_resolvable_domain)" "$(use_https)" || fail_test + +install_latest_release + +header "Running postdowngrade tests" +go_test_e2e -tags=postdowngrade -timeout=${TIMEOUT} ./test/upgrade \ + --resolvabledomain=$(use_resolvable_domain) "$(use_https)" || fail_test + +# The prober is blocking on /tmp/prober-signal to know when it should exit. +# +# This is kind of gross. First attempt was to just send a signal to the go test, +# but "go test" intercepts the signal and always exits with a non-zero code. +echo "done" > /tmp/prober-signal + +header "Waiting for prober test" +wait ${PROBER_PID} || fail_test "Prober failed" + +success From 485e83917a3bc80e8f8cc9d094f97a356eca72de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Fri, 10 Jan 2020 18:14:01 +0100 Subject: [PATCH 02/50] Upgrade tests overall structure --- hack/update-deps.sh | 15 ++--- test/e2e-common.sh | 25 ++++++++ test/e2e-upgrade-tests.sh | 16 +++-- test/prober.go | 97 ++++++++++++++++++++++++++++++ test/upgrade/README.md | 53 ++++++++++++++++ test/upgrade/main_test.go | 36 +++++++++++ test/upgrade/postdowngrade_test.go | 26 ++++++++ test/upgrade/postupgrade_test.go | 26 ++++++++ test/upgrade/preupgrade_test.go | 26 ++++++++ test/upgrade/probe_test.go | 79 ++++++++++++++++++++++++ test/upgrade/smoke_test.go | 30 +++++++++ 11 files changed, 413 insertions(+), 16 deletions(-) create mode 100644 test/prober.go create mode 100644 test/upgrade/README.md create mode 100644 test/upgrade/main_test.go create mode 100644 test/upgrade/postdowngrade_test.go create mode 100644 test/upgrade/postupgrade_test.go create mode 100644 test/upgrade/preupgrade_test.go create mode 100644 test/upgrade/probe_test.go create mode 100644 test/upgrade/smoke_test.go diff --git a/hack/update-deps.sh b/hack/update-deps.sh index 8f986fd429c..d5c93e64fdd 100755 --- a/hack/update-deps.sh +++ b/hack/update-deps.sh @@ -14,22 +14,23 @@ # See the License for the specific language governing permissions and # limitations under the License. -readonly ROOT_DIR=$(dirname $0)/.. -source ${ROOT_DIR}/vendor/knative.dev/test-infra/scripts/library.sh +readonly ROOT_DIR=$(dirname "$0")/.. +# shellcheck disable=SC1090 +source "${ROOT_DIR}/vendor/knative.dev/test-infra/scripts/library.sh" set -o errexit set -o nounset set -o pipefail -cd ${ROOT_DIR} +cd "${ROOT_DIR}" # Ensure we have everything we need under vendor/ dep ensure -rm -rf $(find vendor/ -name 'OWNERS') -rm -rf $(find vendor/ -name 'OWNERS_ALIASES') -rm -rf $(find vendor/ -name 'BUILD') -rm -rf $(find vendor/ -name 'BUILD.bazel') +find vendor/ -name 'OWNERS' -delete +find vendor/ -name 'OWNERS_ALIASES' -delete +find vendor/ -name 'BUILD' -delete +find vendor/ -name 'BUILD.bazel' -delete update_licenses third_party/VENDOR-LICENSE \ $(find . -name "*.go" | grep -v vendor | xargs grep "package main" | cut -d: -f1 | xargs -n1 dirname | uniq) diff --git a/test/e2e-common.sh b/test/e2e-common.sh index 61ff266d64b..3f19c7a06df 100755 --- a/test/e2e-common.sh +++ b/test/e2e-common.sh @@ -130,3 +130,28 @@ function dump_extra_cluster_state() { done done } + +function wait_for_file { + local file timeout + file="$1" + timeout=300 + + echo "Waiting for existance of file: ${file}" + + while [ ! -f "${file}" ]; do + # When the timeout is equal to zero, show an error and leave the loop. + if [ "${timeout}" == 0 ]; then + echo '' + echo "ERROR: Timeout while waiting for the file ${file}." + return 1 + fi + + sleep 1 + echo -n '.' + + # Decrease the timeout of one + ((timeout--)) + done + echo '' + return 0 +} \ No newline at end of file diff --git a/test/e2e-upgrade-tests.sh b/test/e2e-upgrade-tests.sh index 8bf9906cc0f..7717f4a89c3 100755 --- a/test/e2e-upgrade-tests.sh +++ b/test/e2e-upgrade-tests.sh @@ -30,30 +30,28 @@ TIMEOUT=${TIMEOUT:-10m} header "Running preupgrade tests" -go_test_e2e -tags=preupgrade -timeout="${TIMEOUT}" ./test/upgrade \ - --resolvabledomain="$(use_resolvable_domain)" "$(use_https)" || fail_test +go_test_e2e -tags=preupgrade -timeout="${TIMEOUT}" ./test/upgrade || fail_test header "Starting prober test" # Remove this in case we failed to clean it up in an earlier test. -rm -f /tmp/prober-signal +rm -vf /tmp/prober-signal /tmp/prober-ready -go_test_e2e -tags=probe -timeout="${TIMEOUT}" ./test/upgrade \ - --resolvabledomain="$(use_resolvable_domain)" "$(use_https)" & +go_test_e2e -tags=probe -timeout="${TIMEOUT}" ./test/upgrade & PROBER_PID=$! echo "Prober PID is ${PROBER_PID}" +wait_for_file /tmp/prober-ready || fail_test + install_head header "Running postupgrade tests" -go_test_e2e -tags=postupgrade -timeout="${TIMEOUT}" ./test/upgrade \ - --resolvabledomain="$(use_resolvable_domain)" "$(use_https)" || fail_test +go_test_e2e -tags=postupgrade -timeout="${TIMEOUT}" ./test/upgrade || fail_test install_latest_release header "Running postdowngrade tests" -go_test_e2e -tags=postdowngrade -timeout=${TIMEOUT} ./test/upgrade \ - --resolvabledomain=$(use_resolvable_domain) "$(use_https)" || fail_test +go_test_e2e -tags=postdowngrade -timeout="${TIMEOUT}" ./test/upgrade || fail_test # The prober is blocking on /tmp/prober-signal to know when it should exit. # diff --git a/test/prober.go b/test/prober.go new file mode 100644 index 00000000000..b15ed6da610 --- /dev/null +++ b/test/prober.go @@ -0,0 +1,97 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package test + +import ( + "knative.dev/eventing/test/common" + "knative.dev/pkg/test/logging" + "testing" + "time" +) + +// Prober is the interface for a prober, which checks the result of the probes when stopped. +type Prober interface { + // Verify will verify prober state after finished has been send + Verify() []error + + // Finish send finished event + Finish() + + // deploy a prober to a cluster + deploy() + // undeploy a prober from cluster + undeploy() +} + +// ProberConfig represents a configuration for prober +type ProberConfig struct { + Namespace string + Interval time.Duration + UseServing bool +} + +// RunEventProber starts a single Prober of the given domain. +func RunEventProber(logf logging.FormatLogger, client *common.Client, config ProberConfig) Prober { + pm := newProber(logf, client, config) + pm.deploy() + return pm +} + +// AssertEventProber will send finish event and then verify if all events propagated well +func AssertEventProber(t *testing.T, prober Prober) { + prober.Finish() + + errors := prober.Verify() + for _, err := range errors { + t.Error(err) + } + if len(errors) == 0 { + t.Log("All events propagated well") + } + + prober.undeploy() +} + +type prober struct { + logf logging.FormatLogger + client *common.Client + config ProberConfig +} + +func (p *prober) Verify() []error { + p.logf("ERR: Verify(): implement me") + return make([]error, 0) +} + +func (p *prober) Finish() { + p.logf("ERR: Finish(): implement me") +} + +func (p *prober) deploy() { + p.logf("ERR: deploy(): implement me") +} + +func (p *prober) undeploy() { + p.logf("ERR: undeploy(): implement me") +} + +func newProber(logf logging.FormatLogger, client *common.Client, config ProberConfig) Prober { + return &prober{ + logf: logf, + client: client, + config: config, + } +} diff --git a/test/upgrade/README.md b/test/upgrade/README.md new file mode 100644 index 00000000000..a902edbd056 --- /dev/null +++ b/test/upgrade/README.md @@ -0,0 +1,53 @@ +# Upgrade Tests + +In order to get coverage for the upgrade process from an operator’s perspective, +we need an additional suite of tests that perform a complete knative upgrade. +Running these tests on every commit will ensure that we don’t introduce any +non-upgradeable changes, so every commit should be releasable. + +This is inspired by kubernetes +[upgrade testing](https://github.com/kubernetes/community/blob/master/contributors/devel/e2e-tests.md#version-skewed-and-upgrade-testing). + +These tests are a pretty big hammer in that they cover more than just version +changes, but it’s one of the only ways to make sure we don’t accidentally make +breaking changes for now. + +## Flow + +We’d like to validate that the upgrade doesn’t break any resources (they still +propagate events) and doesn't break our installation (we can still update +resources). + +At a high level, we want to do this: + +1. Install the latest knative release. +1. Create some resources. +1. Install knative at HEAD. +1. Test those resources, verify that we didn’t break anything. + +To achieve that, we just have three separate build tags: + +1. Install the latest release from GitHub. +1. Run the `preupgrade` tests in this directory. +1. Install at HEAD (`ko apply -f config/`). +1. Run the `postupgrade` tests in this directory. +1. Install the latest release from GitHub. +1. Run the `postdowngrade` tests in this directory. + +## Tests + +### Smoke test + +This was stolen from the e2e tests as one of the simplest cases. + +#### preupgrade, postupgrade, postdowngrade + +Run the selected smoke test. + +### Probe test + +In order to verify that we don't have data-plane unavailability during our +control-plane outages (when we're upgrading the knative/eventing installation), +we run a prober test that continually sends events to a service during the +entire upgrade/downgrade process. When the upgrade completes, we make sure +that all of those events propagated just once. diff --git a/test/upgrade/main_test.go b/test/upgrade/main_test.go new file mode 100644 index 00000000000..daccbb239ab --- /dev/null +++ b/test/upgrade/main_test.go @@ -0,0 +1,36 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package upgrade + +import ( + "knative.dev/eventing/test" + "knative.dev/eventing/test/common" + "os" + "testing" +) + +var setup = common.Setup +var tearDown = common.TearDown +var channelTestRunner common.ChannelTestRunner + +func TestMain(m *testing.M) { + test.InitializeEventingFlags() + channelTestRunner = common.ChannelTestRunner{ + ChannelFeatureMap: common.ChannelFeatureMap, + ChannelsToTest: test.EventingFlags.Channels, + } + os.Exit(m.Run()) +} diff --git a/test/upgrade/postdowngrade_test.go b/test/upgrade/postdowngrade_test.go new file mode 100644 index 00000000000..5a2755202f7 --- /dev/null +++ b/test/upgrade/postdowngrade_test.go @@ -0,0 +1,26 @@ +// +build postdowngrade + +/* + * Copyright 2020 The Knative 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. + */ + +package upgrade + +import ( + "testing" +) + +func TestPostDowngrade(t *testing.T) { + runSmokeTest(t) +} \ No newline at end of file diff --git a/test/upgrade/postupgrade_test.go b/test/upgrade/postupgrade_test.go new file mode 100644 index 00000000000..e439366d552 --- /dev/null +++ b/test/upgrade/postupgrade_test.go @@ -0,0 +1,26 @@ +// +build postupgrade + +/* + * Copyright 2020 The Knative 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. + */ + +package upgrade + +import ( + "testing" +) + +func TestPostUpgrade(t *testing.T) { + runSmokeTest(t) +} \ No newline at end of file diff --git a/test/upgrade/preupgrade_test.go b/test/upgrade/preupgrade_test.go new file mode 100644 index 00000000000..c0555428031 --- /dev/null +++ b/test/upgrade/preupgrade_test.go @@ -0,0 +1,26 @@ +// +build preupgrade + +/* + * Copyright 2020 The Knative 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. + */ + +package upgrade + +import ( + "testing" +) + +func TestPreUpgrade(t *testing.T) { + runSmokeTest(t) +} \ No newline at end of file diff --git a/test/upgrade/probe_test.go b/test/upgrade/probe_test.go new file mode 100644 index 00000000000..175c51e66c9 --- /dev/null +++ b/test/upgrade/probe_test.go @@ -0,0 +1,79 @@ +// +build probe + +/* + * Copyright 2020 The Knative 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. + */ + +package upgrade + +import ( + "github.com/pkg/errors" + "io/ioutil" + "knative.dev/eventing/test" + "log" + "os" + "syscall" + "testing" + "time" +) + +const ( + pipe = "/tmp/prober-signal" + ready = "/tmp/prober-ready" +) + +var ( + // FIXME: Interval is set to 200 msec, as lower values will result in errors + // https://github.com/knative/eventing/issues/2357 + interval = 200 * time.Millisecond + namespace = "event-test" +) + +func TestProbe(t *testing.T) { + // We run the prober as a golang test because it fits in nicely with + // the rest of our integration tests, and AssertProberDefault needs + // a *testing.T. Unfortunately, "go test" intercepts signals, so we + // can't coordinate with the test by just sending e.g. SIGCONT, so we + // create a named pipe and wait for the upgrade script to write to it + // to signal that we should stop probing. + if err := syscall.Mkfifo(pipe, 0666); err != nil { + t.Fatalf("Failed to create pipe: %v", err) + } + defer func() { + noError(os.Remove(pipe)) + noError(os.Remove(ready)) + }() + client := setup(t, false) + defer tearDown(client) + + // Use log.Printf instead of t.Logf because we want to see failures + // inline with other logs instead of buffered until the end. + config := test.ProberConfig{ + Namespace: namespace, + Interval: interval, + } + prober := test.RunEventProber(log.Printf, client, config) + noError(ioutil.WriteFile(ready, []byte("prober ready"), 0666)) + defer test.AssertEventProber(t, prober) + + // e2e-upgrade-test.sh will close this pipe to signal the upgrade is + // over, at which point we will finish the test and check the prober. + _, _ = ioutil.ReadFile(pipe) +} + +func noError(err error) { + if err != nil { + panic(errors.WithMessage(err, "expected to be no error, but that was")) + } +} diff --git a/test/upgrade/smoke_test.go b/test/upgrade/smoke_test.go new file mode 100644 index 00000000000..8aee579cf4d --- /dev/null +++ b/test/upgrade/smoke_test.go @@ -0,0 +1,30 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package upgrade + +import ( + "knative.dev/eventing/test/base/resources" + "knative.dev/eventing/test/e2e/helpers" + "testing" +) + +func runSmokeTest(t *testing.T) { + helpers.SingleEventForChannelTestHelper( + t, + resources.CloudEventEncodingBinary, + channelTestRunner, + ) +} \ No newline at end of file From 816b3cef9df9f5d755cd75577d42b59f44c099bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Fri, 10 Jan 2020 18:36:46 +0100 Subject: [PATCH 03/50] Adding Istio & Serving to upgrade tests --- test/e2e-common.sh | 52 +- test/e2e-upgrade-tests.sh | 3 + test/upgrade/probe_test.go | 7 +- third_party/istio-1.4-latest | 1 + third_party/istio-1.4.3/README.md | 17 + third_party/istio-1.4.3/download-istio.sh | 76 + .../istio-1.4.3/drain-seconds.yaml.patch | 5 + third_party/istio-1.4.3/istio-ci-mesh.yaml | 3534 +++++++++++ third_party/istio-1.4.3/istio-ci-no-mesh.yaml | 1738 ++++++ third_party/istio-1.4.3/istio-crds.yaml | 5255 +++++++++++++++++ .../istio-1.4.3/istio-knative-extras.yaml | 268 + third_party/istio-1.4.3/istio-minimal.yaml | 960 +++ third_party/istio-1.4.3/namespace.yaml.patch | 10 + third_party/istio-1.4.3/values-extras.yaml | 86 + third_party/istio-1.4.3/values-lean.yaml | 96 + third_party/istio-1.4.3/values-local.yaml | 91 + third_party/istio-1.4.3/values.yaml | 85 + third_party/istio-latest | 1 + 18 files changed, 12281 insertions(+), 4 deletions(-) create mode 120000 third_party/istio-1.4-latest create mode 100644 third_party/istio-1.4.3/README.md create mode 100755 third_party/istio-1.4.3/download-istio.sh create mode 100644 third_party/istio-1.4.3/drain-seconds.yaml.patch create mode 100644 third_party/istio-1.4.3/istio-ci-mesh.yaml create mode 100644 third_party/istio-1.4.3/istio-ci-no-mesh.yaml create mode 100644 third_party/istio-1.4.3/istio-crds.yaml create mode 100644 third_party/istio-1.4.3/istio-knative-extras.yaml create mode 100644 third_party/istio-1.4.3/istio-minimal.yaml create mode 100644 third_party/istio-1.4.3/namespace.yaml.patch create mode 100644 third_party/istio-1.4.3/values-extras.yaml create mode 100644 third_party/istio-1.4.3/values-lean.yaml create mode 100644 third_party/istio-1.4.3/values-local.yaml create mode 100644 third_party/istio-1.4.3/values.yaml create mode 120000 third_party/istio-latest diff --git a/test/e2e-common.sh b/test/e2e-common.sh index 3f19c7a06df..4bf4ae29bea 100755 --- a/test/e2e-common.sh +++ b/test/e2e-common.sh @@ -37,6 +37,8 @@ readonly IN_MEMORY_CHANNEL_CRD_CONFIG_DIR="config/channels/in-memory-channel" # tagged release on the current branch will be used. readonly LATEST_RELEASE_VERSION=$(git describe --match "v[0-9]*" --abbrev=0) +UNINSTALL_LIST=() + # Install Knative Eventing in the current cluster, and waits for it to be ready. # If no parameters are passed, installs the current source-based build. # Parameters: $1 - Knative Eventing YAML file @@ -53,10 +55,12 @@ function install_knative_eventing { echo ">> Installing Knative Monitoring" start_knative_monitoring "${KNATIVE_MONITORING_RELEASE}" || fail_test "Knative Monitoring did not come up" + UNINSTALL_LIST+=( "${KNATIVE_MONITORING_RELEASE}" ) } function install_head { ko apply -f ${EVENTING_CONFIG} || return $? + wait_until_pods_running knative-eventing || fail_test "Knative Eventing did not come up" } function install_latest_release { @@ -67,7 +71,7 @@ function install_latest_release { install_knative_eventing \ "${url}/${yaml}" \ || fail_test "Knative latest release installation failed" - wait_until_pods_running knative-eventing + wait_until_pods_running knative-eventing || fail_test "Knative Eventing did not come up" } function knative_setup { @@ -80,6 +84,15 @@ function knative_teardown() { echo "Uninstalling Knative Eventing" ko delete --ignore-not-found=true --now --timeout 60s -f ${EVENTING_CONFIG} wait_until_object_does_not_exist namespaces knative-eventing + + echo ">> Uninstalling dependencies" + # shellcheck disable=SC2068 + for i in ${!UNINSTALL_LIST[@]}; do + # We uninstall elements in the reverse of the order they were installed. + local YAML="${UNINSTALL_LIST[$(( ${#array[@]} - $i ))]}" + echo ">> Bringing down YAML: ${YAML}" + kubectl delete --ignore-not-found=true -f "${YAML}" || return 1 + done } # Setup resources common to all eventing tests. @@ -131,6 +144,43 @@ function dump_extra_cluster_state() { done } +function install_istio { + if [[ -z "${ISTIO_VERSION}" ]]; then + readonly ISTIO_VERSION="latest" + fi + echo ">> Installing Istio: ${ISTIO_VERSION}" + + local istio_base="./third_party/istio-${ISTIO_VERSION}" + INSTALL_ISTIO_CRD_YAML="${istio_base}/istio-crds.yaml" + INSTALL_ISTIO_YAML="${istio_base}/istio-minimal.yaml" + + echo "Istio CRD YAML: ${INSTALL_ISTIO_CRD_YAML}" + echo "Istio YAML: ${INSTALL_ISTIO_YAML}" + + echo ">> Bringing up Istio" + echo ">> Running Istio CRD installer" + kubectl apply -f "${INSTALL_ISTIO_CRD_YAML}" || return 1 + wait_until_batch_job_complete istio-system || return 1 + UNINSTALL_LIST+=( "${INSTALL_ISTIO_CRD_YAML}" ) + + echo ">> Running Istio" + kubectl apply -f "${INSTALL_ISTIO_YAML}" || return 1 + UNINSTALL_LIST+=( "${INSTALL_ISTIO_YAML}" ) +} + +# Installs Knative Serving in the current cluster, and waits for it to be ready. +function install_knative_serving { + install_istio + echo ">> Installing Knative serving" + readonly SERVING_YAML="https://github.com/knative/serving/releases/download/${LATEST_RELEASE_VERSION}/serving.yaml" + + echo "Knative serving YAML: ${SERVING_YAML}" + kubectl apply -f "${SERVING_YAML}" || return 1 + UNINSTALL_LIST+=( "${SERVING_YAML}" ) + + wait_until_pods_running knative-serving || fail_test "Knative Serving did not come up" +} + function wait_for_file { local file timeout file="$1" diff --git a/test/e2e-upgrade-tests.sh b/test/e2e-upgrade-tests.sh index 7717f4a89c3..ec4fc0e6b96 100755 --- a/test/e2e-upgrade-tests.sh +++ b/test/e2e-upgrade-tests.sh @@ -20,6 +20,7 @@ source "$(dirname "$0")/e2e-common.sh" # Script entry point. function knative_setup() { + install_knative_serving install_latest_release } @@ -43,11 +44,13 @@ echo "Prober PID is ${PROBER_PID}" wait_for_file /tmp/prober-ready || fail_test +header "Performing upgrade to HEAD" install_head header "Running postupgrade tests" go_test_e2e -tags=postupgrade -timeout="${TIMEOUT}" ./test/upgrade || fail_test +header "Performing downgrade to latest release" install_latest_release header "Running postdowngrade tests" diff --git a/test/upgrade/probe_test.go b/test/upgrade/probe_test.go index 175c51e66c9..33a70d90760 100644 --- a/test/upgrade/probe_test.go +++ b/test/upgrade/probe_test.go @@ -36,7 +36,7 @@ const ( var ( // FIXME: Interval is set to 200 msec, as lower values will result in errors // https://github.com/knative/eventing/issues/2357 - interval = 200 * time.Millisecond + interval = 200 * time.Millisecond namespace = "event-test" ) @@ -60,8 +60,9 @@ func TestProbe(t *testing.T) { // Use log.Printf instead of t.Logf because we want to see failures // inline with other logs instead of buffered until the end. config := test.ProberConfig{ - Namespace: namespace, - Interval: interval, + Namespace: namespace, + Interval: interval, + UseServing: true, } prober := test.RunEventProber(log.Printf, client, config) noError(ioutil.WriteFile(ready, []byte("prober ready"), 0666)) diff --git a/third_party/istio-1.4-latest b/third_party/istio-1.4-latest new file mode 120000 index 00000000000..735b5e98785 --- /dev/null +++ b/third_party/istio-1.4-latest @@ -0,0 +1 @@ +istio-1.4.3 \ No newline at end of file diff --git a/third_party/istio-1.4.3/README.md b/third_party/istio-1.4.3/README.md new file mode 100644 index 00000000000..cffd8e93a3b --- /dev/null +++ b/third_party/istio-1.4.3/README.md @@ -0,0 +1,17 @@ +The istio\*.yaml files are generated by running + +``` +./download-istio.sh +``` + +using Helm v3.0.1. + +The generated files are: + +- istio-ci-no-mesh.yaml: used in our continuous testing of Knative with Istio + having sidecar disabled. This is also the setting that we use in our presubmit + tests. +- istio-ci-mesh.yaml: used in our continuous testing of Knative with Istio + having sidecar and mTLS enabled. +- istio-minimal.yaml: a minimal Istio installation used for development + purposes. diff --git a/third_party/istio-1.4.3/download-istio.sh b/third_party/istio-1.4.3/download-istio.sh new file mode 100755 index 00000000000..399a80eb688 --- /dev/null +++ b/third_party/istio-1.4.3/download-istio.sh @@ -0,0 +1,76 @@ +#!/usr/bin/env bash + +# Copyright 2019 The Knative 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. + +# Download and unpack Istio +ISTIO_VERSION=1.4.3 +DOWNLOAD_URL=https://github.com/istio/istio/releases/download/${ISTIO_VERSION}/istio-${ISTIO_VERSION}-linux.tar.gz + +wget --no-check-certificate $DOWNLOAD_URL +if [ $? != 0 ]; then + echo "Failed to download istio package" + exit 1 +fi +tar xzf istio-${ISTIO_VERSION}-linux.tar.gz + +( # subshell in downloaded directory +cd istio-${ISTIO_VERSION} || exit + +# Create CRDs template +helm template --namespace=istio-system \ + install/kubernetes/helm/istio-init \ + `# Removing trailing whitespaces to make automation happy` \ + | sed 's/[ \t]*$//' \ + > ../istio-crds.yaml + +# Create a custom cluster local gateway, based on the Istio custom-gateway template. +helm template --namespace=istio-system install/kubernetes/helm/istio --values ../values-extras.yaml \ + `# Removing trailing whitespaces to make automation happy` \ + | sed 's/[ \t]*$//' \ + > ../istio-knative-extras.yaml + +# A template with sidecar injection enabled. +helm template --namespace=istio-system install/kubernetes/helm/istio --values ../values.yaml \ + `# Removing trailing whitespaces to make automation happy` \ + | sed 's/[ \t]*$//' \ + > ../istio-ci-mesh.yaml + +# A lighter template, with just pilot/gateway. +# Based on install/kubernetes/helm/istio/values-istio-minimal.yaml +helm template --namespace=istio-system install/kubernetes/helm/istio --values ../values-lean.yaml \ + `# Removing trailing whitespaces to make automation happy` \ + | sed 's/[ \t]*$//' \ + > ../istio-ci-no-mesh.yaml + +# An even lighter template, with just pilot/gateway and small resource requests. +# Based on install/kubernetes/helm/istio/values-istio-minimal.yaml +helm template --namespace=istio-system install/kubernetes/helm/istio --values ../values-local.yaml \ + `# Removing trailing whitespaces to make automation happy` \ + | sed 's/[ \t]*$//' \ + > ../istio-minimal.yaml +) + +# Clean up. +rm -rf istio-${ISTIO_VERSION} +rm istio-${ISTIO_VERSION}-linux.tar.gz + +# Add in the `istio-system` namespace to reduce number of commands. +patch istio-crds.yaml namespace.yaml.patch +patch istio-ci-mesh.yaml namespace.yaml.patch +patch istio-ci-no-mesh.yaml namespace.yaml.patch +patch istio-minimal.yaml namespace.yaml.patch + +# Increase termination drain duration seconds. +patch -l istio-ci-mesh.yaml drain-seconds.yaml.patch diff --git a/third_party/istio-1.4.3/drain-seconds.yaml.patch b/third_party/istio-1.4.3/drain-seconds.yaml.patch new file mode 100644 index 00000000000..c4316c58c0c --- /dev/null +++ b/third_party/istio-1.4.3/drain-seconds.yaml.patch @@ -0,0 +1,5 @@ +820a821,824 +> # PATCH #2: Increase termination drain duration. +> - name: TERMINATION_DRAIN_DURATION_SECONDS +> value: "20" +> # PATCH #2 ends. diff --git a/third_party/istio-1.4.3/istio-ci-mesh.yaml b/third_party/istio-1.4.3/istio-ci-mesh.yaml new file mode 100644 index 00000000000..f635a6c359c --- /dev/null +++ b/third_party/istio-1.4.3/istio-ci-mesh.yaml @@ -0,0 +1,3534 @@ +--- +# PATCH #1: Creating the istio-system namespace. +apiVersion: v1 +kind: Namespace +metadata: + name: istio-system + labels: + istio-injection: disabled +# PATCH #1 ends. +--- +# Source: istio/charts/galley/templates/poddisruptionbudget.yaml +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: istio-galley + namespace: istio-system + labels: + app: galley + chart: galley + heritage: Helm + release: RELEASE-NAME + istio: galley +spec: + + minAvailable: 1 + selector: + matchLabels: + app: galley + release: RELEASE-NAME + istio: galley +--- +# Source: istio/charts/gateways/templates/poddisruptionbudget.yaml +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: cluster-local-gateway + namespace: istio-system + labels: + chart: gateways + heritage: Helm + release: RELEASE-NAME + app: cluster-local-gateway + istio: cluster-local-gateway +spec: + + minAvailable: 1 + selector: + matchLabels: + release: RELEASE-NAME + app: cluster-local-gateway + istio: cluster-local-gateway +--- +# Source: istio/charts/gateways/templates/poddisruptionbudget.yaml +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: istio-ingressgateway + namespace: istio-system + labels: + chart: gateways + heritage: Helm + release: RELEASE-NAME + app: istio-ingressgateway + istio: ingressgateway +spec: + + minAvailable: 1 + selector: + matchLabels: + release: RELEASE-NAME + app: istio-ingressgateway + istio: ingressgateway +--- +# Source: istio/charts/mixer/templates/poddisruptionbudget.yaml +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: istio-policy + namespace: istio-system + labels: + app: policy + chart: mixer + heritage: Helm + release: RELEASE-NAME + version: 1.4.3 + istio: mixer + istio-mixer-type: policy +spec: + + minAvailable: 1 + selector: + matchLabels: + app: policy + release: RELEASE-NAME + istio: mixer + istio-mixer-type: policy +--- +# Source: istio/charts/mixer/templates/poddisruptionbudget.yaml +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: istio-telemetry + namespace: istio-system + labels: + app: telemetry + chart: mixer + heritage: Helm + release: RELEASE-NAME + version: 1.4.3 + istio: mixer + istio-mixer-type: telemetry +spec: + + minAvailable: 1 + selector: + matchLabels: + app: telemetry + release: RELEASE-NAME + istio: mixer + istio-mixer-type: telemetry +--- +# Source: istio/charts/pilot/templates/poddisruptionbudget.yaml +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: istio-pilot + namespace: istio-system + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME + istio: pilot +spec: + + minAvailable: 1 + selector: + matchLabels: + app: pilot + release: RELEASE-NAME + istio: pilot +--- +# Source: istio/charts/security/templates/poddisruptionbudget.yaml +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: istio-citadel + namespace: istio-system + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME + istio: citadel +spec: + + minAvailable: 1 + selector: + matchLabels: + app: security + release: RELEASE-NAME + istio: citadel +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/poddisruptionbudget.yaml +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: istio-sidecar-injector + namespace: istio-system + labels: + app: sidecarInjectorWebhook + release: RELEASE-NAME + istio: sidecar-injector +spec: + + minAvailable: 1 + selector: + matchLabels: + app: sidecarInjectorWebhook + release: RELEASE-NAME + istio: sidecar-injector +--- +# Source: istio/charts/galley/templates/configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: istio-galley-configuration + namespace: istio-system + labels: + app: galley + chart: galley + heritage: Helm + release: RELEASE-NAME + istio: galley +data: + validatingwebhookconfiguration.yaml: |- + apiVersion: admissionregistration.k8s.io/v1beta1 + kind: ValidatingWebhookConfiguration + metadata: + name: istio-galley + labels: + app: galley + chart: galley + heritage: Helm + release: RELEASE-NAME + istio: galley + webhooks: + - name: pilot.validation.istio.io + clientConfig: + service: + name: istio-galley + namespace: istio-system + path: "/admitpilot" + caBundle: "" + rules: + - operations: + - CREATE + - UPDATE + apiGroups: + - config.istio.io + apiVersions: + - v1alpha2 + resources: + - httpapispecs + - httpapispecbindings + - quotaspecs + - quotaspecbindings + - operations: + - CREATE + - UPDATE + apiGroups: + - rbac.istio.io + apiVersions: + - "*" + resources: + - "*" + - operations: + - CREATE + - UPDATE + apiGroups: + - security.istio.io + apiVersions: + - "*" + resources: + - "*" + - operations: + - CREATE + - UPDATE + apiGroups: + - authentication.istio.io + apiVersions: + - "*" + resources: + - "*" + - operations: + - CREATE + - UPDATE + apiGroups: + - networking.istio.io + apiVersions: + - "*" + resources: + - destinationrules + - envoyfilters + - gateways + - serviceentries + - sidecars + - virtualservices + failurePolicy: Fail + sideEffects: None + - name: mixer.validation.istio.io + clientConfig: + service: + name: istio-galley + namespace: istio-system + path: "/admitmixer" + caBundle: "" + rules: + - operations: + - CREATE + - UPDATE + apiGroups: + - config.istio.io + apiVersions: + - v1alpha2 + resources: + - rules + - attributemanifests + - circonuses + - deniers + - fluentds + - kubernetesenvs + - listcheckers + - memquotas + - noops + - opas + - prometheuses + - rbacs + - solarwindses + - stackdrivers + - cloudwatches + - dogstatsds + - statsds + - stdios + - apikeys + - authorizations + - checknothings + # - kuberneteses + - listentries + - logentries + - metrics + - quotas + - reportnothings + - tracespans + - adapters + - handlers + - instances + - templates + - zipkins + failurePolicy: Fail + sideEffects: None +--- +# Source: istio/charts/security/templates/configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: istio-security-custom-resources + namespace: istio-system + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME + istio: citadel +data: + custom-resources.yaml: |- + # Authentication policy to enable permissive mode for all services (that have sidecar) in the mesh. + apiVersion: "authentication.istio.io/v1alpha1" + kind: "MeshPolicy" + metadata: + name: "default" + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME + spec: + peers: + - mtls: + mode: PERMISSIVE + run.sh: |- + #!/bin/sh + + set -x + + if [ "$#" -ne "1" ]; then + echo "first argument should be path to custom resource yaml" + exit 1 + fi + + pathToResourceYAML=${1} + + kubectl get validatingwebhookconfiguration istio-galley 2>/dev/null + if [ "$?" -eq 0 ]; then + echo "istio-galley validatingwebhookconfiguration found - waiting for istio-galley deployment to be ready" + while true; do + kubectl -n istio-system get deployment istio-galley 2>/dev/null + if [ "$?" -eq 0 ]; then + break + fi + sleep 1 + done + kubectl -n istio-system rollout status deployment istio-galley + if [ "$?" -ne 0 ]; then + echo "istio-galley deployment rollout status check failed" + exit 1 + fi + echo "istio-galley deployment ready for configuration validation" + fi + sleep 5 + kubectl apply -f ${pathToResourceYAML} +--- +# Source: istio/templates/configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: istio + namespace: istio-system + labels: + app: istio + chart: istio + heritage: Helm + release: RELEASE-NAME +data: + mesh: |- + # Set the following variable to true to disable policy checks by Mixer. + # Note that metrics will still be reported to Mixer. + disablePolicyChecks: true + + disableMixerHttpReports: false + # reportBatchMaxEntries is the number of requests that are batched before telemetry data is sent to the mixer server + reportBatchMaxEntries: 100 + # reportBatchMaxTime is the max waiting time before the telemetry data of a request is sent to the mixer server + reportBatchMaxTime: 1s + + # Set enableTracing to false to disable request tracing. + enableTracing: true + + # Set accessLogFile to empty string to disable access log. + accessLogFile: "/dev/stdout" + + # If accessLogEncoding is TEXT, value will be used directly as the log format + # example: "[%START_TIME%] %REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\n" + # If AccessLogEncoding is JSON, value will be parsed as map[string]string + # example: '{"start_time": "%START_TIME%", "req_method": "%REQ(:METHOD)%"}' + # Leave empty to use default log format + accessLogFormat: "" + + # Set accessLogEncoding to JSON or TEXT to configure sidecar access log + accessLogEncoding: 'JSON' + + enableEnvoyAccessLogService: false + mixerCheckServer: istio-policy.istio-system.svc.cluster.local:9091 + mixerReportServer: istio-telemetry.istio-system.svc.cluster.local:9091 + # policyCheckFailOpen allows traffic in cases when the mixer policy service cannot be reached. + # Default is false which means the traffic is denied when the client is unable to connect to Mixer. + policyCheckFailOpen: false + # Let Pilot give ingresses the public IP of the Istio ingressgateway + ingressService: istio-ingressgateway + + # Default connect timeout for dynamic clusters generated by Pilot and returned via XDS + connectTimeout: 10s + + # Automatic protocol detection uses a set of heuristics to + # determine whether the connection is using TLS or not (on the + # server side), as well as the application protocol being used + # (e.g., http vs tcp). These heuristics rely on the client sending + # the first bits of data. For server first protocols like MySQL, + # MongoDB, etc., Envoy will timeout on the protocol detection after + # the specified period, defaulting to non mTLS plain TCP + # traffic. Set this field to tweak the period that Envoy will wait + # for the client to send the first bits of data. (MUST BE >=1ms) + protocolDetectionTimeout: 100ms + + # DNS refresh rate for Envoy clusters of type STRICT_DNS + dnsRefreshRate: 300s + + # Unix Domain Socket through which envoy communicates with NodeAgent SDS to get + # key/cert for mTLS. Use secret-mount files instead of SDS if set to empty. + sdsUdsPath: "" + + # The trust domain corresponds to the trust root of a system. + # Refer to https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE-ID.md#21-trust-domain + trustDomain: "" + + # The trust domain aliases represent the aliases of trust_domain. + # For example, if we have + # trustDomain: td1 + # trustDomainAliases: [“td2”, "td3"] + # Any service with the identity "td1/ns/foo/sa/a-service-account", "td2/ns/foo/sa/a-service-account", + # or "td3/ns/foo/sa/a-service-account" will be treated the same in the Istio mesh. + trustDomainAliases: + + # If true, automatically configure client side mTLS settings to match the corresponding service's + # server side mTLS authentication policy, when destination rule for that service does not specify + # TLS settings. + enableAutoMtls: false + + # Set the default behavior of the sidecar for handling outbound traffic from the application: + # ALLOW_ANY - outbound traffic to unknown destinations will be allowed, in case there are no + # services or ServiceEntries for the destination port + # REGISTRY_ONLY - restrict outbound traffic to services defined in the service registry as well + # as those defined through ServiceEntries + outboundTrafficPolicy: + mode: ALLOW_ANY + localityLbSetting: + enabled: true + # The namespace to treat as the administrative root namespace for istio + # configuration. + rootNamespace: istio-system + + # Configures DNS certificates provisioned through Chiron linked into Pilot. + certificates: + [] + configSources: + - address: istio-galley.istio-system.svc:9901 + + defaultConfig: + # + # TCP connection timeout between Envoy & the application, and between Envoys. Used for static clusters + # defined in Envoy's configuration file + connectTimeout: 10s + # + ### ADVANCED SETTINGS ############# + # Where should envoy's configuration be stored in the istio-proxy container + configPath: "/etc/istio/proxy" + binaryPath: "/usr/local/bin/envoy" + # The pseudo service name used for Envoy. + serviceCluster: istio-proxy + # These settings that determine how long an old Envoy + # process should be kept alive after an occasional reload. + drainDuration: 45s + parentShutdownDuration: 1m0s + # + # The mode used to redirect inbound connections to Envoy. This setting + # has no effect on outbound traffic: iptables REDIRECT is always used for + # outbound connections. + # If "REDIRECT", use iptables REDIRECT to NAT and redirect to Envoy. + # The "REDIRECT" mode loses source addresses during redirection. + # If "TPROXY", use iptables TPROXY to redirect to Envoy. + # The "TPROXY" mode preserves both the source and destination IP + # addresses and ports, so that they can be used for advanced filtering + # and manipulation. + # The "TPROXY" mode also configures the sidecar to run with the + # CAP_NET_ADMIN capability, which is required to use TPROXY. + #interceptionMode: REDIRECT + # + # Port where Envoy listens (on local host) for admin commands + # You can exec into the istio-proxy container in a pod and + # curl the admin port (curl http://localhost:15000/) to obtain + # diagnostic information from Envoy. See + # https://lyft.github.io/envoy/docs/operations/admin.html + # for more details + proxyAdminPort: 15000 + # + # Set concurrency to a specific number to control the number of Proxy worker threads. + # If set to 0 (default), then start worker thread for each CPU thread/core. + concurrency: 2 + # + tracing: + zipkin: + # Address of the Zipkin collector + address: zipkin.istio-system:9411 + # + # Mutual TLS authentication between sidecars and istio control plane. + controlPlaneAuthPolicy: NONE + # + # Address where istio Pilot service is running + discoveryAddress: istio-pilot.istio-system:15010 + + # Configuration file for the mesh networks to be used by the Split Horizon EDS. + meshNetworks: |- + networks: {} +--- +# Source: istio/templates/sidecar-injector-configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: istio-sidecar-injector + namespace: istio-system + labels: + app: istio + chart: istio + heritage: Helm + release: RELEASE-NAME + istio: sidecar-injector +data: + values: |- + {"certmanager":{"enabled":false,"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"hub":"quay.io/jetstack","image":"cert-manager-controller","nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"replicaCount":1,"resources":{},"tag":"v0.8.1","tolerations":[]},"galley":{"enableAnalysis":false,"enableServiceDiscovery":false,"enabled":true,"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"image":"galley","nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"replicaCount":1,"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%","tolerations":[]},"gateways":{"cluster-local-gateway":{"autoscaleMax":4,"autoscaleMin":2,"cpu":{"targetAverageUtilization":80},"enabled":true,"externalIPs":[],"labels":{"app":"cluster-local-gateway","istio":"cluster-local-gateway"},"loadBalancerIP":"","loadBalancerSourceRanges":{},"podAnnotations":{},"ports":[{"name":"status-port","port":15020},{"name":"http2","port":80},{"name":"https","port":443}],"replicaCount":2,"resources":{"requests":{"cpu":"250m","memory":"256Mi"}},"secretVolumes":[{"mountPath":"/etc/istio/cluster-local-gateway-certs","name":"cluster-local-gateway-certs","secretName":"istio-cluster-local-gateway-certs"},{"mountPath":"/etc/istio/cluster-local-gateway-ca-certs","name":"cluster-local-gateway-ca-certs","secretName":"istio-cluster-local-gateway-ca-certs"}],"serviceAnnotations":{},"type":"ClusterIP"},"enabled":true,"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"istio-egressgateway":{"autoscaleEnabled":true,"autoscaleMax":5,"autoscaleMin":1,"cpu":{"targetAverageUtilization":80},"enabled":false,"env":{"ISTIO_META_ROUTER_MODE":"sni-dnat"},"labels":{"app":"istio-egressgateway","istio":"egressgateway"},"nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"ports":[{"name":"http2","port":80},{"name":"https","port":443},{"name":"tls","port":15443,"targetPort":15443}],"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%","secretVolumes":[{"mountPath":"/etc/istio/egressgateway-certs","name":"egressgateway-certs","secretName":"istio-egressgateway-certs"},{"mountPath":"/etc/istio/egressgateway-ca-certs","name":"egressgateway-ca-certs","secretName":"istio-egressgateway-ca-certs"}],"serviceAnnotations":{},"tolerations":[],"type":"ClusterIP"},"istio-ilbgateway":{"autoscaleEnabled":true,"autoscaleMax":5,"autoscaleMin":1,"cpu":{"targetAverageUtilization":80},"enabled":false,"labels":{"app":"istio-ilbgateway","istio":"ilbgateway"},"loadBalancerIP":"","nodeSelector":{},"podAnnotations":{},"ports":[{"name":"grpc-pilot-mtls","port":15011},{"name":"grpc-pilot","port":15010},{"name":"tcp-citadel-grpc-tls","port":8060,"targetPort":8060},{"name":"tcp-dns","port":5353}],"resources":{"requests":{"cpu":"800m","memory":"512Mi"}},"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%","secretVolumes":[{"mountPath":"/etc/istio/ilbgateway-certs","name":"ilbgateway-certs","secretName":"istio-ilbgateway-certs"},{"mountPath":"/etc/istio/ilbgateway-ca-certs","name":"ilbgateway-ca-certs","secretName":"istio-ilbgateway-ca-certs"}],"serviceAnnotations":{"cloud.google.com/load-balancer-type":"internal"},"tolerations":[],"type":"LoadBalancer"},"istio-ingressgateway":{"applicationPorts":"","autoscaleEnabled":true,"autoscaleMax":4,"autoscaleMin":2,"cpu":{"targetAverageUtilization":80},"enabled":true,"env":{"ISTIO_META_ROUTER_MODE":"sni-dnat"},"externalIPs":[],"labels":{"app":"istio-ingressgateway","istio":"ingressgateway"},"loadBalancerIP":"","loadBalancerSourceRanges":[],"meshExpansionPorts":[{"name":"tcp-pilot-grpc-tls","port":15011,"targetPort":15011},{"name":"tcp-mixer-grpc-tls","port":15004,"targetPort":15004},{"name":"tcp-citadel-grpc-tls","port":8060,"targetPort":8060},{"name":"tcp-dns-tls","port":853,"targetPort":853}],"nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"ports":[{"name":"status-port","port":15020},{"name":"http2","port":80},{"name":"https","port":443}],"replicaCount":2,"resources":{"limits":{"cpu":"3000m","memory":"2048Mi"},"requests":{"cpu":"3000m","memory":"2048Mi"}},"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%","sds":{"enabled":true,"image":"node-agent-k8s","resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}}},"secretVolumes":[{"mountPath":"/etc/istio/ingressgateway-certs","name":"ingressgateway-certs","secretName":"istio-ingressgateway-certs"},{"mountPath":"/etc/istio/ingressgateway-ca-certs","name":"ingressgateway-ca-certs","secretName":"istio-ingressgateway-ca-certs"}],"serviceAnnotations":{},"tolerations":[],"type":"LoadBalancer"}},"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"grafana":{"accessMode":"ReadWriteMany","contextPath":"/grafana","dashboardProviders":{"dashboardproviders.yaml":{"apiVersion":1,"providers":[{"disableDeletion":false,"folder":"istio","name":"istio","options":{"path":"/var/lib/grafana/dashboards/istio"},"orgId":1,"type":"file"}]}},"datasources":{"datasources.yaml":{"apiVersion":1,"datasources":[{"access":"proxy","editable":true,"isDefault":true,"jsonData":{"timeInterval":"5s"},"name":"Prometheus","orgId":1,"type":"prometheus","url":"http://prometheus:9090"}]}},"enabled":false,"env":{},"envSecrets":{},"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"image":{"repository":"grafana/grafana","tag":"6.4.3"},"ingress":{"annotations":{},"enabled":false,"hosts":["grafana.local"],"tls":[]},"nodeSelector":{},"persist":false,"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"replicaCount":1,"security":{"enabled":false,"passphraseKey":"passphrase","secretName":"grafana","usernameKey":"username"},"service":{"annotations":{},"externalPort":3000,"loadBalancerIP":null,"loadBalancerSourceRanges":[],"name":"http","type":"ClusterIP"},"storageClassName":"","tolerations":[]},"istio_cni":{"enabled":false},"istiocoredns":{"coreDNSImage":"coredns/coredns","coreDNSPluginImage":"istio/coredns-plugin:0.2-istio-1.1","coreDNSTag":"1.6.2","enabled":false,"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"replicaCount":1,"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%","tolerations":[]},"kiali":{"contextPath":"/kiali","createDemoSecret":false,"dashboard":{"auth":{"strategy":"login"},"grafanaURL":null,"jaegerURL":null,"secretName":"kiali","viewOnlyMode":false},"enabled":false,"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"hub":"quay.io/kiali","image":"kiali","ingress":{"annotations":{},"enabled":false,"hosts":["kiali.local"],"tls":null},"nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"prometheusAddr":"http://prometheus:9090","replicaCount":1,"security":{"cert_file":"/kiali-cert/cert-chain.pem","enabled":false,"private_key_file":"/kiali-cert/key.pem"},"tag":"v1.9","tolerations":[]},"mixer":{"adapters":{"kubernetesenv":{"enabled":true},"prometheus":{"enabled":false,"metricsExpiryDuration":"10m"},"stdio":{"enabled":false,"outputAsJson":true},"useAdapterCRDs":false},"env":{"GOMAXPROCS":"6"},"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"image":"mixer","nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"policy":{"autoscaleEnabled":true,"autoscaleMax":5,"autoscaleMin":1,"cpu":{"targetAverageUtilization":80},"enabled":true,"replicaCount":1,"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%"},"telemetry":{"autoscaleEnabled":true,"autoscaleMax":5,"autoscaleMin":1,"cpu":{"targetAverageUtilization":80},"enabled":true,"loadshedding":{"latencyThreshold":"100ms","mode":"enforce"},"replicaCount":1,"reportBatchMaxEntries":100,"reportBatchMaxTime":"1s","resources":{"limits":{"cpu":"4800m","memory":"4G"},"requests":{"cpu":"1000m","memory":"1G"}},"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%","sessionAffinityEnabled":false},"tolerations":[]},"nodeagent":{"enabled":false,"env":{"CA_ADDR":"","CA_PROVIDER":"","PLUGINS":""},"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"image":"node-agent-k8s","nodeSelector":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"tolerations":[]},"pilot":{"autoscaleEnabled":true,"autoscaleMax":5,"autoscaleMin":2,"configSource":{"subscribedResources":null},"cpu":{"targetAverageUtilization":80},"enableProtocolSniffingForInbound":false,"enableProtocolSniffingForOutbound":true,"enabled":true,"env":{"PILOT_PUSH_THROTTLE":100},"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"image":"pilot","keepaliveMaxServerConnectionAge":"30m","nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"resources":{"requests":{"cpu":"3000m","memory":"2048Mi"}},"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%","sidecar":true,"tolerations":[],"traceSampling":100},"prometheus":{"enabled":false},"security":{"citadelHealthCheck":false,"createMeshPolicy":true,"enableNamespacesByDefault":true,"enabled":true,"env":{},"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"image":"citadel","nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"replicaCount":1,"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%","selfSigned":true,"tolerations":[],"workloadCertTtl":"2160h"},"sidecarInjectorWebhook":{"alwaysInjectSelector":[],"enableNamespacesByDefault":false,"enabled":true,"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"image":"sidecar_injector","injectedAnnotations":{},"neverInjectSelector":[],"nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"replicaCount":1,"rewriteAppHTTPProbe":true,"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%","tolerations":[]},"tracing":{"enabled":false,"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"ingress":{"annotations":null,"enabled":false,"hosts":null,"tls":null},"jaeger":{"accessMode":"ReadWriteMany","hub":"docker.io/jaegertracing","image":"all-in-one","memory":{"max_traces":50000},"persist":false,"podAnnotations":{},"spanStorageType":"badger","storageClassName":"","tag":1.14},"nodeSelector":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"provider":"jaeger","service":{"annotations":{},"externalPort":80,"name":"http","type":"ClusterIP"},"tolerations":[],"zipkin":{"hub":"docker.io/openzipkin","image":"zipkin","javaOptsHeap":700,"maxSpans":500000,"node":{"cpus":2},"podAnnotations":{},"probeStartupDelay":200,"queryPort":9411,"resources":{"limits":{"cpu":"300m","memory":"900Mi"},"requests":{"cpu":"150m","memory":"900Mi"}},"tag":"2.14.2"}}} + + config: |- + policy: enabled + alwaysInjectSelector: + [] + neverInjectSelector: + [] + template: |- + rewriteAppHTTPProbe: {{ valueOrDefault .Values.sidecarInjectorWebhook.rewriteAppHTTPProbe false }} + {{- if or (not .Values.istio_cni.enabled) .Values.global.proxy.enableCoreDump }} + initContainers: + {{ if ne (annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode) `NONE` }} + {{- if not .Values.istio_cni.enabled }} + - name: istio-init + {{- if contains "/" .Values.global.proxy_init.image }} + image: "{{ .Values.global.proxy_init.image }}" + {{- else }} + image: "{{ .Values.global.hub }}/{{ .Values.global.proxy_init.image }}:{{ .Values.global.tag }}" + {{- end }} + command: + - istio-iptables + - "-p" + - "15001" + - "-z" + - "15006" + - "-u" + - 1337 + - "-m" + - "{{ annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode }}" + - "-i" + - "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeOutboundIPRanges` .Values.global.proxy.includeIPRanges }}" + - "-x" + - "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/excludeOutboundIPRanges` .Values.global.proxy.excludeIPRanges }}" + - "-b" + - "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeInboundPorts` `*` }}" + - "-d" + - "{{ excludeInboundPort (annotation .ObjectMeta `status.sidecar.istio.io/port` .Values.global.proxy.statusPort) (annotation .ObjectMeta `traffic.sidecar.istio.io/excludeInboundPorts` .Values.global.proxy.excludeInboundPorts) }}" + {{ if or (isset .ObjectMeta.Annotations `traffic.sidecar.istio.io/excludeOutboundPorts`) (ne .Values.global.proxy.excludeOutboundPorts "") -}} + - "-o" + - "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/excludeOutboundPorts` .Values.global.proxy.excludeOutboundPorts }}" + {{ end -}} + {{ if (isset .ObjectMeta.Annotations `traffic.sidecar.istio.io/kubevirtInterfaces`) -}} + - "-k" + - "{{ index .ObjectMeta.Annotations `traffic.sidecar.istio.io/kubevirtInterfaces` }}" + {{ end -}} + imagePullPolicy: "{{ .Values.global.imagePullPolicy }}" + {{- if .Values.global.proxy.init.resources }} + resources: + {{ toYaml .Values.global.proxy.init.resources | indent 4 }} + {{- else }} + resources: {} + {{- end }} + securityContext: + allowPrivilegeEscalation: {{ .Values.global.proxy.privileged }} + capabilities: + add: + - NET_ADMIN + - NET_RAW + drop: + - ALL + privileged: {{ .Values.global.proxy.privileged }} + readOnlyRootFilesystem: false + runAsGroup: 0 + runAsNonRoot: false + runAsUser: 0 + restartPolicy: Always + {{- end }} + {{ end -}} + {{- if eq .Values.global.proxy.enableCoreDump true }} + - name: enable-core-dump + args: + - -c + - sysctl -w kernel.core_pattern=/var/lib/istio/core.proxy && ulimit -c unlimited + command: + - /bin/sh + image: {{ $.Values.global.proxy.enableCoreDumpImage }} + imagePullPolicy: IfNotPresent + resources: {} + securityContext: + allowPrivilegeEscalation: true + capabilities: + add: + - SYS_ADMIN + drop: + - ALL + privileged: true + readOnlyRootFilesystem: false + runAsGroup: 0 + runAsNonRoot: false + runAsUser: 0 + {{ end }} + {{- end }} + containers: + - name: istio-proxy + {{- if contains "/" (annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image) }} + image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image }}" + {{- else }} + image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.hub }}/{{ .Values.global.proxy.image }}:{{ .Values.global.tag }}" + {{- end }} + ports: + - containerPort: 15090 + protocol: TCP + name: http-envoy-prom + args: + - proxy + - sidecar + - --domain + - $(POD_NAMESPACE).svc.{{ .Values.global.proxy.clusterDomain }} + - --configPath + - "{{ .ProxyConfig.ConfigPath }}" + - --binaryPath + - "{{ .ProxyConfig.BinaryPath }}" + - --serviceCluster + {{ if ne "" (index .ObjectMeta.Labels "app") -}} + - "{{ index .ObjectMeta.Labels `app` }}.$(POD_NAMESPACE)" + {{ else -}} + - "{{ valueOrDefault .DeploymentMeta.Name `istio-proxy` }}.{{ valueOrDefault .DeploymentMeta.Namespace `default` }}" + {{ end -}} + - --drainDuration + - "{{ formatDuration .ProxyConfig.DrainDuration }}" + - --parentShutdownDuration + - "{{ formatDuration .ProxyConfig.ParentShutdownDuration }}" + - --discoveryAddress + - "{{ annotation .ObjectMeta `sidecar.istio.io/discoveryAddress` .ProxyConfig.DiscoveryAddress }}" + {{- if eq .Values.global.proxy.tracer "lightstep" }} + - --lightstepAddress + - "{{ .ProxyConfig.GetTracing.GetLightstep.GetAddress }}" + - --lightstepAccessToken + - "{{ .ProxyConfig.GetTracing.GetLightstep.GetAccessToken }}" + - --lightstepSecure={{ .ProxyConfig.GetTracing.GetLightstep.GetSecure }} + - --lightstepCacertPath + - "{{ .ProxyConfig.GetTracing.GetLightstep.GetCacertPath }}" + {{- else if eq .Values.global.proxy.tracer "zipkin" }} + - --zipkinAddress + - "{{ .ProxyConfig.GetTracing.GetZipkin.GetAddress }}" + {{- else if eq .Values.global.proxy.tracer "datadog" }} + - --datadogAgentAddress + - "{{ .ProxyConfig.GetTracing.GetDatadog.GetAddress }}" + {{- end }} + {{- if .Values.global.proxy.logLevel }} + - --proxyLogLevel={{ .Values.global.proxy.logLevel }} + {{- end}} + {{- if .Values.global.proxy.componentLogLevel }} + - --proxyComponentLogLevel={{ .Values.global.proxy.componentLogLevel }} + {{- end}} + - --dnsRefreshRate + - {{ .Values.global.proxy.dnsRefreshRate }} + - --connectTimeout + - "{{ formatDuration .ProxyConfig.ConnectTimeout }}" + {{- if .Values.global.proxy.envoyStatsd.enabled }} + - --statsdUdpAddress + - "{{ .ProxyConfig.StatsdUdpAddress }}" + {{- end }} + {{- if .Values.global.proxy.envoyMetricsService.enabled }} + - --envoyMetricsService + - '{{ protoToJSON .ProxyConfig.EnvoyMetricsService }}' + {{- end }} + {{- if .Values.global.proxy.envoyAccessLogService.enabled }} + - --envoyAccessLogService + - '{{ protoToJSON .ProxyConfig.EnvoyAccessLogService }}' + {{- end }} + - --proxyAdminPort + - "{{ .ProxyConfig.ProxyAdminPort }}" + {{ if gt .ProxyConfig.Concurrency 0 -}} + - --concurrency + - "{{ .ProxyConfig.Concurrency }}" + {{ end -}} + - --controlPlaneAuthPolicy + - "{{ annotation .ObjectMeta `sidecar.istio.io/controlPlaneAuthPolicy` .ProxyConfig.ControlPlaneAuthPolicy }}" + {{- if (ne (annotation .ObjectMeta "status.sidecar.istio.io/port" (valueOrDefault .Values.global.proxy.statusPort 0 )) `0`) }} + - --statusPort + - "{{ annotation .ObjectMeta `status.sidecar.istio.io/port` .Values.global.proxy.statusPort }}" + - --applicationPorts + - "{{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/applicationPorts` (applicationPorts .Spec.Containers) }}" + {{- end }} + {{- if .Values.global.trustDomain }} + - --trust-domain={{ .Values.global.trustDomain }} + {{- end }} + {{- if .Values.global.proxy.lifecycle }} + lifecycle: + {{ toYaml .Values.global.proxy.lifecycle | indent 4 }} + {{- end }} + env: + - name: POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: ISTIO_META_POD_PORTS + value: |- + [ + {{- $first := true }} + {{- range $index1, $c := .Spec.Containers }} + {{- range $index2, $p := $c.Ports }} + {{- if (structToJSON $p) }} + {{if not $first}},{{end}}{{ structToJSON $p }} + {{- $first = false }} + {{- end }} + {{- end}} + {{- end}} + ] + - name: ISTIO_META_CLUSTER_ID + value: "{{ valueOrDefault .Values.global.multiCluster.clusterName `Kubernetes` }}" + - name: POD_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + fieldPath: status.podIP + - name: SERVICE_ACCOUNT + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + {{- if .Values.global.mtls.auto }} + - name: ISTIO_AUTO_MTLS_ENABLED + value: "true" + {{- end }} + {{- if eq .Values.global.proxy.tracer "datadog" }} + - name: HOST_IP + valueFrom: + fieldRef: + fieldPath: status.hostIP + {{- if isset .ObjectMeta.Annotations `apm.datadoghq.com/env` }} + {{- range $key, $value := fromJSON (index .ObjectMeta.Annotations `apm.datadoghq.com/env`) }} + - name: {{ $key }} + value: "{{ $value }}" + {{- end }} + {{- end }} + {{- end }} + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + fieldPath: metadata.name + - name: ISTIO_META_CONFIG_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: SDS_ENABLED + value: {{ $.Values.global.sds.enabled }} + - name: ISTIO_META_INTERCEPTION_MODE + value: "{{ or (index .ObjectMeta.Annotations `sidecar.istio.io/interceptionMode`) .ProxyConfig.InterceptionMode.String }}" + - name: ISTIO_META_INCLUDE_INBOUND_PORTS + value: "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeInboundPorts` (applicationPorts .Spec.Containers) }}" + {{- if .Values.global.network }} + - name: ISTIO_META_NETWORK + value: "{{ .Values.global.network }}" + {{- end }} + {{ if .ObjectMeta.Annotations }} + - name: ISTIO_METAJSON_ANNOTATIONS + value: | + {{ toJSON .ObjectMeta.Annotations }} + {{ end }} + {{ if .ObjectMeta.Labels }} + - name: ISTIO_METAJSON_LABELS + value: | + {{ toJSON .ObjectMeta.Labels }} + {{ end }} + {{- if .DeploymentMeta.Name }} + - name: ISTIO_META_WORKLOAD_NAME + value: {{ .DeploymentMeta.Name }} + # PATCH #2: Increase termination drain duration. + - name: TERMINATION_DRAIN_DURATION_SECONDS + value: "20" + # PATCH #2 ends. + {{ end }} + {{- if and .TypeMeta.APIVersion .DeploymentMeta.Name }} + - name: ISTIO_META_OWNER + value: kubernetes://apis/{{ .TypeMeta.APIVersion }}/namespaces/{{ valueOrDefault .DeploymentMeta.Namespace `default` }}/{{ toLower .TypeMeta.Kind}}s/{{ .DeploymentMeta.Name }} + {{- end}} + {{- if (isset .ObjectMeta.Annotations `sidecar.istio.io/bootstrapOverride`) }} + - name: ISTIO_BOOTSTRAP_OVERRIDE + value: "/etc/istio/custom-bootstrap/custom_bootstrap.json" + {{- end }} + {{- if .Values.global.sds.customTokenDirectory }} + - name: ISTIO_META_SDS_TOKEN_PATH + value: "{{ .Values.global.sds.customTokenDirectory -}}/sdstoken" + {{- end }} + {{- if .Values.global.meshID }} + - name: ISTIO_META_MESH_ID + value: "{{ .Values.global.meshID }}" + {{- else if .Values.global.trustDomain }} + - name: ISTIO_META_MESH_ID + value: "{{ .Values.global.trustDomain }}" + {{- end }} + {{- if eq .Values.global.proxy.tracer "stackdriver" }} + - name: STACKDRIVER_TRACING_ENABLED + value: "true" + - name: STACKDRIVER_TRACING_DEBUG + value: "{{ .ProxyConfig.GetTracing.GetStackdriver.GetDebug }}" + {{- if .ProxyConfig.GetTracing.GetStackdriver.GetMaxNumberOfAnnotations }} + - name: STACKDRIVER_TRACING_MAX_NUMBER_OF_ANNOTATIONS + value: "{{ .ProxyConfig.GetTracing.GetStackdriver.GetMaxNumberOfAnnotations }}" + {{- end }} + {{- if .ProxyConfig.GetTracing.GetStackdriver.GetMaxNumberOfAttributes }} + - name: STACKDRIVER_TRACING_MAX_NUMBER_OF_ATTRIBUTES + value: "{{ .ProxyConfig.GetTracing.GetStackdriver.GetMaxNumberOfAttributes }}" + {{- end }} + {{- if .ProxyConfig.GetTracing.GetStackdriver.GetMaxNumberOfMessageEvents }} + - name: STACKDRIVER_TRACING_MAX_NUMBER_OF_MESSAGE_EVENTS + value: "{{ .ProxyConfig.GetTracing.GetStackdriver.GetMaxNumberOfMessageEvents }}" + {{- end }} + {{- end }} + imagePullPolicy: {{ .Values.global.imagePullPolicy }} + {{ if ne (annotation .ObjectMeta `status.sidecar.istio.io/port` (valueOrDefault .Values.global.proxy.statusPort 0 )) `0` }} + readinessProbe: + httpGet: + path: /healthz/ready + port: {{ annotation .ObjectMeta `status.sidecar.istio.io/port` .Values.global.proxy.statusPort }} + initialDelaySeconds: {{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/initialDelaySeconds` .Values.global.proxy.readinessInitialDelaySeconds }} + periodSeconds: {{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/periodSeconds` .Values.global.proxy.readinessPeriodSeconds }} + failureThreshold: {{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/failureThreshold` .Values.global.proxy.readinessFailureThreshold }} + {{ end -}} + securityContext: + allowPrivilegeEscalation: {{ .Values.global.proxy.privileged }} + capabilities: + {{ if eq (annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode) `TPROXY` -}} + add: + - NET_ADMIN + {{- end }} + drop: + - ALL + privileged: {{ .Values.global.proxy.privileged }} + readOnlyRootFilesystem: {{ not .Values.global.proxy.enableCoreDump }} + runAsGroup: 1337 + {{ if eq (annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode) `TPROXY` -}} + runAsNonRoot: false + runAsUser: 0 + {{- else -}} + runAsNonRoot: true + runAsUser: 1337 + {{- end }} + resources: + {{ if or (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory`) -}} + requests: + {{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU`) -}} + cpu: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU` }}" + {{ end}} + {{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory`) -}} + memory: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory` }}" + {{ end }} + {{ else -}} + {{- if .Values.global.proxy.resources }} + {{ toYaml .Values.global.proxy.resources | indent 4 }} + {{- end }} + {{ end -}} + volumeMounts: + {{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/bootstrapOverride`) }} + - mountPath: /etc/istio/custom-bootstrap + name: custom-bootstrap-volume + {{- end }} + - mountPath: /etc/istio/proxy + name: istio-envoy + {{- if .Values.global.sds.enabled }} + - mountPath: /var/run/sds + name: sds-uds-path + readOnly: true + - mountPath: /var/run/secrets/tokens + name: istio-token + {{- if .Values.global.sds.customTokenDirectory }} + - mountPath: "{{ .Values.global.sds.customTokenDirectory -}}" + name: custom-sds-token + readOnly: true + {{- end }} + {{- else }} + - mountPath: /etc/certs/ + name: istio-certs + readOnly: true + {{- end }} + {{- if and (eq .Values.global.proxy.tracer "lightstep") .Values.global.tracer.lightstep.cacertPath }} + - mountPath: {{ directory .ProxyConfig.GetTracing.GetLightstep.GetCacertPath }} + name: lightstep-certs + readOnly: true + {{- end }} + {{- if isset .ObjectMeta.Annotations `sidecar.istio.io/userVolumeMount` }} + {{ range $index, $value := fromJSON (index .ObjectMeta.Annotations `sidecar.istio.io/userVolumeMount`) }} + - name: "{{ $index }}" + {{ toYaml $value | indent 4 }} + {{ end }} + {{- end }} + volumes: + {{- if (isset .ObjectMeta.Annotations `sidecar.istio.io/bootstrapOverride`) }} + - name: custom-bootstrap-volume + configMap: + name: {{ annotation .ObjectMeta `sidecar.istio.io/bootstrapOverride` "" }} + {{- end }} + - emptyDir: + medium: Memory + name: istio-envoy + {{- if .Values.global.sds.enabled }} + - name: sds-uds-path + hostPath: + path: /var/run/sds + - name: istio-token + projected: + sources: + - serviceAccountToken: + path: istio-token + expirationSeconds: 43200 + audience: {{ .Values.global.sds.token.aud }} + {{- if .Values.global.sds.customTokenDirectory }} + - name: custom-sds-token + secret: + secretName: sdstokensecret + {{- end }} + {{- else }} + - name: istio-certs + secret: + optional: true + {{ if eq .Spec.ServiceAccountName "" }} + secretName: istio.default + {{ else -}} + secretName: {{ printf "istio.%s" .Spec.ServiceAccountName }} + {{ end -}} + {{- if isset .ObjectMeta.Annotations `sidecar.istio.io/userVolume` }} + {{range $index, $value := fromJSON (index .ObjectMeta.Annotations `sidecar.istio.io/userVolume`) }} + - name: "{{ $index }}" + {{ toYaml $value | indent 2 }} + {{ end }} + {{ end }} + {{- end }} + {{- if and (eq .Values.global.proxy.tracer "lightstep") .Values.global.tracer.lightstep.cacertPath }} + - name: lightstep-certs + secret: + optional: true + secretName: lightstep.cacert + {{- end }} + {{- if .Values.global.podDNSSearchNamespaces }} + dnsConfig: + searches: + {{- range .Values.global.podDNSSearchNamespaces }} + - {{ render . }} + {{- end }} + {{- end }} + podRedirectAnnot: + sidecar.istio.io/interceptionMode: "{{ annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode }}" + traffic.sidecar.istio.io/includeOutboundIPRanges: "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeOutboundIPRanges` .Values.global.proxy.includeIPRanges }}" + traffic.sidecar.istio.io/excludeOutboundIPRanges: "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/excludeOutboundIPRanges` .Values.global.proxy.excludeIPRanges }}" + traffic.sidecar.istio.io/includeInboundPorts: "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeInboundPorts` (includeInboundPorts .Spec.Containers) }}" + traffic.sidecar.istio.io/excludeInboundPorts: "{{ excludeInboundPort (annotation .ObjectMeta `status.sidecar.istio.io/port` .Values.global.proxy.statusPort) (annotation .ObjectMeta `traffic.sidecar.istio.io/excludeInboundPorts` .Values.global.proxy.excludeInboundPorts) }}" + {{ if or (isset .ObjectMeta.Annotations `traffic.sidecar.istio.io/excludeOutboundPorts`) (ne .Values.global.proxy.excludeOutboundPorts "") }} + traffic.sidecar.istio.io/excludeOutboundPorts: "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/excludeOutboundPorts` .Values.global.proxy.excludeOutboundPorts }}" + {{- end }} + traffic.sidecar.istio.io/kubevirtInterfaces: "{{ index .ObjectMeta.Annotations `traffic.sidecar.istio.io/kubevirtInterfaces` }}" + injectedAnnotations: +--- +# Source: istio/charts/galley/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-galley-service-account + namespace: istio-system + labels: + app: galley + chart: galley + heritage: Helm + release: RELEASE-NAME +--- +# Source: istio/charts/gateways/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-ingressgateway-service-account + namespace: istio-system + labels: + app: istio-ingressgateway + chart: gateways + heritage: Helm + release: RELEASE-NAME +--- +# Source: istio/charts/gateways/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cluster-local-gateway-service-account + namespace: istio-system + labels: + app: cluster-local-gateway + chart: gateways + heritage: Helm + release: RELEASE-NAME +--- +# Source: istio/charts/mixer/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-mixer-service-account + namespace: istio-system + labels: + app: mixer + chart: mixer + heritage: Helm + release: RELEASE-NAME +--- +# Source: istio/charts/pilot/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-pilot-service-account + namespace: istio-system + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME +--- +# Source: istio/charts/security/templates/create-custom-resources-job.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-security-post-install-account + namespace: istio-system + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME +--- +# Source: istio/charts/security/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-citadel-service-account + namespace: istio-system + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-sidecar-injector-service-account + namespace: istio-system + labels: + app: sidecarInjectorWebhook + chart: sidecarInjectorWebhook + heritage: Helm + release: RELEASE-NAME + istio: sidecar-injector +--- +# Source: istio/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-multi + namespace: istio-system +--- +# Source: istio/charts/galley/templates/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: istio-galley-istio-system + labels: + app: galley + chart: galley + heritage: Helm + release: RELEASE-NAME +rules: + # For reading Istio resources +- apiGroups: [ + "authentication.istio.io", + "config.istio.io", + "networking.istio.io", + "rbac.istio.io", + "security.istio.io"] + resources: ["*"] + verbs: ["get", "list", "watch"] + # For updating Istio resource statuses +- apiGroups: [ + "authentication.istio.io", + "config.istio.io", + "networking.istio.io", + "rbac.istio.io", + "security.istio.io"] + resources: ["*/status"] + verbs: ["update"] +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations"] + verbs: ["*"] +- apiGroups: ["extensions","apps"] + resources: ["deployments"] + resourceNames: ["istio-galley"] + verbs: ["get"] +- apiGroups: [""] + resources: ["pods", "nodes", "services", "endpoints", "namespaces"] + verbs: ["get", "list", "watch"] +- apiGroups: ["extensions"] + resources: ["ingresses"] + verbs: ["get", "list", "watch"] +- apiGroups: ["extensions"] + resources: ["deployments/finalizers"] + resourceNames: ["istio-galley"] + verbs: ["update"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] +--- +# Source: istio/charts/mixer/templates/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: istio-mixer-istio-system + labels: + app: mixer + chart: mixer + heritage: Helm + release: RELEASE-NAME +rules: +- apiGroups: ["config.istio.io"] # istio CRD watcher + resources: ["*"] + verbs: ["create", "get", "list", "watch", "patch"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["configmaps", "endpoints", "pods", "services", "namespaces", "secrets", "replicationcontrollers"] + verbs: ["get", "list", "watch"] +- apiGroups: ["extensions", "apps"] + resources: ["replicasets"] + verbs: ["get", "list", "watch"] +--- +# Source: istio/charts/pilot/templates/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: istio-pilot-istio-system + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME +rules: +- apiGroups: ["config.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["rbac.istio.io"] + resources: ["*"] + verbs: ["get", "watch", "list"] +- apiGroups: ["security.istio.io"] + resources: ["*"] + verbs: ["get", "watch", "list"] +- apiGroups: ["networking.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["authentication.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["*"] +- apiGroups: ["extensions"] + resources: ["ingresses", "ingresses/status"] + verbs: ["*"] +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["create", "get", "list", "watch", "update"] +- apiGroups: [""] + resources: ["endpoints", "pods", "services", "namespaces", "nodes"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "get", "watch", "list", "update", "delete"] +- apiGroups: ["certificates.k8s.io"] + resources: + - "certificatesigningrequests" + - "certificatesigningrequests/approval" + - "certificatesigningrequests/status" + verbs: ["update", "create", "get", "delete"] +--- +# Source: istio/charts/security/templates/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: istio-citadel-istio-system + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME +rules: +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["create", "get", "update"] +- apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "get", "watch", "list", "update", "delete"] +- apiGroups: [""] + resources: ["serviceaccounts", "services", "namespaces"] + verbs: ["get", "watch", "list"] +- apiGroups: ["authentication.k8s.io"] + resources: ["tokenreviews"] + verbs: ["create"] +--- +# Source: istio/charts/security/templates/create-custom-resources-job.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: istio-security-post-install-istio-system + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME +rules: +- apiGroups: ["authentication.istio.io"] # needed to create default authn policy + resources: ["*"] + verbs: ["*"] +- apiGroups: ["networking.istio.io"] # needed to create security destination rules + resources: ["*"] + verbs: ["*"] +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations"] + verbs: ["get"] +- apiGroups: ["extensions", "apps"] + resources: ["deployments", "replicasets"] + verbs: ["get", "list", "watch"] +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: istio-sidecar-injector-istio-system + labels: + app: sidecarInjectorWebhook + chart: sidecarInjectorWebhook + heritage: Helm + release: RELEASE-NAME + istio: sidecar-injector +rules: +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["get", "list", "watch"] +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["mutatingwebhookconfigurations"] + verbs: ["get", "list", "watch", "patch"] +--- +# Source: istio/templates/clusterrole.yaml +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: istio-reader +rules: + - apiGroups: [''] + resources: ['nodes', 'pods', 'services', 'endpoints', "replicationcontrollers"] + verbs: ['get', 'watch', 'list'] + - apiGroups: ["extensions", "apps"] + resources: ["replicasets"] + verbs: ["get", "list", "watch"] +--- +# Source: istio/charts/galley/templates/clusterrolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istio-galley-admin-role-binding-istio-system + labels: + app: galley + chart: galley + heritage: Helm + release: RELEASE-NAME +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-galley-istio-system +subjects: + - kind: ServiceAccount + name: istio-galley-service-account + namespace: istio-system +--- +# Source: istio/charts/mixer/templates/clusterrolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istio-mixer-admin-role-binding-istio-system + labels: + app: mixer + chart: mixer + heritage: Helm + release: RELEASE-NAME +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-mixer-istio-system +subjects: + - kind: ServiceAccount + name: istio-mixer-service-account + namespace: istio-system +--- +# Source: istio/charts/pilot/templates/clusterrolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istio-pilot-istio-system + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-pilot-istio-system +subjects: + - kind: ServiceAccount + name: istio-pilot-service-account + namespace: istio-system +--- +# Source: istio/charts/security/templates/clusterrolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istio-citadel-istio-system + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-citadel-istio-system +subjects: + - kind: ServiceAccount + name: istio-citadel-service-account + namespace: istio-system +--- +# Source: istio/charts/security/templates/create-custom-resources-job.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istio-security-post-install-role-binding-istio-system + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-security-post-install-istio-system +subjects: + - kind: ServiceAccount + name: istio-security-post-install-account + namespace: istio-system +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/clusterrolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istio-sidecar-injector-admin-role-binding-istio-system + labels: + app: sidecarInjectorWebhook + chart: sidecarInjectorWebhook + heritage: Helm + release: RELEASE-NAME + istio: sidecar-injector +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-sidecar-injector-istio-system +subjects: + - kind: ServiceAccount + name: istio-sidecar-injector-service-account + namespace: istio-system +--- +# Source: istio/templates/clusterrolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istio-multi + labels: + chart: istio-1.4.3 +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-reader +subjects: +- kind: ServiceAccount + name: istio-multi + namespace: istio-system +--- +# Source: istio/charts/gateways/templates/role.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: istio-ingressgateway-sds + namespace: istio-system +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "watch", "list"] +--- +# Source: istio/charts/gateways/templates/rolebindings.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: istio-ingressgateway-sds + namespace: istio-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: istio-ingressgateway-sds +subjects: +- kind: ServiceAccount + name: istio-ingressgateway-service-account +--- +# Source: istio/charts/galley/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: istio-galley + namespace: istio-system + labels: + app: galley + chart: galley + heritage: Helm + release: RELEASE-NAME + istio: galley +spec: + ports: + - port: 443 + name: https-validation + - port: 15014 + name: http-monitoring + - port: 9901 + name: grpc-mcp + selector: + istio: galley +--- +# Source: istio/charts/gateways/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: cluster-local-gateway + namespace: istio-system + annotations: + labels: + chart: gateways + heritage: Helm + release: RELEASE-NAME + app: cluster-local-gateway + istio: cluster-local-gateway +spec: + type: ClusterIP + selector: + release: RELEASE-NAME + app: cluster-local-gateway + istio: cluster-local-gateway + ports: + - + name: status-port + port: 15020 + - + name: http2 + port: 80 + - + name: https + port: 443 +--- +# Source: istio/charts/gateways/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: istio-ingressgateway + namespace: istio-system + annotations: + labels: + chart: gateways + heritage: Helm + release: RELEASE-NAME + app: istio-ingressgateway + istio: ingressgateway +spec: + type: LoadBalancer + selector: + release: RELEASE-NAME + app: istio-ingressgateway + istio: ingressgateway + ports: + - + name: status-port + port: 15020 + - + name: http2 + port: 80 + - + name: https + port: 443 +--- +# Source: istio/charts/mixer/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: istio-policy + namespace: istio-system + annotations: + networking.istio.io/exportTo: "*" + labels: + app: mixer + chart: mixer + heritage: Helm + release: RELEASE-NAME + istio: mixer +spec: + ports: + - name: grpc-mixer + port: 9091 + - name: grpc-mixer-mtls + port: 15004 + - name: http-monitoring + port: 15014 + selector: + istio: mixer + istio-mixer-type: policy +--- +# Source: istio/charts/mixer/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: istio-telemetry + namespace: istio-system + annotations: + networking.istio.io/exportTo: "*" + labels: + app: mixer + chart: mixer + heritage: Helm + release: RELEASE-NAME + istio: mixer +spec: + ports: + - name: grpc-mixer + port: 9091 + - name: grpc-mixer-mtls + port: 15004 + - name: http-monitoring + port: 15014 + - name: prometheus + port: 42422 + selector: + istio: mixer + istio-mixer-type: telemetry +--- +# Source: istio/charts/pilot/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: istio-pilot + namespace: istio-system + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME + istio: pilot +spec: + ports: + - port: 15010 + name: grpc-xds # direct + - port: 15011 + name: https-xds # mTLS + - port: 8080 + name: http-legacy-discovery # direct + - port: 15014 + name: http-monitoring + selector: + istio: pilot +--- +# Source: istio/charts/security/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + # we use the normal name here (e.g. 'prometheus') + # as grafana is configured to use this as a data source + name: istio-citadel + namespace: istio-system + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME + istio: citadel +spec: + ports: + - name: grpc-citadel + port: 8060 + targetPort: 8060 + protocol: TCP + - name: http-monitoring + port: 15014 + selector: + istio: citadel +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: istio-sidecar-injector + namespace: istio-system + labels: + app: sidecarInjectorWebhook + chart: sidecarInjectorWebhook + heritage: Helm + release: RELEASE-NAME + istio: sidecar-injector +spec: + ports: + - port: 443 + name: https-inject + - port: 15014 + name: http-monitoring + selector: + istio: sidecar-injector +--- +# Source: istio/charts/galley/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: istio-galley + namespace: istio-system + labels: + app: galley + chart: galley + heritage: Helm + release: RELEASE-NAME + istio: galley +spec: + replicas: 1 + selector: + matchLabels: + istio: galley + strategy: + rollingUpdate: + maxSurge: 100% + maxUnavailable: 25% + template: + metadata: + labels: + app: galley + chart: galley + heritage: Helm + release: RELEASE-NAME + istio: galley + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: istio-galley-service-account + containers: + - name: galley + image: "docker.io/istio/galley:1.4.3" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 443 + - containerPort: 15014 + - containerPort: 9901 + command: + - /usr/local/bin/galley + - server + - --meshConfigFile=/etc/mesh-config/mesh + - --livenessProbeInterval=1s + - --livenessProbePath=/healthliveness + - --readinessProbePath=/healthready + - --readinessProbeInterval=1s + - --deployment-namespace=istio-system + - --insecure=true + - --enable-reconcileWebhookConfiguration=true + - --validation-webhook-config-file + - /etc/config/validatingwebhookconfiguration.yaml + - --monitoringPort=15014 + - --log_output_level=default:info + volumeMounts: + - name: certs + mountPath: /etc/certs + readOnly: true + - name: config + mountPath: /etc/config + readOnly: true + - name: mesh-config + mountPath: /etc/mesh-config + readOnly: true + livenessProbe: + exec: + command: + - /usr/local/bin/galley + - probe + - --probe-path=/healthliveness + - --interval=10s + initialDelaySeconds: 5 + periodSeconds: 5 + readinessProbe: + exec: + command: + - /usr/local/bin/galley + - probe + - --probe-path=/healthready + - --interval=10s + initialDelaySeconds: 5 + periodSeconds: 5 + resources: + requests: + cpu: 10m + volumes: + - name: certs + secret: + secretName: istio.istio-galley-service-account + - name: config + configMap: + name: istio-galley-configuration + - name: mesh-config + configMap: + name: istio + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - "ppc64le" + - "s390x" + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "ppc64le" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "s390x" +--- +# Source: istio/charts/gateways/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cluster-local-gateway + namespace: istio-system + labels: + app: cluster-local-gateway + chart: gateways + heritage: Helm + istio: cluster-local-gateway + release: RELEASE-NAME +spec: + replicas: 2 + selector: + matchLabels: + app: cluster-local-gateway + istio: cluster-local-gateway + strategy: + rollingUpdate: + maxSurge: + maxUnavailable: + template: + metadata: + labels: + app: cluster-local-gateway + chart: gateways + heritage: Helm + istio: cluster-local-gateway + release: RELEASE-NAME + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: cluster-local-gateway-service-account + containers: + - name: istio-proxy + image: "docker.io/istio/proxyv2:1.4.3" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 15020 + - containerPort: 80 + - containerPort: 443 + - containerPort: 15090 + protocol: TCP + name: http-envoy-prom + args: + - proxy + - router + - --domain + - $(POD_NAMESPACE).svc.cluster.local + - --log_output_level=default:info + - --drainDuration + - '45s' #drainDuration + - --parentShutdownDuration + - '1m0s' #parentShutdownDuration + - --connectTimeout + - '10s' #connectTimeout + - --serviceCluster + - cluster-local-gateway + - --zipkinAddress + - zipkin:9411 + - --proxyAdminPort + - "15000" + - --statusPort + - "15020" + - --controlPlaneAuthPolicy + - NONE + - --discoveryAddress + - istio-pilot:15010 + readinessProbe: + failureThreshold: 30 + httpGet: + path: /healthz/ready + port: 15020 + scheme: HTTP + initialDelaySeconds: 1 + periodSeconds: 2 + successThreshold: 1 + timeoutSeconds: 1 + resources: + requests: + cpu: 250m + memory: 256Mi + env: + - name: NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + - name: HOST_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + - name: SERVICE_ACCOUNT + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: ISTIO_META_CONFIG_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: ISTIO_METAJSON_LABELS + value: | + {"app":"cluster-local-gateway","chart":"gateways","heritage":"Helm","istio":"cluster-local-gateway","release":"RELEASE-NAME"} + - name: ISTIO_META_CLUSTER_ID + value: "Kubernetes" + - name: SDS_ENABLED + value: "false" + - name: ISTIO_META_WORKLOAD_NAME + value: cluster-local-gateway + - name: ISTIO_META_OWNER + value: kubernetes://apis/apps/v1/namespaces/istio-system/deployments/cluster-local-gateway + + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: cluster-local-gateway-certs + mountPath: "/etc/istio/cluster-local-gateway-certs" + readOnly: true + - name: cluster-local-gateway-ca-certs + mountPath: "/etc/istio/cluster-local-gateway-ca-certs" + readOnly: true + volumes: + - name: istio-certs + secret: + secretName: istio.cluster-local-gateway-service-account + optional: true + - name: cluster-local-gateway-certs + secret: + secretName: "istio-cluster-local-gateway-certs" + optional: true + - name: cluster-local-gateway-ca-certs + secret: + secretName: "istio-cluster-local-gateway-ca-certs" + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - "ppc64le" + - "s390x" + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "ppc64le" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "s390x" +--- +# Source: istio/charts/gateways/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: istio-ingressgateway + namespace: istio-system + labels: + app: istio-ingressgateway + chart: gateways + heritage: Helm + istio: ingressgateway + release: RELEASE-NAME +spec: + selector: + matchLabels: + app: istio-ingressgateway + istio: ingressgateway + strategy: + rollingUpdate: + maxSurge: 100% + maxUnavailable: 25% + template: + metadata: + labels: + app: istio-ingressgateway + chart: gateways + heritage: Helm + istio: ingressgateway + release: RELEASE-NAME + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: istio-ingressgateway-service-account + containers: + - name: ingress-sds + image: "docker.io/istio/node-agent-k8s:1.4.3" + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 2000m + memory: 1024Mi + requests: + cpu: 100m + memory: 128Mi + env: + - name: "ENABLE_WORKLOAD_SDS" + value: "false" + - name: "ENABLE_INGRESS_GATEWAY_SDS" + value: "true" + - name: "INGRESS_GATEWAY_NAMESPACE" + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + volumeMounts: + - name: ingressgatewaysdsudspath + mountPath: /var/run/ingress_gateway + - name: istio-proxy + image: "docker.io/istio/proxyv2:1.4.3" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 15020 + - containerPort: 80 + - containerPort: 443 + - containerPort: 15090 + protocol: TCP + name: http-envoy-prom + args: + - proxy + - router + - --domain + - $(POD_NAMESPACE).svc.cluster.local + - --log_output_level=default:info + - --drainDuration + - '45s' #drainDuration + - --parentShutdownDuration + - '1m0s' #parentShutdownDuration + - --connectTimeout + - '10s' #connectTimeout + - --serviceCluster + - istio-ingressgateway + - --zipkinAddress + - zipkin:9411 + - --proxyAdminPort + - "15000" + - --statusPort + - "15020" + - --controlPlaneAuthPolicy + - NONE + - --discoveryAddress + - istio-pilot:15010 + readinessProbe: + failureThreshold: 30 + httpGet: + path: /healthz/ready + port: 15020 + scheme: HTTP + initialDelaySeconds: 1 + periodSeconds: 2 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + cpu: 3000m + memory: 2048Mi + requests: + cpu: 3000m + memory: 2048Mi + env: + - name: NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + - name: HOST_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + - name: SERVICE_ACCOUNT + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: ISTIO_META_CONFIG_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: ISTIO_METAJSON_LABELS + value: | + {"app":"istio-ingressgateway","chart":"gateways","heritage":"Helm","istio":"ingressgateway","release":"RELEASE-NAME"} + - name: ISTIO_META_CLUSTER_ID + value: "Kubernetes" + - name: SDS_ENABLED + value: "false" + - name: ISTIO_META_WORKLOAD_NAME + value: istio-ingressgateway + - name: ISTIO_META_OWNER + value: kubernetes://apis/apps/v1/namespaces/istio-system/deployments/istio-ingressgateway + - name: ISTIO_META_USER_SDS + value: "true" + - name: ISTIO_META_ROUTER_MODE + value: sni-dnat + + + volumeMounts: + - name: ingressgatewaysdsudspath + mountPath: /var/run/ingress_gateway + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: ingressgateway-certs + mountPath: "/etc/istio/ingressgateway-certs" + readOnly: true + - name: ingressgateway-ca-certs + mountPath: "/etc/istio/ingressgateway-ca-certs" + readOnly: true + volumes: + - name: ingressgatewaysdsudspath + emptyDir: {} + - name: istio-certs + secret: + secretName: istio.istio-ingressgateway-service-account + optional: true + - name: ingressgateway-certs + secret: + secretName: "istio-ingressgateway-certs" + optional: true + - name: ingressgateway-ca-certs + secret: + secretName: "istio-ingressgateway-ca-certs" + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - "ppc64le" + - "s390x" + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "ppc64le" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "s390x" +--- +# Source: istio/charts/mixer/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: istio-policy + namespace: istio-system + labels: + app: istio-mixer + chart: mixer + heritage: Helm + release: RELEASE-NAME + istio: mixer +spec: + strategy: + rollingUpdate: + maxSurge: 100% + maxUnavailable: 25% + selector: + matchLabels: + istio: mixer + istio-mixer-type: policy + template: + metadata: + labels: + app: policy + chart: mixer + heritage: Helm + release: RELEASE-NAME + security.istio.io/tlsMode: "istio" + istio: mixer + istio-mixer-type: policy + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: istio-mixer-service-account + volumes: + - name: istio-certs + secret: + secretName: istio.istio-mixer-service-account + optional: true + - name: uds-socket + emptyDir: {} + - name: policy-adapter-secret + secret: + secretName: policy-adapter-secret + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - "ppc64le" + - "s390x" + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "ppc64le" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "s390x" + containers: + - name: mixer + image: "docker.io/istio/mixer:1.4.3" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 15014 + - containerPort: 42422 + args: + - --monitoringPort=15014 + - --address + - unix:///sock/mixer.socket + - --log_output_level=default:info + - --configStoreURL=mcp://istio-galley.istio-system.svc:9901 + - --configDefaultNamespace=istio-system + - --useAdapterCRDs=false + - --useTemplateCRDs=false + - --trace_zipkin_url=http://zipkin.istio-system:9411/api/v1/spans + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: GOMAXPROCS + value: "6" + resources: + requests: + cpu: 10m + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: uds-socket + mountPath: /sock + livenessProbe: + httpGet: + path: /version + port: 15014 + initialDelaySeconds: 5 + periodSeconds: 5 + - name: istio-proxy + image: "docker.io/istio/proxyv2:1.4.3" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9091 + - containerPort: 15004 + - containerPort: 15090 + protocol: TCP + name: http-envoy-prom + args: + - proxy + - --domain + - $(POD_NAMESPACE).svc.cluster.local + - --serviceCluster + - istio-policy + - --templateFile + - /etc/istio/proxy/envoy_policy.yaml.tmpl + - --controlPlaneAuthPolicy + - NONE + - --log_output_level=default:info + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + - name: SDS_ENABLED + value: "false" + resources: + limits: + cpu: 2000m + memory: 1024Mi + requests: + cpu: 100m + memory: 128Mi + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: uds-socket + mountPath: /sock + - name: policy-adapter-secret + mountPath: /var/run/secrets/istio.io/policy/adapter + readOnly: true +--- +# Source: istio/charts/mixer/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: istio-telemetry + namespace: istio-system + labels: + app: istio-mixer + chart: mixer + heritage: Helm + release: RELEASE-NAME + istio: mixer +spec: + strategy: + rollingUpdate: + maxSurge: 100% + maxUnavailable: 25% + selector: + matchLabels: + istio: mixer + istio-mixer-type: telemetry + template: + metadata: + labels: + app: telemetry + chart: mixer + heritage: Helm + release: RELEASE-NAME + security.istio.io/tlsMode: "istio" + istio: mixer + istio-mixer-type: telemetry + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: istio-mixer-service-account + volumes: + - name: istio-certs + secret: + secretName: istio.istio-mixer-service-account + optional: true + - name: uds-socket + emptyDir: {} + - name: telemetry-adapter-secret + secret: + secretName: telemetry-adapter-secret + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - "ppc64le" + - "s390x" + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "ppc64le" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "s390x" + containers: + - name: mixer + image: "docker.io/istio/mixer:1.4.3" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 15014 + - containerPort: 42422 + args: + - --monitoringPort=15014 + - --address + - unix:///sock/mixer.socket + - --log_output_level=default:info + - --configStoreURL=mcp://istio-galley.istio-system.svc:9901 + - --configDefaultNamespace=istio-system + - --useAdapterCRDs=false + - --trace_zipkin_url=http://zipkin.istio-system:9411/api/v1/spans + - --averageLatencyThreshold + - 100ms + - --loadsheddingMode + - enforce + env: + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: GOMAXPROCS + value: "6" + resources: + limits: + cpu: 4800m + memory: 4G + requests: + cpu: 1000m + memory: 1G + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: telemetry-adapter-secret + mountPath: /var/run/secrets/istio.io/telemetry/adapter + readOnly: true + - name: uds-socket + mountPath: /sock + livenessProbe: + httpGet: + path: /version + port: 15014 + initialDelaySeconds: 5 + periodSeconds: 5 + - name: istio-proxy + image: "docker.io/istio/proxyv2:1.4.3" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 9091 + - containerPort: 15004 + - containerPort: 15090 + protocol: TCP + name: http-envoy-prom + args: + - proxy + - --domain + - $(POD_NAMESPACE).svc.cluster.local + - --serviceCluster + - istio-telemetry + - --templateFile + - /etc/istio/proxy/envoy_telemetry.yaml.tmpl + - --controlPlaneAuthPolicy + - NONE + - --log_output_level=default:info + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + - name: SDS_ENABLED + value: "false" + resources: + limits: + cpu: 2000m + memory: 1024Mi + requests: + cpu: 100m + memory: 128Mi + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: uds-socket + mountPath: /sock +--- +# Source: istio/charts/pilot/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: istio-pilot + namespace: istio-system + # TODO: default template doesn't have this, which one is right ? + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME + istio: pilot +spec: + strategy: + rollingUpdate: + maxSurge: 100% + maxUnavailable: 25% + selector: + matchLabels: + istio: pilot + template: + metadata: + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME + istio: pilot + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: istio-pilot-service-account + containers: + - name: discovery + image: "docker.io/istio/pilot:1.4.3" + imagePullPolicy: IfNotPresent + args: + - "discovery" + - --monitoringAddr=:15014 + - --log_output_level=default:info + - --domain + - cluster.local + - --secureGrpcAddr + - "" + - --keepaliveMaxServerConnectionAge + - "30m" + ports: + - containerPort: 8080 + - containerPort: 15010 + readinessProbe: + httpGet: + path: /ready + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 5 + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: PILOT_PUSH_THROTTLE + value: "100" + - name: PILOT_TRACE_SAMPLING + value: "100" + - name: PILOT_ENABLE_PROTOCOL_SNIFFING_FOR_OUTBOUND + value: "true" + - name: PILOT_ENABLE_PROTOCOL_SNIFFING_FOR_INBOUND + value: "false" + resources: + requests: + cpu: 3000m + memory: 2048Mi + volumeMounts: + - name: config-volume + mountPath: /etc/istio/config + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: istio-proxy + image: "docker.io/istio/proxyv2:1.4.3" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 15003 + - containerPort: 15005 + - containerPort: 15007 + - containerPort: 15011 + args: + - proxy + - --domain + - $(POD_NAMESPACE).svc.cluster.local + - --serviceCluster + - istio-pilot + - --templateFile + - /etc/istio/proxy/envoy_pilot.yaml.tmpl + - --controlPlaneAuthPolicy + - NONE + - --log_output_level=default:info + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + - name: SDS_ENABLED + value: "false" + resources: + limits: + cpu: 2000m + memory: 1024Mi + requests: + cpu: 100m + memory: 128Mi + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + volumes: + - name: config-volume + configMap: + name: istio + - name: istio-certs + secret: + secretName: istio.istio-pilot-service-account + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - "ppc64le" + - "s390x" + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "ppc64le" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "s390x" +--- +# Source: istio/charts/security/templates/deployment.yaml +# istio CA watching all namespaces +apiVersion: apps/v1 +kind: Deployment +metadata: + name: istio-citadel + namespace: istio-system + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME + istio: citadel +spec: + replicas: 1 + selector: + matchLabels: + istio: citadel + strategy: + rollingUpdate: + maxSurge: 100% + maxUnavailable: 25% + template: + metadata: + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME + istio: citadel + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: istio-citadel-service-account + containers: + - name: citadel + image: "docker.io/istio/citadel:1.4.3" + imagePullPolicy: IfNotPresent + args: + - --append-dns-names=true + - --grpc-port=8060 + - --citadel-storage-namespace=istio-system + - --custom-dns-names=istio-pilot-service-account.istio-system:istio-pilot.istio-system + - --monitoring-port=15014 + - --self-signed-ca=true + - --workload-cert-ttl=2160h + env: + - name: CITADEL_ENABLE_NAMESPACES_BY_DEFAULT + value: "true" + resources: + requests: + cpu: 10m + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - "ppc64le" + - "s390x" + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "ppc64le" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "s390x" +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: istio-sidecar-injector + namespace: istio-system + labels: + app: sidecarInjectorWebhook + chart: sidecarInjectorWebhook + heritage: Helm + release: RELEASE-NAME + istio: sidecar-injector +spec: + replicas: 1 + selector: + matchLabels: + istio: sidecar-injector + strategy: + rollingUpdate: + maxSurge: 100% + maxUnavailable: 25% + template: + metadata: + labels: + app: sidecarInjectorWebhook + chart: sidecarInjectorWebhook + heritage: Helm + release: RELEASE-NAME + istio: sidecar-injector + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: istio-sidecar-injector-service-account + containers: + - name: sidecar-injector-webhook + image: "docker.io/istio/sidecar_injector:1.4.3" + imagePullPolicy: IfNotPresent + args: + - --caCertFile=/etc/istio/certs/root-cert.pem + - --tlsCertFile=/etc/istio/certs/cert-chain.pem + - --tlsKeyFile=/etc/istio/certs/key.pem + - --injectConfig=/etc/istio/inject/config + - --meshConfig=/etc/istio/config/mesh + - --healthCheckInterval=2s + - --healthCheckFile=/health + - --reconcileWebhookConfig=true + volumeMounts: + - name: config-volume + mountPath: /etc/istio/config + readOnly: true + - name: certs + mountPath: /etc/istio/certs + readOnly: true + - name: inject-config + mountPath: /etc/istio/inject + readOnly: true + livenessProbe: + exec: + command: + - /usr/local/bin/sidecar-injector + - probe + - --probe-path=/health + - --interval=4s + initialDelaySeconds: 4 + periodSeconds: 4 + readinessProbe: + exec: + command: + - /usr/local/bin/sidecar-injector + - probe + - --probe-path=/health + - --interval=4s + initialDelaySeconds: 4 + periodSeconds: 4 + resources: + requests: + cpu: 10m + volumes: + - name: config-volume + configMap: + name: istio + - name: certs + secret: + secretName: istio.istio-sidecar-injector-service-account + - name: inject-config + configMap: + name: istio-sidecar-injector + items: + - key: config + path: config + - key: values + path: values + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - "ppc64le" + - "s390x" + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "ppc64le" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "s390x" +--- +# Source: istio/charts/gateways/templates/autoscale.yaml +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: istio-ingressgateway + namespace: istio-system + labels: + chart: gateways + heritage: Helm + release: RELEASE-NAME + app: istio-ingressgateway + istio: ingressgateway +spec: + maxReplicas: 4 + minReplicas: 2 + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: istio-ingressgateway + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: 80 +--- +# Source: istio/charts/mixer/templates/autoscale.yaml +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: istio-telemetry + namespace: istio-system + labels: + app: mixer + chart: mixer + heritage: Helm + release: RELEASE-NAME +spec: + maxReplicas: 5 + minReplicas: 1 + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: istio-telemetry + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: 80 +--- +# Source: istio/charts/mixer/templates/autoscale.yaml +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: istio-policy + namespace: istio-system + labels: + app: mixer + chart: mixer + heritage: Helm + release: RELEASE-NAME +spec: + maxReplicas: 5 + minReplicas: 1 + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: istio-policy + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: 80 +--- +# Source: istio/charts/pilot/templates/autoscale.yaml +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: istio-pilot + namespace: istio-system + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME +spec: + maxReplicas: 5 + minReplicas: 2 + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: istio-pilot + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: 80 +--- +# Source: istio/charts/mixer/templates/config.yaml +--- +--- +# Source: istio/charts/mixer/templates/config.yaml +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: istio-telemetry + namespace: istio-system + labels: + app: mixer + chart: mixer + heritage: Helm + release: RELEASE-NAME +spec: + host: istio-telemetry.istio-system.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 15004 # grpc-mixer-mtls + tls: + mode: ISTIO_MUTUAL + - port: + number: 9091 # grpc-mixer + tls: + mode: DISABLE + connectionPool: + http: + http2MaxRequests: 10000 + maxRequestsPerConnection: 10000 +--- +# Source: istio/charts/mixer/templates/config.yaml +# Configuration needed by Mixer. +# Mixer cluster is delivered via CDS +# Specify mixer cluster settings +apiVersion: networking.istio.io/v1alpha3 +kind: DestinationRule +metadata: + name: istio-policy + namespace: istio-system + labels: + app: mixer + chart: mixer + heritage: Helm + release: RELEASE-NAME +spec: + host: istio-policy.istio-system.svc.cluster.local + trafficPolicy: + portLevelSettings: + - port: + number: 15004 # grpc-mixer-mtls + tls: + mode: ISTIO_MUTUAL + - port: + number: 9091 # grpc-mixer + tls: + mode: DISABLE + connectionPool: + http: + http2MaxRequests: 10000 + maxRequestsPerConnection: 10000 +--- +# Source: istio/charts/sidecarInjectorWebhook/templates/mutatingwebhook.yaml +apiVersion: admissionregistration.k8s.io/v1beta1 +kind: MutatingWebhookConfiguration +metadata: + name: istio-sidecar-injector + labels: + app: sidecarInjectorWebhook + chart: sidecarInjectorWebhook + heritage: Helm + release: RELEASE-NAME +webhooks: + - name: sidecar-injector.istio.io + clientConfig: + service: + name: istio-sidecar-injector + namespace: istio-system + path: "/inject" + caBundle: "" + rules: + - operations: [ "CREATE" ] + apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + failurePolicy: Fail + namespaceSelector: + matchLabels: + istio-injection: enabled +--- +# Source: istio/charts/mixer/templates/config.yaml +apiVersion: "config.istio.io/v1alpha2" +kind: attributemanifest +metadata: + name: kubernetes + namespace: istio-system + labels: + app: mixer + chart: mixer + heritage: Helm + release: RELEASE-NAME +spec: + attributes: + source.ip: + valueType: IP_ADDRESS + source.labels: + valueType: STRING_MAP + source.metadata: + valueType: STRING_MAP + source.name: + valueType: STRING + source.namespace: + valueType: STRING + source.owner: + valueType: STRING + source.serviceAccount: + valueType: STRING + source.services: + valueType: STRING + source.workload.uid: + valueType: STRING + source.workload.name: + valueType: STRING + source.workload.namespace: + valueType: STRING + destination.ip: + valueType: IP_ADDRESS + destination.labels: + valueType: STRING_MAP + destination.metadata: + valueType: STRING_MAP + destination.owner: + valueType: STRING + destination.name: + valueType: STRING + destination.container.name: + valueType: STRING + destination.namespace: + valueType: STRING + destination.service.uid: + valueType: STRING + destination.service.name: + valueType: STRING + destination.service.namespace: + valueType: STRING + destination.service.host: + valueType: STRING + destination.serviceAccount: + valueType: STRING + destination.workload.uid: + valueType: STRING + destination.workload.name: + valueType: STRING + destination.workload.namespace: + valueType: STRING +--- +# Source: istio/charts/mixer/templates/config.yaml +apiVersion: "config.istio.io/v1alpha2" +kind: attributemanifest +metadata: + name: istioproxy + namespace: istio-system + labels: + app: mixer + chart: mixer + heritage: Helm + release: RELEASE-NAME +spec: + attributes: + origin.ip: + valueType: IP_ADDRESS + origin.uid: + valueType: STRING + origin.user: + valueType: STRING + request.headers: + valueType: STRING_MAP + request.id: + valueType: STRING + request.host: + valueType: STRING + request.method: + valueType: STRING + request.path: + valueType: STRING + request.url_path: + valueType: STRING + request.query_params: + valueType: STRING_MAP + request.reason: + valueType: STRING + request.referer: + valueType: STRING + request.scheme: + valueType: STRING + request.total_size: + valueType: INT64 + request.size: + valueType: INT64 + request.time: + valueType: TIMESTAMP + request.useragent: + valueType: STRING + response.code: + valueType: INT64 + response.duration: + valueType: DURATION + response.headers: + valueType: STRING_MAP + response.total_size: + valueType: INT64 + response.size: + valueType: INT64 + response.time: + valueType: TIMESTAMP + response.grpc_status: + valueType: STRING + response.grpc_message: + valueType: STRING + source.uid: + valueType: STRING + source.user: # DEPRECATED + valueType: STRING + source.principal: + valueType: STRING + destination.uid: + valueType: STRING + destination.principal: + valueType: STRING + destination.port: + valueType: INT64 + connection.event: + valueType: STRING + connection.id: + valueType: STRING + connection.received.bytes: + valueType: INT64 + connection.received.bytes_total: + valueType: INT64 + connection.sent.bytes: + valueType: INT64 + connection.sent.bytes_total: + valueType: INT64 + connection.duration: + valueType: DURATION + connection.mtls: + valueType: BOOL + connection.requested_server_name: + valueType: STRING + context.protocol: + valueType: STRING + context.proxy_error_code: + valueType: STRING + context.timestamp: + valueType: TIMESTAMP + context.time: + valueType: TIMESTAMP + # Deprecated, kept for compatibility + context.reporter.local: + valueType: BOOL + context.reporter.kind: + valueType: STRING + context.reporter.uid: + valueType: STRING + api.service: + valueType: STRING + api.version: + valueType: STRING + api.operation: + valueType: STRING + api.protocol: + valueType: STRING + request.auth.principal: + valueType: STRING + request.auth.audiences: + valueType: STRING + request.auth.presenter: + valueType: STRING + request.auth.claims: + valueType: STRING_MAP + request.auth.raw_claims: + valueType: STRING + request.api_key: + valueType: STRING + rbac.permissive.response_code: + valueType: STRING + rbac.permissive.effective_policy_id: + valueType: STRING + check.error_code: + valueType: INT64 + check.error_message: + valueType: STRING + check.cache_hit: + valueType: BOOL + quota.cache_hit: + valueType: BOOL + context.proxy_version: + valueType: STRING +--- +# Source: istio/charts/mixer/templates/config.yaml +apiVersion: "config.istio.io/v1alpha2" +kind: handler +metadata: + name: kubernetesenv + namespace: istio-system + labels: + app: mixer + chart: mixer + heritage: Helm + release: RELEASE-NAME +spec: + compiledAdapter: kubernetesenv + params: + # when running from mixer root, use the following config after adding a + # symbolic link to a kubernetes config file via: + # + # $ ln -s ~/.kube/config mixer/adapter/kubernetes/kubeconfig + # + # kubeconfig_path: "mixer/adapter/kubernetes/kubeconfig" +--- +# Source: istio/charts/mixer/templates/config.yaml +apiVersion: "config.istio.io/v1alpha2" +kind: instance +metadata: + name: attributes + namespace: istio-system + labels: + app: mixer + chart: mixer + heritage: Helm + release: RELEASE-NAME +spec: + compiledTemplate: kubernetes + params: + # Pass the required attribute data to the adapter + source_uid: source.uid | "" + source_ip: source.ip | ip("0.0.0.0") # default to unspecified ip addr + destination_uid: destination.uid | "" + destination_port: destination.port | 0 + attributeBindings: + # Fill the new attributes from the adapter produced output. + # $out refers to an instance of OutputTemplate message + source.ip: $out.source_pod_ip | ip("0.0.0.0") + source.uid: $out.source_pod_uid | "unknown" + source.labels: $out.source_labels | emptyStringMap() + source.name: $out.source_pod_name | "unknown" + source.namespace: $out.source_namespace | "default" + source.owner: $out.source_owner | "unknown" + source.serviceAccount: $out.source_service_account_name | "unknown" + source.workload.uid: $out.source_workload_uid | "unknown" + source.workload.name: $out.source_workload_name | "unknown" + source.workload.namespace: $out.source_workload_namespace | "unknown" + destination.ip: $out.destination_pod_ip | ip("0.0.0.0") + destination.uid: $out.destination_pod_uid | "unknown" + destination.labels: $out.destination_labels | emptyStringMap() + destination.name: $out.destination_pod_name | "unknown" + destination.container.name: $out.destination_container_name | "unknown" + destination.namespace: $out.destination_namespace | "default" + destination.owner: $out.destination_owner | "unknown" + destination.serviceAccount: $out.destination_service_account_name | "unknown" + destination.workload.uid: $out.destination_workload_uid | "unknown" + destination.workload.name: $out.destination_workload_name | "unknown" + destination.workload.namespace: $out.destination_workload_namespace | "unknown" +--- +# Source: istio/charts/mixer/templates/config.yaml +apiVersion: "config.istio.io/v1alpha2" +kind: rule +metadata: + name: kubeattrgenrulerule + namespace: istio-system + labels: + app: mixer + chart: mixer + heritage: Helm + release: RELEASE-NAME +spec: + actions: + - handler: kubernetesenv + instances: + - attributes +--- +# Source: istio/charts/mixer/templates/config.yaml +apiVersion: "config.istio.io/v1alpha2" +kind: rule +metadata: + name: tcpkubeattrgenrulerule + namespace: istio-system + labels: + app: mixer + chart: mixer + heritage: Helm + release: RELEASE-NAME +spec: + match: context.protocol == "tcp" + actions: + - handler: kubernetesenv + instances: + - attributes +--- +# Source: istio/charts/security/templates/create-custom-resources-job.yaml +apiVersion: batch/v1 +kind: Job +metadata: + name: istio-security-post-install-1.4.3 + namespace: istio-system + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-delete-policy": hook-succeeded + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME +spec: + template: + metadata: + name: istio-security-post-install + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: istio-security-post-install-account + containers: + - name: kubectl + image: "docker.io/istio/kubectl:1.4.3" + imagePullPolicy: IfNotPresent + command: [ "/bin/bash", "/tmp/security/run.sh", "/tmp/security/custom-resources.yaml" ] + volumeMounts: + - mountPath: "/tmp/security" + name: tmp-configmap-security + volumes: + - name: tmp-configmap-security + configMap: + name: istio-security-custom-resources + restartPolicy: OnFailure + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - "ppc64le" + - "s390x" + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "ppc64le" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "s390x" diff --git a/third_party/istio-1.4.3/istio-ci-no-mesh.yaml b/third_party/istio-1.4.3/istio-ci-no-mesh.yaml new file mode 100644 index 00000000000..c34600b382b --- /dev/null +++ b/third_party/istio-1.4.3/istio-ci-no-mesh.yaml @@ -0,0 +1,1738 @@ +--- +# PATCH #1: Creating the istio-system namespace. +apiVersion: v1 +kind: Namespace +metadata: + name: istio-system + labels: + istio-injection: disabled +# PATCH #1 ends. +--- +# Source: istio/charts/galley/templates/configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: istio-galley-configuration + namespace: istio-system + labels: + app: galley + chart: galley + heritage: Helm + release: RELEASE-NAME + istio: galley +data: + validatingwebhookconfiguration.yaml: |- + apiVersion: admissionregistration.k8s.io/v1beta1 + kind: ValidatingWebhookConfiguration + metadata: + name: istio-galley + labels: + app: galley + chart: galley + heritage: Helm + release: RELEASE-NAME + istio: galley + webhooks: + - name: pilot.validation.istio.io + clientConfig: + service: + name: istio-galley + namespace: istio-system + path: "/admitpilot" + caBundle: "" + rules: + - operations: + - CREATE + - UPDATE + apiGroups: + - config.istio.io + apiVersions: + - v1alpha2 + resources: + - httpapispecs + - httpapispecbindings + - quotaspecs + - quotaspecbindings + - operations: + - CREATE + - UPDATE + apiGroups: + - rbac.istio.io + apiVersions: + - "*" + resources: + - "*" + - operations: + - CREATE + - UPDATE + apiGroups: + - security.istio.io + apiVersions: + - "*" + resources: + - "*" + - operations: + - CREATE + - UPDATE + apiGroups: + - authentication.istio.io + apiVersions: + - "*" + resources: + - "*" + - operations: + - CREATE + - UPDATE + apiGroups: + - networking.istio.io + apiVersions: + - "*" + resources: + - destinationrules + - envoyfilters + - gateways + - serviceentries + - sidecars + - virtualservices + failurePolicy: Fail + sideEffects: None + - name: mixer.validation.istio.io + clientConfig: + service: + name: istio-galley + namespace: istio-system + path: "/admitmixer" + caBundle: "" + rules: + - operations: + - CREATE + - UPDATE + apiGroups: + - config.istio.io + apiVersions: + - v1alpha2 + resources: + - rules + - attributemanifests + - circonuses + - deniers + - fluentds + - kubernetesenvs + - listcheckers + - memquotas + - noops + - opas + - prometheuses + - rbacs + - solarwindses + - stackdrivers + - cloudwatches + - dogstatsds + - statsds + - stdios + - apikeys + - authorizations + - checknothings + # - kuberneteses + - listentries + - logentries + - metrics + - quotas + - reportnothings + - tracespans + - adapters + - handlers + - instances + - templates + - zipkins + failurePolicy: Fail + sideEffects: None +--- +# Source: istio/charts/security/templates/configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: istio-security-custom-resources + namespace: istio-system + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME + istio: citadel +data: + custom-resources.yaml: |- + # Authentication policy to enable permissive mode for all services (that have sidecar) in the mesh. + apiVersion: "authentication.istio.io/v1alpha1" + kind: "MeshPolicy" + metadata: + name: "default" + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME + spec: + peers: + - mtls: + mode: PERMISSIVE + run.sh: |- + #!/bin/sh + + set -x + + if [ "$#" -ne "1" ]; then + echo "first argument should be path to custom resource yaml" + exit 1 + fi + + pathToResourceYAML=${1} + + kubectl get validatingwebhookconfiguration istio-galley 2>/dev/null + if [ "$?" -eq 0 ]; then + echo "istio-galley validatingwebhookconfiguration found - waiting for istio-galley deployment to be ready" + while true; do + kubectl -n istio-system get deployment istio-galley 2>/dev/null + if [ "$?" -eq 0 ]; then + break + fi + sleep 1 + done + kubectl -n istio-system rollout status deployment istio-galley + if [ "$?" -ne 0 ]; then + echo "istio-galley deployment rollout status check failed" + exit 1 + fi + echo "istio-galley deployment ready for configuration validation" + fi + sleep 5 + kubectl apply -f ${pathToResourceYAML} +--- +# Source: istio/templates/configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: istio + namespace: istio-system + labels: + app: istio + chart: istio + heritage: Helm + release: RELEASE-NAME +data: + mesh: |- + # Set the following variable to true to disable policy checks by Mixer. + # Note that metrics will still be reported to Mixer. + disablePolicyChecks: true + + disableMixerHttpReports: false + # reportBatchMaxEntries is the number of requests that are batched before telemetry data is sent to the mixer server + reportBatchMaxEntries: 100 + # reportBatchMaxTime is the max waiting time before the telemetry data of a request is sent to the mixer server + reportBatchMaxTime: 1s + + # Set enableTracing to false to disable request tracing. + enableTracing: true + + # Set accessLogFile to empty string to disable access log. + accessLogFile: "/dev/stdout" + + # If accessLogEncoding is TEXT, value will be used directly as the log format + # example: "[%START_TIME%] %REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\n" + # If AccessLogEncoding is JSON, value will be parsed as map[string]string + # example: '{"start_time": "%START_TIME%", "req_method": "%REQ(:METHOD)%"}' + # Leave empty to use default log format + accessLogFormat: "" + + # Set accessLogEncoding to JSON or TEXT to configure sidecar access log + accessLogEncoding: 'JSON' + + enableEnvoyAccessLogService: false + # Let Pilot give ingresses the public IP of the Istio ingressgateway + ingressService: istio-ingressgateway + + # Default connect timeout for dynamic clusters generated by Pilot and returned via XDS + connectTimeout: 10s + + # Automatic protocol detection uses a set of heuristics to + # determine whether the connection is using TLS or not (on the + # server side), as well as the application protocol being used + # (e.g., http vs tcp). These heuristics rely on the client sending + # the first bits of data. For server first protocols like MySQL, + # MongoDB, etc., Envoy will timeout on the protocol detection after + # the specified period, defaulting to non mTLS plain TCP + # traffic. Set this field to tweak the period that Envoy will wait + # for the client to send the first bits of data. (MUST BE >=1ms) + protocolDetectionTimeout: 100ms + + # DNS refresh rate for Envoy clusters of type STRICT_DNS + dnsRefreshRate: 300s + + # Unix Domain Socket through which envoy communicates with NodeAgent SDS to get + # key/cert for mTLS. Use secret-mount files instead of SDS if set to empty. + sdsUdsPath: "" + + # The trust domain corresponds to the trust root of a system. + # Refer to https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE-ID.md#21-trust-domain + trustDomain: "" + + # The trust domain aliases represent the aliases of trust_domain. + # For example, if we have + # trustDomain: td1 + # trustDomainAliases: [“td2”, "td3"] + # Any service with the identity "td1/ns/foo/sa/a-service-account", "td2/ns/foo/sa/a-service-account", + # or "td3/ns/foo/sa/a-service-account" will be treated the same in the Istio mesh. + trustDomainAliases: + + # If true, automatically configure client side mTLS settings to match the corresponding service's + # server side mTLS authentication policy, when destination rule for that service does not specify + # TLS settings. + enableAutoMtls: false + + # Set the default behavior of the sidecar for handling outbound traffic from the application: + # ALLOW_ANY - outbound traffic to unknown destinations will be allowed, in case there are no + # services or ServiceEntries for the destination port + # REGISTRY_ONLY - restrict outbound traffic to services defined in the service registry as well + # as those defined through ServiceEntries + outboundTrafficPolicy: + mode: ALLOW_ANY + localityLbSetting: + enabled: true + # The namespace to treat as the administrative root namespace for istio + # configuration. + rootNamespace: istio-system + + # Configures DNS certificates provisioned through Chiron linked into Pilot. + certificates: + [] + + defaultConfig: + # + # TCP connection timeout between Envoy & the application, and between Envoys. Used for static clusters + # defined in Envoy's configuration file + connectTimeout: 10s + # + ### ADVANCED SETTINGS ############# + # Where should envoy's configuration be stored in the istio-proxy container + configPath: "/etc/istio/proxy" + binaryPath: "/usr/local/bin/envoy" + # The pseudo service name used for Envoy. + serviceCluster: istio-proxy + # These settings that determine how long an old Envoy + # process should be kept alive after an occasional reload. + drainDuration: 45s + parentShutdownDuration: 1m0s + # + # The mode used to redirect inbound connections to Envoy. This setting + # has no effect on outbound traffic: iptables REDIRECT is always used for + # outbound connections. + # If "REDIRECT", use iptables REDIRECT to NAT and redirect to Envoy. + # The "REDIRECT" mode loses source addresses during redirection. + # If "TPROXY", use iptables TPROXY to redirect to Envoy. + # The "TPROXY" mode preserves both the source and destination IP + # addresses and ports, so that they can be used for advanced filtering + # and manipulation. + # The "TPROXY" mode also configures the sidecar to run with the + # CAP_NET_ADMIN capability, which is required to use TPROXY. + #interceptionMode: REDIRECT + # + # Port where Envoy listens (on local host) for admin commands + # You can exec into the istio-proxy container in a pod and + # curl the admin port (curl http://localhost:15000/) to obtain + # diagnostic information from Envoy. See + # https://lyft.github.io/envoy/docs/operations/admin.html + # for more details + proxyAdminPort: 15000 + # + # Set concurrency to a specific number to control the number of Proxy worker threads. + # If set to 0 (default), then start worker thread for each CPU thread/core. + concurrency: 2 + # + tracing: + zipkin: + # Address of the Zipkin collector + address: zipkin.istio-system:9411 + # + # Mutual TLS authentication between sidecars and istio control plane. + controlPlaneAuthPolicy: NONE + # + # Address where istio Pilot service is running + discoveryAddress: istio-pilot.istio-system:15010 + + # Configuration file for the mesh networks to be used by the Split Horizon EDS. + meshNetworks: |- + networks: {} +--- +# Source: istio/charts/galley/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-galley-service-account + namespace: istio-system + labels: + app: galley + chart: galley + heritage: Helm + release: RELEASE-NAME +--- +# Source: istio/charts/gateways/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cluster-local-gateway-service-account + namespace: istio-system + labels: + app: cluster-local-gateway + chart: gateways + heritage: Helm + release: RELEASE-NAME +--- +# Source: istio/charts/gateways/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-ingressgateway-service-account + namespace: istio-system + labels: + app: istio-ingressgateway + chart: gateways + heritage: Helm + release: RELEASE-NAME +--- +# Source: istio/charts/pilot/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-pilot-service-account + namespace: istio-system + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME +--- +# Source: istio/charts/security/templates/create-custom-resources-job.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-security-post-install-account + namespace: istio-system + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME +--- +# Source: istio/charts/security/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-citadel-service-account + namespace: istio-system + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME +--- +# Source: istio/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-multi + namespace: istio-system +--- +# Source: istio/charts/galley/templates/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: istio-galley-istio-system + labels: + app: galley + chart: galley + heritage: Helm + release: RELEASE-NAME +rules: + # For reading Istio resources +- apiGroups: [ + "authentication.istio.io", + "config.istio.io", + "networking.istio.io", + "rbac.istio.io", + "security.istio.io"] + resources: ["*"] + verbs: ["get", "list", "watch"] + # For updating Istio resource statuses +- apiGroups: [ + "authentication.istio.io", + "config.istio.io", + "networking.istio.io", + "rbac.istio.io", + "security.istio.io"] + resources: ["*/status"] + verbs: ["update"] +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations"] + verbs: ["*"] +- apiGroups: ["extensions","apps"] + resources: ["deployments"] + resourceNames: ["istio-galley"] + verbs: ["get"] +- apiGroups: [""] + resources: ["pods", "nodes", "services", "endpoints", "namespaces"] + verbs: ["get", "list", "watch"] +- apiGroups: ["extensions"] + resources: ["ingresses"] + verbs: ["get", "list", "watch"] +- apiGroups: ["extensions"] + resources: ["deployments/finalizers"] + resourceNames: ["istio-galley"] + verbs: ["update"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch"] +--- +# Source: istio/charts/pilot/templates/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: istio-pilot-istio-system + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME +rules: +- apiGroups: ["config.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["rbac.istio.io"] + resources: ["*"] + verbs: ["get", "watch", "list"] +- apiGroups: ["security.istio.io"] + resources: ["*"] + verbs: ["get", "watch", "list"] +- apiGroups: ["networking.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["authentication.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["*"] +- apiGroups: ["extensions"] + resources: ["ingresses", "ingresses/status"] + verbs: ["*"] +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["create", "get", "list", "watch", "update"] +- apiGroups: [""] + resources: ["endpoints", "pods", "services", "namespaces", "nodes"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "get", "watch", "list", "update", "delete"] +- apiGroups: ["certificates.k8s.io"] + resources: + - "certificatesigningrequests" + - "certificatesigningrequests/approval" + - "certificatesigningrequests/status" + verbs: ["update", "create", "get", "delete"] +--- +# Source: istio/charts/security/templates/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: istio-citadel-istio-system + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME +rules: +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["create", "get", "update"] +- apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "get", "watch", "list", "update", "delete"] +- apiGroups: [""] + resources: ["serviceaccounts", "services", "namespaces"] + verbs: ["get", "watch", "list"] +- apiGroups: ["authentication.k8s.io"] + resources: ["tokenreviews"] + verbs: ["create"] +--- +# Source: istio/charts/security/templates/create-custom-resources-job.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: istio-security-post-install-istio-system + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME +rules: +- apiGroups: ["authentication.istio.io"] # needed to create default authn policy + resources: ["*"] + verbs: ["*"] +- apiGroups: ["networking.istio.io"] # needed to create security destination rules + resources: ["*"] + verbs: ["*"] +- apiGroups: ["admissionregistration.k8s.io"] + resources: ["validatingwebhookconfigurations"] + verbs: ["get"] +- apiGroups: ["extensions", "apps"] + resources: ["deployments", "replicasets"] + verbs: ["get", "list", "watch"] +--- +# Source: istio/templates/clusterrole.yaml +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: istio-reader +rules: + - apiGroups: [''] + resources: ['nodes', 'pods', 'services', 'endpoints', "replicationcontrollers"] + verbs: ['get', 'watch', 'list'] + - apiGroups: ["extensions", "apps"] + resources: ["replicasets"] + verbs: ["get", "list", "watch"] +--- +# Source: istio/charts/galley/templates/clusterrolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istio-galley-admin-role-binding-istio-system + labels: + app: galley + chart: galley + heritage: Helm + release: RELEASE-NAME +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-galley-istio-system +subjects: + - kind: ServiceAccount + name: istio-galley-service-account + namespace: istio-system +--- +# Source: istio/charts/pilot/templates/clusterrolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istio-pilot-istio-system + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-pilot-istio-system +subjects: + - kind: ServiceAccount + name: istio-pilot-service-account + namespace: istio-system +--- +# Source: istio/charts/security/templates/clusterrolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istio-citadel-istio-system + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-citadel-istio-system +subjects: + - kind: ServiceAccount + name: istio-citadel-service-account + namespace: istio-system +--- +# Source: istio/charts/security/templates/create-custom-resources-job.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istio-security-post-install-role-binding-istio-system + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-security-post-install-istio-system +subjects: + - kind: ServiceAccount + name: istio-security-post-install-account + namespace: istio-system +--- +# Source: istio/templates/clusterrolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istio-multi + labels: + chart: istio-1.4.3 +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-reader +subjects: +- kind: ServiceAccount + name: istio-multi + namespace: istio-system +--- +# Source: istio/charts/gateways/templates/role.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: istio-ingressgateway-sds + namespace: istio-system +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "watch", "list"] +--- +# Source: istio/charts/gateways/templates/rolebindings.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: istio-ingressgateway-sds + namespace: istio-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: istio-ingressgateway-sds +subjects: +- kind: ServiceAccount + name: istio-ingressgateway-service-account +--- +# Source: istio/charts/galley/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: istio-galley + namespace: istio-system + labels: + app: galley + chart: galley + heritage: Helm + release: RELEASE-NAME + istio: galley +spec: + ports: + - port: 443 + name: https-validation + - port: 15014 + name: http-monitoring + - port: 9901 + name: grpc-mcp + selector: + istio: galley +--- +# Source: istio/charts/gateways/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: cluster-local-gateway + namespace: istio-system + annotations: + labels: + chart: gateways + heritage: Helm + release: RELEASE-NAME + app: cluster-local-gateway + istio: cluster-local-gateway +spec: + type: ClusterIP + selector: + release: RELEASE-NAME + app: cluster-local-gateway + istio: cluster-local-gateway + ports: + - + name: status-port + port: 15020 + - + name: http2 + port: 80 + - + name: https + port: 443 +--- +# Source: istio/charts/gateways/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: istio-ingressgateway + namespace: istio-system + annotations: + labels: + chart: gateways + heritage: Helm + release: RELEASE-NAME + app: istio-ingressgateway + istio: ingressgateway +spec: + type: LoadBalancer + selector: + release: RELEASE-NAME + app: istio-ingressgateway + istio: ingressgateway + ports: + - + name: status-port + port: 15020 + - + name: http2 + port: 80 + - + name: https + port: 443 +--- +# Source: istio/charts/pilot/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: istio-pilot + namespace: istio-system + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME + istio: pilot +spec: + ports: + - port: 15010 + name: grpc-xds # direct + - port: 15011 + name: https-xds # mTLS + - port: 8080 + name: http-legacy-discovery # direct + - port: 15014 + name: http-monitoring + selector: + istio: pilot +--- +# Source: istio/charts/security/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + # we use the normal name here (e.g. 'prometheus') + # as grafana is configured to use this as a data source + name: istio-citadel + namespace: istio-system + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME + istio: citadel +spec: + ports: + - name: grpc-citadel + port: 8060 + targetPort: 8060 + protocol: TCP + - name: http-monitoring + port: 15014 + selector: + istio: citadel +--- +# Source: istio/charts/galley/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: istio-galley + namespace: istio-system + labels: + app: galley + chart: galley + heritage: Helm + release: RELEASE-NAME + istio: galley +spec: + replicas: 1 + selector: + matchLabels: + istio: galley + strategy: + rollingUpdate: + maxSurge: 100% + maxUnavailable: 25% + template: + metadata: + labels: + app: galley + chart: galley + heritage: Helm + release: RELEASE-NAME + istio: galley + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: istio-galley-service-account + containers: + - name: galley + image: "docker.io/istio/galley:1.4.3" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 443 + - containerPort: 15014 + - containerPort: 9901 + command: + - /usr/local/bin/galley + - server + - --meshConfigFile=/etc/mesh-config/mesh + - --livenessProbeInterval=1s + - --livenessProbePath=/healthliveness + - --readinessProbePath=/healthready + - --readinessProbeInterval=1s + - --deployment-namespace=istio-system + - --insecure=true + - --enable-server=false + - --enable-reconcileWebhookConfiguration=true + - --validation-webhook-config-file + - /etc/config/validatingwebhookconfiguration.yaml + - --monitoringPort=15014 + - --log_output_level=default:info + volumeMounts: + - name: certs + mountPath: /etc/certs + readOnly: true + - name: config + mountPath: /etc/config + readOnly: true + - name: mesh-config + mountPath: /etc/mesh-config + readOnly: true + livenessProbe: + exec: + command: + - /usr/local/bin/galley + - probe + - --probe-path=/healthliveness + - --interval=10s + initialDelaySeconds: 5 + periodSeconds: 5 + readinessProbe: + exec: + command: + - /usr/local/bin/galley + - probe + - --probe-path=/healthready + - --interval=10s + initialDelaySeconds: 5 + periodSeconds: 5 + resources: + requests: + cpu: 10m + volumes: + - name: certs + secret: + secretName: istio.istio-galley-service-account + - name: config + configMap: + name: istio-galley-configuration + - name: mesh-config + configMap: + name: istio + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - "ppc64le" + - "s390x" + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "ppc64le" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "s390x" +--- +# Source: istio/charts/gateways/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cluster-local-gateway + namespace: istio-system + labels: + app: cluster-local-gateway + chart: gateways + heritage: Helm + istio: cluster-local-gateway + release: RELEASE-NAME +spec: + replicas: 2 + selector: + matchLabels: + app: cluster-local-gateway + istio: cluster-local-gateway + strategy: + rollingUpdate: + maxSurge: + maxUnavailable: + template: + metadata: + labels: + app: cluster-local-gateway + chart: gateways + heritage: Helm + istio: cluster-local-gateway + release: RELEASE-NAME + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: cluster-local-gateway-service-account + containers: + - name: istio-proxy + image: "docker.io/istio/proxyv2:1.4.3" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 15020 + - containerPort: 80 + - containerPort: 443 + - containerPort: 15090 + protocol: TCP + name: http-envoy-prom + args: + - proxy + - router + - --domain + - $(POD_NAMESPACE).svc.cluster.local + - --log_output_level=default:info + - --drainDuration + - '45s' #drainDuration + - --parentShutdownDuration + - '1m0s' #parentShutdownDuration + - --connectTimeout + - '10s' #connectTimeout + - --serviceCluster + - cluster-local-gateway + - --zipkinAddress + - zipkin:9411 + - --proxyAdminPort + - "15000" + - --statusPort + - "15020" + - --controlPlaneAuthPolicy + - NONE + - --discoveryAddress + - istio-pilot:15010 + readinessProbe: + failureThreshold: 30 + httpGet: + path: /healthz/ready + port: 15020 + scheme: HTTP + initialDelaySeconds: 1 + periodSeconds: 2 + successThreshold: 1 + timeoutSeconds: 1 + resources: + requests: + cpu: 1000m + memory: 1024Mi + env: + - name: NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + - name: HOST_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + - name: SERVICE_ACCOUNT + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: ISTIO_META_CONFIG_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: ISTIO_METAJSON_LABELS + value: | + {"app":"cluster-local-gateway","chart":"gateways","heritage":"Helm","istio":"cluster-local-gateway","release":"RELEASE-NAME"} + - name: ISTIO_META_CLUSTER_ID + value: "Kubernetes" + - name: SDS_ENABLED + value: "false" + - name: ISTIO_META_WORKLOAD_NAME + value: cluster-local-gateway + - name: ISTIO_META_OWNER + value: kubernetes://apis/apps/v1/namespaces/istio-system/deployments/cluster-local-gateway + + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: cluster-local-gateway-certs + mountPath: "/etc/istio/cluster-local-gateway-certs" + readOnly: true + - name: cluster-local-gateway-ca-certs + mountPath: "/etc/istio/cluster-local-gateway-ca-certs" + readOnly: true + volumes: + - name: istio-certs + secret: + secretName: istio.cluster-local-gateway-service-account + optional: true + - name: cluster-local-gateway-certs + secret: + secretName: "istio-cluster-local-gateway-certs" + optional: true + - name: cluster-local-gateway-ca-certs + secret: + secretName: "istio-cluster-local-gateway-ca-certs" + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - "ppc64le" + - "s390x" + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "ppc64le" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "s390x" +--- +# Source: istio/charts/gateways/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: istio-ingressgateway + namespace: istio-system + labels: + app: istio-ingressgateway + chart: gateways + heritage: Helm + istio: ingressgateway + release: RELEASE-NAME +spec: + selector: + matchLabels: + app: istio-ingressgateway + istio: ingressgateway + strategy: + rollingUpdate: + maxSurge: 100% + maxUnavailable: 25% + template: + metadata: + labels: + app: istio-ingressgateway + chart: gateways + heritage: Helm + istio: ingressgateway + release: RELEASE-NAME + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: istio-ingressgateway-service-account + containers: + - name: ingress-sds + image: "docker.io/istio/node-agent-k8s:1.4.3" + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 2000m + memory: 1024Mi + requests: + cpu: 100m + memory: 128Mi + env: + - name: "ENABLE_WORKLOAD_SDS" + value: "false" + - name: "ENABLE_INGRESS_GATEWAY_SDS" + value: "true" + - name: "INGRESS_GATEWAY_NAMESPACE" + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + volumeMounts: + - name: ingressgatewaysdsudspath + mountPath: /var/run/ingress_gateway + - name: istio-proxy + image: "docker.io/istio/proxyv2:1.4.3" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 15020 + - containerPort: 80 + - containerPort: 443 + - containerPort: 15090 + protocol: TCP + name: http-envoy-prom + args: + - proxy + - router + - --domain + - $(POD_NAMESPACE).svc.cluster.local + - --log_output_level=default:info + - --drainDuration + - '45s' #drainDuration + - --parentShutdownDuration + - '1m0s' #parentShutdownDuration + - --connectTimeout + - '10s' #connectTimeout + - --serviceCluster + - istio-ingressgateway + - --zipkinAddress + - zipkin:9411 + - --proxyAdminPort + - "15000" + - --statusPort + - "15020" + - --controlPlaneAuthPolicy + - NONE + - --discoveryAddress + - istio-pilot:15010 + readinessProbe: + failureThreshold: 30 + httpGet: + path: /healthz/ready + port: 15020 + scheme: HTTP + initialDelaySeconds: 1 + periodSeconds: 2 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + cpu: 2000m + memory: 1024Mi + requests: + cpu: 1000m + memory: 1024Mi + env: + - name: NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + - name: HOST_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + - name: SERVICE_ACCOUNT + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: ISTIO_META_CONFIG_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: ISTIO_METAJSON_LABELS + value: | + {"app":"istio-ingressgateway","chart":"gateways","heritage":"Helm","istio":"ingressgateway","release":"RELEASE-NAME"} + - name: ISTIO_META_CLUSTER_ID + value: "Kubernetes" + - name: SDS_ENABLED + value: "false" + - name: ISTIO_META_WORKLOAD_NAME + value: istio-ingressgateway + - name: ISTIO_META_OWNER + value: kubernetes://apis/apps/v1/namespaces/istio-system/deployments/istio-ingressgateway + - name: ISTIO_META_USER_SDS + value: "true" + - name: ISTIO_META_ROUTER_MODE + value: sni-dnat + + + volumeMounts: + - name: ingressgatewaysdsudspath + mountPath: /var/run/ingress_gateway + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: ingressgateway-certs + mountPath: "/etc/istio/ingressgateway-certs" + readOnly: true + - name: ingressgateway-ca-certs + mountPath: "/etc/istio/ingressgateway-ca-certs" + readOnly: true + volumes: + - name: ingressgatewaysdsudspath + emptyDir: {} + - name: istio-certs + secret: + secretName: istio.istio-ingressgateway-service-account + optional: true + - name: ingressgateway-certs + secret: + secretName: "istio-ingressgateway-certs" + optional: true + - name: ingressgateway-ca-certs + secret: + secretName: "istio-ingressgateway-ca-certs" + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - "ppc64le" + - "s390x" + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "ppc64le" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "s390x" +--- +# Source: istio/charts/pilot/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: istio-pilot + namespace: istio-system + # TODO: default template doesn't have this, which one is right ? + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME + istio: pilot +spec: + strategy: + rollingUpdate: + maxSurge: 100% + maxUnavailable: 25% + selector: + matchLabels: + istio: pilot + template: + metadata: + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME + istio: pilot + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: istio-pilot-service-account + containers: + - name: discovery + image: "docker.io/istio/pilot:1.4.3" + imagePullPolicy: IfNotPresent + args: + - "discovery" + - --monitoringAddr=:15014 + - --log_output_level=default:info + - --domain + - cluster.local + - --secureGrpcAddr + - "" + - --keepaliveMaxServerConnectionAge + - "30m" + ports: + - containerPort: 8080 + - containerPort: 15010 + - containerPort: 15011 + readinessProbe: + httpGet: + path: /ready + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 5 + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: PILOT_PUSH_THROTTLE + value: "100" + - name: PILOT_TRACE_SAMPLING + value: "100" + - name: PILOT_ENABLE_PROTOCOL_SNIFFING_FOR_OUTBOUND + value: "true" + - name: PILOT_ENABLE_PROTOCOL_SNIFFING_FOR_INBOUND + value: "false" + resources: + requests: + cpu: 1000m + memory: 1024Mi + volumeMounts: + - name: config-volume + mountPath: /etc/istio/config + - name: istio-certs + mountPath: /etc/certs + readOnly: true + volumes: + - name: config-volume + configMap: + name: istio + - name: istio-certs + secret: + secretName: istio.istio-pilot-service-account + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - "ppc64le" + - "s390x" + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "ppc64le" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "s390x" +--- +# Source: istio/charts/security/templates/deployment.yaml +# istio CA watching all namespaces +apiVersion: apps/v1 +kind: Deployment +metadata: + name: istio-citadel + namespace: istio-system + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME + istio: citadel +spec: + replicas: 1 + selector: + matchLabels: + istio: citadel + strategy: + rollingUpdate: + maxSurge: 100% + maxUnavailable: 25% + template: + metadata: + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME + istio: citadel + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: istio-citadel-service-account + containers: + - name: citadel + image: "docker.io/istio/citadel:1.4.3" + imagePullPolicy: IfNotPresent + args: + - --append-dns-names=true + - --grpc-port=8060 + - --citadel-storage-namespace=istio-system + - --custom-dns-names=istio-pilot-service-account.istio-system:istio-pilot.istio-system + - --monitoring-port=15014 + - --self-signed-ca=true + - --workload-cert-ttl=2160h + env: + - name: CITADEL_ENABLE_NAMESPACES_BY_DEFAULT + value: "true" + resources: + requests: + cpu: 10m + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - "ppc64le" + - "s390x" + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "ppc64le" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "s390x" +--- +# Source: istio/charts/gateways/templates/autoscale.yaml +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: istio-ingressgateway + namespace: istio-system + labels: + chart: gateways + heritage: Helm + release: RELEASE-NAME + app: istio-ingressgateway + istio: ingressgateway +spec: + maxReplicas: 5 + minReplicas: 2 + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: istio-ingressgateway + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: 80 +--- +# Source: istio/charts/pilot/templates/autoscale.yaml +apiVersion: autoscaling/v2beta1 +kind: HorizontalPodAutoscaler +metadata: + name: istio-pilot + namespace: istio-system + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME +spec: + maxReplicas: 5 + minReplicas: 1 + scaleTargetRef: + apiVersion: apps/v1 + kind: Deployment + name: istio-pilot + metrics: + - type: Resource + resource: + name: cpu + targetAverageUtilization: 80 +--- +# Source: istio/charts/security/templates/create-custom-resources-job.yaml +apiVersion: batch/v1 +kind: Job +metadata: + name: istio-security-post-install-1.4.3 + namespace: istio-system + annotations: + "helm.sh/hook": post-install,post-upgrade + "helm.sh/hook-delete-policy": hook-succeeded + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME +spec: + template: + metadata: + name: istio-security-post-install + labels: + app: security + chart: security + heritage: Helm + release: RELEASE-NAME + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: istio-security-post-install-account + containers: + - name: kubectl + image: "docker.io/istio/kubectl:1.4.3" + imagePullPolicy: IfNotPresent + command: [ "/bin/bash", "/tmp/security/run.sh", "/tmp/security/custom-resources.yaml" ] + volumeMounts: + - mountPath: "/tmp/security" + name: tmp-configmap-security + volumes: + - name: tmp-configmap-security + configMap: + name: istio-security-custom-resources + restartPolicy: OnFailure + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - "ppc64le" + - "s390x" + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "ppc64le" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "s390x" diff --git a/third_party/istio-1.4.3/istio-crds.yaml b/third_party/istio-1.4.3/istio-crds.yaml new file mode 100644 index 00000000000..7dc6559fa82 --- /dev/null +++ b/third_party/istio-1.4.3/istio-crds.yaml @@ -0,0 +1,5255 @@ +--- +# PATCH #1: Creating the istio-system namespace. +apiVersion: v1 +kind: Namespace +metadata: + name: istio-system + labels: + istio-injection: disabled +# PATCH #1 ends. +--- +# Source: istio-init/templates/configmap-crd-10.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: istio-system + name: istio-crd-10 +data: + crd-10.yaml: |- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: mixer + chart: istio + heritage: Tiller + istio: core + package: istio.io.mixer + release: istio + name: attributemanifests.config.istio.io + spec: + group: config.istio.io + names: + categories: + - istio-io + - policy-istio-io + kind: attributemanifest + plural: attributemanifests + singular: attributemanifest + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Describes the rules used to configure Mixer''s policy and + telemetry features. See more details at: https://istio.io/docs/reference/config/policy-and-telemetry/istio.policy.v1beta1.html' + properties: + attributes: + additionalProperties: + properties: + description: + description: A human-readable description of the attribute's purpose. + format: string + type: string + valueType: + description: The type of data carried by this attribute. + enum: + - VALUE_TYPE_UNSPECIFIED + - STRING + - INT64 + - DOUBLE + - BOOL + - TIMESTAMP + - IP_ADDRESS + - EMAIL_ADDRESS + - URI + - DNS_NAME + - DURATION + - STRING_MAP + type: string + type: object + description: The set of attributes this Istio component will be responsible + for producing at runtime. + type: object + name: + description: Name of the component producing these attributes. + format: string + type: string + revision: + description: The revision of this document. + format: string + type: string + type: object + type: object + versions: + - name: v1alpha2 + served: true + storage: true + + --- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-pilot + heritage: Tiller + istio: rbac + release: istio + name: clusterrbacconfigs.rbac.istio.io + spec: + group: rbac.istio.io + names: + categories: + - istio-io + - rbac-istio-io + kind: ClusterRbacConfig + plural: clusterrbacconfigs + singular: clusterrbacconfig + scope: Cluster + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Configuration for Role Based Access Control. See more details + at: https://istio.io/docs/reference/config/authorization/istio.rbac.v1alpha1.html' + properties: + enforcementMode: + enum: + - ENFORCED + - PERMISSIVE + type: string + exclusion: + description: A list of services or namespaces that should not be enforced + by Istio RBAC policies. + properties: + namespaces: + description: A list of namespaces. + items: + format: string + type: string + type: array + services: + description: A list of services. + items: + format: string + type: string + type: array + type: object + inclusion: + description: A list of services or namespaces that should be enforced + by Istio RBAC policies. + properties: + namespaces: + description: A list of namespaces. + items: + format: string + type: string + type: array + services: + description: A list of services. + items: + format: string + type: string + type: array + type: object + mode: + description: Istio RBAC mode. + enum: + - "OFF" + - "ON" + - ON_WITH_INCLUSION + - ON_WITH_EXCLUSION + type: string + type: object + type: object + versions: + - name: v1alpha1 + served: true + storage: true + + --- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-pilot + chart: istio + heritage: Tiller + release: istio + name: destinationrules.networking.istio.io + spec: + additionalPrinterColumns: + - JSONPath: .spec.host + description: The name of a service from the service registry + name: Host + type: string + - JSONPath: .metadata.creationTimestamp + description: |- + CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + name: Age + type: date + group: networking.istio.io + names: + categories: + - istio-io + - networking-istio-io + kind: DestinationRule + listKind: DestinationRuleList + plural: destinationrules + shortNames: + - dr + singular: destinationrule + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Configuration affecting load balancing, outlier detection, + etc. See more details at: https://istio.io/docs/reference/config/networking/v1alpha3/destination-rule.html' + properties: + exportTo: + description: A list of namespaces to which this destination rule is + exported. + items: + format: string + type: string + type: array + host: + description: The name of a service from the service registry. + format: string + type: string + subsets: + items: + properties: + labels: + additionalProperties: + format: string + type: string + type: object + name: + description: Name of the subset. + format: string + type: string + trafficPolicy: + description: Traffic policies that apply to this subset. + properties: + connectionPool: + properties: + http: + description: HTTP connection pool settings. + properties: + h2UpgradePolicy: + description: Specify if http1.1 connection should + be upgraded to http2 for the associated destination. + enum: + - DEFAULT + - DO_NOT_UPGRADE + - UPGRADE + type: string + http1MaxPendingRequests: + description: Maximum number of pending HTTP requests + to a destination. + format: int32 + type: integer + http2MaxRequests: + description: Maximum number of requests to a backend. + format: int32 + type: integer + idleTimeout: + description: The idle timeout for upstream connection + pool connections. + type: string + maxRequestsPerConnection: + description: Maximum number of requests per connection + to a backend. + format: int32 + type: integer + maxRetries: + format: int32 + type: integer + type: object + tcp: + description: Settings common to both HTTP and TCP upstream + connections. + properties: + connectTimeout: + description: TCP connection timeout. + type: string + maxConnections: + description: Maximum number of HTTP1 /TCP connections + to a destination host. + format: int32 + type: integer + tcpKeepalive: + description: If set then set SO_KEEPALIVE on the socket + to enable TCP Keepalives. + properties: + interval: + description: The time duration between keep-alive + probes. + type: string + probes: + type: integer + time: + type: string + type: object + type: object + type: object + loadBalancer: + description: Settings controlling the load balancer algorithms. + oneOf: + - required: + - simple + - properties: + consistentHash: + oneOf: + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + required: + - consistentHash + properties: + consistentHash: + properties: + httpCookie: + description: Hash based on HTTP cookie. + properties: + name: + description: Name of the cookie. + format: string + type: string + path: + description: Path to set for the cookie. + format: string + type: string + ttl: + description: Lifetime of the cookie. + type: string + type: object + httpHeaderName: + description: Hash based on a specific HTTP header. + format: string + type: string + minimumRingSize: + type: integer + useSourceIp: + description: Hash based on the source IP address. + type: boolean + type: object + simple: + enum: + - ROUND_ROBIN + - LEAST_CONN + - RANDOM + - PASSTHROUGH + type: string + type: object + outlierDetection: + properties: + baseEjectionTime: + description: Minimum ejection duration. + type: string + consecutiveErrors: + format: int32 + type: integer + interval: + description: Time interval between ejection sweep analysis. + type: string + maxEjectionPercent: + format: int32 + type: integer + minHealthPercent: + format: int32 + type: integer + type: object + portLevelSettings: + description: Traffic policies specific to individual ports. + items: + properties: + connectionPool: + properties: + http: + description: HTTP connection pool settings. + properties: + h2UpgradePolicy: + description: Specify if http1.1 connection should + be upgraded to http2 for the associated destination. + enum: + - DEFAULT + - DO_NOT_UPGRADE + - UPGRADE + type: string + http1MaxPendingRequests: + description: Maximum number of pending HTTP + requests to a destination. + format: int32 + type: integer + http2MaxRequests: + description: Maximum number of requests to a + backend. + format: int32 + type: integer + idleTimeout: + description: The idle timeout for upstream connection + pool connections. + type: string + maxRequestsPerConnection: + description: Maximum number of requests per + connection to a backend. + format: int32 + type: integer + maxRetries: + format: int32 + type: integer + type: object + tcp: + description: Settings common to both HTTP and TCP + upstream connections. + properties: + connectTimeout: + description: TCP connection timeout. + type: string + maxConnections: + description: Maximum number of HTTP1 /TCP connections + to a destination host. + format: int32 + type: integer + tcpKeepalive: + description: If set then set SO_KEEPALIVE on + the socket to enable TCP Keepalives. + properties: + interval: + description: The time duration between keep-alive + probes. + type: string + probes: + type: integer + time: + type: string + type: object + type: object + type: object + loadBalancer: + description: Settings controlling the load balancer + algorithms. + oneOf: + - required: + - simple + - properties: + consistentHash: + oneOf: + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + required: + - consistentHash + properties: + consistentHash: + properties: + httpCookie: + description: Hash based on HTTP cookie. + properties: + name: + description: Name of the cookie. + format: string + type: string + path: + description: Path to set for the cookie. + format: string + type: string + ttl: + description: Lifetime of the cookie. + type: string + type: object + httpHeaderName: + description: Hash based on a specific HTTP header. + format: string + type: string + minimumRingSize: + type: integer + useSourceIp: + description: Hash based on the source IP address. + type: boolean + type: object + simple: + enum: + - ROUND_ROBIN + - LEAST_CONN + - RANDOM + - PASSTHROUGH + type: string + type: object + outlierDetection: + properties: + baseEjectionTime: + description: Minimum ejection duration. + type: string + consecutiveErrors: + format: int32 + type: integer + interval: + description: Time interval between ejection sweep + analysis. + type: string + maxEjectionPercent: + format: int32 + type: integer + minHealthPercent: + format: int32 + type: integer + type: object + port: + properties: + number: + type: integer + type: object + tls: + description: TLS related settings for connections to + the upstream service. + properties: + caCertificates: + format: string + type: string + clientCertificate: + description: REQUIRED if mode is `MUTUAL`. + format: string + type: string + mode: + enum: + - DISABLE + - SIMPLE + - MUTUAL + - ISTIO_MUTUAL + type: string + privateKey: + description: REQUIRED if mode is `MUTUAL`. + format: string + type: string + sni: + description: SNI string to present to the server + during TLS handshake. + format: string + type: string + subjectAltNames: + items: + format: string + type: string + type: array + type: object + type: object + type: array + tls: + description: TLS related settings for connections to the upstream + service. + properties: + caCertificates: + format: string + type: string + clientCertificate: + description: REQUIRED if mode is `MUTUAL`. + format: string + type: string + mode: + enum: + - DISABLE + - SIMPLE + - MUTUAL + - ISTIO_MUTUAL + type: string + privateKey: + description: REQUIRED if mode is `MUTUAL`. + format: string + type: string + sni: + description: SNI string to present to the server during + TLS handshake. + format: string + type: string + subjectAltNames: + items: + format: string + type: string + type: array + type: object + type: object + type: object + type: array + trafficPolicy: + properties: + connectionPool: + properties: + http: + description: HTTP connection pool settings. + properties: + h2UpgradePolicy: + description: Specify if http1.1 connection should be upgraded + to http2 for the associated destination. + enum: + - DEFAULT + - DO_NOT_UPGRADE + - UPGRADE + type: string + http1MaxPendingRequests: + description: Maximum number of pending HTTP requests to + a destination. + format: int32 + type: integer + http2MaxRequests: + description: Maximum number of requests to a backend. + format: int32 + type: integer + idleTimeout: + description: The idle timeout for upstream connection pool + connections. + type: string + maxRequestsPerConnection: + description: Maximum number of requests per connection to + a backend. + format: int32 + type: integer + maxRetries: + format: int32 + type: integer + type: object + tcp: + description: Settings common to both HTTP and TCP upstream connections. + properties: + connectTimeout: + description: TCP connection timeout. + type: string + maxConnections: + description: Maximum number of HTTP1 /TCP connections to + a destination host. + format: int32 + type: integer + tcpKeepalive: + description: If set then set SO_KEEPALIVE on the socket + to enable TCP Keepalives. + properties: + interval: + description: The time duration between keep-alive probes. + type: string + probes: + type: integer + time: + type: string + type: object + type: object + type: object + loadBalancer: + description: Settings controlling the load balancer algorithms. + oneOf: + - required: + - simple + - properties: + consistentHash: + oneOf: + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + required: + - consistentHash + properties: + consistentHash: + properties: + httpCookie: + description: Hash based on HTTP cookie. + properties: + name: + description: Name of the cookie. + format: string + type: string + path: + description: Path to set for the cookie. + format: string + type: string + ttl: + description: Lifetime of the cookie. + type: string + type: object + httpHeaderName: + description: Hash based on a specific HTTP header. + format: string + type: string + minimumRingSize: + type: integer + useSourceIp: + description: Hash based on the source IP address. + type: boolean + type: object + simple: + enum: + - ROUND_ROBIN + - LEAST_CONN + - RANDOM + - PASSTHROUGH + type: string + type: object + outlierDetection: + properties: + baseEjectionTime: + description: Minimum ejection duration. + type: string + consecutiveErrors: + format: int32 + type: integer + interval: + description: Time interval between ejection sweep analysis. + type: string + maxEjectionPercent: + format: int32 + type: integer + minHealthPercent: + format: int32 + type: integer + type: object + portLevelSettings: + description: Traffic policies specific to individual ports. + items: + properties: + connectionPool: + properties: + http: + description: HTTP connection pool settings. + properties: + h2UpgradePolicy: + description: Specify if http1.1 connection should + be upgraded to http2 for the associated destination. + enum: + - DEFAULT + - DO_NOT_UPGRADE + - UPGRADE + type: string + http1MaxPendingRequests: + description: Maximum number of pending HTTP requests + to a destination. + format: int32 + type: integer + http2MaxRequests: + description: Maximum number of requests to a backend. + format: int32 + type: integer + idleTimeout: + description: The idle timeout for upstream connection + pool connections. + type: string + maxRequestsPerConnection: + description: Maximum number of requests per connection + to a backend. + format: int32 + type: integer + maxRetries: + format: int32 + type: integer + type: object + tcp: + description: Settings common to both HTTP and TCP upstream + connections. + properties: + connectTimeout: + description: TCP connection timeout. + type: string + maxConnections: + description: Maximum number of HTTP1 /TCP connections + to a destination host. + format: int32 + type: integer + tcpKeepalive: + description: If set then set SO_KEEPALIVE on the socket + to enable TCP Keepalives. + properties: + interval: + description: The time duration between keep-alive + probes. + type: string + probes: + type: integer + time: + type: string + type: object + type: object + type: object + loadBalancer: + description: Settings controlling the load balancer algorithms. + oneOf: + - required: + - simple + - properties: + consistentHash: + oneOf: + - required: + - httpHeaderName + - required: + - httpCookie + - required: + - useSourceIp + required: + - consistentHash + properties: + consistentHash: + properties: + httpCookie: + description: Hash based on HTTP cookie. + properties: + name: + description: Name of the cookie. + format: string + type: string + path: + description: Path to set for the cookie. + format: string + type: string + ttl: + description: Lifetime of the cookie. + type: string + type: object + httpHeaderName: + description: Hash based on a specific HTTP header. + format: string + type: string + minimumRingSize: + type: integer + useSourceIp: + description: Hash based on the source IP address. + type: boolean + type: object + simple: + enum: + - ROUND_ROBIN + - LEAST_CONN + - RANDOM + - PASSTHROUGH + type: string + type: object + outlierDetection: + properties: + baseEjectionTime: + description: Minimum ejection duration. + type: string + consecutiveErrors: + format: int32 + type: integer + interval: + description: Time interval between ejection sweep analysis. + type: string + maxEjectionPercent: + format: int32 + type: integer + minHealthPercent: + format: int32 + type: integer + type: object + port: + properties: + number: + type: integer + type: object + tls: + description: TLS related settings for connections to the upstream + service. + properties: + caCertificates: + format: string + type: string + clientCertificate: + description: REQUIRED if mode is `MUTUAL`. + format: string + type: string + mode: + enum: + - DISABLE + - SIMPLE + - MUTUAL + - ISTIO_MUTUAL + type: string + privateKey: + description: REQUIRED if mode is `MUTUAL`. + format: string + type: string + sni: + description: SNI string to present to the server during + TLS handshake. + format: string + type: string + subjectAltNames: + items: + format: string + type: string + type: array + type: object + type: object + type: array + tls: + description: TLS related settings for connections to the upstream + service. + properties: + caCertificates: + format: string + type: string + clientCertificate: + description: REQUIRED if mode is `MUTUAL`. + format: string + type: string + mode: + enum: + - DISABLE + - SIMPLE + - MUTUAL + - ISTIO_MUTUAL + type: string + privateKey: + description: REQUIRED if mode is `MUTUAL`. + format: string + type: string + sni: + description: SNI string to present to the server during TLS + handshake. + format: string + type: string + subjectAltNames: + items: + format: string + type: string + type: array + type: object + type: object + type: object + type: object + versions: + - name: v1alpha3 + served: true + storage: true + + --- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-pilot + chart: istio + heritage: Tiller + release: istio + name: envoyfilters.networking.istio.io + spec: + group: networking.istio.io + names: + categories: + - istio-io + - networking-istio-io + kind: EnvoyFilter + plural: envoyfilters + singular: envoyfilter + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Customizing Envoy configuration generated by Istio. See more + details at: https://istio.io/docs/reference/config/networking/v1alpha3/envoy-filter.html' + properties: + configPatches: + description: One or more patches with match conditions. + items: + properties: + applyTo: + enum: + - INVALID + - LISTENER + - FILTER_CHAIN + - NETWORK_FILTER + - HTTP_FILTER + - ROUTE_CONFIGURATION + - VIRTUAL_HOST + - HTTP_ROUTE + - CLUSTER + type: string + match: + description: Match on listener/route configuration/cluster. + oneOf: + - required: + - listener + - required: + - routeConfiguration + - required: + - cluster + properties: + cluster: + description: Match on envoy cluster attributes. + properties: + name: + description: The exact name of the cluster to match. + format: string + type: string + portNumber: + description: The service port for which this cluster was + generated. + type: integer + service: + description: The fully qualified service name for this + cluster. + format: string + type: string + subset: + description: The subset associated with the service. + format: string + type: string + type: object + context: + description: The specific config generation context to match + on. + enum: + - ANY + - SIDECAR_INBOUND + - SIDECAR_OUTBOUND + - GATEWAY + type: string + listener: + description: Match on envoy listener attributes. + properties: + filterChain: + description: Match a specific filter chain in a listener. + properties: + applicationProtocols: + description: Applies only to sidecars. + format: string + type: string + filter: + description: The name of a specific filter to apply + the patch to. + properties: + name: + description: The filter name to match on. + format: string + type: string + subFilter: + properties: + name: + description: The filter name to match on. + format: string + type: string + type: object + type: object + name: + description: The name assigned to the filter chain. + format: string + type: string + sni: + description: The SNI value used by a filter chain's + match condition. + format: string + type: string + transportProtocol: + description: Applies only to SIDECAR_INBOUND context. + format: string + type: string + type: object + name: + description: Match a specific listener by its name. + format: string + type: string + portName: + format: string + type: string + portNumber: + type: integer + type: object + proxy: + description: Match on properties associated with a proxy. + properties: + metadata: + additionalProperties: + format: string + type: string + type: object + proxyVersion: + format: string + type: string + type: object + routeConfiguration: + description: Match on envoy HTTP route configuration attributes. + properties: + gateway: + format: string + type: string + name: + description: Route configuration name to match on. + format: string + type: string + portName: + description: Applicable only for GATEWAY context. + format: string + type: string + portNumber: + type: integer + vhost: + properties: + name: + format: string + type: string + route: + description: Match a specific route within the virtual + host. + properties: + action: + description: Match a route with specific action + type. + enum: + - ANY + - ROUTE + - REDIRECT + - DIRECT_RESPONSE + type: string + name: + format: string + type: string + type: object + type: object + type: object + type: object + patch: + description: The patch to apply along with the operation. + properties: + operation: + description: Determines how the patch should be applied. + enum: + - INVALID + - MERGE + - ADD + - REMOVE + - INSERT_BEFORE + - INSERT_AFTER + type: string + value: + description: The JSON config of the object being patched. + type: object + type: object + type: object + type: array + filters: + items: + properties: + filterConfig: + type: object + filterName: + description: The name of the filter to instantiate. + format: string + type: string + filterType: + description: The type of filter to instantiate. + enum: + - INVALID + - HTTP + - NETWORK + type: string + insertPosition: + description: Insert position in the filter chain. + properties: + index: + description: Position of this filter in the filter chain. + enum: + - FIRST + - LAST + - BEFORE + - AFTER + type: string + relativeTo: + format: string + type: string + type: object + listenerMatch: + properties: + address: + description: One or more IP addresses to which the listener + is bound. + items: + format: string + type: string + type: array + listenerProtocol: + description: Selects a class of listeners for the same protocol. + enum: + - ALL + - HTTP + - TCP + type: string + listenerType: + description: Inbound vs outbound sidecar listener or gateway + listener. + enum: + - ANY + - SIDECAR_INBOUND + - SIDECAR_OUTBOUND + - GATEWAY + type: string + portNamePrefix: + format: string + type: string + portNumber: + type: integer + type: object + type: object + type: array + workloadLabels: + additionalProperties: + format: string + type: string + description: Deprecated. + type: object + workloadSelector: + properties: + labels: + additionalProperties: + format: string + type: string + type: object + type: object + type: object + type: object + versions: + - name: v1alpha3 + served: true + storage: true + + --- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-pilot + chart: istio + heritage: Tiller + release: istio + name: gateways.networking.istio.io + spec: + group: networking.istio.io + names: + categories: + - istio-io + - networking-istio-io + kind: Gateway + plural: gateways + shortNames: + - gw + singular: gateway + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Configuration affecting edge load balancer. See more details + at: https://istio.io/docs/reference/config/networking/v1alpha3/gateway.html' + properties: + selector: + additionalProperties: + format: string + type: string + type: object + servers: + description: A list of server specifications. + items: + properties: + bind: + format: string + type: string + defaultEndpoint: + format: string + type: string + hosts: + description: One or more hosts exposed by this gateway. + items: + format: string + type: string + type: array + port: + properties: + name: + description: Label assigned to the port. + format: string + type: string + number: + description: A valid non-negative integer port number. + type: integer + protocol: + description: The protocol exposed on the port. + format: string + type: string + type: object + tls: + description: Set of TLS related options that govern the server's + behavior. + properties: + caCertificates: + description: REQUIRED if mode is `MUTUAL`. + format: string + type: string + cipherSuites: + description: 'Optional: If specified, only support the specified + cipher list.' + items: + format: string + type: string + type: array + credentialName: + format: string + type: string + httpsRedirect: + type: boolean + maxProtocolVersion: + description: 'Optional: Maximum TLS protocol version.' + enum: + - TLS_AUTO + - TLSV1_0 + - TLSV1_1 + - TLSV1_2 + - TLSV1_3 + type: string + minProtocolVersion: + description: 'Optional: Minimum TLS protocol version.' + enum: + - TLS_AUTO + - TLSV1_0 + - TLSV1_1 + - TLSV1_2 + - TLSV1_3 + type: string + mode: + enum: + - PASSTHROUGH + - SIMPLE + - MUTUAL + - AUTO_PASSTHROUGH + - ISTIO_MUTUAL + type: string + privateKey: + description: REQUIRED if mode is `SIMPLE` or `MUTUAL`. + format: string + type: string + serverCertificate: + description: REQUIRED if mode is `SIMPLE` or `MUTUAL`. + format: string + type: string + subjectAltNames: + items: + format: string + type: string + type: array + verifyCertificateHash: + items: + format: string + type: string + type: array + verifyCertificateSpki: + items: + format: string + type: string + type: array + type: object + type: object + type: array + type: object + type: object + versions: + - name: v1alpha3 + served: true + storage: true + + --- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-mixer + chart: istio + heritage: Tiller + release: istio + name: httpapispecbindings.config.istio.io + spec: + group: config.istio.io + names: + categories: + - istio-io + - apim-istio-io + kind: HTTPAPISpecBinding + plural: httpapispecbindings + singular: httpapispecbinding + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + properties: + api_specs: + items: + properties: + name: + description: The short name of the HTTPAPISpec. + format: string + type: string + namespace: + description: Optional namespace of the HTTPAPISpec. + format: string + type: string + type: object + type: array + apiSpecs: + items: + properties: + name: + description: The short name of the HTTPAPISpec. + format: string + type: string + namespace: + description: Optional namespace of the HTTPAPISpec. + format: string + type: string + type: object + type: array + services: + description: One or more services to map the listed HTTPAPISpec onto. + items: + properties: + domain: + description: Domain suffix used to construct the service FQDN + in implementations that support such specification. + format: string + type: string + labels: + additionalProperties: + format: string + type: string + description: Optional one or more labels that uniquely identify + the service version. + type: object + name: + description: The short name of the service such as "foo". + format: string + type: string + namespace: + description: Optional namespace of the service. + format: string + type: string + service: + description: The service FQDN. + format: string + type: string + type: object + type: array + type: object + type: object + versions: + - name: v1alpha2 + served: true + storage: true + + --- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-mixer + chart: istio + heritage: Tiller + release: istio + name: httpapispecs.config.istio.io + spec: + group: config.istio.io + names: + categories: + - istio-io + - apim-istio-io + kind: HTTPAPISpec + plural: httpapispecs + singular: httpapispec + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + properties: + api_keys: + items: + oneOf: + - required: + - query + - required: + - header + - required: + - cookie + properties: + cookie: + format: string + type: string + header: + description: API key is sent in a request header. + format: string + type: string + query: + description: API Key is sent as a query parameter. + format: string + type: string + type: object + type: array + apiKeys: + items: + oneOf: + - required: + - query + - required: + - header + - required: + - cookie + properties: + cookie: + format: string + type: string + header: + description: API key is sent in a request header. + format: string + type: string + query: + description: API Key is sent as a query parameter. + format: string + type: string + type: object + type: array + attributes: + properties: + attributes: + additionalProperties: + oneOf: + - required: + - stringValue + - required: + - int64Value + - required: + - doubleValue + - required: + - boolValue + - required: + - bytesValue + - required: + - timestampValue + - required: + - durationValue + - required: + - stringMapValue + properties: + boolValue: + type: boolean + bytesValue: + format: binary + type: string + doubleValue: + format: double + type: number + durationValue: + type: string + int64Value: + format: int64 + type: integer + stringMapValue: + properties: + entries: + additionalProperties: + format: string + type: string + description: Holds a set of name/value pairs. + type: object + type: object + stringValue: + format: string + type: string + timestampValue: + format: dateTime + type: string + type: object + description: A map of attribute name to its value. + type: object + type: object + patterns: + description: List of HTTP patterns to match. + items: + oneOf: + - required: + - uriTemplate + - required: + - regex + properties: + attributes: + properties: + attributes: + additionalProperties: + oneOf: + - required: + - stringValue + - required: + - int64Value + - required: + - doubleValue + - required: + - boolValue + - required: + - bytesValue + - required: + - timestampValue + - required: + - durationValue + - required: + - stringMapValue + properties: + boolValue: + type: boolean + bytesValue: + format: binary + type: string + doubleValue: + format: double + type: number + durationValue: + type: string + int64Value: + format: int64 + type: integer + stringMapValue: + properties: + entries: + additionalProperties: + format: string + type: string + description: Holds a set of name/value pairs. + type: object + type: object + stringValue: + format: string + type: string + timestampValue: + format: dateTime + type: string + type: object + description: A map of attribute name to its value. + type: object + type: object + httpMethod: + format: string + type: string + regex: + format: string + type: string + uriTemplate: + format: string + type: string + type: object + type: array + type: object + type: object + versions: + - name: v1alpha2 + served: true + storage: true + + --- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-citadel + chart: istio + heritage: Tiller + release: istio + name: meshpolicies.authentication.istio.io + spec: + group: authentication.istio.io + names: + categories: + - istio-io + - authentication-istio-io + kind: MeshPolicy + listKind: MeshPolicyList + plural: meshpolicies + singular: meshpolicy + scope: Cluster + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Authentication policy for Istio services. See more details + at: https://istio.io/docs/reference/config/istio.authentication.v1alpha1.html' + properties: + originIsOptional: + type: boolean + origins: + description: List of authentication methods that can be used for origin + authentication. + items: + properties: + jwt: + description: Jwt params for the method. + properties: + audiences: + items: + format: string + type: string + type: array + issuer: + description: Identifies the issuer that issued the JWT. + format: string + type: string + jwks: + description: JSON Web Key Set of public keys to validate signature + of the JWT. + format: string + type: string + jwks_uri: + format: string + type: string + jwksUri: + format: string + type: string + jwt_headers: + description: JWT is sent in a request header. + items: + format: string + type: string + type: array + jwtHeaders: + description: JWT is sent in a request header. + items: + format: string + type: string + type: array + jwtParams: + description: JWT is sent in a query parameter. + items: + format: string + type: string + type: array + trigger_rules: + items: + properties: + excluded_paths: + description: List of paths to be excluded from the request. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + excludedPaths: + description: List of paths to be excluded from the request. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + included_paths: + description: List of paths that the request must include. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + includedPaths: + description: List of paths that the request must include. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + type: object + type: array + triggerRules: + items: + properties: + excluded_paths: + description: List of paths to be excluded from the request. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + excludedPaths: + description: List of paths to be excluded from the request. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + included_paths: + description: List of paths that the request must include. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + includedPaths: + description: List of paths that the request must include. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + type: object + type: array + type: object + type: object + type: array + peerIsOptional: + type: boolean + peers: + description: List of authentication methods that can be used for peer + authentication. + items: + oneOf: + - required: + - mtls + - required: + - jwt + properties: + jwt: + properties: + audiences: + items: + format: string + type: string + type: array + issuer: + description: Identifies the issuer that issued the JWT. + format: string + type: string + jwks: + description: JSON Web Key Set of public keys to validate signature + of the JWT. + format: string + type: string + jwks_uri: + format: string + type: string + jwksUri: + format: string + type: string + jwt_headers: + description: JWT is sent in a request header. + items: + format: string + type: string + type: array + jwtHeaders: + description: JWT is sent in a request header. + items: + format: string + type: string + type: array + jwtParams: + description: JWT is sent in a query parameter. + items: + format: string + type: string + type: array + trigger_rules: + items: + properties: + excluded_paths: + description: List of paths to be excluded from the request. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + excludedPaths: + description: List of paths to be excluded from the request. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + included_paths: + description: List of paths that the request must include. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + includedPaths: + description: List of paths that the request must include. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + type: object + type: array + triggerRules: + items: + properties: + excluded_paths: + description: List of paths to be excluded from the request. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + excludedPaths: + description: List of paths to be excluded from the request. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + included_paths: + description: List of paths that the request must include. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + includedPaths: + description: List of paths that the request must include. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + type: object + type: array + type: object + mtls: + description: Set if mTLS is used. + properties: + allowTls: + description: WILL BE DEPRECATED, if set, will translates to + `TLS_PERMISSIVE` mode. + type: boolean + mode: + description: Defines the mode of mTLS authentication. + enum: + - STRICT + - PERMISSIVE + type: string + type: object + type: object + type: array + principalBinding: + description: Define whether peer or origin identity should be use for + principal. + enum: + - USE_PEER + - USE_ORIGIN + type: string + targets: + description: List rules to select workloads that the policy should be + applied on. + items: + properties: + labels: + additionalProperties: + format: string + type: string + type: object + name: + description: The name must be a short name from the service registry. + format: string + type: string + ports: + description: Specifies the ports. + items: + oneOf: + - required: + - number + - required: + - name + properties: + name: + format: string + type: string + number: + type: integer + type: object + type: array + type: object + type: array + type: object + type: object + versions: + - name: v1alpha1 + served: true + storage: true + + --- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-citadel + chart: istio + heritage: Tiller + release: istio + name: policies.authentication.istio.io + spec: + group: authentication.istio.io + names: + categories: + - istio-io + - authentication-istio-io + kind: Policy + plural: policies + singular: policy + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Authentication policy for Istio services. See more details + at: https://istio.io/docs/reference/config/istio.authentication.v1alpha1.html' + properties: + originIsOptional: + type: boolean + origins: + description: List of authentication methods that can be used for origin + authentication. + items: + properties: + jwt: + description: Jwt params for the method. + properties: + audiences: + items: + format: string + type: string + type: array + issuer: + description: Identifies the issuer that issued the JWT. + format: string + type: string + jwks: + description: JSON Web Key Set of public keys to validate signature + of the JWT. + format: string + type: string + jwks_uri: + format: string + type: string + jwksUri: + format: string + type: string + jwt_headers: + description: JWT is sent in a request header. + items: + format: string + type: string + type: array + jwtHeaders: + description: JWT is sent in a request header. + items: + format: string + type: string + type: array + jwtParams: + description: JWT is sent in a query parameter. + items: + format: string + type: string + type: array + trigger_rules: + items: + properties: + excluded_paths: + description: List of paths to be excluded from the request. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + excludedPaths: + description: List of paths to be excluded from the request. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + included_paths: + description: List of paths that the request must include. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + includedPaths: + description: List of paths that the request must include. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + type: object + type: array + triggerRules: + items: + properties: + excluded_paths: + description: List of paths to be excluded from the request. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + excludedPaths: + description: List of paths to be excluded from the request. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + included_paths: + description: List of paths that the request must include. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + includedPaths: + description: List of paths that the request must include. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + type: object + type: array + type: object + type: object + type: array + peerIsOptional: + type: boolean + peers: + description: List of authentication methods that can be used for peer + authentication. + items: + oneOf: + - required: + - mtls + - required: + - jwt + properties: + jwt: + properties: + audiences: + items: + format: string + type: string + type: array + issuer: + description: Identifies the issuer that issued the JWT. + format: string + type: string + jwks: + description: JSON Web Key Set of public keys to validate signature + of the JWT. + format: string + type: string + jwks_uri: + format: string + type: string + jwksUri: + format: string + type: string + jwt_headers: + description: JWT is sent in a request header. + items: + format: string + type: string + type: array + jwtHeaders: + description: JWT is sent in a request header. + items: + format: string + type: string + type: array + jwtParams: + description: JWT is sent in a query parameter. + items: + format: string + type: string + type: array + trigger_rules: + items: + properties: + excluded_paths: + description: List of paths to be excluded from the request. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + excludedPaths: + description: List of paths to be excluded from the request. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + included_paths: + description: List of paths that the request must include. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + includedPaths: + description: List of paths that the request must include. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + type: object + type: array + triggerRules: + items: + properties: + excluded_paths: + description: List of paths to be excluded from the request. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + excludedPaths: + description: List of paths to be excluded from the request. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + included_paths: + description: List of paths that the request must include. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + includedPaths: + description: List of paths that the request must include. + items: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - suffix + - required: + - regex + properties: + exact: + description: exact string match. + format: string + type: string + prefix: + description: prefix-based match. + format: string + type: string + regex: + description: ECMAscript style regex-based match + as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). + format: string + type: string + suffix: + description: suffix-based match. + format: string + type: string + type: object + type: array + type: object + type: array + type: object + mtls: + description: Set if mTLS is used. + properties: + allowTls: + description: WILL BE DEPRECATED, if set, will translates to + `TLS_PERMISSIVE` mode. + type: boolean + mode: + description: Defines the mode of mTLS authentication. + enum: + - STRICT + - PERMISSIVE + type: string + type: object + type: object + type: array + principalBinding: + description: Define whether peer or origin identity should be use for + principal. + enum: + - USE_PEER + - USE_ORIGIN + type: string + targets: + description: List rules to select workloads that the policy should be + applied on. + items: + properties: + labels: + additionalProperties: + format: string + type: string + type: object + name: + description: The name must be a short name from the service registry. + format: string + type: string + ports: + description: Specifies the ports. + items: + oneOf: + - required: + - number + - required: + - name + properties: + name: + format: string + type: string + number: + type: integer + type: object + type: array + type: object + type: array + type: object + type: object + versions: + - name: v1alpha1 + served: true + storage: true + + --- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-mixer + chart: istio + heritage: Tiller + release: istio + name: quotaspecbindings.config.istio.io + spec: + group: config.istio.io + names: + categories: + - istio-io + - apim-istio-io + kind: QuotaSpecBinding + plural: quotaspecbindings + singular: quotaspecbinding + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + properties: + quotaSpecs: + items: + properties: + name: + description: The short name of the QuotaSpec. + format: string + type: string + namespace: + description: Optional namespace of the QuotaSpec. + format: string + type: string + type: object + type: array + services: + description: One or more services to map the listed QuotaSpec onto. + items: + properties: + domain: + description: Domain suffix used to construct the service FQDN + in implementations that support such specification. + format: string + type: string + labels: + additionalProperties: + format: string + type: string + description: Optional one or more labels that uniquely identify + the service version. + type: object + name: + description: The short name of the service such as "foo". + format: string + type: string + namespace: + description: Optional namespace of the service. + format: string + type: string + service: + description: The service FQDN. + format: string + type: string + type: object + type: array + type: object + type: object + versions: + - name: v1alpha2 + served: true + storage: true + + --- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-mixer + chart: istio + heritage: Tiller + release: istio + name: quotaspecs.config.istio.io + spec: + group: config.istio.io + names: + categories: + - istio-io + - apim-istio-io + kind: QuotaSpec + plural: quotaspecs + singular: quotaspec + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: Determines the quotas used for individual requests. + properties: + rules: + description: A list of Quota rules. + items: + properties: + match: + description: If empty, match all request. + items: + properties: + clause: + additionalProperties: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - regex + properties: + exact: + format: string + type: string + prefix: + format: string + type: string + regex: + format: string + type: string + type: object + description: Map of attribute names to StringMatch type. + type: object + type: object + type: array + quotas: + description: The list of quotas to charge. + items: + properties: + charge: + format: int32 + type: integer + quota: + format: string + type: string + type: object + type: array + type: object + type: array + type: object + type: object + versions: + - name: v1alpha2 + served: true + storage: true + + --- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: mixer + chart: istio + heritage: Tiller + istio: rbac + package: istio.io.mixer + release: istio + name: rbacconfigs.rbac.istio.io + spec: + group: rbac.istio.io + names: + categories: + - istio-io + - rbac-istio-io + kind: RbacConfig + plural: rbacconfigs + singular: rbacconfig + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Configuration for Role Based Access Control. See more details + at: https://istio.io/docs/reference/config/authorization/istio.rbac.v1alpha1.html' + properties: + enforcementMode: + enum: + - ENFORCED + - PERMISSIVE + type: string + exclusion: + description: A list of services or namespaces that should not be enforced + by Istio RBAC policies. + properties: + namespaces: + description: A list of namespaces. + items: + format: string + type: string + type: array + services: + description: A list of services. + items: + format: string + type: string + type: array + type: object + inclusion: + description: A list of services or namespaces that should be enforced + by Istio RBAC policies. + properties: + namespaces: + description: A list of namespaces. + items: + format: string + type: string + type: array + services: + description: A list of services. + items: + format: string + type: string + type: array + type: object + mode: + description: Istio RBAC mode. + enum: + - "OFF" + - "ON" + - ON_WITH_INCLUSION + - ON_WITH_EXCLUSION + type: string + type: object + type: object + versions: + - name: v1alpha1 + served: true + storage: true + + --- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: mixer + chart: istio + heritage: Tiller + istio: core + package: istio.io.mixer + release: istio + name: rules.config.istio.io + spec: + group: config.istio.io + names: + categories: + - istio-io + - policy-istio-io + kind: rule + plural: rules + singular: rule + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Describes the rules used to configure Mixer''s policy and + telemetry features. See more details at: https://istio.io/docs/reference/config/policy-and-telemetry/istio.policy.v1beta1.html' + properties: + actions: + description: The actions that will be executed when match evaluates + to `true`. + items: + properties: + handler: + description: Fully qualified name of the handler to invoke. + format: string + type: string + instances: + items: + format: string + type: string + type: array + name: + description: A handle to refer to the results of the action. + format: string + type: string + type: object + type: array + match: + description: Match is an attribute based predicate. + format: string + type: string + requestHeaderOperations: + items: + properties: + name: + description: Header name literal value. + format: string + type: string + operation: + description: Header operation type. + enum: + - REPLACE + - REMOVE + - APPEND + type: string + values: + description: Header value expressions. + items: + format: string + type: string + type: array + type: object + type: array + responseHeaderOperations: + items: + properties: + name: + description: Header name literal value. + format: string + type: string + operation: + description: Header operation type. + enum: + - REPLACE + - REMOVE + - APPEND + type: string + values: + description: Header value expressions. + items: + format: string + type: string + type: array + type: object + type: array + sampling: + properties: + random: + description: Provides filtering of actions based on random selection + per request. + properties: + attributeExpression: + description: Specifies an attribute expression to use to override + the numerator in the `percent_sampled` field. + format: string + type: string + percentSampled: + description: The default sampling rate, expressed as a percentage. + properties: + denominator: + description: Specifies the denominator. + enum: + - HUNDRED + - TEN_THOUSAND + type: string + numerator: + description: Specifies the numerator. + type: integer + type: object + useIndependentRandomness: + description: By default sampling will be based on the value + of the request header `x-request-id`. + type: boolean + type: object + rateLimit: + properties: + maxUnsampledEntries: + description: Number of entries to allow during the `sampling_duration` + before sampling is enforced. + format: int64 + type: integer + samplingDuration: + description: Window in which to enforce the sampling rate. + type: string + samplingRate: + description: The rate at which to sample entries once the unsampled + limit has been reached. + format: int64 + type: integer + type: object + type: object + type: object + type: object + versions: + - name: v1alpha2 + served: true + storage: true + + --- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-pilot + chart: istio + heritage: Tiller + release: istio + name: serviceentries.networking.istio.io + spec: + additionalPrinterColumns: + - JSONPath: .spec.hosts + description: The hosts associated with the ServiceEntry + name: Hosts + type: string + - JSONPath: .spec.location + description: Whether the service is external to the mesh or part of the mesh (MESH_EXTERNAL + or MESH_INTERNAL) + name: Location + type: string + - JSONPath: .spec.resolution + description: Service discovery mode for the hosts (NONE, STATIC, or DNS) + name: Resolution + type: string + - JSONPath: .metadata.creationTimestamp + description: |- + CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + name: Age + type: date + group: networking.istio.io + names: + categories: + - istio-io + - networking-istio-io + kind: ServiceEntry + listKind: ServiceEntryList + plural: serviceentries + shortNames: + - se + singular: serviceentry + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Configuration affecting service registry. See more details + at: https://istio.io/docs/reference/config/networking/v1alpha3/service-entry.html' + properties: + addresses: + description: The virtual IP addresses associated with the service. + items: + format: string + type: string + type: array + endpoints: + description: One or more endpoints associated with the service. + items: + properties: + address: + format: string + type: string + labels: + additionalProperties: + format: string + type: string + description: One or more labels associated with the endpoint. + type: object + locality: + description: The locality associated with the endpoint. + format: string + type: string + network: + format: string + type: string + ports: + additionalProperties: + type: integer + description: Set of ports associated with the endpoint. + type: object + weight: + description: The load balancing weight associated with the endpoint. + type: integer + type: object + type: array + exportTo: + description: A list of namespaces to which this service is exported. + items: + format: string + type: string + type: array + hosts: + description: The hosts associated with the ServiceEntry. + items: + format: string + type: string + type: array + location: + enum: + - MESH_EXTERNAL + - MESH_INTERNAL + type: string + ports: + description: The ports associated with the external service. + items: + properties: + name: + description: Label assigned to the port. + format: string + type: string + number: + description: A valid non-negative integer port number. + type: integer + protocol: + description: The protocol exposed on the port. + format: string + type: string + type: object + type: array + resolution: + description: Service discovery mode for the hosts. + enum: + - NONE + - STATIC + - DNS + type: string + subjectAltNames: + items: + format: string + type: string + type: array + type: object + type: object + versions: + - name: v1alpha3 + served: true + storage: true + + --- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: mixer + chart: istio + heritage: Tiller + istio: rbac + package: istio.io.mixer + release: istio + name: servicerolebindings.rbac.istio.io + spec: + additionalPrinterColumns: + - JSONPath: .spec.roleRef.name + description: The name of the ServiceRole object being referenced + name: Reference + type: string + - JSONPath: .metadata.creationTimestamp + description: |- + CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + name: Age + type: date + group: rbac.istio.io + names: + categories: + - istio-io + - rbac-istio-io + kind: ServiceRoleBinding + plural: servicerolebindings + singular: servicerolebinding + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Configuration for Role Based Access Control. See more details + at: https://istio.io/docs/reference/config/authorization/istio.rbac.v1alpha1.html' + properties: + actions: + items: + properties: + constraints: + description: Optional. + items: + properties: + key: + description: Key of the constraint. + format: string + type: string + values: + description: List of valid values for the constraint. + items: + format: string + type: string + type: array + type: object + type: array + hosts: + items: + format: string + type: string + type: array + methods: + description: Optional. + items: + format: string + type: string + type: array + notHosts: + items: + format: string + type: string + type: array + notMethods: + items: + format: string + type: string + type: array + notPaths: + items: + format: string + type: string + type: array + notPorts: + items: + format: int32 + type: integer + type: array + paths: + description: Optional. + items: + format: string + type: string + type: array + ports: + items: + format: int32 + type: integer + type: array + services: + description: A list of service names. + items: + format: string + type: string + type: array + type: object + type: array + mode: + enum: + - ENFORCED + - PERMISSIVE + type: string + role: + format: string + type: string + roleRef: + description: Reference to the ServiceRole object. + properties: + kind: + description: The type of the role being referenced. + format: string + type: string + name: + description: The name of the ServiceRole object being referenced. + format: string + type: string + type: object + subjects: + description: List of subjects that are assigned the ServiceRole object. + items: + properties: + group: + format: string + type: string + groups: + items: + format: string + type: string + type: array + ips: + items: + format: string + type: string + type: array + names: + items: + format: string + type: string + type: array + namespaces: + items: + format: string + type: string + type: array + notGroups: + items: + format: string + type: string + type: array + notIps: + items: + format: string + type: string + type: array + notNames: + items: + format: string + type: string + type: array + notNamespaces: + items: + format: string + type: string + type: array + properties: + additionalProperties: + format: string + type: string + description: Optional. + type: object + user: + description: Optional. + format: string + type: string + type: object + type: array + type: object + type: object + versions: + - name: v1alpha1 + served: true + storage: true + + --- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: mixer + chart: istio + heritage: Tiller + istio: rbac + package: istio.io.mixer + release: istio + name: serviceroles.rbac.istio.io + spec: + group: rbac.istio.io + names: + categories: + - istio-io + - rbac-istio-io + kind: ServiceRole + plural: serviceroles + singular: servicerole + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Configuration for Role Based Access Control. See more details + at: https://istio.io/docs/reference/config/authorization/istio.rbac.v1alpha1.html' + properties: + rules: + description: The set of access rules (permissions) that the role has. + items: + properties: + constraints: + description: Optional. + items: + properties: + key: + description: Key of the constraint. + format: string + type: string + values: + description: List of valid values for the constraint. + items: + format: string + type: string + type: array + type: object + type: array + hosts: + items: + format: string + type: string + type: array + methods: + description: Optional. + items: + format: string + type: string + type: array + notHosts: + items: + format: string + type: string + type: array + notMethods: + items: + format: string + type: string + type: array + notPaths: + items: + format: string + type: string + type: array + notPorts: + items: + format: int32 + type: integer + type: array + paths: + description: Optional. + items: + format: string + type: string + type: array + ports: + items: + format: int32 + type: integer + type: array + services: + description: A list of service names. + items: + format: string + type: string + type: array + type: object + type: array + type: object + type: object + versions: + - name: v1alpha1 + served: true + storage: true + + --- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-pilot + chart: istio + heritage: Tiller + release: istio + name: virtualservices.networking.istio.io + spec: + additionalPrinterColumns: + - JSONPath: .spec.gateways + description: The names of gateways and sidecars that should apply these routes + name: Gateways + type: string + - JSONPath: .spec.hosts + description: The destination hosts to which traffic is being sent + name: Hosts + type: string + - JSONPath: .metadata.creationTimestamp + description: |- + CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. + Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata + name: Age + type: date + group: networking.istio.io + names: + categories: + - istio-io + - networking-istio-io + kind: VirtualService + listKind: VirtualServiceList + plural: virtualservices + shortNames: + - vs + singular: virtualservice + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Configuration affecting label/content routing, sni routing, + etc. See more details at: https://istio.io/docs/reference/config/networking/v1alpha3/virtual-service.html' + properties: + exportTo: + description: A list of namespaces to which this virtual service is exported. + items: + format: string + type: string + type: array + gateways: + description: The names of gateways and sidecars that should apply these + routes. + items: + format: string + type: string + type: array + hosts: + description: The destination hosts to which traffic is being sent. + items: + format: string + type: string + type: array + http: + description: An ordered list of route rules for HTTP traffic. + items: + properties: + appendHeaders: + additionalProperties: + format: string + type: string + type: object + appendRequestHeaders: + additionalProperties: + format: string + type: string + type: object + appendResponseHeaders: + additionalProperties: + format: string + type: string + type: object + corsPolicy: + description: Cross-Origin Resource Sharing policy (CORS). + properties: + allowCredentials: + nullable: true + type: boolean + allowHeaders: + items: + format: string + type: string + type: array + allowMethods: + description: List of HTTP methods allowed to access the resource. + items: + format: string + type: string + type: array + allowOrigin: + description: The list of origins that are allowed to perform + CORS requests. + items: + format: string + type: string + type: array + exposeHeaders: + items: + format: string + type: string + type: array + maxAge: + type: string + type: object + fault: + description: Fault injection policy to apply on HTTP traffic at + the client side. + properties: + abort: + oneOf: + - properties: + percent: {} + required: + - httpStatus + - properties: + percent: {} + required: + - grpcStatus + - properties: + percent: {} + required: + - http2Error + properties: + grpcStatus: + format: string + type: string + http2Error: + format: string + type: string + httpStatus: + description: HTTP status code to use to abort the Http + request. + format: int32 + type: integer + percent: + description: Percentage of requests to be aborted with + the error code provided (0-100). + format: int32 + type: integer + percentage: + description: Percentage of requests to be aborted with + the error code provided. + properties: + value: + format: double + type: number + type: object + type: object + delay: + oneOf: + - properties: + percent: {} + required: + - fixedDelay + - properties: + percent: {} + required: + - exponentialDelay + properties: + exponentialDelay: + type: string + fixedDelay: + description: Add a fixed delay before forwarding the request. + type: string + percent: + description: Percentage of requests on which the delay + will be injected (0-100). + format: int32 + type: integer + percentage: + description: Percentage of requests on which the delay + will be injected. + properties: + value: + format: double + type: number + type: object + type: object + type: object + headers: + properties: + request: + properties: + add: + additionalProperties: + format: string + type: string + type: object + remove: + items: + format: string + type: string + type: array + set: + additionalProperties: + format: string + type: string + type: object + type: object + response: + properties: + add: + additionalProperties: + format: string + type: string + type: object + remove: + items: + format: string + type: string + type: array + set: + additionalProperties: + format: string + type: string + type: object + type: object + type: object + match: + items: + properties: + authority: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - regex + properties: + exact: + format: string + type: string + prefix: + format: string + type: string + regex: + format: string + type: string + type: object + gateways: + items: + format: string + type: string + type: array + headers: + additionalProperties: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - regex + properties: + exact: + format: string + type: string + prefix: + format: string + type: string + regex: + format: string + type: string + type: object + type: object + ignoreUriCase: + description: Flag to specify whether the URI matching should + be case-insensitive. + type: boolean + method: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - regex + properties: + exact: + format: string + type: string + prefix: + format: string + type: string + regex: + format: string + type: string + type: object + name: + description: The name assigned to a match. + format: string + type: string + port: + description: Specifies the ports on the host that is being + addressed. + type: integer + queryParams: + additionalProperties: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - regex + properties: + exact: + format: string + type: string + prefix: + format: string + type: string + regex: + format: string + type: string + type: object + description: Query parameters for matching. + type: object + scheme: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - regex + properties: + exact: + format: string + type: string + prefix: + format: string + type: string + regex: + format: string + type: string + type: object + sourceLabels: + additionalProperties: + format: string + type: string + type: object + uri: + oneOf: + - required: + - exact + - required: + - prefix + - required: + - regex + properties: + exact: + format: string + type: string + prefix: + format: string + type: string + regex: + format: string + type: string + type: object + type: object + type: array + mirror: + properties: + host: + description: The name of a service from the service registry. + format: string + type: string + port: + description: Specifies the port on the host that is being + addressed. + properties: + number: + type: integer + type: object + subset: + description: The name of a subset within the service. + format: string + type: string + type: object + mirror_percent: + description: Percentage of the traffic to be mirrored by the `mirror` + field. + nullable: true + type: integer + mirrorPercent: + description: Percentage of the traffic to be mirrored by the `mirror` + field. + nullable: true + type: integer + name: + description: The name assigned to the route for debugging purposes. + format: string + type: string + redirect: + description: A http rule can either redirect or forward (default) + traffic. + properties: + authority: + format: string + type: string + redirectCode: + type: integer + uri: + format: string + type: string + type: object + removeRequestHeaders: + items: + format: string + type: string + type: array + removeResponseHeaders: + items: + format: string + type: string + type: array + retries: + description: Retry policy for HTTP requests. + properties: + attempts: + description: Number of retries for a given request. + format: int32 + type: integer + perTryTimeout: + description: Timeout per retry attempt for a given request. + type: string + retryOn: + description: Specifies the conditions under which retry takes + place. + format: string + type: string + type: object + rewrite: + description: Rewrite HTTP URIs and Authority headers. + properties: + authority: + description: rewrite the Authority/Host header with this value. + format: string + type: string + uri: + format: string + type: string + type: object + route: + description: A http rule can either redirect or forward (default) + traffic. + items: + properties: + appendRequestHeaders: + additionalProperties: + format: string + type: string + description: Use of `append_request_headers` is deprecated. + type: object + appendResponseHeaders: + additionalProperties: + format: string + type: string + description: Use of `append_response_headers` is deprecated. + type: object + destination: + properties: + host: + description: The name of a service from the service + registry. + format: string + type: string + port: + description: Specifies the port on the host that is + being addressed. + properties: + number: + type: integer + type: object + subset: + description: The name of a subset within the service. + format: string + type: string + type: object + headers: + properties: + request: + properties: + add: + additionalProperties: + format: string + type: string + type: object + remove: + items: + format: string + type: string + type: array + set: + additionalProperties: + format: string + type: string + type: object + type: object + response: + properties: + add: + additionalProperties: + format: string + type: string + type: object + remove: + items: + format: string + type: string + type: array + set: + additionalProperties: + format: string + type: string + type: object + type: object + type: object + removeRequestHeaders: + description: Use of `remove_request_headers` is deprecated. + items: + format: string + type: string + type: array + removeResponseHeaders: + description: Use of `remove_response_header` is deprecated. + items: + format: string + type: string + type: array + weight: + format: int32 + type: integer + type: object + type: array + timeout: + description: Timeout for HTTP requests. + type: string + websocketUpgrade: + description: Deprecated. + type: boolean + type: object + type: array + tcp: + description: An ordered list of route rules for opaque TCP traffic. + items: + properties: + match: + items: + properties: + destinationSubnets: + description: IPv4 or IPv6 ip addresses of destination with + optional subnet. + items: + format: string + type: string + type: array + gateways: + description: Names of gateways where the rule should be + applied to. + items: + format: string + type: string + type: array + port: + description: Specifies the port on the host that is being + addressed. + type: integer + sourceLabels: + additionalProperties: + format: string + type: string + type: object + sourceSubnet: + description: IPv4 or IPv6 ip address of source with optional + subnet. + format: string + type: string + type: object + type: array + route: + description: The destination to which the connection should be + forwarded to. + items: + properties: + destination: + properties: + host: + description: The name of a service from the service + registry. + format: string + type: string + port: + description: Specifies the port on the host that is + being addressed. + properties: + number: + type: integer + type: object + subset: + description: The name of a subset within the service. + format: string + type: string + type: object + weight: + format: int32 + type: integer + type: object + type: array + type: object + type: array + tls: + items: + properties: + match: + items: + properties: + destinationSubnets: + description: IPv4 or IPv6 ip addresses of destination with + optional subnet. + items: + format: string + type: string + type: array + gateways: + description: Names of gateways where the rule should be + applied to. + items: + format: string + type: string + type: array + port: + description: Specifies the port on the host that is being + addressed. + type: integer + sniHosts: + description: SNI (server name indicator) to match on. + items: + format: string + type: string + type: array + sourceLabels: + additionalProperties: + format: string + type: string + type: object + sourceSubnet: + description: IPv4 or IPv6 ip address of source with optional + subnet. + format: string + type: string + type: object + type: array + route: + description: The destination to which the connection should be + forwarded to. + items: + properties: + destination: + properties: + host: + description: The name of a service from the service + registry. + format: string + type: string + port: + description: Specifies the port on the host that is + being addressed. + properties: + number: + type: integer + type: object + subset: + description: The name of a subset within the service. + format: string + type: string + type: object + weight: + format: int32 + type: integer + type: object + type: array + type: object + type: array + type: object + type: object + versions: + - name: v1alpha3 + served: true + storage: true + + --- + kind: CustomResourceDefinition + apiVersion: apiextensions.k8s.io/v1beta1 + metadata: + name: adapters.config.istio.io + labels: + app: mixer + package: adapter + istio: mixer-adapter + chart: istio + heritage: Tiller + release: istio + annotations: + "helm.sh/resource-policy": keep + spec: + group: config.istio.io + names: + kind: adapter + plural: adapters + singular: adapter + categories: + - istio-io + - policy-istio-io + scope: Namespaced + subresources: + status: {} + versions: + - name: v1alpha2 + served: true + storage: true + + --- + kind: CustomResourceDefinition + apiVersion: apiextensions.k8s.io/v1beta1 + metadata: + name: instances.config.istio.io + labels: + app: mixer + package: instance + istio: mixer-instance + chart: istio + heritage: Tiller + release: istio + annotations: + "helm.sh/resource-policy": keep + spec: + group: config.istio.io + names: + kind: instance + plural: instances + singular: instance + categories: + - istio-io + - policy-istio-io + scope: Namespaced + subresources: + status: {} + versions: + - name: v1alpha2 + served: true + storage: true + + --- + kind: CustomResourceDefinition + apiVersion: apiextensions.k8s.io/v1beta1 + metadata: + name: templates.config.istio.io + labels: + app: mixer + package: template + istio: mixer-template + chart: istio + heritage: Tiller + release: istio + annotations: + "helm.sh/resource-policy": keep + spec: + group: config.istio.io + names: + kind: template + plural: templates + singular: template + categories: + - istio-io + - policy-istio-io + scope: Namespaced + subresources: + status: {} + versions: + - name: v1alpha2 + served: true + storage: true + + --- + kind: CustomResourceDefinition + apiVersion: apiextensions.k8s.io/v1beta1 + metadata: + name: handlers.config.istio.io + labels: + app: mixer + package: handler + istio: mixer-handler + chart: istio + heritage: Tiller + release: istio + annotations: + "helm.sh/resource-policy": keep + spec: + group: config.istio.io + names: + kind: handler + plural: handlers + singular: handler + categories: + - istio-io + - policy-istio-io + scope: Namespaced + subresources: + status: {} + versions: + - name: v1alpha2 + served: true + storage: true + + --- +--- +# Source: istio-init/templates/configmap-crd-11.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: istio-system + name: istio-crd-11 +data: + crd-11.yaml: |- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + annotations: + "helm.sh/resource-policy": keep + labels: + app: istio-pilot + chart: istio + heritage: Tiller + release: istio + name: sidecars.networking.istio.io + spec: + group: networking.istio.io + names: + categories: + - istio-io + - networking-istio-io + kind: Sidecar + plural: sidecars + singular: sidecar + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Configuration affecting network reachability of a sidecar. + See more details at: https://istio.io/docs/reference/config/networking/v1alpha3/sidecar.html' + properties: + egress: + items: + properties: + bind: + format: string + type: string + captureMode: + enum: + - DEFAULT + - IPTABLES + - NONE + type: string + hosts: + items: + format: string + type: string + type: array + port: + description: The port associated with the listener. + properties: + name: + description: Label assigned to the port. + format: string + type: string + number: + description: A valid non-negative integer port number. + type: integer + protocol: + description: The protocol exposed on the port. + format: string + type: string + type: object + type: object + type: array + ingress: + items: + properties: + bind: + description: The ip to which the listener should be bound. + format: string + type: string + captureMode: + enum: + - DEFAULT + - IPTABLES + - NONE + type: string + defaultEndpoint: + format: string + type: string + port: + description: The port associated with the listener. + properties: + name: + description: Label assigned to the port. + format: string + type: string + number: + description: A valid non-negative integer port number. + type: integer + protocol: + description: The protocol exposed on the port. + format: string + type: string + type: object + type: object + type: array + outboundTrafficPolicy: + description: This allows to configure the outbound traffic policy. + properties: + mode: + enum: + - REGISTRY_ONLY + - ALLOW_ANY + type: string + type: object + workloadSelector: + properties: + labels: + additionalProperties: + format: string + type: string + type: object + type: object + type: object + type: object + versions: + - name: v1alpha3 + served: true + storage: true + + --- +--- +# Source: istio-init/templates/configmap-crd-14.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + namespace: istio-system + name: istio-crd-14 +data: + crd-14.yaml: |- + apiVersion: apiextensions.k8s.io/v1beta1 + kind: CustomResourceDefinition + metadata: + labels: + app: istio-pilot + heritage: Tiller + istio: security + release: istio + name: authorizationpolicies.security.istio.io + spec: + group: security.istio.io + names: + categories: + - istio-io + - security-istio-io + kind: AuthorizationPolicy + plural: authorizationpolicies + singular: authorizationpolicy + scope: Namespaced + subresources: + status: {} + validation: + openAPIV3Schema: + properties: + spec: + description: 'Configuration for access control on workloads. See more details + at: https://istio.io/docs/reference/config/security/v1beta1/authorization-policy.html' + properties: + rules: + description: Optional. + items: + properties: + from: + description: Optional. + items: + properties: + source: + description: Source specifies the source of a request. + properties: + ipBlocks: + description: Optional. + items: + format: string + type: string + type: array + namespaces: + description: Optional. + items: + format: string + type: string + type: array + principals: + description: Optional. + items: + format: string + type: string + type: array + requestPrincipals: + description: Optional. + items: + format: string + type: string + type: array + type: object + type: object + type: array + to: + description: Optional. + items: + properties: + operation: + description: Operation specifies the operation of a request. + properties: + hosts: + description: Optional. + items: + format: string + type: string + type: array + methods: + description: Optional. + items: + format: string + type: string + type: array + paths: + description: Optional. + items: + format: string + type: string + type: array + ports: + description: Optional. + items: + format: string + type: string + type: array + type: object + type: object + type: array + when: + description: Optional. + items: + properties: + key: + description: The name of an Istio attribute. + format: string + type: string + values: + description: The allowed values for the attribute. + items: + format: string + type: string + type: array + type: object + type: array + type: object + type: array + selector: + description: Optional. + properties: + matchLabels: + additionalProperties: + format: string + type: string + type: object + type: object + type: object + type: object + versions: + - name: v1beta1 + served: true + storage: true + + --- +--- +# Source: istio-init/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-init-service-account + namespace: istio-system + labels: + app: istio-init + istio: init +--- +# Source: istio-init/templates/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: istio-init-istio-system + labels: + app: istio-init + istio: init +rules: +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["create", "get", "list", "watch", "patch"] +--- +# Source: istio-init/templates/clusterrolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istio-init-admin-role-binding-istio-system + labels: + app: istio-init + istio: init +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-init-istio-system +subjects: + - kind: ServiceAccount + name: istio-init-service-account + namespace: istio-system +--- +# Source: istio-init/templates/job-crd-10.yaml +apiVersion: batch/v1 +kind: Job +metadata: + namespace: istio-system + name: istio-init-crd-10-1.4.3 +spec: + template: + metadata: + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: istio-init-service-account + containers: + - name: istio-init-crd-10 + image: "docker.io/istio/kubectl:1.4.3" + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 100m + memory: 200Mi + requests: + cpu: 10m + memory: 50Mi + volumeMounts: + - name: crd-10 + mountPath: /etc/istio/crd-10 + readOnly: true + command: ["kubectl", "apply", "-f", "/etc/istio/crd-10/crd-10.yaml"] + volumes: + - name: crd-10 + configMap: + name: istio-crd-10 + restartPolicy: OnFailure +--- +# Source: istio-init/templates/job-crd-11.yaml +apiVersion: batch/v1 +kind: Job +metadata: + namespace: istio-system + name: istio-init-crd-11-1.4.3 +spec: + template: + metadata: + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: istio-init-service-account + containers: + - name: istio-init-crd-11 + image: "docker.io/istio/kubectl:1.4.3" + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 100m + memory: 200Mi + requests: + cpu: 10m + memory: 50Mi + volumeMounts: + - name: crd-11 + mountPath: /etc/istio/crd-11 + readOnly: true + command: ["kubectl", "apply", "-f", "/etc/istio/crd-11/crd-11.yaml"] + volumes: + - name: crd-11 + configMap: + name: istio-crd-11 + restartPolicy: OnFailure +--- +# Source: istio-init/templates/job-crd-14.yaml +apiVersion: batch/v1 +kind: Job +metadata: + namespace: istio-system + name: istio-init-crd-14-1.4.3 +spec: + template: + metadata: + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: istio-init-service-account + containers: + - name: istio-init-crd-14 + image: "docker.io/istio/kubectl:1.4.3" + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 100m + memory: 200Mi + requests: + cpu: 10m + memory: 50Mi + volumeMounts: + - name: crd-14 + mountPath: /etc/istio/crd-14 + readOnly: true + command: ["kubectl", "apply", "-f", "/etc/istio/crd-14/crd-14.yaml"] + volumes: + - name: crd-14 + configMap: + name: istio-crd-14 + restartPolicy: OnFailure diff --git a/third_party/istio-1.4.3/istio-knative-extras.yaml b/third_party/istio-1.4.3/istio-knative-extras.yaml new file mode 100644 index 00000000000..bc1f99538da --- /dev/null +++ b/third_party/istio-1.4.3/istio-knative-extras.yaml @@ -0,0 +1,268 @@ +--- +# Source: istio/charts/gateways/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cluster-local-gateway-service-account + namespace: istio-system + labels: + app: cluster-local-gateway + chart: gateways + heritage: Helm + release: RELEASE-NAME +--- +# Source: istio/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-multi + namespace: istio-system +--- +# Source: istio/templates/clusterrole.yaml +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: istio-reader +rules: + - apiGroups: [''] + resources: ['nodes', 'pods', 'services', 'endpoints', "replicationcontrollers"] + verbs: ['get', 'watch', 'list'] + - apiGroups: ["extensions", "apps"] + resources: ["replicasets"] + verbs: ["get", "list", "watch"] +--- +# Source: istio/templates/clusterrolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istio-multi + labels: + chart: istio-1.4.3 +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-reader +subjects: +- kind: ServiceAccount + name: istio-multi + namespace: istio-system +--- +# Source: istio/charts/gateways/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: cluster-local-gateway + namespace: istio-system + annotations: + labels: + chart: gateways + heritage: Helm + release: RELEASE-NAME + app: cluster-local-gateway + istio: cluster-local-gateway +spec: + type: ClusterIP + selector: + release: RELEASE-NAME + app: cluster-local-gateway + istio: cluster-local-gateway + ports: + - + name: status-port + port: 15020 + - + name: http2 + port: 80 + - + name: https + port: 443 +--- +# Source: istio/charts/gateways/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cluster-local-gateway + namespace: istio-system + labels: + app: cluster-local-gateway + chart: gateways + heritage: Helm + istio: cluster-local-gateway + release: RELEASE-NAME +spec: + replicas: 1 + selector: + matchLabels: + app: cluster-local-gateway + istio: cluster-local-gateway + strategy: + rollingUpdate: + maxSurge: + maxUnavailable: + template: + metadata: + labels: + app: cluster-local-gateway + chart: gateways + heritage: Helm + istio: cluster-local-gateway + release: RELEASE-NAME + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: cluster-local-gateway-service-account + containers: + - name: istio-proxy + image: "docker.io/istio/proxyv2:1.4.3" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 15020 + - containerPort: 80 + - containerPort: 443 + - containerPort: 15090 + protocol: TCP + name: http-envoy-prom + args: + - proxy + - router + - --domain + - $(POD_NAMESPACE).svc.cluster.local + - --log_output_level=default:info + - --drainDuration + - '45s' #drainDuration + - --parentShutdownDuration + - '1m0s' #parentShutdownDuration + - --connectTimeout + - '10s' #connectTimeout + - --serviceCluster + - cluster-local-gateway + - --zipkinAddress + - zipkin:9411 + - --proxyAdminPort + - "15000" + - --statusPort + - "15020" + - --controlPlaneAuthPolicy + - NONE + - --discoveryAddress + - istio-pilot:15010 + readinessProbe: + failureThreshold: 30 + httpGet: + path: /healthz/ready + port: 15020 + scheme: HTTP + initialDelaySeconds: 1 + periodSeconds: 2 + successThreshold: 1 + timeoutSeconds: 1 + resources: + requests: + cpu: 10m + env: + - name: NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + - name: HOST_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + - name: SERVICE_ACCOUNT + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: ISTIO_META_CONFIG_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: ISTIO_METAJSON_LABELS + value: | + {"app":"cluster-local-gateway","chart":"gateways","heritage":"Helm","istio":"cluster-local-gateway","release":"RELEASE-NAME"} + - name: ISTIO_META_CLUSTER_ID + value: "Kubernetes" + - name: SDS_ENABLED + value: "false" + - name: ISTIO_META_WORKLOAD_NAME + value: cluster-local-gateway + - name: ISTIO_META_OWNER + value: kubernetes://apis/apps/v1/namespaces/istio-system/deployments/cluster-local-gateway + + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: cluster-local-gateway-certs + mountPath: "/etc/istio/cluster-local-gateway-certs" + readOnly: true + - name: cluster-local-gateway-ca-certs + mountPath: "/etc/istio/cluster-local-gateway-ca-certs" + readOnly: true + volumes: + - name: istio-certs + secret: + secretName: istio.cluster-local-gateway-service-account + optional: true + - name: cluster-local-gateway-certs + secret: + secretName: "istio-cluster-local-gateway-certs" + optional: true + - name: cluster-local-gateway-ca-certs + secret: + secretName: "istio-cluster-local-gateway-ca-certs" + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - "ppc64le" + - "s390x" + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "ppc64le" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "s390x" diff --git a/third_party/istio-1.4.3/istio-minimal.yaml b/third_party/istio-1.4.3/istio-minimal.yaml new file mode 100644 index 00000000000..33157feac72 --- /dev/null +++ b/third_party/istio-1.4.3/istio-minimal.yaml @@ -0,0 +1,960 @@ +--- +# PATCH #1: Creating the istio-system namespace. +apiVersion: v1 +kind: Namespace +metadata: + name: istio-system + labels: + istio-injection: disabled +# PATCH #1 ends. +--- +# Source: istio/templates/configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: istio + namespace: istio-system + labels: + app: istio + chart: istio + heritage: Helm + release: RELEASE-NAME +data: + mesh: |- + # Set the following variable to true to disable policy checks by Mixer. + # Note that metrics will still be reported to Mixer. + disablePolicyChecks: true + + disableMixerHttpReports: false + # reportBatchMaxEntries is the number of requests that are batched before telemetry data is sent to the mixer server + reportBatchMaxEntries: 100 + # reportBatchMaxTime is the max waiting time before the telemetry data of a request is sent to the mixer server + reportBatchMaxTime: 1s + + # Set enableTracing to false to disable request tracing. + enableTracing: true + + # Set accessLogFile to empty string to disable access log. + accessLogFile: "/dev/stdout" + + # If accessLogEncoding is TEXT, value will be used directly as the log format + # example: "[%START_TIME%] %REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\n" + # If AccessLogEncoding is JSON, value will be parsed as map[string]string + # example: '{"start_time": "%START_TIME%", "req_method": "%REQ(:METHOD)%"}' + # Leave empty to use default log format + accessLogFormat: "" + + # Set accessLogEncoding to JSON or TEXT to configure sidecar access log + accessLogEncoding: 'JSON' + + enableEnvoyAccessLogService: false + # Let Pilot give ingresses the public IP of the Istio ingressgateway + ingressService: istio-ingressgateway + + # Default connect timeout for dynamic clusters generated by Pilot and returned via XDS + connectTimeout: 10s + + # Automatic protocol detection uses a set of heuristics to + # determine whether the connection is using TLS or not (on the + # server side), as well as the application protocol being used + # (e.g., http vs tcp). These heuristics rely on the client sending + # the first bits of data. For server first protocols like MySQL, + # MongoDB, etc., Envoy will timeout on the protocol detection after + # the specified period, defaulting to non mTLS plain TCP + # traffic. Set this field to tweak the period that Envoy will wait + # for the client to send the first bits of data. (MUST BE >=1ms) + protocolDetectionTimeout: 100ms + + # DNS refresh rate for Envoy clusters of type STRICT_DNS + dnsRefreshRate: 300s + + # Unix Domain Socket through which envoy communicates with NodeAgent SDS to get + # key/cert for mTLS. Use secret-mount files instead of SDS if set to empty. + sdsUdsPath: "" + + # The trust domain corresponds to the trust root of a system. + # Refer to https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE-ID.md#21-trust-domain + trustDomain: "" + + # The trust domain aliases represent the aliases of trust_domain. + # For example, if we have + # trustDomain: td1 + # trustDomainAliases: [“td2”, "td3"] + # Any service with the identity "td1/ns/foo/sa/a-service-account", "td2/ns/foo/sa/a-service-account", + # or "td3/ns/foo/sa/a-service-account" will be treated the same in the Istio mesh. + trustDomainAliases: + + # If true, automatically configure client side mTLS settings to match the corresponding service's + # server side mTLS authentication policy, when destination rule for that service does not specify + # TLS settings. + enableAutoMtls: false + + # Set the default behavior of the sidecar for handling outbound traffic from the application: + # ALLOW_ANY - outbound traffic to unknown destinations will be allowed, in case there are no + # services or ServiceEntries for the destination port + # REGISTRY_ONLY - restrict outbound traffic to services defined in the service registry as well + # as those defined through ServiceEntries + outboundTrafficPolicy: + mode: ALLOW_ANY + localityLbSetting: + enabled: true + # The namespace to treat as the administrative root namespace for istio + # configuration. + rootNamespace: istio-system + + # Configures DNS certificates provisioned through Chiron linked into Pilot. + certificates: + [] + + defaultConfig: + # + # TCP connection timeout between Envoy & the application, and between Envoys. Used for static clusters + # defined in Envoy's configuration file + connectTimeout: 10s + # + ### ADVANCED SETTINGS ############# + # Where should envoy's configuration be stored in the istio-proxy container + configPath: "/etc/istio/proxy" + binaryPath: "/usr/local/bin/envoy" + # The pseudo service name used for Envoy. + serviceCluster: istio-proxy + # These settings that determine how long an old Envoy + # process should be kept alive after an occasional reload. + drainDuration: 45s + parentShutdownDuration: 1m0s + # + # The mode used to redirect inbound connections to Envoy. This setting + # has no effect on outbound traffic: iptables REDIRECT is always used for + # outbound connections. + # If "REDIRECT", use iptables REDIRECT to NAT and redirect to Envoy. + # The "REDIRECT" mode loses source addresses during redirection. + # If "TPROXY", use iptables TPROXY to redirect to Envoy. + # The "TPROXY" mode preserves both the source and destination IP + # addresses and ports, so that they can be used for advanced filtering + # and manipulation. + # The "TPROXY" mode also configures the sidecar to run with the + # CAP_NET_ADMIN capability, which is required to use TPROXY. + #interceptionMode: REDIRECT + # + # Port where Envoy listens (on local host) for admin commands + # You can exec into the istio-proxy container in a pod and + # curl the admin port (curl http://localhost:15000/) to obtain + # diagnostic information from Envoy. See + # https://lyft.github.io/envoy/docs/operations/admin.html + # for more details + proxyAdminPort: 15000 + # + # Set concurrency to a specific number to control the number of Proxy worker threads. + # If set to 0 (default), then start worker thread for each CPU thread/core. + concurrency: 2 + # + tracing: + zipkin: + # Address of the Zipkin collector + address: zipkin.istio-system:9411 + # + # Mutual TLS authentication between sidecars and istio control plane. + controlPlaneAuthPolicy: NONE + # + # Address where istio Pilot service is running + discoveryAddress: istio-pilot.istio-system:15010 + + # Configuration file for the mesh networks to be used by the Split Horizon EDS. + meshNetworks: |- + networks: {} +--- +# Source: istio/charts/gateways/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-ingressgateway-service-account + namespace: istio-system + labels: + app: istio-ingressgateway + chart: gateways + heritage: Helm + release: RELEASE-NAME +--- +# Source: istio/charts/gateways/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: cluster-local-gateway-service-account + namespace: istio-system + labels: + app: cluster-local-gateway + chart: gateways + heritage: Helm + release: RELEASE-NAME +--- +# Source: istio/charts/pilot/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-pilot-service-account + namespace: istio-system + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME +--- +# Source: istio/templates/serviceaccount.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + name: istio-multi + namespace: istio-system +--- +# Source: istio/charts/pilot/templates/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: istio-pilot-istio-system + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME +rules: +- apiGroups: ["config.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["rbac.istio.io"] + resources: ["*"] + verbs: ["get", "watch", "list"] +- apiGroups: ["security.istio.io"] + resources: ["*"] + verbs: ["get", "watch", "list"] +- apiGroups: ["networking.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["authentication.istio.io"] + resources: ["*"] + verbs: ["*"] +- apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["*"] +- apiGroups: ["extensions"] + resources: ["ingresses", "ingresses/status"] + verbs: ["*"] +- apiGroups: [""] + resources: ["configmaps"] + verbs: ["create", "get", "list", "watch", "update"] +- apiGroups: [""] + resources: ["endpoints", "pods", "services", "namespaces", "nodes"] + verbs: ["get", "list", "watch"] +- apiGroups: [""] + resources: ["secrets"] + verbs: ["create", "get", "watch", "list", "update", "delete"] +- apiGroups: ["certificates.k8s.io"] + resources: + - "certificatesigningrequests" + - "certificatesigningrequests/approval" + - "certificatesigningrequests/status" + verbs: ["update", "create", "get", "delete"] +--- +# Source: istio/templates/clusterrole.yaml +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: istio-reader +rules: + - apiGroups: [''] + resources: ['nodes', 'pods', 'services', 'endpoints', "replicationcontrollers"] + verbs: ['get', 'watch', 'list'] + - apiGroups: ["extensions", "apps"] + resources: ["replicasets"] + verbs: ["get", "list", "watch"] +--- +# Source: istio/charts/pilot/templates/clusterrolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istio-pilot-istio-system + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-pilot-istio-system +subjects: + - kind: ServiceAccount + name: istio-pilot-service-account + namespace: istio-system +--- +# Source: istio/templates/clusterrolebinding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: istio-multi + labels: + chart: istio-1.4.3 +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: istio-reader +subjects: +- kind: ServiceAccount + name: istio-multi + namespace: istio-system +--- +# Source: istio/charts/gateways/templates/role.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: istio-ingressgateway-sds + namespace: istio-system +rules: +- apiGroups: [""] + resources: ["secrets"] + verbs: ["get", "watch", "list"] +--- +# Source: istio/charts/gateways/templates/rolebindings.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: istio-ingressgateway-sds + namespace: istio-system +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: istio-ingressgateway-sds +subjects: +- kind: ServiceAccount + name: istio-ingressgateway-service-account +--- +# Source: istio/charts/gateways/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: cluster-local-gateway + namespace: istio-system + annotations: + labels: + chart: gateways + heritage: Helm + release: RELEASE-NAME + app: cluster-local-gateway + istio: cluster-local-gateway +spec: + type: ClusterIP + selector: + release: RELEASE-NAME + app: cluster-local-gateway + istio: cluster-local-gateway + ports: + - + name: status-port + port: 15020 + - + name: http2 + port: 80 + - + name: https + port: 443 +--- +# Source: istio/charts/gateways/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: istio-ingressgateway + namespace: istio-system + annotations: + labels: + chart: gateways + heritage: Helm + release: RELEASE-NAME + app: istio-ingressgateway + istio: ingressgateway +spec: + type: LoadBalancer + selector: + release: RELEASE-NAME + app: istio-ingressgateway + istio: ingressgateway + ports: + - + name: status-port + port: 15020 + - + name: http2 + port: 80 + - + name: https + port: 443 +--- +# Source: istio/charts/pilot/templates/service.yaml +apiVersion: v1 +kind: Service +metadata: + name: istio-pilot + namespace: istio-system + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME + istio: pilot +spec: + ports: + - port: 15010 + name: grpc-xds # direct + - port: 15011 + name: https-xds # mTLS + - port: 8080 + name: http-legacy-discovery # direct + - port: 15014 + name: http-monitoring + selector: + istio: pilot +--- +# Source: istio/charts/gateways/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: istio-ingressgateway + namespace: istio-system + labels: + app: istio-ingressgateway + chart: gateways + heritage: Helm + istio: ingressgateway + release: RELEASE-NAME +spec: + replicas: 1 + selector: + matchLabels: + app: istio-ingressgateway + istio: ingressgateway + strategy: + rollingUpdate: + maxSurge: 100% + maxUnavailable: 25% + template: + metadata: + labels: + app: istio-ingressgateway + chart: gateways + heritage: Helm + istio: ingressgateway + release: RELEASE-NAME + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: istio-ingressgateway-service-account + containers: + - name: ingress-sds + image: "docker.io/istio/node-agent-k8s:1.4.3" + imagePullPolicy: IfNotPresent + resources: + limits: + cpu: 2000m + memory: 1024Mi + requests: + cpu: 100m + memory: 128Mi + env: + - name: "ENABLE_WORKLOAD_SDS" + value: "false" + - name: "ENABLE_INGRESS_GATEWAY_SDS" + value: "true" + - name: "INGRESS_GATEWAY_NAMESPACE" + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + volumeMounts: + - name: ingressgatewaysdsudspath + mountPath: /var/run/ingress_gateway + - name: istio-proxy + image: "docker.io/istio/proxyv2:1.4.3" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 15020 + - containerPort: 80 + - containerPort: 443 + - containerPort: 15090 + protocol: TCP + name: http-envoy-prom + args: + - proxy + - router + - --domain + - $(POD_NAMESPACE).svc.cluster.local + - --log_output_level=default:info + - --drainDuration + - '45s' #drainDuration + - --parentShutdownDuration + - '1m0s' #parentShutdownDuration + - --connectTimeout + - '10s' #connectTimeout + - --serviceCluster + - istio-ingressgateway + - --zipkinAddress + - zipkin:9411 + - --proxyAdminPort + - "15000" + - --statusPort + - "15020" + - --controlPlaneAuthPolicy + - NONE + - --discoveryAddress + - istio-pilot:15010 + readinessProbe: + failureThreshold: 30 + httpGet: + path: /healthz/ready + port: 15020 + scheme: HTTP + initialDelaySeconds: 1 + periodSeconds: 2 + successThreshold: 1 + timeoutSeconds: 1 + resources: + limits: + cpu: 2000m + memory: 1024Mi + requests: + cpu: 100m + memory: 128Mi + env: + - name: NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + - name: HOST_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + - name: SERVICE_ACCOUNT + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: ISTIO_META_CONFIG_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: ISTIO_METAJSON_LABELS + value: | + {"app":"istio-ingressgateway","chart":"gateways","heritage":"Helm","istio":"ingressgateway","release":"RELEASE-NAME"} + - name: ISTIO_META_CLUSTER_ID + value: "Kubernetes" + - name: SDS_ENABLED + value: "false" + - name: ISTIO_META_WORKLOAD_NAME + value: istio-ingressgateway + - name: ISTIO_META_OWNER + value: kubernetes://apis/apps/v1/namespaces/istio-system/deployments/istio-ingressgateway + - name: ISTIO_META_USER_SDS + value: "true" + - name: ISTIO_META_ROUTER_MODE + value: sni-dnat + + + volumeMounts: + - name: ingressgatewaysdsudspath + mountPath: /var/run/ingress_gateway + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: ingressgateway-certs + mountPath: "/etc/istio/ingressgateway-certs" + readOnly: true + - name: ingressgateway-ca-certs + mountPath: "/etc/istio/ingressgateway-ca-certs" + readOnly: true + volumes: + - name: ingressgatewaysdsudspath + emptyDir: {} + - name: istio-certs + secret: + secretName: istio.istio-ingressgateway-service-account + optional: true + - name: ingressgateway-certs + secret: + secretName: "istio-ingressgateway-certs" + optional: true + - name: ingressgateway-ca-certs + secret: + secretName: "istio-ingressgateway-ca-certs" + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - "ppc64le" + - "s390x" + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "ppc64le" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "s390x" +--- +# Source: istio/charts/gateways/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: cluster-local-gateway + namespace: istio-system + labels: + app: cluster-local-gateway + chart: gateways + heritage: Helm + istio: cluster-local-gateway + release: RELEASE-NAME +spec: + replicas: 1 + selector: + matchLabels: + app: cluster-local-gateway + istio: cluster-local-gateway + strategy: + rollingUpdate: + maxSurge: + maxUnavailable: + template: + metadata: + labels: + app: cluster-local-gateway + chart: gateways + heritage: Helm + istio: cluster-local-gateway + release: RELEASE-NAME + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: cluster-local-gateway-service-account + containers: + - name: istio-proxy + image: "docker.io/istio/proxyv2:1.4.3" + imagePullPolicy: IfNotPresent + ports: + - containerPort: 15020 + - containerPort: 80 + - containerPort: 443 + - containerPort: 15090 + protocol: TCP + name: http-envoy-prom + args: + - proxy + - router + - --domain + - $(POD_NAMESPACE).svc.cluster.local + - --log_output_level=default:info + - --drainDuration + - '45s' #drainDuration + - --parentShutdownDuration + - '1m0s' #parentShutdownDuration + - --connectTimeout + - '10s' #connectTimeout + - --serviceCluster + - cluster-local-gateway + - --zipkinAddress + - zipkin:9411 + - --proxyAdminPort + - "15000" + - --statusPort + - "15020" + - --controlPlaneAuthPolicy + - NONE + - --discoveryAddress + - istio-pilot:15010 + readinessProbe: + failureThreshold: 30 + httpGet: + path: /healthz/ready + port: 15020 + scheme: HTTP + initialDelaySeconds: 1 + periodSeconds: 2 + successThreshold: 1 + timeoutSeconds: 1 + resources: + requests: + cpu: 100m + memory: 128Mi + env: + - name: NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: INSTANCE_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.podIP + - name: HOST_IP + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: status.hostIP + - name: SERVICE_ACCOUNT + valueFrom: + fieldRef: + fieldPath: spec.serviceAccountName + - name: ISTIO_META_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: ISTIO_META_CONFIG_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: ISTIO_METAJSON_LABELS + value: | + {"app":"cluster-local-gateway","chart":"gateways","heritage":"Helm","istio":"cluster-local-gateway","release":"RELEASE-NAME"} + - name: ISTIO_META_CLUSTER_ID + value: "Kubernetes" + - name: SDS_ENABLED + value: "false" + - name: ISTIO_META_WORKLOAD_NAME + value: cluster-local-gateway + - name: ISTIO_META_OWNER + value: kubernetes://apis/apps/v1/namespaces/istio-system/deployments/cluster-local-gateway + + volumeMounts: + - name: istio-certs + mountPath: /etc/certs + readOnly: true + - name: cluster-local-gateway-certs + mountPath: "/etc/istio/cluster-local-gateway-certs" + readOnly: true + - name: cluster-local-gateway-ca-certs + mountPath: "/etc/istio/cluster-local-gateway-ca-certs" + readOnly: true + volumes: + - name: istio-certs + secret: + secretName: istio.cluster-local-gateway-service-account + optional: true + - name: cluster-local-gateway-certs + secret: + secretName: "istio-cluster-local-gateway-certs" + optional: true + - name: cluster-local-gateway-ca-certs + secret: + secretName: "istio-cluster-local-gateway-ca-certs" + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - "ppc64le" + - "s390x" + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "ppc64le" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "s390x" +--- +# Source: istio/charts/pilot/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: istio-pilot + namespace: istio-system + # TODO: default template doesn't have this, which one is right ? + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME + istio: pilot +spec: + replicas: 1 + strategy: + rollingUpdate: + maxSurge: 100% + maxUnavailable: 25% + selector: + matchLabels: + istio: pilot + template: + metadata: + labels: + app: pilot + chart: pilot + heritage: Helm + release: RELEASE-NAME + istio: pilot + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: istio-pilot-service-account + containers: + - name: discovery + image: "docker.io/istio/pilot:1.4.3" + imagePullPolicy: IfNotPresent + args: + - "discovery" + - --monitoringAddr=:15014 + - --log_output_level=default:info + - --domain + - cluster.local + - --secureGrpcAddr + - "" + - --keepaliveMaxServerConnectionAge + - "30m" + ports: + - containerPort: 8080 + - containerPort: 15010 + - containerPort: 15011 + readinessProbe: + httpGet: + path: /ready + port: 8080 + initialDelaySeconds: 5 + periodSeconds: 5 + timeoutSeconds: 5 + env: + - name: POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: POD_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: PILOT_PUSH_THROTTLE + value: "100" + - name: PILOT_TRACE_SAMPLING + value: "100" + - name: PILOT_ENABLE_PROTOCOL_SNIFFING_FOR_OUTBOUND + value: "true" + - name: PILOT_ENABLE_PROTOCOL_SNIFFING_FOR_INBOUND + value: "false" + resources: + requests: + cpu: 100m + memory: 128Mi + volumeMounts: + - name: config-volume + mountPath: /etc/istio/config + - name: istio-certs + mountPath: /etc/certs + readOnly: true + volumes: + - name: config-volume + configMap: + name: istio + - name: istio-certs + secret: + secretName: istio.istio-pilot-service-account + optional: true + affinity: + nodeAffinity: + requiredDuringSchedulingIgnoredDuringExecution: + nodeSelectorTerms: + - matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - "ppc64le" + - "s390x" + preferredDuringSchedulingIgnoredDuringExecution: + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "amd64" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "ppc64le" + - weight: 2 + preference: + matchExpressions: + - key: beta.kubernetes.io/arch + operator: In + values: + - "s390x" diff --git a/third_party/istio-1.4.3/namespace.yaml.patch b/third_party/istio-1.4.3/namespace.yaml.patch new file mode 100644 index 00000000000..3e15f44aa1b --- /dev/null +++ b/third_party/istio-1.4.3/namespace.yaml.patch @@ -0,0 +1,10 @@ +1a2,10 +> # PATCH #1: Creating the istio-system namespace. +> apiVersion: v1 +> kind: Namespace +> metadata: +> name: istio-system +> labels: +> istio-injection: disabled +> # PATCH #1 ends. +> --- diff --git a/third_party/istio-1.4.3/values-extras.yaml b/third_party/istio-1.4.3/values-extras.yaml new file mode 100644 index 00000000000..d6f2d68edea --- /dev/null +++ b/third_party/istio-1.4.3/values-extras.yaml @@ -0,0 +1,86 @@ +global: + proxy: + # Enable proxy to write access log to /dev/stdout. + accessLogFile: "/dev/stdout" + autoInject: disabled + disablePolicyChecks: true + omitSidecarInjectorConfigMap: true + defaultPodDisruptionBudget: + enabled: false + useMCP: false + +sidecarInjectorWebhook: + enabled: false + enableNamespacesByDefault: false + +gateways: + enabled: true + + istio-ingressgateway: + enabled: false + istio-egressgateway: + enabled: false + istio-ilbgateway: + enabled: false + + cluster-local-gateway: + enabled: true + labels: + app: cluster-local-gateway + istio: cluster-local-gateway + replicaCount: 1 + autoscaleMin: 1 + autoscaleMax: 1 + resources: {} + cpu: + targetAverageUtilization: 80 + loadBalancerIP: "" + loadBalancerSourceRanges: {} + externalIPs: [] + serviceAnnotations: {} + podAnnotations: {} + type: ClusterIP + ports: + - name: status-port + port: 15020 + - name: http2 + port: 80 + - name: https + port: 443 + secretVolumes: + - name: cluster-local-gateway-certs + secretName: istio-cluster-local-gateway-certs + mountPath: /etc/istio/cluster-local-gateway-certs + - name: cluster-local-gateway-ca-certs + secretName: istio-cluster-local-gateway-ca-certs + mountPath: /etc/istio/cluster-local-gateway-ca-certs + +security: + enabled: false + +galley: + enabled: false + +mixer: + policy: + enabled: false + telemetry: + enabled: false + +pilot: + enabled: false + +grafana: + enabled: false + +prometheus: + enabled: false + +tracing: + enabled: false + +kiali: + enabled: false + +certmanager: + enabled: false diff --git a/third_party/istio-1.4.3/values-lean.yaml b/third_party/istio-1.4.3/values-lean.yaml new file mode 100644 index 00000000000..726abf12feb --- /dev/null +++ b/third_party/istio-1.4.3/values-lean.yaml @@ -0,0 +1,96 @@ +global: + proxy: + # Enable proxy to write access log to /dev/stdout. + accessLogFile: "/dev/stdout" + accessLogEncoding: 'JSON' + autoInject: disabled + disablePolicyChecks: true + omitSidecarInjectorConfigMap: true + defaultPodDisruptionBudget: + enabled: false + useMCP: false + +sidecarInjectorWebhook: + enabled: false + enableNamespacesByDefault: false + +gateways: + istio-ingressgateway: + enabled: true + sds: + enabled: true + replicaCount: 2 + autoscaleMin: 2 + autoscaleMax: 5 + resources: + requests: + cpu: 1000m + memory: 1024Mi + ports: + - name: status-port + port: 15020 + - name: http2 + port: 80 + - port: 443 + name: https + cluster-local-gateway: + enabled: true + labels: + app: cluster-local-gateway + istio: cluster-local-gateway + replicaCount: 2 + autoscaleMin: 2 + autoscaleMax: 5 + resources: + requests: + cpu: 1000m + memory: 1024Mi + cpu: + targetAverageUtilization: 80 + loadBalancerIP: "" + loadBalancerSourceRanges: {} + externalIPs: [] + serviceAnnotations: {} + podAnnotations: {} + type: ClusterIP + ports: + - name: status-port + port: 15020 + - name: http2 + port: 80 + - name: https + port: 443 + secretVolumes: + - name: cluster-local-gateway-certs + secretName: istio-cluster-local-gateway-certs + mountPath: /etc/istio/cluster-local-gateway-certs + - name: cluster-local-gateway-ca-certs + secretName: istio-cluster-local-gateway-ca-certs + mountPath: /etc/istio/cluster-local-gateway-ca-certs + +prometheus: + enabled: false + +mixer: + enabled: false + policy: + enabled: false + telemetry: + enabled: false + adapters: + prometheus: + enabled: false + +pilot: + traceSampling: 100 + sidecar: false + resources: + requests: + cpu: 1000m + memory: 1024Mi + +galley: + enabled: true + +security: + enabled: true diff --git a/third_party/istio-1.4.3/values-local.yaml b/third_party/istio-1.4.3/values-local.yaml new file mode 100644 index 00000000000..0f2f0ada03c --- /dev/null +++ b/third_party/istio-1.4.3/values-local.yaml @@ -0,0 +1,91 @@ +global: + proxy: + # Enable proxy to write access log to /dev/stdout. + accessLogFile: "/dev/stdout" + accessLogEncoding: 'JSON' + autoInject: disabled + disablePolicyChecks: true + omitSidecarInjectorConfigMap: true + defaultPodDisruptionBudget: + enabled: false + useMCP: false + +sidecarInjectorWebhook: + enabled: false + enableNamespacesByDefault: false + +gateways: + istio-ingressgateway: + enabled: true + sds: + enabled: true + autoscaleEnabled: false + resources: + requests: + cpu: 100m + memory: 128Mi + ports: + - name: status-port + port: 15020 + - name: http2 + port: 80 + - port: 443 + name: https + cluster-local-gateway: + enabled: true + labels: + app: cluster-local-gateway + istio: cluster-local-gateway + autoscaleEnabled: false + resources: + requests: + cpu: 100m + memory: 128Mi + loadBalancerIP: "" + loadBalancerSourceRanges: {} + externalIPs: [] + serviceAnnotations: {} + podAnnotations: {} + type: ClusterIP + ports: + - name: status-port + port: 15020 + - name: http2 + port: 80 + - name: https + port: 443 + secretVolumes: + - name: cluster-local-gateway-certs + secretName: istio-cluster-local-gateway-certs + mountPath: /etc/istio/cluster-local-gateway-certs + - name: cluster-local-gateway-ca-certs + secretName: istio-cluster-local-gateway-ca-certs + mountPath: /etc/istio/cluster-local-gateway-ca-certs + +prometheus: + enabled: false + +mixer: + enabled: false + policy: + enabled: false + telemetry: + enabled: false + adapters: + prometheus: + enabled: false + +pilot: + traceSampling: 100 + sidecar: false + autoscaleEnabled: false + resources: + requests: + cpu: 100m + memory: 128Mi + +galley: + enabled: false + +security: + enabled: false diff --git a/third_party/istio-1.4.3/values.yaml b/third_party/istio-1.4.3/values.yaml new file mode 100644 index 00000000000..96fe0a36bf8 --- /dev/null +++ b/third_party/istio-1.4.3/values.yaml @@ -0,0 +1,85 @@ +global: + proxy: + # Enable proxy to write access log to /dev/stdout. + accessLogFile: "/dev/stdout" + accessLogEncoding: 'JSON' + autoInject: enabled + disablePolicyChecks: true + +sidecarInjectorWebhook: + enabled: true + enableNamespacesByDefault: false + rewriteAppHTTPProbe: true + +gateways: + istio-ingressgateway: + enabled: true + sds: + enabled: true + replicaCount: 2 + autoscaleMin: 2 + autoscaleMax: 4 + resources: + limits: + cpu: 3000m + memory: 2048Mi + requests: + cpu: 3000m + memory: 2048Mi + ports: + - name: status-port + port: 15020 + - name: http2 + port: 80 + - port: 443 + name: https + cluster-local-gateway: + enabled: true + labels: + app: cluster-local-gateway + istio: cluster-local-gateway + replicaCount: 2 + autoscaleMin: 2 + autoscaleMax: 4 + resources: + requests: + cpu: 250m + memory: 256Mi + cpu: + targetAverageUtilization: 80 + loadBalancerIP: "" + loadBalancerSourceRanges: {} + externalIPs: [] + serviceAnnotations: {} + podAnnotations: {} + type: ClusterIP + ports: + - name: status-port + port: 15020 + - name: http2 + port: 80 + - name: https + port: 443 + secretVolumes: + - name: cluster-local-gateway-certs + secretName: istio-cluster-local-gateway-certs + mountPath: /etc/istio/cluster-local-gateway-certs + - name: cluster-local-gateway-ca-certs + secretName: istio-cluster-local-gateway-ca-certs + mountPath: /etc/istio/cluster-local-gateway-ca-certs + +prometheus: + enabled: false + +mixer: + adapters: + prometheus: + enabled: false + +pilot: + traceSampling: 100 + autoscaleMin: 2 + resources: + requests: + cpu: 3000m + memory: 2048Mi diff --git a/third_party/istio-latest b/third_party/istio-latest new file mode 120000 index 00000000000..04a23d20f0e --- /dev/null +++ b/third_party/istio-latest @@ -0,0 +1 @@ +istio-1.4-latest \ No newline at end of file From e13bf3fb75b75b18d81813e680588bb15bda5b5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Mon, 13 Jan 2020 14:29:15 +0100 Subject: [PATCH 04/50] Delete non required Istio files --- third_party/istio-1.4.3/README.md | 10 +- third_party/istio-1.4.3/download-istio.sh | 24 - .../istio-1.4.3/drain-seconds.yaml.patch | 5 - third_party/istio-1.4.3/istio-ci-mesh.yaml | 3534 ----------------- third_party/istio-1.4.3/istio-ci-no-mesh.yaml | 1738 -------- .../istio-1.4.3/istio-knative-extras.yaml | 268 -- third_party/istio-1.4.3/values-extras.yaml | 86 - third_party/istio-1.4.3/values-lean.yaml | 96 - third_party/istio-1.4.3/values.yaml | 85 - 9 files changed, 3 insertions(+), 5843 deletions(-) delete mode 100644 third_party/istio-1.4.3/drain-seconds.yaml.patch delete mode 100644 third_party/istio-1.4.3/istio-ci-mesh.yaml delete mode 100644 third_party/istio-1.4.3/istio-ci-no-mesh.yaml delete mode 100644 third_party/istio-1.4.3/istio-knative-extras.yaml delete mode 100644 third_party/istio-1.4.3/values-extras.yaml delete mode 100644 third_party/istio-1.4.3/values-lean.yaml delete mode 100644 third_party/istio-1.4.3/values.yaml diff --git a/third_party/istio-1.4.3/README.md b/third_party/istio-1.4.3/README.md index cffd8e93a3b..26610d90843 100644 --- a/third_party/istio-1.4.3/README.md +++ b/third_party/istio-1.4.3/README.md @@ -4,14 +4,10 @@ The istio\*.yaml files are generated by running ./download-istio.sh ``` -using Helm v3.0.1. +using Helm v3.0.2. The generated files are: -- istio-ci-no-mesh.yaml: used in our continuous testing of Knative with Istio - having sidecar disabled. This is also the setting that we use in our presubmit - tests. -- istio-ci-mesh.yaml: used in our continuous testing of Knative with Istio - having sidecar and mTLS enabled. -- istio-minimal.yaml: a minimal Istio installation used for development +- `istio-crd.yaml`: an Istio custom resource definitions. +- `istio-minimal.yaml`: a minimal Istio installation used for development purposes. diff --git a/third_party/istio-1.4.3/download-istio.sh b/third_party/istio-1.4.3/download-istio.sh index 399a80eb688..7566c55247d 100755 --- a/third_party/istio-1.4.3/download-istio.sh +++ b/third_party/istio-1.4.3/download-istio.sh @@ -35,25 +35,6 @@ helm template --namespace=istio-system \ | sed 's/[ \t]*$//' \ > ../istio-crds.yaml -# Create a custom cluster local gateway, based on the Istio custom-gateway template. -helm template --namespace=istio-system install/kubernetes/helm/istio --values ../values-extras.yaml \ - `# Removing trailing whitespaces to make automation happy` \ - | sed 's/[ \t]*$//' \ - > ../istio-knative-extras.yaml - -# A template with sidecar injection enabled. -helm template --namespace=istio-system install/kubernetes/helm/istio --values ../values.yaml \ - `# Removing trailing whitespaces to make automation happy` \ - | sed 's/[ \t]*$//' \ - > ../istio-ci-mesh.yaml - -# A lighter template, with just pilot/gateway. -# Based on install/kubernetes/helm/istio/values-istio-minimal.yaml -helm template --namespace=istio-system install/kubernetes/helm/istio --values ../values-lean.yaml \ - `# Removing trailing whitespaces to make automation happy` \ - | sed 's/[ \t]*$//' \ - > ../istio-ci-no-mesh.yaml - # An even lighter template, with just pilot/gateway and small resource requests. # Based on install/kubernetes/helm/istio/values-istio-minimal.yaml helm template --namespace=istio-system install/kubernetes/helm/istio --values ../values-local.yaml \ @@ -68,9 +49,4 @@ rm istio-${ISTIO_VERSION}-linux.tar.gz # Add in the `istio-system` namespace to reduce number of commands. patch istio-crds.yaml namespace.yaml.patch -patch istio-ci-mesh.yaml namespace.yaml.patch -patch istio-ci-no-mesh.yaml namespace.yaml.patch patch istio-minimal.yaml namespace.yaml.patch - -# Increase termination drain duration seconds. -patch -l istio-ci-mesh.yaml drain-seconds.yaml.patch diff --git a/third_party/istio-1.4.3/drain-seconds.yaml.patch b/third_party/istio-1.4.3/drain-seconds.yaml.patch deleted file mode 100644 index c4316c58c0c..00000000000 --- a/third_party/istio-1.4.3/drain-seconds.yaml.patch +++ /dev/null @@ -1,5 +0,0 @@ -820a821,824 -> # PATCH #2: Increase termination drain duration. -> - name: TERMINATION_DRAIN_DURATION_SECONDS -> value: "20" -> # PATCH #2 ends. diff --git a/third_party/istio-1.4.3/istio-ci-mesh.yaml b/third_party/istio-1.4.3/istio-ci-mesh.yaml deleted file mode 100644 index f635a6c359c..00000000000 --- a/third_party/istio-1.4.3/istio-ci-mesh.yaml +++ /dev/null @@ -1,3534 +0,0 @@ ---- -# PATCH #1: Creating the istio-system namespace. -apiVersion: v1 -kind: Namespace -metadata: - name: istio-system - labels: - istio-injection: disabled -# PATCH #1 ends. ---- -# Source: istio/charts/galley/templates/poddisruptionbudget.yaml -apiVersion: policy/v1beta1 -kind: PodDisruptionBudget -metadata: - name: istio-galley - namespace: istio-system - labels: - app: galley - chart: galley - heritage: Helm - release: RELEASE-NAME - istio: galley -spec: - - minAvailable: 1 - selector: - matchLabels: - app: galley - release: RELEASE-NAME - istio: galley ---- -# Source: istio/charts/gateways/templates/poddisruptionbudget.yaml -apiVersion: policy/v1beta1 -kind: PodDisruptionBudget -metadata: - name: cluster-local-gateway - namespace: istio-system - labels: - chart: gateways - heritage: Helm - release: RELEASE-NAME - app: cluster-local-gateway - istio: cluster-local-gateway -spec: - - minAvailable: 1 - selector: - matchLabels: - release: RELEASE-NAME - app: cluster-local-gateway - istio: cluster-local-gateway ---- -# Source: istio/charts/gateways/templates/poddisruptionbudget.yaml -apiVersion: policy/v1beta1 -kind: PodDisruptionBudget -metadata: - name: istio-ingressgateway - namespace: istio-system - labels: - chart: gateways - heritage: Helm - release: RELEASE-NAME - app: istio-ingressgateway - istio: ingressgateway -spec: - - minAvailable: 1 - selector: - matchLabels: - release: RELEASE-NAME - app: istio-ingressgateway - istio: ingressgateway ---- -# Source: istio/charts/mixer/templates/poddisruptionbudget.yaml -apiVersion: policy/v1beta1 -kind: PodDisruptionBudget -metadata: - name: istio-policy - namespace: istio-system - labels: - app: policy - chart: mixer - heritage: Helm - release: RELEASE-NAME - version: 1.4.3 - istio: mixer - istio-mixer-type: policy -spec: - - minAvailable: 1 - selector: - matchLabels: - app: policy - release: RELEASE-NAME - istio: mixer - istio-mixer-type: policy ---- -# Source: istio/charts/mixer/templates/poddisruptionbudget.yaml -apiVersion: policy/v1beta1 -kind: PodDisruptionBudget -metadata: - name: istio-telemetry - namespace: istio-system - labels: - app: telemetry - chart: mixer - heritage: Helm - release: RELEASE-NAME - version: 1.4.3 - istio: mixer - istio-mixer-type: telemetry -spec: - - minAvailable: 1 - selector: - matchLabels: - app: telemetry - release: RELEASE-NAME - istio: mixer - istio-mixer-type: telemetry ---- -# Source: istio/charts/pilot/templates/poddisruptionbudget.yaml -apiVersion: policy/v1beta1 -kind: PodDisruptionBudget -metadata: - name: istio-pilot - namespace: istio-system - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME - istio: pilot -spec: - - minAvailable: 1 - selector: - matchLabels: - app: pilot - release: RELEASE-NAME - istio: pilot ---- -# Source: istio/charts/security/templates/poddisruptionbudget.yaml -apiVersion: policy/v1beta1 -kind: PodDisruptionBudget -metadata: - name: istio-citadel - namespace: istio-system - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME - istio: citadel -spec: - - minAvailable: 1 - selector: - matchLabels: - app: security - release: RELEASE-NAME - istio: citadel ---- -# Source: istio/charts/sidecarInjectorWebhook/templates/poddisruptionbudget.yaml -apiVersion: policy/v1beta1 -kind: PodDisruptionBudget -metadata: - name: istio-sidecar-injector - namespace: istio-system - labels: - app: sidecarInjectorWebhook - release: RELEASE-NAME - istio: sidecar-injector -spec: - - minAvailable: 1 - selector: - matchLabels: - app: sidecarInjectorWebhook - release: RELEASE-NAME - istio: sidecar-injector ---- -# Source: istio/charts/galley/templates/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: istio-galley-configuration - namespace: istio-system - labels: - app: galley - chart: galley - heritage: Helm - release: RELEASE-NAME - istio: galley -data: - validatingwebhookconfiguration.yaml: |- - apiVersion: admissionregistration.k8s.io/v1beta1 - kind: ValidatingWebhookConfiguration - metadata: - name: istio-galley - labels: - app: galley - chart: galley - heritage: Helm - release: RELEASE-NAME - istio: galley - webhooks: - - name: pilot.validation.istio.io - clientConfig: - service: - name: istio-galley - namespace: istio-system - path: "/admitpilot" - caBundle: "" - rules: - - operations: - - CREATE - - UPDATE - apiGroups: - - config.istio.io - apiVersions: - - v1alpha2 - resources: - - httpapispecs - - httpapispecbindings - - quotaspecs - - quotaspecbindings - - operations: - - CREATE - - UPDATE - apiGroups: - - rbac.istio.io - apiVersions: - - "*" - resources: - - "*" - - operations: - - CREATE - - UPDATE - apiGroups: - - security.istio.io - apiVersions: - - "*" - resources: - - "*" - - operations: - - CREATE - - UPDATE - apiGroups: - - authentication.istio.io - apiVersions: - - "*" - resources: - - "*" - - operations: - - CREATE - - UPDATE - apiGroups: - - networking.istio.io - apiVersions: - - "*" - resources: - - destinationrules - - envoyfilters - - gateways - - serviceentries - - sidecars - - virtualservices - failurePolicy: Fail - sideEffects: None - - name: mixer.validation.istio.io - clientConfig: - service: - name: istio-galley - namespace: istio-system - path: "/admitmixer" - caBundle: "" - rules: - - operations: - - CREATE - - UPDATE - apiGroups: - - config.istio.io - apiVersions: - - v1alpha2 - resources: - - rules - - attributemanifests - - circonuses - - deniers - - fluentds - - kubernetesenvs - - listcheckers - - memquotas - - noops - - opas - - prometheuses - - rbacs - - solarwindses - - stackdrivers - - cloudwatches - - dogstatsds - - statsds - - stdios - - apikeys - - authorizations - - checknothings - # - kuberneteses - - listentries - - logentries - - metrics - - quotas - - reportnothings - - tracespans - - adapters - - handlers - - instances - - templates - - zipkins - failurePolicy: Fail - sideEffects: None ---- -# Source: istio/charts/security/templates/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: istio-security-custom-resources - namespace: istio-system - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME - istio: citadel -data: - custom-resources.yaml: |- - # Authentication policy to enable permissive mode for all services (that have sidecar) in the mesh. - apiVersion: "authentication.istio.io/v1alpha1" - kind: "MeshPolicy" - metadata: - name: "default" - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME - spec: - peers: - - mtls: - mode: PERMISSIVE - run.sh: |- - #!/bin/sh - - set -x - - if [ "$#" -ne "1" ]; then - echo "first argument should be path to custom resource yaml" - exit 1 - fi - - pathToResourceYAML=${1} - - kubectl get validatingwebhookconfiguration istio-galley 2>/dev/null - if [ "$?" -eq 0 ]; then - echo "istio-galley validatingwebhookconfiguration found - waiting for istio-galley deployment to be ready" - while true; do - kubectl -n istio-system get deployment istio-galley 2>/dev/null - if [ "$?" -eq 0 ]; then - break - fi - sleep 1 - done - kubectl -n istio-system rollout status deployment istio-galley - if [ "$?" -ne 0 ]; then - echo "istio-galley deployment rollout status check failed" - exit 1 - fi - echo "istio-galley deployment ready for configuration validation" - fi - sleep 5 - kubectl apply -f ${pathToResourceYAML} ---- -# Source: istio/templates/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: istio - namespace: istio-system - labels: - app: istio - chart: istio - heritage: Helm - release: RELEASE-NAME -data: - mesh: |- - # Set the following variable to true to disable policy checks by Mixer. - # Note that metrics will still be reported to Mixer. - disablePolicyChecks: true - - disableMixerHttpReports: false - # reportBatchMaxEntries is the number of requests that are batched before telemetry data is sent to the mixer server - reportBatchMaxEntries: 100 - # reportBatchMaxTime is the max waiting time before the telemetry data of a request is sent to the mixer server - reportBatchMaxTime: 1s - - # Set enableTracing to false to disable request tracing. - enableTracing: true - - # Set accessLogFile to empty string to disable access log. - accessLogFile: "/dev/stdout" - - # If accessLogEncoding is TEXT, value will be used directly as the log format - # example: "[%START_TIME%] %REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\n" - # If AccessLogEncoding is JSON, value will be parsed as map[string]string - # example: '{"start_time": "%START_TIME%", "req_method": "%REQ(:METHOD)%"}' - # Leave empty to use default log format - accessLogFormat: "" - - # Set accessLogEncoding to JSON or TEXT to configure sidecar access log - accessLogEncoding: 'JSON' - - enableEnvoyAccessLogService: false - mixerCheckServer: istio-policy.istio-system.svc.cluster.local:9091 - mixerReportServer: istio-telemetry.istio-system.svc.cluster.local:9091 - # policyCheckFailOpen allows traffic in cases when the mixer policy service cannot be reached. - # Default is false which means the traffic is denied when the client is unable to connect to Mixer. - policyCheckFailOpen: false - # Let Pilot give ingresses the public IP of the Istio ingressgateway - ingressService: istio-ingressgateway - - # Default connect timeout for dynamic clusters generated by Pilot and returned via XDS - connectTimeout: 10s - - # Automatic protocol detection uses a set of heuristics to - # determine whether the connection is using TLS or not (on the - # server side), as well as the application protocol being used - # (e.g., http vs tcp). These heuristics rely on the client sending - # the first bits of data. For server first protocols like MySQL, - # MongoDB, etc., Envoy will timeout on the protocol detection after - # the specified period, defaulting to non mTLS plain TCP - # traffic. Set this field to tweak the period that Envoy will wait - # for the client to send the first bits of data. (MUST BE >=1ms) - protocolDetectionTimeout: 100ms - - # DNS refresh rate for Envoy clusters of type STRICT_DNS - dnsRefreshRate: 300s - - # Unix Domain Socket through which envoy communicates with NodeAgent SDS to get - # key/cert for mTLS. Use secret-mount files instead of SDS if set to empty. - sdsUdsPath: "" - - # The trust domain corresponds to the trust root of a system. - # Refer to https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE-ID.md#21-trust-domain - trustDomain: "" - - # The trust domain aliases represent the aliases of trust_domain. - # For example, if we have - # trustDomain: td1 - # trustDomainAliases: [“td2”, "td3"] - # Any service with the identity "td1/ns/foo/sa/a-service-account", "td2/ns/foo/sa/a-service-account", - # or "td3/ns/foo/sa/a-service-account" will be treated the same in the Istio mesh. - trustDomainAliases: - - # If true, automatically configure client side mTLS settings to match the corresponding service's - # server side mTLS authentication policy, when destination rule for that service does not specify - # TLS settings. - enableAutoMtls: false - - # Set the default behavior of the sidecar for handling outbound traffic from the application: - # ALLOW_ANY - outbound traffic to unknown destinations will be allowed, in case there are no - # services or ServiceEntries for the destination port - # REGISTRY_ONLY - restrict outbound traffic to services defined in the service registry as well - # as those defined through ServiceEntries - outboundTrafficPolicy: - mode: ALLOW_ANY - localityLbSetting: - enabled: true - # The namespace to treat as the administrative root namespace for istio - # configuration. - rootNamespace: istio-system - - # Configures DNS certificates provisioned through Chiron linked into Pilot. - certificates: - [] - configSources: - - address: istio-galley.istio-system.svc:9901 - - defaultConfig: - # - # TCP connection timeout between Envoy & the application, and between Envoys. Used for static clusters - # defined in Envoy's configuration file - connectTimeout: 10s - # - ### ADVANCED SETTINGS ############# - # Where should envoy's configuration be stored in the istio-proxy container - configPath: "/etc/istio/proxy" - binaryPath: "/usr/local/bin/envoy" - # The pseudo service name used for Envoy. - serviceCluster: istio-proxy - # These settings that determine how long an old Envoy - # process should be kept alive after an occasional reload. - drainDuration: 45s - parentShutdownDuration: 1m0s - # - # The mode used to redirect inbound connections to Envoy. This setting - # has no effect on outbound traffic: iptables REDIRECT is always used for - # outbound connections. - # If "REDIRECT", use iptables REDIRECT to NAT and redirect to Envoy. - # The "REDIRECT" mode loses source addresses during redirection. - # If "TPROXY", use iptables TPROXY to redirect to Envoy. - # The "TPROXY" mode preserves both the source and destination IP - # addresses and ports, so that they can be used for advanced filtering - # and manipulation. - # The "TPROXY" mode also configures the sidecar to run with the - # CAP_NET_ADMIN capability, which is required to use TPROXY. - #interceptionMode: REDIRECT - # - # Port where Envoy listens (on local host) for admin commands - # You can exec into the istio-proxy container in a pod and - # curl the admin port (curl http://localhost:15000/) to obtain - # diagnostic information from Envoy. See - # https://lyft.github.io/envoy/docs/operations/admin.html - # for more details - proxyAdminPort: 15000 - # - # Set concurrency to a specific number to control the number of Proxy worker threads. - # If set to 0 (default), then start worker thread for each CPU thread/core. - concurrency: 2 - # - tracing: - zipkin: - # Address of the Zipkin collector - address: zipkin.istio-system:9411 - # - # Mutual TLS authentication between sidecars and istio control plane. - controlPlaneAuthPolicy: NONE - # - # Address where istio Pilot service is running - discoveryAddress: istio-pilot.istio-system:15010 - - # Configuration file for the mesh networks to be used by the Split Horizon EDS. - meshNetworks: |- - networks: {} ---- -# Source: istio/templates/sidecar-injector-configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: istio-sidecar-injector - namespace: istio-system - labels: - app: istio - chart: istio - heritage: Helm - release: RELEASE-NAME - istio: sidecar-injector -data: - values: |- - {"certmanager":{"enabled":false,"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"hub":"quay.io/jetstack","image":"cert-manager-controller","nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"replicaCount":1,"resources":{},"tag":"v0.8.1","tolerations":[]},"galley":{"enableAnalysis":false,"enableServiceDiscovery":false,"enabled":true,"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"image":"galley","nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"replicaCount":1,"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%","tolerations":[]},"gateways":{"cluster-local-gateway":{"autoscaleMax":4,"autoscaleMin":2,"cpu":{"targetAverageUtilization":80},"enabled":true,"externalIPs":[],"labels":{"app":"cluster-local-gateway","istio":"cluster-local-gateway"},"loadBalancerIP":"","loadBalancerSourceRanges":{},"podAnnotations":{},"ports":[{"name":"status-port","port":15020},{"name":"http2","port":80},{"name":"https","port":443}],"replicaCount":2,"resources":{"requests":{"cpu":"250m","memory":"256Mi"}},"secretVolumes":[{"mountPath":"/etc/istio/cluster-local-gateway-certs","name":"cluster-local-gateway-certs","secretName":"istio-cluster-local-gateway-certs"},{"mountPath":"/etc/istio/cluster-local-gateway-ca-certs","name":"cluster-local-gateway-ca-certs","secretName":"istio-cluster-local-gateway-ca-certs"}],"serviceAnnotations":{},"type":"ClusterIP"},"enabled":true,"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"istio-egressgateway":{"autoscaleEnabled":true,"autoscaleMax":5,"autoscaleMin":1,"cpu":{"targetAverageUtilization":80},"enabled":false,"env":{"ISTIO_META_ROUTER_MODE":"sni-dnat"},"labels":{"app":"istio-egressgateway","istio":"egressgateway"},"nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"ports":[{"name":"http2","port":80},{"name":"https","port":443},{"name":"tls","port":15443,"targetPort":15443}],"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%","secretVolumes":[{"mountPath":"/etc/istio/egressgateway-certs","name":"egressgateway-certs","secretName":"istio-egressgateway-certs"},{"mountPath":"/etc/istio/egressgateway-ca-certs","name":"egressgateway-ca-certs","secretName":"istio-egressgateway-ca-certs"}],"serviceAnnotations":{},"tolerations":[],"type":"ClusterIP"},"istio-ilbgateway":{"autoscaleEnabled":true,"autoscaleMax":5,"autoscaleMin":1,"cpu":{"targetAverageUtilization":80},"enabled":false,"labels":{"app":"istio-ilbgateway","istio":"ilbgateway"},"loadBalancerIP":"","nodeSelector":{},"podAnnotations":{},"ports":[{"name":"grpc-pilot-mtls","port":15011},{"name":"grpc-pilot","port":15010},{"name":"tcp-citadel-grpc-tls","port":8060,"targetPort":8060},{"name":"tcp-dns","port":5353}],"resources":{"requests":{"cpu":"800m","memory":"512Mi"}},"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%","secretVolumes":[{"mountPath":"/etc/istio/ilbgateway-certs","name":"ilbgateway-certs","secretName":"istio-ilbgateway-certs"},{"mountPath":"/etc/istio/ilbgateway-ca-certs","name":"ilbgateway-ca-certs","secretName":"istio-ilbgateway-ca-certs"}],"serviceAnnotations":{"cloud.google.com/load-balancer-type":"internal"},"tolerations":[],"type":"LoadBalancer"},"istio-ingressgateway":{"applicationPorts":"","autoscaleEnabled":true,"autoscaleMax":4,"autoscaleMin":2,"cpu":{"targetAverageUtilization":80},"enabled":true,"env":{"ISTIO_META_ROUTER_MODE":"sni-dnat"},"externalIPs":[],"labels":{"app":"istio-ingressgateway","istio":"ingressgateway"},"loadBalancerIP":"","loadBalancerSourceRanges":[],"meshExpansionPorts":[{"name":"tcp-pilot-grpc-tls","port":15011,"targetPort":15011},{"name":"tcp-mixer-grpc-tls","port":15004,"targetPort":15004},{"name":"tcp-citadel-grpc-tls","port":8060,"targetPort":8060},{"name":"tcp-dns-tls","port":853,"targetPort":853}],"nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"ports":[{"name":"status-port","port":15020},{"name":"http2","port":80},{"name":"https","port":443}],"replicaCount":2,"resources":{"limits":{"cpu":"3000m","memory":"2048Mi"},"requests":{"cpu":"3000m","memory":"2048Mi"}},"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%","sds":{"enabled":true,"image":"node-agent-k8s","resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}}},"secretVolumes":[{"mountPath":"/etc/istio/ingressgateway-certs","name":"ingressgateway-certs","secretName":"istio-ingressgateway-certs"},{"mountPath":"/etc/istio/ingressgateway-ca-certs","name":"ingressgateway-ca-certs","secretName":"istio-ingressgateway-ca-certs"}],"serviceAnnotations":{},"tolerations":[],"type":"LoadBalancer"}},"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"grafana":{"accessMode":"ReadWriteMany","contextPath":"/grafana","dashboardProviders":{"dashboardproviders.yaml":{"apiVersion":1,"providers":[{"disableDeletion":false,"folder":"istio","name":"istio","options":{"path":"/var/lib/grafana/dashboards/istio"},"orgId":1,"type":"file"}]}},"datasources":{"datasources.yaml":{"apiVersion":1,"datasources":[{"access":"proxy","editable":true,"isDefault":true,"jsonData":{"timeInterval":"5s"},"name":"Prometheus","orgId":1,"type":"prometheus","url":"http://prometheus:9090"}]}},"enabled":false,"env":{},"envSecrets":{},"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"image":{"repository":"grafana/grafana","tag":"6.4.3"},"ingress":{"annotations":{},"enabled":false,"hosts":["grafana.local"],"tls":[]},"nodeSelector":{},"persist":false,"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"replicaCount":1,"security":{"enabled":false,"passphraseKey":"passphrase","secretName":"grafana","usernameKey":"username"},"service":{"annotations":{},"externalPort":3000,"loadBalancerIP":null,"loadBalancerSourceRanges":[],"name":"http","type":"ClusterIP"},"storageClassName":"","tolerations":[]},"istio_cni":{"enabled":false},"istiocoredns":{"coreDNSImage":"coredns/coredns","coreDNSPluginImage":"istio/coredns-plugin:0.2-istio-1.1","coreDNSTag":"1.6.2","enabled":false,"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"replicaCount":1,"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%","tolerations":[]},"kiali":{"contextPath":"/kiali","createDemoSecret":false,"dashboard":{"auth":{"strategy":"login"},"grafanaURL":null,"jaegerURL":null,"secretName":"kiali","viewOnlyMode":false},"enabled":false,"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"hub":"quay.io/kiali","image":"kiali","ingress":{"annotations":{},"enabled":false,"hosts":["kiali.local"],"tls":null},"nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"prometheusAddr":"http://prometheus:9090","replicaCount":1,"security":{"cert_file":"/kiali-cert/cert-chain.pem","enabled":false,"private_key_file":"/kiali-cert/key.pem"},"tag":"v1.9","tolerations":[]},"mixer":{"adapters":{"kubernetesenv":{"enabled":true},"prometheus":{"enabled":false,"metricsExpiryDuration":"10m"},"stdio":{"enabled":false,"outputAsJson":true},"useAdapterCRDs":false},"env":{"GOMAXPROCS":"6"},"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"image":"mixer","nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"policy":{"autoscaleEnabled":true,"autoscaleMax":5,"autoscaleMin":1,"cpu":{"targetAverageUtilization":80},"enabled":true,"replicaCount":1,"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%"},"telemetry":{"autoscaleEnabled":true,"autoscaleMax":5,"autoscaleMin":1,"cpu":{"targetAverageUtilization":80},"enabled":true,"loadshedding":{"latencyThreshold":"100ms","mode":"enforce"},"replicaCount":1,"reportBatchMaxEntries":100,"reportBatchMaxTime":"1s","resources":{"limits":{"cpu":"4800m","memory":"4G"},"requests":{"cpu":"1000m","memory":"1G"}},"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%","sessionAffinityEnabled":false},"tolerations":[]},"nodeagent":{"enabled":false,"env":{"CA_ADDR":"","CA_PROVIDER":"","PLUGINS":""},"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"image":"node-agent-k8s","nodeSelector":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"tolerations":[]},"pilot":{"autoscaleEnabled":true,"autoscaleMax":5,"autoscaleMin":2,"configSource":{"subscribedResources":null},"cpu":{"targetAverageUtilization":80},"enableProtocolSniffingForInbound":false,"enableProtocolSniffingForOutbound":true,"enabled":true,"env":{"PILOT_PUSH_THROTTLE":100},"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"image":"pilot","keepaliveMaxServerConnectionAge":"30m","nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"resources":{"requests":{"cpu":"3000m","memory":"2048Mi"}},"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%","sidecar":true,"tolerations":[],"traceSampling":100},"prometheus":{"enabled":false},"security":{"citadelHealthCheck":false,"createMeshPolicy":true,"enableNamespacesByDefault":true,"enabled":true,"env":{},"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"image":"citadel","nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"replicaCount":1,"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%","selfSigned":true,"tolerations":[],"workloadCertTtl":"2160h"},"sidecarInjectorWebhook":{"alwaysInjectSelector":[],"enableNamespacesByDefault":false,"enabled":true,"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"image":"sidecar_injector","injectedAnnotations":{},"neverInjectSelector":[],"nodeSelector":{},"podAnnotations":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"replicaCount":1,"rewriteAppHTTPProbe":true,"rollingMaxSurge":"100%","rollingMaxUnavailable":"25%","tolerations":[]},"tracing":{"enabled":false,"global":{"arch":{"amd64":2,"ppc64le":2,"s390x":2},"certificates":[],"configValidation":true,"controlPlaneSecurityEnabled":false,"defaultNodeSelector":{},"defaultPodDisruptionBudget":{"enabled":true},"defaultResources":{"requests":{"cpu":"10m"}},"defaultTolerations":[],"disablePolicyChecks":true,"enableHelmTest":false,"enableTracing":true,"hub":"docker.io/istio","imagePullPolicy":"IfNotPresent","imagePullSecrets":[],"k8sIngress":{"enableHttps":false,"enabled":false,"gatewayName":"ingressgateway"},"localityLbSetting":{"enabled":true},"logging":{"level":"default:info"},"meshExpansion":{"enabled":false,"useILB":false},"meshID":"","meshNetworks":{},"monitoringPort":15014,"mtls":{"auto":false,"enabled":false},"multiCluster":{"clusterName":"","enabled":false},"network":"","oneNamespace":false,"operatorManageWebhooks":false,"outboundTrafficPolicy":{"mode":"ALLOW_ANY"},"policyCheckFailOpen":false,"priorityClassName":"","proxy":{"accessLogEncoding":"JSON","accessLogFile":"/dev/stdout","accessLogFormat":"","autoInject":"enabled","clusterDomain":"cluster.local","componentLogLevel":"","concurrency":2,"dnsRefreshRate":"300s","enableCoreDump":false,"enableCoreDumpImage":"ubuntu:xenial","envoyAccessLogService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyMetricsService":{"enabled":false,"host":null,"port":null,"tcpKeepalive":{"interval":"10s","probes":3,"time":"10s"},"tlsSettings":{"caCertificates":null,"clientCertificate":null,"mode":"DISABLE","privateKey":null,"sni":null,"subjectAltNames":[]}},"envoyStatsd":{"enabled":false,"host":null,"port":null},"excludeIPRanges":"","excludeInboundPorts":"","excludeOutboundPorts":"","image":"proxyv2","includeIPRanges":"*","includeInboundPorts":"*","init":{"resources":{"limits":{"cpu":"100m","memory":"50Mi"},"requests":{"cpu":"10m","memory":"10Mi"}}},"kubevirtInterfaces":"","logLevel":"","privileged":false,"protocolDetectionTimeout":"100ms","readinessFailureThreshold":30,"readinessInitialDelaySeconds":1,"readinessPeriodSeconds":2,"resources":{"limits":{"cpu":"2000m","memory":"1024Mi"},"requests":{"cpu":"100m","memory":"128Mi"}},"statusPort":15020,"tracer":"zipkin"},"proxy_init":{"image":"proxyv2"},"sds":{"enabled":false,"token":{"aud":"istio-ca"},"udsPath":""},"tag":"1.4.3","tracer":{"datadog":{"address":"$(HOST_IP):8126"},"lightstep":{"accessToken":"","address":"","cacertPath":"","secure":true},"stackdriver":{"debug":false,"maxNumberOfAnnotations":200,"maxNumberOfAttributes":200,"maxNumberOfMessageEvents":200},"zipkin":{"address":""}},"trustDomain":"","trustDomainAliases":[],"useMCP":true},"ingress":{"annotations":null,"enabled":false,"hosts":null,"tls":null},"jaeger":{"accessMode":"ReadWriteMany","hub":"docker.io/jaegertracing","image":"all-in-one","memory":{"max_traces":50000},"persist":false,"podAnnotations":{},"spanStorageType":"badger","storageClassName":"","tag":1.14},"nodeSelector":{},"podAntiAffinityLabelSelector":[],"podAntiAffinityTermLabelSelector":[],"provider":"jaeger","service":{"annotations":{},"externalPort":80,"name":"http","type":"ClusterIP"},"tolerations":[],"zipkin":{"hub":"docker.io/openzipkin","image":"zipkin","javaOptsHeap":700,"maxSpans":500000,"node":{"cpus":2},"podAnnotations":{},"probeStartupDelay":200,"queryPort":9411,"resources":{"limits":{"cpu":"300m","memory":"900Mi"},"requests":{"cpu":"150m","memory":"900Mi"}},"tag":"2.14.2"}}} - - config: |- - policy: enabled - alwaysInjectSelector: - [] - neverInjectSelector: - [] - template: |- - rewriteAppHTTPProbe: {{ valueOrDefault .Values.sidecarInjectorWebhook.rewriteAppHTTPProbe false }} - {{- if or (not .Values.istio_cni.enabled) .Values.global.proxy.enableCoreDump }} - initContainers: - {{ if ne (annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode) `NONE` }} - {{- if not .Values.istio_cni.enabled }} - - name: istio-init - {{- if contains "/" .Values.global.proxy_init.image }} - image: "{{ .Values.global.proxy_init.image }}" - {{- else }} - image: "{{ .Values.global.hub }}/{{ .Values.global.proxy_init.image }}:{{ .Values.global.tag }}" - {{- end }} - command: - - istio-iptables - - "-p" - - "15001" - - "-z" - - "15006" - - "-u" - - 1337 - - "-m" - - "{{ annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode }}" - - "-i" - - "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeOutboundIPRanges` .Values.global.proxy.includeIPRanges }}" - - "-x" - - "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/excludeOutboundIPRanges` .Values.global.proxy.excludeIPRanges }}" - - "-b" - - "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeInboundPorts` `*` }}" - - "-d" - - "{{ excludeInboundPort (annotation .ObjectMeta `status.sidecar.istio.io/port` .Values.global.proxy.statusPort) (annotation .ObjectMeta `traffic.sidecar.istio.io/excludeInboundPorts` .Values.global.proxy.excludeInboundPorts) }}" - {{ if or (isset .ObjectMeta.Annotations `traffic.sidecar.istio.io/excludeOutboundPorts`) (ne .Values.global.proxy.excludeOutboundPorts "") -}} - - "-o" - - "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/excludeOutboundPorts` .Values.global.proxy.excludeOutboundPorts }}" - {{ end -}} - {{ if (isset .ObjectMeta.Annotations `traffic.sidecar.istio.io/kubevirtInterfaces`) -}} - - "-k" - - "{{ index .ObjectMeta.Annotations `traffic.sidecar.istio.io/kubevirtInterfaces` }}" - {{ end -}} - imagePullPolicy: "{{ .Values.global.imagePullPolicy }}" - {{- if .Values.global.proxy.init.resources }} - resources: - {{ toYaml .Values.global.proxy.init.resources | indent 4 }} - {{- else }} - resources: {} - {{- end }} - securityContext: - allowPrivilegeEscalation: {{ .Values.global.proxy.privileged }} - capabilities: - add: - - NET_ADMIN - - NET_RAW - drop: - - ALL - privileged: {{ .Values.global.proxy.privileged }} - readOnlyRootFilesystem: false - runAsGroup: 0 - runAsNonRoot: false - runAsUser: 0 - restartPolicy: Always - {{- end }} - {{ end -}} - {{- if eq .Values.global.proxy.enableCoreDump true }} - - name: enable-core-dump - args: - - -c - - sysctl -w kernel.core_pattern=/var/lib/istio/core.proxy && ulimit -c unlimited - command: - - /bin/sh - image: {{ $.Values.global.proxy.enableCoreDumpImage }} - imagePullPolicy: IfNotPresent - resources: {} - securityContext: - allowPrivilegeEscalation: true - capabilities: - add: - - SYS_ADMIN - drop: - - ALL - privileged: true - readOnlyRootFilesystem: false - runAsGroup: 0 - runAsNonRoot: false - runAsUser: 0 - {{ end }} - {{- end }} - containers: - - name: istio-proxy - {{- if contains "/" (annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image) }} - image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.proxy.image }}" - {{- else }} - image: "{{ annotation .ObjectMeta `sidecar.istio.io/proxyImage` .Values.global.hub }}/{{ .Values.global.proxy.image }}:{{ .Values.global.tag }}" - {{- end }} - ports: - - containerPort: 15090 - protocol: TCP - name: http-envoy-prom - args: - - proxy - - sidecar - - --domain - - $(POD_NAMESPACE).svc.{{ .Values.global.proxy.clusterDomain }} - - --configPath - - "{{ .ProxyConfig.ConfigPath }}" - - --binaryPath - - "{{ .ProxyConfig.BinaryPath }}" - - --serviceCluster - {{ if ne "" (index .ObjectMeta.Labels "app") -}} - - "{{ index .ObjectMeta.Labels `app` }}.$(POD_NAMESPACE)" - {{ else -}} - - "{{ valueOrDefault .DeploymentMeta.Name `istio-proxy` }}.{{ valueOrDefault .DeploymentMeta.Namespace `default` }}" - {{ end -}} - - --drainDuration - - "{{ formatDuration .ProxyConfig.DrainDuration }}" - - --parentShutdownDuration - - "{{ formatDuration .ProxyConfig.ParentShutdownDuration }}" - - --discoveryAddress - - "{{ annotation .ObjectMeta `sidecar.istio.io/discoveryAddress` .ProxyConfig.DiscoveryAddress }}" - {{- if eq .Values.global.proxy.tracer "lightstep" }} - - --lightstepAddress - - "{{ .ProxyConfig.GetTracing.GetLightstep.GetAddress }}" - - --lightstepAccessToken - - "{{ .ProxyConfig.GetTracing.GetLightstep.GetAccessToken }}" - - --lightstepSecure={{ .ProxyConfig.GetTracing.GetLightstep.GetSecure }} - - --lightstepCacertPath - - "{{ .ProxyConfig.GetTracing.GetLightstep.GetCacertPath }}" - {{- else if eq .Values.global.proxy.tracer "zipkin" }} - - --zipkinAddress - - "{{ .ProxyConfig.GetTracing.GetZipkin.GetAddress }}" - {{- else if eq .Values.global.proxy.tracer "datadog" }} - - --datadogAgentAddress - - "{{ .ProxyConfig.GetTracing.GetDatadog.GetAddress }}" - {{- end }} - {{- if .Values.global.proxy.logLevel }} - - --proxyLogLevel={{ .Values.global.proxy.logLevel }} - {{- end}} - {{- if .Values.global.proxy.componentLogLevel }} - - --proxyComponentLogLevel={{ .Values.global.proxy.componentLogLevel }} - {{- end}} - - --dnsRefreshRate - - {{ .Values.global.proxy.dnsRefreshRate }} - - --connectTimeout - - "{{ formatDuration .ProxyConfig.ConnectTimeout }}" - {{- if .Values.global.proxy.envoyStatsd.enabled }} - - --statsdUdpAddress - - "{{ .ProxyConfig.StatsdUdpAddress }}" - {{- end }} - {{- if .Values.global.proxy.envoyMetricsService.enabled }} - - --envoyMetricsService - - '{{ protoToJSON .ProxyConfig.EnvoyMetricsService }}' - {{- end }} - {{- if .Values.global.proxy.envoyAccessLogService.enabled }} - - --envoyAccessLogService - - '{{ protoToJSON .ProxyConfig.EnvoyAccessLogService }}' - {{- end }} - - --proxyAdminPort - - "{{ .ProxyConfig.ProxyAdminPort }}" - {{ if gt .ProxyConfig.Concurrency 0 -}} - - --concurrency - - "{{ .ProxyConfig.Concurrency }}" - {{ end -}} - - --controlPlaneAuthPolicy - - "{{ annotation .ObjectMeta `sidecar.istio.io/controlPlaneAuthPolicy` .ProxyConfig.ControlPlaneAuthPolicy }}" - {{- if (ne (annotation .ObjectMeta "status.sidecar.istio.io/port" (valueOrDefault .Values.global.proxy.statusPort 0 )) `0`) }} - - --statusPort - - "{{ annotation .ObjectMeta `status.sidecar.istio.io/port` .Values.global.proxy.statusPort }}" - - --applicationPorts - - "{{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/applicationPorts` (applicationPorts .Spec.Containers) }}" - {{- end }} - {{- if .Values.global.trustDomain }} - - --trust-domain={{ .Values.global.trustDomain }} - {{- end }} - {{- if .Values.global.proxy.lifecycle }} - lifecycle: - {{ toYaml .Values.global.proxy.lifecycle | indent 4 }} - {{- end }} - env: - - name: POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: ISTIO_META_POD_PORTS - value: |- - [ - {{- $first := true }} - {{- range $index1, $c := .Spec.Containers }} - {{- range $index2, $p := $c.Ports }} - {{- if (structToJSON $p) }} - {{if not $first}},{{end}}{{ structToJSON $p }} - {{- $first = false }} - {{- end }} - {{- end}} - {{- end}} - ] - - name: ISTIO_META_CLUSTER_ID - value: "{{ valueOrDefault .Values.global.multiCluster.clusterName `Kubernetes` }}" - - name: POD_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: INSTANCE_IP - valueFrom: - fieldRef: - fieldPath: status.podIP - - name: SERVICE_ACCOUNT - valueFrom: - fieldRef: - fieldPath: spec.serviceAccountName - {{- if .Values.global.mtls.auto }} - - name: ISTIO_AUTO_MTLS_ENABLED - value: "true" - {{- end }} - {{- if eq .Values.global.proxy.tracer "datadog" }} - - name: HOST_IP - valueFrom: - fieldRef: - fieldPath: status.hostIP - {{- if isset .ObjectMeta.Annotations `apm.datadoghq.com/env` }} - {{- range $key, $value := fromJSON (index .ObjectMeta.Annotations `apm.datadoghq.com/env`) }} - - name: {{ $key }} - value: "{{ $value }}" - {{- end }} - {{- end }} - {{- end }} - - name: ISTIO_META_POD_NAME - valueFrom: - fieldRef: - fieldPath: metadata.name - - name: ISTIO_META_CONFIG_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: SDS_ENABLED - value: {{ $.Values.global.sds.enabled }} - - name: ISTIO_META_INTERCEPTION_MODE - value: "{{ or (index .ObjectMeta.Annotations `sidecar.istio.io/interceptionMode`) .ProxyConfig.InterceptionMode.String }}" - - name: ISTIO_META_INCLUDE_INBOUND_PORTS - value: "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeInboundPorts` (applicationPorts .Spec.Containers) }}" - {{- if .Values.global.network }} - - name: ISTIO_META_NETWORK - value: "{{ .Values.global.network }}" - {{- end }} - {{ if .ObjectMeta.Annotations }} - - name: ISTIO_METAJSON_ANNOTATIONS - value: | - {{ toJSON .ObjectMeta.Annotations }} - {{ end }} - {{ if .ObjectMeta.Labels }} - - name: ISTIO_METAJSON_LABELS - value: | - {{ toJSON .ObjectMeta.Labels }} - {{ end }} - {{- if .DeploymentMeta.Name }} - - name: ISTIO_META_WORKLOAD_NAME - value: {{ .DeploymentMeta.Name }} - # PATCH #2: Increase termination drain duration. - - name: TERMINATION_DRAIN_DURATION_SECONDS - value: "20" - # PATCH #2 ends. - {{ end }} - {{- if and .TypeMeta.APIVersion .DeploymentMeta.Name }} - - name: ISTIO_META_OWNER - value: kubernetes://apis/{{ .TypeMeta.APIVersion }}/namespaces/{{ valueOrDefault .DeploymentMeta.Namespace `default` }}/{{ toLower .TypeMeta.Kind}}s/{{ .DeploymentMeta.Name }} - {{- end}} - {{- if (isset .ObjectMeta.Annotations `sidecar.istio.io/bootstrapOverride`) }} - - name: ISTIO_BOOTSTRAP_OVERRIDE - value: "/etc/istio/custom-bootstrap/custom_bootstrap.json" - {{- end }} - {{- if .Values.global.sds.customTokenDirectory }} - - name: ISTIO_META_SDS_TOKEN_PATH - value: "{{ .Values.global.sds.customTokenDirectory -}}/sdstoken" - {{- end }} - {{- if .Values.global.meshID }} - - name: ISTIO_META_MESH_ID - value: "{{ .Values.global.meshID }}" - {{- else if .Values.global.trustDomain }} - - name: ISTIO_META_MESH_ID - value: "{{ .Values.global.trustDomain }}" - {{- end }} - {{- if eq .Values.global.proxy.tracer "stackdriver" }} - - name: STACKDRIVER_TRACING_ENABLED - value: "true" - - name: STACKDRIVER_TRACING_DEBUG - value: "{{ .ProxyConfig.GetTracing.GetStackdriver.GetDebug }}" - {{- if .ProxyConfig.GetTracing.GetStackdriver.GetMaxNumberOfAnnotations }} - - name: STACKDRIVER_TRACING_MAX_NUMBER_OF_ANNOTATIONS - value: "{{ .ProxyConfig.GetTracing.GetStackdriver.GetMaxNumberOfAnnotations }}" - {{- end }} - {{- if .ProxyConfig.GetTracing.GetStackdriver.GetMaxNumberOfAttributes }} - - name: STACKDRIVER_TRACING_MAX_NUMBER_OF_ATTRIBUTES - value: "{{ .ProxyConfig.GetTracing.GetStackdriver.GetMaxNumberOfAttributes }}" - {{- end }} - {{- if .ProxyConfig.GetTracing.GetStackdriver.GetMaxNumberOfMessageEvents }} - - name: STACKDRIVER_TRACING_MAX_NUMBER_OF_MESSAGE_EVENTS - value: "{{ .ProxyConfig.GetTracing.GetStackdriver.GetMaxNumberOfMessageEvents }}" - {{- end }} - {{- end }} - imagePullPolicy: {{ .Values.global.imagePullPolicy }} - {{ if ne (annotation .ObjectMeta `status.sidecar.istio.io/port` (valueOrDefault .Values.global.proxy.statusPort 0 )) `0` }} - readinessProbe: - httpGet: - path: /healthz/ready - port: {{ annotation .ObjectMeta `status.sidecar.istio.io/port` .Values.global.proxy.statusPort }} - initialDelaySeconds: {{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/initialDelaySeconds` .Values.global.proxy.readinessInitialDelaySeconds }} - periodSeconds: {{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/periodSeconds` .Values.global.proxy.readinessPeriodSeconds }} - failureThreshold: {{ annotation .ObjectMeta `readiness.status.sidecar.istio.io/failureThreshold` .Values.global.proxy.readinessFailureThreshold }} - {{ end -}} - securityContext: - allowPrivilegeEscalation: {{ .Values.global.proxy.privileged }} - capabilities: - {{ if eq (annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode) `TPROXY` -}} - add: - - NET_ADMIN - {{- end }} - drop: - - ALL - privileged: {{ .Values.global.proxy.privileged }} - readOnlyRootFilesystem: {{ not .Values.global.proxy.enableCoreDump }} - runAsGroup: 1337 - {{ if eq (annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode) `TPROXY` -}} - runAsNonRoot: false - runAsUser: 0 - {{- else -}} - runAsNonRoot: true - runAsUser: 1337 - {{- end }} - resources: - {{ if or (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU`) (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory`) -}} - requests: - {{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU`) -}} - cpu: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyCPU` }}" - {{ end}} - {{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory`) -}} - memory: "{{ index .ObjectMeta.Annotations `sidecar.istio.io/proxyMemory` }}" - {{ end }} - {{ else -}} - {{- if .Values.global.proxy.resources }} - {{ toYaml .Values.global.proxy.resources | indent 4 }} - {{- end }} - {{ end -}} - volumeMounts: - {{ if (isset .ObjectMeta.Annotations `sidecar.istio.io/bootstrapOverride`) }} - - mountPath: /etc/istio/custom-bootstrap - name: custom-bootstrap-volume - {{- end }} - - mountPath: /etc/istio/proxy - name: istio-envoy - {{- if .Values.global.sds.enabled }} - - mountPath: /var/run/sds - name: sds-uds-path - readOnly: true - - mountPath: /var/run/secrets/tokens - name: istio-token - {{- if .Values.global.sds.customTokenDirectory }} - - mountPath: "{{ .Values.global.sds.customTokenDirectory -}}" - name: custom-sds-token - readOnly: true - {{- end }} - {{- else }} - - mountPath: /etc/certs/ - name: istio-certs - readOnly: true - {{- end }} - {{- if and (eq .Values.global.proxy.tracer "lightstep") .Values.global.tracer.lightstep.cacertPath }} - - mountPath: {{ directory .ProxyConfig.GetTracing.GetLightstep.GetCacertPath }} - name: lightstep-certs - readOnly: true - {{- end }} - {{- if isset .ObjectMeta.Annotations `sidecar.istio.io/userVolumeMount` }} - {{ range $index, $value := fromJSON (index .ObjectMeta.Annotations `sidecar.istio.io/userVolumeMount`) }} - - name: "{{ $index }}" - {{ toYaml $value | indent 4 }} - {{ end }} - {{- end }} - volumes: - {{- if (isset .ObjectMeta.Annotations `sidecar.istio.io/bootstrapOverride`) }} - - name: custom-bootstrap-volume - configMap: - name: {{ annotation .ObjectMeta `sidecar.istio.io/bootstrapOverride` "" }} - {{- end }} - - emptyDir: - medium: Memory - name: istio-envoy - {{- if .Values.global.sds.enabled }} - - name: sds-uds-path - hostPath: - path: /var/run/sds - - name: istio-token - projected: - sources: - - serviceAccountToken: - path: istio-token - expirationSeconds: 43200 - audience: {{ .Values.global.sds.token.aud }} - {{- if .Values.global.sds.customTokenDirectory }} - - name: custom-sds-token - secret: - secretName: sdstokensecret - {{- end }} - {{- else }} - - name: istio-certs - secret: - optional: true - {{ if eq .Spec.ServiceAccountName "" }} - secretName: istio.default - {{ else -}} - secretName: {{ printf "istio.%s" .Spec.ServiceAccountName }} - {{ end -}} - {{- if isset .ObjectMeta.Annotations `sidecar.istio.io/userVolume` }} - {{range $index, $value := fromJSON (index .ObjectMeta.Annotations `sidecar.istio.io/userVolume`) }} - - name: "{{ $index }}" - {{ toYaml $value | indent 2 }} - {{ end }} - {{ end }} - {{- end }} - {{- if and (eq .Values.global.proxy.tracer "lightstep") .Values.global.tracer.lightstep.cacertPath }} - - name: lightstep-certs - secret: - optional: true - secretName: lightstep.cacert - {{- end }} - {{- if .Values.global.podDNSSearchNamespaces }} - dnsConfig: - searches: - {{- range .Values.global.podDNSSearchNamespaces }} - - {{ render . }} - {{- end }} - {{- end }} - podRedirectAnnot: - sidecar.istio.io/interceptionMode: "{{ annotation .ObjectMeta `sidecar.istio.io/interceptionMode` .ProxyConfig.InterceptionMode }}" - traffic.sidecar.istio.io/includeOutboundIPRanges: "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeOutboundIPRanges` .Values.global.proxy.includeIPRanges }}" - traffic.sidecar.istio.io/excludeOutboundIPRanges: "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/excludeOutboundIPRanges` .Values.global.proxy.excludeIPRanges }}" - traffic.sidecar.istio.io/includeInboundPorts: "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/includeInboundPorts` (includeInboundPorts .Spec.Containers) }}" - traffic.sidecar.istio.io/excludeInboundPorts: "{{ excludeInboundPort (annotation .ObjectMeta `status.sidecar.istio.io/port` .Values.global.proxy.statusPort) (annotation .ObjectMeta `traffic.sidecar.istio.io/excludeInboundPorts` .Values.global.proxy.excludeInboundPorts) }}" - {{ if or (isset .ObjectMeta.Annotations `traffic.sidecar.istio.io/excludeOutboundPorts`) (ne .Values.global.proxy.excludeOutboundPorts "") }} - traffic.sidecar.istio.io/excludeOutboundPorts: "{{ annotation .ObjectMeta `traffic.sidecar.istio.io/excludeOutboundPorts` .Values.global.proxy.excludeOutboundPorts }}" - {{- end }} - traffic.sidecar.istio.io/kubevirtInterfaces: "{{ index .ObjectMeta.Annotations `traffic.sidecar.istio.io/kubevirtInterfaces` }}" - injectedAnnotations: ---- -# Source: istio/charts/galley/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-galley-service-account - namespace: istio-system - labels: - app: galley - chart: galley - heritage: Helm - release: RELEASE-NAME ---- -# Source: istio/charts/gateways/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-ingressgateway-service-account - namespace: istio-system - labels: - app: istio-ingressgateway - chart: gateways - heritage: Helm - release: RELEASE-NAME ---- -# Source: istio/charts/gateways/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: cluster-local-gateway-service-account - namespace: istio-system - labels: - app: cluster-local-gateway - chart: gateways - heritage: Helm - release: RELEASE-NAME ---- -# Source: istio/charts/mixer/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-mixer-service-account - namespace: istio-system - labels: - app: mixer - chart: mixer - heritage: Helm - release: RELEASE-NAME ---- -# Source: istio/charts/pilot/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-pilot-service-account - namespace: istio-system - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME ---- -# Source: istio/charts/security/templates/create-custom-resources-job.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-security-post-install-account - namespace: istio-system - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME ---- -# Source: istio/charts/security/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-citadel-service-account - namespace: istio-system - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME ---- -# Source: istio/charts/sidecarInjectorWebhook/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-sidecar-injector-service-account - namespace: istio-system - labels: - app: sidecarInjectorWebhook - chart: sidecarInjectorWebhook - heritage: Helm - release: RELEASE-NAME - istio: sidecar-injector ---- -# Source: istio/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-multi - namespace: istio-system ---- -# Source: istio/charts/galley/templates/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: istio-galley-istio-system - labels: - app: galley - chart: galley - heritage: Helm - release: RELEASE-NAME -rules: - # For reading Istio resources -- apiGroups: [ - "authentication.istio.io", - "config.istio.io", - "networking.istio.io", - "rbac.istio.io", - "security.istio.io"] - resources: ["*"] - verbs: ["get", "list", "watch"] - # For updating Istio resource statuses -- apiGroups: [ - "authentication.istio.io", - "config.istio.io", - "networking.istio.io", - "rbac.istio.io", - "security.istio.io"] - resources: ["*/status"] - verbs: ["update"] -- apiGroups: ["admissionregistration.k8s.io"] - resources: ["validatingwebhookconfigurations"] - verbs: ["*"] -- apiGroups: ["extensions","apps"] - resources: ["deployments"] - resourceNames: ["istio-galley"] - verbs: ["get"] -- apiGroups: [""] - resources: ["pods", "nodes", "services", "endpoints", "namespaces"] - verbs: ["get", "list", "watch"] -- apiGroups: ["extensions"] - resources: ["ingresses"] - verbs: ["get", "list", "watch"] -- apiGroups: ["extensions"] - resources: ["deployments/finalizers"] - resourceNames: ["istio-galley"] - verbs: ["update"] -- apiGroups: ["apiextensions.k8s.io"] - resources: ["customresourcedefinitions"] - verbs: ["get", "list", "watch"] ---- -# Source: istio/charts/mixer/templates/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: istio-mixer-istio-system - labels: - app: mixer - chart: mixer - heritage: Helm - release: RELEASE-NAME -rules: -- apiGroups: ["config.istio.io"] # istio CRD watcher - resources: ["*"] - verbs: ["create", "get", "list", "watch", "patch"] -- apiGroups: ["apiextensions.k8s.io"] - resources: ["customresourcedefinitions"] - verbs: ["get", "list", "watch"] -- apiGroups: [""] - resources: ["configmaps", "endpoints", "pods", "services", "namespaces", "secrets", "replicationcontrollers"] - verbs: ["get", "list", "watch"] -- apiGroups: ["extensions", "apps"] - resources: ["replicasets"] - verbs: ["get", "list", "watch"] ---- -# Source: istio/charts/pilot/templates/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: istio-pilot-istio-system - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME -rules: -- apiGroups: ["config.istio.io"] - resources: ["*"] - verbs: ["*"] -- apiGroups: ["rbac.istio.io"] - resources: ["*"] - verbs: ["get", "watch", "list"] -- apiGroups: ["security.istio.io"] - resources: ["*"] - verbs: ["get", "watch", "list"] -- apiGroups: ["networking.istio.io"] - resources: ["*"] - verbs: ["*"] -- apiGroups: ["authentication.istio.io"] - resources: ["*"] - verbs: ["*"] -- apiGroups: ["apiextensions.k8s.io"] - resources: ["customresourcedefinitions"] - verbs: ["*"] -- apiGroups: ["extensions"] - resources: ["ingresses", "ingresses/status"] - verbs: ["*"] -- apiGroups: [""] - resources: ["configmaps"] - verbs: ["create", "get", "list", "watch", "update"] -- apiGroups: [""] - resources: ["endpoints", "pods", "services", "namespaces", "nodes"] - verbs: ["get", "list", "watch"] -- apiGroups: [""] - resources: ["secrets"] - verbs: ["create", "get", "watch", "list", "update", "delete"] -- apiGroups: ["certificates.k8s.io"] - resources: - - "certificatesigningrequests" - - "certificatesigningrequests/approval" - - "certificatesigningrequests/status" - verbs: ["update", "create", "get", "delete"] ---- -# Source: istio/charts/security/templates/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: istio-citadel-istio-system - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME -rules: -- apiGroups: [""] - resources: ["configmaps"] - verbs: ["create", "get", "update"] -- apiGroups: [""] - resources: ["secrets"] - verbs: ["create", "get", "watch", "list", "update", "delete"] -- apiGroups: [""] - resources: ["serviceaccounts", "services", "namespaces"] - verbs: ["get", "watch", "list"] -- apiGroups: ["authentication.k8s.io"] - resources: ["tokenreviews"] - verbs: ["create"] ---- -# Source: istio/charts/security/templates/create-custom-resources-job.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: istio-security-post-install-istio-system - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME -rules: -- apiGroups: ["authentication.istio.io"] # needed to create default authn policy - resources: ["*"] - verbs: ["*"] -- apiGroups: ["networking.istio.io"] # needed to create security destination rules - resources: ["*"] - verbs: ["*"] -- apiGroups: ["admissionregistration.k8s.io"] - resources: ["validatingwebhookconfigurations"] - verbs: ["get"] -- apiGroups: ["extensions", "apps"] - resources: ["deployments", "replicasets"] - verbs: ["get", "list", "watch"] ---- -# Source: istio/charts/sidecarInjectorWebhook/templates/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: istio-sidecar-injector-istio-system - labels: - app: sidecarInjectorWebhook - chart: sidecarInjectorWebhook - heritage: Helm - release: RELEASE-NAME - istio: sidecar-injector -rules: -- apiGroups: [""] - resources: ["configmaps"] - verbs: ["get", "list", "watch"] -- apiGroups: ["admissionregistration.k8s.io"] - resources: ["mutatingwebhookconfigurations"] - verbs: ["get", "list", "watch", "patch"] ---- -# Source: istio/templates/clusterrole.yaml -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: istio-reader -rules: - - apiGroups: [''] - resources: ['nodes', 'pods', 'services', 'endpoints', "replicationcontrollers"] - verbs: ['get', 'watch', 'list'] - - apiGroups: ["extensions", "apps"] - resources: ["replicasets"] - verbs: ["get", "list", "watch"] ---- -# Source: istio/charts/galley/templates/clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: istio-galley-admin-role-binding-istio-system - labels: - app: galley - chart: galley - heritage: Helm - release: RELEASE-NAME -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: istio-galley-istio-system -subjects: - - kind: ServiceAccount - name: istio-galley-service-account - namespace: istio-system ---- -# Source: istio/charts/mixer/templates/clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: istio-mixer-admin-role-binding-istio-system - labels: - app: mixer - chart: mixer - heritage: Helm - release: RELEASE-NAME -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: istio-mixer-istio-system -subjects: - - kind: ServiceAccount - name: istio-mixer-service-account - namespace: istio-system ---- -# Source: istio/charts/pilot/templates/clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: istio-pilot-istio-system - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: istio-pilot-istio-system -subjects: - - kind: ServiceAccount - name: istio-pilot-service-account - namespace: istio-system ---- -# Source: istio/charts/security/templates/clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: istio-citadel-istio-system - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: istio-citadel-istio-system -subjects: - - kind: ServiceAccount - name: istio-citadel-service-account - namespace: istio-system ---- -# Source: istio/charts/security/templates/create-custom-resources-job.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: istio-security-post-install-role-binding-istio-system - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: istio-security-post-install-istio-system -subjects: - - kind: ServiceAccount - name: istio-security-post-install-account - namespace: istio-system ---- -# Source: istio/charts/sidecarInjectorWebhook/templates/clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: istio-sidecar-injector-admin-role-binding-istio-system - labels: - app: sidecarInjectorWebhook - chart: sidecarInjectorWebhook - heritage: Helm - release: RELEASE-NAME - istio: sidecar-injector -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: istio-sidecar-injector-istio-system -subjects: - - kind: ServiceAccount - name: istio-sidecar-injector-service-account - namespace: istio-system ---- -# Source: istio/templates/clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: istio-multi - labels: - chart: istio-1.4.3 -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: istio-reader -subjects: -- kind: ServiceAccount - name: istio-multi - namespace: istio-system ---- -# Source: istio/charts/gateways/templates/role.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: istio-ingressgateway-sds - namespace: istio-system -rules: -- apiGroups: [""] - resources: ["secrets"] - verbs: ["get", "watch", "list"] ---- -# Source: istio/charts/gateways/templates/rolebindings.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: istio-ingressgateway-sds - namespace: istio-system -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: istio-ingressgateway-sds -subjects: -- kind: ServiceAccount - name: istio-ingressgateway-service-account ---- -# Source: istio/charts/galley/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: istio-galley - namespace: istio-system - labels: - app: galley - chart: galley - heritage: Helm - release: RELEASE-NAME - istio: galley -spec: - ports: - - port: 443 - name: https-validation - - port: 15014 - name: http-monitoring - - port: 9901 - name: grpc-mcp - selector: - istio: galley ---- -# Source: istio/charts/gateways/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: cluster-local-gateway - namespace: istio-system - annotations: - labels: - chart: gateways - heritage: Helm - release: RELEASE-NAME - app: cluster-local-gateway - istio: cluster-local-gateway -spec: - type: ClusterIP - selector: - release: RELEASE-NAME - app: cluster-local-gateway - istio: cluster-local-gateway - ports: - - - name: status-port - port: 15020 - - - name: http2 - port: 80 - - - name: https - port: 443 ---- -# Source: istio/charts/gateways/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: istio-ingressgateway - namespace: istio-system - annotations: - labels: - chart: gateways - heritage: Helm - release: RELEASE-NAME - app: istio-ingressgateway - istio: ingressgateway -spec: - type: LoadBalancer - selector: - release: RELEASE-NAME - app: istio-ingressgateway - istio: ingressgateway - ports: - - - name: status-port - port: 15020 - - - name: http2 - port: 80 - - - name: https - port: 443 ---- -# Source: istio/charts/mixer/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: istio-policy - namespace: istio-system - annotations: - networking.istio.io/exportTo: "*" - labels: - app: mixer - chart: mixer - heritage: Helm - release: RELEASE-NAME - istio: mixer -spec: - ports: - - name: grpc-mixer - port: 9091 - - name: grpc-mixer-mtls - port: 15004 - - name: http-monitoring - port: 15014 - selector: - istio: mixer - istio-mixer-type: policy ---- -# Source: istio/charts/mixer/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: istio-telemetry - namespace: istio-system - annotations: - networking.istio.io/exportTo: "*" - labels: - app: mixer - chart: mixer - heritage: Helm - release: RELEASE-NAME - istio: mixer -spec: - ports: - - name: grpc-mixer - port: 9091 - - name: grpc-mixer-mtls - port: 15004 - - name: http-monitoring - port: 15014 - - name: prometheus - port: 42422 - selector: - istio: mixer - istio-mixer-type: telemetry ---- -# Source: istio/charts/pilot/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: istio-pilot - namespace: istio-system - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME - istio: pilot -spec: - ports: - - port: 15010 - name: grpc-xds # direct - - port: 15011 - name: https-xds # mTLS - - port: 8080 - name: http-legacy-discovery # direct - - port: 15014 - name: http-monitoring - selector: - istio: pilot ---- -# Source: istio/charts/security/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - # we use the normal name here (e.g. 'prometheus') - # as grafana is configured to use this as a data source - name: istio-citadel - namespace: istio-system - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME - istio: citadel -spec: - ports: - - name: grpc-citadel - port: 8060 - targetPort: 8060 - protocol: TCP - - name: http-monitoring - port: 15014 - selector: - istio: citadel ---- -# Source: istio/charts/sidecarInjectorWebhook/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: istio-sidecar-injector - namespace: istio-system - labels: - app: sidecarInjectorWebhook - chart: sidecarInjectorWebhook - heritage: Helm - release: RELEASE-NAME - istio: sidecar-injector -spec: - ports: - - port: 443 - name: https-inject - - port: 15014 - name: http-monitoring - selector: - istio: sidecar-injector ---- -# Source: istio/charts/galley/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: istio-galley - namespace: istio-system - labels: - app: galley - chart: galley - heritage: Helm - release: RELEASE-NAME - istio: galley -spec: - replicas: 1 - selector: - matchLabels: - istio: galley - strategy: - rollingUpdate: - maxSurge: 100% - maxUnavailable: 25% - template: - metadata: - labels: - app: galley - chart: galley - heritage: Helm - release: RELEASE-NAME - istio: galley - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-galley-service-account - containers: - - name: galley - image: "docker.io/istio/galley:1.4.3" - imagePullPolicy: IfNotPresent - ports: - - containerPort: 443 - - containerPort: 15014 - - containerPort: 9901 - command: - - /usr/local/bin/galley - - server - - --meshConfigFile=/etc/mesh-config/mesh - - --livenessProbeInterval=1s - - --livenessProbePath=/healthliveness - - --readinessProbePath=/healthready - - --readinessProbeInterval=1s - - --deployment-namespace=istio-system - - --insecure=true - - --enable-reconcileWebhookConfiguration=true - - --validation-webhook-config-file - - /etc/config/validatingwebhookconfiguration.yaml - - --monitoringPort=15014 - - --log_output_level=default:info - volumeMounts: - - name: certs - mountPath: /etc/certs - readOnly: true - - name: config - mountPath: /etc/config - readOnly: true - - name: mesh-config - mountPath: /etc/mesh-config - readOnly: true - livenessProbe: - exec: - command: - - /usr/local/bin/galley - - probe - - --probe-path=/healthliveness - - --interval=10s - initialDelaySeconds: 5 - periodSeconds: 5 - readinessProbe: - exec: - command: - - /usr/local/bin/galley - - probe - - --probe-path=/healthready - - --interval=10s - initialDelaySeconds: 5 - periodSeconds: 5 - resources: - requests: - cpu: 10m - volumes: - - name: certs - secret: - secretName: istio.istio-galley-service-account - - name: config - configMap: - name: istio-galley-configuration - - name: mesh-config - configMap: - name: istio - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - "ppc64le" - - "s390x" - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "ppc64le" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "s390x" ---- -# Source: istio/charts/gateways/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: cluster-local-gateway - namespace: istio-system - labels: - app: cluster-local-gateway - chart: gateways - heritage: Helm - istio: cluster-local-gateway - release: RELEASE-NAME -spec: - replicas: 2 - selector: - matchLabels: - app: cluster-local-gateway - istio: cluster-local-gateway - strategy: - rollingUpdate: - maxSurge: - maxUnavailable: - template: - metadata: - labels: - app: cluster-local-gateway - chart: gateways - heritage: Helm - istio: cluster-local-gateway - release: RELEASE-NAME - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: cluster-local-gateway-service-account - containers: - - name: istio-proxy - image: "docker.io/istio/proxyv2:1.4.3" - imagePullPolicy: IfNotPresent - ports: - - containerPort: 15020 - - containerPort: 80 - - containerPort: 443 - - containerPort: 15090 - protocol: TCP - name: http-envoy-prom - args: - - proxy - - router - - --domain - - $(POD_NAMESPACE).svc.cluster.local - - --log_output_level=default:info - - --drainDuration - - '45s' #drainDuration - - --parentShutdownDuration - - '1m0s' #parentShutdownDuration - - --connectTimeout - - '10s' #connectTimeout - - --serviceCluster - - cluster-local-gateway - - --zipkinAddress - - zipkin:9411 - - --proxyAdminPort - - "15000" - - --statusPort - - "15020" - - --controlPlaneAuthPolicy - - NONE - - --discoveryAddress - - istio-pilot:15010 - readinessProbe: - failureThreshold: 30 - httpGet: - path: /healthz/ready - port: 15020 - scheme: HTTP - initialDelaySeconds: 1 - periodSeconds: 2 - successThreshold: 1 - timeoutSeconds: 1 - resources: - requests: - cpu: 250m - memory: 256Mi - env: - - name: NODE_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: spec.nodeName - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: INSTANCE_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.podIP - - name: HOST_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.hostIP - - name: SERVICE_ACCOUNT - valueFrom: - fieldRef: - fieldPath: spec.serviceAccountName - - name: ISTIO_META_POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: ISTIO_META_CONFIG_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: ISTIO_METAJSON_LABELS - value: | - {"app":"cluster-local-gateway","chart":"gateways","heritage":"Helm","istio":"cluster-local-gateway","release":"RELEASE-NAME"} - - name: ISTIO_META_CLUSTER_ID - value: "Kubernetes" - - name: SDS_ENABLED - value: "false" - - name: ISTIO_META_WORKLOAD_NAME - value: cluster-local-gateway - - name: ISTIO_META_OWNER - value: kubernetes://apis/apps/v1/namespaces/istio-system/deployments/cluster-local-gateway - - volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - - name: cluster-local-gateway-certs - mountPath: "/etc/istio/cluster-local-gateway-certs" - readOnly: true - - name: cluster-local-gateway-ca-certs - mountPath: "/etc/istio/cluster-local-gateway-ca-certs" - readOnly: true - volumes: - - name: istio-certs - secret: - secretName: istio.cluster-local-gateway-service-account - optional: true - - name: cluster-local-gateway-certs - secret: - secretName: "istio-cluster-local-gateway-certs" - optional: true - - name: cluster-local-gateway-ca-certs - secret: - secretName: "istio-cluster-local-gateway-ca-certs" - optional: true - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - "ppc64le" - - "s390x" - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "ppc64le" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "s390x" ---- -# Source: istio/charts/gateways/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: istio-ingressgateway - namespace: istio-system - labels: - app: istio-ingressgateway - chart: gateways - heritage: Helm - istio: ingressgateway - release: RELEASE-NAME -spec: - selector: - matchLabels: - app: istio-ingressgateway - istio: ingressgateway - strategy: - rollingUpdate: - maxSurge: 100% - maxUnavailable: 25% - template: - metadata: - labels: - app: istio-ingressgateway - chart: gateways - heritage: Helm - istio: ingressgateway - release: RELEASE-NAME - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-ingressgateway-service-account - containers: - - name: ingress-sds - image: "docker.io/istio/node-agent-k8s:1.4.3" - imagePullPolicy: IfNotPresent - resources: - limits: - cpu: 2000m - memory: 1024Mi - requests: - cpu: 100m - memory: 128Mi - env: - - name: "ENABLE_WORKLOAD_SDS" - value: "false" - - name: "ENABLE_INGRESS_GATEWAY_SDS" - value: "true" - - name: "INGRESS_GATEWAY_NAMESPACE" - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - volumeMounts: - - name: ingressgatewaysdsudspath - mountPath: /var/run/ingress_gateway - - name: istio-proxy - image: "docker.io/istio/proxyv2:1.4.3" - imagePullPolicy: IfNotPresent - ports: - - containerPort: 15020 - - containerPort: 80 - - containerPort: 443 - - containerPort: 15090 - protocol: TCP - name: http-envoy-prom - args: - - proxy - - router - - --domain - - $(POD_NAMESPACE).svc.cluster.local - - --log_output_level=default:info - - --drainDuration - - '45s' #drainDuration - - --parentShutdownDuration - - '1m0s' #parentShutdownDuration - - --connectTimeout - - '10s' #connectTimeout - - --serviceCluster - - istio-ingressgateway - - --zipkinAddress - - zipkin:9411 - - --proxyAdminPort - - "15000" - - --statusPort - - "15020" - - --controlPlaneAuthPolicy - - NONE - - --discoveryAddress - - istio-pilot:15010 - readinessProbe: - failureThreshold: 30 - httpGet: - path: /healthz/ready - port: 15020 - scheme: HTTP - initialDelaySeconds: 1 - periodSeconds: 2 - successThreshold: 1 - timeoutSeconds: 1 - resources: - limits: - cpu: 3000m - memory: 2048Mi - requests: - cpu: 3000m - memory: 2048Mi - env: - - name: NODE_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: spec.nodeName - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: INSTANCE_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.podIP - - name: HOST_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.hostIP - - name: SERVICE_ACCOUNT - valueFrom: - fieldRef: - fieldPath: spec.serviceAccountName - - name: ISTIO_META_POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: ISTIO_META_CONFIG_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: ISTIO_METAJSON_LABELS - value: | - {"app":"istio-ingressgateway","chart":"gateways","heritage":"Helm","istio":"ingressgateway","release":"RELEASE-NAME"} - - name: ISTIO_META_CLUSTER_ID - value: "Kubernetes" - - name: SDS_ENABLED - value: "false" - - name: ISTIO_META_WORKLOAD_NAME - value: istio-ingressgateway - - name: ISTIO_META_OWNER - value: kubernetes://apis/apps/v1/namespaces/istio-system/deployments/istio-ingressgateway - - name: ISTIO_META_USER_SDS - value: "true" - - name: ISTIO_META_ROUTER_MODE - value: sni-dnat - - - volumeMounts: - - name: ingressgatewaysdsudspath - mountPath: /var/run/ingress_gateway - - name: istio-certs - mountPath: /etc/certs - readOnly: true - - name: ingressgateway-certs - mountPath: "/etc/istio/ingressgateway-certs" - readOnly: true - - name: ingressgateway-ca-certs - mountPath: "/etc/istio/ingressgateway-ca-certs" - readOnly: true - volumes: - - name: ingressgatewaysdsudspath - emptyDir: {} - - name: istio-certs - secret: - secretName: istio.istio-ingressgateway-service-account - optional: true - - name: ingressgateway-certs - secret: - secretName: "istio-ingressgateway-certs" - optional: true - - name: ingressgateway-ca-certs - secret: - secretName: "istio-ingressgateway-ca-certs" - optional: true - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - "ppc64le" - - "s390x" - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "ppc64le" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "s390x" ---- -# Source: istio/charts/mixer/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: istio-policy - namespace: istio-system - labels: - app: istio-mixer - chart: mixer - heritage: Helm - release: RELEASE-NAME - istio: mixer -spec: - strategy: - rollingUpdate: - maxSurge: 100% - maxUnavailable: 25% - selector: - matchLabels: - istio: mixer - istio-mixer-type: policy - template: - metadata: - labels: - app: policy - chart: mixer - heritage: Helm - release: RELEASE-NAME - security.istio.io/tlsMode: "istio" - istio: mixer - istio-mixer-type: policy - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-mixer-service-account - volumes: - - name: istio-certs - secret: - secretName: istio.istio-mixer-service-account - optional: true - - name: uds-socket - emptyDir: {} - - name: policy-adapter-secret - secret: - secretName: policy-adapter-secret - optional: true - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - "ppc64le" - - "s390x" - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "ppc64le" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "s390x" - containers: - - name: mixer - image: "docker.io/istio/mixer:1.4.3" - imagePullPolicy: IfNotPresent - ports: - - containerPort: 15014 - - containerPort: 42422 - args: - - --monitoringPort=15014 - - --address - - unix:///sock/mixer.socket - - --log_output_level=default:info - - --configStoreURL=mcp://istio-galley.istio-system.svc:9901 - - --configDefaultNamespace=istio-system - - --useAdapterCRDs=false - - --useTemplateCRDs=false - - --trace_zipkin_url=http://zipkin.istio-system:9411/api/v1/spans - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: GOMAXPROCS - value: "6" - resources: - requests: - cpu: 10m - volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - - name: uds-socket - mountPath: /sock - livenessProbe: - httpGet: - path: /version - port: 15014 - initialDelaySeconds: 5 - periodSeconds: 5 - - name: istio-proxy - image: "docker.io/istio/proxyv2:1.4.3" - imagePullPolicy: IfNotPresent - ports: - - containerPort: 9091 - - containerPort: 15004 - - containerPort: 15090 - protocol: TCP - name: http-envoy-prom - args: - - proxy - - --domain - - $(POD_NAMESPACE).svc.cluster.local - - --serviceCluster - - istio-policy - - --templateFile - - /etc/istio/proxy/envoy_policy.yaml.tmpl - - --controlPlaneAuthPolicy - - NONE - - --log_output_level=default:info - env: - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: INSTANCE_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.podIP - - name: SDS_ENABLED - value: "false" - resources: - limits: - cpu: 2000m - memory: 1024Mi - requests: - cpu: 100m - memory: 128Mi - volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - - name: uds-socket - mountPath: /sock - - name: policy-adapter-secret - mountPath: /var/run/secrets/istio.io/policy/adapter - readOnly: true ---- -# Source: istio/charts/mixer/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: istio-telemetry - namespace: istio-system - labels: - app: istio-mixer - chart: mixer - heritage: Helm - release: RELEASE-NAME - istio: mixer -spec: - strategy: - rollingUpdate: - maxSurge: 100% - maxUnavailable: 25% - selector: - matchLabels: - istio: mixer - istio-mixer-type: telemetry - template: - metadata: - labels: - app: telemetry - chart: mixer - heritage: Helm - release: RELEASE-NAME - security.istio.io/tlsMode: "istio" - istio: mixer - istio-mixer-type: telemetry - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-mixer-service-account - volumes: - - name: istio-certs - secret: - secretName: istio.istio-mixer-service-account - optional: true - - name: uds-socket - emptyDir: {} - - name: telemetry-adapter-secret - secret: - secretName: telemetry-adapter-secret - optional: true - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - "ppc64le" - - "s390x" - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "ppc64le" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "s390x" - containers: - - name: mixer - image: "docker.io/istio/mixer:1.4.3" - imagePullPolicy: IfNotPresent - ports: - - containerPort: 15014 - - containerPort: 42422 - args: - - --monitoringPort=15014 - - --address - - unix:///sock/mixer.socket - - --log_output_level=default:info - - --configStoreURL=mcp://istio-galley.istio-system.svc:9901 - - --configDefaultNamespace=istio-system - - --useAdapterCRDs=false - - --trace_zipkin_url=http://zipkin.istio-system:9411/api/v1/spans - - --averageLatencyThreshold - - 100ms - - --loadsheddingMode - - enforce - env: - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: GOMAXPROCS - value: "6" - resources: - limits: - cpu: 4800m - memory: 4G - requests: - cpu: 1000m - memory: 1G - volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - - name: telemetry-adapter-secret - mountPath: /var/run/secrets/istio.io/telemetry/adapter - readOnly: true - - name: uds-socket - mountPath: /sock - livenessProbe: - httpGet: - path: /version - port: 15014 - initialDelaySeconds: 5 - periodSeconds: 5 - - name: istio-proxy - image: "docker.io/istio/proxyv2:1.4.3" - imagePullPolicy: IfNotPresent - ports: - - containerPort: 9091 - - containerPort: 15004 - - containerPort: 15090 - protocol: TCP - name: http-envoy-prom - args: - - proxy - - --domain - - $(POD_NAMESPACE).svc.cluster.local - - --serviceCluster - - istio-telemetry - - --templateFile - - /etc/istio/proxy/envoy_telemetry.yaml.tmpl - - --controlPlaneAuthPolicy - - NONE - - --log_output_level=default:info - env: - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: INSTANCE_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.podIP - - name: SDS_ENABLED - value: "false" - resources: - limits: - cpu: 2000m - memory: 1024Mi - requests: - cpu: 100m - memory: 128Mi - volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - - name: uds-socket - mountPath: /sock ---- -# Source: istio/charts/pilot/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: istio-pilot - namespace: istio-system - # TODO: default template doesn't have this, which one is right ? - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME - istio: pilot -spec: - strategy: - rollingUpdate: - maxSurge: 100% - maxUnavailable: 25% - selector: - matchLabels: - istio: pilot - template: - metadata: - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME - istio: pilot - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-pilot-service-account - containers: - - name: discovery - image: "docker.io/istio/pilot:1.4.3" - imagePullPolicy: IfNotPresent - args: - - "discovery" - - --monitoringAddr=:15014 - - --log_output_level=default:info - - --domain - - cluster.local - - --secureGrpcAddr - - "" - - --keepaliveMaxServerConnectionAge - - "30m" - ports: - - containerPort: 8080 - - containerPort: 15010 - readinessProbe: - httpGet: - path: /ready - port: 8080 - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 5 - env: - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: PILOT_PUSH_THROTTLE - value: "100" - - name: PILOT_TRACE_SAMPLING - value: "100" - - name: PILOT_ENABLE_PROTOCOL_SNIFFING_FOR_OUTBOUND - value: "true" - - name: PILOT_ENABLE_PROTOCOL_SNIFFING_FOR_INBOUND - value: "false" - resources: - requests: - cpu: 3000m - memory: 2048Mi - volumeMounts: - - name: config-volume - mountPath: /etc/istio/config - - name: istio-certs - mountPath: /etc/certs - readOnly: true - - name: istio-proxy - image: "docker.io/istio/proxyv2:1.4.3" - imagePullPolicy: IfNotPresent - ports: - - containerPort: 15003 - - containerPort: 15005 - - containerPort: 15007 - - containerPort: 15011 - args: - - proxy - - --domain - - $(POD_NAMESPACE).svc.cluster.local - - --serviceCluster - - istio-pilot - - --templateFile - - /etc/istio/proxy/envoy_pilot.yaml.tmpl - - --controlPlaneAuthPolicy - - NONE - - --log_output_level=default:info - env: - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: INSTANCE_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.podIP - - name: SDS_ENABLED - value: "false" - resources: - limits: - cpu: 2000m - memory: 1024Mi - requests: - cpu: 100m - memory: 128Mi - volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - volumes: - - name: config-volume - configMap: - name: istio - - name: istio-certs - secret: - secretName: istio.istio-pilot-service-account - optional: true - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - "ppc64le" - - "s390x" - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "ppc64le" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "s390x" ---- -# Source: istio/charts/security/templates/deployment.yaml -# istio CA watching all namespaces -apiVersion: apps/v1 -kind: Deployment -metadata: - name: istio-citadel - namespace: istio-system - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME - istio: citadel -spec: - replicas: 1 - selector: - matchLabels: - istio: citadel - strategy: - rollingUpdate: - maxSurge: 100% - maxUnavailable: 25% - template: - metadata: - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME - istio: citadel - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-citadel-service-account - containers: - - name: citadel - image: "docker.io/istio/citadel:1.4.3" - imagePullPolicy: IfNotPresent - args: - - --append-dns-names=true - - --grpc-port=8060 - - --citadel-storage-namespace=istio-system - - --custom-dns-names=istio-pilot-service-account.istio-system:istio-pilot.istio-system - - --monitoring-port=15014 - - --self-signed-ca=true - - --workload-cert-ttl=2160h - env: - - name: CITADEL_ENABLE_NAMESPACES_BY_DEFAULT - value: "true" - resources: - requests: - cpu: 10m - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - "ppc64le" - - "s390x" - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "ppc64le" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "s390x" ---- -# Source: istio/charts/sidecarInjectorWebhook/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: istio-sidecar-injector - namespace: istio-system - labels: - app: sidecarInjectorWebhook - chart: sidecarInjectorWebhook - heritage: Helm - release: RELEASE-NAME - istio: sidecar-injector -spec: - replicas: 1 - selector: - matchLabels: - istio: sidecar-injector - strategy: - rollingUpdate: - maxSurge: 100% - maxUnavailable: 25% - template: - metadata: - labels: - app: sidecarInjectorWebhook - chart: sidecarInjectorWebhook - heritage: Helm - release: RELEASE-NAME - istio: sidecar-injector - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-sidecar-injector-service-account - containers: - - name: sidecar-injector-webhook - image: "docker.io/istio/sidecar_injector:1.4.3" - imagePullPolicy: IfNotPresent - args: - - --caCertFile=/etc/istio/certs/root-cert.pem - - --tlsCertFile=/etc/istio/certs/cert-chain.pem - - --tlsKeyFile=/etc/istio/certs/key.pem - - --injectConfig=/etc/istio/inject/config - - --meshConfig=/etc/istio/config/mesh - - --healthCheckInterval=2s - - --healthCheckFile=/health - - --reconcileWebhookConfig=true - volumeMounts: - - name: config-volume - mountPath: /etc/istio/config - readOnly: true - - name: certs - mountPath: /etc/istio/certs - readOnly: true - - name: inject-config - mountPath: /etc/istio/inject - readOnly: true - livenessProbe: - exec: - command: - - /usr/local/bin/sidecar-injector - - probe - - --probe-path=/health - - --interval=4s - initialDelaySeconds: 4 - periodSeconds: 4 - readinessProbe: - exec: - command: - - /usr/local/bin/sidecar-injector - - probe - - --probe-path=/health - - --interval=4s - initialDelaySeconds: 4 - periodSeconds: 4 - resources: - requests: - cpu: 10m - volumes: - - name: config-volume - configMap: - name: istio - - name: certs - secret: - secretName: istio.istio-sidecar-injector-service-account - - name: inject-config - configMap: - name: istio-sidecar-injector - items: - - key: config - path: config - - key: values - path: values - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - "ppc64le" - - "s390x" - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "ppc64le" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "s390x" ---- -# Source: istio/charts/gateways/templates/autoscale.yaml -apiVersion: autoscaling/v2beta1 -kind: HorizontalPodAutoscaler -metadata: - name: istio-ingressgateway - namespace: istio-system - labels: - chart: gateways - heritage: Helm - release: RELEASE-NAME - app: istio-ingressgateway - istio: ingressgateway -spec: - maxReplicas: 4 - minReplicas: 2 - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: istio-ingressgateway - metrics: - - type: Resource - resource: - name: cpu - targetAverageUtilization: 80 ---- -# Source: istio/charts/mixer/templates/autoscale.yaml -apiVersion: autoscaling/v2beta1 -kind: HorizontalPodAutoscaler -metadata: - name: istio-telemetry - namespace: istio-system - labels: - app: mixer - chart: mixer - heritage: Helm - release: RELEASE-NAME -spec: - maxReplicas: 5 - minReplicas: 1 - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: istio-telemetry - metrics: - - type: Resource - resource: - name: cpu - targetAverageUtilization: 80 ---- -# Source: istio/charts/mixer/templates/autoscale.yaml -apiVersion: autoscaling/v2beta1 -kind: HorizontalPodAutoscaler -metadata: - name: istio-policy - namespace: istio-system - labels: - app: mixer - chart: mixer - heritage: Helm - release: RELEASE-NAME -spec: - maxReplicas: 5 - minReplicas: 1 - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: istio-policy - metrics: - - type: Resource - resource: - name: cpu - targetAverageUtilization: 80 ---- -# Source: istio/charts/pilot/templates/autoscale.yaml -apiVersion: autoscaling/v2beta1 -kind: HorizontalPodAutoscaler -metadata: - name: istio-pilot - namespace: istio-system - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME -spec: - maxReplicas: 5 - minReplicas: 2 - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: istio-pilot - metrics: - - type: Resource - resource: - name: cpu - targetAverageUtilization: 80 ---- -# Source: istio/charts/mixer/templates/config.yaml ---- ---- -# Source: istio/charts/mixer/templates/config.yaml -apiVersion: networking.istio.io/v1alpha3 -kind: DestinationRule -metadata: - name: istio-telemetry - namespace: istio-system - labels: - app: mixer - chart: mixer - heritage: Helm - release: RELEASE-NAME -spec: - host: istio-telemetry.istio-system.svc.cluster.local - trafficPolicy: - portLevelSettings: - - port: - number: 15004 # grpc-mixer-mtls - tls: - mode: ISTIO_MUTUAL - - port: - number: 9091 # grpc-mixer - tls: - mode: DISABLE - connectionPool: - http: - http2MaxRequests: 10000 - maxRequestsPerConnection: 10000 ---- -# Source: istio/charts/mixer/templates/config.yaml -# Configuration needed by Mixer. -# Mixer cluster is delivered via CDS -# Specify mixer cluster settings -apiVersion: networking.istio.io/v1alpha3 -kind: DestinationRule -metadata: - name: istio-policy - namespace: istio-system - labels: - app: mixer - chart: mixer - heritage: Helm - release: RELEASE-NAME -spec: - host: istio-policy.istio-system.svc.cluster.local - trafficPolicy: - portLevelSettings: - - port: - number: 15004 # grpc-mixer-mtls - tls: - mode: ISTIO_MUTUAL - - port: - number: 9091 # grpc-mixer - tls: - mode: DISABLE - connectionPool: - http: - http2MaxRequests: 10000 - maxRequestsPerConnection: 10000 ---- -# Source: istio/charts/sidecarInjectorWebhook/templates/mutatingwebhook.yaml -apiVersion: admissionregistration.k8s.io/v1beta1 -kind: MutatingWebhookConfiguration -metadata: - name: istio-sidecar-injector - labels: - app: sidecarInjectorWebhook - chart: sidecarInjectorWebhook - heritage: Helm - release: RELEASE-NAME -webhooks: - - name: sidecar-injector.istio.io - clientConfig: - service: - name: istio-sidecar-injector - namespace: istio-system - path: "/inject" - caBundle: "" - rules: - - operations: [ "CREATE" ] - apiGroups: [""] - apiVersions: ["v1"] - resources: ["pods"] - failurePolicy: Fail - namespaceSelector: - matchLabels: - istio-injection: enabled ---- -# Source: istio/charts/mixer/templates/config.yaml -apiVersion: "config.istio.io/v1alpha2" -kind: attributemanifest -metadata: - name: kubernetes - namespace: istio-system - labels: - app: mixer - chart: mixer - heritage: Helm - release: RELEASE-NAME -spec: - attributes: - source.ip: - valueType: IP_ADDRESS - source.labels: - valueType: STRING_MAP - source.metadata: - valueType: STRING_MAP - source.name: - valueType: STRING - source.namespace: - valueType: STRING - source.owner: - valueType: STRING - source.serviceAccount: - valueType: STRING - source.services: - valueType: STRING - source.workload.uid: - valueType: STRING - source.workload.name: - valueType: STRING - source.workload.namespace: - valueType: STRING - destination.ip: - valueType: IP_ADDRESS - destination.labels: - valueType: STRING_MAP - destination.metadata: - valueType: STRING_MAP - destination.owner: - valueType: STRING - destination.name: - valueType: STRING - destination.container.name: - valueType: STRING - destination.namespace: - valueType: STRING - destination.service.uid: - valueType: STRING - destination.service.name: - valueType: STRING - destination.service.namespace: - valueType: STRING - destination.service.host: - valueType: STRING - destination.serviceAccount: - valueType: STRING - destination.workload.uid: - valueType: STRING - destination.workload.name: - valueType: STRING - destination.workload.namespace: - valueType: STRING ---- -# Source: istio/charts/mixer/templates/config.yaml -apiVersion: "config.istio.io/v1alpha2" -kind: attributemanifest -metadata: - name: istioproxy - namespace: istio-system - labels: - app: mixer - chart: mixer - heritage: Helm - release: RELEASE-NAME -spec: - attributes: - origin.ip: - valueType: IP_ADDRESS - origin.uid: - valueType: STRING - origin.user: - valueType: STRING - request.headers: - valueType: STRING_MAP - request.id: - valueType: STRING - request.host: - valueType: STRING - request.method: - valueType: STRING - request.path: - valueType: STRING - request.url_path: - valueType: STRING - request.query_params: - valueType: STRING_MAP - request.reason: - valueType: STRING - request.referer: - valueType: STRING - request.scheme: - valueType: STRING - request.total_size: - valueType: INT64 - request.size: - valueType: INT64 - request.time: - valueType: TIMESTAMP - request.useragent: - valueType: STRING - response.code: - valueType: INT64 - response.duration: - valueType: DURATION - response.headers: - valueType: STRING_MAP - response.total_size: - valueType: INT64 - response.size: - valueType: INT64 - response.time: - valueType: TIMESTAMP - response.grpc_status: - valueType: STRING - response.grpc_message: - valueType: STRING - source.uid: - valueType: STRING - source.user: # DEPRECATED - valueType: STRING - source.principal: - valueType: STRING - destination.uid: - valueType: STRING - destination.principal: - valueType: STRING - destination.port: - valueType: INT64 - connection.event: - valueType: STRING - connection.id: - valueType: STRING - connection.received.bytes: - valueType: INT64 - connection.received.bytes_total: - valueType: INT64 - connection.sent.bytes: - valueType: INT64 - connection.sent.bytes_total: - valueType: INT64 - connection.duration: - valueType: DURATION - connection.mtls: - valueType: BOOL - connection.requested_server_name: - valueType: STRING - context.protocol: - valueType: STRING - context.proxy_error_code: - valueType: STRING - context.timestamp: - valueType: TIMESTAMP - context.time: - valueType: TIMESTAMP - # Deprecated, kept for compatibility - context.reporter.local: - valueType: BOOL - context.reporter.kind: - valueType: STRING - context.reporter.uid: - valueType: STRING - api.service: - valueType: STRING - api.version: - valueType: STRING - api.operation: - valueType: STRING - api.protocol: - valueType: STRING - request.auth.principal: - valueType: STRING - request.auth.audiences: - valueType: STRING - request.auth.presenter: - valueType: STRING - request.auth.claims: - valueType: STRING_MAP - request.auth.raw_claims: - valueType: STRING - request.api_key: - valueType: STRING - rbac.permissive.response_code: - valueType: STRING - rbac.permissive.effective_policy_id: - valueType: STRING - check.error_code: - valueType: INT64 - check.error_message: - valueType: STRING - check.cache_hit: - valueType: BOOL - quota.cache_hit: - valueType: BOOL - context.proxy_version: - valueType: STRING ---- -# Source: istio/charts/mixer/templates/config.yaml -apiVersion: "config.istio.io/v1alpha2" -kind: handler -metadata: - name: kubernetesenv - namespace: istio-system - labels: - app: mixer - chart: mixer - heritage: Helm - release: RELEASE-NAME -spec: - compiledAdapter: kubernetesenv - params: - # when running from mixer root, use the following config after adding a - # symbolic link to a kubernetes config file via: - # - # $ ln -s ~/.kube/config mixer/adapter/kubernetes/kubeconfig - # - # kubeconfig_path: "mixer/adapter/kubernetes/kubeconfig" ---- -# Source: istio/charts/mixer/templates/config.yaml -apiVersion: "config.istio.io/v1alpha2" -kind: instance -metadata: - name: attributes - namespace: istio-system - labels: - app: mixer - chart: mixer - heritage: Helm - release: RELEASE-NAME -spec: - compiledTemplate: kubernetes - params: - # Pass the required attribute data to the adapter - source_uid: source.uid | "" - source_ip: source.ip | ip("0.0.0.0") # default to unspecified ip addr - destination_uid: destination.uid | "" - destination_port: destination.port | 0 - attributeBindings: - # Fill the new attributes from the adapter produced output. - # $out refers to an instance of OutputTemplate message - source.ip: $out.source_pod_ip | ip("0.0.0.0") - source.uid: $out.source_pod_uid | "unknown" - source.labels: $out.source_labels | emptyStringMap() - source.name: $out.source_pod_name | "unknown" - source.namespace: $out.source_namespace | "default" - source.owner: $out.source_owner | "unknown" - source.serviceAccount: $out.source_service_account_name | "unknown" - source.workload.uid: $out.source_workload_uid | "unknown" - source.workload.name: $out.source_workload_name | "unknown" - source.workload.namespace: $out.source_workload_namespace | "unknown" - destination.ip: $out.destination_pod_ip | ip("0.0.0.0") - destination.uid: $out.destination_pod_uid | "unknown" - destination.labels: $out.destination_labels | emptyStringMap() - destination.name: $out.destination_pod_name | "unknown" - destination.container.name: $out.destination_container_name | "unknown" - destination.namespace: $out.destination_namespace | "default" - destination.owner: $out.destination_owner | "unknown" - destination.serviceAccount: $out.destination_service_account_name | "unknown" - destination.workload.uid: $out.destination_workload_uid | "unknown" - destination.workload.name: $out.destination_workload_name | "unknown" - destination.workload.namespace: $out.destination_workload_namespace | "unknown" ---- -# Source: istio/charts/mixer/templates/config.yaml -apiVersion: "config.istio.io/v1alpha2" -kind: rule -metadata: - name: kubeattrgenrulerule - namespace: istio-system - labels: - app: mixer - chart: mixer - heritage: Helm - release: RELEASE-NAME -spec: - actions: - - handler: kubernetesenv - instances: - - attributes ---- -# Source: istio/charts/mixer/templates/config.yaml -apiVersion: "config.istio.io/v1alpha2" -kind: rule -metadata: - name: tcpkubeattrgenrulerule - namespace: istio-system - labels: - app: mixer - chart: mixer - heritage: Helm - release: RELEASE-NAME -spec: - match: context.protocol == "tcp" - actions: - - handler: kubernetesenv - instances: - - attributes ---- -# Source: istio/charts/security/templates/create-custom-resources-job.yaml -apiVersion: batch/v1 -kind: Job -metadata: - name: istio-security-post-install-1.4.3 - namespace: istio-system - annotations: - "helm.sh/hook": post-install,post-upgrade - "helm.sh/hook-delete-policy": hook-succeeded - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME -spec: - template: - metadata: - name: istio-security-post-install - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-security-post-install-account - containers: - - name: kubectl - image: "docker.io/istio/kubectl:1.4.3" - imagePullPolicy: IfNotPresent - command: [ "/bin/bash", "/tmp/security/run.sh", "/tmp/security/custom-resources.yaml" ] - volumeMounts: - - mountPath: "/tmp/security" - name: tmp-configmap-security - volumes: - - name: tmp-configmap-security - configMap: - name: istio-security-custom-resources - restartPolicy: OnFailure - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - "ppc64le" - - "s390x" - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "ppc64le" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "s390x" diff --git a/third_party/istio-1.4.3/istio-ci-no-mesh.yaml b/third_party/istio-1.4.3/istio-ci-no-mesh.yaml deleted file mode 100644 index c34600b382b..00000000000 --- a/third_party/istio-1.4.3/istio-ci-no-mesh.yaml +++ /dev/null @@ -1,1738 +0,0 @@ ---- -# PATCH #1: Creating the istio-system namespace. -apiVersion: v1 -kind: Namespace -metadata: - name: istio-system - labels: - istio-injection: disabled -# PATCH #1 ends. ---- -# Source: istio/charts/galley/templates/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: istio-galley-configuration - namespace: istio-system - labels: - app: galley - chart: galley - heritage: Helm - release: RELEASE-NAME - istio: galley -data: - validatingwebhookconfiguration.yaml: |- - apiVersion: admissionregistration.k8s.io/v1beta1 - kind: ValidatingWebhookConfiguration - metadata: - name: istio-galley - labels: - app: galley - chart: galley - heritage: Helm - release: RELEASE-NAME - istio: galley - webhooks: - - name: pilot.validation.istio.io - clientConfig: - service: - name: istio-galley - namespace: istio-system - path: "/admitpilot" - caBundle: "" - rules: - - operations: - - CREATE - - UPDATE - apiGroups: - - config.istio.io - apiVersions: - - v1alpha2 - resources: - - httpapispecs - - httpapispecbindings - - quotaspecs - - quotaspecbindings - - operations: - - CREATE - - UPDATE - apiGroups: - - rbac.istio.io - apiVersions: - - "*" - resources: - - "*" - - operations: - - CREATE - - UPDATE - apiGroups: - - security.istio.io - apiVersions: - - "*" - resources: - - "*" - - operations: - - CREATE - - UPDATE - apiGroups: - - authentication.istio.io - apiVersions: - - "*" - resources: - - "*" - - operations: - - CREATE - - UPDATE - apiGroups: - - networking.istio.io - apiVersions: - - "*" - resources: - - destinationrules - - envoyfilters - - gateways - - serviceentries - - sidecars - - virtualservices - failurePolicy: Fail - sideEffects: None - - name: mixer.validation.istio.io - clientConfig: - service: - name: istio-galley - namespace: istio-system - path: "/admitmixer" - caBundle: "" - rules: - - operations: - - CREATE - - UPDATE - apiGroups: - - config.istio.io - apiVersions: - - v1alpha2 - resources: - - rules - - attributemanifests - - circonuses - - deniers - - fluentds - - kubernetesenvs - - listcheckers - - memquotas - - noops - - opas - - prometheuses - - rbacs - - solarwindses - - stackdrivers - - cloudwatches - - dogstatsds - - statsds - - stdios - - apikeys - - authorizations - - checknothings - # - kuberneteses - - listentries - - logentries - - metrics - - quotas - - reportnothings - - tracespans - - adapters - - handlers - - instances - - templates - - zipkins - failurePolicy: Fail - sideEffects: None ---- -# Source: istio/charts/security/templates/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: istio-security-custom-resources - namespace: istio-system - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME - istio: citadel -data: - custom-resources.yaml: |- - # Authentication policy to enable permissive mode for all services (that have sidecar) in the mesh. - apiVersion: "authentication.istio.io/v1alpha1" - kind: "MeshPolicy" - metadata: - name: "default" - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME - spec: - peers: - - mtls: - mode: PERMISSIVE - run.sh: |- - #!/bin/sh - - set -x - - if [ "$#" -ne "1" ]; then - echo "first argument should be path to custom resource yaml" - exit 1 - fi - - pathToResourceYAML=${1} - - kubectl get validatingwebhookconfiguration istio-galley 2>/dev/null - if [ "$?" -eq 0 ]; then - echo "istio-galley validatingwebhookconfiguration found - waiting for istio-galley deployment to be ready" - while true; do - kubectl -n istio-system get deployment istio-galley 2>/dev/null - if [ "$?" -eq 0 ]; then - break - fi - sleep 1 - done - kubectl -n istio-system rollout status deployment istio-galley - if [ "$?" -ne 0 ]; then - echo "istio-galley deployment rollout status check failed" - exit 1 - fi - echo "istio-galley deployment ready for configuration validation" - fi - sleep 5 - kubectl apply -f ${pathToResourceYAML} ---- -# Source: istio/templates/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: istio - namespace: istio-system - labels: - app: istio - chart: istio - heritage: Helm - release: RELEASE-NAME -data: - mesh: |- - # Set the following variable to true to disable policy checks by Mixer. - # Note that metrics will still be reported to Mixer. - disablePolicyChecks: true - - disableMixerHttpReports: false - # reportBatchMaxEntries is the number of requests that are batched before telemetry data is sent to the mixer server - reportBatchMaxEntries: 100 - # reportBatchMaxTime is the max waiting time before the telemetry data of a request is sent to the mixer server - reportBatchMaxTime: 1s - - # Set enableTracing to false to disable request tracing. - enableTracing: true - - # Set accessLogFile to empty string to disable access log. - accessLogFile: "/dev/stdout" - - # If accessLogEncoding is TEXT, value will be used directly as the log format - # example: "[%START_TIME%] %REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\n" - # If AccessLogEncoding is JSON, value will be parsed as map[string]string - # example: '{"start_time": "%START_TIME%", "req_method": "%REQ(:METHOD)%"}' - # Leave empty to use default log format - accessLogFormat: "" - - # Set accessLogEncoding to JSON or TEXT to configure sidecar access log - accessLogEncoding: 'JSON' - - enableEnvoyAccessLogService: false - # Let Pilot give ingresses the public IP of the Istio ingressgateway - ingressService: istio-ingressgateway - - # Default connect timeout for dynamic clusters generated by Pilot and returned via XDS - connectTimeout: 10s - - # Automatic protocol detection uses a set of heuristics to - # determine whether the connection is using TLS or not (on the - # server side), as well as the application protocol being used - # (e.g., http vs tcp). These heuristics rely on the client sending - # the first bits of data. For server first protocols like MySQL, - # MongoDB, etc., Envoy will timeout on the protocol detection after - # the specified period, defaulting to non mTLS plain TCP - # traffic. Set this field to tweak the period that Envoy will wait - # for the client to send the first bits of data. (MUST BE >=1ms) - protocolDetectionTimeout: 100ms - - # DNS refresh rate for Envoy clusters of type STRICT_DNS - dnsRefreshRate: 300s - - # Unix Domain Socket through which envoy communicates with NodeAgent SDS to get - # key/cert for mTLS. Use secret-mount files instead of SDS if set to empty. - sdsUdsPath: "" - - # The trust domain corresponds to the trust root of a system. - # Refer to https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE-ID.md#21-trust-domain - trustDomain: "" - - # The trust domain aliases represent the aliases of trust_domain. - # For example, if we have - # trustDomain: td1 - # trustDomainAliases: [“td2”, "td3"] - # Any service with the identity "td1/ns/foo/sa/a-service-account", "td2/ns/foo/sa/a-service-account", - # or "td3/ns/foo/sa/a-service-account" will be treated the same in the Istio mesh. - trustDomainAliases: - - # If true, automatically configure client side mTLS settings to match the corresponding service's - # server side mTLS authentication policy, when destination rule for that service does not specify - # TLS settings. - enableAutoMtls: false - - # Set the default behavior of the sidecar for handling outbound traffic from the application: - # ALLOW_ANY - outbound traffic to unknown destinations will be allowed, in case there are no - # services or ServiceEntries for the destination port - # REGISTRY_ONLY - restrict outbound traffic to services defined in the service registry as well - # as those defined through ServiceEntries - outboundTrafficPolicy: - mode: ALLOW_ANY - localityLbSetting: - enabled: true - # The namespace to treat as the administrative root namespace for istio - # configuration. - rootNamespace: istio-system - - # Configures DNS certificates provisioned through Chiron linked into Pilot. - certificates: - [] - - defaultConfig: - # - # TCP connection timeout between Envoy & the application, and between Envoys. Used for static clusters - # defined in Envoy's configuration file - connectTimeout: 10s - # - ### ADVANCED SETTINGS ############# - # Where should envoy's configuration be stored in the istio-proxy container - configPath: "/etc/istio/proxy" - binaryPath: "/usr/local/bin/envoy" - # The pseudo service name used for Envoy. - serviceCluster: istio-proxy - # These settings that determine how long an old Envoy - # process should be kept alive after an occasional reload. - drainDuration: 45s - parentShutdownDuration: 1m0s - # - # The mode used to redirect inbound connections to Envoy. This setting - # has no effect on outbound traffic: iptables REDIRECT is always used for - # outbound connections. - # If "REDIRECT", use iptables REDIRECT to NAT and redirect to Envoy. - # The "REDIRECT" mode loses source addresses during redirection. - # If "TPROXY", use iptables TPROXY to redirect to Envoy. - # The "TPROXY" mode preserves both the source and destination IP - # addresses and ports, so that they can be used for advanced filtering - # and manipulation. - # The "TPROXY" mode also configures the sidecar to run with the - # CAP_NET_ADMIN capability, which is required to use TPROXY. - #interceptionMode: REDIRECT - # - # Port where Envoy listens (on local host) for admin commands - # You can exec into the istio-proxy container in a pod and - # curl the admin port (curl http://localhost:15000/) to obtain - # diagnostic information from Envoy. See - # https://lyft.github.io/envoy/docs/operations/admin.html - # for more details - proxyAdminPort: 15000 - # - # Set concurrency to a specific number to control the number of Proxy worker threads. - # If set to 0 (default), then start worker thread for each CPU thread/core. - concurrency: 2 - # - tracing: - zipkin: - # Address of the Zipkin collector - address: zipkin.istio-system:9411 - # - # Mutual TLS authentication between sidecars and istio control plane. - controlPlaneAuthPolicy: NONE - # - # Address where istio Pilot service is running - discoveryAddress: istio-pilot.istio-system:15010 - - # Configuration file for the mesh networks to be used by the Split Horizon EDS. - meshNetworks: |- - networks: {} ---- -# Source: istio/charts/galley/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-galley-service-account - namespace: istio-system - labels: - app: galley - chart: galley - heritage: Helm - release: RELEASE-NAME ---- -# Source: istio/charts/gateways/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: cluster-local-gateway-service-account - namespace: istio-system - labels: - app: cluster-local-gateway - chart: gateways - heritage: Helm - release: RELEASE-NAME ---- -# Source: istio/charts/gateways/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-ingressgateway-service-account - namespace: istio-system - labels: - app: istio-ingressgateway - chart: gateways - heritage: Helm - release: RELEASE-NAME ---- -# Source: istio/charts/pilot/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-pilot-service-account - namespace: istio-system - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME ---- -# Source: istio/charts/security/templates/create-custom-resources-job.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-security-post-install-account - namespace: istio-system - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME ---- -# Source: istio/charts/security/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-citadel-service-account - namespace: istio-system - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME ---- -# Source: istio/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-multi - namespace: istio-system ---- -# Source: istio/charts/galley/templates/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: istio-galley-istio-system - labels: - app: galley - chart: galley - heritage: Helm - release: RELEASE-NAME -rules: - # For reading Istio resources -- apiGroups: [ - "authentication.istio.io", - "config.istio.io", - "networking.istio.io", - "rbac.istio.io", - "security.istio.io"] - resources: ["*"] - verbs: ["get", "list", "watch"] - # For updating Istio resource statuses -- apiGroups: [ - "authentication.istio.io", - "config.istio.io", - "networking.istio.io", - "rbac.istio.io", - "security.istio.io"] - resources: ["*/status"] - verbs: ["update"] -- apiGroups: ["admissionregistration.k8s.io"] - resources: ["validatingwebhookconfigurations"] - verbs: ["*"] -- apiGroups: ["extensions","apps"] - resources: ["deployments"] - resourceNames: ["istio-galley"] - verbs: ["get"] -- apiGroups: [""] - resources: ["pods", "nodes", "services", "endpoints", "namespaces"] - verbs: ["get", "list", "watch"] -- apiGroups: ["extensions"] - resources: ["ingresses"] - verbs: ["get", "list", "watch"] -- apiGroups: ["extensions"] - resources: ["deployments/finalizers"] - resourceNames: ["istio-galley"] - verbs: ["update"] -- apiGroups: ["apiextensions.k8s.io"] - resources: ["customresourcedefinitions"] - verbs: ["get", "list", "watch"] ---- -# Source: istio/charts/pilot/templates/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: istio-pilot-istio-system - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME -rules: -- apiGroups: ["config.istio.io"] - resources: ["*"] - verbs: ["*"] -- apiGroups: ["rbac.istio.io"] - resources: ["*"] - verbs: ["get", "watch", "list"] -- apiGroups: ["security.istio.io"] - resources: ["*"] - verbs: ["get", "watch", "list"] -- apiGroups: ["networking.istio.io"] - resources: ["*"] - verbs: ["*"] -- apiGroups: ["authentication.istio.io"] - resources: ["*"] - verbs: ["*"] -- apiGroups: ["apiextensions.k8s.io"] - resources: ["customresourcedefinitions"] - verbs: ["*"] -- apiGroups: ["extensions"] - resources: ["ingresses", "ingresses/status"] - verbs: ["*"] -- apiGroups: [""] - resources: ["configmaps"] - verbs: ["create", "get", "list", "watch", "update"] -- apiGroups: [""] - resources: ["endpoints", "pods", "services", "namespaces", "nodes"] - verbs: ["get", "list", "watch"] -- apiGroups: [""] - resources: ["secrets"] - verbs: ["create", "get", "watch", "list", "update", "delete"] -- apiGroups: ["certificates.k8s.io"] - resources: - - "certificatesigningrequests" - - "certificatesigningrequests/approval" - - "certificatesigningrequests/status" - verbs: ["update", "create", "get", "delete"] ---- -# Source: istio/charts/security/templates/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: istio-citadel-istio-system - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME -rules: -- apiGroups: [""] - resources: ["configmaps"] - verbs: ["create", "get", "update"] -- apiGroups: [""] - resources: ["secrets"] - verbs: ["create", "get", "watch", "list", "update", "delete"] -- apiGroups: [""] - resources: ["serviceaccounts", "services", "namespaces"] - verbs: ["get", "watch", "list"] -- apiGroups: ["authentication.k8s.io"] - resources: ["tokenreviews"] - verbs: ["create"] ---- -# Source: istio/charts/security/templates/create-custom-resources-job.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: istio-security-post-install-istio-system - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME -rules: -- apiGroups: ["authentication.istio.io"] # needed to create default authn policy - resources: ["*"] - verbs: ["*"] -- apiGroups: ["networking.istio.io"] # needed to create security destination rules - resources: ["*"] - verbs: ["*"] -- apiGroups: ["admissionregistration.k8s.io"] - resources: ["validatingwebhookconfigurations"] - verbs: ["get"] -- apiGroups: ["extensions", "apps"] - resources: ["deployments", "replicasets"] - verbs: ["get", "list", "watch"] ---- -# Source: istio/templates/clusterrole.yaml -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: istio-reader -rules: - - apiGroups: [''] - resources: ['nodes', 'pods', 'services', 'endpoints', "replicationcontrollers"] - verbs: ['get', 'watch', 'list'] - - apiGroups: ["extensions", "apps"] - resources: ["replicasets"] - verbs: ["get", "list", "watch"] ---- -# Source: istio/charts/galley/templates/clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: istio-galley-admin-role-binding-istio-system - labels: - app: galley - chart: galley - heritage: Helm - release: RELEASE-NAME -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: istio-galley-istio-system -subjects: - - kind: ServiceAccount - name: istio-galley-service-account - namespace: istio-system ---- -# Source: istio/charts/pilot/templates/clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: istio-pilot-istio-system - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: istio-pilot-istio-system -subjects: - - kind: ServiceAccount - name: istio-pilot-service-account - namespace: istio-system ---- -# Source: istio/charts/security/templates/clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: istio-citadel-istio-system - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: istio-citadel-istio-system -subjects: - - kind: ServiceAccount - name: istio-citadel-service-account - namespace: istio-system ---- -# Source: istio/charts/security/templates/create-custom-resources-job.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: istio-security-post-install-role-binding-istio-system - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: istio-security-post-install-istio-system -subjects: - - kind: ServiceAccount - name: istio-security-post-install-account - namespace: istio-system ---- -# Source: istio/templates/clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: istio-multi - labels: - chart: istio-1.4.3 -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: istio-reader -subjects: -- kind: ServiceAccount - name: istio-multi - namespace: istio-system ---- -# Source: istio/charts/gateways/templates/role.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: istio-ingressgateway-sds - namespace: istio-system -rules: -- apiGroups: [""] - resources: ["secrets"] - verbs: ["get", "watch", "list"] ---- -# Source: istio/charts/gateways/templates/rolebindings.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: istio-ingressgateway-sds - namespace: istio-system -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: istio-ingressgateway-sds -subjects: -- kind: ServiceAccount - name: istio-ingressgateway-service-account ---- -# Source: istio/charts/galley/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: istio-galley - namespace: istio-system - labels: - app: galley - chart: galley - heritage: Helm - release: RELEASE-NAME - istio: galley -spec: - ports: - - port: 443 - name: https-validation - - port: 15014 - name: http-monitoring - - port: 9901 - name: grpc-mcp - selector: - istio: galley ---- -# Source: istio/charts/gateways/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: cluster-local-gateway - namespace: istio-system - annotations: - labels: - chart: gateways - heritage: Helm - release: RELEASE-NAME - app: cluster-local-gateway - istio: cluster-local-gateway -spec: - type: ClusterIP - selector: - release: RELEASE-NAME - app: cluster-local-gateway - istio: cluster-local-gateway - ports: - - - name: status-port - port: 15020 - - - name: http2 - port: 80 - - - name: https - port: 443 ---- -# Source: istio/charts/gateways/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: istio-ingressgateway - namespace: istio-system - annotations: - labels: - chart: gateways - heritage: Helm - release: RELEASE-NAME - app: istio-ingressgateway - istio: ingressgateway -spec: - type: LoadBalancer - selector: - release: RELEASE-NAME - app: istio-ingressgateway - istio: ingressgateway - ports: - - - name: status-port - port: 15020 - - - name: http2 - port: 80 - - - name: https - port: 443 ---- -# Source: istio/charts/pilot/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: istio-pilot - namespace: istio-system - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME - istio: pilot -spec: - ports: - - port: 15010 - name: grpc-xds # direct - - port: 15011 - name: https-xds # mTLS - - port: 8080 - name: http-legacy-discovery # direct - - port: 15014 - name: http-monitoring - selector: - istio: pilot ---- -# Source: istio/charts/security/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - # we use the normal name here (e.g. 'prometheus') - # as grafana is configured to use this as a data source - name: istio-citadel - namespace: istio-system - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME - istio: citadel -spec: - ports: - - name: grpc-citadel - port: 8060 - targetPort: 8060 - protocol: TCP - - name: http-monitoring - port: 15014 - selector: - istio: citadel ---- -# Source: istio/charts/galley/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: istio-galley - namespace: istio-system - labels: - app: galley - chart: galley - heritage: Helm - release: RELEASE-NAME - istio: galley -spec: - replicas: 1 - selector: - matchLabels: - istio: galley - strategy: - rollingUpdate: - maxSurge: 100% - maxUnavailable: 25% - template: - metadata: - labels: - app: galley - chart: galley - heritage: Helm - release: RELEASE-NAME - istio: galley - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-galley-service-account - containers: - - name: galley - image: "docker.io/istio/galley:1.4.3" - imagePullPolicy: IfNotPresent - ports: - - containerPort: 443 - - containerPort: 15014 - - containerPort: 9901 - command: - - /usr/local/bin/galley - - server - - --meshConfigFile=/etc/mesh-config/mesh - - --livenessProbeInterval=1s - - --livenessProbePath=/healthliveness - - --readinessProbePath=/healthready - - --readinessProbeInterval=1s - - --deployment-namespace=istio-system - - --insecure=true - - --enable-server=false - - --enable-reconcileWebhookConfiguration=true - - --validation-webhook-config-file - - /etc/config/validatingwebhookconfiguration.yaml - - --monitoringPort=15014 - - --log_output_level=default:info - volumeMounts: - - name: certs - mountPath: /etc/certs - readOnly: true - - name: config - mountPath: /etc/config - readOnly: true - - name: mesh-config - mountPath: /etc/mesh-config - readOnly: true - livenessProbe: - exec: - command: - - /usr/local/bin/galley - - probe - - --probe-path=/healthliveness - - --interval=10s - initialDelaySeconds: 5 - periodSeconds: 5 - readinessProbe: - exec: - command: - - /usr/local/bin/galley - - probe - - --probe-path=/healthready - - --interval=10s - initialDelaySeconds: 5 - periodSeconds: 5 - resources: - requests: - cpu: 10m - volumes: - - name: certs - secret: - secretName: istio.istio-galley-service-account - - name: config - configMap: - name: istio-galley-configuration - - name: mesh-config - configMap: - name: istio - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - "ppc64le" - - "s390x" - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "ppc64le" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "s390x" ---- -# Source: istio/charts/gateways/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: cluster-local-gateway - namespace: istio-system - labels: - app: cluster-local-gateway - chart: gateways - heritage: Helm - istio: cluster-local-gateway - release: RELEASE-NAME -spec: - replicas: 2 - selector: - matchLabels: - app: cluster-local-gateway - istio: cluster-local-gateway - strategy: - rollingUpdate: - maxSurge: - maxUnavailable: - template: - metadata: - labels: - app: cluster-local-gateway - chart: gateways - heritage: Helm - istio: cluster-local-gateway - release: RELEASE-NAME - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: cluster-local-gateway-service-account - containers: - - name: istio-proxy - image: "docker.io/istio/proxyv2:1.4.3" - imagePullPolicy: IfNotPresent - ports: - - containerPort: 15020 - - containerPort: 80 - - containerPort: 443 - - containerPort: 15090 - protocol: TCP - name: http-envoy-prom - args: - - proxy - - router - - --domain - - $(POD_NAMESPACE).svc.cluster.local - - --log_output_level=default:info - - --drainDuration - - '45s' #drainDuration - - --parentShutdownDuration - - '1m0s' #parentShutdownDuration - - --connectTimeout - - '10s' #connectTimeout - - --serviceCluster - - cluster-local-gateway - - --zipkinAddress - - zipkin:9411 - - --proxyAdminPort - - "15000" - - --statusPort - - "15020" - - --controlPlaneAuthPolicy - - NONE - - --discoveryAddress - - istio-pilot:15010 - readinessProbe: - failureThreshold: 30 - httpGet: - path: /healthz/ready - port: 15020 - scheme: HTTP - initialDelaySeconds: 1 - periodSeconds: 2 - successThreshold: 1 - timeoutSeconds: 1 - resources: - requests: - cpu: 1000m - memory: 1024Mi - env: - - name: NODE_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: spec.nodeName - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: INSTANCE_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.podIP - - name: HOST_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.hostIP - - name: SERVICE_ACCOUNT - valueFrom: - fieldRef: - fieldPath: spec.serviceAccountName - - name: ISTIO_META_POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: ISTIO_META_CONFIG_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: ISTIO_METAJSON_LABELS - value: | - {"app":"cluster-local-gateway","chart":"gateways","heritage":"Helm","istio":"cluster-local-gateway","release":"RELEASE-NAME"} - - name: ISTIO_META_CLUSTER_ID - value: "Kubernetes" - - name: SDS_ENABLED - value: "false" - - name: ISTIO_META_WORKLOAD_NAME - value: cluster-local-gateway - - name: ISTIO_META_OWNER - value: kubernetes://apis/apps/v1/namespaces/istio-system/deployments/cluster-local-gateway - - volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - - name: cluster-local-gateway-certs - mountPath: "/etc/istio/cluster-local-gateway-certs" - readOnly: true - - name: cluster-local-gateway-ca-certs - mountPath: "/etc/istio/cluster-local-gateway-ca-certs" - readOnly: true - volumes: - - name: istio-certs - secret: - secretName: istio.cluster-local-gateway-service-account - optional: true - - name: cluster-local-gateway-certs - secret: - secretName: "istio-cluster-local-gateway-certs" - optional: true - - name: cluster-local-gateway-ca-certs - secret: - secretName: "istio-cluster-local-gateway-ca-certs" - optional: true - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - "ppc64le" - - "s390x" - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "ppc64le" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "s390x" ---- -# Source: istio/charts/gateways/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: istio-ingressgateway - namespace: istio-system - labels: - app: istio-ingressgateway - chart: gateways - heritage: Helm - istio: ingressgateway - release: RELEASE-NAME -spec: - selector: - matchLabels: - app: istio-ingressgateway - istio: ingressgateway - strategy: - rollingUpdate: - maxSurge: 100% - maxUnavailable: 25% - template: - metadata: - labels: - app: istio-ingressgateway - chart: gateways - heritage: Helm - istio: ingressgateway - release: RELEASE-NAME - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-ingressgateway-service-account - containers: - - name: ingress-sds - image: "docker.io/istio/node-agent-k8s:1.4.3" - imagePullPolicy: IfNotPresent - resources: - limits: - cpu: 2000m - memory: 1024Mi - requests: - cpu: 100m - memory: 128Mi - env: - - name: "ENABLE_WORKLOAD_SDS" - value: "false" - - name: "ENABLE_INGRESS_GATEWAY_SDS" - value: "true" - - name: "INGRESS_GATEWAY_NAMESPACE" - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - volumeMounts: - - name: ingressgatewaysdsudspath - mountPath: /var/run/ingress_gateway - - name: istio-proxy - image: "docker.io/istio/proxyv2:1.4.3" - imagePullPolicy: IfNotPresent - ports: - - containerPort: 15020 - - containerPort: 80 - - containerPort: 443 - - containerPort: 15090 - protocol: TCP - name: http-envoy-prom - args: - - proxy - - router - - --domain - - $(POD_NAMESPACE).svc.cluster.local - - --log_output_level=default:info - - --drainDuration - - '45s' #drainDuration - - --parentShutdownDuration - - '1m0s' #parentShutdownDuration - - --connectTimeout - - '10s' #connectTimeout - - --serviceCluster - - istio-ingressgateway - - --zipkinAddress - - zipkin:9411 - - --proxyAdminPort - - "15000" - - --statusPort - - "15020" - - --controlPlaneAuthPolicy - - NONE - - --discoveryAddress - - istio-pilot:15010 - readinessProbe: - failureThreshold: 30 - httpGet: - path: /healthz/ready - port: 15020 - scheme: HTTP - initialDelaySeconds: 1 - periodSeconds: 2 - successThreshold: 1 - timeoutSeconds: 1 - resources: - limits: - cpu: 2000m - memory: 1024Mi - requests: - cpu: 1000m - memory: 1024Mi - env: - - name: NODE_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: spec.nodeName - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: INSTANCE_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.podIP - - name: HOST_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.hostIP - - name: SERVICE_ACCOUNT - valueFrom: - fieldRef: - fieldPath: spec.serviceAccountName - - name: ISTIO_META_POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: ISTIO_META_CONFIG_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: ISTIO_METAJSON_LABELS - value: | - {"app":"istio-ingressgateway","chart":"gateways","heritage":"Helm","istio":"ingressgateway","release":"RELEASE-NAME"} - - name: ISTIO_META_CLUSTER_ID - value: "Kubernetes" - - name: SDS_ENABLED - value: "false" - - name: ISTIO_META_WORKLOAD_NAME - value: istio-ingressgateway - - name: ISTIO_META_OWNER - value: kubernetes://apis/apps/v1/namespaces/istio-system/deployments/istio-ingressgateway - - name: ISTIO_META_USER_SDS - value: "true" - - name: ISTIO_META_ROUTER_MODE - value: sni-dnat - - - volumeMounts: - - name: ingressgatewaysdsudspath - mountPath: /var/run/ingress_gateway - - name: istio-certs - mountPath: /etc/certs - readOnly: true - - name: ingressgateway-certs - mountPath: "/etc/istio/ingressgateway-certs" - readOnly: true - - name: ingressgateway-ca-certs - mountPath: "/etc/istio/ingressgateway-ca-certs" - readOnly: true - volumes: - - name: ingressgatewaysdsudspath - emptyDir: {} - - name: istio-certs - secret: - secretName: istio.istio-ingressgateway-service-account - optional: true - - name: ingressgateway-certs - secret: - secretName: "istio-ingressgateway-certs" - optional: true - - name: ingressgateway-ca-certs - secret: - secretName: "istio-ingressgateway-ca-certs" - optional: true - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - "ppc64le" - - "s390x" - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "ppc64le" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "s390x" ---- -# Source: istio/charts/pilot/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: istio-pilot - namespace: istio-system - # TODO: default template doesn't have this, which one is right ? - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME - istio: pilot -spec: - strategy: - rollingUpdate: - maxSurge: 100% - maxUnavailable: 25% - selector: - matchLabels: - istio: pilot - template: - metadata: - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME - istio: pilot - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-pilot-service-account - containers: - - name: discovery - image: "docker.io/istio/pilot:1.4.3" - imagePullPolicy: IfNotPresent - args: - - "discovery" - - --monitoringAddr=:15014 - - --log_output_level=default:info - - --domain - - cluster.local - - --secureGrpcAddr - - "" - - --keepaliveMaxServerConnectionAge - - "30m" - ports: - - containerPort: 8080 - - containerPort: 15010 - - containerPort: 15011 - readinessProbe: - httpGet: - path: /ready - port: 8080 - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 5 - env: - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: PILOT_PUSH_THROTTLE - value: "100" - - name: PILOT_TRACE_SAMPLING - value: "100" - - name: PILOT_ENABLE_PROTOCOL_SNIFFING_FOR_OUTBOUND - value: "true" - - name: PILOT_ENABLE_PROTOCOL_SNIFFING_FOR_INBOUND - value: "false" - resources: - requests: - cpu: 1000m - memory: 1024Mi - volumeMounts: - - name: config-volume - mountPath: /etc/istio/config - - name: istio-certs - mountPath: /etc/certs - readOnly: true - volumes: - - name: config-volume - configMap: - name: istio - - name: istio-certs - secret: - secretName: istio.istio-pilot-service-account - optional: true - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - "ppc64le" - - "s390x" - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "ppc64le" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "s390x" ---- -# Source: istio/charts/security/templates/deployment.yaml -# istio CA watching all namespaces -apiVersion: apps/v1 -kind: Deployment -metadata: - name: istio-citadel - namespace: istio-system - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME - istio: citadel -spec: - replicas: 1 - selector: - matchLabels: - istio: citadel - strategy: - rollingUpdate: - maxSurge: 100% - maxUnavailable: 25% - template: - metadata: - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME - istio: citadel - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-citadel-service-account - containers: - - name: citadel - image: "docker.io/istio/citadel:1.4.3" - imagePullPolicy: IfNotPresent - args: - - --append-dns-names=true - - --grpc-port=8060 - - --citadel-storage-namespace=istio-system - - --custom-dns-names=istio-pilot-service-account.istio-system:istio-pilot.istio-system - - --monitoring-port=15014 - - --self-signed-ca=true - - --workload-cert-ttl=2160h - env: - - name: CITADEL_ENABLE_NAMESPACES_BY_DEFAULT - value: "true" - resources: - requests: - cpu: 10m - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - "ppc64le" - - "s390x" - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "ppc64le" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "s390x" ---- -# Source: istio/charts/gateways/templates/autoscale.yaml -apiVersion: autoscaling/v2beta1 -kind: HorizontalPodAutoscaler -metadata: - name: istio-ingressgateway - namespace: istio-system - labels: - chart: gateways - heritage: Helm - release: RELEASE-NAME - app: istio-ingressgateway - istio: ingressgateway -spec: - maxReplicas: 5 - minReplicas: 2 - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: istio-ingressgateway - metrics: - - type: Resource - resource: - name: cpu - targetAverageUtilization: 80 ---- -# Source: istio/charts/pilot/templates/autoscale.yaml -apiVersion: autoscaling/v2beta1 -kind: HorizontalPodAutoscaler -metadata: - name: istio-pilot - namespace: istio-system - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME -spec: - maxReplicas: 5 - minReplicas: 1 - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: istio-pilot - metrics: - - type: Resource - resource: - name: cpu - targetAverageUtilization: 80 ---- -# Source: istio/charts/security/templates/create-custom-resources-job.yaml -apiVersion: batch/v1 -kind: Job -metadata: - name: istio-security-post-install-1.4.3 - namespace: istio-system - annotations: - "helm.sh/hook": post-install,post-upgrade - "helm.sh/hook-delete-policy": hook-succeeded - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME -spec: - template: - metadata: - name: istio-security-post-install - labels: - app: security - chart: security - heritage: Helm - release: RELEASE-NAME - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-security-post-install-account - containers: - - name: kubectl - image: "docker.io/istio/kubectl:1.4.3" - imagePullPolicy: IfNotPresent - command: [ "/bin/bash", "/tmp/security/run.sh", "/tmp/security/custom-resources.yaml" ] - volumeMounts: - - mountPath: "/tmp/security" - name: tmp-configmap-security - volumes: - - name: tmp-configmap-security - configMap: - name: istio-security-custom-resources - restartPolicy: OnFailure - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - "ppc64le" - - "s390x" - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "ppc64le" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "s390x" diff --git a/third_party/istio-1.4.3/istio-knative-extras.yaml b/third_party/istio-1.4.3/istio-knative-extras.yaml deleted file mode 100644 index bc1f99538da..00000000000 --- a/third_party/istio-1.4.3/istio-knative-extras.yaml +++ /dev/null @@ -1,268 +0,0 @@ ---- -# Source: istio/charts/gateways/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: cluster-local-gateway-service-account - namespace: istio-system - labels: - app: cluster-local-gateway - chart: gateways - heritage: Helm - release: RELEASE-NAME ---- -# Source: istio/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-multi - namespace: istio-system ---- -# Source: istio/templates/clusterrole.yaml -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: istio-reader -rules: - - apiGroups: [''] - resources: ['nodes', 'pods', 'services', 'endpoints', "replicationcontrollers"] - verbs: ['get', 'watch', 'list'] - - apiGroups: ["extensions", "apps"] - resources: ["replicasets"] - verbs: ["get", "list", "watch"] ---- -# Source: istio/templates/clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: istio-multi - labels: - chart: istio-1.4.3 -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: istio-reader -subjects: -- kind: ServiceAccount - name: istio-multi - namespace: istio-system ---- -# Source: istio/charts/gateways/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: cluster-local-gateway - namespace: istio-system - annotations: - labels: - chart: gateways - heritage: Helm - release: RELEASE-NAME - app: cluster-local-gateway - istio: cluster-local-gateway -spec: - type: ClusterIP - selector: - release: RELEASE-NAME - app: cluster-local-gateway - istio: cluster-local-gateway - ports: - - - name: status-port - port: 15020 - - - name: http2 - port: 80 - - - name: https - port: 443 ---- -# Source: istio/charts/gateways/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: cluster-local-gateway - namespace: istio-system - labels: - app: cluster-local-gateway - chart: gateways - heritage: Helm - istio: cluster-local-gateway - release: RELEASE-NAME -spec: - replicas: 1 - selector: - matchLabels: - app: cluster-local-gateway - istio: cluster-local-gateway - strategy: - rollingUpdate: - maxSurge: - maxUnavailable: - template: - metadata: - labels: - app: cluster-local-gateway - chart: gateways - heritage: Helm - istio: cluster-local-gateway - release: RELEASE-NAME - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: cluster-local-gateway-service-account - containers: - - name: istio-proxy - image: "docker.io/istio/proxyv2:1.4.3" - imagePullPolicy: IfNotPresent - ports: - - containerPort: 15020 - - containerPort: 80 - - containerPort: 443 - - containerPort: 15090 - protocol: TCP - name: http-envoy-prom - args: - - proxy - - router - - --domain - - $(POD_NAMESPACE).svc.cluster.local - - --log_output_level=default:info - - --drainDuration - - '45s' #drainDuration - - --parentShutdownDuration - - '1m0s' #parentShutdownDuration - - --connectTimeout - - '10s' #connectTimeout - - --serviceCluster - - cluster-local-gateway - - --zipkinAddress - - zipkin:9411 - - --proxyAdminPort - - "15000" - - --statusPort - - "15020" - - --controlPlaneAuthPolicy - - NONE - - --discoveryAddress - - istio-pilot:15010 - readinessProbe: - failureThreshold: 30 - httpGet: - path: /healthz/ready - port: 15020 - scheme: HTTP - initialDelaySeconds: 1 - periodSeconds: 2 - successThreshold: 1 - timeoutSeconds: 1 - resources: - requests: - cpu: 10m - env: - - name: NODE_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: spec.nodeName - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: INSTANCE_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.podIP - - name: HOST_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.hostIP - - name: SERVICE_ACCOUNT - valueFrom: - fieldRef: - fieldPath: spec.serviceAccountName - - name: ISTIO_META_POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: ISTIO_META_CONFIG_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: ISTIO_METAJSON_LABELS - value: | - {"app":"cluster-local-gateway","chart":"gateways","heritage":"Helm","istio":"cluster-local-gateway","release":"RELEASE-NAME"} - - name: ISTIO_META_CLUSTER_ID - value: "Kubernetes" - - name: SDS_ENABLED - value: "false" - - name: ISTIO_META_WORKLOAD_NAME - value: cluster-local-gateway - - name: ISTIO_META_OWNER - value: kubernetes://apis/apps/v1/namespaces/istio-system/deployments/cluster-local-gateway - - volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - - name: cluster-local-gateway-certs - mountPath: "/etc/istio/cluster-local-gateway-certs" - readOnly: true - - name: cluster-local-gateway-ca-certs - mountPath: "/etc/istio/cluster-local-gateway-ca-certs" - readOnly: true - volumes: - - name: istio-certs - secret: - secretName: istio.cluster-local-gateway-service-account - optional: true - - name: cluster-local-gateway-certs - secret: - secretName: "istio-cluster-local-gateway-certs" - optional: true - - name: cluster-local-gateway-ca-certs - secret: - secretName: "istio-cluster-local-gateway-ca-certs" - optional: true - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - "ppc64le" - - "s390x" - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "ppc64le" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "s390x" diff --git a/third_party/istio-1.4.3/values-extras.yaml b/third_party/istio-1.4.3/values-extras.yaml deleted file mode 100644 index d6f2d68edea..00000000000 --- a/third_party/istio-1.4.3/values-extras.yaml +++ /dev/null @@ -1,86 +0,0 @@ -global: - proxy: - # Enable proxy to write access log to /dev/stdout. - accessLogFile: "/dev/stdout" - autoInject: disabled - disablePolicyChecks: true - omitSidecarInjectorConfigMap: true - defaultPodDisruptionBudget: - enabled: false - useMCP: false - -sidecarInjectorWebhook: - enabled: false - enableNamespacesByDefault: false - -gateways: - enabled: true - - istio-ingressgateway: - enabled: false - istio-egressgateway: - enabled: false - istio-ilbgateway: - enabled: false - - cluster-local-gateway: - enabled: true - labels: - app: cluster-local-gateway - istio: cluster-local-gateway - replicaCount: 1 - autoscaleMin: 1 - autoscaleMax: 1 - resources: {} - cpu: - targetAverageUtilization: 80 - loadBalancerIP: "" - loadBalancerSourceRanges: {} - externalIPs: [] - serviceAnnotations: {} - podAnnotations: {} - type: ClusterIP - ports: - - name: status-port - port: 15020 - - name: http2 - port: 80 - - name: https - port: 443 - secretVolumes: - - name: cluster-local-gateway-certs - secretName: istio-cluster-local-gateway-certs - mountPath: /etc/istio/cluster-local-gateway-certs - - name: cluster-local-gateway-ca-certs - secretName: istio-cluster-local-gateway-ca-certs - mountPath: /etc/istio/cluster-local-gateway-ca-certs - -security: - enabled: false - -galley: - enabled: false - -mixer: - policy: - enabled: false - telemetry: - enabled: false - -pilot: - enabled: false - -grafana: - enabled: false - -prometheus: - enabled: false - -tracing: - enabled: false - -kiali: - enabled: false - -certmanager: - enabled: false diff --git a/third_party/istio-1.4.3/values-lean.yaml b/third_party/istio-1.4.3/values-lean.yaml deleted file mode 100644 index 726abf12feb..00000000000 --- a/third_party/istio-1.4.3/values-lean.yaml +++ /dev/null @@ -1,96 +0,0 @@ -global: - proxy: - # Enable proxy to write access log to /dev/stdout. - accessLogFile: "/dev/stdout" - accessLogEncoding: 'JSON' - autoInject: disabled - disablePolicyChecks: true - omitSidecarInjectorConfigMap: true - defaultPodDisruptionBudget: - enabled: false - useMCP: false - -sidecarInjectorWebhook: - enabled: false - enableNamespacesByDefault: false - -gateways: - istio-ingressgateway: - enabled: true - sds: - enabled: true - replicaCount: 2 - autoscaleMin: 2 - autoscaleMax: 5 - resources: - requests: - cpu: 1000m - memory: 1024Mi - ports: - - name: status-port - port: 15020 - - name: http2 - port: 80 - - port: 443 - name: https - cluster-local-gateway: - enabled: true - labels: - app: cluster-local-gateway - istio: cluster-local-gateway - replicaCount: 2 - autoscaleMin: 2 - autoscaleMax: 5 - resources: - requests: - cpu: 1000m - memory: 1024Mi - cpu: - targetAverageUtilization: 80 - loadBalancerIP: "" - loadBalancerSourceRanges: {} - externalIPs: [] - serviceAnnotations: {} - podAnnotations: {} - type: ClusterIP - ports: - - name: status-port - port: 15020 - - name: http2 - port: 80 - - name: https - port: 443 - secretVolumes: - - name: cluster-local-gateway-certs - secretName: istio-cluster-local-gateway-certs - mountPath: /etc/istio/cluster-local-gateway-certs - - name: cluster-local-gateway-ca-certs - secretName: istio-cluster-local-gateway-ca-certs - mountPath: /etc/istio/cluster-local-gateway-ca-certs - -prometheus: - enabled: false - -mixer: - enabled: false - policy: - enabled: false - telemetry: - enabled: false - adapters: - prometheus: - enabled: false - -pilot: - traceSampling: 100 - sidecar: false - resources: - requests: - cpu: 1000m - memory: 1024Mi - -galley: - enabled: true - -security: - enabled: true diff --git a/third_party/istio-1.4.3/values.yaml b/third_party/istio-1.4.3/values.yaml deleted file mode 100644 index 96fe0a36bf8..00000000000 --- a/third_party/istio-1.4.3/values.yaml +++ /dev/null @@ -1,85 +0,0 @@ -global: - proxy: - # Enable proxy to write access log to /dev/stdout. - accessLogFile: "/dev/stdout" - accessLogEncoding: 'JSON' - autoInject: enabled - disablePolicyChecks: true - -sidecarInjectorWebhook: - enabled: true - enableNamespacesByDefault: false - rewriteAppHTTPProbe: true - -gateways: - istio-ingressgateway: - enabled: true - sds: - enabled: true - replicaCount: 2 - autoscaleMin: 2 - autoscaleMax: 4 - resources: - limits: - cpu: 3000m - memory: 2048Mi - requests: - cpu: 3000m - memory: 2048Mi - ports: - - name: status-port - port: 15020 - - name: http2 - port: 80 - - port: 443 - name: https - cluster-local-gateway: - enabled: true - labels: - app: cluster-local-gateway - istio: cluster-local-gateway - replicaCount: 2 - autoscaleMin: 2 - autoscaleMax: 4 - resources: - requests: - cpu: 250m - memory: 256Mi - cpu: - targetAverageUtilization: 80 - loadBalancerIP: "" - loadBalancerSourceRanges: {} - externalIPs: [] - serviceAnnotations: {} - podAnnotations: {} - type: ClusterIP - ports: - - name: status-port - port: 15020 - - name: http2 - port: 80 - - name: https - port: 443 - secretVolumes: - - name: cluster-local-gateway-certs - secretName: istio-cluster-local-gateway-certs - mountPath: /etc/istio/cluster-local-gateway-certs - - name: cluster-local-gateway-ca-certs - secretName: istio-cluster-local-gateway-ca-certs - mountPath: /etc/istio/cluster-local-gateway-ca-certs - -prometheus: - enabled: false - -mixer: - adapters: - prometheus: - enabled: false - -pilot: - traceSampling: 100 - autoscaleMin: 2 - resources: - requests: - cpu: 3000m - memory: 2048Mi From acb8dc6af10bb5701bfeb853386671bfcc2566fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Mon, 13 Jan 2020 14:33:57 +0100 Subject: [PATCH 05/50] Move prober to separate package Prober will be used to it's own package to enable running it from within e2e tests and upgrade tests. --- test/{ => prober}/prober.go | 5 +++-- test/upgrade/probe_test.go | 15 ++++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) rename test/{ => prober}/prober.go (99%) diff --git a/test/prober.go b/test/prober/prober.go similarity index 99% rename from test/prober.go rename to test/prober/prober.go index b15ed6da610..1935666ac76 100644 --- a/test/prober.go +++ b/test/prober/prober.go @@ -13,7 +13,7 @@ * limitations under the License. */ -package test +package prober import ( "knative.dev/eventing/test/common" @@ -82,6 +82,7 @@ func (p *prober) Finish() { func (p *prober) deploy() { p.logf("ERR: deploy(): implement me") + } func (p *prober) undeploy() { @@ -94,4 +95,4 @@ func newProber(logf logging.FormatLogger, client *common.Client, config ProberCo client: client, config: config, } -} +} \ No newline at end of file diff --git a/test/upgrade/probe_test.go b/test/upgrade/probe_test.go index 33a70d90760..5186c24d680 100644 --- a/test/upgrade/probe_test.go +++ b/test/upgrade/probe_test.go @@ -20,7 +20,7 @@ package upgrade import ( "github.com/pkg/errors" "io/ioutil" - "knative.dev/eventing/test" + "knative.dev/eventing/test/prober" "log" "os" "syscall" @@ -29,8 +29,9 @@ import ( ) const ( - pipe = "/tmp/prober-signal" - ready = "/tmp/prober-ready" + pipe = "/tmp/prober-signal" + ready = "/tmp/prober-ready" + readyMessage = "prober ready" ) var ( @@ -59,14 +60,14 @@ func TestProbe(t *testing.T) { // Use log.Printf instead of t.Logf because we want to see failures // inline with other logs instead of buffered until the end. - config := test.ProberConfig{ + config := prober.ProberConfig{ Namespace: namespace, Interval: interval, UseServing: true, } - prober := test.RunEventProber(log.Printf, client, config) - noError(ioutil.WriteFile(ready, []byte("prober ready"), 0666)) - defer test.AssertEventProber(t, prober) + probe := prober.RunEventProber(log.Printf, client, config) + noError(ioutil.WriteFile(ready, []byte(readyMessage), 0666)) + defer prober.AssertEventProber(t, probe) // e2e-upgrade-test.sh will close this pipe to signal the upgrade is // over, at which point we will finish the test and check the prober. From b45ff25a7b899a1861603bf38a57b0998a737366 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Mon, 13 Jan 2020 18:40:29 +0100 Subject: [PATCH 06/50] Working deploy & remove of configuration --- test/common/errors.go | 25 +++++++ test/prober/config.toml | 5 ++ test/prober/configuration.go | 134 +++++++++++++++++++++++++++++++++++ test/prober/forwarder.go | 24 +++++++ test/prober/prober.go | 61 +++++++++++----- test/prober/receiver.go | 24 +++++++ test/prober/sender.go | 24 +++++++ test/upgrade/probe_test.go | 31 ++++---- 8 files changed, 294 insertions(+), 34 deletions(-) create mode 100644 test/common/errors.go create mode 100644 test/prober/config.toml create mode 100644 test/prober/configuration.go create mode 100644 test/prober/forwarder.go create mode 100644 test/prober/receiver.go create mode 100644 test/prober/sender.go diff --git a/test/common/errors.go b/test/common/errors.go new file mode 100644 index 00000000000..9ce5d361fd8 --- /dev/null +++ b/test/common/errors.go @@ -0,0 +1,25 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package common + +import "github.com/pkg/errors" + +// NoError will panic if given an error, as it was unexpected +func NoError(err error) { + if err != nil { + panic(errors.WithMessage(err, "expected to be no error, but that was")) + } +} diff --git a/test/prober/config.toml b/test/prober/config.toml new file mode 100644 index 00000000000..cbab0dbec02 --- /dev/null +++ b/test/prober/config.toml @@ -0,0 +1,5 @@ +# logLevel = 5 +[sender] +address = 'http://default-broker.{{- .Namespace -}}.svc.cluster.local' +[forwarder] +target = 'http://wathola-receiver.{{- .Namespace -}}.svc.cluster.local' diff --git a/test/prober/configuration.go b/test/prober/configuration.go new file mode 100644 index 00000000000..2e5c1d128ec --- /dev/null +++ b/test/prober/configuration.go @@ -0,0 +1,134 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package prober + +import ( + "bytes" + "fmt" + "io/ioutil" + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/eventing/pkg/apis/eventing/v1alpha1" + "knative.dev/eventing/test/common" + duckv1 "knative.dev/pkg/apis/duck/v1" + "path" + "runtime" + "text/template" +) + +const ( + configName = "wathola-config" + configFilename = "config.toml" + watholaEventNs = "com.github.cardil.wathola" +) + +var ( + eventTypes = []string{"step", "finished"} +) + +func (p *prober) deployConfiguration() { + p.deploySecret() + p.deployTriggers() +} + +func (p *prober) deploySecret() { + p.logf("Deploying secret: %v", configName) + + configData := p.compileTemplate(configFilename) + data := make(map[string]string, 0) + data[configFilename] = configData + secret := &corev1.Secret{ + ObjectMeta: v1.ObjectMeta{ + Name: configName, + }, + StringData: data, + Type: "Opaque", + } + _, err := p.client.Kube.Kube.CoreV1().Secrets(p.config.Namespace). + Create(secret) + common.NoError(err) +} + +func (p *prober) deployTriggers() { + for _, eventType := range eventTypes { + name := fmt.Sprintf("wathola-trigger-%v", eventType) + fullType := fmt.Sprintf("%v.%v", watholaEventNs, eventType) + ref := &corev1.ObjectReference{ + Kind: "Service", + Namespace: p.config.Namespace, + Name: "wathola-receiver", + APIVersion: "v1", + } + if p.config.UseServing { + ref.APIVersion = "serving.knative.dev/v1beta1" + ref.Name = "wathola-forwarder" + } + trigger := &v1alpha1.Trigger{ + ObjectMeta: v1.ObjectMeta{ + Name: name, + }, + Spec: v1alpha1.TriggerSpec{ + Broker: "default", + Filter: &v1alpha1.TriggerFilter{ + Attributes: &v1alpha1.TriggerFilterAttributes{ + "type": fullType, + }, + }, + Subscriber: duckv1.Destination{ + Ref: ref, + }, + }, + } + p.logf("Deploying trigger: %v", name) + _, err := p.client.Eventing.EventingV1alpha1().Triggers(p.config.Namespace). + Create(trigger) + common.NoError(err) + } +} + +func (p *prober) removeConfiguration() { + p.removeSecret() + p.removeTriggers() +} + +func (p *prober) removeSecret() { + p.logf("Removing secret: %v", configName) + err := p.client.Kube.Kube.CoreV1().Secrets(p.config.Namespace). + Delete(configName, &v1.DeleteOptions{}) + common.NoError(err) +} + +func (p *prober) removeTriggers() { + for _, eventType := range eventTypes { + name := fmt.Sprintf("wathola-trigger-%v", eventType) + p.logf("Removing trigger: %v", name) + err := p.client.Eventing.EventingV1alpha1().Triggers(p.config.Namespace). + Delete(name, &v1.DeleteOptions{}) + common.NoError(err) + } +} + +func (p *prober) compileTemplate(templateName string) string { + _, filename, _, _ := runtime.Caller(0) + templateFilepath := path.Join(path.Dir(filename), templateName) + templateBytes, err := ioutil.ReadFile(templateFilepath) + common.NoError(err) + tmpl, err := template.New(templateName).Parse(string(templateBytes)) + common.NoError(err) + var buff bytes.Buffer + common.NoError(tmpl.Execute(&buff, p.config)) + return buff.String() +} diff --git a/test/prober/forwarder.go b/test/prober/forwarder.go new file mode 100644 index 00000000000..301eb1a1b72 --- /dev/null +++ b/test/prober/forwarder.go @@ -0,0 +1,24 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package prober + +func (p *prober) deployForwarder() { + p.logf("ERR: deployForwarder(): implement me") +} + +func (p *prober) removeForwarder() { + p.logf("ERR: removeForwarder(): implement me") +} diff --git a/test/prober/prober.go b/test/prober/prober.go index 1935666ac76..25117a7c244 100644 --- a/test/prober/prober.go +++ b/test/prober/prober.go @@ -32,19 +32,29 @@ type Prober interface { // deploy a prober to a cluster deploy() - // undeploy a prober from cluster - undeploy() + // remove a prober from cluster + remove() } -// ProberConfig represents a configuration for prober -type ProberConfig struct { - Namespace string - Interval time.Duration - UseServing bool +// Config represents a configuration for prober +type Config struct { + Namespace string + Interval time.Duration + UseServing bool + FinishedSleep time.Duration +} + +func NewConfig(namespace string) *Config { + return &Config{ + Namespace: namespace, + Interval: 10 * time.Millisecond, + UseServing: true, + FinishedSleep: 5 * time.Second, + } } // RunEventProber starts a single Prober of the given domain. -func RunEventProber(logf logging.FormatLogger, client *common.Client, config ProberConfig) Prober { +func RunEventProber(logf logging.FormatLogger, client *common.Client, config *Config) Prober { pm := newProber(logf, client, config) pm.deploy() return pm @@ -54,6 +64,8 @@ func RunEventProber(logf logging.FormatLogger, client *common.Client, config Pro func AssertEventProber(t *testing.T, prober Prober) { prober.Finish() + waitAfterFinished(prober) + errors := prober.Verify() for _, err := range errors { t.Error(err) @@ -62,13 +74,13 @@ func AssertEventProber(t *testing.T, prober Prober) { t.Log("All events propagated well") } - prober.undeploy() + prober.remove() } type prober struct { logf logging.FormatLogger client *common.Client - config ProberConfig + config *Config } func (p *prober) Verify() []error { @@ -77,22 +89,37 @@ func (p *prober) Verify() []error { } func (p *prober) Finish() { - p.logf("ERR: Finish(): implement me") + p.removeSender() } func (p *prober) deploy() { - p.logf("ERR: deploy(): implement me") - + p.deployConfiguration() + p.deployReceiver() + if p.config.UseServing { + p.deployForwarder() + } + p.deploySender() } -func (p *prober) undeploy() { - p.logf("ERR: undeploy(): implement me") +func (p *prober) remove() { + if p.config.UseServing { + p.removeForwarder() + } + p.removeReceiver() + p.removeConfiguration() } -func newProber(logf logging.FormatLogger, client *common.Client, config ProberConfig) Prober { +func newProber(logf logging.FormatLogger, client *common.Client, config *Config) Prober { return &prober{ logf: logf, client: client, config: config, } -} \ No newline at end of file +} + +func waitAfterFinished(p Prober) { + s := p.(*prober) + cfg := s.config + s.logf("Waiting %v after sender finished...", cfg.FinishedSleep) + time.Sleep(cfg.FinishedSleep) +} diff --git a/test/prober/receiver.go b/test/prober/receiver.go new file mode 100644 index 00000000000..63e5c41b05a --- /dev/null +++ b/test/prober/receiver.go @@ -0,0 +1,24 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package prober + +func (p *prober) deployReceiver() { + p.logf("ERR: deployReceiver(): implement me") +} + +func (p *prober) removeReceiver() { + p.logf("ERR: removeReceiver(): implement me") +} diff --git a/test/prober/sender.go b/test/prober/sender.go new file mode 100644 index 00000000000..100250966ba --- /dev/null +++ b/test/prober/sender.go @@ -0,0 +1,24 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package prober + +func (p *prober) deploySender() { + p.logf("ERR: deploySender(): implement me") +} + +func (p *prober) removeSender() { + p.logf("ERR: removeSender(): implement me") +} \ No newline at end of file diff --git a/test/upgrade/probe_test.go b/test/upgrade/probe_test.go index 5186c24d680..d1fd2f8f205 100644 --- a/test/upgrade/probe_test.go +++ b/test/upgrade/probe_test.go @@ -18,8 +18,8 @@ package upgrade import ( - "github.com/pkg/errors" "io/ioutil" + "knative.dev/eventing/test/common" "knative.dev/eventing/test/prober" "log" "os" @@ -37,8 +37,7 @@ const ( var ( // FIXME: Interval is set to 200 msec, as lower values will result in errors // https://github.com/knative/eventing/issues/2357 - interval = 200 * time.Millisecond - namespace = "event-test" + fixmeInterval = 200 * time.Millisecond ) func TestProbe(t *testing.T) { @@ -51,22 +50,16 @@ func TestProbe(t *testing.T) { if err := syscall.Mkfifo(pipe, 0666); err != nil { t.Fatalf("Failed to create pipe: %v", err) } - defer func() { - noError(os.Remove(pipe)) - noError(os.Remove(ready)) - }() + defer cleanupTempFiles() client := setup(t, false) defer tearDown(client) // Use log.Printf instead of t.Logf because we want to see failures // inline with other logs instead of buffered until the end. - config := prober.ProberConfig{ - Namespace: namespace, - Interval: interval, - UseServing: true, - } + config := prober.NewConfig(client.Namespace) + config.Interval = fixmeInterval probe := prober.RunEventProber(log.Printf, client, config) - noError(ioutil.WriteFile(ready, []byte(readyMessage), 0666)) + common.NoError(ioutil.WriteFile(ready, []byte(readyMessage), 0666)) defer prober.AssertEventProber(t, probe) // e2e-upgrade-test.sh will close this pipe to signal the upgrade is @@ -74,8 +67,12 @@ func TestProbe(t *testing.T) { _, _ = ioutil.ReadFile(pipe) } -func noError(err error) { - if err != nil { - panic(errors.WithMessage(err, "expected to be no error, but that was")) +func cleanupTempFiles() { + filenames := []string{pipe, ready} + for _, filename := range filenames { + _, err := os.Stat(filename) + if err == nil { + common.NoError(os.Remove(filename)) + } } -} +} \ No newline at end of file From 882119e83ca2baf5e9833ab812150adade165dc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Mon, 13 Jan 2020 20:24:38 +0100 Subject: [PATCH 07/50] Probe receiver deploy & remove Implemented receiver deployment and removal with getting service node port, to later be able to connect and fetch results. --- test/prober/prober.go | 4 ++ test/prober/receiver.go | 111 ++++++++++++++++++++++++++++++++++++- test/upgrade/probe_test.go | 7 ++- 3 files changed, 117 insertions(+), 5 deletions(-) diff --git a/test/prober/prober.go b/test/prober/prober.go index 25117a7c244..969c5df5195 100644 --- a/test/prober/prober.go +++ b/test/prober/prober.go @@ -22,6 +22,10 @@ import ( "time" ) +var ( + Version = "v0.6.0" +) + // Prober is the interface for a prober, which checks the result of the probes when stopped. type Prober interface { // Verify will verify prober state after finished has been send diff --git a/test/prober/receiver.go b/test/prober/receiver.go index 63e5c41b05a..e7d6f589045 100644 --- a/test/prober/receiver.go +++ b/test/prober/receiver.go @@ -15,10 +15,117 @@ package prober +import ( + "fmt" + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "knative.dev/eventing/test/common" +) + +var receiverName = "wathola-receiver" +var receiverNodePort int32 = -1 + func (p *prober) deployReceiver() { - p.logf("ERR: deployReceiver(): implement me") + p.deployReceiverPod() + p.deployReceiverService() } func (p *prober) removeReceiver() { - p.logf("ERR: removeReceiver(): implement me") + p.removeReceiverService() + p.removeReceiverPod() +} + +func (p *prober) deployReceiverPod() { + p.logf("Deploy of receiver pod: %v", receiverName) + pod := &corev1.Pod{ + ObjectMeta: v1.ObjectMeta{ + Name: receiverName, + Namespace: p.config.Namespace, + Labels: map[string]string{ + "app": receiverName, + }, + }, + Spec: corev1.PodSpec{ + Volumes: []corev1.Volume{ + { + Name: configName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: configName, + }, + }, + }, + }, + Containers: []corev1.Container{ + { + Name: "receiver", + Image: fmt.Sprintf("quay.io/cardil/wathola-receiver:%v", Version), + VolumeMounts: []corev1.VolumeMount{ + { + Name: configName, + ReadOnly: true, + MountPath: "/.config/wathola", + }, + }, + }, + }, + }, + } + _, err := p.client.Kube.CreatePod(pod) + common.NoError(err) +} + +func (p *prober) deployReceiverService() { + p.logf("Deploy of receiver service: %v", receiverName) + service := &corev1.Service{ + ObjectMeta: v1.ObjectMeta{ + Name: receiverName, + Namespace: p.config.Namespace, + }, + Spec: corev1.ServiceSpec{ + Ports: []corev1.ServicePort{ + { + Name: "http", + Protocol: "TCP", + Port: 80, + TargetPort: intstr.IntOrString{ + Type: intstr.Int, + IntVal: 22111, + }, + }, + }, + Selector: map[string]string{ + "app": receiverName, + }, + Type: corev1.ServiceTypeLoadBalancer, + }, + } + created, err := p.client.Kube.Kube.CoreV1().Services(p.config.Namespace). + Create(service) + common.NoError(err) + for _, portSpec := range created.Spec.Ports { + if portSpec.Port == 80 { + receiverNodePort = portSpec.NodePort + } + } + if receiverNodePort == -1 { + panic(fmt.Errorf("couldn't find a node port for service: %v", receiverName)) + } else { + p.logf("Node port for service: %v is %v", receiverName, receiverNodePort) + } +} + +func (p *prober) removeReceiverPod() { + p.logf("Remove of receiver pod: %v", receiverName) + err := p.client.Kube.Kube.CoreV1().Pods(p.config.Namespace). + Delete(receiverName, &v1.DeleteOptions{}) + common.NoError(err) +} + +func (p *prober) removeReceiverService() { + p.logf("Remove of receiver service: %v", receiverName) + err := p.client.Kube.Kube.CoreV1().Services(p.config.Namespace). + Delete(receiverName, &v1.DeleteOptions{}) + common.NoError(err) } diff --git a/test/upgrade/probe_test.go b/test/upgrade/probe_test.go index d1fd2f8f205..a15017b450d 100644 --- a/test/upgrade/probe_test.go +++ b/test/upgrade/probe_test.go @@ -62,8 +62,9 @@ func TestProbe(t *testing.T) { common.NoError(ioutil.WriteFile(ready, []byte(readyMessage), 0666)) defer prober.AssertEventProber(t, probe) - // e2e-upgrade-test.sh will close this pipe to signal the upgrade is - // over, at which point we will finish the test and check the prober. + log.Printf("Prober is ready. Waiting for file: %v as a signal that "+ + "upgrade/downgrade is over, at which point we will finish the test "+ + "and check the prober.", pipe) _, _ = ioutil.ReadFile(pipe) } @@ -75,4 +76,4 @@ func cleanupTempFiles() { common.NoError(os.Remove(filename)) } } -} \ No newline at end of file +} From 2d925ae7421b9285abaf942be6c6a39684193c30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Tue, 14 Jan 2020 15:46:40 +0100 Subject: [PATCH 08/50] Probe forwarder deploy & removal --- test/prober/configuration.go | 23 +++++----- test/prober/forwarder.go | 88 +++++++++++++++++++++++++++++++++++- test/prober/prober.go | 16 +++++-- test/prober/receiver.go | 8 +++- test/upgrade/probe_test.go | 5 +- 5 files changed, 119 insertions(+), 21 deletions(-) diff --git a/test/prober/configuration.go b/test/prober/configuration.go index 2e5c1d128ec..4c7383d4ecd 100644 --- a/test/prober/configuration.go +++ b/test/prober/configuration.go @@ -20,7 +20,7 @@ import ( "fmt" "io/ioutil" corev1 "k8s.io/api/core/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/eventing/pkg/apis/eventing/v1alpha1" "knative.dev/eventing/test/common" duckv1 "knative.dev/pkg/apis/duck/v1" @@ -45,14 +45,15 @@ func (p *prober) deployConfiguration() { } func (p *prober) deploySecret() { - p.logf("Deploying secret: %v", configName) + name := configName + p.logf("Deploying secret: %v", name) configData := p.compileTemplate(configFilename) data := make(map[string]string, 0) data[configFilename] = configData secret := &corev1.Secret{ - ObjectMeta: v1.ObjectMeta{ - Name: configName, + ObjectMeta: metav1.ObjectMeta{ + Name: name, }, StringData: data, Type: "Opaque", @@ -69,15 +70,15 @@ func (p *prober) deployTriggers() { ref := &corev1.ObjectReference{ Kind: "Service", Namespace: p.config.Namespace, - Name: "wathola-receiver", + Name: receiverName, APIVersion: "v1", } - if p.config.UseServing { - ref.APIVersion = "serving.knative.dev/v1beta1" - ref.Name = "wathola-forwarder" + if p.config.Serving.Use { + ref.APIVersion = servicesCR.GroupVersion().String() + ref.Name = forwarderName } trigger := &v1alpha1.Trigger{ - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: name, }, Spec: v1alpha1.TriggerSpec{ @@ -107,7 +108,7 @@ func (p *prober) removeConfiguration() { func (p *prober) removeSecret() { p.logf("Removing secret: %v", configName) err := p.client.Kube.Kube.CoreV1().Secrets(p.config.Namespace). - Delete(configName, &v1.DeleteOptions{}) + Delete(configName, &metav1.DeleteOptions{}) common.NoError(err) } @@ -116,7 +117,7 @@ func (p *prober) removeTriggers() { name := fmt.Sprintf("wathola-trigger-%v", eventType) p.logf("Removing trigger: %v", name) err := p.client.Eventing.EventingV1alpha1().Triggers(p.config.Namespace). - Delete(name, &v1.DeleteOptions{}) + Delete(name, &metav1.DeleteOptions{}) common.NoError(err) } } diff --git a/test/prober/forwarder.go b/test/prober/forwarder.go index 301eb1a1b72..f140fcc1463 100644 --- a/test/prober/forwarder.go +++ b/test/prober/forwarder.go @@ -15,10 +15,94 @@ package prober +import ( + "fmt" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" + "knative.dev/eventing/test/base" + "knative.dev/eventing/test/base/resources" + "knative.dev/eventing/test/common" +) + +var ( + servicesCR = schema.GroupVersionResource{ + Group: "serving.knative.dev", + Version: "v1alpha1", + Resource: "services", + } + servingType = metav1.TypeMeta{ + Kind: "Service", + APIVersion: servicesCR.GroupVersion().String(), + } + forwarderName = "wathola-forwarder" +) + func (p *prober) deployForwarder() { - p.logf("ERR: deployForwarder(): implement me") + p.logf("Deploy forwarder knative service") + serving := p.client.Dynamic.Resource(servicesCR).Namespace(p.client.Namespace) + service := forwarderKService(forwarderName, p.client.Namespace) + _, err := serving.Create(service, metav1.CreateOptions{}) + common.NoError(err) + + p.logf("Wait until forwarder knative service is ready") + p.waitForKServiceReady(forwarderName, p.client.Namespace) + + if p.config.Serving.ScaleToZero { + p.logf("TODO: wait until wathola-forwarder scales to zero") + } } func (p *prober) removeForwarder() { - p.logf("ERR: removeForwarder(): implement me") + p.logf("Remove forwarder knative service") + serving := p.client.Dynamic.Resource(servicesCR).Namespace(p.client.Namespace) + err := serving.Delete(forwarderName, &metav1.DeleteOptions{}) + common.NoError(err) +} + +func (p *prober) waitForKServiceReady(name, namespace string) { + meta := resources.NewMetaResource(name, namespace, &servingType) + err := base.WaitForResourceReady(p.client.Dynamic, meta) + common.NoError(err) +} + +func forwarderKService(name, namespace string) *unstructured.Unstructured { + obj := map[string]interface{}{ + "apiVersion": servingType.APIVersion, + "kind": servingType.Kind, + "metadata": map[string]interface{}{ + "name": name, + "namespace": namespace, + "labels": map[string]string{ + "serving.knative.dev/visibility": "cluster-local", + }, + }, + "spec": map[string]interface{}{ + "template": map[string]interface{}{ + "spec": map[string]interface{}{ + "containers": []map[string]interface{}{{ + "name": "forwarder", + "image": fmt.Sprintf("quay.io/cardil/wathola-forwarder:%v", Version), + "volumeMounts": []map[string]interface{}{{ + "name": configName, + "mountPath": "/.config/wathola", + "readOnly": true, + }}, + "readinessProbe": map[string]interface{}{ + "httpGet": map[string]interface{}{ + "path": "/healthz", + }, + }, + }}, + "volumes": []map[string]interface{}{{ + "name": configName, + "secret": map[string]interface{}{ + "secretName": configName, + }, + }}, + }, + }, + }, + } + return &unstructured.Unstructured{Object: obj} } diff --git a/test/prober/prober.go b/test/prober/prober.go index 969c5df5195..e1a044615a3 100644 --- a/test/prober/prober.go +++ b/test/prober/prober.go @@ -44,16 +44,24 @@ type Prober interface { type Config struct { Namespace string Interval time.Duration - UseServing bool + Serving ServingConfig FinishedSleep time.Duration } +type ServingConfig struct { + Use bool + ScaleToZero bool +} + func NewConfig(namespace string) *Config { return &Config{ Namespace: namespace, Interval: 10 * time.Millisecond, - UseServing: true, FinishedSleep: 5 * time.Second, + Serving: ServingConfig{ + Use: true, + ScaleToZero: true, + }, } } @@ -99,14 +107,14 @@ func (p *prober) Finish() { func (p *prober) deploy() { p.deployConfiguration() p.deployReceiver() - if p.config.UseServing { + if p.config.Serving.Use { p.deployForwarder() } p.deploySender() } func (p *prober) remove() { - if p.config.UseServing { + if p.config.Serving.Use { p.removeForwarder() } p.removeReceiver() diff --git a/test/prober/receiver.go b/test/prober/receiver.go index e7d6f589045..f89d6b227cd 100644 --- a/test/prober/receiver.go +++ b/test/prober/receiver.go @@ -23,8 +23,10 @@ import ( "knative.dev/eventing/test/common" ) -var receiverName = "wathola-receiver" -var receiverNodePort int32 = -1 +var ( + receiverName = "wathola-receiver" + receiverNodePort int32 = -1 +) func (p *prober) deployReceiver() { p.deployReceiverPod() @@ -74,6 +76,8 @@ func (p *prober) deployReceiverPod() { } _, err := p.client.Kube.CreatePod(pod) common.NoError(err) + + p.logf("TODO: wait until wathola-receiver is ready") } func (p *prober) deployReceiverService() { diff --git a/test/upgrade/probe_test.go b/test/upgrade/probe_test.go index a15017b450d..4097dcf9a92 100644 --- a/test/upgrade/probe_test.go +++ b/test/upgrade/probe_test.go @@ -47,10 +47,11 @@ func TestProbe(t *testing.T) { // can't coordinate with the test by just sending e.g. SIGCONT, so we // create a named pipe and wait for the upgrade script to write to it // to signal that we should stop probing. + ensureTempFilesAreCleaned() if err := syscall.Mkfifo(pipe, 0666); err != nil { t.Fatalf("Failed to create pipe: %v", err) } - defer cleanupTempFiles() + defer ensureTempFilesAreCleaned() client := setup(t, false) defer tearDown(client) @@ -68,7 +69,7 @@ func TestProbe(t *testing.T) { _, _ = ioutil.ReadFile(pipe) } -func cleanupTempFiles() { +func ensureTempFilesAreCleaned() { filenames := []string{pipe, ready} for _, filename := range filenames { _, err := os.Stat(filename) From e91afc71c28c990b09cbc1519799ab4dde9e2661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Tue, 14 Jan 2020 16:23:10 +0100 Subject: [PATCH 09/50] Switch to zap.SugarLogger for better messages visibility --- test/prober/configuration.go | 8 ++++---- test/prober/forwarder.go | 8 ++++---- test/prober/prober.go | 24 +++++++++++++----------- test/prober/receiver.go | 12 ++++++------ test/prober/sender.go | 4 ++-- test/upgrade/probe_test.go | 18 +++++++++++++----- 6 files changed, 42 insertions(+), 32 deletions(-) diff --git a/test/prober/configuration.go b/test/prober/configuration.go index 4c7383d4ecd..41229b50c79 100644 --- a/test/prober/configuration.go +++ b/test/prober/configuration.go @@ -46,7 +46,7 @@ func (p *prober) deployConfiguration() { func (p *prober) deploySecret() { name := configName - p.logf("Deploying secret: %v", name) + p.log.Infof("Deploying secret: %v", name) configData := p.compileTemplate(configFilename) data := make(map[string]string, 0) @@ -93,7 +93,7 @@ func (p *prober) deployTriggers() { }, }, } - p.logf("Deploying trigger: %v", name) + p.log.Infof("Deploying trigger: %v", name) _, err := p.client.Eventing.EventingV1alpha1().Triggers(p.config.Namespace). Create(trigger) common.NoError(err) @@ -106,7 +106,7 @@ func (p *prober) removeConfiguration() { } func (p *prober) removeSecret() { - p.logf("Removing secret: %v", configName) + p.log.Infof("Removing secret: %v", configName) err := p.client.Kube.Kube.CoreV1().Secrets(p.config.Namespace). Delete(configName, &metav1.DeleteOptions{}) common.NoError(err) @@ -115,7 +115,7 @@ func (p *prober) removeSecret() { func (p *prober) removeTriggers() { for _, eventType := range eventTypes { name := fmt.Sprintf("wathola-trigger-%v", eventType) - p.logf("Removing trigger: %v", name) + p.log.Infof("Removing trigger: %v", name) err := p.client.Eventing.EventingV1alpha1().Triggers(p.config.Namespace). Delete(name, &metav1.DeleteOptions{}) common.NoError(err) diff --git a/test/prober/forwarder.go b/test/prober/forwarder.go index f140fcc1463..c9e46f6ee1b 100644 --- a/test/prober/forwarder.go +++ b/test/prober/forwarder.go @@ -39,22 +39,22 @@ var ( ) func (p *prober) deployForwarder() { - p.logf("Deploy forwarder knative service") + p.log.Infof("Deploy forwarder knative service: %v", forwarderName) serving := p.client.Dynamic.Resource(servicesCR).Namespace(p.client.Namespace) service := forwarderKService(forwarderName, p.client.Namespace) _, err := serving.Create(service, metav1.CreateOptions{}) common.NoError(err) - p.logf("Wait until forwarder knative service is ready") + p.log.Infof("Wait until forwarder knative service is ready: %v", forwarderName) p.waitForKServiceReady(forwarderName, p.client.Namespace) if p.config.Serving.ScaleToZero { - p.logf("TODO: wait until wathola-forwarder scales to zero") + p.log.Warnf("TODO: wait until wathola-forwarder scales to zero: %v", forwarderName) } } func (p *prober) removeForwarder() { - p.logf("Remove forwarder knative service") + p.log.Infof("Remove forwarder knative service: %v", forwarderName) serving := p.client.Dynamic.Resource(servicesCR).Namespace(p.client.Namespace) err := serving.Delete(forwarderName, &metav1.DeleteOptions{}) common.NoError(err) diff --git a/test/prober/prober.go b/test/prober/prober.go index e1a044615a3..0db34ba6db4 100644 --- a/test/prober/prober.go +++ b/test/prober/prober.go @@ -16,8 +16,8 @@ package prober import ( + "go.uber.org/zap" "knative.dev/eventing/test/common" - "knative.dev/pkg/test/logging" "testing" "time" ) @@ -66,8 +66,8 @@ func NewConfig(namespace string) *Config { } // RunEventProber starts a single Prober of the given domain. -func RunEventProber(logf logging.FormatLogger, client *common.Client, config *Config) Prober { - pm := newProber(logf, client, config) +func RunEventProber(log *zap.SugaredLogger, client *common.Client, config *Config) Prober { + pm := newProber(log, client, config) pm.deploy() return pm } @@ -79,24 +79,26 @@ func AssertEventProber(t *testing.T, prober Prober) { waitAfterFinished(prober) errors := prober.Verify() - for _, err := range errors { - t.Error(err) - } if len(errors) == 0 { t.Log("All events propagated well") + } else { + t.Logf("There ware %v errors. Listing tem below.", len(errors)) + } + for _, err := range errors { + t.Error(err) } prober.remove() } type prober struct { - logf logging.FormatLogger + log *zap.SugaredLogger client *common.Client config *Config } func (p *prober) Verify() []error { - p.logf("ERR: Verify(): implement me") + p.log.Error("Verify(): implement me") return make([]error, 0) } @@ -121,9 +123,9 @@ func (p *prober) remove() { p.removeConfiguration() } -func newProber(logf logging.FormatLogger, client *common.Client, config *Config) Prober { +func newProber(log *zap.SugaredLogger, client *common.Client, config *Config) Prober { return &prober{ - logf: logf, + log: log, client: client, config: config, } @@ -132,6 +134,6 @@ func newProber(logf logging.FormatLogger, client *common.Client, config *Config) func waitAfterFinished(p Prober) { s := p.(*prober) cfg := s.config - s.logf("Waiting %v after sender finished...", cfg.FinishedSleep) + s.log.Infof("Waiting %v after sender finished...", cfg.FinishedSleep) time.Sleep(cfg.FinishedSleep) } diff --git a/test/prober/receiver.go b/test/prober/receiver.go index f89d6b227cd..edcfdf1eff9 100644 --- a/test/prober/receiver.go +++ b/test/prober/receiver.go @@ -39,7 +39,7 @@ func (p *prober) removeReceiver() { } func (p *prober) deployReceiverPod() { - p.logf("Deploy of receiver pod: %v", receiverName) + p.log.Infof("Deploy of receiver pod: %v", receiverName) pod := &corev1.Pod{ ObjectMeta: v1.ObjectMeta{ Name: receiverName, @@ -77,11 +77,11 @@ func (p *prober) deployReceiverPod() { _, err := p.client.Kube.CreatePod(pod) common.NoError(err) - p.logf("TODO: wait until wathola-receiver is ready") + p.log.Warn("TODO: wait until wathola-receiver is ready") } func (p *prober) deployReceiverService() { - p.logf("Deploy of receiver service: %v", receiverName) + p.log.Infof("Deploy of receiver service: %v", receiverName) service := &corev1.Service{ ObjectMeta: v1.ObjectMeta{ Name: receiverName, @@ -116,19 +116,19 @@ func (p *prober) deployReceiverService() { if receiverNodePort == -1 { panic(fmt.Errorf("couldn't find a node port for service: %v", receiverName)) } else { - p.logf("Node port for service: %v is %v", receiverName, receiverNodePort) + p.log.Debugf("Node port for service: %v is %v", receiverName, receiverNodePort) } } func (p *prober) removeReceiverPod() { - p.logf("Remove of receiver pod: %v", receiverName) + p.log.Infof("Remove of receiver pod: %v", receiverName) err := p.client.Kube.Kube.CoreV1().Pods(p.config.Namespace). Delete(receiverName, &v1.DeleteOptions{}) common.NoError(err) } func (p *prober) removeReceiverService() { - p.logf("Remove of receiver service: %v", receiverName) + p.log.Infof("Remove of receiver service: %v", receiverName) err := p.client.Kube.Kube.CoreV1().Services(p.config.Namespace). Delete(receiverName, &v1.DeleteOptions{}) common.NoError(err) diff --git a/test/prober/sender.go b/test/prober/sender.go index 100250966ba..04fc31d7df6 100644 --- a/test/prober/sender.go +++ b/test/prober/sender.go @@ -16,9 +16,9 @@ package prober func (p *prober) deploySender() { - p.logf("ERR: deploySender(): implement me") + p.log.Error("deploySender(): implement me") } func (p *prober) removeSender() { - p.logf("ERR: removeSender(): implement me") + p.log.Error("removeSender(): implement me") } \ No newline at end of file diff --git a/test/upgrade/probe_test.go b/test/upgrade/probe_test.go index 4097dcf9a92..f2e2e5f655c 100644 --- a/test/upgrade/probe_test.go +++ b/test/upgrade/probe_test.go @@ -18,10 +18,10 @@ package upgrade import ( + "go.uber.org/zap" "io/ioutil" "knative.dev/eventing/test/common" "knative.dev/eventing/test/prober" - "log" "os" "syscall" "testing" @@ -55,20 +55,28 @@ func TestProbe(t *testing.T) { client := setup(t, false) defer tearDown(client) - // Use log.Printf instead of t.Logf because we want to see failures - // inline with other logs instead of buffered until the end. config := prober.NewConfig(client.Namespace) + // TODO: remove this after fix of #2357 config.Interval = fixmeInterval - probe := prober.RunEventProber(log.Printf, client, config) + // Use zap.SugarLogger instead of t.Logf because we want to see failures + // inline with other logs instead of buffered until the end. + log := createLogger() + probe := prober.RunEventProber(log, client, config) common.NoError(ioutil.WriteFile(ready, []byte(readyMessage), 0666)) defer prober.AssertEventProber(t, probe) - log.Printf("Prober is ready. Waiting for file: %v as a signal that "+ + log.Infof("Prober is ready. Waiting for file: %v as a signal that "+ "upgrade/downgrade is over, at which point we will finish the test "+ "and check the prober.", pipe) _, _ = ioutil.ReadFile(pipe) } +func createLogger() *zap.SugaredLogger { + log, err := zap.NewDevelopment() + common.NoError(err) + return log.Sugar() +} + func ensureTempFilesAreCleaned() { filenames := []string{pipe, ready} for _, filename := range filenames { From 2a66e45bbd13f160e4fd93124b25af7f18ea3751 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Tue, 14 Jan 2020 23:37:41 +0100 Subject: [PATCH 10/50] Inteligent waiting for all conditions * ksvc ready * triggers ready * pod ready * ksvc scales to zero --- test/base/resource_checks.go | 11 +-- test/prober/await.go | 155 +++++++++++++++++++++++++++++++++++ test/prober/config.toml | 2 +- test/prober/configuration.go | 16 ++++ test/prober/forwarder.go | 19 ++--- test/prober/prober.go | 3 + test/prober/receiver.go | 12 ++- 7 files changed, 200 insertions(+), 18 deletions(-) create mode 100644 test/prober/await.go diff --git a/test/base/resource_checks.go b/test/base/resource_checks.go index 085befcf6f8..37eb38cdd15 100644 --- a/test/base/resource_checks.go +++ b/test/base/resource_checks.go @@ -35,9 +35,10 @@ import ( ) const ( - // The interval and timeout used for polling in checking resource states. - interval = 1 * time.Second - timeout = 4 * time.Minute + // Interval is used for polling in checking resource states + Interval = 1 * time.Second + // Timeout is used for polling in checking resource states + Timeout = 4 * time.Minute ) // WaitForResourceReady polls the status of the MetaResource from client @@ -50,7 +51,7 @@ func WaitForResourceReady(dynamicClient dynamic.Interface, obj *resources.MetaRe _, span := trace.StartSpan(context.Background(), metricName) defer span.End() - return wait.PollImmediate(interval, timeout, func() (bool, error) { + return wait.PollImmediate(Interval, Timeout, func() (bool, error) { untyped, err := GetGenericObject(dynamicClient, obj, &duckv1beta1.KResource{}) return isResourceReady(untyped, err) }) @@ -62,7 +63,7 @@ func WaitForResourcesReady(dynamicClient dynamic.Interface, objList *resources.M _, span := trace.StartSpan(context.Background(), metricName) defer span.End() - return wait.PollImmediate(interval, timeout, func() (bool, error) { + return wait.PollImmediate(Interval, Timeout, func() (bool, error) { untypeds, err := GetGenericObjectList(dynamicClient, objList, &duckv1beta1.KResource{}) for _, untyped := range untypeds { if isReady, err := isResourceReady(untyped, err); !isReady { diff --git a/test/prober/await.go b/test/prober/await.go new file mode 100644 index 00000000000..551077bc1c1 --- /dev/null +++ b/test/prober/await.go @@ -0,0 +1,155 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package prober + +import ( + "context" + "errors" + "fmt" + "go.opencensus.io/trace" + "go.uber.org/zap" + appsv1 "k8s.io/api/apps/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/util/wait" + "knative.dev/eventing/test/base" + "knative.dev/eventing/test/base/resources" + "knative.dev/eventing/test/common" + "sync" + "time" +) + +func (p *prober) waitForKServiceReady(name, namespace string) error { + meta := resources.NewMetaResource(name, namespace, &servingType) + return base.WaitForResourceReady(p.client.Dynamic, meta) +} + +func (p *prober) waitForKServiceScale(name, namespace string, satisfyScale func(*int32) bool) error { + metricName := fmt.Sprintf("waitForKServiceScale/%s/%s", namespace, name) + _, span := trace.StartSpan(context.Background(), metricName) + defer span.End() + + return wait.PollImmediate(base.Interval, base.Timeout, func() (bool, error) { + serving := p.client.Dynamic.Resource(servicesCR).Namespace(namespace) + unstruct, err := serving.Get(name, metav1.GetOptions{}) + return p.isScaledTo(satisfyScale, unstruct, namespace, err) + }) +} + +func (p *prober) isScaledTo(satisfyScale func(*int32) bool, un *unstructured.Unstructured, namespace string, err error) (bool, error) { + if k8serrors.IsNotFound(err) { + // Return false as we are not done yet. + // We swallow the error to keep on polling. + // It should only happen if we wait for the auto-created resources, like default Broker. + return false, nil + } else if err != nil { + // Return error to stop the polling. + return false, err + } + + content := un.UnstructuredContent() + maybeStatus, ok := content["status"] + if !ok { + return false, nil + } + status := maybeStatus.(map[string]interface{}) + maybeTraffic, ok := status["traffic"] + if !ok { + return false, nil + } + traffic := maybeTraffic.([]interface{}) + if len(traffic) > 1 { + return false, fmt.Errorf("traffic shouldn't be split to more then 1 revision: %v", traffic) + } + if len(traffic) == 0 { + // continue to wait + return false, nil + } + firstTraffic := traffic[0].(map[string]interface{}) + revisionName := firstTraffic["revisionName"].(string) + deploymentName := fmt.Sprintf("%s-deployment", revisionName) + + var dep *appsv1.Deployment + dep, err = p.client.Kube.Kube.AppsV1().Deployments(namespace). + Get(deploymentName, metav1.GetOptions{}) + if k8serrors.IsNotFound(err) { + // Return false as we are not done yet. + return false, nil + } else if err != nil { + // Return error to stop the polling. + return false, err + } + return satisfyScale(dep.Spec.Replicas), nil +} + +func (p *prober) waitForTriggerReady(name, namespace string) error { + meta := resources.NewMetaResource(name, namespace, common.TriggerTypeMeta) + return base.WaitForResourceReady(p.client.Dynamic, meta) +} + +func (p *prober) waitForPodReady(name, namespace string) error { + podType := &metav1.TypeMeta{ + Kind: "Pod", + APIVersion: "v1", + } + meta := resources.NewMetaResource(name, namespace, podType) + return base.WaitForResourceReady(p.client.Dynamic, meta) +} + +type namedAwait struct { + name string + routine awaitRoutine +} + +type awaitRoutine func() error + +var waits []*namedAwait + +func awaitAll(log *zap.SugaredLogger) { + var wg sync.WaitGroup + wg.Add(len(waits)) + thrown := false + for _, w := range waits { + go func(w *namedAwait) { + log.Infof("Wait for %s", w.name) + before := time.Now() + err := w.routine() + took := time.Now().Sub(before) + if err != nil { + thrown = true + log.Errorf("Error while waiting for %s: %v", w.name, err) + } else { + log.Infof("Successful wait for %s, took %v to complete", w.name, took) + } + wg.Done() + }(w) + } + waits = nil + wg.Wait() + + if thrown { + panic(errors.New("there ware errors on waiting")) + } +} + +func waitFor(name string, routine awaitRoutine) { + w := &namedAwait{ + name: name, + routine: routine, + } + waits = append(waits, w) +} diff --git a/test/prober/config.toml b/test/prober/config.toml index cbab0dbec02..84fff16c022 100644 --- a/test/prober/config.toml +++ b/test/prober/config.toml @@ -1,4 +1,4 @@ -# logLevel = 5 +# logLevel = 5 # DEBUG(5) [sender] address = 'http://default-broker.{{- .Namespace -}}.svc.cluster.local' [forwarder] diff --git a/test/prober/configuration.go b/test/prober/configuration.go index 41229b50c79..707109da3b3 100644 --- a/test/prober/configuration.go +++ b/test/prober/configuration.go @@ -40,10 +40,23 @@ var ( ) func (p *prober) deployConfiguration() { + p.annotateNamespace() p.deploySecret() p.deployTriggers() } +func (p *prober) annotateNamespace() { + ns, err := p.client.Kube.Kube.CoreV1().Namespaces(). + Get(p.client.Namespace, metav1.GetOptions{}) + common.NoError(err) + ns.Labels = map[string]string{ + "knative-eventing-injection": "enabled", + } + _, err = p.client.Kube.Kube.CoreV1().Namespaces(). + Update(ns) + common.NoError(err) +} + func (p *prober) deploySecret() { name := configName p.log.Infof("Deploying secret: %v", name) @@ -97,6 +110,9 @@ func (p *prober) deployTriggers() { _, err := p.client.Eventing.EventingV1alpha1().Triggers(p.config.Namespace). Create(trigger) common.NoError(err) + waitFor(fmt.Sprintf("trigger be ready: %v", name), func() error { + return p.waitForTriggerReady(name, p.config.Namespace) + }) } } diff --git a/test/prober/forwarder.go b/test/prober/forwarder.go index c9e46f6ee1b..3c49e698d6c 100644 --- a/test/prober/forwarder.go +++ b/test/prober/forwarder.go @@ -20,8 +20,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" - "knative.dev/eventing/test/base" - "knative.dev/eventing/test/base/resources" "knative.dev/eventing/test/common" ) @@ -45,11 +43,16 @@ func (p *prober) deployForwarder() { _, err := serving.Create(service, metav1.CreateOptions{}) common.NoError(err) - p.log.Infof("Wait until forwarder knative service is ready: %v", forwarderName) - p.waitForKServiceReady(forwarderName, p.client.Namespace) + waitFor(fmt.Sprintf("forwarder ksvc be ready: %v", forwarderName), func() error { + return p.waitForKServiceReady(forwarderName, p.client.Namespace) + }) if p.config.Serving.ScaleToZero { - p.log.Warnf("TODO: wait until wathola-forwarder scales to zero: %v", forwarderName) + waitFor(fmt.Sprintf("forwarder scales to zero: %v", forwarderName), func() error { + return p.waitForKServiceScale(forwarderName, p.client.Namespace, func(scale *int32) bool { + return *scale == 0 + }) + }) } } @@ -60,12 +63,6 @@ func (p *prober) removeForwarder() { common.NoError(err) } -func (p *prober) waitForKServiceReady(name, namespace string) { - meta := resources.NewMetaResource(name, namespace, &servingType) - err := base.WaitForResourceReady(p.client.Dynamic, meta) - common.NoError(err) -} - func forwarderKService(name, namespace string) *unstructured.Unstructured { obj := map[string]interface{}{ "apiVersion": servingType.APIVersion, diff --git a/test/prober/prober.go b/test/prober/prober.go index 0db34ba6db4..a5150216a12 100644 --- a/test/prober/prober.go +++ b/test/prober/prober.go @@ -112,7 +112,10 @@ func (p *prober) deploy() { if p.config.Serving.Use { p.deployForwarder() } + awaitAll(p.log) + p.deploySender() + awaitAll(p.log) } func (p *prober) remove() { diff --git a/test/prober/receiver.go b/test/prober/receiver.go index edcfdf1eff9..24cbc90ca48 100644 --- a/test/prober/receiver.go +++ b/test/prober/receiver.go @@ -70,6 +70,14 @@ func (p *prober) deployReceiverPod() { MountPath: "/.config/wathola", }, }, + ReadinessProbe: &corev1.Probe{ + Handler: corev1.Handler{ + HTTPGet: &corev1.HTTPGetAction{ + Path: "/healthz", + Port: intstr.FromInt(22111), + }, + }, + }, }, }, }, @@ -77,7 +85,9 @@ func (p *prober) deployReceiverPod() { _, err := p.client.Kube.CreatePod(pod) common.NoError(err) - p.log.Warn("TODO: wait until wathola-receiver is ready") + waitFor(fmt.Sprintf("receiver be ready: %v", receiverName), func() error { + return p.waitForPodReady(receiverName, p.client.Namespace) + }) } func (p *prober) deployReceiverService() { From 614cd403559a6f60c71f0fe73dc929a3d3f5bdd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Wed, 15 Jan 2020 12:22:49 +0100 Subject: [PATCH 11/50] Fix interval configuration for Sender --- test/prober/config.toml | 1 + test/prober/prober.go | 8 ++++++-- test/upgrade/probe_test.go | 9 --------- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/test/prober/config.toml b/test/prober/config.toml index 84fff16c022..122ec034ff7 100644 --- a/test/prober/config.toml +++ b/test/prober/config.toml @@ -1,5 +1,6 @@ # logLevel = 5 # DEBUG(5) [sender] address = 'http://default-broker.{{- .Namespace -}}.svc.cluster.local' +interval = {{ .Interval.Nanoseconds }} [forwarder] target = 'http://wathola-receiver.{{- .Namespace -}}.svc.cluster.local' diff --git a/test/prober/prober.go b/test/prober/prober.go index a5150216a12..89c30fa0491 100644 --- a/test/prober/prober.go +++ b/test/prober/prober.go @@ -23,7 +23,11 @@ import ( ) var ( - Version = "v0.6.0" + Version = "v0.6.0" + // FIXME: Interval is set to 200 msec, as lower values will result in errors + // https://github.com/knative/eventing/issues/2357 + // Interval = 10 * time.Millisecond + Interval = 200 * time.Millisecond ) // Prober is the interface for a prober, which checks the result of the probes when stopped. @@ -56,7 +60,7 @@ type ServingConfig struct { func NewConfig(namespace string) *Config { return &Config{ Namespace: namespace, - Interval: 10 * time.Millisecond, + Interval: Interval, FinishedSleep: 5 * time.Second, Serving: ServingConfig{ Use: true, diff --git a/test/upgrade/probe_test.go b/test/upgrade/probe_test.go index f2e2e5f655c..893c6b260de 100644 --- a/test/upgrade/probe_test.go +++ b/test/upgrade/probe_test.go @@ -25,7 +25,6 @@ import ( "os" "syscall" "testing" - "time" ) const ( @@ -34,12 +33,6 @@ const ( readyMessage = "prober ready" ) -var ( - // FIXME: Interval is set to 200 msec, as lower values will result in errors - // https://github.com/knative/eventing/issues/2357 - fixmeInterval = 200 * time.Millisecond -) - func TestProbe(t *testing.T) { // We run the prober as a golang test because it fits in nicely with // the rest of our integration tests, and AssertProberDefault needs @@ -56,8 +49,6 @@ func TestProbe(t *testing.T) { defer tearDown(client) config := prober.NewConfig(client.Namespace) - // TODO: remove this after fix of #2357 - config.Interval = fixmeInterval // Use zap.SugarLogger instead of t.Logf because we want to see failures // inline with other logs instead of buffered until the end. log := createLogger() From dfbf3b67ca05875d1dd904f4df62ed29e5835834 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Wed, 15 Jan 2020 12:55:34 +0100 Subject: [PATCH 12/50] Deploy & removal of sender pod --- test/prober/configuration.go | 8 ++++-- test/prober/forwarder.go | 4 +-- test/prober/prober.go | 1 + test/prober/receiver.go | 4 +-- test/prober/sender.go | 55 ++++++++++++++++++++++++++++++++++-- 5 files changed, 63 insertions(+), 9 deletions(-) diff --git a/test/prober/configuration.go b/test/prober/configuration.go index 707109da3b3..354d002d76a 100644 --- a/test/prober/configuration.go +++ b/test/prober/configuration.go @@ -30,9 +30,11 @@ import ( ) const ( - configName = "wathola-config" - configFilename = "config.toml" - watholaEventNs = "com.github.cardil.wathola" + configName = "wathola-config" + configMountPoint = "/.config/wathola" + configFilename = "config.toml" + watholaEventNs = "com.github.cardil.wathola" + healthEndpoint = "/healthz" ) var ( diff --git a/test/prober/forwarder.go b/test/prober/forwarder.go index 3c49e698d6c..a3907d7ef0c 100644 --- a/test/prober/forwarder.go +++ b/test/prober/forwarder.go @@ -82,12 +82,12 @@ func forwarderKService(name, namespace string) *unstructured.Unstructured { "image": fmt.Sprintf("quay.io/cardil/wathola-forwarder:%v", Version), "volumeMounts": []map[string]interface{}{{ "name": configName, - "mountPath": "/.config/wathola", + "mountPath": configMountPoint, "readOnly": true, }}, "readinessProbe": map[string]interface{}{ "httpGet": map[string]interface{}{ - "path": "/healthz", + "path": healthEndpoint, }, }, }}, diff --git a/test/prober/prober.go b/test/prober/prober.go index 89c30fa0491..785fbec3890 100644 --- a/test/prober/prober.go +++ b/test/prober/prober.go @@ -111,6 +111,7 @@ func (p *prober) Finish() { } func (p *prober) deploy() { + p.log.Infof("Using namespace for probe testing: %v", p.client.Namespace) p.deployConfiguration() p.deployReceiver() if p.config.Serving.Use { diff --git a/test/prober/receiver.go b/test/prober/receiver.go index 24cbc90ca48..830bf6b5da1 100644 --- a/test/prober/receiver.go +++ b/test/prober/receiver.go @@ -67,13 +67,13 @@ func (p *prober) deployReceiverPod() { { Name: configName, ReadOnly: true, - MountPath: "/.config/wathola", + MountPath: configMountPoint, }, }, ReadinessProbe: &corev1.Probe{ Handler: corev1.Handler{ HTTPGet: &corev1.HTTPGetAction{ - Path: "/healthz", + Path: healthEndpoint, Port: intstr.FromInt(22111), }, }, diff --git a/test/prober/sender.go b/test/prober/sender.go index 04fc31d7df6..c07d7e316f8 100644 --- a/test/prober/sender.go +++ b/test/prober/sender.go @@ -15,10 +15,61 @@ package prober +import ( + "fmt" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/eventing/test/common" +) + +var senderName = "wathola-sender" + func (p *prober) deploySender() { - p.log.Error("deploySender(): implement me") + p.log.Infof("Deploy sender pod: %v", senderName) + pod := &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: senderName, + Namespace: p.config.Namespace, + }, + Spec: corev1.PodSpec{ + Volumes: []corev1.Volume{ + { + Name: configName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: configName, + }, + }, + }, + }, + Containers: []corev1.Container{ + { + Name: "sender", + Image: fmt.Sprintf("quay.io/cardil/wathola-sender:%v", Version), + VolumeMounts: []corev1.VolumeMount{ + { + Name: configName, + ReadOnly: true, + MountPath: configMountPoint, + }, + }, + }, + }, + }, + } + _, err := p.client.Kube.Kube.CoreV1().Pods(p.client.Namespace). + Create(pod) + common.NoError(err) + + waitFor(fmt.Sprintf("sender pod become ready: %v", senderName), func() error { + return p.waitForPodReady(senderName, p.client.Namespace) + }) } func (p *prober) removeSender() { - p.log.Error("removeSender(): implement me") + p.log.Infof("Remove of sender pod: %v", senderName) + + err := p.client.Kube.Kube.CoreV1().Pods(p.client.Namespace). + Delete(senderName, &metav1.DeleteOptions{}) + common.NoError(err) } \ No newline at end of file From b046fd403ada70a22974c468787d7cde8c39ed3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Wed, 15 Jan 2020 13:20:34 +0100 Subject: [PATCH 13/50] Update ready message a bit --- test/prober/prober.go | 2 ++ test/prober/sender.go | 2 +- test/upgrade/probe_test.go | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/test/prober/prober.go b/test/prober/prober.go index 785fbec3890..1154a39d219 100644 --- a/test/prober/prober.go +++ b/test/prober/prober.go @@ -121,6 +121,8 @@ func (p *prober) deploy() { p.deploySender() awaitAll(p.log) + p.log.Infof("Prober is now sending events with interval of %v in " + + "namespace: %v", p.config.Interval, p.client.Namespace) } func (p *prober) remove() { diff --git a/test/prober/sender.go b/test/prober/sender.go index c07d7e316f8..263eefaaa82 100644 --- a/test/prober/sender.go +++ b/test/prober/sender.go @@ -61,7 +61,7 @@ func (p *prober) deploySender() { Create(pod) common.NoError(err) - waitFor(fmt.Sprintf("sender pod become ready: %v", senderName), func() error { + waitFor(fmt.Sprintf("sender pod be ready: %v", senderName), func() error { return p.waitForPodReady(senderName, p.client.Namespace) }) } diff --git a/test/upgrade/probe_test.go b/test/upgrade/probe_test.go index 893c6b260de..1d688abe880 100644 --- a/test/upgrade/probe_test.go +++ b/test/upgrade/probe_test.go @@ -56,7 +56,7 @@ func TestProbe(t *testing.T) { common.NoError(ioutil.WriteFile(ready, []byte(readyMessage), 0666)) defer prober.AssertEventProber(t, probe) - log.Infof("Prober is ready. Waiting for file: %v as a signal that "+ + log.Infof("Waiting for file: %v as a signal that "+ "upgrade/downgrade is over, at which point we will finish the test "+ "and check the prober.", pipe) _, _ = ioutil.ReadFile(pipe) From d9f02c3059f39ea08470290a1cd79c34109950cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Wed, 15 Jan 2020 14:48:58 +0100 Subject: [PATCH 14/50] Fetch receiver report via HTTP Get --- test/prober/prober.go | 21 ++++------- test/prober/verify.go | 81 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 14 deletions(-) create mode 100644 test/prober/verify.go diff --git a/test/prober/prober.go b/test/prober/prober.go index 1154a39d219..1bcbfa0c623 100644 --- a/test/prober/prober.go +++ b/test/prober/prober.go @@ -23,7 +23,7 @@ import ( ) var ( - Version = "v0.6.0" + Version = "v0.7.0" // FIXME: Interval is set to 200 msec, as lower values will result in errors // https://github.com/knative/eventing/issues/2357 // Interval = 10 * time.Millisecond @@ -33,7 +33,7 @@ var ( // Prober is the interface for a prober, which checks the result of the probes when stopped. type Prober interface { // Verify will verify prober state after finished has been send - Verify() []error + Verify() ([]error, int) // Finish send finished event Finish() @@ -82,9 +82,9 @@ func AssertEventProber(t *testing.T, prober Prober) { waitAfterFinished(prober) - errors := prober.Verify() + errors, events := prober.Verify() if len(errors) == 0 { - t.Log("All events propagated well") + t.Logf("All %d events propagated well", events) } else { t.Logf("There ware %v errors. Listing tem below.", len(errors)) } @@ -101,15 +101,6 @@ type prober struct { config *Config } -func (p *prober) Verify() []error { - p.log.Error("Verify(): implement me") - return make([]error, 0) -} - -func (p *prober) Finish() { - p.removeSender() -} - func (p *prober) deploy() { p.log.Infof("Using namespace for probe testing: %v", p.client.Namespace) p.deployConfiguration() @@ -121,7 +112,9 @@ func (p *prober) deploy() { p.deploySender() awaitAll(p.log) - p.log.Infof("Prober is now sending events with interval of %v in " + + // allow sender to send at least some events, 2 sec wait + time.Sleep(2 * time.Second) + p.log.Infof("Prober is now sending events with interval of %v in "+ "namespace: %v", p.config.Interval, p.client.Namespace) } diff --git a/test/prober/verify.go b/test/prober/verify.go new file mode 100644 index 00000000000..ac273434c5b --- /dev/null +++ b/test/prober/verify.go @@ -0,0 +1,81 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package prober + +import ( + "bytes" + "encoding/json" + "errors" + "fmt" + "knative.dev/eventing/test/common" + "net/http" + "net/url" + "strings" +) + +func (p *prober) figureOutClusterHostname() string { + u, err := url.Parse(p.client.Config.Host) + common.NoError(err) + return u.Hostname() +} + +func (p *prober) Verify() ([]error, int) { + hostname := p.figureOutClusterHostname() + report := p.fetchReceiverReport(hostname) + p.log.Infof("Fetched receiver report. Events propagated: %v. "+ + "State: %v", report.Events, report.State) + if report.State == "active" { + panic(errors.New("report fetched to early, receiver is in active state")) + } + errs := make([]error, 0) + for _, t := range report.Thrown { + errs = append(errs, errors.New(t)) + } + return errs, report.Events +} + +func (p *prober) Finish() { + p.removeSender() +} + +func (p *prober) fetchReceiverReport(hostname string) *Report { + u := fmt.Sprintf("http://%s:%d/report", hostname, receiverNodePort) + p.log.Infof("Fetching receiver report at: %v", u) + resp, err := http.Get(u) + common.NoError(err) + if resp.StatusCode != 200 { + var b strings.Builder + common.NoError(resp.Header.Write(&b)) + headers := b.String() + panic(fmt.Errorf("could not get receiver report at %v, "+ + "status code: %v, headers: %v", u, resp.StatusCode, headers)) + } + buf := new(bytes.Buffer) + _, err = buf.ReadFrom(resp.Body) + common.NoError(err) + common.NoError(resp.Body.Close()) + jsonBytes := buf.Bytes() + var report Report + common.NoError(json.Unmarshal(jsonBytes, &report)) + return &report +} + +// Report represents a receiver JSON report +type Report struct { + State string `json:"state"` + Events int `json:"events"` + Thrown []string `json:"thrown"` +} From a16e98385aa422e8d6351fc01f530763dbb10a32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Wed, 15 Jan 2020 17:07:28 +0100 Subject: [PATCH 15/50] Don't deploy IMC from HEAD before each test --- test/e2e-upgrade-tests.sh | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/test/e2e-upgrade-tests.sh b/test/e2e-upgrade-tests.sh index ec4fc0e6b96..47f4815bc63 100755 --- a/test/e2e-upgrade-tests.sh +++ b/test/e2e-upgrade-tests.sh @@ -14,20 +14,32 @@ # See the License for the specific language governing permissions and # limitations under the License. +# Script entry point. + # shellcheck disable=SC1090 source "$(dirname "$0")/e2e-common.sh" -# Script entry point. +# Overrides -function knative_setup() { +function knative_setup { install_knative_serving install_latest_release } +function install_test_resources { + # Nothing to install before tests + true +} + +function uninstall_test_resources { + # Nothing to uninstall after tests + true +} + # shellcheck disable=SC2068 initialize $@ --skip-istio-addon -TIMEOUT=${TIMEOUT:-10m} +TIMEOUT=${TIMEOUT:-30m} header "Running preupgrade tests" @@ -35,9 +47,6 @@ go_test_e2e -tags=preupgrade -timeout="${TIMEOUT}" ./test/upgrade || fail_test header "Starting prober test" -# Remove this in case we failed to clean it up in an earlier test. -rm -vf /tmp/prober-signal /tmp/prober-ready - go_test_e2e -tags=probe -timeout="${TIMEOUT}" ./test/upgrade & PROBER_PID=$! echo "Prober PID is ${PROBER_PID}" @@ -45,7 +54,8 @@ echo "Prober PID is ${PROBER_PID}" wait_for_file /tmp/prober-ready || fail_test header "Performing upgrade to HEAD" -install_head +install_head || return $? +install_channel_crds || return $? header "Running postupgrade tests" go_test_e2e -tags=postupgrade -timeout="${TIMEOUT}" ./test/upgrade || fail_test @@ -57,9 +67,6 @@ header "Running postdowngrade tests" go_test_e2e -tags=postdowngrade -timeout="${TIMEOUT}" ./test/upgrade || fail_test # The prober is blocking on /tmp/prober-signal to know when it should exit. -# -# This is kind of gross. First attempt was to just send a signal to the go test, -# but "go test" intercepts the signal and always exits with a non-zero code. echo "done" > /tmp/prober-signal header "Waiting for prober test" From 99909a93f992fc8ddfb0c85c42d3ed768d5a3853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Wed, 15 Jan 2020 18:36:15 +0100 Subject: [PATCH 16/50] Describe an upgrade tests --- test/e2e-upgrade-tests.sh | 2 ++ test/upgrade/README.md | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/test/e2e-upgrade-tests.sh b/test/e2e-upgrade-tests.sh index 47f4815bc63..c1c44cc6523 100755 --- a/test/e2e-upgrade-tests.sh +++ b/test/e2e-upgrade-tests.sh @@ -14,6 +14,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +# Docs -> file://./upgrade/README.md + # Script entry point. # shellcheck disable=SC1090 diff --git a/test/upgrade/README.md b/test/upgrade/README.md index a902edbd056..8bb95d037f5 100644 --- a/test/upgrade/README.md +++ b/test/upgrade/README.md @@ -51,3 +51,33 @@ control-plane outages (when we're upgrading the knative/eventing installation), we run a prober test that continually sends events to a service during the entire upgrade/downgrade process. When the upgrade completes, we make sure that all of those events propagated just once. + +To achieve that a tool was prepared (https://github.com/cardil/wathola). It +consists of 3 components: _sender_, _forwarder_, and _receiver_. _Sender_ is +the usual Kubernetes pod that publishes events to the default `broker` with +given interval. When it closes (by either `SIGTERM`, or `SIGINT`), an +`finished` event is generated. _Forwarder_ is a knative serving service that +scales from zero to receive the requested traffic. _Forwarders_ receive events +and forwards them to given target. _Receiver_ is an ordinary pod that collects +events from multiple forwarders and has an endpoint `/report` that can be +polled to get the status of sent events. + +Diagram below describe the setup: + +``` + (pod) (ksvc) (pod) ++--------+ +-----------+ +----------+ +| | | ++ | | +| Sender | +-->| Forwarder ||----->+ Receiver | +| | | | || | | ++---+----+ | +------------| +----------+ + | | +-----------+ + | | + | | + | +--+-----+ +---------+ + +-----> | | +-+ + | Broker | < - - | Trigger | | + | | | | | + +--------+ +---------+ | + (default) +----------+ +``` From dcaaca45d96316519a49b13a1138cf2abc451328 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Thu, 16 Jan 2020 16:44:25 +0100 Subject: [PATCH 17/50] Ensure knative-networking is installed just once --- .editorconfig | 6 +++--- test/e2e-common.sh | 26 ++++++++++++++++---------- test/e2e-upgrade-tests.sh | 2 +- test/prober/prober.go | 2 +- 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/.editorconfig b/.editorconfig index 9643251a2fb..2f94ce46a1d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -8,8 +8,8 @@ root = true end_of_line = lf insert_final_newline = true charset = utf-8 -indent_style = tab +indent_style = space indent_size = 2 -[{**.yaml,**.yml}] -indent_style = space +[**.go] +indent_style = tab diff --git a/test/e2e-common.sh b/test/e2e-common.sh index 0dbfc72315d..2f40fcd8e78 100755 --- a/test/e2e-common.sh +++ b/test/e2e-common.sh @@ -44,6 +44,7 @@ UNINSTALL_LIST=() # Parameters: $1 - Knative Eventing YAML file # $2 - Knative Monitoring YAML file (optional) function install_knative_eventing { + local knative_networking_pods local INSTALL_RELEASE_YAML=$1 echo ">> Installing Knative Eventing" if [[ -z "$1" ]]; then @@ -53,9 +54,16 @@ function install_knative_eventing { fi wait_until_pods_running knative-eventing || fail_test "Knative Eventing did not come up" - echo ">> Installing Knative Monitoring" - start_knative_monitoring "${KNATIVE_MONITORING_RELEASE}" || fail_test "Knative Monitoring did not come up" - UNINSTALL_LIST+=( "${KNATIVE_MONITORING_RELEASE}" ) + # Ensure knative monitoring is installed only once + knative_networking_pods=$(kubectl get pods -n knative-monitoring \ + --field-selector status.phase=Running 2> /dev/null | tail -n +2 | wc -l) + if ! [[ ${knative_networking_pods} -gt 0 ]]; then + echo ">> Installing Knative Monitoring" + start_knative_monitoring "${KNATIVE_MONITORING_RELEASE}" || fail_test "Knative Monitoring did not come up" + UNINSTALL_LIST+=( "${KNATIVE_MONITORING_RELEASE}" ) + else + echo ">> Knative Monitoring seems to be running, pods running: ${knative_networking_pods}." + fi } function install_head { @@ -101,7 +109,7 @@ function test_setup() { # Publish test images. echo ">> Publishing test images" - $(dirname $0)/upload-test-images.sh e2e || fail_test "Error uploading test images" + "$(dirname $0)/upload-test-images.sh" e2e || fail_test "Error uploading test images" } # Tear down resources used in the eventing tests. @@ -182,26 +190,24 @@ function install_knative_serving { } function wait_for_file { - local file timeout + local file timeout waits file="$1" - timeout=300 + waits=300 + timeout=$waits echo "Waiting for existance of file: ${file}" while [ ! -f "${file}" ]; do # When the timeout is equal to zero, show an error and leave the loop. if [ "${timeout}" == 0 ]; then - echo '' - echo "ERROR: Timeout while waiting for the file ${file}." + echo "ERROR: Timeout (${waits}s) while waiting for the file ${file}." return 1 fi sleep 1 - echo -n '.' # Decrease the timeout of one ((timeout--)) done - echo '' return 0 } diff --git a/test/e2e-upgrade-tests.sh b/test/e2e-upgrade-tests.sh index c1c44cc6523..a0698ab279c 100755 --- a/test/e2e-upgrade-tests.sh +++ b/test/e2e-upgrade-tests.sh @@ -48,7 +48,7 @@ header "Running preupgrade tests" go_test_e2e -tags=preupgrade -timeout="${TIMEOUT}" ./test/upgrade || fail_test header "Starting prober test" - +rm -fv /tmp/prober-ready go_test_e2e -tags=probe -timeout="${TIMEOUT}" ./test/upgrade & PROBER_PID=$! echo "Prober PID is ${PROBER_PID}" diff --git a/test/prober/prober.go b/test/prober/prober.go index 6f0b95db125..ec9869c7fd3 100644 --- a/test/prober/prober.go +++ b/test/prober/prober.go @@ -86,7 +86,7 @@ func AssertEventProber(t *testing.T, prober Prober) { if len(errors) == 0 { t.Logf("All %d events propagated well", events) } else { - t.Logf("There ware %v errors. Listing tem below.", len(errors)) + t.Logf("There ware %v errors. Listing them below.", len(errors)) } for _, err := range errors { t.Error(err) From d01a5665a78afebaa8eca79c935b187beacc53d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Thu, 16 Jan 2020 16:57:55 +0100 Subject: [PATCH 18/50] Change error message to be more simplistic Plus other minor review fixes --- test/e2e-upgrade-tests.sh | 2 +- test/lib/errors.go | 2 +- test/upgrade/README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/e2e-upgrade-tests.sh b/test/e2e-upgrade-tests.sh index a0698ab279c..6d96ff20ee5 100755 --- a/test/e2e-upgrade-tests.sh +++ b/test/e2e-upgrade-tests.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# Copyright 2019 The Knative Authors +# Copyright 2020 The Knative Authors # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. diff --git a/test/lib/errors.go b/test/lib/errors.go index a3c04071221..cdf14b96bec 100644 --- a/test/lib/errors.go +++ b/test/lib/errors.go @@ -20,6 +20,6 @@ import "github.com/pkg/errors" // NoError will panic if given an error, as it was unexpected func NoError(err error) { if err != nil { - panic(errors.WithMessage(err, "expected to be no error, but that was")) + panic(errors.WithMessage(err, "unexpected error")) } } diff --git a/test/upgrade/README.md b/test/upgrade/README.md index 4b4654d80a0..099d1dbe82a 100644 --- a/test/upgrade/README.md +++ b/test/upgrade/README.md @@ -6,7 +6,7 @@ Running these tests on every commit will ensure that we don’t introduce any non-upgradeable changes, so every commit should be releasable. This is inspired by kubernetes -[upgrade testing](https://github.com/kubernetes/community/blob/master/contributors/devel/e2e-tests.md#version-skewed-and-upgrade-testing). +[upgrade testing](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-testing/e2e-tests.md#version-skewed-and-upgrade-testing). These tests are a pretty big hammer in that they cover more than just version changes, but it’s one of the only ways to make sure we don’t accidentally make From 3746ec01ec63fe65d420a5fe4105fddfb17d9e7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Thu, 16 Jan 2020 19:55:40 +0100 Subject: [PATCH 19/50] A proper way of figure out a cluster hostname --- test/prober/receiver.go | 2 +- test/prober/verify.go | 81 +++++++++++++++++++++++++++++++++++++---- 2 files changed, 75 insertions(+), 8 deletions(-) diff --git a/test/prober/receiver.go b/test/prober/receiver.go index 96f16ab499d..8cb3b2e2d58 100644 --- a/test/prober/receiver.go +++ b/test/prober/receiver.go @@ -112,7 +112,7 @@ func (p *prober) deployReceiverService() { Selector: map[string]string{ "app": receiverName, }, - Type: corev1.ServiceTypeLoadBalancer, + Type: corev1.ServiceTypeNodePort, }, } created, err := p.client.Kube.Kube.CoreV1().Services(p.config.Namespace). diff --git a/test/prober/verify.go b/test/prober/verify.go index 718349dace8..76a49d1df7c 100644 --- a/test/prober/verify.go +++ b/test/prober/verify.go @@ -20,18 +20,15 @@ import ( "encoding/json" "errors" "fmt" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/eventing/test/lib" + "math/rand" "net/http" - "net/url" + "sort" "strings" ) -func (p *prober) figureOutClusterHostname() string { - u, err := url.Parse(p.client.Config.Host) - lib.NoError(err) - return u.Hostname() -} - func (p *prober) Verify() ([]error, int) { hostname := p.figureOutClusterHostname() report := p.fetchReceiverReport(hostname) @@ -51,6 +48,76 @@ func (p *prober) Finish() { p.removeSender() } +type nodeAddresses []*corev1.NodeAddress + +type byAddressType struct { + nodeAddresses +} + +func (s byAddressType) Len() int { + return len(s.nodeAddresses) +} + +func (s byAddressType) Swap(i, j int) { + s.nodeAddresses[i], s.nodeAddresses[j] = s.nodeAddresses[j], s.nodeAddresses[i] +} + +func (s byAddressType) Less(i, j int) bool { + return addressTypeToPriority(s.nodeAddresses[i]) < addressTypeToPriority(s.nodeAddresses[j]) +} + +var addressTypeToPriorities = map[corev1.NodeAddressType]int{ + corev1.NodeExternalDNS: 0, + corev1.NodeExternalIP: 1, + corev1.NodeInternalIP: 2, + corev1.NodeInternalDNS: 3, + corev1.NodeHostName: 4, +} + +func (p *prober) figureOutClusterHostname() string { + nodes, err := p.client.Kube.Kube.CoreV1().Nodes().List(metav1.ListOptions{}) + lib.NoError(err) + if len(nodes.Items) == 1 { + node := nodes.Items[0] + return p.nodeExternalAddress(node) + } else { + workers := p.filterOutMasters(nodes.Items) + worker := workers[rand.Intn(len(workers))] + return p.nodeExternalAddress(worker) + } +} + +func (p *prober) nodeExternalAddress(node corev1.Node) string { + return p.prioritizeAddresses(node.Status.Addresses)[0].Address +} + +func (p *prober) prioritizeAddresses(addresses []corev1.NodeAddress) []*corev1.NodeAddress { + result := make([]*corev1.NodeAddress, 0) + for i := 0; i < len(addresses); i++ { + result = append(result, &addresses[i]) + } + sort.Sort(byAddressType{result}) + return result +} + +func addressTypeToPriority(address *corev1.NodeAddress) int { + return addressTypeToPriorities[address.Type] +} + +func (p *prober) filterOutMasters(nodes []corev1.Node) []corev1.Node { + result := make([]corev1.Node, 0) + for _, node := range nodes { + if node.Labels == nil { + result = append(result, node) + continue + } + if _, ok := node.Labels["node-role.kubernetes.io/master"]; !ok { + result = append(result, node) + } + } + return result +} + func (p *prober) fetchReceiverReport(hostname string) *Report { u := fmt.Sprintf("http://%s:%d/report", hostname, receiverNodePort) p.log.Infof("Fetching receiver report at: %v", u) From 9d0605b900201294347b86e9a82194679df0b08f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Thu, 6 Feb 2020 12:14:55 +0100 Subject: [PATCH 20/50] Better way of getting replicas while scale to zero --- test/prober/await.go | 6 +++--- test/prober/forwarder.go | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/prober/await.go b/test/prober/await.go index 4ed10f5fd49..69f382e651b 100644 --- a/test/prober/await.go +++ b/test/prober/await.go @@ -38,7 +38,7 @@ func (p *prober) waitForKServiceReady(name, namespace string) error { return duck.WaitForResourceReady(p.client.Dynamic, meta) } -func (p *prober) waitForKServiceScale(name, namespace string, satisfyScale func(*int32) bool) error { +func (p *prober) waitForKServiceScale(name, namespace string, satisfyScale func(int32) bool) error { metricName := fmt.Sprintf("waitForKServiceScale/%s/%s", namespace, name) _, span := trace.StartSpan(context.Background(), metricName) defer span.End() @@ -50,7 +50,7 @@ func (p *prober) waitForKServiceScale(name, namespace string, satisfyScale func( }) } -func (p *prober) isScaledTo(satisfyScale func(*int32) bool, un *unstructured.Unstructured, namespace string, err error) (bool, error) { +func (p *prober) isScaledTo(satisfyScale func(int32) bool, un *unstructured.Unstructured, namespace string, err error) (bool, error) { if k8serrors.IsNotFound(err) { // Return false as we are not done yet. // We swallow the error to keep on polling. @@ -93,7 +93,7 @@ func (p *prober) isScaledTo(satisfyScale func(*int32) bool, un *unstructured.Uns // Return error to stop the polling. return false, err } - return satisfyScale(dep.Spec.Replicas), nil + return satisfyScale(dep.Status.ReadyReplicas), nil } func (p *prober) waitForTriggerReady(name, namespace string) error { diff --git a/test/prober/forwarder.go b/test/prober/forwarder.go index 47550b146a6..0b211009b40 100644 --- a/test/prober/forwarder.go +++ b/test/prober/forwarder.go @@ -49,8 +49,8 @@ func (p *prober) deployForwarder() { if p.config.Serving.ScaleToZero { waitFor(fmt.Sprintf("forwarder scales to zero: %v", forwarderName), func() error { - return p.waitForKServiceScale(forwarderName, p.client.Namespace, func(scale *int32) bool { - return *scale == 0 + return p.waitForKServiceScale(forwarderName, p.client.Namespace, func(scale int32) bool { + return scale == 0 }) }) } From 52f603e232b4860bae5beba23cfc9c318037edc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Thu, 13 Feb 2020 14:54:16 +0100 Subject: [PATCH 21/50] Removing .editorconfig as not revelant to knative/eventing#2388 --- .editorconfig | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 2f94ce46a1d..00000000000 --- a/.editorconfig +++ /dev/null @@ -1,15 +0,0 @@ -# EditorConfig is awesome: https://EditorConfig.org - -# top-most EditorConfig file -root = true - -# Unix-style newlines with a newline ending every file -[*] -end_of_line = lf -insert_final_newline = true -charset = utf-8 -indent_style = space -indent_size = 2 - -[**.go] -indent_style = tab From cf2e71911548f48c95c717808d435cce5050340e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Thu, 13 Feb 2020 17:06:12 +0100 Subject: [PATCH 22/50] Inteligent way of choosing serving version With the script added serving version is choosen dynamilly, versus the eventing version. The script tries to choose most compatibile version. --- test/e2e-common.sh | 6 +- test/scripts/resolve_matching_release.go | 111 ++++++++++++++++++ test/scripts/resolve_matching_release_test.go | 39 ++++++ 3 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 test/scripts/resolve_matching_release.go create mode 100644 test/scripts/resolve_matching_release_test.go diff --git a/test/e2e-common.sh b/test/e2e-common.sh index 2f40fcd8e78..a710eb949a9 100755 --- a/test/e2e-common.sh +++ b/test/e2e-common.sh @@ -180,7 +180,11 @@ function install_istio { function install_knative_serving { install_istio echo ">> Installing Knative serving" - readonly SERVING_YAML="https://github.com/knative/serving/releases/download/${LATEST_RELEASE_VERSION}/serving.yaml" + local SERVING_VERSION + SERVING_VERSION=$(go run test/scripts/resolve_matching_release.go \ + 'knative/serving' "${LATEST_RELEASE_VERSION}") \ + || fail_test 'Could not resolve knative serving version' + readonly SERVING_YAML="https://github.com/knative/serving/releases/download/${SERVING_VERSION}/serving.yaml" echo "Knative serving YAML: ${SERVING_YAML}" kubectl apply -f "${SERVING_YAML}" || return 1 diff --git a/test/scripts/resolve_matching_release.go b/test/scripts/resolve_matching_release.go new file mode 100644 index 00000000000..fe920ec3509 --- /dev/null +++ b/test/scripts/resolve_matching_release.go @@ -0,0 +1,111 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package main + +import ( + "encoding/json" + "fmt" + "github.com/rogpeppe/go-internal/semver" + "io/ioutil" + "knative.dev/eventing/test/lib" + "net/http" + "os" + "sort" +) + +var ( + ApiGateway = "https://api.github.com" +) + +func main() { + args := os.Args[1:] + if len(args) != 2 { + panic(fmt.Errorf("usage: ")) + } + + resolved := resolveMatchingRelease(args[0], args[1]) + fmt.Print(resolved) +} + +type bySemver []string + +func (s bySemver) Len() int { + return len(s) +} + +func (s bySemver) Swap(i, j int) { + s[i], s[j] = s[j], s[i] +} + +func (s bySemver) Less(i, j int) bool { + return semver.Compare(s[i], s[j]) > 0 +} + +type Tag struct { + Name string +} + +func resolveMatchingRelease(repo, version string) string { + endpoint := fmt.Sprintf("%s/repos/%s/tags", ApiGateway, repo) + resp, err := http.Get(endpoint) + lib.NoError(err) + defer func() { + err := resp.Body.Close() + lib.NoError(err) + }() + body, err := ioutil.ReadAll(resp.Body) + var tags []Tag + lib.NoError(json.Unmarshal(body, &tags)) + + versions := slurpVersions(tags) + matching := filterMatchingVersions(version, versions, true) + if len(matching) == 0 { + matching = filterMatchingVersions(version, versions, false) + if len(matching) == 0 { + matching = versions + } + } + sort.Sort(bySemver(matching)) + first := matching[0] + + return first +} + +func slurpVersions(tags []Tag) []string { + var res []string + for _, tag := range tags { + res = append(res, tag.Name) + } + return res +} + +func filterMatchingVersions(version string, versions []string, strict bool) []string { + matcher := semverMatcher(version, strict) + var matching []string + for _, candidate := range versions { + if matcher == semverMatcher(candidate, strict) { + matching = append(matching, candidate) + } + } + return matching +} + +func semverMatcher(version string, strict bool) string { + if strict { + return semver.MajorMinor(version) + } + return semver.Major(version) +} diff --git a/test/scripts/resolve_matching_release_test.go b/test/scripts/resolve_matching_release_test.go new file mode 100644 index 00000000000..070dfc0bc16 --- /dev/null +++ b/test/scripts/resolve_matching_release_test.go @@ -0,0 +1,39 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package main + +import ( + "github.com/rogpeppe/go-internal/semver" + "testing" +) + +func TestResolveMatchingRelease(t *testing.T) { + candidate := "v0.8.0" + resolved := resolveMatchingRelease("knative/serving", candidate) + + if resolved != "v0.8.1" { + t.Errorf("resolved invalid version: %s", resolved) + } +} + +func TestResolveMatchingReleaseOurAhead(t *testing.T) { + candidate := "v0.800.0" + resolved := resolveMatchingRelease("knative/serving", candidate) + + if semver.Compare(resolved, "v1.0.0") >= 0 { + t.Errorf("resolved invalid version: %s", resolved) + } +} From 77ae82a46bafc9a392e7fc78c2c4c59f1ae81a8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Thu, 13 Feb 2020 20:07:16 +0100 Subject: [PATCH 23/50] Moving shellchecks to other PR --- hack/update-deps.sh | 1 - test/e2e-common.sh | 1 - test/e2e-tests.sh | 2 -- test/e2e-upgrade-tests.sh | 2 -- 4 files changed, 6 deletions(-) diff --git a/hack/update-deps.sh b/hack/update-deps.sh index d5c93e64fdd..64caeb8e129 100755 --- a/hack/update-deps.sh +++ b/hack/update-deps.sh @@ -15,7 +15,6 @@ # limitations under the License. readonly ROOT_DIR=$(dirname "$0")/.. -# shellcheck disable=SC1090 source "${ROOT_DIR}/vendor/knative.dev/test-infra/scripts/library.sh" set -o errexit diff --git a/test/e2e-common.sh b/test/e2e-common.sh index 1fccbe84ca7..41c2b5c7414 100755 --- a/test/e2e-common.sh +++ b/test/e2e-common.sh @@ -94,7 +94,6 @@ function knative_teardown() { wait_until_object_does_not_exist namespaces knative-eventing echo ">> Uninstalling dependencies" - # shellcheck disable=SC2068 for i in ${!UNINSTALL_LIST[@]}; do # We uninstall elements in the reverse of the order they were installed. local YAML="${UNINSTALL_LIST[$(( ${#array[@]} - $i ))]}" diff --git a/test/e2e-tests.sh b/test/e2e-tests.sh index 890f1f56326..af280522372 100755 --- a/test/e2e-tests.sh +++ b/test/e2e-tests.sh @@ -24,12 +24,10 @@ # project $PROJECT_ID, start Knative eventing system, run the tests and # delete the cluster. -# shellcheck disable=SC1090 source "$(dirname "$0")/e2e-common.sh" # Script entry point. -# shellcheck disable=SC2068 initialize $@ --skip-istio-addon go_test_e2e -timeout=20m -parallel=12 ./test/e2e ./test/conformance || fail_test diff --git a/test/e2e-upgrade-tests.sh b/test/e2e-upgrade-tests.sh index 6d96ff20ee5..aae79d087ea 100755 --- a/test/e2e-upgrade-tests.sh +++ b/test/e2e-upgrade-tests.sh @@ -18,7 +18,6 @@ # Script entry point. -# shellcheck disable=SC1090 source "$(dirname "$0")/e2e-common.sh" # Overrides @@ -38,7 +37,6 @@ function uninstall_test_resources { true } -# shellcheck disable=SC2068 initialize $@ --skip-istio-addon TIMEOUT=${TIMEOUT:-30m} From ccc1cc2a3c1ba82aa4c71c1a113ec5b25b81c10e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Fri, 21 Feb 2020 19:20:55 +0100 Subject: [PATCH 24/50] Use Go's sync/errgroup for wait a bunch of conditions --- Gopkg.lock | 1 + test/prober/await.go | 22 ++++++++++------------ 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index 5d1a993a8ff..7defc064a36 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1466,6 +1466,7 @@ "go.opencensus.io/trace", "go.uber.org/atomic", "go.uber.org/zap", + "golang.org/x/sync/errgroup", "google.golang.org/grpc", "google.golang.org/grpc/codes", "google.golang.org/grpc/status", diff --git a/test/prober/await.go b/test/prober/await.go index 69f382e651b..0fb1019f19d 100644 --- a/test/prober/await.go +++ b/test/prober/await.go @@ -19,8 +19,11 @@ import ( "context" "errors" "fmt" + "time" + "go.opencensus.io/trace" "go.uber.org/zap" + "golang.org/x/sync/errgroup" appsv1 "k8s.io/api/apps/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -29,8 +32,6 @@ import ( "knative.dev/eventing/test/lib" "knative.dev/eventing/test/lib/duck" "knative.dev/eventing/test/lib/resources" - "sync" - "time" ) func (p *prober) waitForKServiceReady(name, namespace string) error { @@ -120,28 +121,25 @@ type awaitRoutine func() error var waits []*namedAwait func awaitAll(log *zap.SugaredLogger) { - var wg sync.WaitGroup - wg.Add(len(waits)) - thrown := false + var g errgroup.Group for _, w := range waits { - go func(w *namedAwait) { + w := w // https://golang.org/doc/faq#closures_and_goroutines + g.Go(func() error { log.Infof("Wait for %s", w.name) before := time.Now() err := w.routine() took := time.Now().Sub(before) if err != nil { - thrown = true log.Errorf("Error while waiting for %s: %v", w.name, err) } else { log.Infof("Successful wait for %s, took %v to complete", w.name, took) } - wg.Done() - }(w) + return err + }) } waits = nil - wg.Wait() - - if thrown { + // Wait for all waits to complete. + if err := g.Wait(); err != nil { panic(errors.New("there ware errors on waiting")) } } From 3cb28f3d31d097e9719e5bb623cd513f7d93f969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Wed, 26 Feb 2020 20:01:30 +0100 Subject: [PATCH 25/50] Use vendor for ensure.NoError --- Gopkg.lock | 9 + test/lib/errors.go | 25 -- test/prober/configuration.go | 27 +- test/prober/forwarder.go | 7 +- test/prober/receiver.go | 11 +- test/prober/sender.go | 7 +- test/prober/verify.go | 19 +- test/scripts/resolve_matching_release.go | 11 +- test/scripts/resolve_matching_release_test.go | 3 +- test/upgrade/main_test.go | 5 +- test/upgrade/probe_test.go | 13 +- test/upgrade/smoke_test.go | 3 +- third_party/VENDOR-LICENSE | 415 +++++++++--------- .../github.com/wavesoftware/go-ensure/LICENSE | 201 +++++++++ .../wavesoftware/go-ensure/errors.go | 33 ++ 15 files changed, 508 insertions(+), 281 deletions(-) delete mode 100644 test/lib/errors.go create mode 100644 vendor/github.com/wavesoftware/go-ensure/LICENSE create mode 100644 vendor/github.com/wavesoftware/go-ensure/errors.go diff --git a/Gopkg.lock b/Gopkg.lock index 7defc064a36..84221a388f6 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -552,6 +552,14 @@ revision = "9c95632b3e8562be6df690c639a3f5a6f40d3004" version = "v12.7.0" +[[projects]] + digest = "1:4d3c27cb343a081ef080e6a6d8aae270c3bdd5b04cfb22e36568a1dae5eee655" + name = "github.com/wavesoftware/go-ensure" + packages = ["."] + pruneopts = "NUT" + revision = "3824fe95969c1376f10cf2fe855f56abb69c1b84" + version = "v1.0.0" + [[projects]] digest = "1:b7d98c64e9467a8e5e67509031cd6baee81fba090ba2c3d30df1ff3d02d1d035" name = "go.opencensus.io" @@ -1458,6 +1466,7 @@ "github.com/rogpeppe/fastuuid", "github.com/rogpeppe/go-internal/semver", "github.com/tsenart/vegeta/lib", + "github.com/wavesoftware/go-ensure", "go.opencensus.io/plugin/ochttp", "go.opencensus.io/plugin/ochttp/propagation/b3", "go.opencensus.io/stats", diff --git a/test/lib/errors.go b/test/lib/errors.go deleted file mode 100644 index cdf14b96bec..00000000000 --- a/test/lib/errors.go +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2020 The Knative 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. - */ - -package lib - -import "github.com/pkg/errors" - -// NoError will panic if given an error, as it was unexpected -func NoError(err error) { - if err != nil { - panic(errors.WithMessage(err, "unexpected error")) - } -} diff --git a/test/prober/configuration.go b/test/prober/configuration.go index 79006270f66..ffa3619b672 100644 --- a/test/prober/configuration.go +++ b/test/prober/configuration.go @@ -19,14 +19,15 @@ import ( "bytes" "fmt" "io/ioutil" + "path" + "runtime" + "text/template" + + "github.com/wavesoftware/go-ensure" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/eventing/pkg/apis/eventing/v1alpha1" - "knative.dev/eventing/test/lib" duckv1 "knative.dev/pkg/apis/duck/v1" - "path" - "runtime" - "text/template" ) const ( @@ -50,13 +51,13 @@ func (p *prober) deployConfiguration() { func (p *prober) annotateNamespace() { ns, err := p.client.Kube.Kube.CoreV1().Namespaces(). Get(p.client.Namespace, metav1.GetOptions{}) - lib.NoError(err) + ensure.NoError(err) ns.Labels = map[string]string{ "knative-eventing-injection": "enabled", } _, err = p.client.Kube.Kube.CoreV1().Namespaces(). Update(ns) - lib.NoError(err) + ensure.NoError(err) } func (p *prober) deploySecret() { @@ -75,7 +76,7 @@ func (p *prober) deploySecret() { } _, err := p.client.Kube.Kube.CoreV1().Secrets(p.config.Namespace). Create(secret) - lib.NoError(err) + ensure.NoError(err) } func (p *prober) deployTriggers() { @@ -111,7 +112,7 @@ func (p *prober) deployTriggers() { p.log.Infof("Deploying trigger: %v", name) _, err := p.client.Eventing.EventingV1alpha1().Triggers(p.config.Namespace). Create(trigger) - lib.NoError(err) + ensure.NoError(err) waitFor(fmt.Sprintf("trigger be ready: %v", name), func() error { return p.waitForTriggerReady(name, p.config.Namespace) }) @@ -127,7 +128,7 @@ func (p *prober) removeSecret() { p.log.Infof("Removing secret: %v", configName) err := p.client.Kube.Kube.CoreV1().Secrets(p.config.Namespace). Delete(configName, &metav1.DeleteOptions{}) - lib.NoError(err) + ensure.NoError(err) } func (p *prober) removeTriggers() { @@ -136,7 +137,7 @@ func (p *prober) removeTriggers() { p.log.Infof("Removing trigger: %v", name) err := p.client.Eventing.EventingV1alpha1().Triggers(p.config.Namespace). Delete(name, &metav1.DeleteOptions{}) - lib.NoError(err) + ensure.NoError(err) } } @@ -144,10 +145,10 @@ func (p *prober) compileTemplate(templateName string) string { _, filename, _, _ := runtime.Caller(0) templateFilepath := path.Join(path.Dir(filename), templateName) templateBytes, err := ioutil.ReadFile(templateFilepath) - lib.NoError(err) + ensure.NoError(err) tmpl, err := template.New(templateName).Parse(string(templateBytes)) - lib.NoError(err) + ensure.NoError(err) var buff bytes.Buffer - lib.NoError(tmpl.Execute(&buff, p.config)) + ensure.NoError(tmpl.Execute(&buff, p.config)) return buff.String() } diff --git a/test/prober/forwarder.go b/test/prober/forwarder.go index 0b211009b40..bde0e6806f3 100644 --- a/test/prober/forwarder.go +++ b/test/prober/forwarder.go @@ -17,10 +17,11 @@ package prober import ( "fmt" + + "github.com/wavesoftware/go-ensure" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime/schema" - "knative.dev/eventing/test/lib" ) var ( @@ -41,7 +42,7 @@ func (p *prober) deployForwarder() { serving := p.client.Dynamic.Resource(servicesCR).Namespace(p.client.Namespace) service := forwarderKService(forwarderName, p.client.Namespace) _, err := serving.Create(service, metav1.CreateOptions{}) - lib.NoError(err) + ensure.NoError(err) waitFor(fmt.Sprintf("forwarder ksvc be ready: %v", forwarderName), func() error { return p.waitForKServiceReady(forwarderName, p.client.Namespace) @@ -60,7 +61,7 @@ func (p *prober) removeForwarder() { p.log.Infof("Remove forwarder knative service: %v", forwarderName) serving := p.client.Dynamic.Resource(servicesCR).Namespace(p.client.Namespace) err := serving.Delete(forwarderName, &metav1.DeleteOptions{}) - lib.NoError(err) + ensure.NoError(err) } func forwarderKService(name, namespace string) *unstructured.Unstructured { diff --git a/test/prober/receiver.go b/test/prober/receiver.go index 8cb3b2e2d58..a339470d46a 100644 --- a/test/prober/receiver.go +++ b/test/prober/receiver.go @@ -17,10 +17,11 @@ package prober import ( "fmt" + + "github.com/wavesoftware/go-ensure" corev1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" - "knative.dev/eventing/test/lib" ) var ( @@ -83,7 +84,7 @@ func (p *prober) deployReceiverPod() { }, } _, err := p.client.Kube.CreatePod(pod) - lib.NoError(err) + ensure.NoError(err) waitFor(fmt.Sprintf("receiver be ready: %v", receiverName), func() error { return p.waitForPodReady(receiverName, p.client.Namespace) @@ -117,7 +118,7 @@ func (p *prober) deployReceiverService() { } created, err := p.client.Kube.Kube.CoreV1().Services(p.config.Namespace). Create(service) - lib.NoError(err) + ensure.NoError(err) for _, portSpec := range created.Spec.Ports { if portSpec.Port == 80 { receiverNodePort = portSpec.NodePort @@ -134,12 +135,12 @@ func (p *prober) removeReceiverPod() { p.log.Infof("Remove of receiver pod: %v", receiverName) err := p.client.Kube.Kube.CoreV1().Pods(p.config.Namespace). Delete(receiverName, &v1.DeleteOptions{}) - lib.NoError(err) + ensure.NoError(err) } func (p *prober) removeReceiverService() { p.log.Infof("Remove of receiver service: %v", receiverName) err := p.client.Kube.Kube.CoreV1().Services(p.config.Namespace). Delete(receiverName, &v1.DeleteOptions{}) - lib.NoError(err) + ensure.NoError(err) } diff --git a/test/prober/sender.go b/test/prober/sender.go index 7eaffca95af..8fb8455a4f8 100644 --- a/test/prober/sender.go +++ b/test/prober/sender.go @@ -17,9 +17,10 @@ package prober import ( "fmt" + + "github.com/wavesoftware/go-ensure" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "knative.dev/eventing/test/lib" ) var senderName = "wathola-sender" @@ -59,7 +60,7 @@ func (p *prober) deploySender() { } _, err := p.client.Kube.Kube.CoreV1().Pods(p.client.Namespace). Create(pod) - lib.NoError(err) + ensure.NoError(err) waitFor(fmt.Sprintf("sender pod be ready: %v", senderName), func() error { return p.waitForPodReady(senderName, p.client.Namespace) @@ -71,5 +72,5 @@ func (p *prober) removeSender() { err := p.client.Kube.Kube.CoreV1().Pods(p.client.Namespace). Delete(senderName, &metav1.DeleteOptions{}) - lib.NoError(err) + ensure.NoError(err) } diff --git a/test/prober/verify.go b/test/prober/verify.go index 76a49d1df7c..d7e9de9593b 100644 --- a/test/prober/verify.go +++ b/test/prober/verify.go @@ -20,13 +20,14 @@ import ( "encoding/json" "errors" "fmt" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "knative.dev/eventing/test/lib" "math/rand" "net/http" "sort" "strings" + + "github.com/wavesoftware/go-ensure" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) func (p *prober) Verify() ([]error, int) { @@ -76,7 +77,7 @@ var addressTypeToPriorities = map[corev1.NodeAddressType]int{ func (p *prober) figureOutClusterHostname() string { nodes, err := p.client.Kube.Kube.CoreV1().Nodes().List(metav1.ListOptions{}) - lib.NoError(err) + ensure.NoError(err) if len(nodes.Items) == 1 { node := nodes.Items[0] return p.nodeExternalAddress(node) @@ -122,21 +123,21 @@ func (p *prober) fetchReceiverReport(hostname string) *Report { u := fmt.Sprintf("http://%s:%d/report", hostname, receiverNodePort) p.log.Infof("Fetching receiver report at: %v", u) resp, err := http.Get(u) - lib.NoError(err) + ensure.NoError(err) if resp.StatusCode != 200 { var b strings.Builder - lib.NoError(resp.Header.Write(&b)) + ensure.NoError(resp.Header.Write(&b)) headers := b.String() panic(fmt.Errorf("could not get receiver report at %v, "+ "status code: %v, headers: %v", u, resp.StatusCode, headers)) } buf := new(bytes.Buffer) _, err = buf.ReadFrom(resp.Body) - lib.NoError(err) - lib.NoError(resp.Body.Close()) + ensure.NoError(err) + ensure.NoError(resp.Body.Close()) jsonBytes := buf.Bytes() var report Report - lib.NoError(json.Unmarshal(jsonBytes, &report)) + ensure.NoError(json.Unmarshal(jsonBytes, &report)) return &report } diff --git a/test/scripts/resolve_matching_release.go b/test/scripts/resolve_matching_release.go index fe920ec3509..76244b89947 100644 --- a/test/scripts/resolve_matching_release.go +++ b/test/scripts/resolve_matching_release.go @@ -18,12 +18,13 @@ package main import ( "encoding/json" "fmt" - "github.com/rogpeppe/go-internal/semver" "io/ioutil" - "knative.dev/eventing/test/lib" "net/http" "os" "sort" + + "github.com/rogpeppe/go-internal/semver" + "github.com/wavesoftware/go-ensure" ) var ( @@ -61,14 +62,14 @@ type Tag struct { func resolveMatchingRelease(repo, version string) string { endpoint := fmt.Sprintf("%s/repos/%s/tags", ApiGateway, repo) resp, err := http.Get(endpoint) - lib.NoError(err) + ensure.NoError(err) defer func() { err := resp.Body.Close() - lib.NoError(err) + ensure.NoError(err) }() body, err := ioutil.ReadAll(resp.Body) var tags []Tag - lib.NoError(json.Unmarshal(body, &tags)) + ensure.NoError(json.Unmarshal(body, &tags)) versions := slurpVersions(tags) matching := filterMatchingVersions(version, versions, true) diff --git a/test/scripts/resolve_matching_release_test.go b/test/scripts/resolve_matching_release_test.go index 070dfc0bc16..c9d0631aac3 100644 --- a/test/scripts/resolve_matching_release_test.go +++ b/test/scripts/resolve_matching_release_test.go @@ -16,8 +16,9 @@ package main import ( - "github.com/rogpeppe/go-internal/semver" "testing" + + "github.com/rogpeppe/go-internal/semver" ) func TestResolveMatchingRelease(t *testing.T) { diff --git a/test/upgrade/main_test.go b/test/upgrade/main_test.go index f1480053066..9990630cb1a 100644 --- a/test/upgrade/main_test.go +++ b/test/upgrade/main_test.go @@ -16,10 +16,11 @@ package upgrade import ( - "knative.dev/eventing/test" - "knative.dev/eventing/test/lib" "os" "testing" + + "knative.dev/eventing/test" + "knative.dev/eventing/test/lib" ) var setup = lib.Setup diff --git a/test/upgrade/probe_test.go b/test/upgrade/probe_test.go index 86f79364a8c..4e7a45a7061 100644 --- a/test/upgrade/probe_test.go +++ b/test/upgrade/probe_test.go @@ -18,13 +18,14 @@ package upgrade import ( - "go.uber.org/zap" "io/ioutil" - "knative.dev/eventing/test/lib" - "knative.dev/eventing/test/prober" "os" "syscall" "testing" + + "github.com/wavesoftware/go-ensure" + "go.uber.org/zap" + "knative.dev/eventing/test/prober" ) const ( @@ -53,7 +54,7 @@ func TestProbe(t *testing.T) { // inline with other logs instead of buffered until the end. log := createLogger() probe := prober.RunEventProber(log, client, config) - lib.NoError(ioutil.WriteFile(ready, []byte(readyMessage), 0666)) + ensure.NoError(ioutil.WriteFile(ready, []byte(readyMessage), 0666)) defer prober.AssertEventProber(t, probe) log.Infof("Waiting for file: %v as a signal that "+ @@ -64,7 +65,7 @@ func TestProbe(t *testing.T) { func createLogger() *zap.SugaredLogger { log, err := zap.NewDevelopment() - lib.NoError(err) + ensure.NoError(err) return log.Sugar() } @@ -73,7 +74,7 @@ func ensureTempFilesAreCleaned() { for _, filename := range filenames { _, err := os.Stat(filename) if err == nil { - lib.NoError(os.Remove(filename)) + ensure.NoError(os.Remove(filename)) } } } diff --git a/test/upgrade/smoke_test.go b/test/upgrade/smoke_test.go index 133381c9c30..fba6e32498d 100644 --- a/test/upgrade/smoke_test.go +++ b/test/upgrade/smoke_test.go @@ -16,9 +16,10 @@ package upgrade import ( + "testing" + cloudevents "github.com/cloudevents/sdk-go" "knative.dev/eventing/test/e2e/helpers" - "testing" ) func runSmokeTest(t *testing.T) { diff --git a/third_party/VENDOR-LICENSE b/third_party/VENDOR-LICENSE index 9a4532b97ad..01100687f11 100644 --- a/third_party/VENDOR-LICENSE +++ b/third_party/VENDOR-LICENSE @@ -5714,6 +5714,213 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +=========================================================== +Import: knative.dev/eventing/vendor/github.com/wavesoftware/go-ensure + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 Wave Software + + 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. + + + =========================================================== Import: knative.dev/eventing/vendor/go.opencensus.io @@ -7749,214 +7956,6 @@ Import: knative.dev/eventing/vendor/k8s.io/apimachinery -=========================================================== -Import: knative.dev/eventing/vendor/k8s.io/apiserver - - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. - - - =========================================================== Import: knative.dev/eventing/vendor/k8s.io/client-go diff --git a/vendor/github.com/wavesoftware/go-ensure/LICENSE b/vendor/github.com/wavesoftware/go-ensure/LICENSE new file mode 100644 index 00000000000..6c180a6f23d --- /dev/null +++ b/vendor/github.com/wavesoftware/go-ensure/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 Wave Software + + 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/vendor/github.com/wavesoftware/go-ensure/errors.go b/vendor/github.com/wavesoftware/go-ensure/errors.go new file mode 100644 index 00000000000..9da1e2e860a --- /dev/null +++ b/vendor/github.com/wavesoftware/go-ensure/errors.go @@ -0,0 +1,33 @@ +package ensure + +import ( + "fmt" + "github.com/pkg/errors" + "regexp" +) + +// NoError will panic if given an error, as it was unexpected +func NoError(err error) { + if err != nil { + panic(errors.WithMessage(err, "unexpected error")) + } +} + +// Error will panic if given no error, as it expected one +func Error(err error) { + if err == nil { + panic(errors.New("expecting error, but none given")) + } +} + +// ErrorWithMessage will panic if given no error, or error message don't match provided regexp +func ErrorWithMessage(err error, messageRegexp string) { + Error(err) + validErrorMessage := regexp.MustCompile(messageRegexp) + if !validErrorMessage.MatchString(err.Error()) { + panic(errors.WithMessage( + err, + fmt.Sprintf("given error doesn't match given regexp (%s)", messageRegexp), + )) + } +} From 1312462438d59b1e3f4d85c33219eff232e77053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Wed, 26 Feb 2020 20:09:06 +0100 Subject: [PATCH 26/50] Move awiat parameters to await package --- test/lib/await/constants.go | 25 +++++++++++++++++++++++++ test/lib/duck/resource_checks.go | 14 +++----------- test/prober/await.go | 3 ++- 3 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 test/lib/await/constants.go diff --git a/test/lib/await/constants.go b/test/lib/await/constants.go new file mode 100644 index 00000000000..a48f71e2ab4 --- /dev/null +++ b/test/lib/await/constants.go @@ -0,0 +1,25 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package await + +import "time" + +const ( + // Interval is used for polling in checking resource states + Interval = 1 * time.Second + // Timeout is used for polling in checking resource states + Timeout = 4 * time.Minute +) diff --git a/test/lib/duck/resource_checks.go b/test/lib/duck/resource_checks.go index 7e3ef59dc1c..e8ce654aa3f 100644 --- a/test/lib/duck/resource_checks.go +++ b/test/lib/duck/resource_checks.go @@ -20,30 +20,22 @@ limitations under the License. package duck import ( - "time" - k8serrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/dynamic" + "knative.dev/eventing/test/lib/await" "knative.dev/pkg/apis" duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" "knative.dev/eventing/test/lib/resources" ) -const ( - // Interval is used for polling in checking resource states - Interval = 1 * time.Second - // Timeout is used for polling in checking resource states - Timeout = 4 * time.Minute -) - // WaitForResourceReady polls the status of the MetaResource from client // every interval until isResourceReady returns `true` indicating // it is done, returns an error or timeout. func WaitForResourceReady(dynamicClient dynamic.Interface, obj *resources.MetaResource) error { - return wait.PollImmediate(Interval, Timeout, func() (bool, error) { + return wait.PollImmediate(await.Interval, await.Timeout, func() (bool, error) { untyped, err := GetGenericObject(dynamicClient, obj, &duckv1beta1.KResource{}) return isResourceReady(untyped, err) }) @@ -51,7 +43,7 @@ func WaitForResourceReady(dynamicClient dynamic.Interface, obj *resources.MetaRe // WaitForResourcesReady waits until all the specified resources in the given namespace are ready. func WaitForResourcesReady(dynamicClient dynamic.Interface, objList *resources.MetaResourceList) error { - return wait.PollImmediate(Interval, Timeout, func() (bool, error) { + return wait.PollImmediate(await.Interval, await.Timeout, func() (bool, error) { untypeds, err := GetGenericObjectList(dynamicClient, objList, &duckv1beta1.KResource{}) for _, untyped := range untypeds { if isReady, err := isResourceReady(untyped, err); !isReady { diff --git a/test/prober/await.go b/test/prober/await.go index 0fb1019f19d..22cdacfa940 100644 --- a/test/prober/await.go +++ b/test/prober/await.go @@ -30,6 +30,7 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/util/wait" "knative.dev/eventing/test/lib" + "knative.dev/eventing/test/lib/await" "knative.dev/eventing/test/lib/duck" "knative.dev/eventing/test/lib/resources" ) @@ -44,7 +45,7 @@ func (p *prober) waitForKServiceScale(name, namespace string, satisfyScale func( _, span := trace.StartSpan(context.Background(), metricName) defer span.End() - return wait.PollImmediate(duck.Interval, duck.Timeout, func() (bool, error) { + return wait.PollImmediate(await.Interval, await.Timeout, func() (bool, error) { serving := p.client.Dynamic.Resource(servicesCR).Namespace(namespace) unstruct, err := serving.Get(name, metav1.GetOptions{}) return p.isScaledTo(satisfyScale, unstruct, namespace, err) From 9c8cdab3939f89c8099a0b89d3c45b7f5c42e63b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Wed, 26 Feb 2020 20:11:53 +0100 Subject: [PATCH 27/50] Remove trace span metric --- test/prober/await.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/prober/await.go b/test/prober/await.go index 22cdacfa940..a79d23deaea 100644 --- a/test/prober/await.go +++ b/test/prober/await.go @@ -16,12 +16,10 @@ package prober import ( - "context" "errors" "fmt" "time" - "go.opencensus.io/trace" "go.uber.org/zap" "golang.org/x/sync/errgroup" appsv1 "k8s.io/api/apps/v1" @@ -41,10 +39,6 @@ func (p *prober) waitForKServiceReady(name, namespace string) error { } func (p *prober) waitForKServiceScale(name, namespace string, satisfyScale func(int32) bool) error { - metricName := fmt.Sprintf("waitForKServiceScale/%s/%s", namespace, name) - _, span := trace.StartSpan(context.Background(), metricName) - defer span.End() - return wait.PollImmediate(await.Interval, await.Timeout, func() (bool, error) { serving := p.client.Dynamic.Resource(servicesCR).Namespace(namespace) unstruct, err := serving.Get(name, metav1.GetOptions{}) From 6cfcc7311d04b445b3ca825d1fa039baeef5d581 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Wed, 26 Feb 2020 20:16:49 +0100 Subject: [PATCH 28/50] Use WaitForPodRunning from knative/pkg lib --- test/prober/await.go | 9 --------- test/prober/receiver.go | 3 ++- test/prober/sender.go | 3 ++- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/test/prober/await.go b/test/prober/await.go index a79d23deaea..f29058c5ce1 100644 --- a/test/prober/await.go +++ b/test/prober/await.go @@ -97,15 +97,6 @@ func (p *prober) waitForTriggerReady(name, namespace string) error { return duck.WaitForResourceReady(p.client.Dynamic, meta) } -func (p *prober) waitForPodReady(name, namespace string) error { - podType := &metav1.TypeMeta{ - Kind: "Pod", - APIVersion: "v1", - } - meta := resources.NewMetaResource(name, namespace, podType) - return duck.WaitForResourceReady(p.client.Dynamic, meta) -} - type namedAwait struct { name string routine awaitRoutine diff --git a/test/prober/receiver.go b/test/prober/receiver.go index a339470d46a..aedf6df3bcc 100644 --- a/test/prober/receiver.go +++ b/test/prober/receiver.go @@ -22,6 +22,7 @@ import ( corev1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" + "knative.dev/pkg/test" ) var ( @@ -87,7 +88,7 @@ func (p *prober) deployReceiverPod() { ensure.NoError(err) waitFor(fmt.Sprintf("receiver be ready: %v", receiverName), func() error { - return p.waitForPodReady(receiverName, p.client.Namespace) + return test.WaitForPodRunning(p.client.Kube, receiverName, p.client.Namespace) }) } diff --git a/test/prober/sender.go b/test/prober/sender.go index 8fb8455a4f8..0da93c05402 100644 --- a/test/prober/sender.go +++ b/test/prober/sender.go @@ -21,6 +21,7 @@ import ( "github.com/wavesoftware/go-ensure" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/test" ) var senderName = "wathola-sender" @@ -63,7 +64,7 @@ func (p *prober) deploySender() { ensure.NoError(err) waitFor(fmt.Sprintf("sender pod be ready: %v", senderName), func() error { - return p.waitForPodReady(senderName, p.client.Namespace) + return test.WaitForPodRunning(p.client.Kube, senderName, p.client.Namespace) }) } From 206b8ea647f0c378cf3d5316d0c800c0be90c2c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Wed, 26 Feb 2020 20:35:22 +0100 Subject: [PATCH 29/50] Use ConfigMap instead of Secret --- test/prober/configuration.go | 21 ++++++++++----------- test/prober/forwarder.go | 4 ++-- test/prober/receiver.go | 4 ++-- test/prober/sender.go | 4 ++-- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/test/prober/configuration.go b/test/prober/configuration.go index ffa3619b672..82945ca3956 100644 --- a/test/prober/configuration.go +++ b/test/prober/configuration.go @@ -44,7 +44,7 @@ var ( func (p *prober) deployConfiguration() { p.annotateNamespace() - p.deploySecret() + p.deployConfigMap() p.deployTriggers() } @@ -60,21 +60,20 @@ func (p *prober) annotateNamespace() { ensure.NoError(err) } -func (p *prober) deploySecret() { +func (p *prober) deployConfigMap() { name := configName - p.log.Infof("Deploying secret: %v", name) + p.log.Infof("Deploying config map: %v", name) configData := p.compileTemplate(configFilename) data := make(map[string]string, 0) data[configFilename] = configData - secret := &corev1.Secret{ + secret := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ Name: name, }, - StringData: data, - Type: "Opaque", + Data: data, } - _, err := p.client.Kube.Kube.CoreV1().Secrets(p.config.Namespace). + _, err := p.client.Kube.Kube.CoreV1().ConfigMaps(p.config.Namespace). Create(secret) ensure.NoError(err) } @@ -120,13 +119,13 @@ func (p *prober) deployTriggers() { } func (p *prober) removeConfiguration() { - p.removeSecret() + p.removeConfigMap() p.removeTriggers() } -func (p *prober) removeSecret() { - p.log.Infof("Removing secret: %v", configName) - err := p.client.Kube.Kube.CoreV1().Secrets(p.config.Namespace). +func (p *prober) removeConfigMap() { + p.log.Infof("Removing config map: %v", configName) + err := p.client.Kube.Kube.CoreV1().ConfigMaps(p.config.Namespace). Delete(configName, &metav1.DeleteOptions{}) ensure.NoError(err) } diff --git a/test/prober/forwarder.go b/test/prober/forwarder.go index bde0e6806f3..afc6edb7e6e 100644 --- a/test/prober/forwarder.go +++ b/test/prober/forwarder.go @@ -94,8 +94,8 @@ func forwarderKService(name, namespace string) *unstructured.Unstructured { }}, "volumes": []map[string]interface{}{{ "name": configName, - "secret": map[string]interface{}{ - "secretName": configName, + "configMap": map[string]interface{}{ + "name": configName, }, }}, }, diff --git a/test/prober/receiver.go b/test/prober/receiver.go index aedf6df3bcc..a22b62fee4b 100644 --- a/test/prober/receiver.go +++ b/test/prober/receiver.go @@ -55,8 +55,8 @@ func (p *prober) deployReceiverPod() { { Name: configName, VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: configName, + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{Name: configName}, }, }, }, diff --git a/test/prober/sender.go b/test/prober/sender.go index 0da93c05402..16f7357c32c 100644 --- a/test/prober/sender.go +++ b/test/prober/sender.go @@ -38,8 +38,8 @@ func (p *prober) deploySender() { { Name: configName, VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: configName, + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{Name: configName}, }, }, }, From 9cdbe679db368a5981c94baea4136d2592e3aeea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Thu, 27 Feb 2020 11:51:46 +0100 Subject: [PATCH 30/50] Warn about errors in upgrade tests (ref #2665) --- test/prober/prober.go | 34 ++++++++++++++++++++++++---------- test/upgrade/probe_test.go | 4 ++++ 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/test/prober/prober.go b/test/prober/prober.go index ec9869c7fd3..8698e8db3be 100644 --- a/test/prober/prober.go +++ b/test/prober/prober.go @@ -16,10 +16,11 @@ package prober import ( - "go.uber.org/zap" - "knative.dev/eventing/test/lib" "testing" "time" + + "go.uber.org/zap" + "knative.dev/eventing/test/lib" ) var ( @@ -38,6 +39,9 @@ type Prober interface { // Finish send finished event Finish() + // ReportError will reports found errors in proper way + ReportError(t *testing.T, err error) + // deploy a prober to a cluster deploy() // remove a prober from cluster @@ -46,10 +50,11 @@ type Prober interface { // Config represents a configuration for prober type Config struct { - Namespace string - Interval time.Duration - Serving ServingConfig - FinishedSleep time.Duration + Namespace string + Interval time.Duration + Serving ServingConfig + FinishedSleep time.Duration + FailOnMissingEvents bool } type ServingConfig struct { @@ -59,9 +64,10 @@ type ServingConfig struct { func NewConfig(namespace string) *Config { return &Config{ - Namespace: namespace, - Interval: Interval, - FinishedSleep: 5 * time.Second, + Namespace: namespace, + Interval: Interval, + FinishedSleep: 5 * time.Second, + FailOnMissingEvents: true, Serving: ServingConfig{ Use: true, ScaleToZero: true, @@ -89,7 +95,7 @@ func AssertEventProber(t *testing.T, prober Prober) { t.Logf("There ware %v errors. Listing them below.", len(errors)) } for _, err := range errors { - t.Error(err) + prober.ReportError(t, err) } prober.remove() @@ -101,6 +107,14 @@ type prober struct { config *Config } +func (p *prober) ReportError(t *testing.T, err error) { + if p.config.FailOnMissingEvents { + t.Error(err) + } else { + p.log.Warn(err) + } +} + func (p *prober) deploy() { p.log.Infof("Using namespace for probe testing: %v", p.client.Namespace) p.deployConfiguration() diff --git a/test/upgrade/probe_test.go b/test/upgrade/probe_test.go index 4e7a45a7061..04683b7f9b3 100644 --- a/test/upgrade/probe_test.go +++ b/test/upgrade/probe_test.go @@ -50,6 +50,10 @@ func TestProbe(t *testing.T) { defer tearDown(client) config := prober.NewConfig(client.Namespace) + + // FIXME: https://github.com/knative/eventing/issues/2665 + config.FailOnMissingEvents = false + // Use zap.SugarLogger instead of t.Logf because we want to see failures // inline with other logs instead of buffered until the end. log := createLogger() From 5960650d77ff3c3415897368914518324660cf52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Thu, 27 Feb 2020 15:33:34 +0100 Subject: [PATCH 31/50] Move knative serving to duck & resources libs The prober had to much code in itself. Moving knative serving to more appropriate packages like duck and resources. --- test/lib/{await => duck}/constants.go | 8 +-- test/lib/duck/resource_checks.go | 5 +- test/lib/duck/serving_checks.go | 60 +++++++++++++++++++ test/lib/resources/constants.go | 19 ++++++ test/lib/resources/serving.go | 83 +++++++++++++++++++++++++++ test/prober/await.go | 66 --------------------- test/prober/configuration.go | 3 +- test/prober/forwarder.go | 25 +++----- test/prober/prober.go | 8 +++ 9 files changed, 186 insertions(+), 91 deletions(-) rename test/lib/{await => duck}/constants.go (76%) create mode 100644 test/lib/duck/serving_checks.go diff --git a/test/lib/await/constants.go b/test/lib/duck/constants.go similarity index 76% rename from test/lib/await/constants.go rename to test/lib/duck/constants.go index a48f71e2ab4..54c9f6a80ea 100644 --- a/test/lib/await/constants.go +++ b/test/lib/duck/constants.go @@ -13,13 +13,11 @@ * limitations under the License. */ -package await +package duck import "time" const ( - // Interval is used for polling in checking resource states - Interval = 1 * time.Second - // Timeout is used for polling in checking resource states - Timeout = 4 * time.Minute + interval = 1 * time.Second + timeout = 4 * time.Minute ) diff --git a/test/lib/duck/resource_checks.go b/test/lib/duck/resource_checks.go index e8ce654aa3f..371982b0f73 100644 --- a/test/lib/duck/resource_checks.go +++ b/test/lib/duck/resource_checks.go @@ -24,7 +24,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/wait" "k8s.io/client-go/dynamic" - "knative.dev/eventing/test/lib/await" "knative.dev/pkg/apis" duckv1beta1 "knative.dev/pkg/apis/duck/v1beta1" @@ -35,7 +34,7 @@ import ( // every interval until isResourceReady returns `true` indicating // it is done, returns an error or timeout. func WaitForResourceReady(dynamicClient dynamic.Interface, obj *resources.MetaResource) error { - return wait.PollImmediate(await.Interval, await.Timeout, func() (bool, error) { + return wait.PollImmediate(interval, timeout, func() (bool, error) { untyped, err := GetGenericObject(dynamicClient, obj, &duckv1beta1.KResource{}) return isResourceReady(untyped, err) }) @@ -43,7 +42,7 @@ func WaitForResourceReady(dynamicClient dynamic.Interface, obj *resources.MetaRe // WaitForResourcesReady waits until all the specified resources in the given namespace are ready. func WaitForResourcesReady(dynamicClient dynamic.Interface, objList *resources.MetaResourceList) error { - return wait.PollImmediate(await.Interval, await.Timeout, func() (bool, error) { + return wait.PollImmediate(interval, timeout, func() (bool, error) { untypeds, err := GetGenericObjectList(dynamicClient, objList, &duckv1beta1.KResource{}) for _, untyped := range untypeds { if isReady, err := isResourceReady(untyped, err); !isReady { diff --git a/test/lib/duck/serving_checks.go b/test/lib/duck/serving_checks.go new file mode 100644 index 00000000000..123e6241c41 --- /dev/null +++ b/test/lib/duck/serving_checks.go @@ -0,0 +1,60 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package duck + +import ( + appsv1 "k8s.io/api/apps/v1" + "k8s.io/apimachinery/pkg/util/wait" + "knative.dev/eventing/test/lib/resources" + "knative.dev/pkg/test" +) + +// WaitForKServiceReady will wait until ksvc reports that's ready +func WaitForKServiceReady(client resources.ServingClient, name, namespace string) error { + meta := resources.NewMetaResource(name, namespace, &resources.KServiceType) + return WaitForResourceReady(client.Dynamic, meta) +} + +// WaitForKServiceScales will wait until ksvc scale is satisfied +func WaitForKServiceScales(client resources.ServingClient, name, namespace string, satisfyScale func(int) bool) error { + err := WaitForKServiceReady(client, name, namespace) + if err != nil { + return err + } + deploymentName, err := waitForKServiceDeploymentName(client, name, namespace) + if err != nil { + return err + } + inState := func(dep *appsv1.Deployment) (bool, error) { + return satisfyScale(int(dep.Status.ReadyReplicas)), nil + } + return test.WaitForDeploymentState( + client.Kube, deploymentName, inState, "scales", namespace, timeout, + ) +} + +func waitForKServiceDeploymentName(client resources.ServingClient, name, namespace string) (string, error) { + var deploymentName string + err := wait.PollImmediate(interval, timeout, func() (bool, error) { + dn, found, err := resources.KServiceDeploymentName(client, name, namespace) + if found { + deploymentName = dn + } + return found, err + }) + + return deploymentName, err +} diff --git a/test/lib/resources/constants.go b/test/lib/resources/constants.go index d2303f64817..6b63a45ce8e 100644 --- a/test/lib/resources/constants.go +++ b/test/lib/resources/constants.go @@ -16,6 +16,11 @@ limitations under the License. package resources +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" +) + // SystemNamespace is the namespace where Eventing is installed, it's default to be knative-eventing. const SystemNamespace = "knative-eventing" @@ -34,6 +39,20 @@ const ( KServiceKind string = "Service" ) +var ( + // KServicesGVR is GroupVersionResource for Knative Service + KServicesGVR = schema.GroupVersionResource{ + Group: "serving.knative.dev", + Version: "v1alpha1", + Resource: "services", + } + // KServiceType is type of Knative Service + KServiceType = metav1.TypeMeta{ + Kind: "Service", + APIVersion: KServicesGVR.GroupVersion().String(), + } +) + // Kind for core Kubernetes resources. const ( ServiceKind string = "Service" diff --git a/test/lib/resources/serving.go b/test/lib/resources/serving.go index 86bd110a137..ab912bd2bbd 100644 --- a/test/lib/resources/serving.go +++ b/test/lib/resources/serving.go @@ -19,11 +19,94 @@ package resources // This file contains functions that construct Serving resources. import ( + "fmt" + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/client-go/dynamic" pkgTest "knative.dev/pkg/test" ) +// ServingClient holds clients required to get serving resources +type ServingClient struct { + Kube *pkgTest.KubeClient + Dynamic dynamic.Interface +} + +// KServiceRoute represents ksvc route, so how much traffic is routed to given deployment +type KServiceRoute struct { + TrafficPercent uint8 + DeploymentName string +} + // KServiceRef returns a Knative Service ObjectReference for a given Service name. func KServiceRef(name string) *corev1.ObjectReference { return pkgTest.CoreV1ObjectReference(KServiceKind, ServingAPIVersion, name) } + +// KServiceRoutes gets routes of given ksvc. +// If ksvc isn't ready yet second return value will be false. +func KServiceRoutes(client ServingClient, name, namespace string) ([]KServiceRoute, bool, error) { + serving := client.Dynamic.Resource(KServicesGVR).Namespace(namespace) + unstruct, err := serving.Get(name, metav1.GetOptions{}) + if k8serrors.IsNotFound(err) { + // Return false as we are not done yet. + // We swallow the error to keep on polling. + // It should only happen if we wait for the auto-created resources, like default Broker. + return nil, false, nil + } else if err != nil { + // Return error to stop the polling. + return nil, false, err + } + + routes, ready := ksvcRoutes(unstruct) + return routes, ready, nil +} + +// KServiceDeploymentName returns a name of deployment of Knative Service that +// receives 100% of traffic. +// If ksvc isn't ready yet second return value will be false. +func KServiceDeploymentName(client ServingClient, name, namespace string) (string, bool, error) { + routes, ready, err := KServiceRoutes(client, name, namespace) + if ready { + if len(routes) > 1 { + return "", false, fmt.Errorf("traffic shouldn't be split to more then 1 revision: %v", routes) + } + r := routes[0] + return r.DeploymentName, true, nil + } + + return "", ready, err +} + +func ksvcRoutes(un *unstructured.Unstructured) ([]KServiceRoute, bool) { + routes := make([]KServiceRoute, 0) + content := un.UnstructuredContent() + maybeStatus, ok := content["status"] + if !ok { + return routes, false + } + status := maybeStatus.(map[string]interface{}) + maybeTraffic, ok := status["traffic"] + if !ok { + return routes, false + } + traffic := maybeTraffic.([]interface{}) + if len(traffic) == 0 { + // continue to wait + return routes, false + } + for _, uRoute := range traffic { + route := uRoute.(map[string]interface{}) + revisionName := route["revisionName"].(string) + percent := uint8(route["percent"].(int64)) + deploymentName := fmt.Sprintf("%s-deployment", revisionName) + routes = append(routes, KServiceRoute{ + TrafficPercent: percent, + DeploymentName: deploymentName, + }) + } + return routes, true +} diff --git a/test/prober/await.go b/test/prober/await.go index f29058c5ce1..2474afe2ba8 100644 --- a/test/prober/await.go +++ b/test/prober/await.go @@ -17,81 +17,15 @@ package prober import ( "errors" - "fmt" "time" "go.uber.org/zap" "golang.org/x/sync/errgroup" - appsv1 "k8s.io/api/apps/v1" - k8serrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/util/wait" "knative.dev/eventing/test/lib" - "knative.dev/eventing/test/lib/await" "knative.dev/eventing/test/lib/duck" "knative.dev/eventing/test/lib/resources" ) -func (p *prober) waitForKServiceReady(name, namespace string) error { - meta := resources.NewMetaResource(name, namespace, &servingType) - return duck.WaitForResourceReady(p.client.Dynamic, meta) -} - -func (p *prober) waitForKServiceScale(name, namespace string, satisfyScale func(int32) bool) error { - return wait.PollImmediate(await.Interval, await.Timeout, func() (bool, error) { - serving := p.client.Dynamic.Resource(servicesCR).Namespace(namespace) - unstruct, err := serving.Get(name, metav1.GetOptions{}) - return p.isScaledTo(satisfyScale, unstruct, namespace, err) - }) -} - -func (p *prober) isScaledTo(satisfyScale func(int32) bool, un *unstructured.Unstructured, namespace string, err error) (bool, error) { - if k8serrors.IsNotFound(err) { - // Return false as we are not done yet. - // We swallow the error to keep on polling. - // It should only happen if we wait for the auto-created resources, like default Broker. - return false, nil - } else if err != nil { - // Return error to stop the polling. - return false, err - } - - content := un.UnstructuredContent() - maybeStatus, ok := content["status"] - if !ok { - return false, nil - } - status := maybeStatus.(map[string]interface{}) - maybeTraffic, ok := status["traffic"] - if !ok { - return false, nil - } - traffic := maybeTraffic.([]interface{}) - if len(traffic) > 1 { - return false, fmt.Errorf("traffic shouldn't be split to more then 1 revision: %v", traffic) - } - if len(traffic) == 0 { - // continue to wait - return false, nil - } - firstTraffic := traffic[0].(map[string]interface{}) - revisionName := firstTraffic["revisionName"].(string) - deploymentName := fmt.Sprintf("%s-deployment", revisionName) - - var dep *appsv1.Deployment - dep, err = p.client.Kube.Kube.AppsV1().Deployments(namespace). - Get(deploymentName, metav1.GetOptions{}) - if k8serrors.IsNotFound(err) { - // Return false as we are not done yet. - return false, nil - } else if err != nil { - // Return error to stop the polling. - return false, err - } - return satisfyScale(dep.Status.ReadyReplicas), nil -} - func (p *prober) waitForTriggerReady(name, namespace string) error { meta := resources.NewMetaResource(name, namespace, lib.TriggerTypeMeta) return duck.WaitForResourceReady(p.client.Dynamic, meta) diff --git a/test/prober/configuration.go b/test/prober/configuration.go index 82945ca3956..0c5f811f7ad 100644 --- a/test/prober/configuration.go +++ b/test/prober/configuration.go @@ -27,6 +27,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/eventing/pkg/apis/eventing/v1alpha1" + "knative.dev/eventing/test/lib/resources" duckv1 "knative.dev/pkg/apis/duck/v1" ) @@ -89,7 +90,7 @@ func (p *prober) deployTriggers() { APIVersion: "v1", } if p.config.Serving.Use { - ref.APIVersion = servicesCR.GroupVersion().String() + ref.APIVersion = resources.KServicesGVR.GroupVersion().String() ref.Name = forwarderName } trigger := &v1alpha1.Trigger{ diff --git a/test/prober/forwarder.go b/test/prober/forwarder.go index afc6edb7e6e..5e54238346e 100644 --- a/test/prober/forwarder.go +++ b/test/prober/forwarder.go @@ -21,36 +21,29 @@ import ( "github.com/wavesoftware/go-ensure" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime/schema" + "knative.dev/eventing/test/lib/duck" + "knative.dev/eventing/test/lib/resources" ) var ( - servicesCR = schema.GroupVersionResource{ - Group: "serving.knative.dev", - Version: "v1alpha1", - Resource: "services", - } - servingType = metav1.TypeMeta{ - Kind: "Service", - APIVersion: servicesCR.GroupVersion().String(), - } forwarderName = "wathola-forwarder" ) func (p *prober) deployForwarder() { p.log.Infof("Deploy forwarder knative service: %v", forwarderName) - serving := p.client.Dynamic.Resource(servicesCR).Namespace(p.client.Namespace) + serving := p.client.Dynamic.Resource(resources.KServicesGVR).Namespace(p.client.Namespace) service := forwarderKService(forwarderName, p.client.Namespace) _, err := serving.Create(service, metav1.CreateOptions{}) ensure.NoError(err) + sc := p.servingClient() waitFor(fmt.Sprintf("forwarder ksvc be ready: %v", forwarderName), func() error { - return p.waitForKServiceReady(forwarderName, p.client.Namespace) + return duck.WaitForKServiceReady(sc, forwarderName, p.client.Namespace) }) if p.config.Serving.ScaleToZero { waitFor(fmt.Sprintf("forwarder scales to zero: %v", forwarderName), func() error { - return p.waitForKServiceScale(forwarderName, p.client.Namespace, func(scale int32) bool { + return duck.WaitForKServiceScales(sc, forwarderName, p.client.Namespace, func(scale int) bool { return scale == 0 }) }) @@ -59,15 +52,15 @@ func (p *prober) deployForwarder() { func (p *prober) removeForwarder() { p.log.Infof("Remove forwarder knative service: %v", forwarderName) - serving := p.client.Dynamic.Resource(servicesCR).Namespace(p.client.Namespace) + serving := p.client.Dynamic.Resource(resources.KServicesGVR).Namespace(p.client.Namespace) err := serving.Delete(forwarderName, &metav1.DeleteOptions{}) ensure.NoError(err) } func forwarderKService(name, namespace string) *unstructured.Unstructured { obj := map[string]interface{}{ - "apiVersion": servingType.APIVersion, - "kind": servingType.Kind, + "apiVersion": resources.KServiceType.APIVersion, + "kind": resources.KServiceType.Kind, "metadata": map[string]interface{}{ "name": name, "namespace": namespace, diff --git a/test/prober/prober.go b/test/prober/prober.go index 8698e8db3be..787eb4b4744 100644 --- a/test/prober/prober.go +++ b/test/prober/prober.go @@ -21,6 +21,7 @@ import ( "go.uber.org/zap" "knative.dev/eventing/test/lib" + "knative.dev/eventing/test/lib/resources" ) var ( @@ -107,6 +108,13 @@ type prober struct { config *Config } +func (p *prober) servingClient() resources.ServingClient { + return resources.ServingClient{ + Kube: p.client.Kube, + Dynamic: p.client.Dynamic, + } +} + func (p *prober) ReportError(t *testing.T, err error) { if p.config.FailOnMissingEvents { t.Error(err) From bab062a5dbce8e9f38d19b201ee46b6afdf1f19c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Thu, 27 Feb 2020 15:55:27 +0100 Subject: [PATCH 32/50] Moving group await to lib package --- test/lib/await.go | 67 ++++++++++++++++++++++++++++++++++++ test/prober/await.go | 46 ------------------------- test/prober/configuration.go | 3 +- test/prober/forwarder.go | 5 +-- test/prober/prober.go | 5 +-- test/prober/receiver.go | 3 +- test/prober/sender.go | 3 +- 7 files changed, 79 insertions(+), 53 deletions(-) create mode 100644 test/lib/await.go diff --git a/test/lib/await.go b/test/lib/await.go new file mode 100644 index 00000000000..5703240ac75 --- /dev/null +++ b/test/lib/await.go @@ -0,0 +1,67 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package lib + +import ( + "time" + + "go.uber.org/zap" + "golang.org/x/sync/errgroup" +) + +// WaitFor will register a wait routine to be resolved later +func WaitFor(name string, routine AwaitRoutine) { + w := &namedAwait{ + name: name, + routine: routine, + } + waits = append(waits, w) +} + +// AwaitForAll will wait until all registered wait routines resolves +func AwaitForAll(log *zap.SugaredLogger) error { + var g errgroup.Group + for _, w := range waits { + w := w // https://golang.org/doc/faq#closures_and_goroutines + g.Go(func() error { + log.Infof("Wait for %s", w.name) + before := time.Now() + err := w.routine() + took := time.Now().Sub(before) + if err != nil { + log.Errorf("Error while waiting for %s: %v", w.name, err) + } else { + log.Infof("Successful wait for %s, took %v to complete", w.name, took) + } + return err + }) + } + waits = nil + // Wait for all waits to complete. + if err := g.Wait(); err != nil { + return err + } + return nil +} + +type AwaitRoutine func() error + +type namedAwait struct { + name string + routine AwaitRoutine +} + +var waits []*namedAwait diff --git a/test/prober/await.go b/test/prober/await.go index 2474afe2ba8..a42a96f170d 100644 --- a/test/prober/await.go +++ b/test/prober/await.go @@ -16,11 +16,6 @@ package prober import ( - "errors" - "time" - - "go.uber.org/zap" - "golang.org/x/sync/errgroup" "knative.dev/eventing/test/lib" "knative.dev/eventing/test/lib/duck" "knative.dev/eventing/test/lib/resources" @@ -30,44 +25,3 @@ func (p *prober) waitForTriggerReady(name, namespace string) error { meta := resources.NewMetaResource(name, namespace, lib.TriggerTypeMeta) return duck.WaitForResourceReady(p.client.Dynamic, meta) } - -type namedAwait struct { - name string - routine awaitRoutine -} - -type awaitRoutine func() error - -var waits []*namedAwait - -func awaitAll(log *zap.SugaredLogger) { - var g errgroup.Group - for _, w := range waits { - w := w // https://golang.org/doc/faq#closures_and_goroutines - g.Go(func() error { - log.Infof("Wait for %s", w.name) - before := time.Now() - err := w.routine() - took := time.Now().Sub(before) - if err != nil { - log.Errorf("Error while waiting for %s: %v", w.name, err) - } else { - log.Infof("Successful wait for %s, took %v to complete", w.name, took) - } - return err - }) - } - waits = nil - // Wait for all waits to complete. - if err := g.Wait(); err != nil { - panic(errors.New("there ware errors on waiting")) - } -} - -func waitFor(name string, routine awaitRoutine) { - w := &namedAwait{ - name: name, - routine: routine, - } - waits = append(waits, w) -} diff --git a/test/prober/configuration.go b/test/prober/configuration.go index 0c5f811f7ad..9c2e4d758c3 100644 --- a/test/prober/configuration.go +++ b/test/prober/configuration.go @@ -27,6 +27,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/eventing/pkg/apis/eventing/v1alpha1" + "knative.dev/eventing/test/lib" "knative.dev/eventing/test/lib/resources" duckv1 "knative.dev/pkg/apis/duck/v1" ) @@ -113,7 +114,7 @@ func (p *prober) deployTriggers() { _, err := p.client.Eventing.EventingV1alpha1().Triggers(p.config.Namespace). Create(trigger) ensure.NoError(err) - waitFor(fmt.Sprintf("trigger be ready: %v", name), func() error { + lib.WaitFor(fmt.Sprintf("trigger be ready: %v", name), func() error { return p.waitForTriggerReady(name, p.config.Namespace) }) } diff --git a/test/prober/forwarder.go b/test/prober/forwarder.go index 5e54238346e..eb944cc9eff 100644 --- a/test/prober/forwarder.go +++ b/test/prober/forwarder.go @@ -21,6 +21,7 @@ import ( "github.com/wavesoftware/go-ensure" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "knative.dev/eventing/test/lib" "knative.dev/eventing/test/lib/duck" "knative.dev/eventing/test/lib/resources" ) @@ -37,12 +38,12 @@ func (p *prober) deployForwarder() { ensure.NoError(err) sc := p.servingClient() - waitFor(fmt.Sprintf("forwarder ksvc be ready: %v", forwarderName), func() error { + lib.WaitFor(fmt.Sprintf("forwarder ksvc be ready: %v", forwarderName), func() error { return duck.WaitForKServiceReady(sc, forwarderName, p.client.Namespace) }) if p.config.Serving.ScaleToZero { - waitFor(fmt.Sprintf("forwarder scales to zero: %v", forwarderName), func() error { + lib.WaitFor(fmt.Sprintf("forwarder scales to zero: %v", forwarderName), func() error { return duck.WaitForKServiceScales(sc, forwarderName, p.client.Namespace, func(scale int) bool { return scale == 0 }) diff --git a/test/prober/prober.go b/test/prober/prober.go index 787eb4b4744..61880629ab0 100644 --- a/test/prober/prober.go +++ b/test/prober/prober.go @@ -19,6 +19,7 @@ import ( "testing" "time" + "github.com/wavesoftware/go-ensure" "go.uber.org/zap" "knative.dev/eventing/test/lib" "knative.dev/eventing/test/lib/resources" @@ -130,10 +131,10 @@ func (p *prober) deploy() { if p.config.Serving.Use { p.deployForwarder() } - awaitAll(p.log) + ensure.NoError(lib.AwaitForAll(p.log)) p.deploySender() - awaitAll(p.log) + ensure.NoError(lib.AwaitForAll(p.log)) // allow sender to send at least some events, 2 sec wait time.Sleep(2 * time.Second) p.log.Infof("Prober is now sending events with interval of %v in "+ diff --git a/test/prober/receiver.go b/test/prober/receiver.go index a22b62fee4b..c1c554c9350 100644 --- a/test/prober/receiver.go +++ b/test/prober/receiver.go @@ -22,6 +22,7 @@ import ( corev1 "k8s.io/api/core/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" + "knative.dev/eventing/test/lib" "knative.dev/pkg/test" ) @@ -87,7 +88,7 @@ func (p *prober) deployReceiverPod() { _, err := p.client.Kube.CreatePod(pod) ensure.NoError(err) - waitFor(fmt.Sprintf("receiver be ready: %v", receiverName), func() error { + lib.WaitFor(fmt.Sprintf("receiver be ready: %v", receiverName), func() error { return test.WaitForPodRunning(p.client.Kube, receiverName, p.client.Namespace) }) } diff --git a/test/prober/sender.go b/test/prober/sender.go index 16f7357c32c..fe1ceffd86f 100644 --- a/test/prober/sender.go +++ b/test/prober/sender.go @@ -21,6 +21,7 @@ import ( "github.com/wavesoftware/go-ensure" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/eventing/test/lib" "knative.dev/pkg/test" ) @@ -63,7 +64,7 @@ func (p *prober) deploySender() { Create(pod) ensure.NoError(err) - waitFor(fmt.Sprintf("sender pod be ready: %v", senderName), func() error { + lib.WaitFor(fmt.Sprintf("sender pod be ready: %v", senderName), func() error { return test.WaitForPodRunning(p.client.Kube, senderName, p.client.Namespace) }) } From e6a1b40624ffe07a80c22868bee5a65ed56b5009 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Thu, 27 Feb 2020 16:19:34 +0100 Subject: [PATCH 33/50] Create triggers with resource builders --- test/prober/await.go | 27 --------------------- test/prober/configuration.go | 46 ++++++++++++++---------------------- 2 files changed, 18 insertions(+), 55 deletions(-) delete mode 100644 test/prober/await.go diff --git a/test/prober/await.go b/test/prober/await.go deleted file mode 100644 index a42a96f170d..00000000000 --- a/test/prober/await.go +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2020 The Knative 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. - */ - -package prober - -import ( - "knative.dev/eventing/test/lib" - "knative.dev/eventing/test/lib/duck" - "knative.dev/eventing/test/lib/resources" -) - -func (p *prober) waitForTriggerReady(name, namespace string) error { - meta := resources.NewMetaResource(name, namespace, lib.TriggerTypeMeta) - return duck.WaitForResourceReady(p.client.Dynamic, meta) -} diff --git a/test/prober/configuration.go b/test/prober/configuration.go index 9c2e4d758c3..4d43434dc8a 100644 --- a/test/prober/configuration.go +++ b/test/prober/configuration.go @@ -28,8 +28,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/eventing/pkg/apis/eventing/v1alpha1" "knative.dev/eventing/test/lib" + "knative.dev/eventing/test/lib/duck" "knative.dev/eventing/test/lib/resources" - duckv1 "knative.dev/pkg/apis/duck/v1" ) const ( @@ -84,38 +84,28 @@ func (p *prober) deployTriggers() { for _, eventType := range eventTypes { name := fmt.Sprintf("wathola-trigger-%v", eventType) fullType := fmt.Sprintf("%v.%v", watholaEventNs, eventType) - ref := &duckv1.KReference{ - Kind: "Service", - Namespace: p.config.Namespace, - Name: receiverName, - APIVersion: "v1", - } + subscriberOption := resources.WithSubscriberServiceRefForTrigger(receiverName) if p.config.Serving.Use { - ref.APIVersion = resources.KServicesGVR.GroupVersion().String() - ref.Name = forwarderName - } - trigger := &v1alpha1.Trigger{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - }, - Spec: v1alpha1.TriggerSpec{ - Broker: "default", - Filter: &v1alpha1.TriggerFilter{ - Attributes: &v1alpha1.TriggerFilterAttributes{ - "type": fullType, - }, - }, - Subscriber: duckv1.Destination{ - Ref: ref, - }, - }, + subscriberOption = resources.WithSubscriberKServiceRefForTrigger(forwarderName) } + trigger := resources.Trigger( + name, + resources.WithBroker("default"), + resources.WithAttributesTriggerFilter( + v1alpha1.TriggerAnyFilter, + fullType, + map[string]interface{}{}, + ), + subscriberOption, + ) + triggers := p.client.Eventing.EventingV1alpha1().Triggers(p.config.Namespace) p.log.Infof("Deploying trigger: %v", name) - _, err := p.client.Eventing.EventingV1alpha1().Triggers(p.config.Namespace). - Create(trigger) + // update trigger with the new reference + _, err := triggers.Create(trigger) ensure.NoError(err) lib.WaitFor(fmt.Sprintf("trigger be ready: %v", name), func() error { - return p.waitForTriggerReady(name, p.config.Namespace) + meta := resources.NewMetaResource(name, p.config.Namespace, lib.TriggerTypeMeta) + return duck.WaitForResourceReady(p.client.Dynamic, meta) }) } } From e9ba06a6dd593629b52a77e2378dac132db04b84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Thu, 27 Feb 2020 18:29:24 +0100 Subject: [PATCH 34/50] Add comment about wathola version --- test/prober/prober.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/prober/prober.go b/test/prober/prober.go index 61880629ab0..f7e271eebcf 100644 --- a/test/prober/prober.go +++ b/test/prober/prober.go @@ -26,7 +26,9 @@ import ( ) var ( + // Version is a version of wathola tool version that is built outside of eventing Version = "v0.7.0" + // FIXME: Interval is set to 200 msec, as lower values will result in errors // https://github.com/knative/eventing/issues/2357 // Interval = 10 * time.Millisecond From e4049a913335f14584e7aae4fa8b73e2d261aad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Thu, 27 Feb 2020 19:23:38 +0100 Subject: [PATCH 35/50] Warn with FAIL to trigger reporting on Prow --- test/prober/prober.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/prober/prober.go b/test/prober/prober.go index f7e271eebcf..510b49b4375 100644 --- a/test/prober/prober.go +++ b/test/prober/prober.go @@ -122,7 +122,7 @@ func (p *prober) ReportError(t *testing.T, err error) { if p.config.FailOnMissingEvents { t.Error(err) } else { - p.log.Warn(err) + p.log.Warnf("Silenced FAIL: %v", err) } } From daed3c359f4ee6e9609b38dc5767fbe8e07742b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Thu, 27 Feb 2020 22:57:58 +0100 Subject: [PATCH 36/50] Fixing issues with scripts --- test/e2e-common.sh | 23 +++++++++++-------- test/e2e-upgrade-tests.sh | 11 +++++---- test/scripts/resolve_matching_release.go | 10 +++++++- test/scripts/resolve_matching_release_test.go | 20 ++++++++++++++++ third_party/istio-1.4-latest | 1 - third_party/istio-latest | 1 - 6 files changed, 48 insertions(+), 18 deletions(-) delete mode 120000 third_party/istio-1.4-latest delete mode 120000 third_party/istio-latest diff --git a/test/e2e-common.sh b/test/e2e-common.sh index 72769ce6a3a..fdc3e35049a 100755 --- a/test/e2e-common.sh +++ b/test/e2e-common.sh @@ -42,9 +42,8 @@ UNINSTALL_LIST=() # Install Knative Eventing in the current cluster, and waits for it to be ready. # If no parameters are passed, installs the current source-based build. # Parameters: $1 - Knative Eventing YAML file -# $2 - Knative Monitoring YAML file (optional) function install_knative_eventing { - local knative_networking_pods + local knative_monitoring_pods knative_monitoring_version monitoring_yaml local INSTALL_RELEASE_YAML=$1 echo ">> Installing Knative Eventing" if [[ -z "$1" ]]; then @@ -54,15 +53,20 @@ function install_knative_eventing { fi wait_until_pods_running knative-eventing || fail_test "Knative Eventing did not come up" + knative_monitoring_version=$(go run test/scripts/resolve_matching_release.go \ + 'knative/serving' "${LATEST_RELEASE_VERSION}") \ + || fail_test 'Could not resolve knative monitoring version' + # Ensure knative monitoring is installed only once - knative_networking_pods=$(kubectl get pods -n knative-monitoring \ + knative_monitoring_pods=$(kubectl get pods -n knative-monitoring \ --field-selector status.phase=Running 2> /dev/null | tail -n +2 | wc -l) - if ! [[ ${knative_networking_pods} -gt 0 ]]; then - echo ">> Installing Knative Monitoring" - start_knative_monitoring "${KNATIVE_MONITORING_RELEASE}" || fail_test "Knative Monitoring did not come up" - UNINSTALL_LIST+=( "${KNATIVE_MONITORING_RELEASE}" ) + if ! [[ ${knative_monitoring_pods} -gt 0 ]]; then + echo ">> Installing Knative Monitoring: ${knative_monitoring_version}" + monitoring_yaml="https://github.com/knative/serving/releases/download/${knative_monitoring_version}/monitoring.yaml" + start_knative_monitoring "${monitoring_yaml}" || fail_test "Knative Monitoring did not come up" + UNINSTALL_LIST+=( "${monitoring_yaml}" ) else - echo ">> Knative Monitoring seems to be running, pods running: ${knative_networking_pods}." + echo ">> Knative Monitoring seems to be running, pods running: ${knative_monitoring_pods}." fi } @@ -179,7 +183,7 @@ function dump_extra_cluster_state() { function install_istio { if [[ -z "${ISTIO_VERSION}" ]]; then - readonly ISTIO_VERSION="latest" + readonly ISTIO_VERSION="1.4.3" fi echo ">> Installing Istio: ${ISTIO_VERSION}" @@ -203,7 +207,6 @@ function install_istio { # Installs Knative Serving in the current cluster, and waits for it to be ready. function install_knative_serving { - install_istio echo ">> Installing Knative serving" local SERVING_VERSION SERVING_VERSION=$(go run test/scripts/resolve_matching_release.go \ diff --git a/test/e2e-upgrade-tests.sh b/test/e2e-upgrade-tests.sh index aae79d087ea..d5b782e9ebd 100755 --- a/test/e2e-upgrade-tests.sh +++ b/test/e2e-upgrade-tests.sh @@ -23,8 +23,9 @@ source "$(dirname "$0")/e2e-common.sh" # Overrides function knative_setup { - install_knative_serving - install_latest_release + install_istio || fail_test 'Installing Istio failed' + install_knative_serving || fail_test 'Installing Knative Serving failed' + install_latest_release || fail_test 'Installing latest release of Knative Eventing failed' } function install_test_resources { @@ -54,14 +55,14 @@ echo "Prober PID is ${PROBER_PID}" wait_for_file /tmp/prober-ready || fail_test header "Performing upgrade to HEAD" -install_head || return $? -install_channel_crds || return $? +install_head || fail_test 'Installing HEAD version of eventing failed' +install_channel_crds || fail_test 'Installing HEAD channel CRDs failed' header "Running postupgrade tests" go_test_e2e -tags=postupgrade -timeout="${TIMEOUT}" ./test/upgrade || fail_test header "Performing downgrade to latest release" -install_latest_release +install_latest_release || fail_test 'Installing latest release of Knative Eventing failed' header "Running postdowngrade tests" go_test_e2e -tags=postdowngrade -timeout="${TIMEOUT}" ./test/upgrade || fail_test diff --git a/test/scripts/resolve_matching_release.go b/test/scripts/resolve_matching_release.go index 76244b89947..39f45db3431 100644 --- a/test/scripts/resolve_matching_release.go +++ b/test/scripts/resolve_matching_release.go @@ -60,6 +60,7 @@ type Tag struct { } func resolveMatchingRelease(repo, version string) string { + version = prependV(version) endpoint := fmt.Sprintf("%s/repos/%s/tags", ApiGateway, repo) resp, err := http.Get(endpoint) ensure.NoError(err) @@ -88,11 +89,18 @@ func resolveMatchingRelease(repo, version string) string { func slurpVersions(tags []Tag) []string { var res []string for _, tag := range tags { - res = append(res, tag.Name) + res = append(res, prependV(tag.Name)) } return res } +func prependV(version string) string { + if version[0] != 'v' { + return "v" + version + } + return version +} + func filterMatchingVersions(version string, versions []string, strict bool) []string { matcher := semverMatcher(version, strict) var matching []string diff --git a/test/scripts/resolve_matching_release_test.go b/test/scripts/resolve_matching_release_test.go index c9d0631aac3..78d7ec4953f 100644 --- a/test/scripts/resolve_matching_release_test.go +++ b/test/scripts/resolve_matching_release_test.go @@ -38,3 +38,23 @@ func TestResolveMatchingReleaseOurAhead(t *testing.T) { t.Errorf("resolved invalid version: %s", resolved) } } + +func TestResolveIstioRelease(t *testing.T) { + candidate := "v1.4.0" + repo := "istio/istio" + resolved := resolveMatchingRelease(repo, candidate) + + if semver.Compare(resolved, "v1.4.0") < 0 || semver.Compare(resolved, "v1.5.0") >= 0{ + t.Errorf("resolved invalid version: %s", resolved) + } +} + +func TestResolveIstioReleaseWithoutV(t *testing.T) { + candidate := "1.4.0" + repo := "istio/istio" + resolved := resolveMatchingRelease(repo, candidate) + + if semver.Compare(resolved, "v1.4.0") < 0 || semver.Compare(resolved, "v1.5.0") >= 0{ + t.Errorf("resolved invalid version: %s", resolved) + } +} diff --git a/third_party/istio-1.4-latest b/third_party/istio-1.4-latest deleted file mode 120000 index 735b5e98785..00000000000 --- a/third_party/istio-1.4-latest +++ /dev/null @@ -1 +0,0 @@ -istio-1.4.3 \ No newline at end of file diff --git a/third_party/istio-latest b/third_party/istio-latest deleted file mode 120000 index 04a23d20f0e..00000000000 --- a/third_party/istio-latest +++ /dev/null @@ -1 +0,0 @@ -istio-1.4-latest \ No newline at end of file From bd308bdedccdb428002f24fc91e53b94c24bb112 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Fri, 28 Feb 2020 13:03:36 +0100 Subject: [PATCH 37/50] Move nodes resolver code in preparation for native/pkg#1001 merger --- Gopkg.lock | 1 + test/lib/nodes/address.go | 68 +++++++++++++++++++++++ test/lib/nodes/address_test.go | 79 +++++++++++++++++++++++++++ test/lib/nodes/kind.go | 47 ++++++++++++++++ test/lib/nodes/logger_test.go | 32 +++++++++++ test/lib/nodes/nodes.go | 69 ++++++++++++++++++++++++ test/lib/nodes/nodes_test.go | 99 ++++++++++++++++++++++++++++++++++ test/prober/verify.go | 89 ++++-------------------------- 8 files changed, 406 insertions(+), 78 deletions(-) create mode 100644 test/lib/nodes/address.go create mode 100644 test/lib/nodes/address_test.go create mode 100644 test/lib/nodes/kind.go create mode 100644 test/lib/nodes/logger_test.go create mode 100644 test/lib/nodes/nodes.go create mode 100644 test/lib/nodes/nodes_test.go diff --git a/Gopkg.lock b/Gopkg.lock index 770c20e5830..e771ca5d4bb 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1483,6 +1483,7 @@ "go.opencensus.io/trace", "go.uber.org/atomic", "go.uber.org/zap", + "go.uber.org/zap/zapcore", "golang.org/x/sync/errgroup", "google.golang.org/grpc", "google.golang.org/grpc/codes", diff --git a/test/lib/nodes/address.go b/test/lib/nodes/address.go new file mode 100644 index 00000000000..6512ac9e36b --- /dev/null +++ b/test/lib/nodes/address.go @@ -0,0 +1,68 @@ +/* + * Copyright 2020 The Knative 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. + */ + +// TODO(ksuszyns): remove the whole package after knative/pkg#1001 is merged + +package nodes + +import ( + "sort" + + corev1 "k8s.io/api/core/v1" +) + +// GuessNodeExternalAddress tries to guess external address of a node +func (n *NodesClient) GuessNodeExternalAddress(node *corev1.Node) *corev1.NodeAddress { + sorted := make([]*corev1.NodeAddress, len(node.Status.Addresses)) + for i := 0; i < len(node.Status.Addresses); i++ { + sorted[i] = &node.Status.Addresses[i] + } + sort.Sort(byAddressType{sorted}) + first := sorted[0] + priority := addressTypePriority[first.Type] + if priority >= 2 { + n.logger.Warnf("Chosen address is probably an internal type: %s, "+ + "and might be unaccessible", first.Type) + } + return first +} + +type nodeAddresses []*corev1.NodeAddress + +type byAddressType struct { + nodeAddresses +} + +func (s byAddressType) Len() int { + return len(s.nodeAddresses) +} + +func (s byAddressType) Swap(i, j int) { + s.nodeAddresses[i], s.nodeAddresses[j] = s.nodeAddresses[j], s.nodeAddresses[i] +} + +func (s byAddressType) Less(i, j int) bool { + return addressTypePriority[s.nodeAddresses[i].Type] < + addressTypePriority[s.nodeAddresses[j].Type] +} + +var addressTypePriority = map[corev1.NodeAddressType]int{ + corev1.NodeExternalDNS: 0, + corev1.NodeExternalIP: 1, + corev1.NodeInternalIP: 2, + corev1.NodeInternalDNS: 3, + corev1.NodeHostName: 4, +} diff --git a/test/lib/nodes/address_test.go b/test/lib/nodes/address_test.go new file mode 100644 index 00000000000..1718c59fa6f --- /dev/null +++ b/test/lib/nodes/address_test.go @@ -0,0 +1,79 @@ +/* + * Copyright 2020 The Knative 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. + */ + +// TODO(ksuszyns): remove the whole package after knative/pkg#1001 is merged + +package nodes + +import ( + "testing" + + corev1 "k8s.io/api/core/v1" + kubernetesfake "k8s.io/client-go/kubernetes/fake" +) + +func TestNodesClientGuessNodeExternalAddress(t *testing.T) { + clientset := kubernetesfake.NewSimpleClientset() + c := Client(clientset, newLogger()) + node := &corev1.Node{ + Status: corev1.NodeStatus{ + Addresses: []corev1.NodeAddress{{ + Type: corev1.NodeInternalIP, + Address: "10.0.2.17", + }, { + Type: corev1.NodeHostName, + Address: "node-17", + }, { + Type: corev1.NodeInternalDNS, + Address: "node-17.europe3.internal", + }, { + Type: corev1.NodeExternalIP, + Address: "35.123.11.234", + }}, + }, + } + + address := c.GuessNodeExternalAddress(node) + + if address.Address != "35.123.11.234" { + t.Errorf("Address: %s want: 35.123.11.234", address.Address) + } +} + +func TestNodesClientGuessNodeExternalAddress_PrivateOnly(t *testing.T) { + clientset := kubernetesfake.NewSimpleClientset() + c := Client(clientset, newLogger()) + node := &corev1.Node{ + Status: corev1.NodeStatus{ + Addresses: []corev1.NodeAddress{{ + Type: corev1.NodeInternalIP, + Address: "10.0.2.17", + }, { + Type: corev1.NodeHostName, + Address: "node-17", + }, { + Type: corev1.NodeInternalDNS, + Address: "node-17.europe3.internal", + }}, + }, + } + + address := c.GuessNodeExternalAddress(node) + + if address.Address != "10.0.2.17" { + t.Errorf("Address: %s want: 10.0.2.17", address.Address) + } +} diff --git a/test/lib/nodes/kind.go b/test/lib/nodes/kind.go new file mode 100644 index 00000000000..7cbe5a34527 --- /dev/null +++ b/test/lib/nodes/kind.go @@ -0,0 +1,47 @@ +/* + * Copyright 2020 The Knative 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. + */ + +// TODO(ksuszyns): remove the whole package after knative/pkg#1001 is merged + +package nodes + +import ( + corev1 "k8s.io/api/core/v1" +) + +const ( + roleLabelFormat = "node-role.kubernetes.io/" +) + +// FilterOutByRole returns a new slice without nodes that have given role +func FilterOutByRole(nodes []corev1.Node, role string) []corev1.Node { + result := make([]corev1.Node, 0, len(nodes)) + for _, node := range nodes { + if !hasRole(role, node) { + result = append(result, node) + } + } + return result +} + +func hasRole(role string, node corev1.Node) bool { + if node.Labels == nil { + return false + } + label := roleLabelFormat + role + _, has := node.Labels[label] + return has +} diff --git a/test/lib/nodes/logger_test.go b/test/lib/nodes/logger_test.go new file mode 100644 index 00000000000..18928392fdf --- /dev/null +++ b/test/lib/nodes/logger_test.go @@ -0,0 +1,32 @@ +/* + * Copyright 2020 The Knative 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. + */ + +// TODO(ksuszyns): remove the whole package after knative/pkg#1001 is merged + +package nodes + +import ( + "go.uber.org/zap" + "go.uber.org/zap/zapcore" +) + +func newLogger() *zap.SugaredLogger { + z, err := zap.NewDevelopment(zap.AddStacktrace(zapcore.ErrorLevel)) + if err != nil { + panic(err) + } + return z.Sugar() +} diff --git a/test/lib/nodes/nodes.go b/test/lib/nodes/nodes.go new file mode 100644 index 00000000000..a4259eca7b2 --- /dev/null +++ b/test/lib/nodes/nodes.go @@ -0,0 +1,69 @@ +/* + * Copyright 2020 The Knative 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. + */ + +// TODO(ksuszyns): remove the whole package after knative/pkg#1001 is merged + +package nodes + +import ( + "errors" + "math/rand" + + "go.uber.org/zap" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" +) + +// NodesClient contains interface for making requests to kubernetes client. +type NodesClient struct { + kube kubernetes.Interface + logger *zap.SugaredLogger +} + +// Client creates a new nodes client +func Client(kube kubernetes.Interface, logger *zap.SugaredLogger) *NodesClient { + return &NodesClient{ + kube: kube, + logger: logger, + } +} + +// RandomWorkerNode gets a worker node randomly +func (n *NodesClient) RandomWorkerNode() (*corev1.Node, error) { + nodes, err := n.kube.CoreV1().Nodes().List(metav1.ListOptions{}) + if err != nil { + return nil, err + } + nodesCount := len(nodes.Items) + if nodesCount == 0 { + return nil, errors.New("fetched 0 nodes, so can't chose a worker") + } + if nodesCount == 1 { + node := nodes.Items[0] + n.logger.Infof("Only one node found (named: %s), returning it as"+ + " it must be a worker (Minikube, CRC)", node.Name) + return &node, nil + } else { + role := "master" + n.logger.Infof("Filtering %d nodes, to not contain role: %s", nodesCount, role) + workers := FilterOutByRole(nodes.Items, role) + n.logger.Infof("Found %d worker(s)", len(workers)) + worker := workers[rand.Intn(len(workers))] + n.logger.Infof("Chosen node: %s", worker.Name) + return &worker, nil + } +} diff --git a/test/lib/nodes/nodes_test.go b/test/lib/nodes/nodes_test.go new file mode 100644 index 00000000000..2d4c49417a1 --- /dev/null +++ b/test/lib/nodes/nodes_test.go @@ -0,0 +1,99 @@ +/* + * Copyright 2020 The Knative 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. + */ + +// TODO(ksuszyns): remove the whole package after knative/pkg#1001 is merged + +package nodes + +import ( + "testing" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + kubernetesfake "k8s.io/client-go/kubernetes/fake" +) + +func TestNodesClientRandomWorkerNode(t *testing.T) { + masterNode := &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "master-1", + Labels: map[string]string{ + roleLabelFormat + "master": "", + }, + }, + } + workerNode := &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: "worker-1", + }, + } + clientset := kubernetesfake.NewSimpleClientset(masterNode, workerNode) + c := Client(clientset, newLogger()) + + node, err := c.RandomWorkerNode() + + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + nodeName := workerNode.Name + assertProperNodeIsReturned(t, node, nodeName) +} + +func TestNodesClientRandomWorkerNode_OneNode(t *testing.T) { + nodeName := "minikube" + minikube := &corev1.Node{ + ObjectMeta: metav1.ObjectMeta{ + Name: nodeName, + Labels: map[string]string{ + roleLabelFormat + "master": "", + }, + }, + } + clientset := kubernetesfake.NewSimpleClientset(minikube) + c := Client(clientset, newLogger()) + + node, err := c.RandomWorkerNode() + + if err != nil { + t.Fatalf("Unexpected error: %v", err) + } + assertProperNodeIsReturned(t, node, nodeName) +} + +func TestNodesClientRandomWorkerNode_NoNode(t *testing.T) { + clientset := kubernetesfake.NewSimpleClientset() + c := Client(clientset, newLogger()) + + _, err := c.RandomWorkerNode() + + if err == nil { + t.Fatal("Expected error, but not received") + } + actual := err.Error() + if actual != "fetched 0 nodes, so can't chose a worker" { + t.Errorf("Unexpected error: %s", actual) + } +} + +func assertProperNodeIsReturned(t *testing.T, node *corev1.Node, nodeName string) { + t.Helper() + if node == nil { + t.Fatal("Expect not to be nil") + } + if node.Name != nodeName { + t.Errorf("Got = %v, want: %s", node, nodeName) + } +} diff --git a/test/prober/verify.go b/test/prober/verify.go index d7e9de9593b..7db5f69a434 100644 --- a/test/prober/verify.go +++ b/test/prober/verify.go @@ -20,19 +20,22 @@ import ( "encoding/json" "errors" "fmt" - "math/rand" "net/http" - "sort" "strings" "github.com/wavesoftware/go-ensure" + "go.uber.org/zap" corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/eventing/test/lib/nodes" ) func (p *prober) Verify() ([]error, int) { - hostname := p.figureOutClusterHostname() - report := p.fetchReceiverReport(hostname) + nc := nodes.Client(p.client.Kube.Kube, p.log) + node, err := nc.RandomWorkerNode() + ensure.NoError(err) + address := nc.GuessNodeExternalAddress(node) + p.log.Debugf("Address resolved: %v, type: %v", address.Address, address.Type) + report := fetchReceiverReport(address, p.log) p.log.Infof("Fetched receiver report. Events propagated: %v. "+ "State: %v", report.Events, report.State) if report.State == "active" { @@ -49,79 +52,9 @@ func (p *prober) Finish() { p.removeSender() } -type nodeAddresses []*corev1.NodeAddress - -type byAddressType struct { - nodeAddresses -} - -func (s byAddressType) Len() int { - return len(s.nodeAddresses) -} - -func (s byAddressType) Swap(i, j int) { - s.nodeAddresses[i], s.nodeAddresses[j] = s.nodeAddresses[j], s.nodeAddresses[i] -} - -func (s byAddressType) Less(i, j int) bool { - return addressTypeToPriority(s.nodeAddresses[i]) < addressTypeToPriority(s.nodeAddresses[j]) -} - -var addressTypeToPriorities = map[corev1.NodeAddressType]int{ - corev1.NodeExternalDNS: 0, - corev1.NodeExternalIP: 1, - corev1.NodeInternalIP: 2, - corev1.NodeInternalDNS: 3, - corev1.NodeHostName: 4, -} - -func (p *prober) figureOutClusterHostname() string { - nodes, err := p.client.Kube.Kube.CoreV1().Nodes().List(metav1.ListOptions{}) - ensure.NoError(err) - if len(nodes.Items) == 1 { - node := nodes.Items[0] - return p.nodeExternalAddress(node) - } else { - workers := p.filterOutMasters(nodes.Items) - worker := workers[rand.Intn(len(workers))] - return p.nodeExternalAddress(worker) - } -} - -func (p *prober) nodeExternalAddress(node corev1.Node) string { - return p.prioritizeAddresses(node.Status.Addresses)[0].Address -} - -func (p *prober) prioritizeAddresses(addresses []corev1.NodeAddress) []*corev1.NodeAddress { - result := make([]*corev1.NodeAddress, 0) - for i := 0; i < len(addresses); i++ { - result = append(result, &addresses[i]) - } - sort.Sort(byAddressType{result}) - return result -} - -func addressTypeToPriority(address *corev1.NodeAddress) int { - return addressTypeToPriorities[address.Type] -} - -func (p *prober) filterOutMasters(nodes []corev1.Node) []corev1.Node { - result := make([]corev1.Node, 0) - for _, node := range nodes { - if node.Labels == nil { - result = append(result, node) - continue - } - if _, ok := node.Labels["node-role.kubernetes.io/master"]; !ok { - result = append(result, node) - } - } - return result -} - -func (p *prober) fetchReceiverReport(hostname string) *Report { - u := fmt.Sprintf("http://%s:%d/report", hostname, receiverNodePort) - p.log.Infof("Fetching receiver report at: %v", u) +func fetchReceiverReport(address *corev1.NodeAddress, log *zap.SugaredLogger) *Report { + u := fmt.Sprintf("http://%s:%d/report", address.Address, receiverNodePort) + log.Infof("Fetching receiver report from: %v", u) resp, err := http.Get(u) ensure.NoError(err) if resp.StatusCode != 200 { From e7d49fab944b22008125773f60cece5e8f4a039b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Fri, 28 Feb 2020 13:12:59 +0100 Subject: [PATCH 38/50] Add notice about wathola donation --- test/prober/prober.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/prober/prober.go b/test/prober/prober.go index 510b49b4375..17a058ba636 100644 --- a/test/prober/prober.go +++ b/test/prober/prober.go @@ -27,10 +27,10 @@ import ( var ( // Version is a version of wathola tool version that is built outside of eventing + // TODO(ksuszyns): Donate a wathola tool to this repo, as discussed in knative/test-infra#1631 Version = "v0.7.0" - // FIXME: Interval is set to 200 msec, as lower values will result in errors - // https://github.com/knative/eventing/issues/2357 + // FIXME: Interval is set to 200 msec, as lower values will result in errors: knative/eventing#2357 // Interval = 10 * time.Millisecond Interval = 200 * time.Millisecond ) From 95cb9c28bc9a5a6616b0f64db5d4cbaa99edaa08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Fri, 28 Feb 2020 15:34:18 +0100 Subject: [PATCH 39/50] Donation of wathola testing tool The wathola testing tool was develop to make testing of eventing upgrade tests possible. At first it was developed separately, and published with versioning on https://quay.io/repository/cardil/wathola-*. It was done that way to ease of use of the eventing prober in different context, like eventing operator or knative vendor tests. Then it was propose to donate that tool to knative. In knative/test-infra#1631 discussion it was decided to donate it directly to knative/eventing. --- Gopkg.lock | 44 + test/prober/configuration.go | 2 +- test/prober/forwarder.go | 3 +- test/prober/prober.go | 4 - test/prober/receiver.go | 16 +- test/prober/sender.go | 6 +- test/prober/wathola/README.md | 3 + test/prober/wathola/client/receiver.go | 95 + test/prober/wathola/config/defaults.go | 74 + test/prober/wathola/config/defaults_test.go | 29 + test/prober/wathola/config/logger.go | 32 + test/prober/wathola/config/reader.go | 64 + test/prober/wathola/config/reader_test.go | 98 + test/prober/wathola/config/structure.go | 69 + test/prober/wathola/event/operations.go | 34 + test/prober/wathola/event/services.go | 162 ++ test/prober/wathola/event/services_test.go | 79 + test/prober/wathola/event/types.go | 59 + test/prober/wathola/event/types_test.go | 34 + test/prober/wathola/forwarder/operations.go | 21 + test/prober/wathola/forwarder/services.go | 77 + test/prober/wathola/receiver/operations.go | 21 + test/prober/wathola/receiver/services.go | 144 ++ test/prober/wathola/receiver/services_test.go | 64 + test/prober/wathola/sender/operations.go | 55 + test/prober/wathola/sender/services.go | 115 ++ test/prober/wathola/sender/types.go | 21 + test/test_images/wathola-forwarder/main.go | 10 + .../wathola-forwarder/main_test.go | 21 + test/test_images/wathola-forwarder/pod.yaml | 8 + test/test_images/wathola-receiver/main.go | 10 + .../test_images/wathola-receiver/main_test.go | 22 + test/test_images/wathola-receiver/pod.yaml | 8 + test/test_images/wathola-sender/main.go | 7 + test/test_images/wathola-sender/main_test.go | 17 + test/test_images/wathola-sender/pod.yaml | 8 + third_party/VENDOR-LICENSE | 54 + .../github.com/mitchellh/go-homedir/LICENSE | 21 + .../mitchellh/go-homedir/homedir.go | 167 ++ vendor/github.com/pelletier/go-toml/LICENSE | 21 + vendor/github.com/pelletier/go-toml/doc.go | 23 + vendor/github.com/pelletier/go-toml/fuzz.go | 31 + .../pelletier/go-toml/keysparsing.go | 113 ++ vendor/github.com/pelletier/go-toml/lexer.go | 780 ++++++++ .../github.com/pelletier/go-toml/localtime.go | 281 +++ .../github.com/pelletier/go-toml/marshal.go | 868 +++++++++ vendor/github.com/pelletier/go-toml/parser.go | 479 +++++ .../github.com/pelletier/go-toml/position.go | 29 + vendor/github.com/pelletier/go-toml/token.go | 137 ++ vendor/github.com/pelletier/go-toml/toml.go | 393 ++++ .../pelletier/go-toml/tomltree_create.go | 142 ++ .../pelletier/go-toml/tomltree_write.go | 475 +++++ vendor/github.com/phayes/freeport/LICENSE.md | 15 + vendor/github.com/phayes/freeport/freeport.go | 30 + vendor/github.com/pmezard/go-difflib/LICENSE | 27 + .../pmezard/go-difflib/difflib/difflib.go | 772 ++++++++ vendor/github.com/stretchr/testify/LICENSE | 21 + .../testify/assert/assertion_format.go | 622 +++++++ .../testify/assert/assertion_forward.go | 1232 +++++++++++++ .../testify/assert/assertion_order.go | 309 ++++ .../stretchr/testify/assert/assertions.go | 1626 +++++++++++++++++ .../github.com/stretchr/testify/assert/doc.go | 45 + .../stretchr/testify/assert/errors.go | 10 + .../testify/assert/forward_assertions.go | 16 + .../testify/assert/http_assertions.go | 143 ++ 65 files changed, 10401 insertions(+), 17 deletions(-) create mode 100644 test/prober/wathola/README.md create mode 100644 test/prober/wathola/client/receiver.go create mode 100644 test/prober/wathola/config/defaults.go create mode 100644 test/prober/wathola/config/defaults_test.go create mode 100644 test/prober/wathola/config/logger.go create mode 100644 test/prober/wathola/config/reader.go create mode 100644 test/prober/wathola/config/reader_test.go create mode 100644 test/prober/wathola/config/structure.go create mode 100644 test/prober/wathola/event/operations.go create mode 100644 test/prober/wathola/event/services.go create mode 100644 test/prober/wathola/event/services_test.go create mode 100644 test/prober/wathola/event/types.go create mode 100644 test/prober/wathola/event/types_test.go create mode 100644 test/prober/wathola/forwarder/operations.go create mode 100644 test/prober/wathola/forwarder/services.go create mode 100644 test/prober/wathola/receiver/operations.go create mode 100644 test/prober/wathola/receiver/services.go create mode 100644 test/prober/wathola/receiver/services_test.go create mode 100644 test/prober/wathola/sender/operations.go create mode 100644 test/prober/wathola/sender/services.go create mode 100644 test/prober/wathola/sender/types.go create mode 100644 test/test_images/wathola-forwarder/main.go create mode 100644 test/test_images/wathola-forwarder/main_test.go create mode 100644 test/test_images/wathola-forwarder/pod.yaml create mode 100644 test/test_images/wathola-receiver/main.go create mode 100644 test/test_images/wathola-receiver/main_test.go create mode 100644 test/test_images/wathola-receiver/pod.yaml create mode 100644 test/test_images/wathola-sender/main.go create mode 100644 test/test_images/wathola-sender/main_test.go create mode 100644 test/test_images/wathola-sender/pod.yaml create mode 100644 vendor/github.com/mitchellh/go-homedir/LICENSE create mode 100644 vendor/github.com/mitchellh/go-homedir/homedir.go create mode 100644 vendor/github.com/pelletier/go-toml/LICENSE create mode 100644 vendor/github.com/pelletier/go-toml/doc.go create mode 100644 vendor/github.com/pelletier/go-toml/fuzz.go create mode 100644 vendor/github.com/pelletier/go-toml/keysparsing.go create mode 100644 vendor/github.com/pelletier/go-toml/lexer.go create mode 100644 vendor/github.com/pelletier/go-toml/localtime.go create mode 100644 vendor/github.com/pelletier/go-toml/marshal.go create mode 100644 vendor/github.com/pelletier/go-toml/parser.go create mode 100644 vendor/github.com/pelletier/go-toml/position.go create mode 100644 vendor/github.com/pelletier/go-toml/token.go create mode 100644 vendor/github.com/pelletier/go-toml/toml.go create mode 100644 vendor/github.com/pelletier/go-toml/tomltree_create.go create mode 100644 vendor/github.com/pelletier/go-toml/tomltree_write.go create mode 100644 vendor/github.com/phayes/freeport/LICENSE.md create mode 100644 vendor/github.com/phayes/freeport/freeport.go create mode 100644 vendor/github.com/pmezard/go-difflib/LICENSE create mode 100644 vendor/github.com/pmezard/go-difflib/difflib/difflib.go create mode 100644 vendor/github.com/stretchr/testify/LICENSE create mode 100644 vendor/github.com/stretchr/testify/assert/assertion_format.go create mode 100644 vendor/github.com/stretchr/testify/assert/assertion_forward.go create mode 100644 vendor/github.com/stretchr/testify/assert/assertion_order.go create mode 100644 vendor/github.com/stretchr/testify/assert/assertions.go create mode 100644 vendor/github.com/stretchr/testify/assert/doc.go create mode 100644 vendor/github.com/stretchr/testify/assert/errors.go create mode 100644 vendor/github.com/stretchr/testify/assert/forward_assertions.go create mode 100644 vendor/github.com/stretchr/testify/assert/http_assertions.go diff --git a/Gopkg.lock b/Gopkg.lock index e771ca5d4bb..10829e69a7f 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -424,6 +424,14 @@ revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c" version = "v1.0.1" +[[projects]] + digest = "1:f9f72e583aaacf1d1ac5d6121abd4afd3c690baa9e14e1d009df26bf831ba347" + name = "github.com/mitchellh/go-homedir" + packages = ["."] + pruneopts = "NUT" + revision = "af06845cf3004701891bf4fdb884bfe4920b3727" + version = "v1.1.0" + [[projects]] digest = "1:2f42fa12d6911c7b7659738758631bec870b7e9b4c6be5444f963cdcfccc191f" name = "github.com/modern-go/concurrent" @@ -455,6 +463,22 @@ revision = "c29478e51bfb2e9c93e0e9f5e015e5993a490399" version = "v0.2.2" +[[projects]] + digest = "1:efec7b15c9f6f20c96a5710fea5d946aabf13018d9e2d2c50a4746f850514f9d" + name = "github.com/pelletier/go-toml" + packages = ["."] + pruneopts = "NUT" + revision = "903d9455db9ff1d7ac1ab199062eca7266dd11a3" + version = "v1.6.0" + +[[projects]] + digest = "1:d3ed3beb4c8434d4b8a8ac7696128c2c1e5ca96c720df78447b7b1ccbd7b0f92" + name = "github.com/phayes/freeport" + packages = ["."] + pruneopts = "NUT" + revision = "b8543db493a5ed890c5499e935e2cad7504f3a04" + version = "1.0.2" + [[projects]] digest = "1:14715f705ff5dfe0ffd6571d7d201dd8e921030f8070321a79380d8ca4ec1a24" name = "github.com/pkg/errors" @@ -463,6 +487,14 @@ revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4" version = "v0.8.1" +[[projects]] + digest = "1:0028cb19b2e4c3112225cd871870f2d9cf49b9b4276531f03438a88e94be86fe" + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + pruneopts = "NUT" + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + [[projects]] digest = "1:097cc61836050f45cbb712ae3bb45d66fba464c16b8fac09907fa3c1f753eff6" name = "github.com/prometheus/client_golang" @@ -551,6 +583,14 @@ revision = "2e9d26c8c37aae03e3f9d4e90b7116f5accb7cab" version = "v1.0.5" +[[projects]] + digest = "1:619c0d90a027b62dfc220e66d94522d283e911aac02b1cef4242e3ca7be7b859" + name = "github.com/stretchr/testify" + packages = ["assert"] + pruneopts = "NUT" + revision = "3ebf1ddaeb260c4b1ae502a01c7844fa8c1fa0e9" + version = "v1.5.1" + [[projects]] digest = "1:435d9fe926ee0d903662215091e27fba6f1b7228d33a30c289cdb5aeff1c8fc8" name = "github.com/tsenart/vegeta" @@ -1468,11 +1508,15 @@ "github.com/google/mako/spec/proto/mako_go_proto", "github.com/google/uuid", "github.com/kelseyhightower/envconfig", + "github.com/mitchellh/go-homedir", "github.com/openzipkin/zipkin-go/model", + "github.com/pelletier/go-toml", + "github.com/phayes/freeport", "github.com/pkg/errors", "github.com/robfig/cron", "github.com/rogpeppe/fastuuid", "github.com/rogpeppe/go-internal/semver", + "github.com/stretchr/testify/assert", "github.com/tsenart/vegeta/lib", "github.com/wavesoftware/go-ensure", "go.opencensus.io/plugin/ochttp", diff --git a/test/prober/configuration.go b/test/prober/configuration.go index 4d43434dc8a..496cacdd042 100644 --- a/test/prober/configuration.go +++ b/test/prober/configuration.go @@ -34,7 +34,7 @@ import ( const ( configName = "wathola-config" - configMountPoint = "/.config/wathola" + configMountPoint = "/home/nonroot/.config/wathola" configFilename = "config.toml" watholaEventNs = "com.github.cardil.wathola" healthEndpoint = "/healthz" diff --git a/test/prober/forwarder.go b/test/prober/forwarder.go index eb944cc9eff..4268800ccac 100644 --- a/test/prober/forwarder.go +++ b/test/prober/forwarder.go @@ -24,6 +24,7 @@ import ( "knative.dev/eventing/test/lib" "knative.dev/eventing/test/lib/duck" "knative.dev/eventing/test/lib/resources" + pkgTest "knative.dev/pkg/test" ) var ( @@ -74,7 +75,7 @@ func forwarderKService(name, namespace string) *unstructured.Unstructured { "spec": map[string]interface{}{ "containers": []map[string]interface{}{{ "name": "forwarder", - "image": fmt.Sprintf("quay.io/cardil/wathola-forwarder:%v", Version), + "image": pkgTest.ImagePath(forwarderName), "volumeMounts": []map[string]interface{}{{ "name": configName, "mountPath": configMountPoint, diff --git a/test/prober/prober.go b/test/prober/prober.go index 17a058ba636..7303ad06a8f 100644 --- a/test/prober/prober.go +++ b/test/prober/prober.go @@ -26,10 +26,6 @@ import ( ) var ( - // Version is a version of wathola tool version that is built outside of eventing - // TODO(ksuszyns): Donate a wathola tool to this repo, as discussed in knative/test-infra#1631 - Version = "v0.7.0" - // FIXME: Interval is set to 200 msec, as lower values will result in errors: knative/eventing#2357 // Interval = 10 * time.Millisecond Interval = 200 * time.Millisecond diff --git a/test/prober/receiver.go b/test/prober/receiver.go index c1c554c9350..9564216529b 100644 --- a/test/prober/receiver.go +++ b/test/prober/receiver.go @@ -20,10 +20,10 @@ import ( "github.com/wavesoftware/go-ensure" corev1 "k8s.io/api/core/v1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "knative.dev/eventing/test/lib" - "knative.dev/pkg/test" + pkgTest "knative.dev/pkg/test" ) var ( @@ -44,7 +44,7 @@ func (p *prober) removeReceiver() { func (p *prober) deployReceiverPod() { p.log.Infof("Deploy of receiver pod: %v", receiverName) pod := &corev1.Pod{ - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: receiverName, Namespace: p.config.Namespace, Labels: map[string]string{ @@ -65,7 +65,7 @@ func (p *prober) deployReceiverPod() { Containers: []corev1.Container{ { Name: "receiver", - Image: fmt.Sprintf("quay.io/cardil/wathola-receiver:%v", Version), + Image: pkgTest.ImagePath(receiverName), VolumeMounts: []corev1.VolumeMount{ { Name: configName, @@ -89,14 +89,14 @@ func (p *prober) deployReceiverPod() { ensure.NoError(err) lib.WaitFor(fmt.Sprintf("receiver be ready: %v", receiverName), func() error { - return test.WaitForPodRunning(p.client.Kube, receiverName, p.client.Namespace) + return pkgTest.WaitForPodRunning(p.client.Kube, receiverName, p.client.Namespace) }) } func (p *prober) deployReceiverService() { p.log.Infof("Deploy of receiver service: %v", receiverName) service := &corev1.Service{ - ObjectMeta: v1.ObjectMeta{ + ObjectMeta: metav1.ObjectMeta{ Name: receiverName, Namespace: p.config.Namespace, }, @@ -136,13 +136,13 @@ func (p *prober) deployReceiverService() { func (p *prober) removeReceiverPod() { p.log.Infof("Remove of receiver pod: %v", receiverName) err := p.client.Kube.Kube.CoreV1().Pods(p.config.Namespace). - Delete(receiverName, &v1.DeleteOptions{}) + Delete(receiverName, &metav1.DeleteOptions{}) ensure.NoError(err) } func (p *prober) removeReceiverService() { p.log.Infof("Remove of receiver service: %v", receiverName) err := p.client.Kube.Kube.CoreV1().Services(p.config.Namespace). - Delete(receiverName, &v1.DeleteOptions{}) + Delete(receiverName, &metav1.DeleteOptions{}) ensure.NoError(err) } diff --git a/test/prober/sender.go b/test/prober/sender.go index fe1ceffd86f..c261f136ad4 100644 --- a/test/prober/sender.go +++ b/test/prober/sender.go @@ -22,7 +22,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "knative.dev/eventing/test/lib" - "knative.dev/pkg/test" + pkgTest "knative.dev/pkg/test" ) var senderName = "wathola-sender" @@ -48,7 +48,7 @@ func (p *prober) deploySender() { Containers: []corev1.Container{ { Name: "sender", - Image: fmt.Sprintf("quay.io/cardil/wathola-sender:%v", Version), + Image: pkgTest.ImagePath(senderName), VolumeMounts: []corev1.VolumeMount{ { Name: configName, @@ -65,7 +65,7 @@ func (p *prober) deploySender() { ensure.NoError(err) lib.WaitFor(fmt.Sprintf("sender pod be ready: %v", senderName), func() error { - return test.WaitForPodRunning(p.client.Kube, senderName, p.client.Namespace) + return pkgTest.WaitForPodRunning(p.client.Kube, senderName, p.client.Namespace) }) } diff --git a/test/prober/wathola/README.md b/test/prober/wathola/README.md new file mode 100644 index 00000000000..2abfc564c65 --- /dev/null +++ b/test/prober/wathola/README.md @@ -0,0 +1,3 @@ +# Wathola + +A cloudevents mass assurer tool (wathola - "he receive" in zulu) diff --git a/test/prober/wathola/client/receiver.go b/test/prober/wathola/client/receiver.go new file mode 100644 index 00000000000..a7eefcaa912 --- /dev/null +++ b/test/prober/wathola/client/receiver.go @@ -0,0 +1,95 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package client + +import ( + "context" + nethttp "net/http" + "strings" + + cloudevents "github.com/cloudevents/sdk-go" + cloudeventshttp "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http" + "github.com/wavesoftware/go-ensure" + "knative.dev/eventing/test/prober/wathola/config" +) + +var log = config.Log + +// ReceiveEvent represents a function that receive event +type ReceiveEvent func(e cloudevents.Event) + +// Receive events and push then to passed fn +func Receive( + port int, + cancel *context.CancelFunc, + receiveEvent ReceiveEvent, + middlewares ... cloudeventshttp.Middleware) { + portOpt := cloudevents.WithPort(port) + opts := make([]cloudeventshttp.Option, 0) + opts = append(opts, portOpt) + if config.Instance.Readiness.Enabled { + readyOpt := cloudevents.WithMiddleware(readinessMiddleware) + opts = append(opts, readyOpt) + } + for _, m := range middlewares { + opt := cloudevents.WithMiddleware(m) + opts = append(opts, opt) + } + http, err := cloudevents.NewHTTPTransport(opts...) + if err != nil { + log.Fatalf("failed to create http transport, %v", err) + } + c, err := cloudevents.NewClient(http) + if err != nil { + log.Fatalf("failed to create client, %v", err) + } + ctx, ccancel := context.WithCancel(context.Background()) + cancel = &ccancel + log.Infof("listening for events on port %v", port) + err = c.StartReceiver(ctx, receiveEvent) + if err != nil { + log.Fatal(err) + } +} + +func readinessMiddleware(next nethttp.Handler) nethttp.Handler { + log.Debugf("Using readiness probe: %v", config.Instance.Readiness.URI) + return &readinessProbe{ + next: next, + } +} + +type readinessProbe struct { + next nethttp.Handler +} + +func (r readinessProbe) ServeHTTP(rw nethttp.ResponseWriter, req *nethttp.Request) { + if req.RequestURI == config.Instance.Readiness.URI { + rw.WriteHeader(config.Instance.Readiness.Status) + _, err := rw.Write([]byte(config.Instance.Readiness.Message)) + ensure.NoError(err) + log.Debugf("Received ready check. Headers: %v", headersOf(req)) + } else { + r.next.ServeHTTP(rw, req) + } +} + +func headersOf(req *nethttp.Request) string { + var b strings.Builder + ensure.NoError(req.Header.Write(&b)) + headers := b.String() + return strings.ReplaceAll(headers, "\r\n", "; ") +} diff --git a/test/prober/wathola/config/defaults.go b/test/prober/wathola/config/defaults.go new file mode 100644 index 00000000000..7b043ca2608 --- /dev/null +++ b/test/prober/wathola/config/defaults.go @@ -0,0 +1,74 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package config + +import ( + "fmt" + nethttp "net/http" + "os" + "strconv" + "time" + + "go.uber.org/zap" +) + +// Instance holds configuration values +var Instance = defaultValues() + +var port = envint("PORT", 22111) +var forwarderPort = envint("PORT", 22110) + +func envint(envKey string, defaultValue int) int { + val, ok := os.LookupEnv(envKey) + if !ok { + return defaultValue + } + result, err := strconv.Atoi(val) + if err != nil { + panic(err) + } + return result +} + +func defaultValues() *Config { + return &Config{ + Receiver: ReceiverConfig{ + Port: port, + Teardown: ReceiverTeardownConfig{ + Duration: 3 * time.Second, + }, + Progress: ReceiverProgressConfig{ + Duration: time.Second, + }, + }, + Forwarder: ForwarderConfig{ + Target: fmt.Sprintf("http://localhost:%v/", port), + Port: forwarderPort, + }, + Sender: SenderConfig{ + Address: fmt.Sprintf("http://localhost:%v/", forwarderPort), + Interval: 10 * time.Millisecond, + Cooldown: time.Second, + }, + Readiness: ReadinessConfig{ + Enabled: true, + URI: "/healthz", + Message: "OK", + Status: nethttp.StatusOK, + }, + LogLevel: zap.InfoLevel, + } +} diff --git a/test/prober/wathola/config/defaults_test.go b/test/prober/wathola/config/defaults_test.go new file mode 100644 index 00000000000..00b4fd86e9e --- /dev/null +++ b/test/prober/wathola/config/defaults_test.go @@ -0,0 +1,29 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package config + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestDefaultValues(t *testing.T) { + assert.NotNil(t, Instance) + assert.Condition(t, func() (success bool) { + return Instance.Receiver.Teardown.Duration.Seconds() >= 1 + }) +} diff --git a/test/prober/wathola/config/logger.go b/test/prober/wathola/config/logger.go new file mode 100644 index 00000000000..a933bd63610 --- /dev/null +++ b/test/prober/wathola/config/logger.go @@ -0,0 +1,32 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package config + +import ( + "go.uber.org/zap" +) + +// Log is a default logger for wathola +var Log = newLogger() +var logConfig = zap.NewProductionConfig() + +func newLogger() *zap.SugaredLogger { + z, err := logConfig.Build() + if err != nil { + panic(err) + } + return z.Sugar() +} diff --git a/test/prober/wathola/config/reader.go b/test/prober/wathola/config/reader.go new file mode 100644 index 00000000000..efb7f563fd2 --- /dev/null +++ b/test/prober/wathola/config/reader.go @@ -0,0 +1,64 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package config + +import ( + "github.com/mitchellh/go-homedir" + "github.com/pelletier/go-toml" + "github.com/wavesoftware/go-ensure" + + "os" +) + +var location = "~/.config/wathola/config.toml" +var logFatal = Log.Fatal + +// ReadIfPresent read a configuration file if it exists +func ReadIfPresent() { + configFile, err := homedir.Expand(location) + ensure.NoError(err) + if fileExists(configFile) { + Log.Infof("Reading config file: %v", configFile) + err := Read(configFile) + if err != nil { + logFatal(err) + } + } else { + Log.Infof("Define config file to be taken into account: %v", configFile) + } +} + +// Read a config file and update configuration object +func Read(configFile string) error { + r, err := os.Open(configFile) + if err != nil { + return err + } + d := toml.NewDecoder(r) + err = d.Decode(Instance) + if err == nil { + logConfig.Level.SetLevel(Instance.LogLevel) + } + return err +} + +func fileExists(filename string) bool { + info, err := os.Stat(filename) + if os.IsNotExist(err) { + return false + } + return !info.IsDir() +} diff --git a/test/prober/wathola/config/reader_test.go b/test/prober/wathola/config/reader_test.go new file mode 100644 index 00000000000..5fddf558561 --- /dev/null +++ b/test/prober/wathola/config/reader_test.go @@ -0,0 +1,98 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package config + +import ( + "fmt" + "github.com/google/uuid" + "github.com/mitchellh/go-homedir" + "github.com/stretchr/testify/assert" + "github.com/wavesoftware/go-ensure" + + "io/ioutil" + "os" + "path" + "testing" +) + +var id = uuid.New() + +func TestReadIfPresent(t *testing.T) { + // given + expanded := ensureConfigFileNotPresent() + data := []byte(`[sender] +address = 'http://default-broker.event-example.svc.cluster.local/' +`) + ensure.NoError(ioutil.WriteFile(expanded, data, 0644)) + defer func() { ensure.NoError(os.Remove(expanded)) }() + + // when + ReadIfPresent() + + // then + assert.Equal(t, + "http://default-broker.event-example.svc.cluster.local/", + Instance.Sender.Address) +} + +func TestReadIfPresentAndInvalid(t *testing.T) { + // given + origLogFatal := logFatal + defer func() { logFatal = origLogFatal } () + expanded := ensureConfigFileNotPresent() + data := []byte(`[sender] +address = 'http://default-broker.event-example.svc.cluster.local/ +`) + ensure.NoError(ioutil.WriteFile(expanded, data, 0644)) + defer func() { ensure.NoError(os.Remove(expanded)) }() + var errors []string + logFatal = func(args ...interface{}) { + errors = append(errors, fmt.Sprint(args)) + } + + // when + ReadIfPresent() + + // then + assert.Contains(t, errors, "[(2, 12): unclosed string]") +} + +func TestReadIfNotPresent(t *testing.T) { + // given + ensureConfigFileNotPresent() + + // when + ReadIfPresent() + + // then + assert.Equal(t, + "http://localhost:22110/", + Instance.Sender.Address) +} + +func ensureConfigFileNotPresent() string { + Instance = defaultValues() + location = fmt.Sprintf("~/tmp/wathola-%v/config.toml", id.String()) + expanded, err := homedir.Expand(location) + ensure.NoError(err) + dir := path.Dir(expanded) + ensure.NoError(os.MkdirAll(dir, os.ModePerm)) + if _, err := os.Stat(expanded); err == nil { + ensure.NoError(os.Remove(expanded)) + } + + return expanded +} diff --git a/test/prober/wathola/config/structure.go b/test/prober/wathola/config/structure.go new file mode 100644 index 00000000000..cd6af611a43 --- /dev/null +++ b/test/prober/wathola/config/structure.go @@ -0,0 +1,69 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package config + +import ( + "time" + + "go.uber.org/zap/zapcore" +) + +// ReceiverTeardownConfig holds config receiver teardown +type ReceiverTeardownConfig struct { + Duration time.Duration +} + +// ReceiverProgressConfig holds config receiver progress reporting +type ReceiverProgressConfig struct { + Duration time.Duration +} + +// ReceiverConfig hold configuration for receiver +type ReceiverConfig struct { + Teardown ReceiverTeardownConfig + Progress ReceiverProgressConfig + Port int +} + +// SenderConfig hold configuration for sender +type SenderConfig struct { + Address string + Interval time.Duration + Cooldown time.Duration +} + +// ForwarderConfig holds configuration for forwarder +type ForwarderConfig struct { + Target string + Port int +} + +// ReadinessConfig holds a readiness configuration +type ReadinessConfig struct { + Enabled bool + URI string + Message string + Status int +} + +// Config hold complete configuration +type Config struct { + Sender SenderConfig + Forwarder ForwarderConfig + Receiver ReceiverConfig + Readiness ReadinessConfig + LogLevel zapcore.Level +} diff --git a/test/prober/wathola/event/operations.go b/test/prober/wathola/event/operations.go new file mode 100644 index 00000000000..c28cba92180 --- /dev/null +++ b/test/prober/wathola/event/operations.go @@ -0,0 +1,34 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package event + +// StepsStore contains methods that register step event type +type StepsStore interface { + RegisterStep(step *Step) + Count() int +} + +// FinishedStore registers a finished event type +type FinishedStore interface { + RegisterFinished(finished *Finished) + State() State + Thrown() []string +} + +// Typed says a type of an event +type Typed interface { + Type() string +} diff --git a/test/prober/wathola/event/services.go b/test/prober/wathola/event/services.go new file mode 100644 index 00000000000..e9cbb14ddbf --- /dev/null +++ b/test/prober/wathola/event/services.go @@ -0,0 +1,162 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package event + +import ( + "fmt" + "sync" + "time" + + "knative.dev/eventing/test/prober/wathola/config" +) + +var mutex = sync.RWMutex{} +var lastProgressReport = time.Now() + +// ErrorStore contains errors that was thrown +type ErrorStore struct { + state State + thrown []thrown +} + +// NewErrorStore creates a new error store +func NewErrorStore() *ErrorStore { + return &ErrorStore{ + state: Active, + thrown: make([]thrown, 0), + } +} + +// NewStepsStore creates StepsStore +func NewStepsStore(errors *ErrorStore) StepsStore { + return &stepStore{ + store: make(map[int]int), + errors: errors, + } +} + +// NewFinishedStore creates FinishedStore +func NewFinishedStore(steps StepsStore, errors *ErrorStore) FinishedStore { + return &finishedStore{ + received: 0, + count: -1, + steps: steps, + errors: errors, + } +} + +func (s *stepStore) RegisterStep(step *Step) { + mutex.Lock() + if times, found := s.store[step.Number]; found { + s.errors.throw( + "event #%d received %d times, but should be received only once", + step.Number, times+1) + } else { + s.store[step.Number] = 0 + } + s.store[step.Number]++ + mutex.Unlock() + log.Debugf("event #%d received", step.Number) + s.reportProgress() +} + +func (s *stepStore) Count() int { + return len(s.store) +} + +func (f *finishedStore) RegisterFinished(finished *Finished) { + if f.received > 0 { + f.errors.throw( + "finish event should be received only once, received %d", + f.received+1) + } + f.received++ + f.count = finished.Count + log.Infof("finish event received, expecting %d event ware propagated", finished.Count) + d := config.Instance.Receiver.Teardown.Duration + log.Infof("waiting additional %v to be sure all events came", d) + time.Sleep(d) + receivedEvents := f.steps.Count() + if receivedEvents != finished.Count { + f.errors.throw("expecting to have %v unique events received, "+ + "but received %v unique events", finished.Count, receivedEvents) + f.reportViolations(finished) + f.errors.state = Failed + } else { + log.Infof("properly received %d unique events", receivedEvents) + f.errors.state = Success + } +} + +func (f *finishedStore) State() State { + return f.errors.state +} + +func (f *finishedStore) Thrown() []string { + msgs := make([]string, 0) + for _, t := range f.errors.thrown { + errMsg := fmt.Sprintf(t.format, t.args...) + msgs = append(msgs, errMsg) + } + return msgs +} + +func (f *finishedStore) reportViolations(finished *Finished) { + steps := f.steps.(*stepStore) + for eventNo := 1; eventNo <= finished.Count; eventNo++ { + times, ok := steps.store[eventNo] + if !ok { + times = 0 + } + if times != 1 { + f.errors.throw("event #%v should be received once, but was received %v times", + eventNo, times) + } + } +} + +func (s *stepStore) reportProgress() { + if lastProgressReport.Add(config.Instance.Receiver.Progress.Duration).Before(time.Now()) { + lastProgressReport = time.Now() + log.Infof("collected %v unique events", s.Count()) + } +} + +func (e *ErrorStore) throw(format string, args ...interface{}) { + t := thrown{ + format: format, + args: args, + } + e.thrown = append(e.thrown, t) + log.Errorf(t.format, t.args...) +} + +type stepStore struct { + store map[int]int + errors *ErrorStore +} + +type finishedStore struct { + received int + count int + errors *ErrorStore + steps StepsStore +} + +type thrown struct { + format string + args []interface{} +} diff --git a/test/prober/wathola/event/services_test.go b/test/prober/wathola/event/services_test.go new file mode 100644 index 00000000000..a0ee9b38b00 --- /dev/null +++ b/test/prober/wathola/event/services_test.go @@ -0,0 +1,79 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package event + +import ( + "github.com/stretchr/testify/assert" + "knative.dev/eventing/test/prober/wathola/config" + + "os" + "testing" + "time" +) + +func TestProperEventsPropagation(t *testing.T) { + // given + errors := NewErrorStore() + stepsStore := NewStepsStore(errors) + finishedStore := NewFinishedStore(stepsStore, errors) + + // when + stepsStore.RegisterStep(&Step{Number: 1}) + stepsStore.RegisterStep(&Step{Number: 3}) + stepsStore.RegisterStep(&Step{Number: 2}) + finishedStore.RegisterFinished(&Finished{Count: 3}) + + // then + assert.Empty(t, errors.thrown) +} + +func TestMissingAndDoubleEvent(t *testing.T) { + // given + errors := NewErrorStore() + stepsStore := NewStepsStore(errors) + finishedStore := NewFinishedStore(stepsStore, errors) + + // when + stepsStore.RegisterStep(&Step{Number: 1}) + stepsStore.RegisterStep(&Step{Number: 2}) + stepsStore.RegisterStep(&Step{Number: 2}) + finishedStore.RegisterFinished(&Finished{Count: 3}) + + // then + assert.NotEmpty(t, errors.thrown) +} + +func TestDoubleFinished(t *testing.T) { + // given + errors := NewErrorStore() + stepsStore := NewStepsStore(errors) + finishedStore := NewFinishedStore(stepsStore, errors) + + // when + stepsStore.RegisterStep(&Step{Number: 1}) + stepsStore.RegisterStep(&Step{Number: 2}) + finishedStore.RegisterFinished(&Finished{Count: 2}) + finishedStore.RegisterFinished(&Finished{Count: 2}) + + // then + assert.NotEmpty(t, errors.thrown) +} + +func TestMain(m *testing.M) { + config.Instance.Receiver.Teardown.Duration = 20 * time.Millisecond + exitcode := m.Run() + os.Exit(exitcode) +} diff --git a/test/prober/wathola/event/types.go b/test/prober/wathola/event/types.go new file mode 100644 index 00000000000..020913dd5f8 --- /dev/null +++ b/test/prober/wathola/event/types.go @@ -0,0 +1,59 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package event + +import "knative.dev/eventing/test/prober/wathola/config" + +const ( + // StepType is a string type representation of step event + StepType = "com.github.cardil.wathola.step" + // FinishedType os a string type representation of finished event + FinishedType = "com.github.cardil.wathola.finished" +) + +// Step is a event call at each step of verification +type Step struct { + Number int +} + +// Finished is step call after verification finishes +type Finished struct { + Count int +} + +// Type returns a type of a event +func (s Step) Type() string { + return StepType +} + +// Type returns a type of a event +func (f Finished) Type() string { + return FinishedType +} + +// State defines a state of event store +type State int + +const ( + // Active == 1 (iota has been reset) + Active State = 1 << iota + // Success == 2 + Success State = 1 << iota + // Failed == 4 + Failed State = 1 << iota +) + +var log = config.Log diff --git a/test/prober/wathola/event/types_test.go b/test/prober/wathola/event/types_test.go new file mode 100644 index 00000000000..9080fb4c7e4 --- /dev/null +++ b/test/prober/wathola/event/types_test.go @@ -0,0 +1,34 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package event + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestStepType(t *testing.T) { + s1 := Step{Number:1} + + assert.Equal(t, StepType, s1.Type()) +} + +func TestFinishedType(t *testing.T) { + f1 := Finished{Count:441} + + assert.Equal(t, FinishedType, f1.Type()) +} diff --git a/test/prober/wathola/forwarder/operations.go b/test/prober/wathola/forwarder/operations.go new file mode 100644 index 00000000000..4ee037fde30 --- /dev/null +++ b/test/prober/wathola/forwarder/operations.go @@ -0,0 +1,21 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package forwarder + +// Forwarder perform waiting and receiving of events and forwarding them to other place +type Forwarder interface { + Forward() +} diff --git a/test/prober/wathola/forwarder/services.go b/test/prober/wathola/forwarder/services.go new file mode 100644 index 00000000000..e243230fecd --- /dev/null +++ b/test/prober/wathola/forwarder/services.go @@ -0,0 +1,77 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package forwarder + +import ( + "context" + + "github.com/cloudevents/sdk-go" + "knative.dev/eventing/test/prober/wathola/client" + "knative.dev/eventing/test/prober/wathola/config" + "knative.dev/eventing/test/prober/wathola/sender" + + "time" +) + +var log = config.Log +var lastProgressReport = time.Now() + +// New creates new forwarder +func New() Forwarder { + config.ReadIfPresent() + f := &forwarder{ + count: 0, + } + return f +} + +// Stop will stop running forwarder if there is one +func Stop() { + if cancel != nil { + log.Info("stopping forwarder") + cancel() + cancel = nil + } +} + +var cancel context.CancelFunc + +func (f *forwarder) Forward() { + port := config.Instance.Forwarder.Port + client.Receive(port, &cancel, f.forwardEvent) +} + +func (f *forwarder) forwardEvent(e cloudevents.Event) { + target := config.Instance.Forwarder.Target + log.Debugf("Forwarding event %v to %v", e.ID(), target) + err := sender.SendEvent(e, target) + if err != nil { + log.Error(err) + } + f.count++ + f.reportProgress() +} + +func (f *forwarder) reportProgress() { + if lastProgressReport.Add(config.Instance.Receiver.Progress.Duration).Before(time.Now()) { + lastProgressReport = time.Now() + log.Infof("forwarded %v events", f.count) + } +} + +type forwarder struct { + count int +} diff --git a/test/prober/wathola/receiver/operations.go b/test/prober/wathola/receiver/operations.go new file mode 100644 index 00000000000..b188cc3afab --- /dev/null +++ b/test/prober/wathola/receiver/operations.go @@ -0,0 +1,21 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package receiver + +// Receiver perform waiting and receiving of events +type Receiver interface { + Receive() +} diff --git a/test/prober/wathola/receiver/services.go b/test/prober/wathola/receiver/services.go new file mode 100644 index 00000000000..e7c3f59121c --- /dev/null +++ b/test/prober/wathola/receiver/services.go @@ -0,0 +1,144 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package receiver + +import ( + "context" + "encoding/json" + "fmt" + + cloudevents "github.com/cloudevents/sdk-go" + "github.com/wavesoftware/go-ensure" + "knative.dev/eventing/test/prober/wathola/client" + "knative.dev/eventing/test/prober/wathola/config" + "knative.dev/eventing/test/prober/wathola/event" + + "net/http" +) + +var log = config.Log +var cancel context.CancelFunc + +// New creates new Receiver +func New() Receiver { + config.ReadIfPresent() + errors := event.NewErrorStore() + stepsStore := event.NewStepsStore(errors) + finishedStore := event.NewFinishedStore(stepsStore, errors) + r := newReceiver(stepsStore, finishedStore) + return r +} + +// Stop will stop running receiver if there is one +func Stop() { + if cancel != nil { + log.Info("stopping receiver") + cancel() + cancel = nil + } +} + +func (r receiver) Receive() { + port := config.Instance.Receiver.Port + client.Receive(port, &cancel, r.receiveEvent, r.reportMiddleware) +} + +func (r receiver) receiveEvent(e cloudevents.Event) { + // do something with event.Context and event.Data (via event.DataAs(foo) + t := e.Context.GetType() + if t == event.StepType { + step := &event.Step{} + err := e.DataAs(step) + if err != nil { + log.Fatal(err) + } + r.step.RegisterStep(step) + } + if t == event.FinishedType { + finished := &event.Finished{} + err := e.DataAs(finished) + if err != nil { + log.Fatal(err) + } + r.finished.RegisterFinished(finished) + } +} + +func (r *receiver) reportMiddleware(next http.Handler) http.Handler { + return &reportHandler{ + next: next, + receiver: r, + } +} + +type receiver struct { + step event.StepsStore + finished event.FinishedStore +} + +func newReceiver(step event.StepsStore, finished event.FinishedStore) *receiver { + r := &receiver{ + step: step, + finished: finished, + } + return r +} + +type reportHandler struct { + next http.Handler + receiver *receiver +} + +func (r reportHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { + if req.RequestURI == "/report" { + s := r.receiver.finished.State() + errs := r.receiver.finished.Thrown() + events := r.receiver.step.Count() + sj := &StateJSON{ + State: stateToString(s), + Events: events, + Thrown: errs, + } + b, err := json.Marshal(sj) + ensure.NoError(err) + rw.Header().Add("Content-Type", "application/json") + rw.WriteHeader(http.StatusOK) + _, err = rw.Write(b) + ensure.NoError(err) + } else { + r.next.ServeHTTP(rw, req) + } +} + +func stateToString(state event.State) string { + switch state { + case event.Active: + return "active" + case event.Success: + return "success" + case event.Failed: + return "failed" + default: + panic(fmt.Sprintf("unknown state: %v", state)) + } +} + +// StateJSON represents state as JSON +type StateJSON struct { + State string `json:"state"` + Events int `json:"events"` + Thrown []string `json:"thrown"` +} diff --git a/test/prober/wathola/receiver/services_test.go b/test/prober/wathola/receiver/services_test.go new file mode 100644 index 00000000000..ade50d4081b --- /dev/null +++ b/test/prober/wathola/receiver/services_test.go @@ -0,0 +1,64 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package receiver + +import ( + "fmt" + + cloudevents "github.com/cloudevents/sdk-go" + "github.com/phayes/freeport" + "github.com/stretchr/testify/assert" + "knative.dev/eventing/test/prober/wathola/config" + "knative.dev/eventing/test/prober/wathola/event" + "knative.dev/eventing/test/prober/wathola/sender" + + "os" + "testing" + "time" +) + +func TestReceiverReceive(t *testing.T) { + // given + e := sender.NewCloudEvent(event.Step{Number: 42}, event.StepType) + f := sender.NewCloudEvent(event.Finished{Count: 1}, event.FinishedType) + + instance := New() + port := freeport.GetPort() + config.Instance.Receiver.Port = port + go instance.Receive() + time.Sleep(time.Second) + defer Stop() + + // when + sendEvent(e, port) + sendEvent(f, port) + + // then + rr := instance.(*receiver) + assert.Equal(t, 1, rr.step.Count()) + assert.Equal(t, event.Success, rr.finished.State()) +} + +func TestMain(m *testing.M) { + config.Instance.Receiver.Teardown.Duration = 20 * time.Millisecond + exitcode := m.Run() + os.Exit(exitcode) +} + +func sendEvent(e cloudevents.Event, port int) { + url := fmt.Sprintf("http://localhost:%v/", port) + sender.SendEvent(e, url) +} diff --git a/test/prober/wathola/sender/operations.go b/test/prober/wathola/sender/operations.go new file mode 100644 index 00000000000..de0a452e27a --- /dev/null +++ b/test/prober/wathola/sender/operations.go @@ -0,0 +1,55 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package sender + +import ( + "math/rand" + "time" + + "knative.dev/eventing/test/prober/wathola/config" +) + +// New creates new Sender +func New() Sender { + config.ReadIfPresent() + return &sender{ + active: true, + counter: 0, + } +} + +// NewEventID creates new event ID +func NewEventID() string { + return randString(16) +} + +const charset = "abcdefghijklmnopqrstuvwxyz" + + "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" + +var seededRand = rand.New( + rand.NewSource(time.Now().UnixNano())) + +func randStringWithCharset(length int, charset string) string { + b := make([]byte, length) + for i := range b { + b[i] = charset[seededRand.Intn(len(charset))] + } + return string(b) +} + +func randString(length int) string { + return randStringWithCharset(length, charset) +} diff --git a/test/prober/wathola/sender/services.go b/test/prober/wathola/sender/services.go new file mode 100644 index 00000000000..7b4736dd0eb --- /dev/null +++ b/test/prober/wathola/sender/services.go @@ -0,0 +1,115 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package sender + +import ( + "context" + "fmt" + + cloudevents "github.com/cloudevents/sdk-go" + "github.com/wavesoftware/go-ensure" + "knative.dev/eventing/test/prober/wathola/config" + "knative.dev/eventing/test/prober/wathola/event" + + "os" + "os/signal" + "syscall" + "time" +) + +var log = config.Log +var senderConfig = &config.Instance.Sender + +type sender struct { + counter int + active bool +} + +func (s *sender) SendContinually() { + c := make(chan os.Signal, 1) + signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) + go func() { + for sig := range c { + // sig is a ^C or term, handle it + log.Infof("Received: %v, closing", sig.String()) + s.active = false + s.sendFinished() + } + }() + for s.active { + err := s.sendStep() + if err != nil { + log.Warnf("Could not send step event, retry in %v", senderConfig.Cooldown) + time.Sleep(senderConfig.Cooldown) + } else { + time.Sleep(senderConfig.Interval) + } + } +} + +// NewCloudEvent creates a new cloud event +func NewCloudEvent(data interface{}, typ string) cloudevents.Event { + e := cloudevents.NewEvent() + e.SetDataContentType("application/json") + e.SetType(typ) + host, err := os.Hostname() + ensure.NoError(err) + e.SetSource(fmt.Sprintf("knative://%s/wathola/sender", host)) + e.SetID(NewEventID()) + e.SetTime(time.Now()) + err = e.SetData(data) + ensure.NoError(err) + ensure.NoError(e.Validate()) + return e +} + +// SendEvent will send cloud event to given url +func SendEvent(e cloudevents.Event, url string) error { + ht, err := cloudevents.NewHTTPTransport( + cloudevents.WithTarget(url), + cloudevents.WithEncoding(cloudevents.HTTPBinaryV02), + ) + ensure.NoError(err) + c, err := cloudevents.NewClient(ht) + ensure.NoError(err) + ctx := context.Background() + _, _, err = c.Send(ctx, e) + return err +} + +func (s *sender) sendStep() error { + step := event.Step{Number: s.counter + 1} + ce := NewCloudEvent(step, event.StepType) + url := senderConfig.Address + log.Infof("Sending step event #%v to %s", step.Number, url) + err := SendEvent(ce, url) + if err != nil { + return err + } + s.counter++ + return nil +} + +func (s *sender) sendFinished() { + if s.counter == 0 { + return + } + finished := event.Finished{Count: s.counter} + url := senderConfig.Address + ce := NewCloudEvent(finished, event.FinishedType) + log.Infof("Sending finished event (count: %v) to %s", finished.Count, url) + ensure.NoError(SendEvent(ce, url)) +} diff --git a/test/prober/wathola/sender/types.go b/test/prober/wathola/sender/types.go new file mode 100644 index 00000000000..3b78c465724 --- /dev/null +++ b/test/prober/wathola/sender/types.go @@ -0,0 +1,21 @@ +/* + * Copyright 2020 The Knative 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. + */ + +package sender + +// Sender will send messages continuously until process receives a SIGINT +type Sender interface { + SendContinually() +} diff --git a/test/test_images/wathola-forwarder/main.go b/test/test_images/wathola-forwarder/main.go new file mode 100644 index 00000000000..b25a6ae3716 --- /dev/null +++ b/test/test_images/wathola-forwarder/main.go @@ -0,0 +1,10 @@ +package main + +import "knative.dev/eventing/test/prober/wathola/forwarder" + +var instance forwarder.Forwarder + +func main() { + instance = forwarder.New() + instance.Forward() +} diff --git a/test/test_images/wathola-forwarder/main_test.go b/test/test_images/wathola-forwarder/main_test.go new file mode 100644 index 00000000000..d7565347252 --- /dev/null +++ b/test/test_images/wathola-forwarder/main_test.go @@ -0,0 +1,21 @@ +package main + +import ( + "github.com/phayes/freeport" + "github.com/stretchr/testify/assert" + "knative.dev/eventing/test/prober/wathola/config" + "knative.dev/eventing/test/prober/wathola/forwarder" + + "testing" + "time" +) + +func TestForwarderMain(t *testing.T) { + config.Instance.Forwarder.Port = freeport.GetPort() + go main() + defer forwarder.Stop() + + time.Sleep(time.Second) + + assert.NotNil(t, instance) +} diff --git a/test/test_images/wathola-forwarder/pod.yaml b/test/test_images/wathola-forwarder/pod.yaml new file mode 100644 index 00000000000..d46df9257c9 --- /dev/null +++ b/test/test_images/wathola-forwarder/pod.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Pod +metadata: + name: wathola-forwarder +spec: + containers: + - name: wathola-forwarder + image: knative.dev/eventing/test/test_images/wathola-forwarder diff --git a/test/test_images/wathola-receiver/main.go b/test/test_images/wathola-receiver/main.go new file mode 100644 index 00000000000..f640d1ca580 --- /dev/null +++ b/test/test_images/wathola-receiver/main.go @@ -0,0 +1,10 @@ +package main + +import "knative.dev/eventing/test/prober/wathola/receiver" + +var instance receiver.Receiver + +func main() { + instance = receiver.New() + instance.Receive() +} diff --git a/test/test_images/wathola-receiver/main_test.go b/test/test_images/wathola-receiver/main_test.go new file mode 100644 index 00000000000..06b32ec8174 --- /dev/null +++ b/test/test_images/wathola-receiver/main_test.go @@ -0,0 +1,22 @@ +package main + +import ( + "github.com/phayes/freeport" + "knative.dev/eventing/test/prober/wathola/config" + "knative.dev/eventing/test/prober/wathola/receiver" + + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestReceiverMain(t *testing.T) { + config.Instance.Receiver.Port = freeport.GetPort() + go main() + defer receiver.Stop() + + time.Sleep(time.Second) + + assert.NotNil(t, instance) +} diff --git a/test/test_images/wathola-receiver/pod.yaml b/test/test_images/wathola-receiver/pod.yaml new file mode 100644 index 00000000000..f170f7dd0b7 --- /dev/null +++ b/test/test_images/wathola-receiver/pod.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Pod +metadata: + name: wathola-receiver +spec: + containers: + - name: wathola-receiver + image: knative.dev/eventing/test/test_images/wathola-receiver diff --git a/test/test_images/wathola-sender/main.go b/test/test_images/wathola-sender/main.go new file mode 100644 index 00000000000..0fc1b7fc52a --- /dev/null +++ b/test/test_images/wathola-sender/main.go @@ -0,0 +1,7 @@ +package main + +import "knative.dev/eventing/test/prober/wathola/sender" + +func main() { + sender.New().SendContinually() +} diff --git a/test/test_images/wathola-sender/main_test.go b/test/test_images/wathola-sender/main_test.go new file mode 100644 index 00000000000..2ba33527e3c --- /dev/null +++ b/test/test_images/wathola-sender/main_test.go @@ -0,0 +1,17 @@ +package main + +import ( + "syscall" + "testing" + "time" + + "github.com/wavesoftware/go-ensure" +) + +func TestSenderMain(t *testing.T) { + p := syscall.Getpid() + go main() + time.Sleep(time.Second) + err := syscall.Kill(p, syscall.SIGINT) + ensure.NoError(err) +} diff --git a/test/test_images/wathola-sender/pod.yaml b/test/test_images/wathola-sender/pod.yaml new file mode 100644 index 00000000000..5b85e6058a5 --- /dev/null +++ b/test/test_images/wathola-sender/pod.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Pod +metadata: + name: wathola-sender +spec: + containers: + - name: wathola-sender + image: knative.dev/eventing/test/test_images/wathola-sender diff --git a/third_party/VENDOR-LICENSE b/third_party/VENDOR-LICENSE index 6a8bd064528..cf881f8b749 100644 --- a/third_party/VENDOR-LICENSE +++ b/third_party/VENDOR-LICENSE @@ -4291,6 +4291,33 @@ Import: knative.dev/eventing/vendor/github.com/matttproud/golang_protobuf_extens +=========================================================== +Import: knative.dev/eventing/vendor/github.com/mitchellh/go-homedir + +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + + + =========================================================== Import: knative.dev/eventing/vendor/github.com/modern-go/concurrent @@ -4912,6 +4939,33 @@ limitations under the License. +=========================================================== +Import: knative.dev/eventing/vendor/github.com/pelletier/go-toml + +The MIT License (MIT) + +Copyright (c) 2013 - 2017 Thomas Pelletier, Eric Anderton + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + + =========================================================== Import: knative.dev/eventing/vendor/github.com/pkg/errors diff --git a/vendor/github.com/mitchellh/go-homedir/LICENSE b/vendor/github.com/mitchellh/go-homedir/LICENSE new file mode 100644 index 00000000000..f9c841a51e0 --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/github.com/mitchellh/go-homedir/homedir.go b/vendor/github.com/mitchellh/go-homedir/homedir.go new file mode 100644 index 00000000000..25378537ead --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/homedir.go @@ -0,0 +1,167 @@ +package homedir + +import ( + "bytes" + "errors" + "os" + "os/exec" + "path/filepath" + "runtime" + "strconv" + "strings" + "sync" +) + +// DisableCache will disable caching of the home directory. Caching is enabled +// by default. +var DisableCache bool + +var homedirCache string +var cacheLock sync.RWMutex + +// Dir returns the home directory for the executing user. +// +// This uses an OS-specific method for discovering the home directory. +// An error is returned if a home directory cannot be detected. +func Dir() (string, error) { + if !DisableCache { + cacheLock.RLock() + cached := homedirCache + cacheLock.RUnlock() + if cached != "" { + return cached, nil + } + } + + cacheLock.Lock() + defer cacheLock.Unlock() + + var result string + var err error + if runtime.GOOS == "windows" { + result, err = dirWindows() + } else { + // Unix-like system, so just assume Unix + result, err = dirUnix() + } + + if err != nil { + return "", err + } + homedirCache = result + return result, nil +} + +// Expand expands the path to include the home directory if the path +// is prefixed with `~`. If it isn't prefixed with `~`, the path is +// returned as-is. +func Expand(path string) (string, error) { + if len(path) == 0 { + return path, nil + } + + if path[0] != '~' { + return path, nil + } + + if len(path) > 1 && path[1] != '/' && path[1] != '\\' { + return "", errors.New("cannot expand user-specific home dir") + } + + dir, err := Dir() + if err != nil { + return "", err + } + + return filepath.Join(dir, path[1:]), nil +} + +// Reset clears the cache, forcing the next call to Dir to re-detect +// the home directory. This generally never has to be called, but can be +// useful in tests if you're modifying the home directory via the HOME +// env var or something. +func Reset() { + cacheLock.Lock() + defer cacheLock.Unlock() + homedirCache = "" +} + +func dirUnix() (string, error) { + homeEnv := "HOME" + if runtime.GOOS == "plan9" { + // On plan9, env vars are lowercase. + homeEnv = "home" + } + + // First prefer the HOME environmental variable + if home := os.Getenv(homeEnv); home != "" { + return home, nil + } + + var stdout bytes.Buffer + + // If that fails, try OS specific commands + if runtime.GOOS == "darwin" { + cmd := exec.Command("sh", "-c", `dscl -q . -read /Users/"$(whoami)" NFSHomeDirectory | sed 's/^[^ ]*: //'`) + cmd.Stdout = &stdout + if err := cmd.Run(); err == nil { + result := strings.TrimSpace(stdout.String()) + if result != "" { + return result, nil + } + } + } else { + cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid())) + cmd.Stdout = &stdout + if err := cmd.Run(); err != nil { + // If the error is ErrNotFound, we ignore it. Otherwise, return it. + if err != exec.ErrNotFound { + return "", err + } + } else { + if passwd := strings.TrimSpace(stdout.String()); passwd != "" { + // username:password:uid:gid:gecos:home:shell + passwdParts := strings.SplitN(passwd, ":", 7) + if len(passwdParts) > 5 { + return passwdParts[5], nil + } + } + } + } + + // If all else fails, try the shell + stdout.Reset() + cmd := exec.Command("sh", "-c", "cd && pwd") + cmd.Stdout = &stdout + if err := cmd.Run(); err != nil { + return "", err + } + + result := strings.TrimSpace(stdout.String()) + if result == "" { + return "", errors.New("blank output when reading home directory") + } + + return result, nil +} + +func dirWindows() (string, error) { + // First prefer the HOME environmental variable + if home := os.Getenv("HOME"); home != "" { + return home, nil + } + + // Prefer standard environment variable USERPROFILE + if home := os.Getenv("USERPROFILE"); home != "" { + return home, nil + } + + drive := os.Getenv("HOMEDRIVE") + path := os.Getenv("HOMEPATH") + home := drive + path + if drive == "" || path == "" { + return "", errors.New("HOMEDRIVE, HOMEPATH, or USERPROFILE are blank") + } + + return home, nil +} diff --git a/vendor/github.com/pelletier/go-toml/LICENSE b/vendor/github.com/pelletier/go-toml/LICENSE new file mode 100644 index 00000000000..583bdae6282 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 - 2017 Thomas Pelletier, Eric Anderton + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/pelletier/go-toml/doc.go b/vendor/github.com/pelletier/go-toml/doc.go new file mode 100644 index 00000000000..a1406a32b38 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/doc.go @@ -0,0 +1,23 @@ +// Package toml is a TOML parser and manipulation library. +// +// This version supports the specification as described in +// https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md +// +// Marshaling +// +// Go-toml can marshal and unmarshal TOML documents from and to data +// structures. +// +// TOML document as a tree +// +// Go-toml can operate on a TOML document as a tree. Use one of the Load* +// functions to parse TOML data and obtain a Tree instance, then one of its +// methods to manipulate the tree. +// +// JSONPath-like queries +// +// The package github.com/pelletier/go-toml/query implements a system +// similar to JSONPath to quickly retrieve elements of a TOML document using a +// single expression. See the package documentation for more information. +// +package toml diff --git a/vendor/github.com/pelletier/go-toml/fuzz.go b/vendor/github.com/pelletier/go-toml/fuzz.go new file mode 100644 index 00000000000..14570c8d357 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/fuzz.go @@ -0,0 +1,31 @@ +// +build gofuzz + +package toml + +func Fuzz(data []byte) int { + tree, err := LoadBytes(data) + if err != nil { + if tree != nil { + panic("tree must be nil if there is an error") + } + return 0 + } + + str, err := tree.ToTomlString() + if err != nil { + if str != "" { + panic(`str must be "" if there is an error`) + } + panic(err) + } + + tree, err = Load(str) + if err != nil { + if tree != nil { + panic("tree must be nil if there is an error") + } + return 0 + } + + return 1 +} diff --git a/vendor/github.com/pelletier/go-toml/keysparsing.go b/vendor/github.com/pelletier/go-toml/keysparsing.go new file mode 100644 index 00000000000..e923bc4f9b7 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/keysparsing.go @@ -0,0 +1,113 @@ +// Parsing keys handling both bare and quoted keys. + +package toml + +import ( + "errors" + "fmt" + "unicode" +) + +// Convert the bare key group string to an array. +// The input supports double quotation and single quotation, +// but escape sequences are not supported. Lexers must unescape them beforehand. +func parseKey(key string) ([]string, error) { + runes := []rune(key) + var groups []string + + if len(key) == 0 { + return nil, errors.New("empty key") + } + + idx := 0 + for idx < len(runes) { + for ; idx < len(runes) && isSpace(runes[idx]); idx++ { + // skip leading whitespace + } + if idx >= len(runes) { + break + } + r := runes[idx] + if isValidBareChar(r) { + // parse bare key + startIdx := idx + endIdx := -1 + idx++ + for idx < len(runes) { + r = runes[idx] + if isValidBareChar(r) { + idx++ + } else if r == '.' { + endIdx = idx + break + } else if isSpace(r) { + endIdx = idx + for ; idx < len(runes) && isSpace(runes[idx]); idx++ { + // skip trailing whitespace + } + if idx < len(runes) && runes[idx] != '.' { + return nil, fmt.Errorf("invalid key character after whitespace: %c", runes[idx]) + } + break + } else { + return nil, fmt.Errorf("invalid bare key character: %c", r) + } + } + if endIdx == -1 { + endIdx = idx + } + groups = append(groups, string(runes[startIdx:endIdx])) + } else if r == '\'' { + // parse single quoted key + idx++ + startIdx := idx + for { + if idx >= len(runes) { + return nil, fmt.Errorf("unclosed single-quoted key") + } + r = runes[idx] + if r == '\'' { + groups = append(groups, string(runes[startIdx:idx])) + idx++ + break + } + idx++ + } + } else if r == '"' { + // parse double quoted key + idx++ + startIdx := idx + for { + if idx >= len(runes) { + return nil, fmt.Errorf("unclosed double-quoted key") + } + r = runes[idx] + if r == '"' { + groups = append(groups, string(runes[startIdx:idx])) + idx++ + break + } + idx++ + } + } else if r == '.' { + idx++ + if idx >= len(runes) { + return nil, fmt.Errorf("unexpected end of key") + } + r = runes[idx] + if !isValidBareChar(r) && r != '\'' && r != '"' && r != ' ' { + return nil, fmt.Errorf("expecting key part after dot") + } + } else { + return nil, fmt.Errorf("invalid key character: %c", r) + } + } + if len(groups) == 0 { + return nil, fmt.Errorf("empty key") + } + return groups, nil +} + +func isValidBareChar(r rune) bool { + return isAlphanumeric(r) || r == '-' || unicode.IsNumber(r) +} diff --git a/vendor/github.com/pelletier/go-toml/lexer.go b/vendor/github.com/pelletier/go-toml/lexer.go new file mode 100644 index 00000000000..735673bd7c1 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/lexer.go @@ -0,0 +1,780 @@ +// TOML lexer. +// +// Written using the principles developed by Rob Pike in +// http://www.youtube.com/watch?v=HxaD_trXwRE + +package toml + +import ( + "bytes" + "errors" + "fmt" + "regexp" + "strconv" + "strings" +) + +var dateRegexp *regexp.Regexp + +// Define state functions +type tomlLexStateFn func() tomlLexStateFn + +// Define lexer +type tomlLexer struct { + inputIdx int + input []rune // Textual source + currentTokenStart int + currentTokenStop int + tokens []token + depth int + line int + col int + endbufferLine int + endbufferCol int +} + +// Basic read operations on input + +func (l *tomlLexer) read() rune { + r := l.peek() + if r == '\n' { + l.endbufferLine++ + l.endbufferCol = 1 + } else { + l.endbufferCol++ + } + l.inputIdx++ + return r +} + +func (l *tomlLexer) next() rune { + r := l.read() + + if r != eof { + l.currentTokenStop++ + } + return r +} + +func (l *tomlLexer) ignore() { + l.currentTokenStart = l.currentTokenStop + l.line = l.endbufferLine + l.col = l.endbufferCol +} + +func (l *tomlLexer) skip() { + l.next() + l.ignore() +} + +func (l *tomlLexer) fastForward(n int) { + for i := 0; i < n; i++ { + l.next() + } +} + +func (l *tomlLexer) emitWithValue(t tokenType, value string) { + l.tokens = append(l.tokens, token{ + Position: Position{l.line, l.col}, + typ: t, + val: value, + }) + l.ignore() +} + +func (l *tomlLexer) emit(t tokenType) { + l.emitWithValue(t, string(l.input[l.currentTokenStart:l.currentTokenStop])) +} + +func (l *tomlLexer) peek() rune { + if l.inputIdx >= len(l.input) { + return eof + } + return l.input[l.inputIdx] +} + +func (l *tomlLexer) peekString(size int) string { + maxIdx := len(l.input) + upperIdx := l.inputIdx + size // FIXME: potential overflow + if upperIdx > maxIdx { + upperIdx = maxIdx + } + return string(l.input[l.inputIdx:upperIdx]) +} + +func (l *tomlLexer) follow(next string) bool { + return next == l.peekString(len(next)) +} + +// Error management + +func (l *tomlLexer) errorf(format string, args ...interface{}) tomlLexStateFn { + l.tokens = append(l.tokens, token{ + Position: Position{l.line, l.col}, + typ: tokenError, + val: fmt.Sprintf(format, args...), + }) + return nil +} + +// State functions + +func (l *tomlLexer) lexVoid() tomlLexStateFn { + for { + next := l.peek() + switch next { + case '[': + return l.lexTableKey + case '#': + return l.lexComment(l.lexVoid) + case '=': + return l.lexEqual + case '\r': + fallthrough + case '\n': + l.skip() + continue + } + + if isSpace(next) { + l.skip() + } + + if l.depth > 0 { + return l.lexRvalue + } + + if isKeyStartChar(next) { + return l.lexKey + } + + if next == eof { + l.next() + break + } + } + + l.emit(tokenEOF) + return nil +} + +func (l *tomlLexer) lexRvalue() tomlLexStateFn { + for { + next := l.peek() + switch next { + case '.': + return l.errorf("cannot start float with a dot") + case '=': + return l.lexEqual + case '[': + l.depth++ + return l.lexLeftBracket + case ']': + l.depth-- + return l.lexRightBracket + case '{': + return l.lexLeftCurlyBrace + case '}': + return l.lexRightCurlyBrace + case '#': + return l.lexComment(l.lexRvalue) + case '"': + return l.lexString + case '\'': + return l.lexLiteralString + case ',': + return l.lexComma + case '\r': + fallthrough + case '\n': + l.skip() + if l.depth == 0 { + return l.lexVoid + } + return l.lexRvalue + case '_': + return l.errorf("cannot start number with underscore") + } + + if l.follow("true") { + return l.lexTrue + } + + if l.follow("false") { + return l.lexFalse + } + + if l.follow("inf") { + return l.lexInf + } + + if l.follow("nan") { + return l.lexNan + } + + if isSpace(next) { + l.skip() + continue + } + + if next == eof { + l.next() + break + } + + possibleDate := l.peekString(35) + dateSubmatches := dateRegexp.FindStringSubmatch(possibleDate) + if dateSubmatches != nil && dateSubmatches[0] != "" { + l.fastForward(len(dateSubmatches[0])) + if dateSubmatches[2] == "" { // no timezone information => local date + return l.lexLocalDate + } + return l.lexDate + } + + if next == '+' || next == '-' || isDigit(next) { + return l.lexNumber + } + + if isAlphanumeric(next) { + return l.lexKey + } + + return l.errorf("no value can start with %c", next) + } + + l.emit(tokenEOF) + return nil +} + +func (l *tomlLexer) lexLeftCurlyBrace() tomlLexStateFn { + l.next() + l.emit(tokenLeftCurlyBrace) + return l.lexVoid +} + +func (l *tomlLexer) lexRightCurlyBrace() tomlLexStateFn { + l.next() + l.emit(tokenRightCurlyBrace) + return l.lexVoid +} + +func (l *tomlLexer) lexDate() tomlLexStateFn { + l.emit(tokenDate) + return l.lexRvalue +} + +func (l *tomlLexer) lexLocalDate() tomlLexStateFn { + l.emit(tokenLocalDate) + return l.lexRvalue +} + +func (l *tomlLexer) lexTrue() tomlLexStateFn { + l.fastForward(4) + l.emit(tokenTrue) + return l.lexRvalue +} + +func (l *tomlLexer) lexFalse() tomlLexStateFn { + l.fastForward(5) + l.emit(tokenFalse) + return l.lexRvalue +} + +func (l *tomlLexer) lexInf() tomlLexStateFn { + l.fastForward(3) + l.emit(tokenInf) + return l.lexRvalue +} + +func (l *tomlLexer) lexNan() tomlLexStateFn { + l.fastForward(3) + l.emit(tokenNan) + return l.lexRvalue +} + +func (l *tomlLexer) lexEqual() tomlLexStateFn { + l.next() + l.emit(tokenEqual) + return l.lexRvalue +} + +func (l *tomlLexer) lexComma() tomlLexStateFn { + l.next() + l.emit(tokenComma) + return l.lexRvalue +} + +// Parse the key and emits its value without escape sequences. +// bare keys, basic string keys and literal string keys are supported. +func (l *tomlLexer) lexKey() tomlLexStateFn { + growingString := "" + + for r := l.peek(); isKeyChar(r) || r == '\n' || r == '\r'; r = l.peek() { + if r == '"' { + l.next() + str, err := l.lexStringAsString(`"`, false, true) + if err != nil { + return l.errorf(err.Error()) + } + growingString += "\"" + str + "\"" + l.next() + continue + } else if r == '\'' { + l.next() + str, err := l.lexLiteralStringAsString(`'`, false) + if err != nil { + return l.errorf(err.Error()) + } + growingString += "'" + str + "'" + l.next() + continue + } else if r == '\n' { + return l.errorf("keys cannot contain new lines") + } else if isSpace(r) { + break + } else if r == '.' { + // skip + } else if !isValidBareChar(r) { + return l.errorf("keys cannot contain %c character", r) + } + growingString += string(r) + l.next() + } + l.emitWithValue(tokenKey, growingString) + return l.lexVoid +} + +func (l *tomlLexer) lexComment(previousState tomlLexStateFn) tomlLexStateFn { + return func() tomlLexStateFn { + for next := l.peek(); next != '\n' && next != eof; next = l.peek() { + if next == '\r' && l.follow("\r\n") { + break + } + l.next() + } + l.ignore() + return previousState + } +} + +func (l *tomlLexer) lexLeftBracket() tomlLexStateFn { + l.next() + l.emit(tokenLeftBracket) + return l.lexRvalue +} + +func (l *tomlLexer) lexLiteralStringAsString(terminator string, discardLeadingNewLine bool) (string, error) { + growingString := "" + + if discardLeadingNewLine { + if l.follow("\r\n") { + l.skip() + l.skip() + } else if l.peek() == '\n' { + l.skip() + } + } + + // find end of string + for { + if l.follow(terminator) { + return growingString, nil + } + + next := l.peek() + if next == eof { + break + } + growingString += string(l.next()) + } + + return "", errors.New("unclosed string") +} + +func (l *tomlLexer) lexLiteralString() tomlLexStateFn { + l.skip() + + // handle special case for triple-quote + terminator := "'" + discardLeadingNewLine := false + if l.follow("''") { + l.skip() + l.skip() + terminator = "'''" + discardLeadingNewLine = true + } + + str, err := l.lexLiteralStringAsString(terminator, discardLeadingNewLine) + if err != nil { + return l.errorf(err.Error()) + } + + l.emitWithValue(tokenString, str) + l.fastForward(len(terminator)) + l.ignore() + return l.lexRvalue +} + +// Lex a string and return the results as a string. +// Terminator is the substring indicating the end of the token. +// The resulting string does not include the terminator. +func (l *tomlLexer) lexStringAsString(terminator string, discardLeadingNewLine, acceptNewLines bool) (string, error) { + growingString := "" + + if discardLeadingNewLine { + if l.follow("\r\n") { + l.skip() + l.skip() + } else if l.peek() == '\n' { + l.skip() + } + } + + for { + if l.follow(terminator) { + return growingString, nil + } + + if l.follow("\\") { + l.next() + switch l.peek() { + case '\r': + fallthrough + case '\n': + fallthrough + case '\t': + fallthrough + case ' ': + // skip all whitespace chars following backslash + for strings.ContainsRune("\r\n\t ", l.peek()) { + l.next() + } + case '"': + growingString += "\"" + l.next() + case 'n': + growingString += "\n" + l.next() + case 'b': + growingString += "\b" + l.next() + case 'f': + growingString += "\f" + l.next() + case '/': + growingString += "/" + l.next() + case 't': + growingString += "\t" + l.next() + case 'r': + growingString += "\r" + l.next() + case '\\': + growingString += "\\" + l.next() + case 'u': + l.next() + code := "" + for i := 0; i < 4; i++ { + c := l.peek() + if !isHexDigit(c) { + return "", errors.New("unfinished unicode escape") + } + l.next() + code = code + string(c) + } + intcode, err := strconv.ParseInt(code, 16, 32) + if err != nil { + return "", errors.New("invalid unicode escape: \\u" + code) + } + growingString += string(rune(intcode)) + case 'U': + l.next() + code := "" + for i := 0; i < 8; i++ { + c := l.peek() + if !isHexDigit(c) { + return "", errors.New("unfinished unicode escape") + } + l.next() + code = code + string(c) + } + intcode, err := strconv.ParseInt(code, 16, 64) + if err != nil { + return "", errors.New("invalid unicode escape: \\U" + code) + } + growingString += string(rune(intcode)) + default: + return "", errors.New("invalid escape sequence: \\" + string(l.peek())) + } + } else { + r := l.peek() + + if 0x00 <= r && r <= 0x1F && !(acceptNewLines && (r == '\n' || r == '\r')) { + return "", fmt.Errorf("unescaped control character %U", r) + } + l.next() + growingString += string(r) + } + + if l.peek() == eof { + break + } + } + + return "", errors.New("unclosed string") +} + +func (l *tomlLexer) lexString() tomlLexStateFn { + l.skip() + + // handle special case for triple-quote + terminator := `"` + discardLeadingNewLine := false + acceptNewLines := false + if l.follow(`""`) { + l.skip() + l.skip() + terminator = `"""` + discardLeadingNewLine = true + acceptNewLines = true + } + + str, err := l.lexStringAsString(terminator, discardLeadingNewLine, acceptNewLines) + + if err != nil { + return l.errorf(err.Error()) + } + + l.emitWithValue(tokenString, str) + l.fastForward(len(terminator)) + l.ignore() + return l.lexRvalue +} + +func (l *tomlLexer) lexTableKey() tomlLexStateFn { + l.next() + + if l.peek() == '[' { + // token '[[' signifies an array of tables + l.next() + l.emit(tokenDoubleLeftBracket) + return l.lexInsideTableArrayKey + } + // vanilla table key + l.emit(tokenLeftBracket) + return l.lexInsideTableKey +} + +// Parse the key till "]]", but only bare keys are supported +func (l *tomlLexer) lexInsideTableArrayKey() tomlLexStateFn { + for r := l.peek(); r != eof; r = l.peek() { + switch r { + case ']': + if l.currentTokenStop > l.currentTokenStart { + l.emit(tokenKeyGroupArray) + } + l.next() + if l.peek() != ']' { + break + } + l.next() + l.emit(tokenDoubleRightBracket) + return l.lexVoid + case '[': + return l.errorf("table array key cannot contain ']'") + default: + l.next() + } + } + return l.errorf("unclosed table array key") +} + +// Parse the key till "]" but only bare keys are supported +func (l *tomlLexer) lexInsideTableKey() tomlLexStateFn { + for r := l.peek(); r != eof; r = l.peek() { + switch r { + case ']': + if l.currentTokenStop > l.currentTokenStart { + l.emit(tokenKeyGroup) + } + l.next() + l.emit(tokenRightBracket) + return l.lexVoid + case '[': + return l.errorf("table key cannot contain ']'") + default: + l.next() + } + } + return l.errorf("unclosed table key") +} + +func (l *tomlLexer) lexRightBracket() tomlLexStateFn { + l.next() + l.emit(tokenRightBracket) + return l.lexRvalue +} + +type validRuneFn func(r rune) bool + +func isValidHexRune(r rune) bool { + return r >= 'a' && r <= 'f' || + r >= 'A' && r <= 'F' || + r >= '0' && r <= '9' || + r == '_' +} + +func isValidOctalRune(r rune) bool { + return r >= '0' && r <= '7' || r == '_' +} + +func isValidBinaryRune(r rune) bool { + return r == '0' || r == '1' || r == '_' +} + +func (l *tomlLexer) lexNumber() tomlLexStateFn { + r := l.peek() + + if r == '0' { + follow := l.peekString(2) + if len(follow) == 2 { + var isValidRune validRuneFn + switch follow[1] { + case 'x': + isValidRune = isValidHexRune + case 'o': + isValidRune = isValidOctalRune + case 'b': + isValidRune = isValidBinaryRune + default: + if follow[1] >= 'a' && follow[1] <= 'z' || follow[1] >= 'A' && follow[1] <= 'Z' { + return l.errorf("unknown number base: %s. possible options are x (hex) o (octal) b (binary)", string(follow[1])) + } + } + + if isValidRune != nil { + l.next() + l.next() + digitSeen := false + for { + next := l.peek() + if !isValidRune(next) { + break + } + digitSeen = true + l.next() + } + + if !digitSeen { + return l.errorf("number needs at least one digit") + } + + l.emit(tokenInteger) + + return l.lexRvalue + } + } + } + + if r == '+' || r == '-' { + l.next() + if l.follow("inf") { + return l.lexInf + } + if l.follow("nan") { + return l.lexNan + } + } + + pointSeen := false + expSeen := false + digitSeen := false + for { + next := l.peek() + if next == '.' { + if pointSeen { + return l.errorf("cannot have two dots in one float") + } + l.next() + if !isDigit(l.peek()) { + return l.errorf("float cannot end with a dot") + } + pointSeen = true + } else if next == 'e' || next == 'E' { + expSeen = true + l.next() + r := l.peek() + if r == '+' || r == '-' { + l.next() + } + } else if isDigit(next) { + digitSeen = true + l.next() + } else if next == '_' { + l.next() + } else { + break + } + if pointSeen && !digitSeen { + return l.errorf("cannot start float with a dot") + } + } + + if !digitSeen { + return l.errorf("no digit in that number") + } + if pointSeen || expSeen { + l.emit(tokenFloat) + } else { + l.emit(tokenInteger) + } + return l.lexRvalue +} + +func (l *tomlLexer) run() { + for state := l.lexVoid; state != nil; { + state = state() + } +} + +func init() { + // Regexp for all date/time formats supported by TOML. + // Group 1: nano precision + // Group 2: timezone + // + // /!\ also matches the empty string + // + // Example matches: + //1979-05-27T07:32:00Z + //1979-05-27T00:32:00-07:00 + //1979-05-27T00:32:00.999999-07:00 + //1979-05-27 07:32:00Z + //1979-05-27 00:32:00-07:00 + //1979-05-27 00:32:00.999999-07:00 + //1979-05-27T07:32:00 + //1979-05-27T00:32:00.999999 + //1979-05-27 07:32:00 + //1979-05-27 00:32:00.999999 + //1979-05-27 + //07:32:00 + //00:32:00.999999 + dateRegexp = regexp.MustCompile(`^(?:\d{1,4}-\d{2}-\d{2})?(?:[T ]?\d{2}:\d{2}:\d{2}(\.\d{1,9})?(Z|[+-]\d{2}:\d{2})?)?`) +} + +// Entry point +func lexToml(inputBytes []byte) []token { + runes := bytes.Runes(inputBytes) + l := &tomlLexer{ + input: runes, + tokens: make([]token, 0, 256), + line: 1, + col: 1, + endbufferLine: 1, + endbufferCol: 1, + } + l.run() + return l.tokens +} diff --git a/vendor/github.com/pelletier/go-toml/localtime.go b/vendor/github.com/pelletier/go-toml/localtime.go new file mode 100644 index 00000000000..a2149e9663a --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/localtime.go @@ -0,0 +1,281 @@ +// Implementation of TOML's local date/time. +// Copied over from https://github.com/googleapis/google-cloud-go/blob/master/civil/civil.go +// to avoid pulling all the Google dependencies. +// +// Copyright 2016 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package civil implements types for civil time, a time-zone-independent +// representation of time that follows the rules of the proleptic +// Gregorian calendar with exactly 24-hour days, 60-minute hours, and 60-second +// minutes. +// +// Because they lack location information, these types do not represent unique +// moments or intervals of time. Use time.Time for that purpose. +package toml + +import ( + "fmt" + "time" +) + +// A LocalDate represents a date (year, month, day). +// +// This type does not include location information, and therefore does not +// describe a unique 24-hour timespan. +type LocalDate struct { + Year int // Year (e.g., 2014). + Month time.Month // Month of the year (January = 1, ...). + Day int // Day of the month, starting at 1. +} + +// LocalDateOf returns the LocalDate in which a time occurs in that time's location. +func LocalDateOf(t time.Time) LocalDate { + var d LocalDate + d.Year, d.Month, d.Day = t.Date() + return d +} + +// ParseLocalDate parses a string in RFC3339 full-date format and returns the date value it represents. +func ParseLocalDate(s string) (LocalDate, error) { + t, err := time.Parse("2006-01-02", s) + if err != nil { + return LocalDate{}, err + } + return LocalDateOf(t), nil +} + +// String returns the date in RFC3339 full-date format. +func (d LocalDate) String() string { + return fmt.Sprintf("%04d-%02d-%02d", d.Year, d.Month, d.Day) +} + +// IsValid reports whether the date is valid. +func (d LocalDate) IsValid() bool { + return LocalDateOf(d.In(time.UTC)) == d +} + +// In returns the time corresponding to time 00:00:00 of the date in the location. +// +// In is always consistent with time.LocalDate, even when time.LocalDate returns a time +// on a different day. For example, if loc is America/Indiana/Vincennes, then both +// time.LocalDate(1955, time.May, 1, 0, 0, 0, 0, loc) +// and +// civil.LocalDate{Year: 1955, Month: time.May, Day: 1}.In(loc) +// return 23:00:00 on April 30, 1955. +// +// In panics if loc is nil. +func (d LocalDate) In(loc *time.Location) time.Time { + return time.Date(d.Year, d.Month, d.Day, 0, 0, 0, 0, loc) +} + +// AddDays returns the date that is n days in the future. +// n can also be negative to go into the past. +func (d LocalDate) AddDays(n int) LocalDate { + return LocalDateOf(d.In(time.UTC).AddDate(0, 0, n)) +} + +// DaysSince returns the signed number of days between the date and s, not including the end day. +// This is the inverse operation to AddDays. +func (d LocalDate) DaysSince(s LocalDate) (days int) { + // We convert to Unix time so we do not have to worry about leap seconds: + // Unix time increases by exactly 86400 seconds per day. + deltaUnix := d.In(time.UTC).Unix() - s.In(time.UTC).Unix() + return int(deltaUnix / 86400) +} + +// Before reports whether d1 occurs before d2. +func (d1 LocalDate) Before(d2 LocalDate) bool { + if d1.Year != d2.Year { + return d1.Year < d2.Year + } + if d1.Month != d2.Month { + return d1.Month < d2.Month + } + return d1.Day < d2.Day +} + +// After reports whether d1 occurs after d2. +func (d1 LocalDate) After(d2 LocalDate) bool { + return d2.Before(d1) +} + +// MarshalText implements the encoding.TextMarshaler interface. +// The output is the result of d.String(). +func (d LocalDate) MarshalText() ([]byte, error) { + return []byte(d.String()), nil +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +// The date is expected to be a string in a format accepted by ParseLocalDate. +func (d *LocalDate) UnmarshalText(data []byte) error { + var err error + *d, err = ParseLocalDate(string(data)) + return err +} + +// A LocalTime represents a time with nanosecond precision. +// +// This type does not include location information, and therefore does not +// describe a unique moment in time. +// +// This type exists to represent the TIME type in storage-based APIs like BigQuery. +// Most operations on Times are unlikely to be meaningful. Prefer the LocalDateTime type. +type LocalTime struct { + Hour int // The hour of the day in 24-hour format; range [0-23] + Minute int // The minute of the hour; range [0-59] + Second int // The second of the minute; range [0-59] + Nanosecond int // The nanosecond of the second; range [0-999999999] +} + +// LocalTimeOf returns the LocalTime representing the time of day in which a time occurs +// in that time's location. It ignores the date. +func LocalTimeOf(t time.Time) LocalTime { + var tm LocalTime + tm.Hour, tm.Minute, tm.Second = t.Clock() + tm.Nanosecond = t.Nanosecond() + return tm +} + +// ParseLocalTime parses a string and returns the time value it represents. +// ParseLocalTime accepts an extended form of the RFC3339 partial-time format. After +// the HH:MM:SS part of the string, an optional fractional part may appear, +// consisting of a decimal point followed by one to nine decimal digits. +// (RFC3339 admits only one digit after the decimal point). +func ParseLocalTime(s string) (LocalTime, error) { + t, err := time.Parse("15:04:05.999999999", s) + if err != nil { + return LocalTime{}, err + } + return LocalTimeOf(t), nil +} + +// String returns the date in the format described in ParseLocalTime. If Nanoseconds +// is zero, no fractional part will be generated. Otherwise, the result will +// end with a fractional part consisting of a decimal point and nine digits. +func (t LocalTime) String() string { + s := fmt.Sprintf("%02d:%02d:%02d", t.Hour, t.Minute, t.Second) + if t.Nanosecond == 0 { + return s + } + return s + fmt.Sprintf(".%09d", t.Nanosecond) +} + +// IsValid reports whether the time is valid. +func (t LocalTime) IsValid() bool { + // Construct a non-zero time. + tm := time.Date(2, 2, 2, t.Hour, t.Minute, t.Second, t.Nanosecond, time.UTC) + return LocalTimeOf(tm) == t +} + +// MarshalText implements the encoding.TextMarshaler interface. +// The output is the result of t.String(). +func (t LocalTime) MarshalText() ([]byte, error) { + return []byte(t.String()), nil +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +// The time is expected to be a string in a format accepted by ParseLocalTime. +func (t *LocalTime) UnmarshalText(data []byte) error { + var err error + *t, err = ParseLocalTime(string(data)) + return err +} + +// A LocalDateTime represents a date and time. +// +// This type does not include location information, and therefore does not +// describe a unique moment in time. +type LocalDateTime struct { + Date LocalDate + Time LocalTime +} + +// Note: We deliberately do not embed LocalDate into LocalDateTime, to avoid promoting AddDays and Sub. + +// LocalDateTimeOf returns the LocalDateTime in which a time occurs in that time's location. +func LocalDateTimeOf(t time.Time) LocalDateTime { + return LocalDateTime{ + Date: LocalDateOf(t), + Time: LocalTimeOf(t), + } +} + +// ParseLocalDateTime parses a string and returns the LocalDateTime it represents. +// ParseLocalDateTime accepts a variant of the RFC3339 date-time format that omits +// the time offset but includes an optional fractional time, as described in +// ParseLocalTime. Informally, the accepted format is +// YYYY-MM-DDTHH:MM:SS[.FFFFFFFFF] +// where the 'T' may be a lower-case 't'. +func ParseLocalDateTime(s string) (LocalDateTime, error) { + t, err := time.Parse("2006-01-02T15:04:05.999999999", s) + if err != nil { + t, err = time.Parse("2006-01-02t15:04:05.999999999", s) + if err != nil { + return LocalDateTime{}, err + } + } + return LocalDateTimeOf(t), nil +} + +// String returns the date in the format described in ParseLocalDate. +func (dt LocalDateTime) String() string { + return dt.Date.String() + "T" + dt.Time.String() +} + +// IsValid reports whether the datetime is valid. +func (dt LocalDateTime) IsValid() bool { + return dt.Date.IsValid() && dt.Time.IsValid() +} + +// In returns the time corresponding to the LocalDateTime in the given location. +// +// If the time is missing or ambigous at the location, In returns the same +// result as time.LocalDate. For example, if loc is America/Indiana/Vincennes, then +// both +// time.LocalDate(1955, time.May, 1, 0, 30, 0, 0, loc) +// and +// civil.LocalDateTime{ +// civil.LocalDate{Year: 1955, Month: time.May, Day: 1}}, +// civil.LocalTime{Minute: 30}}.In(loc) +// return 23:30:00 on April 30, 1955. +// +// In panics if loc is nil. +func (dt LocalDateTime) In(loc *time.Location) time.Time { + return time.Date(dt.Date.Year, dt.Date.Month, dt.Date.Day, dt.Time.Hour, dt.Time.Minute, dt.Time.Second, dt.Time.Nanosecond, loc) +} + +// Before reports whether dt1 occurs before dt2. +func (dt1 LocalDateTime) Before(dt2 LocalDateTime) bool { + return dt1.In(time.UTC).Before(dt2.In(time.UTC)) +} + +// After reports whether dt1 occurs after dt2. +func (dt1 LocalDateTime) After(dt2 LocalDateTime) bool { + return dt2.Before(dt1) +} + +// MarshalText implements the encoding.TextMarshaler interface. +// The output is the result of dt.String(). +func (dt LocalDateTime) MarshalText() ([]byte, error) { + return []byte(dt.String()), nil +} + +// UnmarshalText implements the encoding.TextUnmarshaler interface. +// The datetime is expected to be a string in a format accepted by ParseLocalDateTime +func (dt *LocalDateTime) UnmarshalText(data []byte) error { + var err error + *dt, err = ParseLocalDateTime(string(data)) + return err +} diff --git a/vendor/github.com/pelletier/go-toml/marshal.go b/vendor/github.com/pelletier/go-toml/marshal.go new file mode 100644 index 00000000000..2a6cfbae423 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/marshal.go @@ -0,0 +1,868 @@ +package toml + +import ( + "bytes" + "errors" + "fmt" + "io" + "reflect" + "sort" + "strconv" + "strings" + "time" +) + +const ( + tagFieldName = "toml" + tagFieldComment = "comment" + tagCommented = "commented" + tagMultiline = "multiline" + tagDefault = "default" +) + +type tomlOpts struct { + name string + comment string + commented bool + multiline bool + include bool + omitempty bool + defaultValue string +} + +type encOpts struct { + quoteMapKeys bool + arraysOneElementPerLine bool +} + +var encOptsDefaults = encOpts{ + quoteMapKeys: false, +} + +type annotation struct { + tag string + comment string + commented string + multiline string + defaultValue string +} + +var annotationDefault = annotation{ + tag: tagFieldName, + comment: tagFieldComment, + commented: tagCommented, + multiline: tagMultiline, + defaultValue: tagDefault, +} + +type marshalOrder int + +// Orders the Encoder can write the fields to the output stream. +const ( + // Sort fields alphabetically. + OrderAlphabetical marshalOrder = iota + 1 + // Preserve the order the fields are encountered. For example, the order of fields in + // a struct. + OrderPreserve +) + +var timeType = reflect.TypeOf(time.Time{}) +var marshalerType = reflect.TypeOf(new(Marshaler)).Elem() +var localDateType = reflect.TypeOf(LocalDate{}) +var localTimeType = reflect.TypeOf(LocalTime{}) +var localDateTimeType = reflect.TypeOf(LocalDateTime{}) + +// Check if the given marshal type maps to a Tree primitive +func isPrimitive(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Ptr: + return isPrimitive(mtype.Elem()) + case reflect.Bool: + return true + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return true + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return true + case reflect.Float32, reflect.Float64: + return true + case reflect.String: + return true + case reflect.Struct: + return mtype == timeType || mtype == localDateType || mtype == localDateTimeType || mtype == localTimeType || isCustomMarshaler(mtype) + default: + return false + } +} + +// Check if the given marshal type maps to a Tree slice or array +func isTreeSequence(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Ptr: + return isTreeSequence(mtype.Elem()) + case reflect.Slice, reflect.Array: + return isTree(mtype.Elem()) + default: + return false + } +} + +// Check if the given marshal type maps to a non-Tree slice or array +func isOtherSequence(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Ptr: + return isOtherSequence(mtype.Elem()) + case reflect.Slice, reflect.Array: + return !isTreeSequence(mtype) + default: + return false + } +} + +// Check if the given marshal type maps to a Tree +func isTree(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Ptr: + return isTree(mtype.Elem()) + case reflect.Map: + return true + case reflect.Struct: + return !isPrimitive(mtype) + default: + return false + } +} + +func isCustomMarshaler(mtype reflect.Type) bool { + return mtype.Implements(marshalerType) +} + +func callCustomMarshaler(mval reflect.Value) ([]byte, error) { + return mval.Interface().(Marshaler).MarshalTOML() +} + +// Marshaler is the interface implemented by types that +// can marshal themselves into valid TOML. +type Marshaler interface { + MarshalTOML() ([]byte, error) +} + +/* +Marshal returns the TOML encoding of v. Behavior is similar to the Go json +encoder, except that there is no concept of a Marshaler interface or MarshalTOML +function for sub-structs, and currently only definite types can be marshaled +(i.e. no `interface{}`). + +The following struct annotations are supported: + + toml:"Field" Overrides the field's name to output. + omitempty When set, empty values and groups are not emitted. + comment:"comment" Emits a # comment on the same line. This supports new lines. + commented:"true" Emits the value as commented. + +Note that pointers are automatically assigned the "omitempty" option, as TOML +explicitly does not handle null values (saying instead the label should be +dropped). + +Tree structural types and corresponding marshal types: + + *Tree (*)struct, (*)map[string]interface{} + []*Tree (*)[](*)struct, (*)[](*)map[string]interface{} + []interface{} (as interface{}) (*)[]primitive, (*)[]([]interface{}) + interface{} (*)primitive + +Tree primitive types and corresponding marshal types: + + uint64 uint, uint8-uint64, pointers to same + int64 int, int8-uint64, pointers to same + float64 float32, float64, pointers to same + string string, pointers to same + bool bool, pointers to same + time.LocalTime time.LocalTime{}, pointers to same + +For additional flexibility, use the Encoder API. +*/ +func Marshal(v interface{}) ([]byte, error) { + return NewEncoder(nil).marshal(v) +} + +// Encoder writes TOML values to an output stream. +type Encoder struct { + w io.Writer + encOpts + annotation + line int + col int + order marshalOrder +} + +// NewEncoder returns a new encoder that writes to w. +func NewEncoder(w io.Writer) *Encoder { + return &Encoder{ + w: w, + encOpts: encOptsDefaults, + annotation: annotationDefault, + line: 0, + col: 1, + order: OrderAlphabetical, + } +} + +// Encode writes the TOML encoding of v to the stream. +// +// See the documentation for Marshal for details. +func (e *Encoder) Encode(v interface{}) error { + b, err := e.marshal(v) + if err != nil { + return err + } + if _, err := e.w.Write(b); err != nil { + return err + } + return nil +} + +// QuoteMapKeys sets up the encoder to encode +// maps with string type keys with quoted TOML keys. +// +// This relieves the character limitations on map keys. +func (e *Encoder) QuoteMapKeys(v bool) *Encoder { + e.quoteMapKeys = v + return e +} + +// ArraysWithOneElementPerLine sets up the encoder to encode arrays +// with more than one element on multiple lines instead of one. +// +// For example: +// +// A = [1,2,3] +// +// Becomes +// +// A = [ +// 1, +// 2, +// 3, +// ] +func (e *Encoder) ArraysWithOneElementPerLine(v bool) *Encoder { + e.arraysOneElementPerLine = v + return e +} + +// Order allows to change in which order fields will be written to the output stream. +func (e *Encoder) Order(ord marshalOrder) *Encoder { + e.order = ord + return e +} + +// SetTagName allows changing default tag "toml" +func (e *Encoder) SetTagName(v string) *Encoder { + e.tag = v + return e +} + +// SetTagComment allows changing default tag "comment" +func (e *Encoder) SetTagComment(v string) *Encoder { + e.comment = v + return e +} + +// SetTagCommented allows changing default tag "commented" +func (e *Encoder) SetTagCommented(v string) *Encoder { + e.commented = v + return e +} + +// SetTagMultiline allows changing default tag "multiline" +func (e *Encoder) SetTagMultiline(v string) *Encoder { + e.multiline = v + return e +} + +func (e *Encoder) marshal(v interface{}) ([]byte, error) { + mtype := reflect.TypeOf(v) + + switch mtype.Kind() { + case reflect.Struct, reflect.Map: + case reflect.Ptr: + if mtype.Elem().Kind() != reflect.Struct { + return []byte{}, errors.New("Only pointer to struct can be marshaled to TOML") + } + default: + return []byte{}, errors.New("Only a struct or map can be marshaled to TOML") + } + + sval := reflect.ValueOf(v) + if isCustomMarshaler(mtype) { + return callCustomMarshaler(sval) + } + t, err := e.valueToTree(mtype, sval) + if err != nil { + return []byte{}, err + } + + var buf bytes.Buffer + _, err = t.writeToOrdered(&buf, "", "", 0, e.arraysOneElementPerLine, e.order) + + return buf.Bytes(), err +} + +// Create next tree with a position based on Encoder.line +func (e *Encoder) nextTree() *Tree { + return newTreeWithPosition(Position{Line: e.line, Col: 1}) +} + +// Convert given marshal struct or map value to toml tree +func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, error) { + if mtype.Kind() == reflect.Ptr { + return e.valueToTree(mtype.Elem(), mval.Elem()) + } + tval := e.nextTree() + switch mtype.Kind() { + case reflect.Struct: + for i := 0; i < mtype.NumField(); i++ { + mtypef, mvalf := mtype.Field(i), mval.Field(i) + opts := tomlOptions(mtypef, e.annotation) + if opts.include && (!opts.omitempty || !isZero(mvalf)) { + val, err := e.valueToToml(mtypef.Type, mvalf) + if err != nil { + return nil, err + } + + tval.SetWithOptions(opts.name, SetOptions{ + Comment: opts.comment, + Commented: opts.commented, + Multiline: opts.multiline, + }, val) + } + } + case reflect.Map: + keys := mval.MapKeys() + if e.order == OrderPreserve && len(keys) > 0 { + // Sorting []reflect.Value is not straight forward. + // + // OrderPreserve will support deterministic results when string is used + // as the key to maps. + typ := keys[0].Type() + kind := keys[0].Kind() + if kind == reflect.String { + ikeys := make([]string, len(keys)) + for i := range keys { + ikeys[i] = keys[i].Interface().(string) + } + sort.Strings(ikeys) + for i := range ikeys { + keys[i] = reflect.ValueOf(ikeys[i]).Convert(typ) + } + } + } + for _, key := range keys { + mvalf := mval.MapIndex(key) + val, err := e.valueToToml(mtype.Elem(), mvalf) + if err != nil { + return nil, err + } + if e.quoteMapKeys { + keyStr, err := tomlValueStringRepresentation(key.String(), "", e.arraysOneElementPerLine) + if err != nil { + return nil, err + } + tval.SetPath([]string{keyStr}, val) + } else { + tval.Set(key.String(), val) + } + } + } + return tval, nil +} + +// Convert given marshal slice to slice of Toml trees +func (e *Encoder) valueToTreeSlice(mtype reflect.Type, mval reflect.Value) ([]*Tree, error) { + tval := make([]*Tree, mval.Len(), mval.Len()) + for i := 0; i < mval.Len(); i++ { + val, err := e.valueToTree(mtype.Elem(), mval.Index(i)) + if err != nil { + return nil, err + } + tval[i] = val + } + return tval, nil +} + +// Convert given marshal slice to slice of toml values +func (e *Encoder) valueToOtherSlice(mtype reflect.Type, mval reflect.Value) (interface{}, error) { + tval := make([]interface{}, mval.Len(), mval.Len()) + for i := 0; i < mval.Len(); i++ { + val, err := e.valueToToml(mtype.Elem(), mval.Index(i)) + if err != nil { + return nil, err + } + tval[i] = val + } + return tval, nil +} + +// Convert given marshal value to toml value +func (e *Encoder) valueToToml(mtype reflect.Type, mval reflect.Value) (interface{}, error) { + e.line++ + if mtype.Kind() == reflect.Ptr { + return e.valueToToml(mtype.Elem(), mval.Elem()) + } + switch { + case isCustomMarshaler(mtype): + return callCustomMarshaler(mval) + case isTree(mtype): + return e.valueToTree(mtype, mval) + case isTreeSequence(mtype): + return e.valueToTreeSlice(mtype, mval) + case isOtherSequence(mtype): + return e.valueToOtherSlice(mtype, mval) + default: + switch mtype.Kind() { + case reflect.Bool: + return mval.Bool(), nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + if mtype.Kind() == reflect.Int64 && mtype == reflect.TypeOf(time.Duration(1)) { + return fmt.Sprint(mval), nil + } + return mval.Int(), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: + return mval.Uint(), nil + case reflect.Float32, reflect.Float64: + return mval.Float(), nil + case reflect.String: + return mval.String(), nil + case reflect.Struct: + return mval.Interface(), nil + default: + return nil, fmt.Errorf("Marshal can't handle %v(%v)", mtype, mtype.Kind()) + } + } +} + +// Unmarshal attempts to unmarshal the Tree into a Go struct pointed by v. +// Neither Unmarshaler interfaces nor UnmarshalTOML functions are supported for +// sub-structs, and only definite types can be unmarshaled. +func (t *Tree) Unmarshal(v interface{}) error { + d := Decoder{tval: t, tagName: tagFieldName} + return d.unmarshal(v) +} + +// Marshal returns the TOML encoding of Tree. +// See Marshal() documentation for types mapping table. +func (t *Tree) Marshal() ([]byte, error) { + var buf bytes.Buffer + _, err := t.WriteTo(&buf) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// Unmarshal parses the TOML-encoded data and stores the result in the value +// pointed to by v. Behavior is similar to the Go json encoder, except that there +// is no concept of an Unmarshaler interface or UnmarshalTOML function for +// sub-structs, and currently only definite types can be unmarshaled to (i.e. no +// `interface{}`). +// +// The following struct annotations are supported: +// +// toml:"Field" Overrides the field's name to map to. +// default:"foo" Provides a default value. +// +// For default values, only fields of the following types are supported: +// * string +// * bool +// * int +// * int64 +// * float64 +// +// See Marshal() documentation for types mapping table. +func Unmarshal(data []byte, v interface{}) error { + t, err := LoadReader(bytes.NewReader(data)) + if err != nil { + return err + } + return t.Unmarshal(v) +} + +// Decoder reads and decodes TOML values from an input stream. +type Decoder struct { + r io.Reader + tval *Tree + encOpts + tagName string +} + +// NewDecoder returns a new decoder that reads from r. +func NewDecoder(r io.Reader) *Decoder { + return &Decoder{ + r: r, + encOpts: encOptsDefaults, + tagName: tagFieldName, + } +} + +// Decode reads a TOML-encoded value from it's input +// and unmarshals it in the value pointed at by v. +// +// See the documentation for Marshal for details. +func (d *Decoder) Decode(v interface{}) error { + var err error + d.tval, err = LoadReader(d.r) + if err != nil { + return err + } + return d.unmarshal(v) +} + +// SetTagName allows changing default tag "toml" +func (d *Decoder) SetTagName(v string) *Decoder { + d.tagName = v + return d +} + +func (d *Decoder) unmarshal(v interface{}) error { + mtype := reflect.TypeOf(v) + if mtype.Kind() != reflect.Ptr { + return errors.New("only a pointer to struct or map can be unmarshaled from TOML") + } + + elem := mtype.Elem() + + switch elem.Kind() { + case reflect.Struct, reflect.Map: + default: + return errors.New("only a pointer to struct or map can be unmarshaled from TOML") + } + + vv := reflect.ValueOf(v).Elem() + + sval, err := d.valueFromTree(elem, d.tval, &vv) + if err != nil { + return err + } + reflect.ValueOf(v).Elem().Set(sval) + return nil +} + +// Convert toml tree to marshal struct or map, using marshal type. When mval1 +// is non-nil, merge fields into the given value instead of allocating a new one. +func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree, mval1 *reflect.Value) (reflect.Value, error) { + if mtype.Kind() == reflect.Ptr { + return d.unwrapPointer(mtype, tval, mval1) + } + var mval reflect.Value + switch mtype.Kind() { + case reflect.Struct: + if mval1 != nil { + mval = *mval1 + } else { + mval = reflect.New(mtype).Elem() + } + + for i := 0; i < mtype.NumField(); i++ { + mtypef := mtype.Field(i) + an := annotation{tag: d.tagName} + opts := tomlOptions(mtypef, an) + if opts.include { + baseKey := opts.name + keysToTry := []string{ + baseKey, + strings.ToLower(baseKey), + strings.ToTitle(baseKey), + strings.ToLower(string(baseKey[0])) + baseKey[1:], + } + + found := false + for _, key := range keysToTry { + exists := tval.Has(key) + if !exists { + continue + } + val := tval.Get(key) + fval := mval.Field(i) + mvalf, err := d.valueFromToml(mtypef.Type, val, &fval) + if err != nil { + return mval, formatError(err, tval.GetPosition(key)) + } + mval.Field(i).Set(mvalf) + found = true + break + } + + if !found && opts.defaultValue != "" { + mvalf := mval.Field(i) + var val interface{} + var err error + switch mvalf.Kind() { + case reflect.Bool: + val, err = strconv.ParseBool(opts.defaultValue) + if err != nil { + return mval.Field(i), err + } + case reflect.Int: + val, err = strconv.Atoi(opts.defaultValue) + if err != nil { + return mval.Field(i), err + } + case reflect.String: + val = opts.defaultValue + case reflect.Int64: + val, err = strconv.ParseInt(opts.defaultValue, 10, 64) + if err != nil { + return mval.Field(i), err + } + case reflect.Float64: + val, err = strconv.ParseFloat(opts.defaultValue, 64) + if err != nil { + return mval.Field(i), err + } + default: + return mval.Field(i), fmt.Errorf("unsuported field type for default option") + } + mval.Field(i).Set(reflect.ValueOf(val)) + } + + // save the old behavior above and try to check anonymous structs + if !found && opts.defaultValue == "" && mtypef.Anonymous && mtypef.Type.Kind() == reflect.Struct { + v, err := d.valueFromTree(mtypef.Type, tval, nil) + if err != nil { + return v, err + } + mval.Field(i).Set(v) + } + } + } + case reflect.Map: + mval = reflect.MakeMap(mtype) + for _, key := range tval.Keys() { + // TODO: path splits key + val := tval.GetPath([]string{key}) + mvalf, err := d.valueFromToml(mtype.Elem(), val, nil) + if err != nil { + return mval, formatError(err, tval.GetPosition(key)) + } + mval.SetMapIndex(reflect.ValueOf(key).Convert(mtype.Key()), mvalf) + } + } + return mval, nil +} + +// Convert toml value to marshal struct/map slice, using marshal type +func (d *Decoder) valueFromTreeSlice(mtype reflect.Type, tval []*Tree) (reflect.Value, error) { + mval := reflect.MakeSlice(mtype, len(tval), len(tval)) + for i := 0; i < len(tval); i++ { + val, err := d.valueFromTree(mtype.Elem(), tval[i], nil) + if err != nil { + return mval, err + } + mval.Index(i).Set(val) + } + return mval, nil +} + +// Convert toml value to marshal primitive slice, using marshal type +func (d *Decoder) valueFromOtherSlice(mtype reflect.Type, tval []interface{}) (reflect.Value, error) { + mval := reflect.MakeSlice(mtype, len(tval), len(tval)) + for i := 0; i < len(tval); i++ { + val, err := d.valueFromToml(mtype.Elem(), tval[i], nil) + if err != nil { + return mval, err + } + mval.Index(i).Set(val) + } + return mval, nil +} + +// Convert toml value to marshal value, using marshal type. When mval1 is non-nil +// and the given type is a struct value, merge fields into it. +func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}, mval1 *reflect.Value) (reflect.Value, error) { + if mtype.Kind() == reflect.Ptr { + return d.unwrapPointer(mtype, tval, mval1) + } + + switch t := tval.(type) { + case *Tree: + var mval11 *reflect.Value + if mtype.Kind() == reflect.Struct { + mval11 = mval1 + } + + if isTree(mtype) { + return d.valueFromTree(mtype, t, mval11) + } + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a tree", tval, tval) + case []*Tree: + if isTreeSequence(mtype) { + return d.valueFromTreeSlice(mtype, t) + } + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to trees", tval, tval) + case []interface{}: + if isOtherSequence(mtype) { + return d.valueFromOtherSlice(mtype, t) + } + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a slice", tval, tval) + default: + switch mtype.Kind() { + case reflect.Bool, reflect.Struct: + val := reflect.ValueOf(tval) + + switch val.Type() { + case localDateType: + localDate := val.Interface().(LocalDate) + switch mtype { + case timeType: + return reflect.ValueOf(time.Date(localDate.Year, localDate.Month, localDate.Day, 0, 0, 0, 0, time.Local)), nil + } + case localDateTimeType: + localDateTime := val.Interface().(LocalDateTime) + switch mtype { + case timeType: + return reflect.ValueOf(time.Date( + localDateTime.Date.Year, + localDateTime.Date.Month, + localDateTime.Date.Day, + localDateTime.Time.Hour, + localDateTime.Time.Minute, + localDateTime.Time.Second, + localDateTime.Time.Nanosecond, + time.Local)), nil + } + } + + // if this passes for when mtype is reflect.Struct, tval is a time.LocalTime + if !val.Type().ConvertibleTo(mtype) { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + case reflect.String: + val := reflect.ValueOf(tval) + // stupidly, int64 is convertible to string. So special case this. + if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Int64 { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + val := reflect.ValueOf(tval) + if mtype.Kind() == reflect.Int64 && mtype == reflect.TypeOf(time.Duration(1)) && val.Kind() == reflect.String { + d, err := time.ParseDuration(val.String()) + if err != nil { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v. %s", tval, tval, mtype.String(), err) + } + return reflect.ValueOf(d), nil + } + if !val.Type().ConvertibleTo(mtype) { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + if reflect.Indirect(reflect.New(mtype)).OverflowInt(val.Convert(mtype).Int()) { + return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + val := reflect.ValueOf(tval) + if !val.Type().ConvertibleTo(mtype) { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + + if val.Convert(reflect.TypeOf(int(1))).Int() < 0 { + return reflect.ValueOf(nil), fmt.Errorf("%v(%T) is negative so does not fit in %v", tval, tval, mtype.String()) + } + if reflect.Indirect(reflect.New(mtype)).OverflowUint(uint64(val.Convert(mtype).Uint())) { + return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + case reflect.Float32, reflect.Float64: + val := reflect.ValueOf(tval) + if !val.Type().ConvertibleTo(mtype) { + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) + } + if reflect.Indirect(reflect.New(mtype)).OverflowFloat(val.Convert(mtype).Float()) { + return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String()) + } + + return val.Convert(mtype), nil + default: + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v(%v)", tval, tval, mtype, mtype.Kind()) + } + } +} + +func (d *Decoder) unwrapPointer(mtype reflect.Type, tval interface{}, mval1 *reflect.Value) (reflect.Value, error) { + var melem *reflect.Value + + if mval1 != nil && !mval1.IsNil() && mtype.Elem().Kind() == reflect.Struct { + elem := mval1.Elem() + melem = &elem + } + + val, err := d.valueFromToml(mtype.Elem(), tval, melem) + if err != nil { + return reflect.ValueOf(nil), err + } + mval := reflect.New(mtype.Elem()) + mval.Elem().Set(val) + return mval, nil +} + +func tomlOptions(vf reflect.StructField, an annotation) tomlOpts { + tag := vf.Tag.Get(an.tag) + parse := strings.Split(tag, ",") + var comment string + if c := vf.Tag.Get(an.comment); c != "" { + comment = c + } + commented, _ := strconv.ParseBool(vf.Tag.Get(an.commented)) + multiline, _ := strconv.ParseBool(vf.Tag.Get(an.multiline)) + defaultValue := vf.Tag.Get(tagDefault) + result := tomlOpts{ + name: vf.Name, + comment: comment, + commented: commented, + multiline: multiline, + include: true, + omitempty: false, + defaultValue: defaultValue, + } + if parse[0] != "" { + if parse[0] == "-" && len(parse) == 1 { + result.include = false + } else { + result.name = strings.Trim(parse[0], " ") + } + } + if vf.PkgPath != "" { + result.include = false + } + if len(parse) > 1 && strings.Trim(parse[1], " ") == "omitempty" { + result.omitempty = true + } + if vf.Type.Kind() == reflect.Ptr { + result.omitempty = true + } + return result +} + +func isZero(val reflect.Value) bool { + switch val.Type().Kind() { + case reflect.Map: + fallthrough + case reflect.Array: + fallthrough + case reflect.Slice: + return val.Len() == 0 + default: + return reflect.DeepEqual(val.Interface(), reflect.Zero(val.Type()).Interface()) + } +} + +func formatError(err error, pos Position) error { + if err.Error()[0] == '(' { // Error already contains position information + return err + } + return fmt.Errorf("%s: %s", pos, err) +} diff --git a/vendor/github.com/pelletier/go-toml/parser.go b/vendor/github.com/pelletier/go-toml/parser.go new file mode 100644 index 00000000000..1b344fee6c5 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/parser.go @@ -0,0 +1,479 @@ +// TOML Parser. + +package toml + +import ( + "errors" + "fmt" + "math" + "reflect" + "regexp" + "strconv" + "strings" + "time" +) + +type tomlParser struct { + flowIdx int + flow []token + tree *Tree + currentTable []string + seenTableKeys []string +} + +type tomlParserStateFn func() tomlParserStateFn + +// Formats and panics an error message based on a token +func (p *tomlParser) raiseError(tok *token, msg string, args ...interface{}) { + panic(tok.Position.String() + ": " + fmt.Sprintf(msg, args...)) +} + +func (p *tomlParser) run() { + for state := p.parseStart; state != nil; { + state = state() + } +} + +func (p *tomlParser) peek() *token { + if p.flowIdx >= len(p.flow) { + return nil + } + return &p.flow[p.flowIdx] +} + +func (p *tomlParser) assume(typ tokenType) { + tok := p.getToken() + if tok == nil { + p.raiseError(tok, "was expecting token %s, but token stream is empty", tok) + } + if tok.typ != typ { + p.raiseError(tok, "was expecting token %s, but got %s instead", typ, tok) + } +} + +func (p *tomlParser) getToken() *token { + tok := p.peek() + if tok == nil { + return nil + } + p.flowIdx++ + return tok +} + +func (p *tomlParser) parseStart() tomlParserStateFn { + tok := p.peek() + + // end of stream, parsing is finished + if tok == nil { + return nil + } + + switch tok.typ { + case tokenDoubleLeftBracket: + return p.parseGroupArray + case tokenLeftBracket: + return p.parseGroup + case tokenKey: + return p.parseAssign + case tokenEOF: + return nil + case tokenError: + p.raiseError(tok, "parsing error: %s", tok.String()) + default: + p.raiseError(tok, "unexpected token %s", tok.typ) + } + return nil +} + +func (p *tomlParser) parseGroupArray() tomlParserStateFn { + startToken := p.getToken() // discard the [[ + key := p.getToken() + if key.typ != tokenKeyGroupArray { + p.raiseError(key, "unexpected token %s, was expecting a table array key", key) + } + + // get or create table array element at the indicated part in the path + keys, err := parseKey(key.val) + if err != nil { + p.raiseError(key, "invalid table array key: %s", err) + } + p.tree.createSubTree(keys[:len(keys)-1], startToken.Position) // create parent entries + destTree := p.tree.GetPath(keys) + var array []*Tree + if destTree == nil { + array = make([]*Tree, 0) + } else if target, ok := destTree.([]*Tree); ok && target != nil { + array = destTree.([]*Tree) + } else { + p.raiseError(key, "key %s is already assigned and not of type table array", key) + } + p.currentTable = keys + + // add a new tree to the end of the table array + newTree := newTree() + newTree.position = startToken.Position + array = append(array, newTree) + p.tree.SetPath(p.currentTable, array) + + // remove all keys that were children of this table array + prefix := key.val + "." + found := false + for ii := 0; ii < len(p.seenTableKeys); { + tableKey := p.seenTableKeys[ii] + if strings.HasPrefix(tableKey, prefix) { + p.seenTableKeys = append(p.seenTableKeys[:ii], p.seenTableKeys[ii+1:]...) + } else { + found = (tableKey == key.val) + ii++ + } + } + + // keep this key name from use by other kinds of assignments + if !found { + p.seenTableKeys = append(p.seenTableKeys, key.val) + } + + // move to next parser state + p.assume(tokenDoubleRightBracket) + return p.parseStart +} + +func (p *tomlParser) parseGroup() tomlParserStateFn { + startToken := p.getToken() // discard the [ + key := p.getToken() + if key.typ != tokenKeyGroup { + p.raiseError(key, "unexpected token %s, was expecting a table key", key) + } + for _, item := range p.seenTableKeys { + if item == key.val { + p.raiseError(key, "duplicated tables") + } + } + + p.seenTableKeys = append(p.seenTableKeys, key.val) + keys, err := parseKey(key.val) + if err != nil { + p.raiseError(key, "invalid table array key: %s", err) + } + if err := p.tree.createSubTree(keys, startToken.Position); err != nil { + p.raiseError(key, "%s", err) + } + p.assume(tokenRightBracket) + p.currentTable = keys + return p.parseStart +} + +func (p *tomlParser) parseAssign() tomlParserStateFn { + key := p.getToken() + p.assume(tokenEqual) + + parsedKey, err := parseKey(key.val) + if err != nil { + p.raiseError(key, "invalid key: %s", err.Error()) + } + + value := p.parseRvalue() + var tableKey []string + if len(p.currentTable) > 0 { + tableKey = p.currentTable + } else { + tableKey = []string{} + } + + prefixKey := parsedKey[0 : len(parsedKey)-1] + tableKey = append(tableKey, prefixKey...) + + // find the table to assign, looking out for arrays of tables + var targetNode *Tree + switch node := p.tree.GetPath(tableKey).(type) { + case []*Tree: + targetNode = node[len(node)-1] + case *Tree: + targetNode = node + case nil: + // create intermediate + if err := p.tree.createSubTree(tableKey, key.Position); err != nil { + p.raiseError(key, "could not create intermediate group: %s", err) + } + targetNode = p.tree.GetPath(tableKey).(*Tree) + default: + p.raiseError(key, "Unknown table type for path: %s", + strings.Join(tableKey, ".")) + } + + // assign value to the found table + keyVal := parsedKey[len(parsedKey)-1] + localKey := []string{keyVal} + finalKey := append(tableKey, keyVal) + if targetNode.GetPath(localKey) != nil { + p.raiseError(key, "The following key was defined twice: %s", + strings.Join(finalKey, ".")) + } + var toInsert interface{} + + switch value.(type) { + case *Tree, []*Tree: + toInsert = value + default: + toInsert = &tomlValue{value: value, position: key.Position} + } + targetNode.values[keyVal] = toInsert + return p.parseStart +} + +var numberUnderscoreInvalidRegexp *regexp.Regexp +var hexNumberUnderscoreInvalidRegexp *regexp.Regexp + +func numberContainsInvalidUnderscore(value string) error { + if numberUnderscoreInvalidRegexp.MatchString(value) { + return errors.New("invalid use of _ in number") + } + return nil +} + +func hexNumberContainsInvalidUnderscore(value string) error { + if hexNumberUnderscoreInvalidRegexp.MatchString(value) { + return errors.New("invalid use of _ in hex number") + } + return nil +} + +func cleanupNumberToken(value string) string { + cleanedVal := strings.Replace(value, "_", "", -1) + return cleanedVal +} + +func (p *tomlParser) parseRvalue() interface{} { + tok := p.getToken() + if tok == nil || tok.typ == tokenEOF { + p.raiseError(tok, "expecting a value") + } + + switch tok.typ { + case tokenString: + return tok.val + case tokenTrue: + return true + case tokenFalse: + return false + case tokenInf: + if tok.val[0] == '-' { + return math.Inf(-1) + } + return math.Inf(1) + case tokenNan: + return math.NaN() + case tokenInteger: + cleanedVal := cleanupNumberToken(tok.val) + var err error + var val int64 + if len(cleanedVal) >= 3 && cleanedVal[0] == '0' { + switch cleanedVal[1] { + case 'x': + err = hexNumberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + val, err = strconv.ParseInt(cleanedVal[2:], 16, 64) + case 'o': + err = numberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + val, err = strconv.ParseInt(cleanedVal[2:], 8, 64) + case 'b': + err = numberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + val, err = strconv.ParseInt(cleanedVal[2:], 2, 64) + default: + panic("invalid base") // the lexer should catch this first + } + } else { + err = numberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + val, err = strconv.ParseInt(cleanedVal, 10, 64) + } + if err != nil { + p.raiseError(tok, "%s", err) + } + return val + case tokenFloat: + err := numberContainsInvalidUnderscore(tok.val) + if err != nil { + p.raiseError(tok, "%s", err) + } + cleanedVal := cleanupNumberToken(tok.val) + val, err := strconv.ParseFloat(cleanedVal, 64) + if err != nil { + p.raiseError(tok, "%s", err) + } + return val + case tokenDate: + layout := time.RFC3339Nano + if !strings.Contains(tok.val, "T") { + layout = strings.Replace(layout, "T", " ", 1) + } + val, err := time.ParseInLocation(layout, tok.val, time.UTC) + if err != nil { + p.raiseError(tok, "%s", err) + } + return val + case tokenLocalDate: + v := strings.Replace(tok.val, " ", "T", -1) + isDateTime := false + isTime := false + for _, c := range v { + if c == 'T' || c == 't' { + isDateTime = true + break + } + if c == ':' { + isTime = true + break + } + } + + var val interface{} + var err error + + if isDateTime { + val, err = ParseLocalDateTime(v) + } else if isTime { + val, err = ParseLocalTime(v) + } else { + val, err = ParseLocalDate(v) + } + + if err != nil { + p.raiseError(tok, "%s", err) + } + return val + case tokenLeftBracket: + return p.parseArray() + case tokenLeftCurlyBrace: + return p.parseInlineTable() + case tokenEqual: + p.raiseError(tok, "cannot have multiple equals for the same key") + case tokenError: + p.raiseError(tok, "%s", tok) + } + + p.raiseError(tok, "never reached") + + return nil +} + +func tokenIsComma(t *token) bool { + return t != nil && t.typ == tokenComma +} + +func (p *tomlParser) parseInlineTable() *Tree { + tree := newTree() + var previous *token +Loop: + for { + follow := p.peek() + if follow == nil || follow.typ == tokenEOF { + p.raiseError(follow, "unterminated inline table") + } + switch follow.typ { + case tokenRightCurlyBrace: + p.getToken() + break Loop + case tokenKey, tokenInteger, tokenString: + if !tokenIsComma(previous) && previous != nil { + p.raiseError(follow, "comma expected between fields in inline table") + } + key := p.getToken() + p.assume(tokenEqual) + + parsedKey, err := parseKey(key.val) + if err != nil { + p.raiseError(key, "invalid key: %s", err) + } + + value := p.parseRvalue() + tree.SetPath(parsedKey, value) + case tokenComma: + if tokenIsComma(previous) { + p.raiseError(follow, "need field between two commas in inline table") + } + p.getToken() + default: + p.raiseError(follow, "unexpected token type in inline table: %s", follow.String()) + } + previous = follow + } + if tokenIsComma(previous) { + p.raiseError(previous, "trailing comma at the end of inline table") + } + return tree +} + +func (p *tomlParser) parseArray() interface{} { + var array []interface{} + arrayType := reflect.TypeOf(nil) + for { + follow := p.peek() + if follow == nil || follow.typ == tokenEOF { + p.raiseError(follow, "unterminated array") + } + if follow.typ == tokenRightBracket { + p.getToken() + break + } + val := p.parseRvalue() + if arrayType == nil { + arrayType = reflect.TypeOf(val) + } + if reflect.TypeOf(val) != arrayType { + p.raiseError(follow, "mixed types in array") + } + array = append(array, val) + follow = p.peek() + if follow == nil || follow.typ == tokenEOF { + p.raiseError(follow, "unterminated array") + } + if follow.typ != tokenRightBracket && follow.typ != tokenComma { + p.raiseError(follow, "missing comma") + } + if follow.typ == tokenComma { + p.getToken() + } + } + // An array of Trees is actually an array of inline + // tables, which is a shorthand for a table array. If the + // array was not converted from []interface{} to []*Tree, + // the two notations would not be equivalent. + if arrayType == reflect.TypeOf(newTree()) { + tomlArray := make([]*Tree, len(array)) + for i, v := range array { + tomlArray[i] = v.(*Tree) + } + return tomlArray + } + return array +} + +func parseToml(flow []token) *Tree { + result := newTree() + result.position = Position{1, 1} + parser := &tomlParser{ + flowIdx: 0, + flow: flow, + tree: result, + currentTable: make([]string, 0), + seenTableKeys: make([]string, 0), + } + parser.run() + return result +} + +func init() { + numberUnderscoreInvalidRegexp = regexp.MustCompile(`([^\d]_|_[^\d])|_$|^_`) + hexNumberUnderscoreInvalidRegexp = regexp.MustCompile(`(^0x_)|([^\da-f]_|_[^\da-f])|_$|^_`) +} diff --git a/vendor/github.com/pelletier/go-toml/position.go b/vendor/github.com/pelletier/go-toml/position.go new file mode 100644 index 00000000000..c17bff87baa --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/position.go @@ -0,0 +1,29 @@ +// Position support for go-toml + +package toml + +import ( + "fmt" +) + +// Position of a document element within a TOML document. +// +// Line and Col are both 1-indexed positions for the element's line number and +// column number, respectively. Values of zero or less will cause Invalid(), +// to return true. +type Position struct { + Line int // line within the document + Col int // column within the line +} + +// String representation of the position. +// Displays 1-indexed line and column numbers. +func (p Position) String() string { + return fmt.Sprintf("(%d, %d)", p.Line, p.Col) +} + +// Invalid returns whether or not the position is valid (i.e. with negative or +// null values) +func (p Position) Invalid() bool { + return p.Line <= 0 || p.Col <= 0 +} diff --git a/vendor/github.com/pelletier/go-toml/token.go b/vendor/github.com/pelletier/go-toml/token.go new file mode 100644 index 00000000000..36a3fc88f2f --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/token.go @@ -0,0 +1,137 @@ +package toml + +import ( + "fmt" + "unicode" +) + +// Define tokens +type tokenType int + +const ( + eof = -(iota + 1) +) + +const ( + tokenError tokenType = iota + tokenEOF + tokenComment + tokenKey + tokenString + tokenInteger + tokenTrue + tokenFalse + tokenFloat + tokenInf + tokenNan + tokenEqual + tokenLeftBracket + tokenRightBracket + tokenLeftCurlyBrace + tokenRightCurlyBrace + tokenLeftParen + tokenRightParen + tokenDoubleLeftBracket + tokenDoubleRightBracket + tokenDate + tokenLocalDate + tokenKeyGroup + tokenKeyGroupArray + tokenComma + tokenColon + tokenDollar + tokenStar + tokenQuestion + tokenDot + tokenDotDot + tokenEOL +) + +var tokenTypeNames = []string{ + "Error", + "EOF", + "Comment", + "Key", + "String", + "Integer", + "True", + "False", + "Float", + "Inf", + "NaN", + "=", + "[", + "]", + "{", + "}", + "(", + ")", + "]]", + "[[", + "LocalDate", + "LocalDate", + "KeyGroup", + "KeyGroupArray", + ",", + ":", + "$", + "*", + "?", + ".", + "..", + "EOL", +} + +type token struct { + Position + typ tokenType + val string +} + +func (tt tokenType) String() string { + idx := int(tt) + if idx < len(tokenTypeNames) { + return tokenTypeNames[idx] + } + return "Unknown" +} + +func (t token) String() string { + switch t.typ { + case tokenEOF: + return "EOF" + case tokenError: + return t.val + } + + return fmt.Sprintf("%q", t.val) +} + +func isSpace(r rune) bool { + return r == ' ' || r == '\t' +} + +func isAlphanumeric(r rune) bool { + return unicode.IsLetter(r) || r == '_' +} + +func isKeyChar(r rune) bool { + // Keys start with the first character that isn't whitespace or [ and end + // with the last non-whitespace character before the equals sign. Keys + // cannot contain a # character." + return !(r == '\r' || r == '\n' || r == eof || r == '=') +} + +func isKeyStartChar(r rune) bool { + return !(isSpace(r) || r == '\r' || r == '\n' || r == eof || r == '[') +} + +func isDigit(r rune) bool { + return unicode.IsNumber(r) +} + +func isHexDigit(r rune) bool { + return isDigit(r) || + (r >= 'a' && r <= 'f') || + (r >= 'A' && r <= 'F') +} diff --git a/vendor/github.com/pelletier/go-toml/toml.go b/vendor/github.com/pelletier/go-toml/toml.go new file mode 100644 index 00000000000..358a9be5ce8 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/toml.go @@ -0,0 +1,393 @@ +package toml + +import ( + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "runtime" + "strings" +) + +type tomlValue struct { + value interface{} // string, int64, uint64, float64, bool, time.Time, [] of any of this list + comment string + commented bool + multiline bool + position Position +} + +// Tree is the result of the parsing of a TOML file. +type Tree struct { + values map[string]interface{} // string -> *tomlValue, *Tree, []*Tree + comment string + commented bool + position Position +} + +func newTree() *Tree { + return newTreeWithPosition(Position{}) +} + +func newTreeWithPosition(pos Position) *Tree { + return &Tree{ + values: make(map[string]interface{}), + position: pos, + } +} + +// TreeFromMap initializes a new Tree object using the given map. +func TreeFromMap(m map[string]interface{}) (*Tree, error) { + result, err := toTree(m) + if err != nil { + return nil, err + } + return result.(*Tree), nil +} + +// Position returns the position of the tree. +func (t *Tree) Position() Position { + return t.position +} + +// Has returns a boolean indicating if the given key exists. +func (t *Tree) Has(key string) bool { + if key == "" { + return false + } + return t.HasPath(strings.Split(key, ".")) +} + +// HasPath returns true if the given path of keys exists, false otherwise. +func (t *Tree) HasPath(keys []string) bool { + return t.GetPath(keys) != nil +} + +// Keys returns the keys of the toplevel tree (does not recurse). +func (t *Tree) Keys() []string { + keys := make([]string, len(t.values)) + i := 0 + for k := range t.values { + keys[i] = k + i++ + } + return keys +} + +// Get the value at key in the Tree. +// Key is a dot-separated path (e.g. a.b.c) without single/double quoted strings. +// If you need to retrieve non-bare keys, use GetPath. +// Returns nil if the path does not exist in the tree. +// If keys is of length zero, the current tree is returned. +func (t *Tree) Get(key string) interface{} { + if key == "" { + return t + } + return t.GetPath(strings.Split(key, ".")) +} + +// GetPath returns the element in the tree indicated by 'keys'. +// If keys is of length zero, the current tree is returned. +func (t *Tree) GetPath(keys []string) interface{} { + if len(keys) == 0 { + return t + } + subtree := t + for _, intermediateKey := range keys[:len(keys)-1] { + value, exists := subtree.values[intermediateKey] + if !exists { + return nil + } + switch node := value.(type) { + case *Tree: + subtree = node + case []*Tree: + // go to most recent element + if len(node) == 0 { + return nil + } + subtree = node[len(node)-1] + default: + return nil // cannot navigate through other node types + } + } + // branch based on final node type + switch node := subtree.values[keys[len(keys)-1]].(type) { + case *tomlValue: + return node.value + default: + return node + } +} + +// GetPosition returns the position of the given key. +func (t *Tree) GetPosition(key string) Position { + if key == "" { + return t.position + } + return t.GetPositionPath(strings.Split(key, ".")) +} + +// GetPositionPath returns the element in the tree indicated by 'keys'. +// If keys is of length zero, the current tree is returned. +func (t *Tree) GetPositionPath(keys []string) Position { + if len(keys) == 0 { + return t.position + } + subtree := t + for _, intermediateKey := range keys[:len(keys)-1] { + value, exists := subtree.values[intermediateKey] + if !exists { + return Position{0, 0} + } + switch node := value.(type) { + case *Tree: + subtree = node + case []*Tree: + // go to most recent element + if len(node) == 0 { + return Position{0, 0} + } + subtree = node[len(node)-1] + default: + return Position{0, 0} + } + } + // branch based on final node type + switch node := subtree.values[keys[len(keys)-1]].(type) { + case *tomlValue: + return node.position + case *Tree: + return node.position + case []*Tree: + // go to most recent element + if len(node) == 0 { + return Position{0, 0} + } + return node[len(node)-1].position + default: + return Position{0, 0} + } +} + +// GetDefault works like Get but with a default value +func (t *Tree) GetDefault(key string, def interface{}) interface{} { + val := t.Get(key) + if val == nil { + return def + } + return val +} + +// SetOptions arguments are supplied to the SetWithOptions and SetPathWithOptions functions to modify marshalling behaviour. +// The default values within the struct are valid default options. +type SetOptions struct { + Comment string + Commented bool + Multiline bool +} + +// SetWithOptions is the same as Set, but allows you to provide formatting +// instructions to the key, that will be used by Marshal(). +func (t *Tree) SetWithOptions(key string, opts SetOptions, value interface{}) { + t.SetPathWithOptions(strings.Split(key, "."), opts, value) +} + +// SetPathWithOptions is the same as SetPath, but allows you to provide +// formatting instructions to the key, that will be reused by Marshal(). +func (t *Tree) SetPathWithOptions(keys []string, opts SetOptions, value interface{}) { + subtree := t + for i, intermediateKey := range keys[:len(keys)-1] { + nextTree, exists := subtree.values[intermediateKey] + if !exists { + nextTree = newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col}) + subtree.values[intermediateKey] = nextTree // add new element here + } + switch node := nextTree.(type) { + case *Tree: + subtree = node + case []*Tree: + // go to most recent element + if len(node) == 0 { + // create element if it does not exist + subtree.values[intermediateKey] = append(node, newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col})) + } + subtree = node[len(node)-1] + } + } + + var toInsert interface{} + + switch v := value.(type) { + case *Tree: + v.comment = opts.Comment + toInsert = value + case []*Tree: + toInsert = value + case *tomlValue: + v.comment = opts.Comment + toInsert = v + default: + toInsert = &tomlValue{value: value, + comment: opts.Comment, + commented: opts.Commented, + multiline: opts.Multiline, + position: Position{Line: subtree.position.Line + len(subtree.values) + 1, Col: subtree.position.Col}} + } + + subtree.values[keys[len(keys)-1]] = toInsert +} + +// Set an element in the tree. +// Key is a dot-separated path (e.g. a.b.c). +// Creates all necessary intermediate trees, if needed. +func (t *Tree) Set(key string, value interface{}) { + t.SetWithComment(key, "", false, value) +} + +// SetWithComment is the same as Set, but allows you to provide comment +// information to the key, that will be reused by Marshal(). +func (t *Tree) SetWithComment(key string, comment string, commented bool, value interface{}) { + t.SetPathWithComment(strings.Split(key, "."), comment, commented, value) +} + +// SetPath sets an element in the tree. +// Keys is an array of path elements (e.g. {"a","b","c"}). +// Creates all necessary intermediate trees, if needed. +func (t *Tree) SetPath(keys []string, value interface{}) { + t.SetPathWithComment(keys, "", false, value) +} + +// SetPathWithComment is the same as SetPath, but allows you to provide comment +// information to the key, that will be reused by Marshal(). +func (t *Tree) SetPathWithComment(keys []string, comment string, commented bool, value interface{}) { + t.SetPathWithOptions(keys, SetOptions{Comment: comment, Commented: commented}, value) +} + +// Delete removes a key from the tree. +// Key is a dot-separated path (e.g. a.b.c). +func (t *Tree) Delete(key string) error { + keys, err := parseKey(key) + if err != nil { + return err + } + return t.DeletePath(keys) +} + +// DeletePath removes a key from the tree. +// Keys is an array of path elements (e.g. {"a","b","c"}). +func (t *Tree) DeletePath(keys []string) error { + keyLen := len(keys) + if keyLen == 1 { + delete(t.values, keys[0]) + return nil + } + tree := t.GetPath(keys[:keyLen-1]) + item := keys[keyLen-1] + switch node := tree.(type) { + case *Tree: + delete(node.values, item) + return nil + } + return errors.New("no such key to delete") +} + +// createSubTree takes a tree and a key and create the necessary intermediate +// subtrees to create a subtree at that point. In-place. +// +// e.g. passing a.b.c will create (assuming tree is empty) tree[a], tree[a][b] +// and tree[a][b][c] +// +// Returns nil on success, error object on failure +func (t *Tree) createSubTree(keys []string, pos Position) error { + subtree := t + for i, intermediateKey := range keys { + nextTree, exists := subtree.values[intermediateKey] + if !exists { + tree := newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col}) + tree.position = pos + subtree.values[intermediateKey] = tree + nextTree = tree + } + + switch node := nextTree.(type) { + case []*Tree: + subtree = node[len(node)-1] + case *Tree: + subtree = node + default: + return fmt.Errorf("unknown type for path %s (%s): %T (%#v)", + strings.Join(keys, "."), intermediateKey, nextTree, nextTree) + } + } + return nil +} + +// LoadBytes creates a Tree from a []byte. +func LoadBytes(b []byte) (tree *Tree, err error) { + defer func() { + if r := recover(); r != nil { + if _, ok := r.(runtime.Error); ok { + panic(r) + } + err = errors.New(r.(string)) + } + }() + + if len(b) >= 4 && (hasUTF32BigEndianBOM4(b) || hasUTF32LittleEndianBOM4(b)) { + b = b[4:] + } else if len(b) >= 3 && hasUTF8BOM3(b) { + b = b[3:] + } else if len(b) >= 2 && (hasUTF16BigEndianBOM2(b) || hasUTF16LittleEndianBOM2(b)) { + b = b[2:] + } + + tree = parseToml(lexToml(b)) + return +} + +func hasUTF16BigEndianBOM2(b []byte) bool { + return b[0] == 0xFE && b[1] == 0xFF +} + +func hasUTF16LittleEndianBOM2(b []byte) bool { + return b[0] == 0xFF && b[1] == 0xFE +} + +func hasUTF8BOM3(b []byte) bool { + return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF +} + +func hasUTF32BigEndianBOM4(b []byte) bool { + return b[0] == 0x00 && b[1] == 0x00 && b[2] == 0xFE && b[3] == 0xFF +} + +func hasUTF32LittleEndianBOM4(b []byte) bool { + return b[0] == 0xFF && b[1] == 0xFE && b[2] == 0x00 && b[3] == 0x00 +} + +// LoadReader creates a Tree from any io.Reader. +func LoadReader(reader io.Reader) (tree *Tree, err error) { + inputBytes, err := ioutil.ReadAll(reader) + if err != nil { + return + } + tree, err = LoadBytes(inputBytes) + return +} + +// Load creates a Tree from a string. +func Load(content string) (tree *Tree, err error) { + return LoadBytes([]byte(content)) +} + +// LoadFile creates a Tree from a file. +func LoadFile(path string) (tree *Tree, err error) { + file, err := os.Open(path) + if err != nil { + return nil, err + } + defer file.Close() + return LoadReader(file) +} diff --git a/vendor/github.com/pelletier/go-toml/tomltree_create.go b/vendor/github.com/pelletier/go-toml/tomltree_create.go new file mode 100644 index 00000000000..79610e9b340 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/tomltree_create.go @@ -0,0 +1,142 @@ +package toml + +import ( + "fmt" + "reflect" + "time" +) + +var kindToType = [reflect.String + 1]reflect.Type{ + reflect.Bool: reflect.TypeOf(true), + reflect.String: reflect.TypeOf(""), + reflect.Float32: reflect.TypeOf(float64(1)), + reflect.Float64: reflect.TypeOf(float64(1)), + reflect.Int: reflect.TypeOf(int64(1)), + reflect.Int8: reflect.TypeOf(int64(1)), + reflect.Int16: reflect.TypeOf(int64(1)), + reflect.Int32: reflect.TypeOf(int64(1)), + reflect.Int64: reflect.TypeOf(int64(1)), + reflect.Uint: reflect.TypeOf(uint64(1)), + reflect.Uint8: reflect.TypeOf(uint64(1)), + reflect.Uint16: reflect.TypeOf(uint64(1)), + reflect.Uint32: reflect.TypeOf(uint64(1)), + reflect.Uint64: reflect.TypeOf(uint64(1)), +} + +// typeFor returns a reflect.Type for a reflect.Kind, or nil if none is found. +// supported values: +// string, bool, int64, uint64, float64, time.Time, int, int8, int16, int32, uint, uint8, uint16, uint32, float32 +func typeFor(k reflect.Kind) reflect.Type { + if k > 0 && int(k) < len(kindToType) { + return kindToType[k] + } + return nil +} + +func simpleValueCoercion(object interface{}) (interface{}, error) { + switch original := object.(type) { + case string, bool, int64, uint64, float64, time.Time: + return original, nil + case int: + return int64(original), nil + case int8: + return int64(original), nil + case int16: + return int64(original), nil + case int32: + return int64(original), nil + case uint: + return uint64(original), nil + case uint8: + return uint64(original), nil + case uint16: + return uint64(original), nil + case uint32: + return uint64(original), nil + case float32: + return float64(original), nil + case fmt.Stringer: + return original.String(), nil + default: + return nil, fmt.Errorf("cannot convert type %T to Tree", object) + } +} + +func sliceToTree(object interface{}) (interface{}, error) { + // arrays are a bit tricky, since they can represent either a + // collection of simple values, which is represented by one + // *tomlValue, or an array of tables, which is represented by an + // array of *Tree. + + // holding the assumption that this function is called from toTree only when value.Kind() is Array or Slice + value := reflect.ValueOf(object) + insideType := value.Type().Elem() + length := value.Len() + if length > 0 { + insideType = reflect.ValueOf(value.Index(0).Interface()).Type() + } + if insideType.Kind() == reflect.Map { + // this is considered as an array of tables + tablesArray := make([]*Tree, 0, length) + for i := 0; i < length; i++ { + table := value.Index(i) + tree, err := toTree(table.Interface()) + if err != nil { + return nil, err + } + tablesArray = append(tablesArray, tree.(*Tree)) + } + return tablesArray, nil + } + + sliceType := typeFor(insideType.Kind()) + if sliceType == nil { + sliceType = insideType + } + + arrayValue := reflect.MakeSlice(reflect.SliceOf(sliceType), 0, length) + + for i := 0; i < length; i++ { + val := value.Index(i).Interface() + simpleValue, err := simpleValueCoercion(val) + if err != nil { + return nil, err + } + arrayValue = reflect.Append(arrayValue, reflect.ValueOf(simpleValue)) + } + return &tomlValue{value: arrayValue.Interface(), position: Position{}}, nil +} + +func toTree(object interface{}) (interface{}, error) { + value := reflect.ValueOf(object) + + if value.Kind() == reflect.Map { + values := map[string]interface{}{} + keys := value.MapKeys() + for _, key := range keys { + if key.Kind() != reflect.String { + if _, ok := key.Interface().(string); !ok { + return nil, fmt.Errorf("map key needs to be a string, not %T (%v)", key.Interface(), key.Kind()) + } + } + + v := value.MapIndex(key) + newValue, err := toTree(v.Interface()) + if err != nil { + return nil, err + } + values[key.String()] = newValue + } + return &Tree{values: values, position: Position{}}, nil + } + + if value.Kind() == reflect.Array || value.Kind() == reflect.Slice { + return sliceToTree(object) + } + + simpleValue, err := simpleValueCoercion(object) + if err != nil { + return nil, err + } + return &tomlValue{value: simpleValue, position: Position{}}, nil +} diff --git a/vendor/github.com/pelletier/go-toml/tomltree_write.go b/vendor/github.com/pelletier/go-toml/tomltree_write.go new file mode 100644 index 00000000000..43c63030d26 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/tomltree_write.go @@ -0,0 +1,475 @@ +package toml + +import ( + "bytes" + "fmt" + "io" + "math" + "math/big" + "reflect" + "sort" + "strconv" + "strings" + "time" +) + +type valueComplexity int + +const ( + valueSimple valueComplexity = iota + 1 + valueComplex +) + +type sortNode struct { + key string + complexity valueComplexity +} + +// Encodes a string to a TOML-compliant multi-line string value +// This function is a clone of the existing encodeTomlString function, except that whitespace characters +// are preserved. Quotation marks and backslashes are also not escaped. +func encodeMultilineTomlString(value string) string { + var b bytes.Buffer + + for _, rr := range value { + switch rr { + case '\b': + b.WriteString(`\b`) + case '\t': + b.WriteString("\t") + case '\n': + b.WriteString("\n") + case '\f': + b.WriteString(`\f`) + case '\r': + b.WriteString("\r") + case '"': + b.WriteString(`"`) + case '\\': + b.WriteString(`\`) + default: + intRr := uint16(rr) + if intRr < 0x001F { + b.WriteString(fmt.Sprintf("\\u%0.4X", intRr)) + } else { + b.WriteRune(rr) + } + } + } + return b.String() +} + +// Encodes a string to a TOML-compliant string value +func encodeTomlString(value string) string { + var b bytes.Buffer + + for _, rr := range value { + switch rr { + case '\b': + b.WriteString(`\b`) + case '\t': + b.WriteString(`\t`) + case '\n': + b.WriteString(`\n`) + case '\f': + b.WriteString(`\f`) + case '\r': + b.WriteString(`\r`) + case '"': + b.WriteString(`\"`) + case '\\': + b.WriteString(`\\`) + default: + intRr := uint16(rr) + if intRr < 0x001F { + b.WriteString(fmt.Sprintf("\\u%0.4X", intRr)) + } else { + b.WriteRune(rr) + } + } + } + return b.String() +} + +func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElementPerLine bool) (string, error) { + // this interface check is added to dereference the change made in the writeTo function. + // That change was made to allow this function to see formatting options. + tv, ok := v.(*tomlValue) + if ok { + v = tv.value + } else { + tv = &tomlValue{} + } + + switch value := v.(type) { + case uint64: + return strconv.FormatUint(value, 10), nil + case int64: + return strconv.FormatInt(value, 10), nil + case float64: + // Default bit length is full 64 + bits := 64 + // Float panics if nan is used + if !math.IsNaN(value) { + // if 32 bit accuracy is enough to exactly show, use 32 + _, acc := big.NewFloat(value).Float32() + if acc == big.Exact { + bits = 32 + } + } + if math.Trunc(value) == value { + return strings.ToLower(strconv.FormatFloat(value, 'f', 1, bits)), nil + } + return strings.ToLower(strconv.FormatFloat(value, 'f', -1, bits)), nil + case string: + if tv.multiline { + return "\"\"\"\n" + encodeMultilineTomlString(value) + "\"\"\"", nil + } + return "\"" + encodeTomlString(value) + "\"", nil + case []byte: + b, _ := v.([]byte) + return tomlValueStringRepresentation(string(b), indent, arraysOneElementPerLine) + case bool: + if value { + return "true", nil + } + return "false", nil + case time.Time: + return value.Format(time.RFC3339), nil + case LocalDate: + return value.String(), nil + case LocalDateTime: + return value.String(), nil + case LocalTime: + return value.String(), nil + case nil: + return "", nil + } + + rv := reflect.ValueOf(v) + + if rv.Kind() == reflect.Slice { + var values []string + for i := 0; i < rv.Len(); i++ { + item := rv.Index(i).Interface() + itemRepr, err := tomlValueStringRepresentation(item, indent, arraysOneElementPerLine) + if err != nil { + return "", err + } + values = append(values, itemRepr) + } + if arraysOneElementPerLine && len(values) > 1 { + stringBuffer := bytes.Buffer{} + valueIndent := indent + ` ` // TODO: move that to a shared encoder state + + stringBuffer.WriteString("[\n") + + for _, value := range values { + stringBuffer.WriteString(valueIndent) + stringBuffer.WriteString(value) + stringBuffer.WriteString(`,`) + stringBuffer.WriteString("\n") + } + + stringBuffer.WriteString(indent + "]") + + return stringBuffer.String(), nil + } + return "[" + strings.Join(values, ",") + "]", nil + } + return "", fmt.Errorf("unsupported value type %T: %v", v, v) +} + +func getTreeArrayLine(trees []*Tree) (line int) { + // get lowest line number that is not 0 + for _, tv := range trees { + if tv.position.Line < line || line == 0 { + line = tv.position.Line + } + } + return +} + +func sortByLines(t *Tree) (vals []sortNode) { + var ( + line int + lines []int + tv *Tree + tom *tomlValue + node sortNode + ) + vals = make([]sortNode, 0) + m := make(map[int]sortNode) + + for k := range t.values { + v := t.values[k] + switch v.(type) { + case *Tree: + tv = v.(*Tree) + line = tv.position.Line + node = sortNode{key: k, complexity: valueComplex} + case []*Tree: + line = getTreeArrayLine(v.([]*Tree)) + node = sortNode{key: k, complexity: valueComplex} + default: + tom = v.(*tomlValue) + line = tom.position.Line + node = sortNode{key: k, complexity: valueSimple} + } + lines = append(lines, line) + vals = append(vals, node) + m[line] = node + } + sort.Ints(lines) + + for i, line := range lines { + vals[i] = m[line] + } + + return vals +} + +func sortAlphabetical(t *Tree) (vals []sortNode) { + var ( + node sortNode + simpVals []string + compVals []string + ) + vals = make([]sortNode, 0) + m := make(map[string]sortNode) + + for k := range t.values { + v := t.values[k] + switch v.(type) { + case *Tree, []*Tree: + node = sortNode{key: k, complexity: valueComplex} + compVals = append(compVals, node.key) + default: + node = sortNode{key: k, complexity: valueSimple} + simpVals = append(simpVals, node.key) + } + vals = append(vals, node) + m[node.key] = node + } + + // Simples first to match previous implementation + sort.Strings(simpVals) + i := 0 + for _, key := range simpVals { + vals[i] = m[key] + i++ + } + + sort.Strings(compVals) + for _, key := range compVals { + vals[i] = m[key] + i++ + } + + return vals +} + +func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool) (int64, error) { + return t.writeToOrdered(w, indent, keyspace, bytesCount, arraysOneElementPerLine, OrderAlphabetical) +} + +func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool, ord marshalOrder) (int64, error) { + var orderedVals []sortNode + + switch ord { + case OrderPreserve: + orderedVals = sortByLines(t) + default: + orderedVals = sortAlphabetical(t) + } + + for _, node := range orderedVals { + switch node.complexity { + case valueComplex: + k := node.key + v := t.values[k] + + combinedKey := k + if keyspace != "" { + combinedKey = keyspace + "." + combinedKey + } + var commented string + if t.commented { + commented = "# " + } + + switch node := v.(type) { + // node has to be of those two types given how keys are sorted above + case *Tree: + tv, ok := t.values[k].(*Tree) + if !ok { + return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k]) + } + if tv.comment != "" { + comment := strings.Replace(tv.comment, "\n", "\n"+indent+"#", -1) + start := "# " + if strings.HasPrefix(comment, "#") { + start = "" + } + writtenBytesCountComment, errc := writeStrings(w, "\n", indent, start, comment) + bytesCount += int64(writtenBytesCountComment) + if errc != nil { + return bytesCount, errc + } + } + writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[", combinedKey, "]\n") + bytesCount += int64(writtenBytesCount) + if err != nil { + return bytesCount, err + } + bytesCount, err = node.writeToOrdered(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine, ord) + if err != nil { + return bytesCount, err + } + case []*Tree: + for _, subTree := range node { + writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[[", combinedKey, "]]\n") + bytesCount += int64(writtenBytesCount) + if err != nil { + return bytesCount, err + } + + bytesCount, err = subTree.writeToOrdered(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine, ord) + if err != nil { + return bytesCount, err + } + } + } + default: // Simple + k := node.key + v, ok := t.values[k].(*tomlValue) + if !ok { + return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k]) + } + + repr, err := tomlValueStringRepresentation(v, indent, arraysOneElementPerLine) + if err != nil { + return bytesCount, err + } + + if v.comment != "" { + comment := strings.Replace(v.comment, "\n", "\n"+indent+"#", -1) + start := "# " + if strings.HasPrefix(comment, "#") { + start = "" + } + writtenBytesCountComment, errc := writeStrings(w, "\n", indent, start, comment, "\n") + bytesCount += int64(writtenBytesCountComment) + if errc != nil { + return bytesCount, errc + } + } + + var commented string + if v.commented { + commented = "# " + } + quotedKey := quoteKeyIfNeeded(k) + writtenBytesCount, err := writeStrings(w, indent, commented, quotedKey, " = ", repr, "\n") + bytesCount += int64(writtenBytesCount) + if err != nil { + return bytesCount, err + } + } + } + + return bytesCount, nil +} + +// quote a key if it does not fit the bare key format (A-Za-z0-9_-) +// quoted keys use the same rules as strings +func quoteKeyIfNeeded(k string) string { + // when encoding a map with the 'quoteMapKeys' option enabled, the tree will contain + // keys that have already been quoted. + // not an ideal situation, but good enough of a stop gap. + if len(k) >= 2 && k[0] == '"' && k[len(k)-1] == '"' { + return k + } + isBare := true + for _, r := range k { + if !isValidBareChar(r) { + isBare = false + break + } + } + if isBare { + return k + } + return quoteKey(k) +} + +func quoteKey(k string) string { + return "\"" + encodeTomlString(k) + "\"" +} + +func writeStrings(w io.Writer, s ...string) (int, error) { + var n int + for i := range s { + b, err := io.WriteString(w, s[i]) + n += b + if err != nil { + return n, err + } + } + return n, nil +} + +// WriteTo encode the Tree as Toml and writes it to the writer w. +// Returns the number of bytes written in case of success, or an error if anything happened. +func (t *Tree) WriteTo(w io.Writer) (int64, error) { + return t.writeTo(w, "", "", 0, false) +} + +// ToTomlString generates a human-readable representation of the current tree. +// Output spans multiple lines, and is suitable for ingest by a TOML parser. +// If the conversion cannot be performed, ToString returns a non-nil error. +func (t *Tree) ToTomlString() (string, error) { + b, err := t.Marshal() + if err != nil { + return "", err + } + return string(b), nil +} + +// String generates a human-readable representation of the current tree. +// Alias of ToString. Present to implement the fmt.Stringer interface. +func (t *Tree) String() string { + result, _ := t.ToTomlString() + return result +} + +// ToMap recursively generates a representation of the tree using Go built-in structures. +// The following types are used: +// +// * bool +// * float64 +// * int64 +// * string +// * uint64 +// * time.Time +// * map[string]interface{} (where interface{} is any of this list) +// * []interface{} (where interface{} is any of this list) +func (t *Tree) ToMap() map[string]interface{} { + result := map[string]interface{}{} + + for k, v := range t.values { + switch node := v.(type) { + case []*Tree: + var array []interface{} + for _, item := range node { + array = append(array, item.ToMap()) + } + result[k] = array + case *Tree: + result[k] = node.ToMap() + case *tomlValue: + result[k] = node.value + } + } + return result +} diff --git a/vendor/github.com/phayes/freeport/LICENSE.md b/vendor/github.com/phayes/freeport/LICENSE.md new file mode 100644 index 00000000000..d9882e595e4 --- /dev/null +++ b/vendor/github.com/phayes/freeport/LICENSE.md @@ -0,0 +1,15 @@ +Open Source License (BSD 3-Clause) +---------------------------------- + +Copyright (c) 2014, Patrick Hayes / HighWire Press +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/phayes/freeport/freeport.go b/vendor/github.com/phayes/freeport/freeport.go new file mode 100644 index 00000000000..c44b60df278 --- /dev/null +++ b/vendor/github.com/phayes/freeport/freeport.go @@ -0,0 +1,30 @@ +package freeport + +import ( + "net" +) + +// GetFreePort asks the kernel for a free open port that is ready to use. +func GetFreePort() (int, error) { + addr, err := net.ResolveTCPAddr("tcp", "localhost:0") + if err != nil { + return 0, err + } + + l, err := net.ListenTCP("tcp", addr) + if err != nil { + return 0, err + } + defer l.Close() + return l.Addr().(*net.TCPAddr).Port, nil +} + +// GetPort is deprecated, use GetFreePort instead +// Ask the kernel for a free open port that is ready to use +func GetPort() int { + port, err := GetFreePort() + if err != nil { + panic(err) + } + return port +} diff --git a/vendor/github.com/pmezard/go-difflib/LICENSE b/vendor/github.com/pmezard/go-difflib/LICENSE new file mode 100644 index 00000000000..c67dad612a3 --- /dev/null +++ b/vendor/github.com/pmezard/go-difflib/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2013, Patrick Mezard +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + The names of its contributors may not be used to endorse or promote +products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/vendor/github.com/pmezard/go-difflib/difflib/difflib.go b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go new file mode 100644 index 00000000000..003e99fadb4 --- /dev/null +++ b/vendor/github.com/pmezard/go-difflib/difflib/difflib.go @@ -0,0 +1,772 @@ +// Package difflib is a partial port of Python difflib module. +// +// It provides tools to compare sequences of strings and generate textual diffs. +// +// The following class and functions have been ported: +// +// - SequenceMatcher +// +// - unified_diff +// +// - context_diff +// +// Getting unified diffs was the main goal of the port. Keep in mind this code +// is mostly suitable to output text differences in a human friendly way, there +// are no guarantees generated diffs are consumable by patch(1). +package difflib + +import ( + "bufio" + "bytes" + "fmt" + "io" + "strings" +) + +func min(a, b int) int { + if a < b { + return a + } + return b +} + +func max(a, b int) int { + if a > b { + return a + } + return b +} + +func calculateRatio(matches, length int) float64 { + if length > 0 { + return 2.0 * float64(matches) / float64(length) + } + return 1.0 +} + +type Match struct { + A int + B int + Size int +} + +type OpCode struct { + Tag byte + I1 int + I2 int + J1 int + J2 int +} + +// SequenceMatcher compares sequence of strings. The basic +// algorithm predates, and is a little fancier than, an algorithm +// published in the late 1980's by Ratcliff and Obershelp under the +// hyperbolic name "gestalt pattern matching". The basic idea is to find +// the longest contiguous matching subsequence that contains no "junk" +// elements (R-O doesn't address junk). The same idea is then applied +// recursively to the pieces of the sequences to the left and to the right +// of the matching subsequence. This does not yield minimal edit +// sequences, but does tend to yield matches that "look right" to people. +// +// SequenceMatcher tries to compute a "human-friendly diff" between two +// sequences. Unlike e.g. UNIX(tm) diff, the fundamental notion is the +// longest *contiguous* & junk-free matching subsequence. That's what +// catches peoples' eyes. The Windows(tm) windiff has another interesting +// notion, pairing up elements that appear uniquely in each sequence. +// That, and the method here, appear to yield more intuitive difference +// reports than does diff. This method appears to be the least vulnerable +// to synching up on blocks of "junk lines", though (like blank lines in +// ordinary text files, or maybe "

" lines in HTML files). That may be +// because this is the only method of the 3 that has a *concept* of +// "junk" . +// +// Timing: Basic R-O is cubic time worst case and quadratic time expected +// case. SequenceMatcher is quadratic time for the worst case and has +// expected-case behavior dependent in a complicated way on how many +// elements the sequences have in common; best case time is linear. +type SequenceMatcher struct { + a []string + b []string + b2j map[string][]int + IsJunk func(string) bool + autoJunk bool + bJunk map[string]struct{} + matchingBlocks []Match + fullBCount map[string]int + bPopular map[string]struct{} + opCodes []OpCode +} + +func NewMatcher(a, b []string) *SequenceMatcher { + m := SequenceMatcher{autoJunk: true} + m.SetSeqs(a, b) + return &m +} + +func NewMatcherWithJunk(a, b []string, autoJunk bool, + isJunk func(string) bool) *SequenceMatcher { + + m := SequenceMatcher{IsJunk: isJunk, autoJunk: autoJunk} + m.SetSeqs(a, b) + return &m +} + +// Set two sequences to be compared. +func (m *SequenceMatcher) SetSeqs(a, b []string) { + m.SetSeq1(a) + m.SetSeq2(b) +} + +// Set the first sequence to be compared. The second sequence to be compared is +// not changed. +// +// SequenceMatcher computes and caches detailed information about the second +// sequence, so if you want to compare one sequence S against many sequences, +// use .SetSeq2(s) once and call .SetSeq1(x) repeatedly for each of the other +// sequences. +// +// See also SetSeqs() and SetSeq2(). +func (m *SequenceMatcher) SetSeq1(a []string) { + if &a == &m.a { + return + } + m.a = a + m.matchingBlocks = nil + m.opCodes = nil +} + +// Set the second sequence to be compared. The first sequence to be compared is +// not changed. +func (m *SequenceMatcher) SetSeq2(b []string) { + if &b == &m.b { + return + } + m.b = b + m.matchingBlocks = nil + m.opCodes = nil + m.fullBCount = nil + m.chainB() +} + +func (m *SequenceMatcher) chainB() { + // Populate line -> index mapping + b2j := map[string][]int{} + for i, s := range m.b { + indices := b2j[s] + indices = append(indices, i) + b2j[s] = indices + } + + // Purge junk elements + m.bJunk = map[string]struct{}{} + if m.IsJunk != nil { + junk := m.bJunk + for s, _ := range b2j { + if m.IsJunk(s) { + junk[s] = struct{}{} + } + } + for s, _ := range junk { + delete(b2j, s) + } + } + + // Purge remaining popular elements + popular := map[string]struct{}{} + n := len(m.b) + if m.autoJunk && n >= 200 { + ntest := n/100 + 1 + for s, indices := range b2j { + if len(indices) > ntest { + popular[s] = struct{}{} + } + } + for s, _ := range popular { + delete(b2j, s) + } + } + m.bPopular = popular + m.b2j = b2j +} + +func (m *SequenceMatcher) isBJunk(s string) bool { + _, ok := m.bJunk[s] + return ok +} + +// Find longest matching block in a[alo:ahi] and b[blo:bhi]. +// +// If IsJunk is not defined: +// +// Return (i,j,k) such that a[i:i+k] is equal to b[j:j+k], where +// alo <= i <= i+k <= ahi +// blo <= j <= j+k <= bhi +// and for all (i',j',k') meeting those conditions, +// k >= k' +// i <= i' +// and if i == i', j <= j' +// +// In other words, of all maximal matching blocks, return one that +// starts earliest in a, and of all those maximal matching blocks that +// start earliest in a, return the one that starts earliest in b. +// +// If IsJunk is defined, first the longest matching block is +// determined as above, but with the additional restriction that no +// junk element appears in the block. Then that block is extended as +// far as possible by matching (only) junk elements on both sides. So +// the resulting block never matches on junk except as identical junk +// happens to be adjacent to an "interesting" match. +// +// If no blocks match, return (alo, blo, 0). +func (m *SequenceMatcher) findLongestMatch(alo, ahi, blo, bhi int) Match { + // CAUTION: stripping common prefix or suffix would be incorrect. + // E.g., + // ab + // acab + // Longest matching block is "ab", but if common prefix is + // stripped, it's "a" (tied with "b"). UNIX(tm) diff does so + // strip, so ends up claiming that ab is changed to acab by + // inserting "ca" in the middle. That's minimal but unintuitive: + // "it's obvious" that someone inserted "ac" at the front. + // Windiff ends up at the same place as diff, but by pairing up + // the unique 'b's and then matching the first two 'a's. + besti, bestj, bestsize := alo, blo, 0 + + // find longest junk-free match + // during an iteration of the loop, j2len[j] = length of longest + // junk-free match ending with a[i-1] and b[j] + j2len := map[int]int{} + for i := alo; i != ahi; i++ { + // look at all instances of a[i] in b; note that because + // b2j has no junk keys, the loop is skipped if a[i] is junk + newj2len := map[int]int{} + for _, j := range m.b2j[m.a[i]] { + // a[i] matches b[j] + if j < blo { + continue + } + if j >= bhi { + break + } + k := j2len[j-1] + 1 + newj2len[j] = k + if k > bestsize { + besti, bestj, bestsize = i-k+1, j-k+1, k + } + } + j2len = newj2len + } + + // Extend the best by non-junk elements on each end. In particular, + // "popular" non-junk elements aren't in b2j, which greatly speeds + // the inner loop above, but also means "the best" match so far + // doesn't contain any junk *or* popular non-junk elements. + for besti > alo && bestj > blo && !m.isBJunk(m.b[bestj-1]) && + m.a[besti-1] == m.b[bestj-1] { + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + } + for besti+bestsize < ahi && bestj+bestsize < bhi && + !m.isBJunk(m.b[bestj+bestsize]) && + m.a[besti+bestsize] == m.b[bestj+bestsize] { + bestsize += 1 + } + + // Now that we have a wholly interesting match (albeit possibly + // empty!), we may as well suck up the matching junk on each + // side of it too. Can't think of a good reason not to, and it + // saves post-processing the (possibly considerable) expense of + // figuring out what to do with it. In the case of an empty + // interesting match, this is clearly the right thing to do, + // because no other kind of match is possible in the regions. + for besti > alo && bestj > blo && m.isBJunk(m.b[bestj-1]) && + m.a[besti-1] == m.b[bestj-1] { + besti, bestj, bestsize = besti-1, bestj-1, bestsize+1 + } + for besti+bestsize < ahi && bestj+bestsize < bhi && + m.isBJunk(m.b[bestj+bestsize]) && + m.a[besti+bestsize] == m.b[bestj+bestsize] { + bestsize += 1 + } + + return Match{A: besti, B: bestj, Size: bestsize} +} + +// Return list of triples describing matching subsequences. +// +// Each triple is of the form (i, j, n), and means that +// a[i:i+n] == b[j:j+n]. The triples are monotonically increasing in +// i and in j. It's also guaranteed that if (i, j, n) and (i', j', n') are +// adjacent triples in the list, and the second is not the last triple in the +// list, then i+n != i' or j+n != j'. IOW, adjacent triples never describe +// adjacent equal blocks. +// +// The last triple is a dummy, (len(a), len(b), 0), and is the only +// triple with n==0. +func (m *SequenceMatcher) GetMatchingBlocks() []Match { + if m.matchingBlocks != nil { + return m.matchingBlocks + } + + var matchBlocks func(alo, ahi, blo, bhi int, matched []Match) []Match + matchBlocks = func(alo, ahi, blo, bhi int, matched []Match) []Match { + match := m.findLongestMatch(alo, ahi, blo, bhi) + i, j, k := match.A, match.B, match.Size + if match.Size > 0 { + if alo < i && blo < j { + matched = matchBlocks(alo, i, blo, j, matched) + } + matched = append(matched, match) + if i+k < ahi && j+k < bhi { + matched = matchBlocks(i+k, ahi, j+k, bhi, matched) + } + } + return matched + } + matched := matchBlocks(0, len(m.a), 0, len(m.b), nil) + + // It's possible that we have adjacent equal blocks in the + // matching_blocks list now. + nonAdjacent := []Match{} + i1, j1, k1 := 0, 0, 0 + for _, b := range matched { + // Is this block adjacent to i1, j1, k1? + i2, j2, k2 := b.A, b.B, b.Size + if i1+k1 == i2 && j1+k1 == j2 { + // Yes, so collapse them -- this just increases the length of + // the first block by the length of the second, and the first + // block so lengthened remains the block to compare against. + k1 += k2 + } else { + // Not adjacent. Remember the first block (k1==0 means it's + // the dummy we started with), and make the second block the + // new block to compare against. + if k1 > 0 { + nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) + } + i1, j1, k1 = i2, j2, k2 + } + } + if k1 > 0 { + nonAdjacent = append(nonAdjacent, Match{i1, j1, k1}) + } + + nonAdjacent = append(nonAdjacent, Match{len(m.a), len(m.b), 0}) + m.matchingBlocks = nonAdjacent + return m.matchingBlocks +} + +// Return list of 5-tuples describing how to turn a into b. +// +// Each tuple is of the form (tag, i1, i2, j1, j2). The first tuple +// has i1 == j1 == 0, and remaining tuples have i1 == the i2 from the +// tuple preceding it, and likewise for j1 == the previous j2. +// +// The tags are characters, with these meanings: +// +// 'r' (replace): a[i1:i2] should be replaced by b[j1:j2] +// +// 'd' (delete): a[i1:i2] should be deleted, j1==j2 in this case. +// +// 'i' (insert): b[j1:j2] should be inserted at a[i1:i1], i1==i2 in this case. +// +// 'e' (equal): a[i1:i2] == b[j1:j2] +func (m *SequenceMatcher) GetOpCodes() []OpCode { + if m.opCodes != nil { + return m.opCodes + } + i, j := 0, 0 + matching := m.GetMatchingBlocks() + opCodes := make([]OpCode, 0, len(matching)) + for _, m := range matching { + // invariant: we've pumped out correct diffs to change + // a[:i] into b[:j], and the next matching block is + // a[ai:ai+size] == b[bj:bj+size]. So we need to pump + // out a diff to change a[i:ai] into b[j:bj], pump out + // the matching block, and move (i,j) beyond the match + ai, bj, size := m.A, m.B, m.Size + tag := byte(0) + if i < ai && j < bj { + tag = 'r' + } else if i < ai { + tag = 'd' + } else if j < bj { + tag = 'i' + } + if tag > 0 { + opCodes = append(opCodes, OpCode{tag, i, ai, j, bj}) + } + i, j = ai+size, bj+size + // the list of matching blocks is terminated by a + // sentinel with size 0 + if size > 0 { + opCodes = append(opCodes, OpCode{'e', ai, i, bj, j}) + } + } + m.opCodes = opCodes + return m.opCodes +} + +// Isolate change clusters by eliminating ranges with no changes. +// +// Return a generator of groups with up to n lines of context. +// Each group is in the same format as returned by GetOpCodes(). +func (m *SequenceMatcher) GetGroupedOpCodes(n int) [][]OpCode { + if n < 0 { + n = 3 + } + codes := m.GetOpCodes() + if len(codes) == 0 { + codes = []OpCode{OpCode{'e', 0, 1, 0, 1}} + } + // Fixup leading and trailing groups if they show no changes. + if codes[0].Tag == 'e' { + c := codes[0] + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + codes[0] = OpCode{c.Tag, max(i1, i2-n), i2, max(j1, j2-n), j2} + } + if codes[len(codes)-1].Tag == 'e' { + c := codes[len(codes)-1] + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + codes[len(codes)-1] = OpCode{c.Tag, i1, min(i2, i1+n), j1, min(j2, j1+n)} + } + nn := n + n + groups := [][]OpCode{} + group := []OpCode{} + for _, c := range codes { + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + // End the current group and start a new one whenever + // there is a large range with no changes. + if c.Tag == 'e' && i2-i1 > nn { + group = append(group, OpCode{c.Tag, i1, min(i2, i1+n), + j1, min(j2, j1+n)}) + groups = append(groups, group) + group = []OpCode{} + i1, j1 = max(i1, i2-n), max(j1, j2-n) + } + group = append(group, OpCode{c.Tag, i1, i2, j1, j2}) + } + if len(group) > 0 && !(len(group) == 1 && group[0].Tag == 'e') { + groups = append(groups, group) + } + return groups +} + +// Return a measure of the sequences' similarity (float in [0,1]). +// +// Where T is the total number of elements in both sequences, and +// M is the number of matches, this is 2.0*M / T. +// Note that this is 1 if the sequences are identical, and 0 if +// they have nothing in common. +// +// .Ratio() is expensive to compute if you haven't already computed +// .GetMatchingBlocks() or .GetOpCodes(), in which case you may +// want to try .QuickRatio() or .RealQuickRation() first to get an +// upper bound. +func (m *SequenceMatcher) Ratio() float64 { + matches := 0 + for _, m := range m.GetMatchingBlocks() { + matches += m.Size + } + return calculateRatio(matches, len(m.a)+len(m.b)) +} + +// Return an upper bound on ratio() relatively quickly. +// +// This isn't defined beyond that it is an upper bound on .Ratio(), and +// is faster to compute. +func (m *SequenceMatcher) QuickRatio() float64 { + // viewing a and b as multisets, set matches to the cardinality + // of their intersection; this counts the number of matches + // without regard to order, so is clearly an upper bound + if m.fullBCount == nil { + m.fullBCount = map[string]int{} + for _, s := range m.b { + m.fullBCount[s] = m.fullBCount[s] + 1 + } + } + + // avail[x] is the number of times x appears in 'b' less the + // number of times we've seen it in 'a' so far ... kinda + avail := map[string]int{} + matches := 0 + for _, s := range m.a { + n, ok := avail[s] + if !ok { + n = m.fullBCount[s] + } + avail[s] = n - 1 + if n > 0 { + matches += 1 + } + } + return calculateRatio(matches, len(m.a)+len(m.b)) +} + +// Return an upper bound on ratio() very quickly. +// +// This isn't defined beyond that it is an upper bound on .Ratio(), and +// is faster to compute than either .Ratio() or .QuickRatio(). +func (m *SequenceMatcher) RealQuickRatio() float64 { + la, lb := len(m.a), len(m.b) + return calculateRatio(min(la, lb), la+lb) +} + +// Convert range to the "ed" format +func formatRangeUnified(start, stop int) string { + // Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning := start + 1 // lines start numbering with one + length := stop - start + if length == 1 { + return fmt.Sprintf("%d", beginning) + } + if length == 0 { + beginning -= 1 // empty ranges begin at line just before the range + } + return fmt.Sprintf("%d,%d", beginning, length) +} + +// Unified diff parameters +type UnifiedDiff struct { + A []string // First sequence lines + FromFile string // First file name + FromDate string // First file time + B []string // Second sequence lines + ToFile string // Second file name + ToDate string // Second file time + Eol string // Headers end of line, defaults to LF + Context int // Number of context lines +} + +// Compare two sequences of lines; generate the delta as a unified diff. +// +// Unified diffs are a compact way of showing line changes and a few +// lines of context. The number of context lines is set by 'n' which +// defaults to three. +// +// By default, the diff control lines (those with ---, +++, or @@) are +// created with a trailing newline. This is helpful so that inputs +// created from file.readlines() result in diffs that are suitable for +// file.writelines() since both the inputs and outputs have trailing +// newlines. +// +// For inputs that do not have trailing newlines, set the lineterm +// argument to "" so that the output will be uniformly newline free. +// +// The unidiff format normally has a header for filenames and modification +// times. Any or all of these may be specified using strings for +// 'fromfile', 'tofile', 'fromfiledate', and 'tofiledate'. +// The modification times are normally expressed in the ISO 8601 format. +func WriteUnifiedDiff(writer io.Writer, diff UnifiedDiff) error { + buf := bufio.NewWriter(writer) + defer buf.Flush() + wf := func(format string, args ...interface{}) error { + _, err := buf.WriteString(fmt.Sprintf(format, args...)) + return err + } + ws := func(s string) error { + _, err := buf.WriteString(s) + return err + } + + if len(diff.Eol) == 0 { + diff.Eol = "\n" + } + + started := false + m := NewMatcher(diff.A, diff.B) + for _, g := range m.GetGroupedOpCodes(diff.Context) { + if !started { + started = true + fromDate := "" + if len(diff.FromDate) > 0 { + fromDate = "\t" + diff.FromDate + } + toDate := "" + if len(diff.ToDate) > 0 { + toDate = "\t" + diff.ToDate + } + if diff.FromFile != "" || diff.ToFile != "" { + err := wf("--- %s%s%s", diff.FromFile, fromDate, diff.Eol) + if err != nil { + return err + } + err = wf("+++ %s%s%s", diff.ToFile, toDate, diff.Eol) + if err != nil { + return err + } + } + } + first, last := g[0], g[len(g)-1] + range1 := formatRangeUnified(first.I1, last.I2) + range2 := formatRangeUnified(first.J1, last.J2) + if err := wf("@@ -%s +%s @@%s", range1, range2, diff.Eol); err != nil { + return err + } + for _, c := range g { + i1, i2, j1, j2 := c.I1, c.I2, c.J1, c.J2 + if c.Tag == 'e' { + for _, line := range diff.A[i1:i2] { + if err := ws(" " + line); err != nil { + return err + } + } + continue + } + if c.Tag == 'r' || c.Tag == 'd' { + for _, line := range diff.A[i1:i2] { + if err := ws("-" + line); err != nil { + return err + } + } + } + if c.Tag == 'r' || c.Tag == 'i' { + for _, line := range diff.B[j1:j2] { + if err := ws("+" + line); err != nil { + return err + } + } + } + } + } + return nil +} + +// Like WriteUnifiedDiff but returns the diff a string. +func GetUnifiedDiffString(diff UnifiedDiff) (string, error) { + w := &bytes.Buffer{} + err := WriteUnifiedDiff(w, diff) + return string(w.Bytes()), err +} + +// Convert range to the "ed" format. +func formatRangeContext(start, stop int) string { + // Per the diff spec at http://www.unix.org/single_unix_specification/ + beginning := start + 1 // lines start numbering with one + length := stop - start + if length == 0 { + beginning -= 1 // empty ranges begin at line just before the range + } + if length <= 1 { + return fmt.Sprintf("%d", beginning) + } + return fmt.Sprintf("%d,%d", beginning, beginning+length-1) +} + +type ContextDiff UnifiedDiff + +// Compare two sequences of lines; generate the delta as a context diff. +// +// Context diffs are a compact way of showing line changes and a few +// lines of context. The number of context lines is set by diff.Context +// which defaults to three. +// +// By default, the diff control lines (those with *** or ---) are +// created with a trailing newline. +// +// For inputs that do not have trailing newlines, set the diff.Eol +// argument to "" so that the output will be uniformly newline free. +// +// The context diff format normally has a header for filenames and +// modification times. Any or all of these may be specified using +// strings for diff.FromFile, diff.ToFile, diff.FromDate, diff.ToDate. +// The modification times are normally expressed in the ISO 8601 format. +// If not specified, the strings default to blanks. +func WriteContextDiff(writer io.Writer, diff ContextDiff) error { + buf := bufio.NewWriter(writer) + defer buf.Flush() + var diffErr error + wf := func(format string, args ...interface{}) { + _, err := buf.WriteString(fmt.Sprintf(format, args...)) + if diffErr == nil && err != nil { + diffErr = err + } + } + ws := func(s string) { + _, err := buf.WriteString(s) + if diffErr == nil && err != nil { + diffErr = err + } + } + + if len(diff.Eol) == 0 { + diff.Eol = "\n" + } + + prefix := map[byte]string{ + 'i': "+ ", + 'd': "- ", + 'r': "! ", + 'e': " ", + } + + started := false + m := NewMatcher(diff.A, diff.B) + for _, g := range m.GetGroupedOpCodes(diff.Context) { + if !started { + started = true + fromDate := "" + if len(diff.FromDate) > 0 { + fromDate = "\t" + diff.FromDate + } + toDate := "" + if len(diff.ToDate) > 0 { + toDate = "\t" + diff.ToDate + } + if diff.FromFile != "" || diff.ToFile != "" { + wf("*** %s%s%s", diff.FromFile, fromDate, diff.Eol) + wf("--- %s%s%s", diff.ToFile, toDate, diff.Eol) + } + } + + first, last := g[0], g[len(g)-1] + ws("***************" + diff.Eol) + + range1 := formatRangeContext(first.I1, last.I2) + wf("*** %s ****%s", range1, diff.Eol) + for _, c := range g { + if c.Tag == 'r' || c.Tag == 'd' { + for _, cc := range g { + if cc.Tag == 'i' { + continue + } + for _, line := range diff.A[cc.I1:cc.I2] { + ws(prefix[cc.Tag] + line) + } + } + break + } + } + + range2 := formatRangeContext(first.J1, last.J2) + wf("--- %s ----%s", range2, diff.Eol) + for _, c := range g { + if c.Tag == 'r' || c.Tag == 'i' { + for _, cc := range g { + if cc.Tag == 'd' { + continue + } + for _, line := range diff.B[cc.J1:cc.J2] { + ws(prefix[cc.Tag] + line) + } + } + break + } + } + } + return diffErr +} + +// Like WriteContextDiff but returns the diff a string. +func GetContextDiffString(diff ContextDiff) (string, error) { + w := &bytes.Buffer{} + err := WriteContextDiff(w, diff) + return string(w.Bytes()), err +} + +// Split a string on "\n" while preserving them. The output can be used +// as input for UnifiedDiff and ContextDiff structures. +func SplitLines(s string) []string { + lines := strings.SplitAfter(s, "\n") + lines[len(lines)-1] += "\n" + return lines +} diff --git a/vendor/github.com/stretchr/testify/LICENSE b/vendor/github.com/stretchr/testify/LICENSE new file mode 100644 index 00000000000..f38ec5956b6 --- /dev/null +++ b/vendor/github.com/stretchr/testify/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2012-2018 Mat Ryer and Tyler Bunnell + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/stretchr/testify/assert/assertion_format.go b/vendor/github.com/stretchr/testify/assert/assertion_format.go new file mode 100644 index 00000000000..bf89ecd21f7 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_format.go @@ -0,0 +1,622 @@ +/* +* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen +* THIS FILE MUST NOT BE EDITED BY HAND + */ + +package assert + +import ( + http "net/http" + url "net/url" + time "time" +) + +// Conditionf uses a Comparison to assert a complex condition. +func Conditionf(t TestingT, comp Comparison, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Condition(t, comp, append([]interface{}{msg}, args...)...) +} + +// Containsf asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// assert.Containsf(t, "Hello World", "World", "error message %s", "formatted") +// assert.Containsf(t, ["Hello", "World"], "World", "error message %s", "formatted") +// assert.Containsf(t, {"Hello": "World"}, "Hello", "error message %s", "formatted") +func Containsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Contains(t, s, contains, append([]interface{}{msg}, args...)...) +} + +// DirExistsf checks whether a directory exists in the given path. It also fails +// if the path is a file rather a directory or there is an error checking whether it exists. +func DirExistsf(t TestingT, path string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return DirExists(t, path, append([]interface{}{msg}, args...)...) +} + +// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// assert.ElementsMatchf(t, [1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") +func ElementsMatchf(t TestingT, listA interface{}, listB interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return ElementsMatch(t, listA, listB, append([]interface{}{msg}, args...)...) +} + +// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// assert.Emptyf(t, obj, "error message %s", "formatted") +func Emptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Empty(t, object, append([]interface{}{msg}, args...)...) +} + +// Equalf asserts that two objects are equal. +// +// assert.Equalf(t, 123, 123, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func Equalf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Equal(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// EqualErrorf asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// assert.EqualErrorf(t, err, expectedErrorString, "error message %s", "formatted") +func EqualErrorf(t TestingT, theError error, errString string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return EqualError(t, theError, errString, append([]interface{}{msg}, args...)...) +} + +// EqualValuesf asserts that two objects are equal or convertable to the same types +// and equal. +// +// assert.EqualValuesf(t, uint32(123, "error message %s", "formatted"), int32(123)) +func EqualValuesf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return EqualValues(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// Errorf asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if assert.Errorf(t, err, "error message %s", "formatted") { +// assert.Equal(t, expectedErrorf, err) +// } +func Errorf(t TestingT, err error, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Error(t, err, append([]interface{}{msg}, args...)...) +} + +// Eventuallyf asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. +// +// assert.Eventuallyf(t, func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +func Eventuallyf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Eventually(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) +} + +// Exactlyf asserts that two objects are equal in value and type. +// +// assert.Exactlyf(t, int32(123, "error message %s", "formatted"), int64(123)) +func Exactlyf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Exactly(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// Failf reports a failure through +func Failf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Fail(t, failureMessage, append([]interface{}{msg}, args...)...) +} + +// FailNowf fails test +func FailNowf(t TestingT, failureMessage string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return FailNow(t, failureMessage, append([]interface{}{msg}, args...)...) +} + +// Falsef asserts that the specified value is false. +// +// assert.Falsef(t, myBool, "error message %s", "formatted") +func Falsef(t TestingT, value bool, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return False(t, value, append([]interface{}{msg}, args...)...) +} + +// FileExistsf checks whether a file exists in the given path. It also fails if +// the path points to a directory or there is an error when trying to check the file. +func FileExistsf(t TestingT, path string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return FileExists(t, path, append([]interface{}{msg}, args...)...) +} + +// Greaterf asserts that the first element is greater than the second +// +// assert.Greaterf(t, 2, 1, "error message %s", "formatted") +// assert.Greaterf(t, float64(2, "error message %s", "formatted"), float64(1)) +// assert.Greaterf(t, "b", "a", "error message %s", "formatted") +func Greaterf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Greater(t, e1, e2, append([]interface{}{msg}, args...)...) +} + +// GreaterOrEqualf asserts that the first element is greater than or equal to the second +// +// assert.GreaterOrEqualf(t, 2, 1, "error message %s", "formatted") +// assert.GreaterOrEqualf(t, 2, 2, "error message %s", "formatted") +// assert.GreaterOrEqualf(t, "b", "a", "error message %s", "formatted") +// assert.GreaterOrEqualf(t, "b", "b", "error message %s", "formatted") +func GreaterOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return GreaterOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...) +} + +// HTTPBodyContainsf asserts that a specified handler returns a +// body that contains a string. +// +// assert.HTTPBodyContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return HTTPBodyContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) +} + +// HTTPBodyNotContainsf asserts that a specified handler returns a +// body that does not contain a string. +// +// assert.HTTPBodyNotContainsf(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyNotContainsf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return HTTPBodyNotContains(t, handler, method, url, values, str, append([]interface{}{msg}, args...)...) +} + +// HTTPErrorf asserts that a specified handler returns an error status code. +// +// assert.HTTPErrorf(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func HTTPErrorf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return HTTPError(t, handler, method, url, values, append([]interface{}{msg}, args...)...) +} + +// HTTPRedirectf asserts that a specified handler returns a redirect status code. +// +// assert.HTTPRedirectf(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func HTTPRedirectf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return HTTPRedirect(t, handler, method, url, values, append([]interface{}{msg}, args...)...) +} + +// HTTPSuccessf asserts that a specified handler returns a success status code. +// +// assert.HTTPSuccessf(t, myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPSuccessf(t TestingT, handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return HTTPSuccess(t, handler, method, url, values, append([]interface{}{msg}, args...)...) +} + +// Implementsf asserts that an object is implemented by the specified interface. +// +// assert.Implementsf(t, (*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) +func Implementsf(t TestingT, interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Implements(t, interfaceObject, object, append([]interface{}{msg}, args...)...) +} + +// InDeltaf asserts that the two numerals are within delta of each other. +// +// assert.InDeltaf(t, math.Pi, 22/7.0, 0.01, "error message %s", "formatted") +func InDeltaf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return InDelta(t, expected, actual, delta, append([]interface{}{msg}, args...)...) +} + +// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func InDeltaMapValuesf(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return InDeltaMapValues(t, expected, actual, delta, append([]interface{}{msg}, args...)...) +} + +// InDeltaSlicef is the same as InDelta, except it compares two slices. +func InDeltaSlicef(t TestingT, expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return InDeltaSlice(t, expected, actual, delta, append([]interface{}{msg}, args...)...) +} + +// InEpsilonf asserts that expected and actual have a relative error less than epsilon +func InEpsilonf(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return InEpsilon(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) +} + +// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. +func InEpsilonSlicef(t TestingT, expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return InEpsilonSlice(t, expected, actual, epsilon, append([]interface{}{msg}, args...)...) +} + +// IsTypef asserts that the specified objects are of the same type. +func IsTypef(t TestingT, expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return IsType(t, expectedType, object, append([]interface{}{msg}, args...)...) +} + +// JSONEqf asserts that two JSON strings are equivalent. +// +// assert.JSONEqf(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") +func JSONEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return JSONEq(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// Lenf asserts that the specified object has specific length. +// Lenf also fails if the object has a type that len() not accept. +// +// assert.Lenf(t, mySlice, 3, "error message %s", "formatted") +func Lenf(t TestingT, object interface{}, length int, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Len(t, object, length, append([]interface{}{msg}, args...)...) +} + +// Lessf asserts that the first element is less than the second +// +// assert.Lessf(t, 1, 2, "error message %s", "formatted") +// assert.Lessf(t, float64(1, "error message %s", "formatted"), float64(2)) +// assert.Lessf(t, "a", "b", "error message %s", "formatted") +func Lessf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Less(t, e1, e2, append([]interface{}{msg}, args...)...) +} + +// LessOrEqualf asserts that the first element is less than or equal to the second +// +// assert.LessOrEqualf(t, 1, 2, "error message %s", "formatted") +// assert.LessOrEqualf(t, 2, 2, "error message %s", "formatted") +// assert.LessOrEqualf(t, "a", "b", "error message %s", "formatted") +// assert.LessOrEqualf(t, "b", "b", "error message %s", "formatted") +func LessOrEqualf(t TestingT, e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return LessOrEqual(t, e1, e2, append([]interface{}{msg}, args...)...) +} + +// Neverf asserts that the given condition doesn't satisfy in waitFor time, +// periodically checking the target function each tick. +// +// assert.Neverf(t, func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +func Neverf(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Never(t, condition, waitFor, tick, append([]interface{}{msg}, args...)...) +} + +// Nilf asserts that the specified object is nil. +// +// assert.Nilf(t, err, "error message %s", "formatted") +func Nilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Nil(t, object, append([]interface{}{msg}, args...)...) +} + +// NoDirExistsf checks whether a directory does not exist in the given path. +// It fails if the path points to an existing _directory_ only. +func NoDirExistsf(t TestingT, path string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NoDirExists(t, path, append([]interface{}{msg}, args...)...) +} + +// NoErrorf asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if assert.NoErrorf(t, err, "error message %s", "formatted") { +// assert.Equal(t, expectedObj, actualObj) +// } +func NoErrorf(t TestingT, err error, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NoError(t, err, append([]interface{}{msg}, args...)...) +} + +// NoFileExistsf checks whether a file does not exist in a given path. It fails +// if the path points to an existing _file_ only. +func NoFileExistsf(t TestingT, path string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NoFileExists(t, path, append([]interface{}{msg}, args...)...) +} + +// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// assert.NotContainsf(t, "Hello World", "Earth", "error message %s", "formatted") +// assert.NotContainsf(t, ["Hello", "World"], "Earth", "error message %s", "formatted") +// assert.NotContainsf(t, {"Hello": "World"}, "Earth", "error message %s", "formatted") +func NotContainsf(t TestingT, s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotContains(t, s, contains, append([]interface{}{msg}, args...)...) +} + +// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if assert.NotEmptyf(t, obj, "error message %s", "formatted") { +// assert.Equal(t, "two", obj[1]) +// } +func NotEmptyf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotEmpty(t, object, append([]interface{}{msg}, args...)...) +} + +// NotEqualf asserts that the specified values are NOT equal. +// +// assert.NotEqualf(t, obj1, obj2, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func NotEqualf(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotEqual(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// NotNilf asserts that the specified object is not nil. +// +// assert.NotNilf(t, err, "error message %s", "formatted") +func NotNilf(t TestingT, object interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotNil(t, object, append([]interface{}{msg}, args...)...) +} + +// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// assert.NotPanicsf(t, func(){ RemainCalm() }, "error message %s", "formatted") +func NotPanicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotPanics(t, f, append([]interface{}{msg}, args...)...) +} + +// NotRegexpf asserts that a specified regexp does not match a string. +// +// assert.NotRegexpf(t, regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") +// assert.NotRegexpf(t, "^start", "it's not starting", "error message %s", "formatted") +func NotRegexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotRegexp(t, rx, str, append([]interface{}{msg}, args...)...) +} + +// NotSamef asserts that two pointers do not reference the same object. +// +// assert.NotSamef(t, ptr1, ptr2, "error message %s", "formatted") +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func NotSamef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotSame(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// NotSubsetf asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// assert.NotSubsetf(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +func NotSubsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotSubset(t, list, subset, append([]interface{}{msg}, args...)...) +} + +// NotZerof asserts that i is not the zero value for its type. +func NotZerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return NotZero(t, i, append([]interface{}{msg}, args...)...) +} + +// Panicsf asserts that the code inside the specified PanicTestFunc panics. +// +// assert.Panicsf(t, func(){ GoCrazy() }, "error message %s", "formatted") +func Panicsf(t TestingT, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Panics(t, f, append([]interface{}{msg}, args...)...) +} + +// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc +// panics, and that the recovered panic value is an error that satisfies the +// EqualError comparison. +// +// assert.PanicsWithErrorf(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +func PanicsWithErrorf(t TestingT, errString string, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return PanicsWithError(t, errString, f, append([]interface{}{msg}, args...)...) +} + +// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// assert.PanicsWithValuef(t, "crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +func PanicsWithValuef(t TestingT, expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return PanicsWithValue(t, expected, f, append([]interface{}{msg}, args...)...) +} + +// Regexpf asserts that a specified regexp matches a string. +// +// assert.Regexpf(t, regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") +// assert.Regexpf(t, "start...$", "it's not starting", "error message %s", "formatted") +func Regexpf(t TestingT, rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Regexp(t, rx, str, append([]interface{}{msg}, args...)...) +} + +// Samef asserts that two pointers reference the same object. +// +// assert.Samef(t, ptr1, ptr2, "error message %s", "formatted") +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func Samef(t TestingT, expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Same(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// Subsetf asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// assert.Subsetf(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +func Subsetf(t TestingT, list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Subset(t, list, subset, append([]interface{}{msg}, args...)...) +} + +// Truef asserts that the specified value is true. +// +// assert.Truef(t, myBool, "error message %s", "formatted") +func Truef(t TestingT, value bool, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return True(t, value, append([]interface{}{msg}, args...)...) +} + +// WithinDurationf asserts that the two times are within duration delta of each other. +// +// assert.WithinDurationf(t, time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") +func WithinDurationf(t TestingT, expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return WithinDuration(t, expected, actual, delta, append([]interface{}{msg}, args...)...) +} + +// YAMLEqf asserts that two YAML strings are equivalent. +func YAMLEqf(t TestingT, expected string, actual string, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return YAMLEq(t, expected, actual, append([]interface{}{msg}, args...)...) +} + +// Zerof asserts that i is the zero value for its type. +func Zerof(t TestingT, i interface{}, msg string, args ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + return Zero(t, i, append([]interface{}{msg}, args...)...) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_forward.go b/vendor/github.com/stretchr/testify/assert/assertion_forward.go new file mode 100644 index 00000000000..75ecdcaa2f3 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_forward.go @@ -0,0 +1,1232 @@ +/* +* CODE GENERATED AUTOMATICALLY WITH github.com/stretchr/testify/_codegen +* THIS FILE MUST NOT BE EDITED BY HAND + */ + +package assert + +import ( + http "net/http" + url "net/url" + time "time" +) + +// Condition uses a Comparison to assert a complex condition. +func (a *Assertions) Condition(comp Comparison, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Condition(a.t, comp, msgAndArgs...) +} + +// Conditionf uses a Comparison to assert a complex condition. +func (a *Assertions) Conditionf(comp Comparison, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Conditionf(a.t, comp, msg, args...) +} + +// Contains asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// a.Contains("Hello World", "World") +// a.Contains(["Hello", "World"], "World") +// a.Contains({"Hello": "World"}, "Hello") +func (a *Assertions) Contains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Contains(a.t, s, contains, msgAndArgs...) +} + +// Containsf asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// a.Containsf("Hello World", "World", "error message %s", "formatted") +// a.Containsf(["Hello", "World"], "World", "error message %s", "formatted") +// a.Containsf({"Hello": "World"}, "Hello", "error message %s", "formatted") +func (a *Assertions) Containsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Containsf(a.t, s, contains, msg, args...) +} + +// DirExists checks whether a directory exists in the given path. It also fails +// if the path is a file rather a directory or there is an error checking whether it exists. +func (a *Assertions) DirExists(path string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return DirExists(a.t, path, msgAndArgs...) +} + +// DirExistsf checks whether a directory exists in the given path. It also fails +// if the path is a file rather a directory or there is an error checking whether it exists. +func (a *Assertions) DirExistsf(path string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return DirExistsf(a.t, path, msg, args...) +} + +// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// a.ElementsMatch([1, 3, 2, 3], [1, 3, 3, 2]) +func (a *Assertions) ElementsMatch(listA interface{}, listB interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return ElementsMatch(a.t, listA, listB, msgAndArgs...) +} + +// ElementsMatchf asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// a.ElementsMatchf([1, 3, 2, 3], [1, 3, 3, 2], "error message %s", "formatted") +func (a *Assertions) ElementsMatchf(listA interface{}, listB interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return ElementsMatchf(a.t, listA, listB, msg, args...) +} + +// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// a.Empty(obj) +func (a *Assertions) Empty(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Empty(a.t, object, msgAndArgs...) +} + +// Emptyf asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// a.Emptyf(obj, "error message %s", "formatted") +func (a *Assertions) Emptyf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Emptyf(a.t, object, msg, args...) +} + +// Equal asserts that two objects are equal. +// +// a.Equal(123, 123) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func (a *Assertions) Equal(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Equal(a.t, expected, actual, msgAndArgs...) +} + +// EqualError asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// a.EqualError(err, expectedErrorString) +func (a *Assertions) EqualError(theError error, errString string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return EqualError(a.t, theError, errString, msgAndArgs...) +} + +// EqualErrorf asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// a.EqualErrorf(err, expectedErrorString, "error message %s", "formatted") +func (a *Assertions) EqualErrorf(theError error, errString string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return EqualErrorf(a.t, theError, errString, msg, args...) +} + +// EqualValues asserts that two objects are equal or convertable to the same types +// and equal. +// +// a.EqualValues(uint32(123), int32(123)) +func (a *Assertions) EqualValues(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return EqualValues(a.t, expected, actual, msgAndArgs...) +} + +// EqualValuesf asserts that two objects are equal or convertable to the same types +// and equal. +// +// a.EqualValuesf(uint32(123, "error message %s", "formatted"), int32(123)) +func (a *Assertions) EqualValuesf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return EqualValuesf(a.t, expected, actual, msg, args...) +} + +// Equalf asserts that two objects are equal. +// +// a.Equalf(123, 123, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func (a *Assertions) Equalf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Equalf(a.t, expected, actual, msg, args...) +} + +// Error asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if a.Error(err) { +// assert.Equal(t, expectedError, err) +// } +func (a *Assertions) Error(err error, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Error(a.t, err, msgAndArgs...) +} + +// Errorf asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if a.Errorf(err, "error message %s", "formatted") { +// assert.Equal(t, expectedErrorf, err) +// } +func (a *Assertions) Errorf(err error, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Errorf(a.t, err, msg, args...) +} + +// Eventually asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. +// +// a.Eventually(func() bool { return true; }, time.Second, 10*time.Millisecond) +func (a *Assertions) Eventually(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Eventually(a.t, condition, waitFor, tick, msgAndArgs...) +} + +// Eventuallyf asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. +// +// a.Eventuallyf(func() bool { return true; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +func (a *Assertions) Eventuallyf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Eventuallyf(a.t, condition, waitFor, tick, msg, args...) +} + +// Exactly asserts that two objects are equal in value and type. +// +// a.Exactly(int32(123), int64(123)) +func (a *Assertions) Exactly(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Exactly(a.t, expected, actual, msgAndArgs...) +} + +// Exactlyf asserts that two objects are equal in value and type. +// +// a.Exactlyf(int32(123, "error message %s", "formatted"), int64(123)) +func (a *Assertions) Exactlyf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Exactlyf(a.t, expected, actual, msg, args...) +} + +// Fail reports a failure through +func (a *Assertions) Fail(failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Fail(a.t, failureMessage, msgAndArgs...) +} + +// FailNow fails test +func (a *Assertions) FailNow(failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return FailNow(a.t, failureMessage, msgAndArgs...) +} + +// FailNowf fails test +func (a *Assertions) FailNowf(failureMessage string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return FailNowf(a.t, failureMessage, msg, args...) +} + +// Failf reports a failure through +func (a *Assertions) Failf(failureMessage string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Failf(a.t, failureMessage, msg, args...) +} + +// False asserts that the specified value is false. +// +// a.False(myBool) +func (a *Assertions) False(value bool, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return False(a.t, value, msgAndArgs...) +} + +// Falsef asserts that the specified value is false. +// +// a.Falsef(myBool, "error message %s", "formatted") +func (a *Assertions) Falsef(value bool, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Falsef(a.t, value, msg, args...) +} + +// FileExists checks whether a file exists in the given path. It also fails if +// the path points to a directory or there is an error when trying to check the file. +func (a *Assertions) FileExists(path string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return FileExists(a.t, path, msgAndArgs...) +} + +// FileExistsf checks whether a file exists in the given path. It also fails if +// the path points to a directory or there is an error when trying to check the file. +func (a *Assertions) FileExistsf(path string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return FileExistsf(a.t, path, msg, args...) +} + +// Greater asserts that the first element is greater than the second +// +// a.Greater(2, 1) +// a.Greater(float64(2), float64(1)) +// a.Greater("b", "a") +func (a *Assertions) Greater(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Greater(a.t, e1, e2, msgAndArgs...) +} + +// GreaterOrEqual asserts that the first element is greater than or equal to the second +// +// a.GreaterOrEqual(2, 1) +// a.GreaterOrEqual(2, 2) +// a.GreaterOrEqual("b", "a") +// a.GreaterOrEqual("b", "b") +func (a *Assertions) GreaterOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return GreaterOrEqual(a.t, e1, e2, msgAndArgs...) +} + +// GreaterOrEqualf asserts that the first element is greater than or equal to the second +// +// a.GreaterOrEqualf(2, 1, "error message %s", "formatted") +// a.GreaterOrEqualf(2, 2, "error message %s", "formatted") +// a.GreaterOrEqualf("b", "a", "error message %s", "formatted") +// a.GreaterOrEqualf("b", "b", "error message %s", "formatted") +func (a *Assertions) GreaterOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return GreaterOrEqualf(a.t, e1, e2, msg, args...) +} + +// Greaterf asserts that the first element is greater than the second +// +// a.Greaterf(2, 1, "error message %s", "formatted") +// a.Greaterf(float64(2, "error message %s", "formatted"), float64(1)) +// a.Greaterf("b", "a", "error message %s", "formatted") +func (a *Assertions) Greaterf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Greaterf(a.t, e1, e2, msg, args...) +} + +// HTTPBodyContains asserts that a specified handler returns a +// body that contains a string. +// +// a.HTTPBodyContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPBodyContains(a.t, handler, method, url, values, str, msgAndArgs...) +} + +// HTTPBodyContainsf asserts that a specified handler returns a +// body that contains a string. +// +// a.HTTPBodyContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPBodyContainsf(a.t, handler, method, url, values, str, msg, args...) +} + +// HTTPBodyNotContains asserts that a specified handler returns a +// body that does not contain a string. +// +// a.HTTPBodyNotContains(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyNotContains(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPBodyNotContains(a.t, handler, method, url, values, str, msgAndArgs...) +} + +// HTTPBodyNotContainsf asserts that a specified handler returns a +// body that does not contain a string. +// +// a.HTTPBodyNotContainsf(myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky", "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPBodyNotContainsf(handler http.HandlerFunc, method string, url string, values url.Values, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPBodyNotContainsf(a.t, handler, method, url, values, str, msg, args...) +} + +// HTTPError asserts that a specified handler returns an error status code. +// +// a.HTTPError(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPError(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPError(a.t, handler, method, url, values, msgAndArgs...) +} + +// HTTPErrorf asserts that a specified handler returns an error status code. +// +// a.HTTPErrorf(myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func (a *Assertions) HTTPErrorf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPErrorf(a.t, handler, method, url, values, msg, args...) +} + +// HTTPRedirect asserts that a specified handler returns a redirect status code. +// +// a.HTTPRedirect(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPRedirect(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPRedirect(a.t, handler, method, url, values, msgAndArgs...) +} + +// HTTPRedirectf asserts that a specified handler returns a redirect status code. +// +// a.HTTPRedirectf(myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true, "error message %s", "formatted") or not (false). +func (a *Assertions) HTTPRedirectf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPRedirectf(a.t, handler, method, url, values, msg, args...) +} + +// HTTPSuccess asserts that a specified handler returns a success status code. +// +// a.HTTPSuccess(myHandler, "POST", "http://www.google.com", nil) +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPSuccess(handler http.HandlerFunc, method string, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPSuccess(a.t, handler, method, url, values, msgAndArgs...) +} + +// HTTPSuccessf asserts that a specified handler returns a success status code. +// +// a.HTTPSuccessf(myHandler, "POST", "http://www.google.com", nil, "error message %s", "formatted") +// +// Returns whether the assertion was successful (true) or not (false). +func (a *Assertions) HTTPSuccessf(handler http.HandlerFunc, method string, url string, values url.Values, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return HTTPSuccessf(a.t, handler, method, url, values, msg, args...) +} + +// Implements asserts that an object is implemented by the specified interface. +// +// a.Implements((*MyInterface)(nil), new(MyObject)) +func (a *Assertions) Implements(interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Implements(a.t, interfaceObject, object, msgAndArgs...) +} + +// Implementsf asserts that an object is implemented by the specified interface. +// +// a.Implementsf((*MyInterface, "error message %s", "formatted")(nil), new(MyObject)) +func (a *Assertions) Implementsf(interfaceObject interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Implementsf(a.t, interfaceObject, object, msg, args...) +} + +// InDelta asserts that the two numerals are within delta of each other. +// +// a.InDelta(math.Pi, 22/7.0, 0.01) +func (a *Assertions) InDelta(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InDelta(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func (a *Assertions) InDeltaMapValues(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InDeltaMapValues(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDeltaMapValuesf is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func (a *Assertions) InDeltaMapValuesf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InDeltaMapValuesf(a.t, expected, actual, delta, msg, args...) +} + +// InDeltaSlice is the same as InDelta, except it compares two slices. +func (a *Assertions) InDeltaSlice(expected interface{}, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InDeltaSlice(a.t, expected, actual, delta, msgAndArgs...) +} + +// InDeltaSlicef is the same as InDelta, except it compares two slices. +func (a *Assertions) InDeltaSlicef(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InDeltaSlicef(a.t, expected, actual, delta, msg, args...) +} + +// InDeltaf asserts that the two numerals are within delta of each other. +// +// a.InDeltaf(math.Pi, 22/7.0, 0.01, "error message %s", "formatted") +func (a *Assertions) InDeltaf(expected interface{}, actual interface{}, delta float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InDeltaf(a.t, expected, actual, delta, msg, args...) +} + +// InEpsilon asserts that expected and actual have a relative error less than epsilon +func (a *Assertions) InEpsilon(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InEpsilon(a.t, expected, actual, epsilon, msgAndArgs...) +} + +// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. +func (a *Assertions) InEpsilonSlice(expected interface{}, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InEpsilonSlice(a.t, expected, actual, epsilon, msgAndArgs...) +} + +// InEpsilonSlicef is the same as InEpsilon, except it compares each value from two slices. +func (a *Assertions) InEpsilonSlicef(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InEpsilonSlicef(a.t, expected, actual, epsilon, msg, args...) +} + +// InEpsilonf asserts that expected and actual have a relative error less than epsilon +func (a *Assertions) InEpsilonf(expected interface{}, actual interface{}, epsilon float64, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return InEpsilonf(a.t, expected, actual, epsilon, msg, args...) +} + +// IsType asserts that the specified objects are of the same type. +func (a *Assertions) IsType(expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsType(a.t, expectedType, object, msgAndArgs...) +} + +// IsTypef asserts that the specified objects are of the same type. +func (a *Assertions) IsTypef(expectedType interface{}, object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return IsTypef(a.t, expectedType, object, msg, args...) +} + +// JSONEq asserts that two JSON strings are equivalent. +// +// a.JSONEq(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) +func (a *Assertions) JSONEq(expected string, actual string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return JSONEq(a.t, expected, actual, msgAndArgs...) +} + +// JSONEqf asserts that two JSON strings are equivalent. +// +// a.JSONEqf(`{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`, "error message %s", "formatted") +func (a *Assertions) JSONEqf(expected string, actual string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return JSONEqf(a.t, expected, actual, msg, args...) +} + +// Len asserts that the specified object has specific length. +// Len also fails if the object has a type that len() not accept. +// +// a.Len(mySlice, 3) +func (a *Assertions) Len(object interface{}, length int, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Len(a.t, object, length, msgAndArgs...) +} + +// Lenf asserts that the specified object has specific length. +// Lenf also fails if the object has a type that len() not accept. +// +// a.Lenf(mySlice, 3, "error message %s", "formatted") +func (a *Assertions) Lenf(object interface{}, length int, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Lenf(a.t, object, length, msg, args...) +} + +// Less asserts that the first element is less than the second +// +// a.Less(1, 2) +// a.Less(float64(1), float64(2)) +// a.Less("a", "b") +func (a *Assertions) Less(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Less(a.t, e1, e2, msgAndArgs...) +} + +// LessOrEqual asserts that the first element is less than or equal to the second +// +// a.LessOrEqual(1, 2) +// a.LessOrEqual(2, 2) +// a.LessOrEqual("a", "b") +// a.LessOrEqual("b", "b") +func (a *Assertions) LessOrEqual(e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return LessOrEqual(a.t, e1, e2, msgAndArgs...) +} + +// LessOrEqualf asserts that the first element is less than or equal to the second +// +// a.LessOrEqualf(1, 2, "error message %s", "formatted") +// a.LessOrEqualf(2, 2, "error message %s", "formatted") +// a.LessOrEqualf("a", "b", "error message %s", "formatted") +// a.LessOrEqualf("b", "b", "error message %s", "formatted") +func (a *Assertions) LessOrEqualf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return LessOrEqualf(a.t, e1, e2, msg, args...) +} + +// Lessf asserts that the first element is less than the second +// +// a.Lessf(1, 2, "error message %s", "formatted") +// a.Lessf(float64(1, "error message %s", "formatted"), float64(2)) +// a.Lessf("a", "b", "error message %s", "formatted") +func (a *Assertions) Lessf(e1 interface{}, e2 interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Lessf(a.t, e1, e2, msg, args...) +} + +// Never asserts that the given condition doesn't satisfy in waitFor time, +// periodically checking the target function each tick. +// +// a.Never(func() bool { return false; }, time.Second, 10*time.Millisecond) +func (a *Assertions) Never(condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Never(a.t, condition, waitFor, tick, msgAndArgs...) +} + +// Neverf asserts that the given condition doesn't satisfy in waitFor time, +// periodically checking the target function each tick. +// +// a.Neverf(func() bool { return false; }, time.Second, 10*time.Millisecond, "error message %s", "formatted") +func (a *Assertions) Neverf(condition func() bool, waitFor time.Duration, tick time.Duration, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Neverf(a.t, condition, waitFor, tick, msg, args...) +} + +// Nil asserts that the specified object is nil. +// +// a.Nil(err) +func (a *Assertions) Nil(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Nil(a.t, object, msgAndArgs...) +} + +// Nilf asserts that the specified object is nil. +// +// a.Nilf(err, "error message %s", "formatted") +func (a *Assertions) Nilf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Nilf(a.t, object, msg, args...) +} + +// NoDirExists checks whether a directory does not exist in the given path. +// It fails if the path points to an existing _directory_ only. +func (a *Assertions) NoDirExists(path string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NoDirExists(a.t, path, msgAndArgs...) +} + +// NoDirExistsf checks whether a directory does not exist in the given path. +// It fails if the path points to an existing _directory_ only. +func (a *Assertions) NoDirExistsf(path string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NoDirExistsf(a.t, path, msg, args...) +} + +// NoError asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if a.NoError(err) { +// assert.Equal(t, expectedObj, actualObj) +// } +func (a *Assertions) NoError(err error, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NoError(a.t, err, msgAndArgs...) +} + +// NoErrorf asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if a.NoErrorf(err, "error message %s", "formatted") { +// assert.Equal(t, expectedObj, actualObj) +// } +func (a *Assertions) NoErrorf(err error, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NoErrorf(a.t, err, msg, args...) +} + +// NoFileExists checks whether a file does not exist in a given path. It fails +// if the path points to an existing _file_ only. +func (a *Assertions) NoFileExists(path string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NoFileExists(a.t, path, msgAndArgs...) +} + +// NoFileExistsf checks whether a file does not exist in a given path. It fails +// if the path points to an existing _file_ only. +func (a *Assertions) NoFileExistsf(path string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NoFileExistsf(a.t, path, msg, args...) +} + +// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// a.NotContains("Hello World", "Earth") +// a.NotContains(["Hello", "World"], "Earth") +// a.NotContains({"Hello": "World"}, "Earth") +func (a *Assertions) NotContains(s interface{}, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotContains(a.t, s, contains, msgAndArgs...) +} + +// NotContainsf asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// a.NotContainsf("Hello World", "Earth", "error message %s", "formatted") +// a.NotContainsf(["Hello", "World"], "Earth", "error message %s", "formatted") +// a.NotContainsf({"Hello": "World"}, "Earth", "error message %s", "formatted") +func (a *Assertions) NotContainsf(s interface{}, contains interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotContainsf(a.t, s, contains, msg, args...) +} + +// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if a.NotEmpty(obj) { +// assert.Equal(t, "two", obj[1]) +// } +func (a *Assertions) NotEmpty(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotEmpty(a.t, object, msgAndArgs...) +} + +// NotEmptyf asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if a.NotEmptyf(obj, "error message %s", "formatted") { +// assert.Equal(t, "two", obj[1]) +// } +func (a *Assertions) NotEmptyf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotEmptyf(a.t, object, msg, args...) +} + +// NotEqual asserts that the specified values are NOT equal. +// +// a.NotEqual(obj1, obj2) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func (a *Assertions) NotEqual(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotEqual(a.t, expected, actual, msgAndArgs...) +} + +// NotEqualf asserts that the specified values are NOT equal. +// +// a.NotEqualf(obj1, obj2, "error message %s", "formatted") +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func (a *Assertions) NotEqualf(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotEqualf(a.t, expected, actual, msg, args...) +} + +// NotNil asserts that the specified object is not nil. +// +// a.NotNil(err) +func (a *Assertions) NotNil(object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotNil(a.t, object, msgAndArgs...) +} + +// NotNilf asserts that the specified object is not nil. +// +// a.NotNilf(err, "error message %s", "formatted") +func (a *Assertions) NotNilf(object interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotNilf(a.t, object, msg, args...) +} + +// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// a.NotPanics(func(){ RemainCalm() }) +func (a *Assertions) NotPanics(f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotPanics(a.t, f, msgAndArgs...) +} + +// NotPanicsf asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// a.NotPanicsf(func(){ RemainCalm() }, "error message %s", "formatted") +func (a *Assertions) NotPanicsf(f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotPanicsf(a.t, f, msg, args...) +} + +// NotRegexp asserts that a specified regexp does not match a string. +// +// a.NotRegexp(regexp.MustCompile("starts"), "it's starting") +// a.NotRegexp("^start", "it's not starting") +func (a *Assertions) NotRegexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotRegexp(a.t, rx, str, msgAndArgs...) +} + +// NotRegexpf asserts that a specified regexp does not match a string. +// +// a.NotRegexpf(regexp.MustCompile("starts", "error message %s", "formatted"), "it's starting") +// a.NotRegexpf("^start", "it's not starting", "error message %s", "formatted") +func (a *Assertions) NotRegexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotRegexpf(a.t, rx, str, msg, args...) +} + +// NotSame asserts that two pointers do not reference the same object. +// +// a.NotSame(ptr1, ptr2) +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func (a *Assertions) NotSame(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotSame(a.t, expected, actual, msgAndArgs...) +} + +// NotSamef asserts that two pointers do not reference the same object. +// +// a.NotSamef(ptr1, ptr2, "error message %s", "formatted") +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func (a *Assertions) NotSamef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotSamef(a.t, expected, actual, msg, args...) +} + +// NotSubset asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// a.NotSubset([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +func (a *Assertions) NotSubset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotSubset(a.t, list, subset, msgAndArgs...) +} + +// NotSubsetf asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// a.NotSubsetf([1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]", "error message %s", "formatted") +func (a *Assertions) NotSubsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotSubsetf(a.t, list, subset, msg, args...) +} + +// NotZero asserts that i is not the zero value for its type. +func (a *Assertions) NotZero(i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotZero(a.t, i, msgAndArgs...) +} + +// NotZerof asserts that i is not the zero value for its type. +func (a *Assertions) NotZerof(i interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return NotZerof(a.t, i, msg, args...) +} + +// Panics asserts that the code inside the specified PanicTestFunc panics. +// +// a.Panics(func(){ GoCrazy() }) +func (a *Assertions) Panics(f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Panics(a.t, f, msgAndArgs...) +} + +// PanicsWithError asserts that the code inside the specified PanicTestFunc +// panics, and that the recovered panic value is an error that satisfies the +// EqualError comparison. +// +// a.PanicsWithError("crazy error", func(){ GoCrazy() }) +func (a *Assertions) PanicsWithError(errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return PanicsWithError(a.t, errString, f, msgAndArgs...) +} + +// PanicsWithErrorf asserts that the code inside the specified PanicTestFunc +// panics, and that the recovered panic value is an error that satisfies the +// EqualError comparison. +// +// a.PanicsWithErrorf("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +func (a *Assertions) PanicsWithErrorf(errString string, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return PanicsWithErrorf(a.t, errString, f, msg, args...) +} + +// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// a.PanicsWithValue("crazy error", func(){ GoCrazy() }) +func (a *Assertions) PanicsWithValue(expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return PanicsWithValue(a.t, expected, f, msgAndArgs...) +} + +// PanicsWithValuef asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// a.PanicsWithValuef("crazy error", func(){ GoCrazy() }, "error message %s", "formatted") +func (a *Assertions) PanicsWithValuef(expected interface{}, f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return PanicsWithValuef(a.t, expected, f, msg, args...) +} + +// Panicsf asserts that the code inside the specified PanicTestFunc panics. +// +// a.Panicsf(func(){ GoCrazy() }, "error message %s", "formatted") +func (a *Assertions) Panicsf(f PanicTestFunc, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Panicsf(a.t, f, msg, args...) +} + +// Regexp asserts that a specified regexp matches a string. +// +// a.Regexp(regexp.MustCompile("start"), "it's starting") +// a.Regexp("start...$", "it's not starting") +func (a *Assertions) Regexp(rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Regexp(a.t, rx, str, msgAndArgs...) +} + +// Regexpf asserts that a specified regexp matches a string. +// +// a.Regexpf(regexp.MustCompile("start", "error message %s", "formatted"), "it's starting") +// a.Regexpf("start...$", "it's not starting", "error message %s", "formatted") +func (a *Assertions) Regexpf(rx interface{}, str interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Regexpf(a.t, rx, str, msg, args...) +} + +// Same asserts that two pointers reference the same object. +// +// a.Same(ptr1, ptr2) +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func (a *Assertions) Same(expected interface{}, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Same(a.t, expected, actual, msgAndArgs...) +} + +// Samef asserts that two pointers reference the same object. +// +// a.Samef(ptr1, ptr2, "error message %s", "formatted") +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func (a *Assertions) Samef(expected interface{}, actual interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Samef(a.t, expected, actual, msg, args...) +} + +// Subset asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// a.Subset([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +func (a *Assertions) Subset(list interface{}, subset interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Subset(a.t, list, subset, msgAndArgs...) +} + +// Subsetf asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// a.Subsetf([1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]", "error message %s", "formatted") +func (a *Assertions) Subsetf(list interface{}, subset interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Subsetf(a.t, list, subset, msg, args...) +} + +// True asserts that the specified value is true. +// +// a.True(myBool) +func (a *Assertions) True(value bool, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return True(a.t, value, msgAndArgs...) +} + +// Truef asserts that the specified value is true. +// +// a.Truef(myBool, "error message %s", "formatted") +func (a *Assertions) Truef(value bool, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Truef(a.t, value, msg, args...) +} + +// WithinDuration asserts that the two times are within duration delta of each other. +// +// a.WithinDuration(time.Now(), time.Now(), 10*time.Second) +func (a *Assertions) WithinDuration(expected time.Time, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return WithinDuration(a.t, expected, actual, delta, msgAndArgs...) +} + +// WithinDurationf asserts that the two times are within duration delta of each other. +// +// a.WithinDurationf(time.Now(), time.Now(), 10*time.Second, "error message %s", "formatted") +func (a *Assertions) WithinDurationf(expected time.Time, actual time.Time, delta time.Duration, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return WithinDurationf(a.t, expected, actual, delta, msg, args...) +} + +// YAMLEq asserts that two YAML strings are equivalent. +func (a *Assertions) YAMLEq(expected string, actual string, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return YAMLEq(a.t, expected, actual, msgAndArgs...) +} + +// YAMLEqf asserts that two YAML strings are equivalent. +func (a *Assertions) YAMLEqf(expected string, actual string, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return YAMLEqf(a.t, expected, actual, msg, args...) +} + +// Zero asserts that i is the zero value for its type. +func (a *Assertions) Zero(i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Zero(a.t, i, msgAndArgs...) +} + +// Zerof asserts that i is the zero value for its type. +func (a *Assertions) Zerof(i interface{}, msg string, args ...interface{}) bool { + if h, ok := a.t.(tHelper); ok { + h.Helper() + } + return Zerof(a.t, i, msg, args...) +} diff --git a/vendor/github.com/stretchr/testify/assert/assertion_order.go b/vendor/github.com/stretchr/testify/assert/assertion_order.go new file mode 100644 index 00000000000..15a486ca6e2 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertion_order.go @@ -0,0 +1,309 @@ +package assert + +import ( + "fmt" + "reflect" +) + +func compare(obj1, obj2 interface{}, kind reflect.Kind) (int, bool) { + switch kind { + case reflect.Int: + { + intobj1 := obj1.(int) + intobj2 := obj2.(int) + if intobj1 > intobj2 { + return -1, true + } + if intobj1 == intobj2 { + return 0, true + } + if intobj1 < intobj2 { + return 1, true + } + } + case reflect.Int8: + { + int8obj1 := obj1.(int8) + int8obj2 := obj2.(int8) + if int8obj1 > int8obj2 { + return -1, true + } + if int8obj1 == int8obj2 { + return 0, true + } + if int8obj1 < int8obj2 { + return 1, true + } + } + case reflect.Int16: + { + int16obj1 := obj1.(int16) + int16obj2 := obj2.(int16) + if int16obj1 > int16obj2 { + return -1, true + } + if int16obj1 == int16obj2 { + return 0, true + } + if int16obj1 < int16obj2 { + return 1, true + } + } + case reflect.Int32: + { + int32obj1 := obj1.(int32) + int32obj2 := obj2.(int32) + if int32obj1 > int32obj2 { + return -1, true + } + if int32obj1 == int32obj2 { + return 0, true + } + if int32obj1 < int32obj2 { + return 1, true + } + } + case reflect.Int64: + { + int64obj1 := obj1.(int64) + int64obj2 := obj2.(int64) + if int64obj1 > int64obj2 { + return -1, true + } + if int64obj1 == int64obj2 { + return 0, true + } + if int64obj1 < int64obj2 { + return 1, true + } + } + case reflect.Uint: + { + uintobj1 := obj1.(uint) + uintobj2 := obj2.(uint) + if uintobj1 > uintobj2 { + return -1, true + } + if uintobj1 == uintobj2 { + return 0, true + } + if uintobj1 < uintobj2 { + return 1, true + } + } + case reflect.Uint8: + { + uint8obj1 := obj1.(uint8) + uint8obj2 := obj2.(uint8) + if uint8obj1 > uint8obj2 { + return -1, true + } + if uint8obj1 == uint8obj2 { + return 0, true + } + if uint8obj1 < uint8obj2 { + return 1, true + } + } + case reflect.Uint16: + { + uint16obj1 := obj1.(uint16) + uint16obj2 := obj2.(uint16) + if uint16obj1 > uint16obj2 { + return -1, true + } + if uint16obj1 == uint16obj2 { + return 0, true + } + if uint16obj1 < uint16obj2 { + return 1, true + } + } + case reflect.Uint32: + { + uint32obj1 := obj1.(uint32) + uint32obj2 := obj2.(uint32) + if uint32obj1 > uint32obj2 { + return -1, true + } + if uint32obj1 == uint32obj2 { + return 0, true + } + if uint32obj1 < uint32obj2 { + return 1, true + } + } + case reflect.Uint64: + { + uint64obj1 := obj1.(uint64) + uint64obj2 := obj2.(uint64) + if uint64obj1 > uint64obj2 { + return -1, true + } + if uint64obj1 == uint64obj2 { + return 0, true + } + if uint64obj1 < uint64obj2 { + return 1, true + } + } + case reflect.Float32: + { + float32obj1 := obj1.(float32) + float32obj2 := obj2.(float32) + if float32obj1 > float32obj2 { + return -1, true + } + if float32obj1 == float32obj2 { + return 0, true + } + if float32obj1 < float32obj2 { + return 1, true + } + } + case reflect.Float64: + { + float64obj1 := obj1.(float64) + float64obj2 := obj2.(float64) + if float64obj1 > float64obj2 { + return -1, true + } + if float64obj1 == float64obj2 { + return 0, true + } + if float64obj1 < float64obj2 { + return 1, true + } + } + case reflect.String: + { + stringobj1 := obj1.(string) + stringobj2 := obj2.(string) + if stringobj1 > stringobj2 { + return -1, true + } + if stringobj1 == stringobj2 { + return 0, true + } + if stringobj1 < stringobj2 { + return 1, true + } + } + } + + return 0, false +} + +// Greater asserts that the first element is greater than the second +// +// assert.Greater(t, 2, 1) +// assert.Greater(t, float64(2), float64(1)) +// assert.Greater(t, "b", "a") +func Greater(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + e1Kind := reflect.ValueOf(e1).Kind() + e2Kind := reflect.ValueOf(e2).Kind() + if e1Kind != e2Kind { + return Fail(t, "Elements should be the same type", msgAndArgs...) + } + + res, isComparable := compare(e1, e2, e1Kind) + if !isComparable { + return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...) + } + + if res != -1 { + return Fail(t, fmt.Sprintf("\"%v\" is not greater than \"%v\"", e1, e2), msgAndArgs...) + } + + return true +} + +// GreaterOrEqual asserts that the first element is greater than or equal to the second +// +// assert.GreaterOrEqual(t, 2, 1) +// assert.GreaterOrEqual(t, 2, 2) +// assert.GreaterOrEqual(t, "b", "a") +// assert.GreaterOrEqual(t, "b", "b") +func GreaterOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + e1Kind := reflect.ValueOf(e1).Kind() + e2Kind := reflect.ValueOf(e2).Kind() + if e1Kind != e2Kind { + return Fail(t, "Elements should be the same type", msgAndArgs...) + } + + res, isComparable := compare(e1, e2, e1Kind) + if !isComparable { + return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...) + } + + if res != -1 && res != 0 { + return Fail(t, fmt.Sprintf("\"%v\" is not greater than or equal to \"%v\"", e1, e2), msgAndArgs...) + } + + return true +} + +// Less asserts that the first element is less than the second +// +// assert.Less(t, 1, 2) +// assert.Less(t, float64(1), float64(2)) +// assert.Less(t, "a", "b") +func Less(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + e1Kind := reflect.ValueOf(e1).Kind() + e2Kind := reflect.ValueOf(e2).Kind() + if e1Kind != e2Kind { + return Fail(t, "Elements should be the same type", msgAndArgs...) + } + + res, isComparable := compare(e1, e2, e1Kind) + if !isComparable { + return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...) + } + + if res != 1 { + return Fail(t, fmt.Sprintf("\"%v\" is not less than \"%v\"", e1, e2), msgAndArgs...) + } + + return true +} + +// LessOrEqual asserts that the first element is less than or equal to the second +// +// assert.LessOrEqual(t, 1, 2) +// assert.LessOrEqual(t, 2, 2) +// assert.LessOrEqual(t, "a", "b") +// assert.LessOrEqual(t, "b", "b") +func LessOrEqual(t TestingT, e1 interface{}, e2 interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + e1Kind := reflect.ValueOf(e1).Kind() + e2Kind := reflect.ValueOf(e2).Kind() + if e1Kind != e2Kind { + return Fail(t, "Elements should be the same type", msgAndArgs...) + } + + res, isComparable := compare(e1, e2, e1Kind) + if !isComparable { + return Fail(t, fmt.Sprintf("Can not compare type \"%s\"", reflect.TypeOf(e1)), msgAndArgs...) + } + + if res != 1 && res != 0 { + return Fail(t, fmt.Sprintf("\"%v\" is not less than or equal to \"%v\"", e1, e2), msgAndArgs...) + } + + return true +} diff --git a/vendor/github.com/stretchr/testify/assert/assertions.go b/vendor/github.com/stretchr/testify/assert/assertions.go new file mode 100644 index 00000000000..bdd81389a97 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/assertions.go @@ -0,0 +1,1626 @@ +package assert + +import ( + "bufio" + "bytes" + "encoding/json" + "errors" + "fmt" + "math" + "os" + "reflect" + "regexp" + "runtime" + "runtime/debug" + "strings" + "time" + "unicode" + "unicode/utf8" + + "github.com/davecgh/go-spew/spew" + "github.com/pmezard/go-difflib/difflib" + yaml "gopkg.in/yaml.v2" +) + +//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_format.go.tmpl" + +// TestingT is an interface wrapper around *testing.T +type TestingT interface { + Errorf(format string, args ...interface{}) +} + +// ComparisonAssertionFunc is a common function prototype when comparing two values. Can be useful +// for table driven tests. +type ComparisonAssertionFunc func(TestingT, interface{}, interface{}, ...interface{}) bool + +// ValueAssertionFunc is a common function prototype when validating a single value. Can be useful +// for table driven tests. +type ValueAssertionFunc func(TestingT, interface{}, ...interface{}) bool + +// BoolAssertionFunc is a common function prototype when validating a bool value. Can be useful +// for table driven tests. +type BoolAssertionFunc func(TestingT, bool, ...interface{}) bool + +// ErrorAssertionFunc is a common function prototype when validating an error value. Can be useful +// for table driven tests. +type ErrorAssertionFunc func(TestingT, error, ...interface{}) bool + +// Comparison a custom function that returns true on success and false on failure +type Comparison func() (success bool) + +/* + Helper functions +*/ + +// ObjectsAreEqual determines if two objects are considered equal. +// +// This function does no assertion of any kind. +func ObjectsAreEqual(expected, actual interface{}) bool { + if expected == nil || actual == nil { + return expected == actual + } + + exp, ok := expected.([]byte) + if !ok { + return reflect.DeepEqual(expected, actual) + } + + act, ok := actual.([]byte) + if !ok { + return false + } + if exp == nil || act == nil { + return exp == nil && act == nil + } + return bytes.Equal(exp, act) +} + +// ObjectsAreEqualValues gets whether two objects are equal, or if their +// values are equal. +func ObjectsAreEqualValues(expected, actual interface{}) bool { + if ObjectsAreEqual(expected, actual) { + return true + } + + actualType := reflect.TypeOf(actual) + if actualType == nil { + return false + } + expectedValue := reflect.ValueOf(expected) + if expectedValue.IsValid() && expectedValue.Type().ConvertibleTo(actualType) { + // Attempt comparison after type conversion + return reflect.DeepEqual(expectedValue.Convert(actualType).Interface(), actual) + } + + return false +} + +/* CallerInfo is necessary because the assert functions use the testing object +internally, causing it to print the file:line of the assert method, rather than where +the problem actually occurred in calling code.*/ + +// CallerInfo returns an array of strings containing the file and line number +// of each stack frame leading from the current test to the assert call that +// failed. +func CallerInfo() []string { + + pc := uintptr(0) + file := "" + line := 0 + ok := false + name := "" + + callers := []string{} + for i := 0; ; i++ { + pc, file, line, ok = runtime.Caller(i) + if !ok { + // The breaks below failed to terminate the loop, and we ran off the + // end of the call stack. + break + } + + // This is a huge edge case, but it will panic if this is the case, see #180 + if file == "" { + break + } + + f := runtime.FuncForPC(pc) + if f == nil { + break + } + name = f.Name() + + // testing.tRunner is the standard library function that calls + // tests. Subtests are called directly by tRunner, without going through + // the Test/Benchmark/Example function that contains the t.Run calls, so + // with subtests we should break when we hit tRunner, without adding it + // to the list of callers. + if name == "testing.tRunner" { + break + } + + parts := strings.Split(file, "/") + file = parts[len(parts)-1] + if len(parts) > 1 { + dir := parts[len(parts)-2] + if (dir != "assert" && dir != "mock" && dir != "require") || file == "mock_test.go" { + callers = append(callers, fmt.Sprintf("%s:%d", file, line)) + } + } + + // Drop the package + segments := strings.Split(name, ".") + name = segments[len(segments)-1] + if isTest(name, "Test") || + isTest(name, "Benchmark") || + isTest(name, "Example") { + break + } + } + + return callers +} + +// Stolen from the `go test` tool. +// isTest tells whether name looks like a test (or benchmark, according to prefix). +// It is a Test (say) if there is a character after Test that is not a lower-case letter. +// We don't want TesticularCancer. +func isTest(name, prefix string) bool { + if !strings.HasPrefix(name, prefix) { + return false + } + if len(name) == len(prefix) { // "Test" is ok + return true + } + rune, _ := utf8.DecodeRuneInString(name[len(prefix):]) + return !unicode.IsLower(rune) +} + +func messageFromMsgAndArgs(msgAndArgs ...interface{}) string { + if len(msgAndArgs) == 0 || msgAndArgs == nil { + return "" + } + if len(msgAndArgs) == 1 { + msg := msgAndArgs[0] + if msgAsStr, ok := msg.(string); ok { + return msgAsStr + } + return fmt.Sprintf("%+v", msg) + } + if len(msgAndArgs) > 1 { + return fmt.Sprintf(msgAndArgs[0].(string), msgAndArgs[1:]...) + } + return "" +} + +// Aligns the provided message so that all lines after the first line start at the same location as the first line. +// Assumes that the first line starts at the correct location (after carriage return, tab, label, spacer and tab). +// The longestLabelLen parameter specifies the length of the longest label in the output (required becaues this is the +// basis on which the alignment occurs). +func indentMessageLines(message string, longestLabelLen int) string { + outBuf := new(bytes.Buffer) + + for i, scanner := 0, bufio.NewScanner(strings.NewReader(message)); scanner.Scan(); i++ { + // no need to align first line because it starts at the correct location (after the label) + if i != 0 { + // append alignLen+1 spaces to align with "{{longestLabel}}:" before adding tab + outBuf.WriteString("\n\t" + strings.Repeat(" ", longestLabelLen+1) + "\t") + } + outBuf.WriteString(scanner.Text()) + } + + return outBuf.String() +} + +type failNower interface { + FailNow() +} + +// FailNow fails test +func FailNow(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + Fail(t, failureMessage, msgAndArgs...) + + // We cannot extend TestingT with FailNow() and + // maintain backwards compatibility, so we fallback + // to panicking when FailNow is not available in + // TestingT. + // See issue #263 + + if t, ok := t.(failNower); ok { + t.FailNow() + } else { + panic("test failed and t is missing `FailNow()`") + } + return false +} + +// Fail reports a failure through +func Fail(t TestingT, failureMessage string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + content := []labeledContent{ + {"Error Trace", strings.Join(CallerInfo(), "\n\t\t\t")}, + {"Error", failureMessage}, + } + + // Add test name if the Go version supports it + if n, ok := t.(interface { + Name() string + }); ok { + content = append(content, labeledContent{"Test", n.Name()}) + } + + message := messageFromMsgAndArgs(msgAndArgs...) + if len(message) > 0 { + content = append(content, labeledContent{"Messages", message}) + } + + t.Errorf("\n%s", ""+labeledOutput(content...)) + + return false +} + +type labeledContent struct { + label string + content string +} + +// labeledOutput returns a string consisting of the provided labeledContent. Each labeled output is appended in the following manner: +// +// \t{{label}}:{{align_spaces}}\t{{content}}\n +// +// The initial carriage return is required to undo/erase any padding added by testing.T.Errorf. The "\t{{label}}:" is for the label. +// If a label is shorter than the longest label provided, padding spaces are added to make all the labels match in length. Once this +// alignment is achieved, "\t{{content}}\n" is added for the output. +// +// If the content of the labeledOutput contains line breaks, the subsequent lines are aligned so that they start at the same location as the first line. +func labeledOutput(content ...labeledContent) string { + longestLabel := 0 + for _, v := range content { + if len(v.label) > longestLabel { + longestLabel = len(v.label) + } + } + var output string + for _, v := range content { + output += "\t" + v.label + ":" + strings.Repeat(" ", longestLabel-len(v.label)) + "\t" + indentMessageLines(v.content, longestLabel) + "\n" + } + return output +} + +// Implements asserts that an object is implemented by the specified interface. +// +// assert.Implements(t, (*MyInterface)(nil), new(MyObject)) +func Implements(t TestingT, interfaceObject interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + interfaceType := reflect.TypeOf(interfaceObject).Elem() + + if object == nil { + return Fail(t, fmt.Sprintf("Cannot check if nil implements %v", interfaceType), msgAndArgs...) + } + if !reflect.TypeOf(object).Implements(interfaceType) { + return Fail(t, fmt.Sprintf("%T must implement %v", object, interfaceType), msgAndArgs...) + } + + return true +} + +// IsType asserts that the specified objects are of the same type. +func IsType(t TestingT, expectedType interface{}, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if !ObjectsAreEqual(reflect.TypeOf(object), reflect.TypeOf(expectedType)) { + return Fail(t, fmt.Sprintf("Object expected to be of type %v, but was %v", reflect.TypeOf(expectedType), reflect.TypeOf(object)), msgAndArgs...) + } + + return true +} + +// Equal asserts that two objects are equal. +// +// assert.Equal(t, 123, 123) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). Function equality +// cannot be determined and will always fail. +func Equal(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if err := validateEqualArgs(expected, actual); err != nil { + return Fail(t, fmt.Sprintf("Invalid operation: %#v == %#v (%s)", + expected, actual, err), msgAndArgs...) + } + + if !ObjectsAreEqual(expected, actual) { + diff := diff(expected, actual) + expected, actual = formatUnequalValues(expected, actual) + return Fail(t, fmt.Sprintf("Not equal: \n"+ + "expected: %s\n"+ + "actual : %s%s", expected, actual, diff), msgAndArgs...) + } + + return true + +} + +// validateEqualArgs checks whether provided arguments can be safely used in the +// Equal/NotEqual functions. +func validateEqualArgs(expected, actual interface{}) error { + if expected == nil && actual == nil { + return nil + } + + if isFunction(expected) || isFunction(actual) { + return errors.New("cannot take func type as argument") + } + return nil +} + +// Same asserts that two pointers reference the same object. +// +// assert.Same(t, ptr1, ptr2) +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func Same(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if !samePointers(expected, actual) { + return Fail(t, fmt.Sprintf("Not same: \n"+ + "expected: %p %#v\n"+ + "actual : %p %#v", expected, expected, actual, actual), msgAndArgs...) + } + + return true +} + +// NotSame asserts that two pointers do not reference the same object. +// +// assert.NotSame(t, ptr1, ptr2) +// +// Both arguments must be pointer variables. Pointer variable sameness is +// determined based on the equality of both type and value. +func NotSame(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if samePointers(expected, actual) { + return Fail(t, fmt.Sprintf( + "Expected and actual point to the same object: %p %#v", + expected, expected), msgAndArgs...) + } + return true +} + +// samePointers compares two generic interface objects and returns whether +// they point to the same object +func samePointers(first, second interface{}) bool { + firstPtr, secondPtr := reflect.ValueOf(first), reflect.ValueOf(second) + if firstPtr.Kind() != reflect.Ptr || secondPtr.Kind() != reflect.Ptr { + return false + } + + firstType, secondType := reflect.TypeOf(first), reflect.TypeOf(second) + if firstType != secondType { + return false + } + + // compare pointer addresses + return first == second +} + +// formatUnequalValues takes two values of arbitrary types and returns string +// representations appropriate to be presented to the user. +// +// If the values are not of like type, the returned strings will be prefixed +// with the type name, and the value will be enclosed in parenthesis similar +// to a type conversion in the Go grammar. +func formatUnequalValues(expected, actual interface{}) (e string, a string) { + if reflect.TypeOf(expected) != reflect.TypeOf(actual) { + return fmt.Sprintf("%T(%#v)", expected, expected), + fmt.Sprintf("%T(%#v)", actual, actual) + } + switch expected.(type) { + case time.Duration: + return fmt.Sprintf("%v", expected), fmt.Sprintf("%v", actual) + } + return fmt.Sprintf("%#v", expected), fmt.Sprintf("%#v", actual) +} + +// EqualValues asserts that two objects are equal or convertable to the same types +// and equal. +// +// assert.EqualValues(t, uint32(123), int32(123)) +func EqualValues(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if !ObjectsAreEqualValues(expected, actual) { + diff := diff(expected, actual) + expected, actual = formatUnequalValues(expected, actual) + return Fail(t, fmt.Sprintf("Not equal: \n"+ + "expected: %s\n"+ + "actual : %s%s", expected, actual, diff), msgAndArgs...) + } + + return true + +} + +// Exactly asserts that two objects are equal in value and type. +// +// assert.Exactly(t, int32(123), int64(123)) +func Exactly(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + aType := reflect.TypeOf(expected) + bType := reflect.TypeOf(actual) + + if aType != bType { + return Fail(t, fmt.Sprintf("Types expected to match exactly\n\t%v != %v", aType, bType), msgAndArgs...) + } + + return Equal(t, expected, actual, msgAndArgs...) + +} + +// NotNil asserts that the specified object is not nil. +// +// assert.NotNil(t, err) +func NotNil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if !isNil(object) { + return true + } + return Fail(t, "Expected value not to be nil.", msgAndArgs...) +} + +// containsKind checks if a specified kind in the slice of kinds. +func containsKind(kinds []reflect.Kind, kind reflect.Kind) bool { + for i := 0; i < len(kinds); i++ { + if kind == kinds[i] { + return true + } + } + + return false +} + +// isNil checks if a specified object is nil or not, without Failing. +func isNil(object interface{}) bool { + if object == nil { + return true + } + + value := reflect.ValueOf(object) + kind := value.Kind() + isNilableKind := containsKind( + []reflect.Kind{ + reflect.Chan, reflect.Func, + reflect.Interface, reflect.Map, + reflect.Ptr, reflect.Slice}, + kind) + + if isNilableKind && value.IsNil() { + return true + } + + return false +} + +// Nil asserts that the specified object is nil. +// +// assert.Nil(t, err) +func Nil(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if isNil(object) { + return true + } + return Fail(t, fmt.Sprintf("Expected nil, but got: %#v", object), msgAndArgs...) +} + +// isEmpty gets whether the specified object is considered empty or not. +func isEmpty(object interface{}) bool { + + // get nil case out of the way + if object == nil { + return true + } + + objValue := reflect.ValueOf(object) + + switch objValue.Kind() { + // collection types are empty when they have no element + case reflect.Array, reflect.Chan, reflect.Map, reflect.Slice: + return objValue.Len() == 0 + // pointers are empty if nil or if the value they point to is empty + case reflect.Ptr: + if objValue.IsNil() { + return true + } + deref := objValue.Elem().Interface() + return isEmpty(deref) + // for all other types, compare against the zero value + default: + zero := reflect.Zero(objValue.Type()) + return reflect.DeepEqual(object, zero.Interface()) + } +} + +// Empty asserts that the specified object is empty. I.e. nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// assert.Empty(t, obj) +func Empty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + pass := isEmpty(object) + if !pass { + Fail(t, fmt.Sprintf("Should be empty, but was %v", object), msgAndArgs...) + } + + return pass + +} + +// NotEmpty asserts that the specified object is NOT empty. I.e. not nil, "", false, 0 or either +// a slice or a channel with len == 0. +// +// if assert.NotEmpty(t, obj) { +// assert.Equal(t, "two", obj[1]) +// } +func NotEmpty(t TestingT, object interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + pass := !isEmpty(object) + if !pass { + Fail(t, fmt.Sprintf("Should NOT be empty, but was %v", object), msgAndArgs...) + } + + return pass + +} + +// getLen try to get length of object. +// return (false, 0) if impossible. +func getLen(x interface{}) (ok bool, length int) { + v := reflect.ValueOf(x) + defer func() { + if e := recover(); e != nil { + ok = false + } + }() + return true, v.Len() +} + +// Len asserts that the specified object has specific length. +// Len also fails if the object has a type that len() not accept. +// +// assert.Len(t, mySlice, 3) +func Len(t TestingT, object interface{}, length int, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + ok, l := getLen(object) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", object), msgAndArgs...) + } + + if l != length { + return Fail(t, fmt.Sprintf("\"%s\" should have %d item(s), but has %d", object, length, l), msgAndArgs...) + } + return true +} + +// True asserts that the specified value is true. +// +// assert.True(t, myBool) +func True(t TestingT, value bool, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if h, ok := t.(interface { + Helper() + }); ok { + h.Helper() + } + + if value != true { + return Fail(t, "Should be true", msgAndArgs...) + } + + return true + +} + +// False asserts that the specified value is false. +// +// assert.False(t, myBool) +func False(t TestingT, value bool, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if value != false { + return Fail(t, "Should be false", msgAndArgs...) + } + + return true + +} + +// NotEqual asserts that the specified values are NOT equal. +// +// assert.NotEqual(t, obj1, obj2) +// +// Pointer variable equality is determined based on the equality of the +// referenced values (as opposed to the memory addresses). +func NotEqual(t TestingT, expected, actual interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if err := validateEqualArgs(expected, actual); err != nil { + return Fail(t, fmt.Sprintf("Invalid operation: %#v != %#v (%s)", + expected, actual, err), msgAndArgs...) + } + + if ObjectsAreEqual(expected, actual) { + return Fail(t, fmt.Sprintf("Should not be: %#v\n", actual), msgAndArgs...) + } + + return true + +} + +// containsElement try loop over the list check if the list includes the element. +// return (false, false) if impossible. +// return (true, false) if element was not found. +// return (true, true) if element was found. +func includeElement(list interface{}, element interface{}) (ok, found bool) { + + listValue := reflect.ValueOf(list) + listKind := reflect.TypeOf(list).Kind() + defer func() { + if e := recover(); e != nil { + ok = false + found = false + } + }() + + if listKind == reflect.String { + elementValue := reflect.ValueOf(element) + return true, strings.Contains(listValue.String(), elementValue.String()) + } + + if listKind == reflect.Map { + mapKeys := listValue.MapKeys() + for i := 0; i < len(mapKeys); i++ { + if ObjectsAreEqual(mapKeys[i].Interface(), element) { + return true, true + } + } + return true, false + } + + for i := 0; i < listValue.Len(); i++ { + if ObjectsAreEqual(listValue.Index(i).Interface(), element) { + return true, true + } + } + return true, false + +} + +// Contains asserts that the specified string, list(array, slice...) or map contains the +// specified substring or element. +// +// assert.Contains(t, "Hello World", "World") +// assert.Contains(t, ["Hello", "World"], "World") +// assert.Contains(t, {"Hello": "World"}, "Hello") +func Contains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + ok, found := includeElement(s, contains) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) + } + if !found { + return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", s, contains), msgAndArgs...) + } + + return true + +} + +// NotContains asserts that the specified string, list(array, slice...) or map does NOT contain the +// specified substring or element. +// +// assert.NotContains(t, "Hello World", "Earth") +// assert.NotContains(t, ["Hello", "World"], "Earth") +// assert.NotContains(t, {"Hello": "World"}, "Earth") +func NotContains(t TestingT, s, contains interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + ok, found := includeElement(s, contains) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", s), msgAndArgs...) + } + if found { + return Fail(t, fmt.Sprintf("\"%s\" should not contain \"%s\"", s, contains), msgAndArgs...) + } + + return true + +} + +// Subset asserts that the specified list(array, slice...) contains all +// elements given in the specified subset(array, slice...). +// +// assert.Subset(t, [1, 2, 3], [1, 2], "But [1, 2, 3] does contain [1, 2]") +func Subset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if subset == nil { + return true // we consider nil to be equal to the nil set + } + + subsetValue := reflect.ValueOf(subset) + defer func() { + if e := recover(); e != nil { + ok = false + } + }() + + listKind := reflect.TypeOf(list).Kind() + subsetKind := reflect.TypeOf(subset).Kind() + + if listKind != reflect.Array && listKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) + } + + if subsetKind != reflect.Array && subsetKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) + } + + for i := 0; i < subsetValue.Len(); i++ { + element := subsetValue.Index(i).Interface() + ok, found := includeElement(list, element) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) + } + if !found { + return Fail(t, fmt.Sprintf("\"%s\" does not contain \"%s\"", list, element), msgAndArgs...) + } + } + + return true +} + +// NotSubset asserts that the specified list(array, slice...) contains not all +// elements given in the specified subset(array, slice...). +// +// assert.NotSubset(t, [1, 3, 4], [1, 2], "But [1, 3, 4] does not contain [1, 2]") +func NotSubset(t TestingT, list, subset interface{}, msgAndArgs ...interface{}) (ok bool) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if subset == nil { + return Fail(t, fmt.Sprintf("nil is the empty set which is a subset of every set"), msgAndArgs...) + } + + subsetValue := reflect.ValueOf(subset) + defer func() { + if e := recover(); e != nil { + ok = false + } + }() + + listKind := reflect.TypeOf(list).Kind() + subsetKind := reflect.TypeOf(subset).Kind() + + if listKind != reflect.Array && listKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", list, listKind), msgAndArgs...) + } + + if subsetKind != reflect.Array && subsetKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", subset, subsetKind), msgAndArgs...) + } + + for i := 0; i < subsetValue.Len(); i++ { + element := subsetValue.Index(i).Interface() + ok, found := includeElement(list, element) + if !ok { + return Fail(t, fmt.Sprintf("\"%s\" could not be applied builtin len()", list), msgAndArgs...) + } + if !found { + return true + } + } + + return Fail(t, fmt.Sprintf("%q is a subset of %q", subset, list), msgAndArgs...) +} + +// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified +// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements, +// the number of appearances of each of them in both lists should match. +// +// assert.ElementsMatch(t, [1, 3, 2, 3], [1, 3, 3, 2]) +func ElementsMatch(t TestingT, listA, listB interface{}, msgAndArgs ...interface{}) (ok bool) { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if isEmpty(listA) && isEmpty(listB) { + return true + } + + aKind := reflect.TypeOf(listA).Kind() + bKind := reflect.TypeOf(listB).Kind() + + if aKind != reflect.Array && aKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listA, aKind), msgAndArgs...) + } + + if bKind != reflect.Array && bKind != reflect.Slice { + return Fail(t, fmt.Sprintf("%q has an unsupported type %s", listB, bKind), msgAndArgs...) + } + + aValue := reflect.ValueOf(listA) + bValue := reflect.ValueOf(listB) + + aLen := aValue.Len() + bLen := bValue.Len() + + if aLen != bLen { + return Fail(t, fmt.Sprintf("lengths don't match: %d != %d", aLen, bLen), msgAndArgs...) + } + + // Mark indexes in bValue that we already used + visited := make([]bool, bLen) + for i := 0; i < aLen; i++ { + element := aValue.Index(i).Interface() + found := false + for j := 0; j < bLen; j++ { + if visited[j] { + continue + } + if ObjectsAreEqual(bValue.Index(j).Interface(), element) { + visited[j] = true + found = true + break + } + } + if !found { + return Fail(t, fmt.Sprintf("element %s appears more times in %s than in %s", element, aValue, bValue), msgAndArgs...) + } + } + + return true +} + +// Condition uses a Comparison to assert a complex condition. +func Condition(t TestingT, comp Comparison, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + result := comp() + if !result { + Fail(t, "Condition failed!", msgAndArgs...) + } + return result +} + +// PanicTestFunc defines a func that should be passed to the assert.Panics and assert.NotPanics +// methods, and represents a simple func that takes no arguments, and returns nothing. +type PanicTestFunc func() + +// didPanic returns true if the function passed to it panics. Otherwise, it returns false. +func didPanic(f PanicTestFunc) (bool, interface{}, string) { + + didPanic := false + var message interface{} + var stack string + func() { + + defer func() { + if message = recover(); message != nil { + didPanic = true + stack = string(debug.Stack()) + } + }() + + // call the target function + f() + + }() + + return didPanic, message, stack + +} + +// Panics asserts that the code inside the specified PanicTestFunc panics. +// +// assert.Panics(t, func(){ GoCrazy() }) +func Panics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if funcDidPanic, panicValue, _ := didPanic(f); !funcDidPanic { + return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) + } + + return true +} + +// PanicsWithValue asserts that the code inside the specified PanicTestFunc panics, and that +// the recovered panic value equals the expected panic value. +// +// assert.PanicsWithValue(t, "crazy error", func(){ GoCrazy() }) +func PanicsWithValue(t TestingT, expected interface{}, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + funcDidPanic, panicValue, panickedStack := didPanic(f) + if !funcDidPanic { + return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) + } + if panicValue != expected { + return Fail(t, fmt.Sprintf("func %#v should panic with value:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, expected, panicValue, panickedStack), msgAndArgs...) + } + + return true +} + +// PanicsWithError asserts that the code inside the specified PanicTestFunc +// panics, and that the recovered panic value is an error that satisfies the +// EqualError comparison. +// +// assert.PanicsWithError(t, "crazy error", func(){ GoCrazy() }) +func PanicsWithError(t TestingT, errString string, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + funcDidPanic, panicValue, panickedStack := didPanic(f) + if !funcDidPanic { + return Fail(t, fmt.Sprintf("func %#v should panic\n\tPanic value:\t%#v", f, panicValue), msgAndArgs...) + } + panicErr, ok := panicValue.(error) + if !ok || panicErr.Error() != errString { + return Fail(t, fmt.Sprintf("func %#v should panic with error message:\t%#v\n\tPanic value:\t%#v\n\tPanic stack:\t%s", f, errString, panicValue, panickedStack), msgAndArgs...) + } + + return true +} + +// NotPanics asserts that the code inside the specified PanicTestFunc does NOT panic. +// +// assert.NotPanics(t, func(){ RemainCalm() }) +func NotPanics(t TestingT, f PanicTestFunc, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if funcDidPanic, panicValue, panickedStack := didPanic(f); funcDidPanic { + return Fail(t, fmt.Sprintf("func %#v should not panic\n\tPanic value:\t%v\n\tPanic stack:\t%s", f, panicValue, panickedStack), msgAndArgs...) + } + + return true +} + +// WithinDuration asserts that the two times are within duration delta of each other. +// +// assert.WithinDuration(t, time.Now(), time.Now(), 10*time.Second) +func WithinDuration(t TestingT, expected, actual time.Time, delta time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + dt := expected.Sub(actual) + if dt < -delta || dt > delta { + return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) + } + + return true +} + +func toFloat(x interface{}) (float64, bool) { + var xf float64 + xok := true + + switch xn := x.(type) { + case uint8: + xf = float64(xn) + case uint16: + xf = float64(xn) + case uint32: + xf = float64(xn) + case uint64: + xf = float64(xn) + case int: + xf = float64(xn) + case int8: + xf = float64(xn) + case int16: + xf = float64(xn) + case int32: + xf = float64(xn) + case int64: + xf = float64(xn) + case float32: + xf = float64(xn) + case float64: + xf = float64(xn) + case time.Duration: + xf = float64(xn) + default: + xok = false + } + + return xf, xok +} + +// InDelta asserts that the two numerals are within delta of each other. +// +// assert.InDelta(t, math.Pi, 22/7.0, 0.01) +func InDelta(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + af, aok := toFloat(expected) + bf, bok := toFloat(actual) + + if !aok || !bok { + return Fail(t, fmt.Sprintf("Parameters must be numerical"), msgAndArgs...) + } + + if math.IsNaN(af) { + return Fail(t, fmt.Sprintf("Expected must not be NaN"), msgAndArgs...) + } + + if math.IsNaN(bf) { + return Fail(t, fmt.Sprintf("Expected %v with delta %v, but was NaN", expected, delta), msgAndArgs...) + } + + dt := af - bf + if dt < -delta || dt > delta { + return Fail(t, fmt.Sprintf("Max difference between %v and %v allowed is %v, but difference was %v", expected, actual, delta, dt), msgAndArgs...) + } + + return true +} + +// InDeltaSlice is the same as InDelta, except it compares two slices. +func InDeltaSlice(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if expected == nil || actual == nil || + reflect.TypeOf(actual).Kind() != reflect.Slice || + reflect.TypeOf(expected).Kind() != reflect.Slice { + return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) + } + + actualSlice := reflect.ValueOf(actual) + expectedSlice := reflect.ValueOf(expected) + + for i := 0; i < actualSlice.Len(); i++ { + result := InDelta(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), delta, msgAndArgs...) + if !result { + return result + } + } + + return true +} + +// InDeltaMapValues is the same as InDelta, but it compares all values between two maps. Both maps must have exactly the same keys. +func InDeltaMapValues(t TestingT, expected, actual interface{}, delta float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if expected == nil || actual == nil || + reflect.TypeOf(actual).Kind() != reflect.Map || + reflect.TypeOf(expected).Kind() != reflect.Map { + return Fail(t, "Arguments must be maps", msgAndArgs...) + } + + expectedMap := reflect.ValueOf(expected) + actualMap := reflect.ValueOf(actual) + + if expectedMap.Len() != actualMap.Len() { + return Fail(t, "Arguments must have the same number of keys", msgAndArgs...) + } + + for _, k := range expectedMap.MapKeys() { + ev := expectedMap.MapIndex(k) + av := actualMap.MapIndex(k) + + if !ev.IsValid() { + return Fail(t, fmt.Sprintf("missing key %q in expected map", k), msgAndArgs...) + } + + if !av.IsValid() { + return Fail(t, fmt.Sprintf("missing key %q in actual map", k), msgAndArgs...) + } + + if !InDelta( + t, + ev.Interface(), + av.Interface(), + delta, + msgAndArgs..., + ) { + return false + } + } + + return true +} + +func calcRelativeError(expected, actual interface{}) (float64, error) { + af, aok := toFloat(expected) + if !aok { + return 0, fmt.Errorf("expected value %q cannot be converted to float", expected) + } + if af == 0 { + return 0, fmt.Errorf("expected value must have a value other than zero to calculate the relative error") + } + bf, bok := toFloat(actual) + if !bok { + return 0, fmt.Errorf("actual value %q cannot be converted to float", actual) + } + + return math.Abs(af-bf) / math.Abs(af), nil +} + +// InEpsilon asserts that expected and actual have a relative error less than epsilon +func InEpsilon(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + actualEpsilon, err := calcRelativeError(expected, actual) + if err != nil { + return Fail(t, err.Error(), msgAndArgs...) + } + if actualEpsilon > epsilon { + return Fail(t, fmt.Sprintf("Relative error is too high: %#v (expected)\n"+ + " < %#v (actual)", epsilon, actualEpsilon), msgAndArgs...) + } + + return true +} + +// InEpsilonSlice is the same as InEpsilon, except it compares each value from two slices. +func InEpsilonSlice(t TestingT, expected, actual interface{}, epsilon float64, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if expected == nil || actual == nil || + reflect.TypeOf(actual).Kind() != reflect.Slice || + reflect.TypeOf(expected).Kind() != reflect.Slice { + return Fail(t, fmt.Sprintf("Parameters must be slice"), msgAndArgs...) + } + + actualSlice := reflect.ValueOf(actual) + expectedSlice := reflect.ValueOf(expected) + + for i := 0; i < actualSlice.Len(); i++ { + result := InEpsilon(t, actualSlice.Index(i).Interface(), expectedSlice.Index(i).Interface(), epsilon) + if !result { + return result + } + } + + return true +} + +/* + Errors +*/ + +// NoError asserts that a function returned no error (i.e. `nil`). +// +// actualObj, err := SomeFunction() +// if assert.NoError(t, err) { +// assert.Equal(t, expectedObj, actualObj) +// } +func NoError(t TestingT, err error, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if err != nil { + return Fail(t, fmt.Sprintf("Received unexpected error:\n%+v", err), msgAndArgs...) + } + + return true +} + +// Error asserts that a function returned an error (i.e. not `nil`). +// +// actualObj, err := SomeFunction() +// if assert.Error(t, err) { +// assert.Equal(t, expectedError, err) +// } +func Error(t TestingT, err error, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + if err == nil { + return Fail(t, "An error is expected but got nil.", msgAndArgs...) + } + + return true +} + +// EqualError asserts that a function returned an error (i.e. not `nil`) +// and that it is equal to the provided error. +// +// actualObj, err := SomeFunction() +// assert.EqualError(t, err, expectedErrorString) +func EqualError(t TestingT, theError error, errString string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if !Error(t, theError, msgAndArgs...) { + return false + } + expected := errString + actual := theError.Error() + // don't need to use deep equals here, we know they are both strings + if expected != actual { + return Fail(t, fmt.Sprintf("Error message not equal:\n"+ + "expected: %q\n"+ + "actual : %q", expected, actual), msgAndArgs...) + } + return true +} + +// matchRegexp return true if a specified regexp matches a string. +func matchRegexp(rx interface{}, str interface{}) bool { + + var r *regexp.Regexp + if rr, ok := rx.(*regexp.Regexp); ok { + r = rr + } else { + r = regexp.MustCompile(fmt.Sprint(rx)) + } + + return (r.FindStringIndex(fmt.Sprint(str)) != nil) + +} + +// Regexp asserts that a specified regexp matches a string. +// +// assert.Regexp(t, regexp.MustCompile("start"), "it's starting") +// assert.Regexp(t, "start...$", "it's not starting") +func Regexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + match := matchRegexp(rx, str) + + if !match { + Fail(t, fmt.Sprintf("Expect \"%v\" to match \"%v\"", str, rx), msgAndArgs...) + } + + return match +} + +// NotRegexp asserts that a specified regexp does not match a string. +// +// assert.NotRegexp(t, regexp.MustCompile("starts"), "it's starting") +// assert.NotRegexp(t, "^start", "it's not starting") +func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + match := matchRegexp(rx, str) + + if match { + Fail(t, fmt.Sprintf("Expect \"%v\" to NOT match \"%v\"", str, rx), msgAndArgs...) + } + + return !match + +} + +// Zero asserts that i is the zero value for its type. +func Zero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if i != nil && !reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { + return Fail(t, fmt.Sprintf("Should be zero, but was %v", i), msgAndArgs...) + } + return true +} + +// NotZero asserts that i is not the zero value for its type. +func NotZero(t TestingT, i interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + if i == nil || reflect.DeepEqual(i, reflect.Zero(reflect.TypeOf(i)).Interface()) { + return Fail(t, fmt.Sprintf("Should not be zero, but was %v", i), msgAndArgs...) + } + return true +} + +// FileExists checks whether a file exists in the given path. It also fails if +// the path points to a directory or there is an error when trying to check the file. +func FileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + info, err := os.Lstat(path) + if err != nil { + if os.IsNotExist(err) { + return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) + } + return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) + } + if info.IsDir() { + return Fail(t, fmt.Sprintf("%q is a directory", path), msgAndArgs...) + } + return true +} + +// NoFileExists checks whether a file does not exist in a given path. It fails +// if the path points to an existing _file_ only. +func NoFileExists(t TestingT, path string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + info, err := os.Lstat(path) + if err != nil { + return true + } + if info.IsDir() { + return true + } + return Fail(t, fmt.Sprintf("file %q exists", path), msgAndArgs...) +} + +// DirExists checks whether a directory exists in the given path. It also fails +// if the path is a file rather a directory or there is an error checking whether it exists. +func DirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + info, err := os.Lstat(path) + if err != nil { + if os.IsNotExist(err) { + return Fail(t, fmt.Sprintf("unable to find file %q", path), msgAndArgs...) + } + return Fail(t, fmt.Sprintf("error when running os.Lstat(%q): %s", path, err), msgAndArgs...) + } + if !info.IsDir() { + return Fail(t, fmt.Sprintf("%q is a file", path), msgAndArgs...) + } + return true +} + +// NoDirExists checks whether a directory does not exist in the given path. +// It fails if the path points to an existing _directory_ only. +func NoDirExists(t TestingT, path string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + info, err := os.Lstat(path) + if err != nil { + if os.IsNotExist(err) { + return true + } + return true + } + if !info.IsDir() { + return true + } + return Fail(t, fmt.Sprintf("directory %q exists", path), msgAndArgs...) +} + +// JSONEq asserts that two JSON strings are equivalent. +// +// assert.JSONEq(t, `{"hello": "world", "foo": "bar"}`, `{"foo": "bar", "hello": "world"}`) +func JSONEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + var expectedJSONAsInterface, actualJSONAsInterface interface{} + + if err := json.Unmarshal([]byte(expected), &expectedJSONAsInterface); err != nil { + return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid json.\nJSON parsing error: '%s'", expected, err.Error()), msgAndArgs...) + } + + if err := json.Unmarshal([]byte(actual), &actualJSONAsInterface); err != nil { + return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid json.\nJSON parsing error: '%s'", actual, err.Error()), msgAndArgs...) + } + + return Equal(t, expectedJSONAsInterface, actualJSONAsInterface, msgAndArgs...) +} + +// YAMLEq asserts that two YAML strings are equivalent. +func YAMLEq(t TestingT, expected string, actual string, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + var expectedYAMLAsInterface, actualYAMLAsInterface interface{} + + if err := yaml.Unmarshal([]byte(expected), &expectedYAMLAsInterface); err != nil { + return Fail(t, fmt.Sprintf("Expected value ('%s') is not valid yaml.\nYAML parsing error: '%s'", expected, err.Error()), msgAndArgs...) + } + + if err := yaml.Unmarshal([]byte(actual), &actualYAMLAsInterface); err != nil { + return Fail(t, fmt.Sprintf("Input ('%s') needs to be valid yaml.\nYAML error: '%s'", actual, err.Error()), msgAndArgs...) + } + + return Equal(t, expectedYAMLAsInterface, actualYAMLAsInterface, msgAndArgs...) +} + +func typeAndKind(v interface{}) (reflect.Type, reflect.Kind) { + t := reflect.TypeOf(v) + k := t.Kind() + + if k == reflect.Ptr { + t = t.Elem() + k = t.Kind() + } + return t, k +} + +// diff returns a diff of both values as long as both are of the same type and +// are a struct, map, slice, array or string. Otherwise it returns an empty string. +func diff(expected interface{}, actual interface{}) string { + if expected == nil || actual == nil { + return "" + } + + et, ek := typeAndKind(expected) + at, _ := typeAndKind(actual) + + if et != at { + return "" + } + + if ek != reflect.Struct && ek != reflect.Map && ek != reflect.Slice && ek != reflect.Array && ek != reflect.String { + return "" + } + + var e, a string + if et != reflect.TypeOf("") { + e = spewConfig.Sdump(expected) + a = spewConfig.Sdump(actual) + } else { + e = reflect.ValueOf(expected).String() + a = reflect.ValueOf(actual).String() + } + + diff, _ := difflib.GetUnifiedDiffString(difflib.UnifiedDiff{ + A: difflib.SplitLines(e), + B: difflib.SplitLines(a), + FromFile: "Expected", + FromDate: "", + ToFile: "Actual", + ToDate: "", + Context: 1, + }) + + return "\n\nDiff:\n" + diff +} + +func isFunction(arg interface{}) bool { + if arg == nil { + return false + } + return reflect.TypeOf(arg).Kind() == reflect.Func +} + +var spewConfig = spew.ConfigState{ + Indent: " ", + DisablePointerAddresses: true, + DisableCapacities: true, + SortKeys: true, +} + +type tHelper interface { + Helper() +} + +// Eventually asserts that given condition will be met in waitFor time, +// periodically checking target function each tick. +// +// assert.Eventually(t, func() bool { return true; }, time.Second, 10*time.Millisecond) +func Eventually(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + ch := make(chan bool, 1) + + timer := time.NewTimer(waitFor) + defer timer.Stop() + + ticker := time.NewTicker(tick) + defer ticker.Stop() + + for tick := ticker.C; ; { + select { + case <-timer.C: + return Fail(t, "Condition never satisfied", msgAndArgs...) + case <-tick: + tick = nil + go func() { ch <- condition() }() + case v := <-ch: + if v { + return true + } + tick = ticker.C + } + } +} + +// Never asserts that the given condition doesn't satisfy in waitFor time, +// periodically checking the target function each tick. +// +// assert.Never(t, func() bool { return false; }, time.Second, 10*time.Millisecond) +func Never(t TestingT, condition func() bool, waitFor time.Duration, tick time.Duration, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + + ch := make(chan bool, 1) + + timer := time.NewTimer(waitFor) + defer timer.Stop() + + ticker := time.NewTicker(tick) + defer ticker.Stop() + + for tick := ticker.C; ; { + select { + case <-timer.C: + return true + case <-tick: + tick = nil + go func() { ch <- condition() }() + case v := <-ch: + if v { + return Fail(t, "Condition satisfied", msgAndArgs...) + } + tick = ticker.C + } + } +} diff --git a/vendor/github.com/stretchr/testify/assert/doc.go b/vendor/github.com/stretchr/testify/assert/doc.go new file mode 100644 index 00000000000..c9dccc4d6cd --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/doc.go @@ -0,0 +1,45 @@ +// Package assert provides a set of comprehensive testing tools for use with the normal Go testing system. +// +// Example Usage +// +// The following is a complete example using assert in a standard test function: +// import ( +// "testing" +// "github.com/stretchr/testify/assert" +// ) +// +// func TestSomething(t *testing.T) { +// +// var a string = "Hello" +// var b string = "Hello" +// +// assert.Equal(t, a, b, "The two words should be the same.") +// +// } +// +// if you assert many times, use the format below: +// +// import ( +// "testing" +// "github.com/stretchr/testify/assert" +// ) +// +// func TestSomething(t *testing.T) { +// assert := assert.New(t) +// +// var a string = "Hello" +// var b string = "Hello" +// +// assert.Equal(a, b, "The two words should be the same.") +// } +// +// Assertions +// +// Assertions allow you to easily write test code, and are global funcs in the `assert` package. +// All assertion functions take, as the first argument, the `*testing.T` object provided by the +// testing framework. This allows the assertion funcs to write the failings and other details to +// the correct place. +// +// Every assertion function also takes an optional string message as the final argument, +// allowing custom error messages to be appended to the message the assertion method outputs. +package assert diff --git a/vendor/github.com/stretchr/testify/assert/errors.go b/vendor/github.com/stretchr/testify/assert/errors.go new file mode 100644 index 00000000000..ac9dc9d1d61 --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/errors.go @@ -0,0 +1,10 @@ +package assert + +import ( + "errors" +) + +// AnError is an error instance useful for testing. If the code does not care +// about error specifics, and only needs to return the error for example, this +// error should be used to make the test code more readable. +var AnError = errors.New("assert.AnError general error for testing") diff --git a/vendor/github.com/stretchr/testify/assert/forward_assertions.go b/vendor/github.com/stretchr/testify/assert/forward_assertions.go new file mode 100644 index 00000000000..df189d2348f --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/forward_assertions.go @@ -0,0 +1,16 @@ +package assert + +// Assertions provides assertion methods around the +// TestingT interface. +type Assertions struct { + t TestingT +} + +// New makes a new Assertions object for the specified TestingT. +func New(t TestingT) *Assertions { + return &Assertions{ + t: t, + } +} + +//go:generate sh -c "cd ../_codegen && go build && cd - && ../_codegen/_codegen -output-package=assert -template=assertion_forward.go.tmpl -include-format-funcs" diff --git a/vendor/github.com/stretchr/testify/assert/http_assertions.go b/vendor/github.com/stretchr/testify/assert/http_assertions.go new file mode 100644 index 00000000000..df46fa777ac --- /dev/null +++ b/vendor/github.com/stretchr/testify/assert/http_assertions.go @@ -0,0 +1,143 @@ +package assert + +import ( + "fmt" + "net/http" + "net/http/httptest" + "net/url" + "strings" +) + +// httpCode is a helper that returns HTTP code of the response. It returns -1 and +// an error if building a new request fails. +func httpCode(handler http.HandlerFunc, method, url string, values url.Values) (int, error) { + w := httptest.NewRecorder() + req, err := http.NewRequest(method, url, nil) + if err != nil { + return -1, err + } + req.URL.RawQuery = values.Encode() + handler(w, req) + return w.Code, nil +} + +// HTTPSuccess asserts that a specified handler returns a success status code. +// +// assert.HTTPSuccess(t, myHandler, "POST", "http://www.google.com", nil) +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPSuccess(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + code, err := httpCode(handler, method, url, values) + if err != nil { + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + return false + } + + isSuccessCode := code >= http.StatusOK && code <= http.StatusPartialContent + if !isSuccessCode { + Fail(t, fmt.Sprintf("Expected HTTP success status code for %q but received %d", url+"?"+values.Encode(), code)) + } + + return isSuccessCode +} + +// HTTPRedirect asserts that a specified handler returns a redirect status code. +// +// assert.HTTPRedirect(t, myHandler, "GET", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPRedirect(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + code, err := httpCode(handler, method, url, values) + if err != nil { + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + return false + } + + isRedirectCode := code >= http.StatusMultipleChoices && code <= http.StatusTemporaryRedirect + if !isRedirectCode { + Fail(t, fmt.Sprintf("Expected HTTP redirect status code for %q but received %d", url+"?"+values.Encode(), code)) + } + + return isRedirectCode +} + +// HTTPError asserts that a specified handler returns an error status code. +// +// assert.HTTPError(t, myHandler, "POST", "/a/b/c", url.Values{"a": []string{"b", "c"}} +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPError(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + code, err := httpCode(handler, method, url, values) + if err != nil { + Fail(t, fmt.Sprintf("Failed to build test request, got error: %s", err)) + return false + } + + isErrorCode := code >= http.StatusBadRequest + if !isErrorCode { + Fail(t, fmt.Sprintf("Expected HTTP error status code for %q but received %d", url+"?"+values.Encode(), code)) + } + + return isErrorCode +} + +// HTTPBody is a helper that returns HTTP body of the response. It returns +// empty string if building a new request fails. +func HTTPBody(handler http.HandlerFunc, method, url string, values url.Values) string { + w := httptest.NewRecorder() + req, err := http.NewRequest(method, url+"?"+values.Encode(), nil) + if err != nil { + return "" + } + handler(w, req) + return w.Body.String() +} + +// HTTPBodyContains asserts that a specified handler returns a +// body that contains a string. +// +// assert.HTTPBodyContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + body := HTTPBody(handler, method, url, values) + + contains := strings.Contains(body, fmt.Sprint(str)) + if !contains { + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + } + + return contains +} + +// HTTPBodyNotContains asserts that a specified handler returns a +// body that does not contain a string. +// +// assert.HTTPBodyNotContains(t, myHandler, "GET", "www.google.com", nil, "I'm Feeling Lucky") +// +// Returns whether the assertion was successful (true) or not (false). +func HTTPBodyNotContains(t TestingT, handler http.HandlerFunc, method, url string, values url.Values, str interface{}, msgAndArgs ...interface{}) bool { + if h, ok := t.(tHelper); ok { + h.Helper() + } + body := HTTPBody(handler, method, url, values) + + contains := strings.Contains(body, fmt.Sprint(str)) + if contains { + Fail(t, fmt.Sprintf("Expected response body for \"%s\" to NOT contain \"%s\" but found \"%s\"", url+"?"+values.Encode(), str, body)) + } + + return !contains +} From 62f78445649431e58507106b772501f6f84bc655 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Fri, 28 Feb 2020 18:24:46 +0100 Subject: [PATCH 40/50] Use test-infra scripts to intall serving and monitoring --- Gopkg.lock | 1 - test/e2e-common.sh | 27 +-- test/scripts/resolve_matching_release.go | 120 ---------- test/scripts/resolve_matching_release_test.go | 60 ----- third_party/VENDOR-LICENSE | 207 ------------------ 5 files changed, 7 insertions(+), 408 deletions(-) delete mode 100644 test/scripts/resolve_matching_release.go delete mode 100644 test/scripts/resolve_matching_release_test.go diff --git a/Gopkg.lock b/Gopkg.lock index e771ca5d4bb..9f526841d90 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1472,7 +1472,6 @@ "github.com/pkg/errors", "github.com/robfig/cron", "github.com/rogpeppe/fastuuid", - "github.com/rogpeppe/go-internal/semver", "github.com/tsenart/vegeta/lib", "github.com/wavesoftware/go-ensure", "go.opencensus.io/plugin/ochttp", diff --git a/test/e2e-common.sh b/test/e2e-common.sh index fdc3e35049a..7556c561f05 100755 --- a/test/e2e-common.sh +++ b/test/e2e-common.sh @@ -43,7 +43,7 @@ UNINSTALL_LIST=() # If no parameters are passed, installs the current source-based build. # Parameters: $1 - Knative Eventing YAML file function install_knative_eventing { - local knative_monitoring_pods knative_monitoring_version monitoring_yaml + local knative_monitoring_pods local INSTALL_RELEASE_YAML=$1 echo ">> Installing Knative Eventing" if [[ -z "$1" ]]; then @@ -53,18 +53,13 @@ function install_knative_eventing { fi wait_until_pods_running knative-eventing || fail_test "Knative Eventing did not come up" - knative_monitoring_version=$(go run test/scripts/resolve_matching_release.go \ - 'knative/serving' "${LATEST_RELEASE_VERSION}") \ - || fail_test 'Could not resolve knative monitoring version' - # Ensure knative monitoring is installed only once knative_monitoring_pods=$(kubectl get pods -n knative-monitoring \ --field-selector status.phase=Running 2> /dev/null | tail -n +2 | wc -l) if ! [[ ${knative_monitoring_pods} -gt 0 ]]; then - echo ">> Installing Knative Monitoring: ${knative_monitoring_version}" - monitoring_yaml="https://github.com/knative/serving/releases/download/${knative_monitoring_version}/monitoring.yaml" - start_knative_monitoring "${monitoring_yaml}" || fail_test "Knative Monitoring did not come up" - UNINSTALL_LIST+=( "${monitoring_yaml}" ) + echo ">> Installing Knative Monitoring" + start_knative_monitoring "${KNATIVE_MONITORING_RELEASE}" || fail_test "Knative Monitoring did not come up" + UNINSTALL_LIST+=( "${KNATIVE_MONITORING_RELEASE}" ) else echo ">> Knative Monitoring seems to be running, pods running: ${knative_monitoring_pods}." fi @@ -208,17 +203,9 @@ function install_istio { # Installs Knative Serving in the current cluster, and waits for it to be ready. function install_knative_serving { echo ">> Installing Knative serving" - local SERVING_VERSION - SERVING_VERSION=$(go run test/scripts/resolve_matching_release.go \ - 'knative/serving' "${LATEST_RELEASE_VERSION}") \ - || fail_test 'Could not resolve knative serving version' - readonly SERVING_YAML="https://github.com/knative/serving/releases/download/${SERVING_VERSION}/serving.yaml" - - echo "Knative serving YAML: ${SERVING_YAML}" - kubectl apply -f "${SERVING_YAML}" || return 1 - UNINSTALL_LIST+=( "${SERVING_YAML}" ) - - wait_until_pods_running knative-serving || fail_test "Knative Serving did not come up" + echo "Knative serving YAML: ${KNATIVE_SERVING_RELEASE}" + start_latest_knative_serving || fail_test 'Knative Serving failed to install' + UNINSTALL_LIST+=( "${KNATIVE_SERVING_RELEASE}" ) } function wait_for_file { diff --git a/test/scripts/resolve_matching_release.go b/test/scripts/resolve_matching_release.go deleted file mode 100644 index 39f45db3431..00000000000 --- a/test/scripts/resolve_matching_release.go +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright 2020 The Knative 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. - */ - -package main - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "net/http" - "os" - "sort" - - "github.com/rogpeppe/go-internal/semver" - "github.com/wavesoftware/go-ensure" -) - -var ( - ApiGateway = "https://api.github.com" -) - -func main() { - args := os.Args[1:] - if len(args) != 2 { - panic(fmt.Errorf("usage: ")) - } - - resolved := resolveMatchingRelease(args[0], args[1]) - fmt.Print(resolved) -} - -type bySemver []string - -func (s bySemver) Len() int { - return len(s) -} - -func (s bySemver) Swap(i, j int) { - s[i], s[j] = s[j], s[i] -} - -func (s bySemver) Less(i, j int) bool { - return semver.Compare(s[i], s[j]) > 0 -} - -type Tag struct { - Name string -} - -func resolveMatchingRelease(repo, version string) string { - version = prependV(version) - endpoint := fmt.Sprintf("%s/repos/%s/tags", ApiGateway, repo) - resp, err := http.Get(endpoint) - ensure.NoError(err) - defer func() { - err := resp.Body.Close() - ensure.NoError(err) - }() - body, err := ioutil.ReadAll(resp.Body) - var tags []Tag - ensure.NoError(json.Unmarshal(body, &tags)) - - versions := slurpVersions(tags) - matching := filterMatchingVersions(version, versions, true) - if len(matching) == 0 { - matching = filterMatchingVersions(version, versions, false) - if len(matching) == 0 { - matching = versions - } - } - sort.Sort(bySemver(matching)) - first := matching[0] - - return first -} - -func slurpVersions(tags []Tag) []string { - var res []string - for _, tag := range tags { - res = append(res, prependV(tag.Name)) - } - return res -} - -func prependV(version string) string { - if version[0] != 'v' { - return "v" + version - } - return version -} - -func filterMatchingVersions(version string, versions []string, strict bool) []string { - matcher := semverMatcher(version, strict) - var matching []string - for _, candidate := range versions { - if matcher == semverMatcher(candidate, strict) { - matching = append(matching, candidate) - } - } - return matching -} - -func semverMatcher(version string, strict bool) string { - if strict { - return semver.MajorMinor(version) - } - return semver.Major(version) -} diff --git a/test/scripts/resolve_matching_release_test.go b/test/scripts/resolve_matching_release_test.go deleted file mode 100644 index 78d7ec4953f..00000000000 --- a/test/scripts/resolve_matching_release_test.go +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright 2020 The Knative 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. - */ - -package main - -import ( - "testing" - - "github.com/rogpeppe/go-internal/semver" -) - -func TestResolveMatchingRelease(t *testing.T) { - candidate := "v0.8.0" - resolved := resolveMatchingRelease("knative/serving", candidate) - - if resolved != "v0.8.1" { - t.Errorf("resolved invalid version: %s", resolved) - } -} - -func TestResolveMatchingReleaseOurAhead(t *testing.T) { - candidate := "v0.800.0" - resolved := resolveMatchingRelease("knative/serving", candidate) - - if semver.Compare(resolved, "v1.0.0") >= 0 { - t.Errorf("resolved invalid version: %s", resolved) - } -} - -func TestResolveIstioRelease(t *testing.T) { - candidate := "v1.4.0" - repo := "istio/istio" - resolved := resolveMatchingRelease(repo, candidate) - - if semver.Compare(resolved, "v1.4.0") < 0 || semver.Compare(resolved, "v1.5.0") >= 0{ - t.Errorf("resolved invalid version: %s", resolved) - } -} - -func TestResolveIstioReleaseWithoutV(t *testing.T) { - candidate := "1.4.0" - repo := "istio/istio" - resolved := resolveMatchingRelease(repo, candidate) - - if semver.Compare(resolved, "v1.4.0") < 0 || semver.Compare(resolved, "v1.5.0") >= 0{ - t.Errorf("resolved invalid version: %s", resolved) - } -} diff --git a/third_party/VENDOR-LICENSE b/third_party/VENDOR-LICENSE index 6a8bd064528..8742d1dd2ec 100644 --- a/third_party/VENDOR-LICENSE +++ b/third_party/VENDOR-LICENSE @@ -5921,213 +5921,6 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -=========================================================== -Import: knative.dev/eventing/vendor/github.com/wavesoftware/go-ensure - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright 2020 Wave Software - - 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. - - - =========================================================== Import: knative.dev/eventing/vendor/go.opencensus.io From ecd0c9e8c82386f5290879eb85e5e919af1609cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Tue, 5 May 2020 17:44:23 +0200 Subject: [PATCH 41/50] Removal of Istio & Serving from tests --- test/e2e-common.sh | 32 - test/e2e-upgrade-tests.sh | 2 - test/lib/resources/serving.go | 4 +- test/prober/prober.go | 2 +- test/upgrade/README.md | 20 +- third_party/istio-1.4.3/README.md | 13 - third_party/istio-1.4.3/download-istio.sh | 52 - third_party/istio-1.4.3/istio-crds.yaml | 5255 ------------------ third_party/istio-1.4.3/istio-minimal.yaml | 960 ---- third_party/istio-1.4.3/namespace.yaml.patch | 10 - third_party/istio-1.4.3/values-local.yaml | 91 - 11 files changed, 13 insertions(+), 6428 deletions(-) delete mode 100644 third_party/istio-1.4.3/README.md delete mode 100755 third_party/istio-1.4.3/download-istio.sh delete mode 100644 third_party/istio-1.4.3/istio-crds.yaml delete mode 100644 third_party/istio-1.4.3/istio-minimal.yaml delete mode 100644 third_party/istio-1.4.3/namespace.yaml.patch delete mode 100644 third_party/istio-1.4.3/values-local.yaml diff --git a/test/e2e-common.sh b/test/e2e-common.sh index 7556c561f05..76fc8f72dd9 100755 --- a/test/e2e-common.sh +++ b/test/e2e-common.sh @@ -176,38 +176,6 @@ function dump_extra_cluster_state() { done } -function install_istio { - if [[ -z "${ISTIO_VERSION}" ]]; then - readonly ISTIO_VERSION="1.4.3" - fi - echo ">> Installing Istio: ${ISTIO_VERSION}" - - local istio_base="./third_party/istio-${ISTIO_VERSION}" - INSTALL_ISTIO_CRD_YAML="${istio_base}/istio-crds.yaml" - INSTALL_ISTIO_YAML="${istio_base}/istio-minimal.yaml" - - echo "Istio CRD YAML: ${INSTALL_ISTIO_CRD_YAML}" - echo "Istio YAML: ${INSTALL_ISTIO_YAML}" - - echo ">> Bringing up Istio" - echo ">> Running Istio CRD installer" - kubectl apply -f "${INSTALL_ISTIO_CRD_YAML}" || return 1 - wait_until_batch_job_complete istio-system || return 1 - UNINSTALL_LIST+=( "${INSTALL_ISTIO_CRD_YAML}" ) - - echo ">> Running Istio" - kubectl apply -f "${INSTALL_ISTIO_YAML}" || return 1 - UNINSTALL_LIST+=( "${INSTALL_ISTIO_YAML}" ) -} - -# Installs Knative Serving in the current cluster, and waits for it to be ready. -function install_knative_serving { - echo ">> Installing Knative serving" - echo "Knative serving YAML: ${KNATIVE_SERVING_RELEASE}" - start_latest_knative_serving || fail_test 'Knative Serving failed to install' - UNINSTALL_LIST+=( "${KNATIVE_SERVING_RELEASE}" ) -} - function wait_for_file { local file timeout waits file="$1" diff --git a/test/e2e-upgrade-tests.sh b/test/e2e-upgrade-tests.sh index d5b782e9ebd..1a53720c197 100755 --- a/test/e2e-upgrade-tests.sh +++ b/test/e2e-upgrade-tests.sh @@ -23,8 +23,6 @@ source "$(dirname "$0")/e2e-common.sh" # Overrides function knative_setup { - install_istio || fail_test 'Installing Istio failed' - install_knative_serving || fail_test 'Installing Knative Serving failed' install_latest_release || fail_test 'Installing latest release of Knative Eventing failed' } diff --git a/test/lib/resources/serving.go b/test/lib/resources/serving.go index ab912bd2bbd..f3cdc63dd6a 100644 --- a/test/lib/resources/serving.go +++ b/test/lib/resources/serving.go @@ -31,8 +31,8 @@ import ( // ServingClient holds clients required to get serving resources type ServingClient struct { - Kube *pkgTest.KubeClient - Dynamic dynamic.Interface + Kube *pkgTest.KubeClient + Dynamic dynamic.Interface } // KServiceRoute represents ksvc route, so how much traffic is routed to given deployment diff --git a/test/prober/prober.go b/test/prober/prober.go index 17a058ba636..e842a2e1267 100644 --- a/test/prober/prober.go +++ b/test/prober/prober.go @@ -73,7 +73,7 @@ func NewConfig(namespace string) *Config { FinishedSleep: 5 * time.Second, FailOnMissingEvents: true, Serving: ServingConfig{ - Use: true, + Use: false, ScaleToZero: true, }, } diff --git a/test/upgrade/README.md b/test/upgrade/README.md index 099d1dbe82a..c7a0c391124 100644 --- a/test/upgrade/README.md +++ b/test/upgrade/README.md @@ -49,18 +49,18 @@ Run the selected smoke test. In order to verify that we don't have data-plane unavailability during our control-plane outages (when we're upgrading the knative/eventing installation), we run a prober test that continually sends events to a service during the -entire upgrade/downgrade process. When the upgrade completes, we make sure -that all of those events propagated just once. +entire upgrade/downgrade process. When the upgrade completes, we make sure that +all of those events propagated just once. To achieve that a tool was prepared (https://github.com/cardil/wathola). It -consists of 3 components: _sender_, _forwarder_, and _receiver_. _Sender_ is -the usual Kubernetes pod that publishes events to the default `broker` with -given interval. When it closes (by either `SIGTERM`, or `SIGINT`), an -`finished` event is generated. _Forwarder_ is a knative serving service that -scales from zero to receive the requested traffic. _Forwarders_ receive events -and forwards them to given target. _Receiver_ is an ordinary pod that collects -events from multiple forwarders and has an endpoint `/report` that can be -polled to get the status of sent events. +consists of 3 components: _sender_, _forwarder_, and _receiver_. _Sender_ is the +usual Kubernetes pod that publishes events to the default `broker` with given +interval. When it closes (by either `SIGTERM`, or `SIGINT`), an `finished` event +is generated. _Forwarder_ is a knative serving service that scales from zero to +receive the requested traffic. _Forwarders_ receive events and forwards them to +given target. _Receiver_ is an ordinary pod that collects events from multiple +forwarders and has an endpoint `/report` that can be polled to get the status of +sent events. Diagram below describe the setup: diff --git a/third_party/istio-1.4.3/README.md b/third_party/istio-1.4.3/README.md deleted file mode 100644 index 26610d90843..00000000000 --- a/third_party/istio-1.4.3/README.md +++ /dev/null @@ -1,13 +0,0 @@ -The istio\*.yaml files are generated by running - -``` -./download-istio.sh -``` - -using Helm v3.0.2. - -The generated files are: - -- `istio-crd.yaml`: an Istio custom resource definitions. -- `istio-minimal.yaml`: a minimal Istio installation used for development - purposes. diff --git a/third_party/istio-1.4.3/download-istio.sh b/third_party/istio-1.4.3/download-istio.sh deleted file mode 100755 index 7566c55247d..00000000000 --- a/third_party/istio-1.4.3/download-istio.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env bash - -# Copyright 2019 The Knative 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. - -# Download and unpack Istio -ISTIO_VERSION=1.4.3 -DOWNLOAD_URL=https://github.com/istio/istio/releases/download/${ISTIO_VERSION}/istio-${ISTIO_VERSION}-linux.tar.gz - -wget --no-check-certificate $DOWNLOAD_URL -if [ $? != 0 ]; then - echo "Failed to download istio package" - exit 1 -fi -tar xzf istio-${ISTIO_VERSION}-linux.tar.gz - -( # subshell in downloaded directory -cd istio-${ISTIO_VERSION} || exit - -# Create CRDs template -helm template --namespace=istio-system \ - install/kubernetes/helm/istio-init \ - `# Removing trailing whitespaces to make automation happy` \ - | sed 's/[ \t]*$//' \ - > ../istio-crds.yaml - -# An even lighter template, with just pilot/gateway and small resource requests. -# Based on install/kubernetes/helm/istio/values-istio-minimal.yaml -helm template --namespace=istio-system install/kubernetes/helm/istio --values ../values-local.yaml \ - `# Removing trailing whitespaces to make automation happy` \ - | sed 's/[ \t]*$//' \ - > ../istio-minimal.yaml -) - -# Clean up. -rm -rf istio-${ISTIO_VERSION} -rm istio-${ISTIO_VERSION}-linux.tar.gz - -# Add in the `istio-system` namespace to reduce number of commands. -patch istio-crds.yaml namespace.yaml.patch -patch istio-minimal.yaml namespace.yaml.patch diff --git a/third_party/istio-1.4.3/istio-crds.yaml b/third_party/istio-1.4.3/istio-crds.yaml deleted file mode 100644 index 7dc6559fa82..00000000000 --- a/third_party/istio-1.4.3/istio-crds.yaml +++ /dev/null @@ -1,5255 +0,0 @@ ---- -# PATCH #1: Creating the istio-system namespace. -apiVersion: v1 -kind: Namespace -metadata: - name: istio-system - labels: - istio-injection: disabled -# PATCH #1 ends. ---- -# Source: istio-init/templates/configmap-crd-10.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: istio-system - name: istio-crd-10 -data: - crd-10.yaml: |- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - annotations: - "helm.sh/resource-policy": keep - labels: - app: mixer - chart: istio - heritage: Tiller - istio: core - package: istio.io.mixer - release: istio - name: attributemanifests.config.istio.io - spec: - group: config.istio.io - names: - categories: - - istio-io - - policy-istio-io - kind: attributemanifest - plural: attributemanifests - singular: attributemanifest - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - description: 'Describes the rules used to configure Mixer''s policy and - telemetry features. See more details at: https://istio.io/docs/reference/config/policy-and-telemetry/istio.policy.v1beta1.html' - properties: - attributes: - additionalProperties: - properties: - description: - description: A human-readable description of the attribute's purpose. - format: string - type: string - valueType: - description: The type of data carried by this attribute. - enum: - - VALUE_TYPE_UNSPECIFIED - - STRING - - INT64 - - DOUBLE - - BOOL - - TIMESTAMP - - IP_ADDRESS - - EMAIL_ADDRESS - - URI - - DNS_NAME - - DURATION - - STRING_MAP - type: string - type: object - description: The set of attributes this Istio component will be responsible - for producing at runtime. - type: object - name: - description: Name of the component producing these attributes. - format: string - type: string - revision: - description: The revision of this document. - format: string - type: string - type: object - type: object - versions: - - name: v1alpha2 - served: true - storage: true - - --- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - annotations: - "helm.sh/resource-policy": keep - labels: - app: istio-pilot - heritage: Tiller - istio: rbac - release: istio - name: clusterrbacconfigs.rbac.istio.io - spec: - group: rbac.istio.io - names: - categories: - - istio-io - - rbac-istio-io - kind: ClusterRbacConfig - plural: clusterrbacconfigs - singular: clusterrbacconfig - scope: Cluster - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - description: 'Configuration for Role Based Access Control. See more details - at: https://istio.io/docs/reference/config/authorization/istio.rbac.v1alpha1.html' - properties: - enforcementMode: - enum: - - ENFORCED - - PERMISSIVE - type: string - exclusion: - description: A list of services or namespaces that should not be enforced - by Istio RBAC policies. - properties: - namespaces: - description: A list of namespaces. - items: - format: string - type: string - type: array - services: - description: A list of services. - items: - format: string - type: string - type: array - type: object - inclusion: - description: A list of services or namespaces that should be enforced - by Istio RBAC policies. - properties: - namespaces: - description: A list of namespaces. - items: - format: string - type: string - type: array - services: - description: A list of services. - items: - format: string - type: string - type: array - type: object - mode: - description: Istio RBAC mode. - enum: - - "OFF" - - "ON" - - ON_WITH_INCLUSION - - ON_WITH_EXCLUSION - type: string - type: object - type: object - versions: - - name: v1alpha1 - served: true - storage: true - - --- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - annotations: - "helm.sh/resource-policy": keep - labels: - app: istio-pilot - chart: istio - heritage: Tiller - release: istio - name: destinationrules.networking.istio.io - spec: - additionalPrinterColumns: - - JSONPath: .spec.host - description: The name of a service from the service registry - name: Host - type: string - - JSONPath: .metadata.creationTimestamp - description: |- - CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - name: Age - type: date - group: networking.istio.io - names: - categories: - - istio-io - - networking-istio-io - kind: DestinationRule - listKind: DestinationRuleList - plural: destinationrules - shortNames: - - dr - singular: destinationrule - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - description: 'Configuration affecting load balancing, outlier detection, - etc. See more details at: https://istio.io/docs/reference/config/networking/v1alpha3/destination-rule.html' - properties: - exportTo: - description: A list of namespaces to which this destination rule is - exported. - items: - format: string - type: string - type: array - host: - description: The name of a service from the service registry. - format: string - type: string - subsets: - items: - properties: - labels: - additionalProperties: - format: string - type: string - type: object - name: - description: Name of the subset. - format: string - type: string - trafficPolicy: - description: Traffic policies that apply to this subset. - properties: - connectionPool: - properties: - http: - description: HTTP connection pool settings. - properties: - h2UpgradePolicy: - description: Specify if http1.1 connection should - be upgraded to http2 for the associated destination. - enum: - - DEFAULT - - DO_NOT_UPGRADE - - UPGRADE - type: string - http1MaxPendingRequests: - description: Maximum number of pending HTTP requests - to a destination. - format: int32 - type: integer - http2MaxRequests: - description: Maximum number of requests to a backend. - format: int32 - type: integer - idleTimeout: - description: The idle timeout for upstream connection - pool connections. - type: string - maxRequestsPerConnection: - description: Maximum number of requests per connection - to a backend. - format: int32 - type: integer - maxRetries: - format: int32 - type: integer - type: object - tcp: - description: Settings common to both HTTP and TCP upstream - connections. - properties: - connectTimeout: - description: TCP connection timeout. - type: string - maxConnections: - description: Maximum number of HTTP1 /TCP connections - to a destination host. - format: int32 - type: integer - tcpKeepalive: - description: If set then set SO_KEEPALIVE on the socket - to enable TCP Keepalives. - properties: - interval: - description: The time duration between keep-alive - probes. - type: string - probes: - type: integer - time: - type: string - type: object - type: object - type: object - loadBalancer: - description: Settings controlling the load balancer algorithms. - oneOf: - - required: - - simple - - properties: - consistentHash: - oneOf: - - required: - - httpHeaderName - - required: - - httpCookie - - required: - - useSourceIp - required: - - consistentHash - properties: - consistentHash: - properties: - httpCookie: - description: Hash based on HTTP cookie. - properties: - name: - description: Name of the cookie. - format: string - type: string - path: - description: Path to set for the cookie. - format: string - type: string - ttl: - description: Lifetime of the cookie. - type: string - type: object - httpHeaderName: - description: Hash based on a specific HTTP header. - format: string - type: string - minimumRingSize: - type: integer - useSourceIp: - description: Hash based on the source IP address. - type: boolean - type: object - simple: - enum: - - ROUND_ROBIN - - LEAST_CONN - - RANDOM - - PASSTHROUGH - type: string - type: object - outlierDetection: - properties: - baseEjectionTime: - description: Minimum ejection duration. - type: string - consecutiveErrors: - format: int32 - type: integer - interval: - description: Time interval between ejection sweep analysis. - type: string - maxEjectionPercent: - format: int32 - type: integer - minHealthPercent: - format: int32 - type: integer - type: object - portLevelSettings: - description: Traffic policies specific to individual ports. - items: - properties: - connectionPool: - properties: - http: - description: HTTP connection pool settings. - properties: - h2UpgradePolicy: - description: Specify if http1.1 connection should - be upgraded to http2 for the associated destination. - enum: - - DEFAULT - - DO_NOT_UPGRADE - - UPGRADE - type: string - http1MaxPendingRequests: - description: Maximum number of pending HTTP - requests to a destination. - format: int32 - type: integer - http2MaxRequests: - description: Maximum number of requests to a - backend. - format: int32 - type: integer - idleTimeout: - description: The idle timeout for upstream connection - pool connections. - type: string - maxRequestsPerConnection: - description: Maximum number of requests per - connection to a backend. - format: int32 - type: integer - maxRetries: - format: int32 - type: integer - type: object - tcp: - description: Settings common to both HTTP and TCP - upstream connections. - properties: - connectTimeout: - description: TCP connection timeout. - type: string - maxConnections: - description: Maximum number of HTTP1 /TCP connections - to a destination host. - format: int32 - type: integer - tcpKeepalive: - description: If set then set SO_KEEPALIVE on - the socket to enable TCP Keepalives. - properties: - interval: - description: The time duration between keep-alive - probes. - type: string - probes: - type: integer - time: - type: string - type: object - type: object - type: object - loadBalancer: - description: Settings controlling the load balancer - algorithms. - oneOf: - - required: - - simple - - properties: - consistentHash: - oneOf: - - required: - - httpHeaderName - - required: - - httpCookie - - required: - - useSourceIp - required: - - consistentHash - properties: - consistentHash: - properties: - httpCookie: - description: Hash based on HTTP cookie. - properties: - name: - description: Name of the cookie. - format: string - type: string - path: - description: Path to set for the cookie. - format: string - type: string - ttl: - description: Lifetime of the cookie. - type: string - type: object - httpHeaderName: - description: Hash based on a specific HTTP header. - format: string - type: string - minimumRingSize: - type: integer - useSourceIp: - description: Hash based on the source IP address. - type: boolean - type: object - simple: - enum: - - ROUND_ROBIN - - LEAST_CONN - - RANDOM - - PASSTHROUGH - type: string - type: object - outlierDetection: - properties: - baseEjectionTime: - description: Minimum ejection duration. - type: string - consecutiveErrors: - format: int32 - type: integer - interval: - description: Time interval between ejection sweep - analysis. - type: string - maxEjectionPercent: - format: int32 - type: integer - minHealthPercent: - format: int32 - type: integer - type: object - port: - properties: - number: - type: integer - type: object - tls: - description: TLS related settings for connections to - the upstream service. - properties: - caCertificates: - format: string - type: string - clientCertificate: - description: REQUIRED if mode is `MUTUAL`. - format: string - type: string - mode: - enum: - - DISABLE - - SIMPLE - - MUTUAL - - ISTIO_MUTUAL - type: string - privateKey: - description: REQUIRED if mode is `MUTUAL`. - format: string - type: string - sni: - description: SNI string to present to the server - during TLS handshake. - format: string - type: string - subjectAltNames: - items: - format: string - type: string - type: array - type: object - type: object - type: array - tls: - description: TLS related settings for connections to the upstream - service. - properties: - caCertificates: - format: string - type: string - clientCertificate: - description: REQUIRED if mode is `MUTUAL`. - format: string - type: string - mode: - enum: - - DISABLE - - SIMPLE - - MUTUAL - - ISTIO_MUTUAL - type: string - privateKey: - description: REQUIRED if mode is `MUTUAL`. - format: string - type: string - sni: - description: SNI string to present to the server during - TLS handshake. - format: string - type: string - subjectAltNames: - items: - format: string - type: string - type: array - type: object - type: object - type: object - type: array - trafficPolicy: - properties: - connectionPool: - properties: - http: - description: HTTP connection pool settings. - properties: - h2UpgradePolicy: - description: Specify if http1.1 connection should be upgraded - to http2 for the associated destination. - enum: - - DEFAULT - - DO_NOT_UPGRADE - - UPGRADE - type: string - http1MaxPendingRequests: - description: Maximum number of pending HTTP requests to - a destination. - format: int32 - type: integer - http2MaxRequests: - description: Maximum number of requests to a backend. - format: int32 - type: integer - idleTimeout: - description: The idle timeout for upstream connection pool - connections. - type: string - maxRequestsPerConnection: - description: Maximum number of requests per connection to - a backend. - format: int32 - type: integer - maxRetries: - format: int32 - type: integer - type: object - tcp: - description: Settings common to both HTTP and TCP upstream connections. - properties: - connectTimeout: - description: TCP connection timeout. - type: string - maxConnections: - description: Maximum number of HTTP1 /TCP connections to - a destination host. - format: int32 - type: integer - tcpKeepalive: - description: If set then set SO_KEEPALIVE on the socket - to enable TCP Keepalives. - properties: - interval: - description: The time duration between keep-alive probes. - type: string - probes: - type: integer - time: - type: string - type: object - type: object - type: object - loadBalancer: - description: Settings controlling the load balancer algorithms. - oneOf: - - required: - - simple - - properties: - consistentHash: - oneOf: - - required: - - httpHeaderName - - required: - - httpCookie - - required: - - useSourceIp - required: - - consistentHash - properties: - consistentHash: - properties: - httpCookie: - description: Hash based on HTTP cookie. - properties: - name: - description: Name of the cookie. - format: string - type: string - path: - description: Path to set for the cookie. - format: string - type: string - ttl: - description: Lifetime of the cookie. - type: string - type: object - httpHeaderName: - description: Hash based on a specific HTTP header. - format: string - type: string - minimumRingSize: - type: integer - useSourceIp: - description: Hash based on the source IP address. - type: boolean - type: object - simple: - enum: - - ROUND_ROBIN - - LEAST_CONN - - RANDOM - - PASSTHROUGH - type: string - type: object - outlierDetection: - properties: - baseEjectionTime: - description: Minimum ejection duration. - type: string - consecutiveErrors: - format: int32 - type: integer - interval: - description: Time interval between ejection sweep analysis. - type: string - maxEjectionPercent: - format: int32 - type: integer - minHealthPercent: - format: int32 - type: integer - type: object - portLevelSettings: - description: Traffic policies specific to individual ports. - items: - properties: - connectionPool: - properties: - http: - description: HTTP connection pool settings. - properties: - h2UpgradePolicy: - description: Specify if http1.1 connection should - be upgraded to http2 for the associated destination. - enum: - - DEFAULT - - DO_NOT_UPGRADE - - UPGRADE - type: string - http1MaxPendingRequests: - description: Maximum number of pending HTTP requests - to a destination. - format: int32 - type: integer - http2MaxRequests: - description: Maximum number of requests to a backend. - format: int32 - type: integer - idleTimeout: - description: The idle timeout for upstream connection - pool connections. - type: string - maxRequestsPerConnection: - description: Maximum number of requests per connection - to a backend. - format: int32 - type: integer - maxRetries: - format: int32 - type: integer - type: object - tcp: - description: Settings common to both HTTP and TCP upstream - connections. - properties: - connectTimeout: - description: TCP connection timeout. - type: string - maxConnections: - description: Maximum number of HTTP1 /TCP connections - to a destination host. - format: int32 - type: integer - tcpKeepalive: - description: If set then set SO_KEEPALIVE on the socket - to enable TCP Keepalives. - properties: - interval: - description: The time duration between keep-alive - probes. - type: string - probes: - type: integer - time: - type: string - type: object - type: object - type: object - loadBalancer: - description: Settings controlling the load balancer algorithms. - oneOf: - - required: - - simple - - properties: - consistentHash: - oneOf: - - required: - - httpHeaderName - - required: - - httpCookie - - required: - - useSourceIp - required: - - consistentHash - properties: - consistentHash: - properties: - httpCookie: - description: Hash based on HTTP cookie. - properties: - name: - description: Name of the cookie. - format: string - type: string - path: - description: Path to set for the cookie. - format: string - type: string - ttl: - description: Lifetime of the cookie. - type: string - type: object - httpHeaderName: - description: Hash based on a specific HTTP header. - format: string - type: string - minimumRingSize: - type: integer - useSourceIp: - description: Hash based on the source IP address. - type: boolean - type: object - simple: - enum: - - ROUND_ROBIN - - LEAST_CONN - - RANDOM - - PASSTHROUGH - type: string - type: object - outlierDetection: - properties: - baseEjectionTime: - description: Minimum ejection duration. - type: string - consecutiveErrors: - format: int32 - type: integer - interval: - description: Time interval between ejection sweep analysis. - type: string - maxEjectionPercent: - format: int32 - type: integer - minHealthPercent: - format: int32 - type: integer - type: object - port: - properties: - number: - type: integer - type: object - tls: - description: TLS related settings for connections to the upstream - service. - properties: - caCertificates: - format: string - type: string - clientCertificate: - description: REQUIRED if mode is `MUTUAL`. - format: string - type: string - mode: - enum: - - DISABLE - - SIMPLE - - MUTUAL - - ISTIO_MUTUAL - type: string - privateKey: - description: REQUIRED if mode is `MUTUAL`. - format: string - type: string - sni: - description: SNI string to present to the server during - TLS handshake. - format: string - type: string - subjectAltNames: - items: - format: string - type: string - type: array - type: object - type: object - type: array - tls: - description: TLS related settings for connections to the upstream - service. - properties: - caCertificates: - format: string - type: string - clientCertificate: - description: REQUIRED if mode is `MUTUAL`. - format: string - type: string - mode: - enum: - - DISABLE - - SIMPLE - - MUTUAL - - ISTIO_MUTUAL - type: string - privateKey: - description: REQUIRED if mode is `MUTUAL`. - format: string - type: string - sni: - description: SNI string to present to the server during TLS - handshake. - format: string - type: string - subjectAltNames: - items: - format: string - type: string - type: array - type: object - type: object - type: object - type: object - versions: - - name: v1alpha3 - served: true - storage: true - - --- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - annotations: - "helm.sh/resource-policy": keep - labels: - app: istio-pilot - chart: istio - heritage: Tiller - release: istio - name: envoyfilters.networking.istio.io - spec: - group: networking.istio.io - names: - categories: - - istio-io - - networking-istio-io - kind: EnvoyFilter - plural: envoyfilters - singular: envoyfilter - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - description: 'Customizing Envoy configuration generated by Istio. See more - details at: https://istio.io/docs/reference/config/networking/v1alpha3/envoy-filter.html' - properties: - configPatches: - description: One or more patches with match conditions. - items: - properties: - applyTo: - enum: - - INVALID - - LISTENER - - FILTER_CHAIN - - NETWORK_FILTER - - HTTP_FILTER - - ROUTE_CONFIGURATION - - VIRTUAL_HOST - - HTTP_ROUTE - - CLUSTER - type: string - match: - description: Match on listener/route configuration/cluster. - oneOf: - - required: - - listener - - required: - - routeConfiguration - - required: - - cluster - properties: - cluster: - description: Match on envoy cluster attributes. - properties: - name: - description: The exact name of the cluster to match. - format: string - type: string - portNumber: - description: The service port for which this cluster was - generated. - type: integer - service: - description: The fully qualified service name for this - cluster. - format: string - type: string - subset: - description: The subset associated with the service. - format: string - type: string - type: object - context: - description: The specific config generation context to match - on. - enum: - - ANY - - SIDECAR_INBOUND - - SIDECAR_OUTBOUND - - GATEWAY - type: string - listener: - description: Match on envoy listener attributes. - properties: - filterChain: - description: Match a specific filter chain in a listener. - properties: - applicationProtocols: - description: Applies only to sidecars. - format: string - type: string - filter: - description: The name of a specific filter to apply - the patch to. - properties: - name: - description: The filter name to match on. - format: string - type: string - subFilter: - properties: - name: - description: The filter name to match on. - format: string - type: string - type: object - type: object - name: - description: The name assigned to the filter chain. - format: string - type: string - sni: - description: The SNI value used by a filter chain's - match condition. - format: string - type: string - transportProtocol: - description: Applies only to SIDECAR_INBOUND context. - format: string - type: string - type: object - name: - description: Match a specific listener by its name. - format: string - type: string - portName: - format: string - type: string - portNumber: - type: integer - type: object - proxy: - description: Match on properties associated with a proxy. - properties: - metadata: - additionalProperties: - format: string - type: string - type: object - proxyVersion: - format: string - type: string - type: object - routeConfiguration: - description: Match on envoy HTTP route configuration attributes. - properties: - gateway: - format: string - type: string - name: - description: Route configuration name to match on. - format: string - type: string - portName: - description: Applicable only for GATEWAY context. - format: string - type: string - portNumber: - type: integer - vhost: - properties: - name: - format: string - type: string - route: - description: Match a specific route within the virtual - host. - properties: - action: - description: Match a route with specific action - type. - enum: - - ANY - - ROUTE - - REDIRECT - - DIRECT_RESPONSE - type: string - name: - format: string - type: string - type: object - type: object - type: object - type: object - patch: - description: The patch to apply along with the operation. - properties: - operation: - description: Determines how the patch should be applied. - enum: - - INVALID - - MERGE - - ADD - - REMOVE - - INSERT_BEFORE - - INSERT_AFTER - type: string - value: - description: The JSON config of the object being patched. - type: object - type: object - type: object - type: array - filters: - items: - properties: - filterConfig: - type: object - filterName: - description: The name of the filter to instantiate. - format: string - type: string - filterType: - description: The type of filter to instantiate. - enum: - - INVALID - - HTTP - - NETWORK - type: string - insertPosition: - description: Insert position in the filter chain. - properties: - index: - description: Position of this filter in the filter chain. - enum: - - FIRST - - LAST - - BEFORE - - AFTER - type: string - relativeTo: - format: string - type: string - type: object - listenerMatch: - properties: - address: - description: One or more IP addresses to which the listener - is bound. - items: - format: string - type: string - type: array - listenerProtocol: - description: Selects a class of listeners for the same protocol. - enum: - - ALL - - HTTP - - TCP - type: string - listenerType: - description: Inbound vs outbound sidecar listener or gateway - listener. - enum: - - ANY - - SIDECAR_INBOUND - - SIDECAR_OUTBOUND - - GATEWAY - type: string - portNamePrefix: - format: string - type: string - portNumber: - type: integer - type: object - type: object - type: array - workloadLabels: - additionalProperties: - format: string - type: string - description: Deprecated. - type: object - workloadSelector: - properties: - labels: - additionalProperties: - format: string - type: string - type: object - type: object - type: object - type: object - versions: - - name: v1alpha3 - served: true - storage: true - - --- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - annotations: - "helm.sh/resource-policy": keep - labels: - app: istio-pilot - chart: istio - heritage: Tiller - release: istio - name: gateways.networking.istio.io - spec: - group: networking.istio.io - names: - categories: - - istio-io - - networking-istio-io - kind: Gateway - plural: gateways - shortNames: - - gw - singular: gateway - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - description: 'Configuration affecting edge load balancer. See more details - at: https://istio.io/docs/reference/config/networking/v1alpha3/gateway.html' - properties: - selector: - additionalProperties: - format: string - type: string - type: object - servers: - description: A list of server specifications. - items: - properties: - bind: - format: string - type: string - defaultEndpoint: - format: string - type: string - hosts: - description: One or more hosts exposed by this gateway. - items: - format: string - type: string - type: array - port: - properties: - name: - description: Label assigned to the port. - format: string - type: string - number: - description: A valid non-negative integer port number. - type: integer - protocol: - description: The protocol exposed on the port. - format: string - type: string - type: object - tls: - description: Set of TLS related options that govern the server's - behavior. - properties: - caCertificates: - description: REQUIRED if mode is `MUTUAL`. - format: string - type: string - cipherSuites: - description: 'Optional: If specified, only support the specified - cipher list.' - items: - format: string - type: string - type: array - credentialName: - format: string - type: string - httpsRedirect: - type: boolean - maxProtocolVersion: - description: 'Optional: Maximum TLS protocol version.' - enum: - - TLS_AUTO - - TLSV1_0 - - TLSV1_1 - - TLSV1_2 - - TLSV1_3 - type: string - minProtocolVersion: - description: 'Optional: Minimum TLS protocol version.' - enum: - - TLS_AUTO - - TLSV1_0 - - TLSV1_1 - - TLSV1_2 - - TLSV1_3 - type: string - mode: - enum: - - PASSTHROUGH - - SIMPLE - - MUTUAL - - AUTO_PASSTHROUGH - - ISTIO_MUTUAL - type: string - privateKey: - description: REQUIRED if mode is `SIMPLE` or `MUTUAL`. - format: string - type: string - serverCertificate: - description: REQUIRED if mode is `SIMPLE` or `MUTUAL`. - format: string - type: string - subjectAltNames: - items: - format: string - type: string - type: array - verifyCertificateHash: - items: - format: string - type: string - type: array - verifyCertificateSpki: - items: - format: string - type: string - type: array - type: object - type: object - type: array - type: object - type: object - versions: - - name: v1alpha3 - served: true - storage: true - - --- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - annotations: - "helm.sh/resource-policy": keep - labels: - app: istio-mixer - chart: istio - heritage: Tiller - release: istio - name: httpapispecbindings.config.istio.io - spec: - group: config.istio.io - names: - categories: - - istio-io - - apim-istio-io - kind: HTTPAPISpecBinding - plural: httpapispecbindings - singular: httpapispecbinding - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - properties: - api_specs: - items: - properties: - name: - description: The short name of the HTTPAPISpec. - format: string - type: string - namespace: - description: Optional namespace of the HTTPAPISpec. - format: string - type: string - type: object - type: array - apiSpecs: - items: - properties: - name: - description: The short name of the HTTPAPISpec. - format: string - type: string - namespace: - description: Optional namespace of the HTTPAPISpec. - format: string - type: string - type: object - type: array - services: - description: One or more services to map the listed HTTPAPISpec onto. - items: - properties: - domain: - description: Domain suffix used to construct the service FQDN - in implementations that support such specification. - format: string - type: string - labels: - additionalProperties: - format: string - type: string - description: Optional one or more labels that uniquely identify - the service version. - type: object - name: - description: The short name of the service such as "foo". - format: string - type: string - namespace: - description: Optional namespace of the service. - format: string - type: string - service: - description: The service FQDN. - format: string - type: string - type: object - type: array - type: object - type: object - versions: - - name: v1alpha2 - served: true - storage: true - - --- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - annotations: - "helm.sh/resource-policy": keep - labels: - app: istio-mixer - chart: istio - heritage: Tiller - release: istio - name: httpapispecs.config.istio.io - spec: - group: config.istio.io - names: - categories: - - istio-io - - apim-istio-io - kind: HTTPAPISpec - plural: httpapispecs - singular: httpapispec - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - properties: - api_keys: - items: - oneOf: - - required: - - query - - required: - - header - - required: - - cookie - properties: - cookie: - format: string - type: string - header: - description: API key is sent in a request header. - format: string - type: string - query: - description: API Key is sent as a query parameter. - format: string - type: string - type: object - type: array - apiKeys: - items: - oneOf: - - required: - - query - - required: - - header - - required: - - cookie - properties: - cookie: - format: string - type: string - header: - description: API key is sent in a request header. - format: string - type: string - query: - description: API Key is sent as a query parameter. - format: string - type: string - type: object - type: array - attributes: - properties: - attributes: - additionalProperties: - oneOf: - - required: - - stringValue - - required: - - int64Value - - required: - - doubleValue - - required: - - boolValue - - required: - - bytesValue - - required: - - timestampValue - - required: - - durationValue - - required: - - stringMapValue - properties: - boolValue: - type: boolean - bytesValue: - format: binary - type: string - doubleValue: - format: double - type: number - durationValue: - type: string - int64Value: - format: int64 - type: integer - stringMapValue: - properties: - entries: - additionalProperties: - format: string - type: string - description: Holds a set of name/value pairs. - type: object - type: object - stringValue: - format: string - type: string - timestampValue: - format: dateTime - type: string - type: object - description: A map of attribute name to its value. - type: object - type: object - patterns: - description: List of HTTP patterns to match. - items: - oneOf: - - required: - - uriTemplate - - required: - - regex - properties: - attributes: - properties: - attributes: - additionalProperties: - oneOf: - - required: - - stringValue - - required: - - int64Value - - required: - - doubleValue - - required: - - boolValue - - required: - - bytesValue - - required: - - timestampValue - - required: - - durationValue - - required: - - stringMapValue - properties: - boolValue: - type: boolean - bytesValue: - format: binary - type: string - doubleValue: - format: double - type: number - durationValue: - type: string - int64Value: - format: int64 - type: integer - stringMapValue: - properties: - entries: - additionalProperties: - format: string - type: string - description: Holds a set of name/value pairs. - type: object - type: object - stringValue: - format: string - type: string - timestampValue: - format: dateTime - type: string - type: object - description: A map of attribute name to its value. - type: object - type: object - httpMethod: - format: string - type: string - regex: - format: string - type: string - uriTemplate: - format: string - type: string - type: object - type: array - type: object - type: object - versions: - - name: v1alpha2 - served: true - storage: true - - --- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - annotations: - "helm.sh/resource-policy": keep - labels: - app: istio-citadel - chart: istio - heritage: Tiller - release: istio - name: meshpolicies.authentication.istio.io - spec: - group: authentication.istio.io - names: - categories: - - istio-io - - authentication-istio-io - kind: MeshPolicy - listKind: MeshPolicyList - plural: meshpolicies - singular: meshpolicy - scope: Cluster - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - description: 'Authentication policy for Istio services. See more details - at: https://istio.io/docs/reference/config/istio.authentication.v1alpha1.html' - properties: - originIsOptional: - type: boolean - origins: - description: List of authentication methods that can be used for origin - authentication. - items: - properties: - jwt: - description: Jwt params for the method. - properties: - audiences: - items: - format: string - type: string - type: array - issuer: - description: Identifies the issuer that issued the JWT. - format: string - type: string - jwks: - description: JSON Web Key Set of public keys to validate signature - of the JWT. - format: string - type: string - jwks_uri: - format: string - type: string - jwksUri: - format: string - type: string - jwt_headers: - description: JWT is sent in a request header. - items: - format: string - type: string - type: array - jwtHeaders: - description: JWT is sent in a request header. - items: - format: string - type: string - type: array - jwtParams: - description: JWT is sent in a query parameter. - items: - format: string - type: string - type: array - trigger_rules: - items: - properties: - excluded_paths: - description: List of paths to be excluded from the request. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - excludedPaths: - description: List of paths to be excluded from the request. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - included_paths: - description: List of paths that the request must include. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - includedPaths: - description: List of paths that the request must include. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - type: object - type: array - triggerRules: - items: - properties: - excluded_paths: - description: List of paths to be excluded from the request. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - excludedPaths: - description: List of paths to be excluded from the request. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - included_paths: - description: List of paths that the request must include. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - includedPaths: - description: List of paths that the request must include. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - type: object - type: array - type: object - type: object - type: array - peerIsOptional: - type: boolean - peers: - description: List of authentication methods that can be used for peer - authentication. - items: - oneOf: - - required: - - mtls - - required: - - jwt - properties: - jwt: - properties: - audiences: - items: - format: string - type: string - type: array - issuer: - description: Identifies the issuer that issued the JWT. - format: string - type: string - jwks: - description: JSON Web Key Set of public keys to validate signature - of the JWT. - format: string - type: string - jwks_uri: - format: string - type: string - jwksUri: - format: string - type: string - jwt_headers: - description: JWT is sent in a request header. - items: - format: string - type: string - type: array - jwtHeaders: - description: JWT is sent in a request header. - items: - format: string - type: string - type: array - jwtParams: - description: JWT is sent in a query parameter. - items: - format: string - type: string - type: array - trigger_rules: - items: - properties: - excluded_paths: - description: List of paths to be excluded from the request. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - excludedPaths: - description: List of paths to be excluded from the request. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - included_paths: - description: List of paths that the request must include. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - includedPaths: - description: List of paths that the request must include. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - type: object - type: array - triggerRules: - items: - properties: - excluded_paths: - description: List of paths to be excluded from the request. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - excludedPaths: - description: List of paths to be excluded from the request. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - included_paths: - description: List of paths that the request must include. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - includedPaths: - description: List of paths that the request must include. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - type: object - type: array - type: object - mtls: - description: Set if mTLS is used. - properties: - allowTls: - description: WILL BE DEPRECATED, if set, will translates to - `TLS_PERMISSIVE` mode. - type: boolean - mode: - description: Defines the mode of mTLS authentication. - enum: - - STRICT - - PERMISSIVE - type: string - type: object - type: object - type: array - principalBinding: - description: Define whether peer or origin identity should be use for - principal. - enum: - - USE_PEER - - USE_ORIGIN - type: string - targets: - description: List rules to select workloads that the policy should be - applied on. - items: - properties: - labels: - additionalProperties: - format: string - type: string - type: object - name: - description: The name must be a short name from the service registry. - format: string - type: string - ports: - description: Specifies the ports. - items: - oneOf: - - required: - - number - - required: - - name - properties: - name: - format: string - type: string - number: - type: integer - type: object - type: array - type: object - type: array - type: object - type: object - versions: - - name: v1alpha1 - served: true - storage: true - - --- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - annotations: - "helm.sh/resource-policy": keep - labels: - app: istio-citadel - chart: istio - heritage: Tiller - release: istio - name: policies.authentication.istio.io - spec: - group: authentication.istio.io - names: - categories: - - istio-io - - authentication-istio-io - kind: Policy - plural: policies - singular: policy - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - description: 'Authentication policy for Istio services. See more details - at: https://istio.io/docs/reference/config/istio.authentication.v1alpha1.html' - properties: - originIsOptional: - type: boolean - origins: - description: List of authentication methods that can be used for origin - authentication. - items: - properties: - jwt: - description: Jwt params for the method. - properties: - audiences: - items: - format: string - type: string - type: array - issuer: - description: Identifies the issuer that issued the JWT. - format: string - type: string - jwks: - description: JSON Web Key Set of public keys to validate signature - of the JWT. - format: string - type: string - jwks_uri: - format: string - type: string - jwksUri: - format: string - type: string - jwt_headers: - description: JWT is sent in a request header. - items: - format: string - type: string - type: array - jwtHeaders: - description: JWT is sent in a request header. - items: - format: string - type: string - type: array - jwtParams: - description: JWT is sent in a query parameter. - items: - format: string - type: string - type: array - trigger_rules: - items: - properties: - excluded_paths: - description: List of paths to be excluded from the request. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - excludedPaths: - description: List of paths to be excluded from the request. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - included_paths: - description: List of paths that the request must include. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - includedPaths: - description: List of paths that the request must include. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - type: object - type: array - triggerRules: - items: - properties: - excluded_paths: - description: List of paths to be excluded from the request. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - excludedPaths: - description: List of paths to be excluded from the request. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - included_paths: - description: List of paths that the request must include. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - includedPaths: - description: List of paths that the request must include. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - type: object - type: array - type: object - type: object - type: array - peerIsOptional: - type: boolean - peers: - description: List of authentication methods that can be used for peer - authentication. - items: - oneOf: - - required: - - mtls - - required: - - jwt - properties: - jwt: - properties: - audiences: - items: - format: string - type: string - type: array - issuer: - description: Identifies the issuer that issued the JWT. - format: string - type: string - jwks: - description: JSON Web Key Set of public keys to validate signature - of the JWT. - format: string - type: string - jwks_uri: - format: string - type: string - jwksUri: - format: string - type: string - jwt_headers: - description: JWT is sent in a request header. - items: - format: string - type: string - type: array - jwtHeaders: - description: JWT is sent in a request header. - items: - format: string - type: string - type: array - jwtParams: - description: JWT is sent in a query parameter. - items: - format: string - type: string - type: array - trigger_rules: - items: - properties: - excluded_paths: - description: List of paths to be excluded from the request. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - excludedPaths: - description: List of paths to be excluded from the request. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - included_paths: - description: List of paths that the request must include. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - includedPaths: - description: List of paths that the request must include. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - type: object - type: array - triggerRules: - items: - properties: - excluded_paths: - description: List of paths to be excluded from the request. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - excludedPaths: - description: List of paths to be excluded from the request. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - included_paths: - description: List of paths that the request must include. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - includedPaths: - description: List of paths that the request must include. - items: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - suffix - - required: - - regex - properties: - exact: - description: exact string match. - format: string - type: string - prefix: - description: prefix-based match. - format: string - type: string - regex: - description: ECMAscript style regex-based match - as defined by [EDCA-262](http://en.cppreference.com/w/cpp/regex/ecmascript). - format: string - type: string - suffix: - description: suffix-based match. - format: string - type: string - type: object - type: array - type: object - type: array - type: object - mtls: - description: Set if mTLS is used. - properties: - allowTls: - description: WILL BE DEPRECATED, if set, will translates to - `TLS_PERMISSIVE` mode. - type: boolean - mode: - description: Defines the mode of mTLS authentication. - enum: - - STRICT - - PERMISSIVE - type: string - type: object - type: object - type: array - principalBinding: - description: Define whether peer or origin identity should be use for - principal. - enum: - - USE_PEER - - USE_ORIGIN - type: string - targets: - description: List rules to select workloads that the policy should be - applied on. - items: - properties: - labels: - additionalProperties: - format: string - type: string - type: object - name: - description: The name must be a short name from the service registry. - format: string - type: string - ports: - description: Specifies the ports. - items: - oneOf: - - required: - - number - - required: - - name - properties: - name: - format: string - type: string - number: - type: integer - type: object - type: array - type: object - type: array - type: object - type: object - versions: - - name: v1alpha1 - served: true - storage: true - - --- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - annotations: - "helm.sh/resource-policy": keep - labels: - app: istio-mixer - chart: istio - heritage: Tiller - release: istio - name: quotaspecbindings.config.istio.io - spec: - group: config.istio.io - names: - categories: - - istio-io - - apim-istio-io - kind: QuotaSpecBinding - plural: quotaspecbindings - singular: quotaspecbinding - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - properties: - quotaSpecs: - items: - properties: - name: - description: The short name of the QuotaSpec. - format: string - type: string - namespace: - description: Optional namespace of the QuotaSpec. - format: string - type: string - type: object - type: array - services: - description: One or more services to map the listed QuotaSpec onto. - items: - properties: - domain: - description: Domain suffix used to construct the service FQDN - in implementations that support such specification. - format: string - type: string - labels: - additionalProperties: - format: string - type: string - description: Optional one or more labels that uniquely identify - the service version. - type: object - name: - description: The short name of the service such as "foo". - format: string - type: string - namespace: - description: Optional namespace of the service. - format: string - type: string - service: - description: The service FQDN. - format: string - type: string - type: object - type: array - type: object - type: object - versions: - - name: v1alpha2 - served: true - storage: true - - --- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - annotations: - "helm.sh/resource-policy": keep - labels: - app: istio-mixer - chart: istio - heritage: Tiller - release: istio - name: quotaspecs.config.istio.io - spec: - group: config.istio.io - names: - categories: - - istio-io - - apim-istio-io - kind: QuotaSpec - plural: quotaspecs - singular: quotaspec - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - description: Determines the quotas used for individual requests. - properties: - rules: - description: A list of Quota rules. - items: - properties: - match: - description: If empty, match all request. - items: - properties: - clause: - additionalProperties: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - regex - properties: - exact: - format: string - type: string - prefix: - format: string - type: string - regex: - format: string - type: string - type: object - description: Map of attribute names to StringMatch type. - type: object - type: object - type: array - quotas: - description: The list of quotas to charge. - items: - properties: - charge: - format: int32 - type: integer - quota: - format: string - type: string - type: object - type: array - type: object - type: array - type: object - type: object - versions: - - name: v1alpha2 - served: true - storage: true - - --- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - annotations: - "helm.sh/resource-policy": keep - labels: - app: mixer - chart: istio - heritage: Tiller - istio: rbac - package: istio.io.mixer - release: istio - name: rbacconfigs.rbac.istio.io - spec: - group: rbac.istio.io - names: - categories: - - istio-io - - rbac-istio-io - kind: RbacConfig - plural: rbacconfigs - singular: rbacconfig - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - description: 'Configuration for Role Based Access Control. See more details - at: https://istio.io/docs/reference/config/authorization/istio.rbac.v1alpha1.html' - properties: - enforcementMode: - enum: - - ENFORCED - - PERMISSIVE - type: string - exclusion: - description: A list of services or namespaces that should not be enforced - by Istio RBAC policies. - properties: - namespaces: - description: A list of namespaces. - items: - format: string - type: string - type: array - services: - description: A list of services. - items: - format: string - type: string - type: array - type: object - inclusion: - description: A list of services or namespaces that should be enforced - by Istio RBAC policies. - properties: - namespaces: - description: A list of namespaces. - items: - format: string - type: string - type: array - services: - description: A list of services. - items: - format: string - type: string - type: array - type: object - mode: - description: Istio RBAC mode. - enum: - - "OFF" - - "ON" - - ON_WITH_INCLUSION - - ON_WITH_EXCLUSION - type: string - type: object - type: object - versions: - - name: v1alpha1 - served: true - storage: true - - --- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - annotations: - "helm.sh/resource-policy": keep - labels: - app: mixer - chart: istio - heritage: Tiller - istio: core - package: istio.io.mixer - release: istio - name: rules.config.istio.io - spec: - group: config.istio.io - names: - categories: - - istio-io - - policy-istio-io - kind: rule - plural: rules - singular: rule - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - description: 'Describes the rules used to configure Mixer''s policy and - telemetry features. See more details at: https://istio.io/docs/reference/config/policy-and-telemetry/istio.policy.v1beta1.html' - properties: - actions: - description: The actions that will be executed when match evaluates - to `true`. - items: - properties: - handler: - description: Fully qualified name of the handler to invoke. - format: string - type: string - instances: - items: - format: string - type: string - type: array - name: - description: A handle to refer to the results of the action. - format: string - type: string - type: object - type: array - match: - description: Match is an attribute based predicate. - format: string - type: string - requestHeaderOperations: - items: - properties: - name: - description: Header name literal value. - format: string - type: string - operation: - description: Header operation type. - enum: - - REPLACE - - REMOVE - - APPEND - type: string - values: - description: Header value expressions. - items: - format: string - type: string - type: array - type: object - type: array - responseHeaderOperations: - items: - properties: - name: - description: Header name literal value. - format: string - type: string - operation: - description: Header operation type. - enum: - - REPLACE - - REMOVE - - APPEND - type: string - values: - description: Header value expressions. - items: - format: string - type: string - type: array - type: object - type: array - sampling: - properties: - random: - description: Provides filtering of actions based on random selection - per request. - properties: - attributeExpression: - description: Specifies an attribute expression to use to override - the numerator in the `percent_sampled` field. - format: string - type: string - percentSampled: - description: The default sampling rate, expressed as a percentage. - properties: - denominator: - description: Specifies the denominator. - enum: - - HUNDRED - - TEN_THOUSAND - type: string - numerator: - description: Specifies the numerator. - type: integer - type: object - useIndependentRandomness: - description: By default sampling will be based on the value - of the request header `x-request-id`. - type: boolean - type: object - rateLimit: - properties: - maxUnsampledEntries: - description: Number of entries to allow during the `sampling_duration` - before sampling is enforced. - format: int64 - type: integer - samplingDuration: - description: Window in which to enforce the sampling rate. - type: string - samplingRate: - description: The rate at which to sample entries once the unsampled - limit has been reached. - format: int64 - type: integer - type: object - type: object - type: object - type: object - versions: - - name: v1alpha2 - served: true - storage: true - - --- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - annotations: - "helm.sh/resource-policy": keep - labels: - app: istio-pilot - chart: istio - heritage: Tiller - release: istio - name: serviceentries.networking.istio.io - spec: - additionalPrinterColumns: - - JSONPath: .spec.hosts - description: The hosts associated with the ServiceEntry - name: Hosts - type: string - - JSONPath: .spec.location - description: Whether the service is external to the mesh or part of the mesh (MESH_EXTERNAL - or MESH_INTERNAL) - name: Location - type: string - - JSONPath: .spec.resolution - description: Service discovery mode for the hosts (NONE, STATIC, or DNS) - name: Resolution - type: string - - JSONPath: .metadata.creationTimestamp - description: |- - CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - name: Age - type: date - group: networking.istio.io - names: - categories: - - istio-io - - networking-istio-io - kind: ServiceEntry - listKind: ServiceEntryList - plural: serviceentries - shortNames: - - se - singular: serviceentry - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - description: 'Configuration affecting service registry. See more details - at: https://istio.io/docs/reference/config/networking/v1alpha3/service-entry.html' - properties: - addresses: - description: The virtual IP addresses associated with the service. - items: - format: string - type: string - type: array - endpoints: - description: One or more endpoints associated with the service. - items: - properties: - address: - format: string - type: string - labels: - additionalProperties: - format: string - type: string - description: One or more labels associated with the endpoint. - type: object - locality: - description: The locality associated with the endpoint. - format: string - type: string - network: - format: string - type: string - ports: - additionalProperties: - type: integer - description: Set of ports associated with the endpoint. - type: object - weight: - description: The load balancing weight associated with the endpoint. - type: integer - type: object - type: array - exportTo: - description: A list of namespaces to which this service is exported. - items: - format: string - type: string - type: array - hosts: - description: The hosts associated with the ServiceEntry. - items: - format: string - type: string - type: array - location: - enum: - - MESH_EXTERNAL - - MESH_INTERNAL - type: string - ports: - description: The ports associated with the external service. - items: - properties: - name: - description: Label assigned to the port. - format: string - type: string - number: - description: A valid non-negative integer port number. - type: integer - protocol: - description: The protocol exposed on the port. - format: string - type: string - type: object - type: array - resolution: - description: Service discovery mode for the hosts. - enum: - - NONE - - STATIC - - DNS - type: string - subjectAltNames: - items: - format: string - type: string - type: array - type: object - type: object - versions: - - name: v1alpha3 - served: true - storage: true - - --- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - annotations: - "helm.sh/resource-policy": keep - labels: - app: mixer - chart: istio - heritage: Tiller - istio: rbac - package: istio.io.mixer - release: istio - name: servicerolebindings.rbac.istio.io - spec: - additionalPrinterColumns: - - JSONPath: .spec.roleRef.name - description: The name of the ServiceRole object being referenced - name: Reference - type: string - - JSONPath: .metadata.creationTimestamp - description: |- - CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - name: Age - type: date - group: rbac.istio.io - names: - categories: - - istio-io - - rbac-istio-io - kind: ServiceRoleBinding - plural: servicerolebindings - singular: servicerolebinding - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - description: 'Configuration for Role Based Access Control. See more details - at: https://istio.io/docs/reference/config/authorization/istio.rbac.v1alpha1.html' - properties: - actions: - items: - properties: - constraints: - description: Optional. - items: - properties: - key: - description: Key of the constraint. - format: string - type: string - values: - description: List of valid values for the constraint. - items: - format: string - type: string - type: array - type: object - type: array - hosts: - items: - format: string - type: string - type: array - methods: - description: Optional. - items: - format: string - type: string - type: array - notHosts: - items: - format: string - type: string - type: array - notMethods: - items: - format: string - type: string - type: array - notPaths: - items: - format: string - type: string - type: array - notPorts: - items: - format: int32 - type: integer - type: array - paths: - description: Optional. - items: - format: string - type: string - type: array - ports: - items: - format: int32 - type: integer - type: array - services: - description: A list of service names. - items: - format: string - type: string - type: array - type: object - type: array - mode: - enum: - - ENFORCED - - PERMISSIVE - type: string - role: - format: string - type: string - roleRef: - description: Reference to the ServiceRole object. - properties: - kind: - description: The type of the role being referenced. - format: string - type: string - name: - description: The name of the ServiceRole object being referenced. - format: string - type: string - type: object - subjects: - description: List of subjects that are assigned the ServiceRole object. - items: - properties: - group: - format: string - type: string - groups: - items: - format: string - type: string - type: array - ips: - items: - format: string - type: string - type: array - names: - items: - format: string - type: string - type: array - namespaces: - items: - format: string - type: string - type: array - notGroups: - items: - format: string - type: string - type: array - notIps: - items: - format: string - type: string - type: array - notNames: - items: - format: string - type: string - type: array - notNamespaces: - items: - format: string - type: string - type: array - properties: - additionalProperties: - format: string - type: string - description: Optional. - type: object - user: - description: Optional. - format: string - type: string - type: object - type: array - type: object - type: object - versions: - - name: v1alpha1 - served: true - storage: true - - --- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - annotations: - "helm.sh/resource-policy": keep - labels: - app: mixer - chart: istio - heritage: Tiller - istio: rbac - package: istio.io.mixer - release: istio - name: serviceroles.rbac.istio.io - spec: - group: rbac.istio.io - names: - categories: - - istio-io - - rbac-istio-io - kind: ServiceRole - plural: serviceroles - singular: servicerole - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - description: 'Configuration for Role Based Access Control. See more details - at: https://istio.io/docs/reference/config/authorization/istio.rbac.v1alpha1.html' - properties: - rules: - description: The set of access rules (permissions) that the role has. - items: - properties: - constraints: - description: Optional. - items: - properties: - key: - description: Key of the constraint. - format: string - type: string - values: - description: List of valid values for the constraint. - items: - format: string - type: string - type: array - type: object - type: array - hosts: - items: - format: string - type: string - type: array - methods: - description: Optional. - items: - format: string - type: string - type: array - notHosts: - items: - format: string - type: string - type: array - notMethods: - items: - format: string - type: string - type: array - notPaths: - items: - format: string - type: string - type: array - notPorts: - items: - format: int32 - type: integer - type: array - paths: - description: Optional. - items: - format: string - type: string - type: array - ports: - items: - format: int32 - type: integer - type: array - services: - description: A list of service names. - items: - format: string - type: string - type: array - type: object - type: array - type: object - type: object - versions: - - name: v1alpha1 - served: true - storage: true - - --- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - annotations: - "helm.sh/resource-policy": keep - labels: - app: istio-pilot - chart: istio - heritage: Tiller - release: istio - name: virtualservices.networking.istio.io - spec: - additionalPrinterColumns: - - JSONPath: .spec.gateways - description: The names of gateways and sidecars that should apply these routes - name: Gateways - type: string - - JSONPath: .spec.hosts - description: The destination hosts to which traffic is being sent - name: Hosts - type: string - - JSONPath: .metadata.creationTimestamp - description: |- - CreationTimestamp is a timestamp representing the server time when this object was created. It is not guaranteed to be set in happens-before order across separate operations. Clients may not set this value. It is represented in RFC3339 form and is in UTC. - Populated by the system. Read-only. Null for lists. More info: https://git.k8s.io/community/contributors/devel/api-conventions.md#metadata - name: Age - type: date - group: networking.istio.io - names: - categories: - - istio-io - - networking-istio-io - kind: VirtualService - listKind: VirtualServiceList - plural: virtualservices - shortNames: - - vs - singular: virtualservice - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - description: 'Configuration affecting label/content routing, sni routing, - etc. See more details at: https://istio.io/docs/reference/config/networking/v1alpha3/virtual-service.html' - properties: - exportTo: - description: A list of namespaces to which this virtual service is exported. - items: - format: string - type: string - type: array - gateways: - description: The names of gateways and sidecars that should apply these - routes. - items: - format: string - type: string - type: array - hosts: - description: The destination hosts to which traffic is being sent. - items: - format: string - type: string - type: array - http: - description: An ordered list of route rules for HTTP traffic. - items: - properties: - appendHeaders: - additionalProperties: - format: string - type: string - type: object - appendRequestHeaders: - additionalProperties: - format: string - type: string - type: object - appendResponseHeaders: - additionalProperties: - format: string - type: string - type: object - corsPolicy: - description: Cross-Origin Resource Sharing policy (CORS). - properties: - allowCredentials: - nullable: true - type: boolean - allowHeaders: - items: - format: string - type: string - type: array - allowMethods: - description: List of HTTP methods allowed to access the resource. - items: - format: string - type: string - type: array - allowOrigin: - description: The list of origins that are allowed to perform - CORS requests. - items: - format: string - type: string - type: array - exposeHeaders: - items: - format: string - type: string - type: array - maxAge: - type: string - type: object - fault: - description: Fault injection policy to apply on HTTP traffic at - the client side. - properties: - abort: - oneOf: - - properties: - percent: {} - required: - - httpStatus - - properties: - percent: {} - required: - - grpcStatus - - properties: - percent: {} - required: - - http2Error - properties: - grpcStatus: - format: string - type: string - http2Error: - format: string - type: string - httpStatus: - description: HTTP status code to use to abort the Http - request. - format: int32 - type: integer - percent: - description: Percentage of requests to be aborted with - the error code provided (0-100). - format: int32 - type: integer - percentage: - description: Percentage of requests to be aborted with - the error code provided. - properties: - value: - format: double - type: number - type: object - type: object - delay: - oneOf: - - properties: - percent: {} - required: - - fixedDelay - - properties: - percent: {} - required: - - exponentialDelay - properties: - exponentialDelay: - type: string - fixedDelay: - description: Add a fixed delay before forwarding the request. - type: string - percent: - description: Percentage of requests on which the delay - will be injected (0-100). - format: int32 - type: integer - percentage: - description: Percentage of requests on which the delay - will be injected. - properties: - value: - format: double - type: number - type: object - type: object - type: object - headers: - properties: - request: - properties: - add: - additionalProperties: - format: string - type: string - type: object - remove: - items: - format: string - type: string - type: array - set: - additionalProperties: - format: string - type: string - type: object - type: object - response: - properties: - add: - additionalProperties: - format: string - type: string - type: object - remove: - items: - format: string - type: string - type: array - set: - additionalProperties: - format: string - type: string - type: object - type: object - type: object - match: - items: - properties: - authority: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - regex - properties: - exact: - format: string - type: string - prefix: - format: string - type: string - regex: - format: string - type: string - type: object - gateways: - items: - format: string - type: string - type: array - headers: - additionalProperties: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - regex - properties: - exact: - format: string - type: string - prefix: - format: string - type: string - regex: - format: string - type: string - type: object - type: object - ignoreUriCase: - description: Flag to specify whether the URI matching should - be case-insensitive. - type: boolean - method: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - regex - properties: - exact: - format: string - type: string - prefix: - format: string - type: string - regex: - format: string - type: string - type: object - name: - description: The name assigned to a match. - format: string - type: string - port: - description: Specifies the ports on the host that is being - addressed. - type: integer - queryParams: - additionalProperties: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - regex - properties: - exact: - format: string - type: string - prefix: - format: string - type: string - regex: - format: string - type: string - type: object - description: Query parameters for matching. - type: object - scheme: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - regex - properties: - exact: - format: string - type: string - prefix: - format: string - type: string - regex: - format: string - type: string - type: object - sourceLabels: - additionalProperties: - format: string - type: string - type: object - uri: - oneOf: - - required: - - exact - - required: - - prefix - - required: - - regex - properties: - exact: - format: string - type: string - prefix: - format: string - type: string - regex: - format: string - type: string - type: object - type: object - type: array - mirror: - properties: - host: - description: The name of a service from the service registry. - format: string - type: string - port: - description: Specifies the port on the host that is being - addressed. - properties: - number: - type: integer - type: object - subset: - description: The name of a subset within the service. - format: string - type: string - type: object - mirror_percent: - description: Percentage of the traffic to be mirrored by the `mirror` - field. - nullable: true - type: integer - mirrorPercent: - description: Percentage of the traffic to be mirrored by the `mirror` - field. - nullable: true - type: integer - name: - description: The name assigned to the route for debugging purposes. - format: string - type: string - redirect: - description: A http rule can either redirect or forward (default) - traffic. - properties: - authority: - format: string - type: string - redirectCode: - type: integer - uri: - format: string - type: string - type: object - removeRequestHeaders: - items: - format: string - type: string - type: array - removeResponseHeaders: - items: - format: string - type: string - type: array - retries: - description: Retry policy for HTTP requests. - properties: - attempts: - description: Number of retries for a given request. - format: int32 - type: integer - perTryTimeout: - description: Timeout per retry attempt for a given request. - type: string - retryOn: - description: Specifies the conditions under which retry takes - place. - format: string - type: string - type: object - rewrite: - description: Rewrite HTTP URIs and Authority headers. - properties: - authority: - description: rewrite the Authority/Host header with this value. - format: string - type: string - uri: - format: string - type: string - type: object - route: - description: A http rule can either redirect or forward (default) - traffic. - items: - properties: - appendRequestHeaders: - additionalProperties: - format: string - type: string - description: Use of `append_request_headers` is deprecated. - type: object - appendResponseHeaders: - additionalProperties: - format: string - type: string - description: Use of `append_response_headers` is deprecated. - type: object - destination: - properties: - host: - description: The name of a service from the service - registry. - format: string - type: string - port: - description: Specifies the port on the host that is - being addressed. - properties: - number: - type: integer - type: object - subset: - description: The name of a subset within the service. - format: string - type: string - type: object - headers: - properties: - request: - properties: - add: - additionalProperties: - format: string - type: string - type: object - remove: - items: - format: string - type: string - type: array - set: - additionalProperties: - format: string - type: string - type: object - type: object - response: - properties: - add: - additionalProperties: - format: string - type: string - type: object - remove: - items: - format: string - type: string - type: array - set: - additionalProperties: - format: string - type: string - type: object - type: object - type: object - removeRequestHeaders: - description: Use of `remove_request_headers` is deprecated. - items: - format: string - type: string - type: array - removeResponseHeaders: - description: Use of `remove_response_header` is deprecated. - items: - format: string - type: string - type: array - weight: - format: int32 - type: integer - type: object - type: array - timeout: - description: Timeout for HTTP requests. - type: string - websocketUpgrade: - description: Deprecated. - type: boolean - type: object - type: array - tcp: - description: An ordered list of route rules for opaque TCP traffic. - items: - properties: - match: - items: - properties: - destinationSubnets: - description: IPv4 or IPv6 ip addresses of destination with - optional subnet. - items: - format: string - type: string - type: array - gateways: - description: Names of gateways where the rule should be - applied to. - items: - format: string - type: string - type: array - port: - description: Specifies the port on the host that is being - addressed. - type: integer - sourceLabels: - additionalProperties: - format: string - type: string - type: object - sourceSubnet: - description: IPv4 or IPv6 ip address of source with optional - subnet. - format: string - type: string - type: object - type: array - route: - description: The destination to which the connection should be - forwarded to. - items: - properties: - destination: - properties: - host: - description: The name of a service from the service - registry. - format: string - type: string - port: - description: Specifies the port on the host that is - being addressed. - properties: - number: - type: integer - type: object - subset: - description: The name of a subset within the service. - format: string - type: string - type: object - weight: - format: int32 - type: integer - type: object - type: array - type: object - type: array - tls: - items: - properties: - match: - items: - properties: - destinationSubnets: - description: IPv4 or IPv6 ip addresses of destination with - optional subnet. - items: - format: string - type: string - type: array - gateways: - description: Names of gateways where the rule should be - applied to. - items: - format: string - type: string - type: array - port: - description: Specifies the port on the host that is being - addressed. - type: integer - sniHosts: - description: SNI (server name indicator) to match on. - items: - format: string - type: string - type: array - sourceLabels: - additionalProperties: - format: string - type: string - type: object - sourceSubnet: - description: IPv4 or IPv6 ip address of source with optional - subnet. - format: string - type: string - type: object - type: array - route: - description: The destination to which the connection should be - forwarded to. - items: - properties: - destination: - properties: - host: - description: The name of a service from the service - registry. - format: string - type: string - port: - description: Specifies the port on the host that is - being addressed. - properties: - number: - type: integer - type: object - subset: - description: The name of a subset within the service. - format: string - type: string - type: object - weight: - format: int32 - type: integer - type: object - type: array - type: object - type: array - type: object - type: object - versions: - - name: v1alpha3 - served: true - storage: true - - --- - kind: CustomResourceDefinition - apiVersion: apiextensions.k8s.io/v1beta1 - metadata: - name: adapters.config.istio.io - labels: - app: mixer - package: adapter - istio: mixer-adapter - chart: istio - heritage: Tiller - release: istio - annotations: - "helm.sh/resource-policy": keep - spec: - group: config.istio.io - names: - kind: adapter - plural: adapters - singular: adapter - categories: - - istio-io - - policy-istio-io - scope: Namespaced - subresources: - status: {} - versions: - - name: v1alpha2 - served: true - storage: true - - --- - kind: CustomResourceDefinition - apiVersion: apiextensions.k8s.io/v1beta1 - metadata: - name: instances.config.istio.io - labels: - app: mixer - package: instance - istio: mixer-instance - chart: istio - heritage: Tiller - release: istio - annotations: - "helm.sh/resource-policy": keep - spec: - group: config.istio.io - names: - kind: instance - plural: instances - singular: instance - categories: - - istio-io - - policy-istio-io - scope: Namespaced - subresources: - status: {} - versions: - - name: v1alpha2 - served: true - storage: true - - --- - kind: CustomResourceDefinition - apiVersion: apiextensions.k8s.io/v1beta1 - metadata: - name: templates.config.istio.io - labels: - app: mixer - package: template - istio: mixer-template - chart: istio - heritage: Tiller - release: istio - annotations: - "helm.sh/resource-policy": keep - spec: - group: config.istio.io - names: - kind: template - plural: templates - singular: template - categories: - - istio-io - - policy-istio-io - scope: Namespaced - subresources: - status: {} - versions: - - name: v1alpha2 - served: true - storage: true - - --- - kind: CustomResourceDefinition - apiVersion: apiextensions.k8s.io/v1beta1 - metadata: - name: handlers.config.istio.io - labels: - app: mixer - package: handler - istio: mixer-handler - chart: istio - heritage: Tiller - release: istio - annotations: - "helm.sh/resource-policy": keep - spec: - group: config.istio.io - names: - kind: handler - plural: handlers - singular: handler - categories: - - istio-io - - policy-istio-io - scope: Namespaced - subresources: - status: {} - versions: - - name: v1alpha2 - served: true - storage: true - - --- ---- -# Source: istio-init/templates/configmap-crd-11.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: istio-system - name: istio-crd-11 -data: - crd-11.yaml: |- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - annotations: - "helm.sh/resource-policy": keep - labels: - app: istio-pilot - chart: istio - heritage: Tiller - release: istio - name: sidecars.networking.istio.io - spec: - group: networking.istio.io - names: - categories: - - istio-io - - networking-istio-io - kind: Sidecar - plural: sidecars - singular: sidecar - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - description: 'Configuration affecting network reachability of a sidecar. - See more details at: https://istio.io/docs/reference/config/networking/v1alpha3/sidecar.html' - properties: - egress: - items: - properties: - bind: - format: string - type: string - captureMode: - enum: - - DEFAULT - - IPTABLES - - NONE - type: string - hosts: - items: - format: string - type: string - type: array - port: - description: The port associated with the listener. - properties: - name: - description: Label assigned to the port. - format: string - type: string - number: - description: A valid non-negative integer port number. - type: integer - protocol: - description: The protocol exposed on the port. - format: string - type: string - type: object - type: object - type: array - ingress: - items: - properties: - bind: - description: The ip to which the listener should be bound. - format: string - type: string - captureMode: - enum: - - DEFAULT - - IPTABLES - - NONE - type: string - defaultEndpoint: - format: string - type: string - port: - description: The port associated with the listener. - properties: - name: - description: Label assigned to the port. - format: string - type: string - number: - description: A valid non-negative integer port number. - type: integer - protocol: - description: The protocol exposed on the port. - format: string - type: string - type: object - type: object - type: array - outboundTrafficPolicy: - description: This allows to configure the outbound traffic policy. - properties: - mode: - enum: - - REGISTRY_ONLY - - ALLOW_ANY - type: string - type: object - workloadSelector: - properties: - labels: - additionalProperties: - format: string - type: string - type: object - type: object - type: object - type: object - versions: - - name: v1alpha3 - served: true - storage: true - - --- ---- -# Source: istio-init/templates/configmap-crd-14.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - namespace: istio-system - name: istio-crd-14 -data: - crd-14.yaml: |- - apiVersion: apiextensions.k8s.io/v1beta1 - kind: CustomResourceDefinition - metadata: - labels: - app: istio-pilot - heritage: Tiller - istio: security - release: istio - name: authorizationpolicies.security.istio.io - spec: - group: security.istio.io - names: - categories: - - istio-io - - security-istio-io - kind: AuthorizationPolicy - plural: authorizationpolicies - singular: authorizationpolicy - scope: Namespaced - subresources: - status: {} - validation: - openAPIV3Schema: - properties: - spec: - description: 'Configuration for access control on workloads. See more details - at: https://istio.io/docs/reference/config/security/v1beta1/authorization-policy.html' - properties: - rules: - description: Optional. - items: - properties: - from: - description: Optional. - items: - properties: - source: - description: Source specifies the source of a request. - properties: - ipBlocks: - description: Optional. - items: - format: string - type: string - type: array - namespaces: - description: Optional. - items: - format: string - type: string - type: array - principals: - description: Optional. - items: - format: string - type: string - type: array - requestPrincipals: - description: Optional. - items: - format: string - type: string - type: array - type: object - type: object - type: array - to: - description: Optional. - items: - properties: - operation: - description: Operation specifies the operation of a request. - properties: - hosts: - description: Optional. - items: - format: string - type: string - type: array - methods: - description: Optional. - items: - format: string - type: string - type: array - paths: - description: Optional. - items: - format: string - type: string - type: array - ports: - description: Optional. - items: - format: string - type: string - type: array - type: object - type: object - type: array - when: - description: Optional. - items: - properties: - key: - description: The name of an Istio attribute. - format: string - type: string - values: - description: The allowed values for the attribute. - items: - format: string - type: string - type: array - type: object - type: array - type: object - type: array - selector: - description: Optional. - properties: - matchLabels: - additionalProperties: - format: string - type: string - type: object - type: object - type: object - type: object - versions: - - name: v1beta1 - served: true - storage: true - - --- ---- -# Source: istio-init/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-init-service-account - namespace: istio-system - labels: - app: istio-init - istio: init ---- -# Source: istio-init/templates/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: istio-init-istio-system - labels: - app: istio-init - istio: init -rules: -- apiGroups: ["apiextensions.k8s.io"] - resources: ["customresourcedefinitions"] - verbs: ["create", "get", "list", "watch", "patch"] ---- -# Source: istio-init/templates/clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: istio-init-admin-role-binding-istio-system - labels: - app: istio-init - istio: init -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: istio-init-istio-system -subjects: - - kind: ServiceAccount - name: istio-init-service-account - namespace: istio-system ---- -# Source: istio-init/templates/job-crd-10.yaml -apiVersion: batch/v1 -kind: Job -metadata: - namespace: istio-system - name: istio-init-crd-10-1.4.3 -spec: - template: - metadata: - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-init-service-account - containers: - - name: istio-init-crd-10 - image: "docker.io/istio/kubectl:1.4.3" - imagePullPolicy: IfNotPresent - resources: - limits: - cpu: 100m - memory: 200Mi - requests: - cpu: 10m - memory: 50Mi - volumeMounts: - - name: crd-10 - mountPath: /etc/istio/crd-10 - readOnly: true - command: ["kubectl", "apply", "-f", "/etc/istio/crd-10/crd-10.yaml"] - volumes: - - name: crd-10 - configMap: - name: istio-crd-10 - restartPolicy: OnFailure ---- -# Source: istio-init/templates/job-crd-11.yaml -apiVersion: batch/v1 -kind: Job -metadata: - namespace: istio-system - name: istio-init-crd-11-1.4.3 -spec: - template: - metadata: - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-init-service-account - containers: - - name: istio-init-crd-11 - image: "docker.io/istio/kubectl:1.4.3" - imagePullPolicy: IfNotPresent - resources: - limits: - cpu: 100m - memory: 200Mi - requests: - cpu: 10m - memory: 50Mi - volumeMounts: - - name: crd-11 - mountPath: /etc/istio/crd-11 - readOnly: true - command: ["kubectl", "apply", "-f", "/etc/istio/crd-11/crd-11.yaml"] - volumes: - - name: crd-11 - configMap: - name: istio-crd-11 - restartPolicy: OnFailure ---- -# Source: istio-init/templates/job-crd-14.yaml -apiVersion: batch/v1 -kind: Job -metadata: - namespace: istio-system - name: istio-init-crd-14-1.4.3 -spec: - template: - metadata: - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-init-service-account - containers: - - name: istio-init-crd-14 - image: "docker.io/istio/kubectl:1.4.3" - imagePullPolicy: IfNotPresent - resources: - limits: - cpu: 100m - memory: 200Mi - requests: - cpu: 10m - memory: 50Mi - volumeMounts: - - name: crd-14 - mountPath: /etc/istio/crd-14 - readOnly: true - command: ["kubectl", "apply", "-f", "/etc/istio/crd-14/crd-14.yaml"] - volumes: - - name: crd-14 - configMap: - name: istio-crd-14 - restartPolicy: OnFailure diff --git a/third_party/istio-1.4.3/istio-minimal.yaml b/third_party/istio-1.4.3/istio-minimal.yaml deleted file mode 100644 index 33157feac72..00000000000 --- a/third_party/istio-1.4.3/istio-minimal.yaml +++ /dev/null @@ -1,960 +0,0 @@ ---- -# PATCH #1: Creating the istio-system namespace. -apiVersion: v1 -kind: Namespace -metadata: - name: istio-system - labels: - istio-injection: disabled -# PATCH #1 ends. ---- -# Source: istio/templates/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: istio - namespace: istio-system - labels: - app: istio - chart: istio - heritage: Helm - release: RELEASE-NAME -data: - mesh: |- - # Set the following variable to true to disable policy checks by Mixer. - # Note that metrics will still be reported to Mixer. - disablePolicyChecks: true - - disableMixerHttpReports: false - # reportBatchMaxEntries is the number of requests that are batched before telemetry data is sent to the mixer server - reportBatchMaxEntries: 100 - # reportBatchMaxTime is the max waiting time before the telemetry data of a request is sent to the mixer server - reportBatchMaxTime: 1s - - # Set enableTracing to false to disable request tracing. - enableTracing: true - - # Set accessLogFile to empty string to disable access log. - accessLogFile: "/dev/stdout" - - # If accessLogEncoding is TEXT, value will be used directly as the log format - # example: "[%START_TIME%] %REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\n" - # If AccessLogEncoding is JSON, value will be parsed as map[string]string - # example: '{"start_time": "%START_TIME%", "req_method": "%REQ(:METHOD)%"}' - # Leave empty to use default log format - accessLogFormat: "" - - # Set accessLogEncoding to JSON or TEXT to configure sidecar access log - accessLogEncoding: 'JSON' - - enableEnvoyAccessLogService: false - # Let Pilot give ingresses the public IP of the Istio ingressgateway - ingressService: istio-ingressgateway - - # Default connect timeout for dynamic clusters generated by Pilot and returned via XDS - connectTimeout: 10s - - # Automatic protocol detection uses a set of heuristics to - # determine whether the connection is using TLS or not (on the - # server side), as well as the application protocol being used - # (e.g., http vs tcp). These heuristics rely on the client sending - # the first bits of data. For server first protocols like MySQL, - # MongoDB, etc., Envoy will timeout on the protocol detection after - # the specified period, defaulting to non mTLS plain TCP - # traffic. Set this field to tweak the period that Envoy will wait - # for the client to send the first bits of data. (MUST BE >=1ms) - protocolDetectionTimeout: 100ms - - # DNS refresh rate for Envoy clusters of type STRICT_DNS - dnsRefreshRate: 300s - - # Unix Domain Socket through which envoy communicates with NodeAgent SDS to get - # key/cert for mTLS. Use secret-mount files instead of SDS if set to empty. - sdsUdsPath: "" - - # The trust domain corresponds to the trust root of a system. - # Refer to https://github.com/spiffe/spiffe/blob/master/standards/SPIFFE-ID.md#21-trust-domain - trustDomain: "" - - # The trust domain aliases represent the aliases of trust_domain. - # For example, if we have - # trustDomain: td1 - # trustDomainAliases: [“td2”, "td3"] - # Any service with the identity "td1/ns/foo/sa/a-service-account", "td2/ns/foo/sa/a-service-account", - # or "td3/ns/foo/sa/a-service-account" will be treated the same in the Istio mesh. - trustDomainAliases: - - # If true, automatically configure client side mTLS settings to match the corresponding service's - # server side mTLS authentication policy, when destination rule for that service does not specify - # TLS settings. - enableAutoMtls: false - - # Set the default behavior of the sidecar for handling outbound traffic from the application: - # ALLOW_ANY - outbound traffic to unknown destinations will be allowed, in case there are no - # services or ServiceEntries for the destination port - # REGISTRY_ONLY - restrict outbound traffic to services defined in the service registry as well - # as those defined through ServiceEntries - outboundTrafficPolicy: - mode: ALLOW_ANY - localityLbSetting: - enabled: true - # The namespace to treat as the administrative root namespace for istio - # configuration. - rootNamespace: istio-system - - # Configures DNS certificates provisioned through Chiron linked into Pilot. - certificates: - [] - - defaultConfig: - # - # TCP connection timeout between Envoy & the application, and between Envoys. Used for static clusters - # defined in Envoy's configuration file - connectTimeout: 10s - # - ### ADVANCED SETTINGS ############# - # Where should envoy's configuration be stored in the istio-proxy container - configPath: "/etc/istio/proxy" - binaryPath: "/usr/local/bin/envoy" - # The pseudo service name used for Envoy. - serviceCluster: istio-proxy - # These settings that determine how long an old Envoy - # process should be kept alive after an occasional reload. - drainDuration: 45s - parentShutdownDuration: 1m0s - # - # The mode used to redirect inbound connections to Envoy. This setting - # has no effect on outbound traffic: iptables REDIRECT is always used for - # outbound connections. - # If "REDIRECT", use iptables REDIRECT to NAT and redirect to Envoy. - # The "REDIRECT" mode loses source addresses during redirection. - # If "TPROXY", use iptables TPROXY to redirect to Envoy. - # The "TPROXY" mode preserves both the source and destination IP - # addresses and ports, so that they can be used for advanced filtering - # and manipulation. - # The "TPROXY" mode also configures the sidecar to run with the - # CAP_NET_ADMIN capability, which is required to use TPROXY. - #interceptionMode: REDIRECT - # - # Port where Envoy listens (on local host) for admin commands - # You can exec into the istio-proxy container in a pod and - # curl the admin port (curl http://localhost:15000/) to obtain - # diagnostic information from Envoy. See - # https://lyft.github.io/envoy/docs/operations/admin.html - # for more details - proxyAdminPort: 15000 - # - # Set concurrency to a specific number to control the number of Proxy worker threads. - # If set to 0 (default), then start worker thread for each CPU thread/core. - concurrency: 2 - # - tracing: - zipkin: - # Address of the Zipkin collector - address: zipkin.istio-system:9411 - # - # Mutual TLS authentication between sidecars and istio control plane. - controlPlaneAuthPolicy: NONE - # - # Address where istio Pilot service is running - discoveryAddress: istio-pilot.istio-system:15010 - - # Configuration file for the mesh networks to be used by the Split Horizon EDS. - meshNetworks: |- - networks: {} ---- -# Source: istio/charts/gateways/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-ingressgateway-service-account - namespace: istio-system - labels: - app: istio-ingressgateway - chart: gateways - heritage: Helm - release: RELEASE-NAME ---- -# Source: istio/charts/gateways/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: cluster-local-gateway-service-account - namespace: istio-system - labels: - app: cluster-local-gateway - chart: gateways - heritage: Helm - release: RELEASE-NAME ---- -# Source: istio/charts/pilot/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-pilot-service-account - namespace: istio-system - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME ---- -# Source: istio/templates/serviceaccount.yaml -apiVersion: v1 -kind: ServiceAccount -metadata: - name: istio-multi - namespace: istio-system ---- -# Source: istio/charts/pilot/templates/clusterrole.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: istio-pilot-istio-system - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME -rules: -- apiGroups: ["config.istio.io"] - resources: ["*"] - verbs: ["*"] -- apiGroups: ["rbac.istio.io"] - resources: ["*"] - verbs: ["get", "watch", "list"] -- apiGroups: ["security.istio.io"] - resources: ["*"] - verbs: ["get", "watch", "list"] -- apiGroups: ["networking.istio.io"] - resources: ["*"] - verbs: ["*"] -- apiGroups: ["authentication.istio.io"] - resources: ["*"] - verbs: ["*"] -- apiGroups: ["apiextensions.k8s.io"] - resources: ["customresourcedefinitions"] - verbs: ["*"] -- apiGroups: ["extensions"] - resources: ["ingresses", "ingresses/status"] - verbs: ["*"] -- apiGroups: [""] - resources: ["configmaps"] - verbs: ["create", "get", "list", "watch", "update"] -- apiGroups: [""] - resources: ["endpoints", "pods", "services", "namespaces", "nodes"] - verbs: ["get", "list", "watch"] -- apiGroups: [""] - resources: ["secrets"] - verbs: ["create", "get", "watch", "list", "update", "delete"] -- apiGroups: ["certificates.k8s.io"] - resources: - - "certificatesigningrequests" - - "certificatesigningrequests/approval" - - "certificatesigningrequests/status" - verbs: ["update", "create", "get", "delete"] ---- -# Source: istio/templates/clusterrole.yaml -kind: ClusterRole -apiVersion: rbac.authorization.k8s.io/v1 -metadata: - name: istio-reader -rules: - - apiGroups: [''] - resources: ['nodes', 'pods', 'services', 'endpoints', "replicationcontrollers"] - verbs: ['get', 'watch', 'list'] - - apiGroups: ["extensions", "apps"] - resources: ["replicasets"] - verbs: ["get", "list", "watch"] ---- -# Source: istio/charts/pilot/templates/clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: istio-pilot-istio-system - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: istio-pilot-istio-system -subjects: - - kind: ServiceAccount - name: istio-pilot-service-account - namespace: istio-system ---- -# Source: istio/templates/clusterrolebinding.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: istio-multi - labels: - chart: istio-1.4.3 -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: istio-reader -subjects: -- kind: ServiceAccount - name: istio-multi - namespace: istio-system ---- -# Source: istio/charts/gateways/templates/role.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: Role -metadata: - name: istio-ingressgateway-sds - namespace: istio-system -rules: -- apiGroups: [""] - resources: ["secrets"] - verbs: ["get", "watch", "list"] ---- -# Source: istio/charts/gateways/templates/rolebindings.yaml -apiVersion: rbac.authorization.k8s.io/v1 -kind: RoleBinding -metadata: - name: istio-ingressgateway-sds - namespace: istio-system -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: Role - name: istio-ingressgateway-sds -subjects: -- kind: ServiceAccount - name: istio-ingressgateway-service-account ---- -# Source: istio/charts/gateways/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: cluster-local-gateway - namespace: istio-system - annotations: - labels: - chart: gateways - heritage: Helm - release: RELEASE-NAME - app: cluster-local-gateway - istio: cluster-local-gateway -spec: - type: ClusterIP - selector: - release: RELEASE-NAME - app: cluster-local-gateway - istio: cluster-local-gateway - ports: - - - name: status-port - port: 15020 - - - name: http2 - port: 80 - - - name: https - port: 443 ---- -# Source: istio/charts/gateways/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: istio-ingressgateway - namespace: istio-system - annotations: - labels: - chart: gateways - heritage: Helm - release: RELEASE-NAME - app: istio-ingressgateway - istio: ingressgateway -spec: - type: LoadBalancer - selector: - release: RELEASE-NAME - app: istio-ingressgateway - istio: ingressgateway - ports: - - - name: status-port - port: 15020 - - - name: http2 - port: 80 - - - name: https - port: 443 ---- -# Source: istio/charts/pilot/templates/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: istio-pilot - namespace: istio-system - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME - istio: pilot -spec: - ports: - - port: 15010 - name: grpc-xds # direct - - port: 15011 - name: https-xds # mTLS - - port: 8080 - name: http-legacy-discovery # direct - - port: 15014 - name: http-monitoring - selector: - istio: pilot ---- -# Source: istio/charts/gateways/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: istio-ingressgateway - namespace: istio-system - labels: - app: istio-ingressgateway - chart: gateways - heritage: Helm - istio: ingressgateway - release: RELEASE-NAME -spec: - replicas: 1 - selector: - matchLabels: - app: istio-ingressgateway - istio: ingressgateway - strategy: - rollingUpdate: - maxSurge: 100% - maxUnavailable: 25% - template: - metadata: - labels: - app: istio-ingressgateway - chart: gateways - heritage: Helm - istio: ingressgateway - release: RELEASE-NAME - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-ingressgateway-service-account - containers: - - name: ingress-sds - image: "docker.io/istio/node-agent-k8s:1.4.3" - imagePullPolicy: IfNotPresent - resources: - limits: - cpu: 2000m - memory: 1024Mi - requests: - cpu: 100m - memory: 128Mi - env: - - name: "ENABLE_WORKLOAD_SDS" - value: "false" - - name: "ENABLE_INGRESS_GATEWAY_SDS" - value: "true" - - name: "INGRESS_GATEWAY_NAMESPACE" - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - volumeMounts: - - name: ingressgatewaysdsudspath - mountPath: /var/run/ingress_gateway - - name: istio-proxy - image: "docker.io/istio/proxyv2:1.4.3" - imagePullPolicy: IfNotPresent - ports: - - containerPort: 15020 - - containerPort: 80 - - containerPort: 443 - - containerPort: 15090 - protocol: TCP - name: http-envoy-prom - args: - - proxy - - router - - --domain - - $(POD_NAMESPACE).svc.cluster.local - - --log_output_level=default:info - - --drainDuration - - '45s' #drainDuration - - --parentShutdownDuration - - '1m0s' #parentShutdownDuration - - --connectTimeout - - '10s' #connectTimeout - - --serviceCluster - - istio-ingressgateway - - --zipkinAddress - - zipkin:9411 - - --proxyAdminPort - - "15000" - - --statusPort - - "15020" - - --controlPlaneAuthPolicy - - NONE - - --discoveryAddress - - istio-pilot:15010 - readinessProbe: - failureThreshold: 30 - httpGet: - path: /healthz/ready - port: 15020 - scheme: HTTP - initialDelaySeconds: 1 - periodSeconds: 2 - successThreshold: 1 - timeoutSeconds: 1 - resources: - limits: - cpu: 2000m - memory: 1024Mi - requests: - cpu: 100m - memory: 128Mi - env: - - name: NODE_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: spec.nodeName - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: INSTANCE_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.podIP - - name: HOST_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.hostIP - - name: SERVICE_ACCOUNT - valueFrom: - fieldRef: - fieldPath: spec.serviceAccountName - - name: ISTIO_META_POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: ISTIO_META_CONFIG_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: ISTIO_METAJSON_LABELS - value: | - {"app":"istio-ingressgateway","chart":"gateways","heritage":"Helm","istio":"ingressgateway","release":"RELEASE-NAME"} - - name: ISTIO_META_CLUSTER_ID - value: "Kubernetes" - - name: SDS_ENABLED - value: "false" - - name: ISTIO_META_WORKLOAD_NAME - value: istio-ingressgateway - - name: ISTIO_META_OWNER - value: kubernetes://apis/apps/v1/namespaces/istio-system/deployments/istio-ingressgateway - - name: ISTIO_META_USER_SDS - value: "true" - - name: ISTIO_META_ROUTER_MODE - value: sni-dnat - - - volumeMounts: - - name: ingressgatewaysdsudspath - mountPath: /var/run/ingress_gateway - - name: istio-certs - mountPath: /etc/certs - readOnly: true - - name: ingressgateway-certs - mountPath: "/etc/istio/ingressgateway-certs" - readOnly: true - - name: ingressgateway-ca-certs - mountPath: "/etc/istio/ingressgateway-ca-certs" - readOnly: true - volumes: - - name: ingressgatewaysdsudspath - emptyDir: {} - - name: istio-certs - secret: - secretName: istio.istio-ingressgateway-service-account - optional: true - - name: ingressgateway-certs - secret: - secretName: "istio-ingressgateway-certs" - optional: true - - name: ingressgateway-ca-certs - secret: - secretName: "istio-ingressgateway-ca-certs" - optional: true - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - "ppc64le" - - "s390x" - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "ppc64le" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "s390x" ---- -# Source: istio/charts/gateways/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: cluster-local-gateway - namespace: istio-system - labels: - app: cluster-local-gateway - chart: gateways - heritage: Helm - istio: cluster-local-gateway - release: RELEASE-NAME -spec: - replicas: 1 - selector: - matchLabels: - app: cluster-local-gateway - istio: cluster-local-gateway - strategy: - rollingUpdate: - maxSurge: - maxUnavailable: - template: - metadata: - labels: - app: cluster-local-gateway - chart: gateways - heritage: Helm - istio: cluster-local-gateway - release: RELEASE-NAME - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: cluster-local-gateway-service-account - containers: - - name: istio-proxy - image: "docker.io/istio/proxyv2:1.4.3" - imagePullPolicy: IfNotPresent - ports: - - containerPort: 15020 - - containerPort: 80 - - containerPort: 443 - - containerPort: 15090 - protocol: TCP - name: http-envoy-prom - args: - - proxy - - router - - --domain - - $(POD_NAMESPACE).svc.cluster.local - - --log_output_level=default:info - - --drainDuration - - '45s' #drainDuration - - --parentShutdownDuration - - '1m0s' #parentShutdownDuration - - --connectTimeout - - '10s' #connectTimeout - - --serviceCluster - - cluster-local-gateway - - --zipkinAddress - - zipkin:9411 - - --proxyAdminPort - - "15000" - - --statusPort - - "15020" - - --controlPlaneAuthPolicy - - NONE - - --discoveryAddress - - istio-pilot:15010 - readinessProbe: - failureThreshold: 30 - httpGet: - path: /healthz/ready - port: 15020 - scheme: HTTP - initialDelaySeconds: 1 - periodSeconds: 2 - successThreshold: 1 - timeoutSeconds: 1 - resources: - requests: - cpu: 100m - memory: 128Mi - env: - - name: NODE_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: spec.nodeName - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: INSTANCE_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.podIP - - name: HOST_IP - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: status.hostIP - - name: SERVICE_ACCOUNT - valueFrom: - fieldRef: - fieldPath: spec.serviceAccountName - - name: ISTIO_META_POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: ISTIO_META_CONFIG_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: ISTIO_METAJSON_LABELS - value: | - {"app":"cluster-local-gateway","chart":"gateways","heritage":"Helm","istio":"cluster-local-gateway","release":"RELEASE-NAME"} - - name: ISTIO_META_CLUSTER_ID - value: "Kubernetes" - - name: SDS_ENABLED - value: "false" - - name: ISTIO_META_WORKLOAD_NAME - value: cluster-local-gateway - - name: ISTIO_META_OWNER - value: kubernetes://apis/apps/v1/namespaces/istio-system/deployments/cluster-local-gateway - - volumeMounts: - - name: istio-certs - mountPath: /etc/certs - readOnly: true - - name: cluster-local-gateway-certs - mountPath: "/etc/istio/cluster-local-gateway-certs" - readOnly: true - - name: cluster-local-gateway-ca-certs - mountPath: "/etc/istio/cluster-local-gateway-ca-certs" - readOnly: true - volumes: - - name: istio-certs - secret: - secretName: istio.cluster-local-gateway-service-account - optional: true - - name: cluster-local-gateway-certs - secret: - secretName: "istio-cluster-local-gateway-certs" - optional: true - - name: cluster-local-gateway-ca-certs - secret: - secretName: "istio-cluster-local-gateway-ca-certs" - optional: true - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - "ppc64le" - - "s390x" - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "ppc64le" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "s390x" ---- -# Source: istio/charts/pilot/templates/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: istio-pilot - namespace: istio-system - # TODO: default template doesn't have this, which one is right ? - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME - istio: pilot -spec: - replicas: 1 - strategy: - rollingUpdate: - maxSurge: 100% - maxUnavailable: 25% - selector: - matchLabels: - istio: pilot - template: - metadata: - labels: - app: pilot - chart: pilot - heritage: Helm - release: RELEASE-NAME - istio: pilot - annotations: - sidecar.istio.io/inject: "false" - spec: - serviceAccountName: istio-pilot-service-account - containers: - - name: discovery - image: "docker.io/istio/pilot:1.4.3" - imagePullPolicy: IfNotPresent - args: - - "discovery" - - --monitoringAddr=:15014 - - --log_output_level=default:info - - --domain - - cluster.local - - --secureGrpcAddr - - "" - - --keepaliveMaxServerConnectionAge - - "30m" - ports: - - containerPort: 8080 - - containerPort: 15010 - - containerPort: 15011 - readinessProbe: - httpGet: - path: /ready - port: 8080 - initialDelaySeconds: 5 - periodSeconds: 5 - timeoutSeconds: 5 - env: - - name: POD_NAME - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.name - - name: POD_NAMESPACE - valueFrom: - fieldRef: - apiVersion: v1 - fieldPath: metadata.namespace - - name: PILOT_PUSH_THROTTLE - value: "100" - - name: PILOT_TRACE_SAMPLING - value: "100" - - name: PILOT_ENABLE_PROTOCOL_SNIFFING_FOR_OUTBOUND - value: "true" - - name: PILOT_ENABLE_PROTOCOL_SNIFFING_FOR_INBOUND - value: "false" - resources: - requests: - cpu: 100m - memory: 128Mi - volumeMounts: - - name: config-volume - mountPath: /etc/istio/config - - name: istio-certs - mountPath: /etc/certs - readOnly: true - volumes: - - name: config-volume - configMap: - name: istio - - name: istio-certs - secret: - secretName: istio.istio-pilot-service-account - optional: true - affinity: - nodeAffinity: - requiredDuringSchedulingIgnoredDuringExecution: - nodeSelectorTerms: - - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - "ppc64le" - - "s390x" - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "amd64" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "ppc64le" - - weight: 2 - preference: - matchExpressions: - - key: beta.kubernetes.io/arch - operator: In - values: - - "s390x" diff --git a/third_party/istio-1.4.3/namespace.yaml.patch b/third_party/istio-1.4.3/namespace.yaml.patch deleted file mode 100644 index 3e15f44aa1b..00000000000 --- a/third_party/istio-1.4.3/namespace.yaml.patch +++ /dev/null @@ -1,10 +0,0 @@ -1a2,10 -> # PATCH #1: Creating the istio-system namespace. -> apiVersion: v1 -> kind: Namespace -> metadata: -> name: istio-system -> labels: -> istio-injection: disabled -> # PATCH #1 ends. -> --- diff --git a/third_party/istio-1.4.3/values-local.yaml b/third_party/istio-1.4.3/values-local.yaml deleted file mode 100644 index 0f2f0ada03c..00000000000 --- a/third_party/istio-1.4.3/values-local.yaml +++ /dev/null @@ -1,91 +0,0 @@ -global: - proxy: - # Enable proxy to write access log to /dev/stdout. - accessLogFile: "/dev/stdout" - accessLogEncoding: 'JSON' - autoInject: disabled - disablePolicyChecks: true - omitSidecarInjectorConfigMap: true - defaultPodDisruptionBudget: - enabled: false - useMCP: false - -sidecarInjectorWebhook: - enabled: false - enableNamespacesByDefault: false - -gateways: - istio-ingressgateway: - enabled: true - sds: - enabled: true - autoscaleEnabled: false - resources: - requests: - cpu: 100m - memory: 128Mi - ports: - - name: status-port - port: 15020 - - name: http2 - port: 80 - - port: 443 - name: https - cluster-local-gateway: - enabled: true - labels: - app: cluster-local-gateway - istio: cluster-local-gateway - autoscaleEnabled: false - resources: - requests: - cpu: 100m - memory: 128Mi - loadBalancerIP: "" - loadBalancerSourceRanges: {} - externalIPs: [] - serviceAnnotations: {} - podAnnotations: {} - type: ClusterIP - ports: - - name: status-port - port: 15020 - - name: http2 - port: 80 - - name: https - port: 443 - secretVolumes: - - name: cluster-local-gateway-certs - secretName: istio-cluster-local-gateway-certs - mountPath: /etc/istio/cluster-local-gateway-certs - - name: cluster-local-gateway-ca-certs - secretName: istio-cluster-local-gateway-ca-certs - mountPath: /etc/istio/cluster-local-gateway-ca-certs - -prometheus: - enabled: false - -mixer: - enabled: false - policy: - enabled: false - telemetry: - enabled: false - adapters: - prometheus: - enabled: false - -pilot: - traceSampling: 100 - sidecar: false - autoscaleEnabled: false - resources: - requests: - cpu: 100m - memory: 128Mi - -galley: - enabled: false - -security: - enabled: false From ea030054c4d92c5e7d4e733fc1be3573ed99b50f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Thu, 7 May 2020 14:34:08 +0200 Subject: [PATCH 42/50] Wathola toml configuration respects default After merging Wathola to eventing, a bug came out that toml package has in 1.7.0 - https://github.com/pelletier/go-toml/issues/406 Adding tests to address that and pining pelletier/go-toml version to working one. --- Gopkg.lock | 6 +- Gopkg.toml | 5 + test/lib/await.go | 15 ++ test/prober/wathola/client/receiver.go | 6 +- test/prober/wathola/config/defaults.go | 12 +- test/prober/wathola/config/reader_test.go | 4 + test/prober/wathola/forwarder/services.go | 17 ++- test/prober/wathola/receiver/services.go | 17 ++- .../wathola-forwarder/main_test.go | 14 +- .../test_images/wathola-receiver/main_test.go | 14 +- vendor/github.com/pelletier/go-toml/lexer.go | 2 +- .../github.com/pelletier/go-toml/marshal.go | 132 +++++------------- vendor/github.com/pelletier/go-toml/toml.go | 4 - .../pelletier/go-toml/tomltree_write.go | 48 +++---- 14 files changed, 141 insertions(+), 155 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index fafaa7d94d8..45221af992f 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -464,12 +464,12 @@ version = "v0.2.2" [[projects]] - digest = "1:a9f0e3995b962f3e8db041c2475491661f33d7f873bcfc517bacd4b709039d9c" + digest = "1:efec7b15c9f6f20c96a5710fea5d946aabf13018d9e2d2c50a4746f850514f9d" name = "github.com/pelletier/go-toml" packages = ["."] pruneopts = "NUT" - revision = "8e8d2a6aad23fcaa64716c5fa6975ec3abbf8281" - version = "v1.7.0" + revision = "903d9455db9ff1d7ac1ab199062eca7266dd11a3" + version = "v1.6.0" [[projects]] digest = "1:d3ed3beb4c8434d4b8a8ac7696128c2c1e5ca96c720df78447b7b1ccbd7b0f92" diff --git a/Gopkg.toml b/Gopkg.toml index 3373fb0ea51..6b6dc160fc5 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -125,3 +125,8 @@ required = [ [[constraint]] name = "contrib.go.opencensus.io/exporter/ocagent" version = "0.6.0" + +# TODO(ksuszyns): Unpin when https://github.com/pelletier/go-toml/issues/406 is fixed +[[constraint]] + name = "github.com/pelletier/go-toml" + version = "~v1.6.0" diff --git a/test/lib/await.go b/test/lib/await.go index 5703240ac75..bd9a427ef12 100644 --- a/test/lib/await.go +++ b/test/lib/await.go @@ -16,12 +16,27 @@ package lib import ( + "fmt" "time" "go.uber.org/zap" "golang.org/x/sync/errgroup" ) +// WaitUntil a condition is met +func WaitUntil(condition func() bool, timeout time.Duration) error { + deadline := time.Now().Add(timeout) + for { + if condition() { + return nil + } + if time.Now().After(deadline) { + return fmt.Errorf("wait for condition exceed timeout of %v", timeout) + } + time.Sleep(25 * time.Millisecond) + } +} + // WaitFor will register a wait routine to be resolved later func WaitFor(name string, routine AwaitRoutine) { w := &namedAwait{ diff --git a/test/prober/wathola/client/receiver.go b/test/prober/wathola/client/receiver.go index a7eefcaa912..0792f8aa7a7 100644 --- a/test/prober/wathola/client/receiver.go +++ b/test/prober/wathola/client/receiver.go @@ -34,7 +34,7 @@ type ReceiveEvent func(e cloudevents.Event) // Receive events and push then to passed fn func Receive( port int, - cancel *context.CancelFunc, + cancelRegistrar func(*context.CancelFunc), receiveEvent ReceiveEvent, middlewares ... cloudeventshttp.Middleware) { portOpt := cloudevents.WithPort(port) @@ -56,9 +56,9 @@ func Receive( if err != nil { log.Fatalf("failed to create client, %v", err) } - ctx, ccancel := context.WithCancel(context.Background()) - cancel = &ccancel log.Infof("listening for events on port %v", port) + ctx, ccancel := context.WithCancel(context.Background()) + cancelRegistrar(&ccancel) err = c.StartReceiver(ctx, receiveEvent) if err != nil { log.Fatal(err) diff --git a/test/prober/wathola/config/defaults.go b/test/prober/wathola/config/defaults.go index 7b043ca2608..e2bfd8ced14 100644 --- a/test/prober/wathola/config/defaults.go +++ b/test/prober/wathola/config/defaults.go @@ -25,11 +25,19 @@ import ( "go.uber.org/zap" ) +const ( + // DefaultReceiverPort point to a default port of receiver component, and is + // unique so that components can be easily run on localhost for easy debugging + DefaultReceiverPort = 22111 + // DefaultForwarderPort point to a default port of forwarder component + DefaultForwarderPort = 22110 +) + // Instance holds configuration values var Instance = defaultValues() -var port = envint("PORT", 22111) -var forwarderPort = envint("PORT", 22110) +var port = envint("PORT", DefaultReceiverPort) +var forwarderPort = envint("PORT", DefaultForwarderPort) func envint(envKey string, defaultValue int) int { val, ok := os.LookupEnv(envKey) diff --git a/test/prober/wathola/config/reader_test.go b/test/prober/wathola/config/reader_test.go index 5fddf558561..13f03c8e83b 100644 --- a/test/prober/wathola/config/reader_test.go +++ b/test/prober/wathola/config/reader_test.go @@ -46,6 +46,8 @@ address = 'http://default-broker.event-example.svc.cluster.local/' assert.Equal(t, "http://default-broker.event-example.svc.cluster.local/", Instance.Sender.Address) + assert.Equal(t, DefaultReceiverPort, Instance.Receiver.Port) + assert.Equal(t, DefaultForwarderPort, Instance.Forwarder.Port) } func TestReadIfPresentAndInvalid(t *testing.T) { @@ -81,6 +83,8 @@ func TestReadIfNotPresent(t *testing.T) { assert.Equal(t, "http://localhost:22110/", Instance.Sender.Address) + assert.Equal(t, DefaultReceiverPort, Instance.Receiver.Port) + assert.Equal(t, DefaultForwarderPort, Instance.Forwarder.Port) } func ensureConfigFileNotPresent() string { diff --git a/test/prober/wathola/forwarder/services.go b/test/prober/wathola/forwarder/services.go index e243230fecd..2e91f098655 100644 --- a/test/prober/wathola/forwarder/services.go +++ b/test/prober/wathola/forwarder/services.go @@ -40,18 +40,27 @@ func New() Forwarder { // Stop will stop running forwarder if there is one func Stop() { - if cancel != nil { + if IsRunning() { log.Info("stopping forwarder") - cancel() + cf := *cancel + cf() cancel = nil } } -var cancel context.CancelFunc +// IsRunning checks if receiver is operating and can be stopped +func IsRunning() bool { + return cancel != nil +} + +var cancel *context.CancelFunc func (f *forwarder) Forward() { port := config.Instance.Forwarder.Port - client.Receive(port, &cancel, f.forwardEvent) + cancelRegistrar := func(cc *context.CancelFunc) { + cancel = cc + } + client.Receive(port, cancelRegistrar, f.forwardEvent) } func (f *forwarder) forwardEvent(e cloudevents.Event) { diff --git a/test/prober/wathola/receiver/services.go b/test/prober/wathola/receiver/services.go index e7c3f59121c..3bbe102f908 100644 --- a/test/prober/wathola/receiver/services.go +++ b/test/prober/wathola/receiver/services.go @@ -30,7 +30,7 @@ import ( ) var log = config.Log -var cancel context.CancelFunc +var cancel *context.CancelFunc // New creates new Receiver func New() Receiver { @@ -44,16 +44,25 @@ func New() Receiver { // Stop will stop running receiver if there is one func Stop() { - if cancel != nil { + if IsRunning() { log.Info("stopping receiver") - cancel() + cancelFunc := *cancel + cancelFunc() cancel = nil } } +// IsRunning checks if receiver is operating and can be stopped +func IsRunning() bool { + return cancel != nil +} + func (r receiver) Receive() { port := config.Instance.Receiver.Port - client.Receive(port, &cancel, r.receiveEvent, r.reportMiddleware) + cancelRegistrar := func(cc *context.CancelFunc) { + cancel = cc + } + client.Receive(port, cancelRegistrar, r.receiveEvent, r.reportMiddleware) } func (r receiver) receiveEvent(e cloudevents.Event) { diff --git a/test/test_images/wathola-forwarder/main_test.go b/test/test_images/wathola-forwarder/main_test.go index d7565347252..2ad263f37b3 100644 --- a/test/test_images/wathola-forwarder/main_test.go +++ b/test/test_images/wathola-forwarder/main_test.go @@ -1,21 +1,23 @@ package main import ( + "testing" + "time" + "github.com/phayes/freeport" "github.com/stretchr/testify/assert" + "knative.dev/eventing/test/lib" "knative.dev/eventing/test/prober/wathola/config" "knative.dev/eventing/test/prober/wathola/forwarder" - - "testing" - "time" ) func TestForwarderMain(t *testing.T) { config.Instance.Forwarder.Port = freeport.GetPort() go main() defer forwarder.Stop() - - time.Sleep(time.Second) - + err := lib.WaitUntil(forwarder.IsRunning, 10 * time.Minute) + if err != nil { + t.Error(err) + } assert.NotNil(t, instance) } diff --git a/test/test_images/wathola-receiver/main_test.go b/test/test_images/wathola-receiver/main_test.go index 06b32ec8174..8fd139d01f9 100644 --- a/test/test_images/wathola-receiver/main_test.go +++ b/test/test_images/wathola-receiver/main_test.go @@ -1,13 +1,14 @@ package main import ( + "testing" + "time" + "github.com/phayes/freeport" + "knative.dev/eventing/test/lib" "knative.dev/eventing/test/prober/wathola/config" "knative.dev/eventing/test/prober/wathola/receiver" - "testing" - "time" - "github.com/stretchr/testify/assert" ) @@ -15,8 +16,9 @@ func TestReceiverMain(t *testing.T) { config.Instance.Receiver.Port = freeport.GetPort() go main() defer receiver.Stop() - - time.Sleep(time.Second) - + err := lib.WaitUntil(receiver.IsRunning, 10 * time.Minute) + if err != nil { + t.Error(err) + } assert.NotNil(t, instance) } diff --git a/vendor/github.com/pelletier/go-toml/lexer.go b/vendor/github.com/pelletier/go-toml/lexer.go index 88fd91ee0b0..735673bd7c1 100644 --- a/vendor/github.com/pelletier/go-toml/lexer.go +++ b/vendor/github.com/pelletier/go-toml/lexer.go @@ -256,7 +256,7 @@ func (l *tomlLexer) lexLeftCurlyBrace() tomlLexStateFn { func (l *tomlLexer) lexRightCurlyBrace() tomlLexStateFn { l.next() l.emit(tokenRightCurlyBrace) - return l.lexRvalue + return l.lexVoid } func (l *tomlLexer) lexDate() tomlLexStateFn { diff --git a/vendor/github.com/pelletier/go-toml/marshal.go b/vendor/github.com/pelletier/go-toml/marshal.go index dcddad8dba0..2a6cfbae423 100644 --- a/vendor/github.com/pelletier/go-toml/marshal.go +++ b/vendor/github.com/pelletier/go-toml/marshal.go @@ -302,7 +302,7 @@ func (e *Encoder) marshal(v interface{}) ([]byte, error) { } var buf bytes.Buffer - _, err = t.writeToOrdered(&buf, "", "", 0, e.arraysOneElementPerLine, e.order, false) + _, err = t.writeToOrdered(&buf, "", "", 0, e.arraysOneElementPerLine, e.order) return buf.Bytes(), err } @@ -320,25 +320,20 @@ func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, er tval := e.nextTree() switch mtype.Kind() { case reflect.Struct: - switch mval.Interface().(type) { - case Tree: - reflect.ValueOf(tval).Elem().Set(mval) - default: - for i := 0; i < mtype.NumField(); i++ { - mtypef, mvalf := mtype.Field(i), mval.Field(i) - opts := tomlOptions(mtypef, e.annotation) - if opts.include && ((mtypef.Type.Kind() != reflect.Interface && !opts.omitempty) || !isZero(mvalf)) { - val, err := e.valueToToml(mtypef.Type, mvalf) - if err != nil { - return nil, err - } - - tval.SetWithOptions(opts.name, SetOptions{ - Comment: opts.comment, - Commented: opts.commented, - Multiline: opts.multiline, - }, val) + for i := 0; i < mtype.NumField(); i++ { + mtypef, mvalf := mtype.Field(i), mval.Field(i) + opts := tomlOptions(mtypef, e.annotation) + if opts.include && (!opts.omitempty || !isZero(mvalf)) { + val, err := e.valueToToml(mtypef.Type, mvalf) + if err != nil { + return nil, err } + + tval.SetWithOptions(opts.name, SetOptions{ + Comment: opts.comment, + Commented: opts.commented, + Multiline: opts.multiline, + }, val) } } case reflect.Map: @@ -363,15 +358,12 @@ func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, er } for _, key := range keys { mvalf := mval.MapIndex(key) - if (mtype.Elem().Kind() == reflect.Ptr || mtype.Elem().Kind() == reflect.Interface) && mvalf.IsNil() { - continue - } val, err := e.valueToToml(mtype.Elem(), mvalf) if err != nil { return nil, err } if e.quoteMapKeys { - keyStr, err := tomlValueStringRepresentation(key.String(), "", "", e.arraysOneElementPerLine) + keyStr, err := tomlValueStringRepresentation(key.String(), "", e.arraysOneElementPerLine) if err != nil { return nil, err } @@ -399,9 +391,6 @@ func (e *Encoder) valueToTreeSlice(mtype reflect.Type, mval reflect.Value) ([]*T // Convert given marshal slice to slice of toml values func (e *Encoder) valueToOtherSlice(mtype reflect.Type, mval reflect.Value) (interface{}, error) { - if mtype.Elem().Kind() == reflect.Interface { - return nil, fmt.Errorf("marshal can't handle []interface{}") - } tval := make([]interface{}, mval.Len(), mval.Len()) for i := 0; i < mval.Len(); i++ { val, err := e.valueToToml(mtype.Elem(), mval.Index(i)) @@ -419,9 +408,6 @@ func (e *Encoder) valueToToml(mtype reflect.Type, mval reflect.Value) (interface if mtype.Kind() == reflect.Ptr { return e.valueToToml(mtype.Elem(), mval.Elem()) } - if mtype.Kind() == reflect.Interface { - return e.valueToToml(mval.Elem().Type(), mval.Elem()) - } switch { case isCustomMarshaler(mtype): return callCustomMarshaler(mval) @@ -575,17 +561,11 @@ func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree, mval1 *reflect.V mval = reflect.New(mtype).Elem() } - switch mval.Interface().(type) { - case Tree: - mval.Set(reflect.ValueOf(tval).Elem()) - default: - for i := 0; i < mtype.NumField(); i++ { - mtypef := mtype.Field(i) - an := annotation{tag: d.tagName} - opts := tomlOptions(mtypef, an) - if !opts.include { - continue - } + for i := 0; i < mtype.NumField(); i++ { + mtypef := mtype.Field(i) + an := annotation{tag: d.tagName} + opts := tomlOptions(mtypef, an) + if opts.include { baseKey := opts.name keysToTry := []string{ baseKey, @@ -595,22 +575,20 @@ func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree, mval1 *reflect.V } found := false - if tval != nil { - for _, key := range keysToTry { - exists := tval.Has(key) - if !exists { - continue - } - val := tval.Get(key) - fval := mval.Field(i) - mvalf, err := d.valueFromToml(mtypef.Type, val, &fval) - if err != nil { - return mval, formatError(err, tval.GetPosition(key)) - } - mval.Field(i).Set(mvalf) - found = true - break + for _, key := range keysToTry { + exists := tval.Has(key) + if !exists { + continue } + val := tval.Get(key) + fval := mval.Field(i) + mvalf, err := d.valueFromToml(mtypef.Type, val, &fval) + if err != nil { + return mval, formatError(err, tval.GetPosition(key)) + } + mval.Field(i).Set(mvalf) + found = true + break } if !found && opts.defaultValue != "" { @@ -646,13 +624,9 @@ func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree, mval1 *reflect.V mval.Field(i).Set(reflect.ValueOf(val)) } - // save the old behavior above and try to check structs - if !found && opts.defaultValue == "" && mtypef.Type.Kind() == reflect.Struct { - tmpTval := tval - if !mtypef.Anonymous { - tmpTval = nil - } - v, err := d.valueFromTree(mtypef.Type, tmpTval, nil) + // save the old behavior above and try to check anonymous structs + if !found && opts.defaultValue == "" && mtypef.Anonymous && mtypef.Type.Kind() == reflect.Struct { + v, err := d.valueFromTree(mtypef.Type, tval, nil) if err != nil { return v, err } @@ -718,41 +692,16 @@ func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}, mval1 *ref if isTree(mtype) { return d.valueFromTree(mtype, t, mval11) } - - if mtype.Kind() == reflect.Interface { - if mval1 == nil || mval1.IsNil() { - return d.valueFromTree(reflect.TypeOf(map[string]interface{}{}), t, nil) - } else { - return d.valueFromToml(mval1.Elem().Type(), t, nil) - } - } - return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a tree", tval, tval) case []*Tree: if isTreeSequence(mtype) { return d.valueFromTreeSlice(mtype, t) } - if mtype.Kind() == reflect.Interface { - if mval1 == nil || mval1.IsNil() { - return d.valueFromTreeSlice(reflect.TypeOf([]map[string]interface{}{}), t) - } else { - ival := mval1.Elem() - return d.valueFromToml(mval1.Elem().Type(), t, &ival) - } - } return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to trees", tval, tval) case []interface{}: if isOtherSequence(mtype) { return d.valueFromOtherSlice(mtype, t) } - if mtype.Kind() == reflect.Interface { - if mval1 == nil || mval1.IsNil() { - return d.valueFromOtherSlice(reflect.TypeOf([]interface{}{}), t) - } else { - ival := mval1.Elem() - return d.valueFromToml(mval1.Elem().Type(), t, &ival) - } - } return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a slice", tval, tval) default: switch mtype.Kind() { @@ -837,13 +786,6 @@ func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}, mval1 *ref } return val.Convert(mtype), nil - case reflect.Interface: - if mval1 == nil || mval1.IsNil() { - return reflect.ValueOf(tval), nil - } else { - ival := mval1.Elem() - return d.valueFromToml(mval1.Elem().Type(), t, &ival) - } default: return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v(%v)", tval, tval, mtype, mtype.Kind()) } @@ -853,7 +795,7 @@ func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}, mval1 *ref func (d *Decoder) unwrapPointer(mtype reflect.Type, tval interface{}, mval1 *reflect.Value) (reflect.Value, error) { var melem *reflect.Value - if mval1 != nil && !mval1.IsNil() && (mtype.Elem().Kind() == reflect.Struct || mtype.Elem().Kind() == reflect.Interface) { + if mval1 != nil && !mval1.IsNil() && mtype.Elem().Kind() == reflect.Struct { elem := mval1.Elem() melem = &elem } diff --git a/vendor/github.com/pelletier/go-toml/toml.go b/vendor/github.com/pelletier/go-toml/toml.go index f4d56870b8d..358a9be5ce8 100644 --- a/vendor/github.com/pelletier/go-toml/toml.go +++ b/vendor/github.com/pelletier/go-toml/toml.go @@ -222,12 +222,8 @@ func (t *Tree) SetPathWithOptions(keys []string, opts SetOptions, value interfac switch v := value.(type) { case *Tree: v.comment = opts.Comment - v.commented = opts.Commented toInsert = value case []*Tree: - for i := range v { - v[i].commented = opts.Commented - } toInsert = value case *tomlValue: v.comment = opts.Comment diff --git a/vendor/github.com/pelletier/go-toml/tomltree_write.go b/vendor/github.com/pelletier/go-toml/tomltree_write.go index 16c198670fc..43c63030d26 100644 --- a/vendor/github.com/pelletier/go-toml/tomltree_write.go +++ b/vendor/github.com/pelletier/go-toml/tomltree_write.go @@ -28,10 +28,9 @@ type sortNode struct { // Encodes a string to a TOML-compliant multi-line string value // This function is a clone of the existing encodeTomlString function, except that whitespace characters // are preserved. Quotation marks and backslashes are also not escaped. -func encodeMultilineTomlString(value string, commented string) string { +func encodeMultilineTomlString(value string) string { var b bytes.Buffer - b.WriteString(commented) for _, rr := range value { switch rr { case '\b': @@ -39,7 +38,7 @@ func encodeMultilineTomlString(value string, commented string) string { case '\t': b.WriteString("\t") case '\n': - b.WriteString("\n" + commented) + b.WriteString("\n") case '\f': b.WriteString(`\f`) case '\r': @@ -92,7 +91,7 @@ func encodeTomlString(value string) string { return b.String() } -func tomlValueStringRepresentation(v interface{}, commented string, indent string, arraysOneElementPerLine bool) (string, error) { +func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElementPerLine bool) (string, error) { // this interface check is added to dereference the change made in the writeTo function. // That change was made to allow this function to see formatting options. tv, ok := v.(*tomlValue) @@ -124,12 +123,12 @@ func tomlValueStringRepresentation(v interface{}, commented string, indent strin return strings.ToLower(strconv.FormatFloat(value, 'f', -1, bits)), nil case string: if tv.multiline { - return "\"\"\"\n" + encodeMultilineTomlString(value, commented) + "\"\"\"", nil + return "\"\"\"\n" + encodeMultilineTomlString(value) + "\"\"\"", nil } return "\"" + encodeTomlString(value) + "\"", nil case []byte: b, _ := v.([]byte) - return tomlValueStringRepresentation(string(b), commented, indent, arraysOneElementPerLine) + return tomlValueStringRepresentation(string(b), indent, arraysOneElementPerLine) case bool: if value { return "true", nil @@ -153,7 +152,7 @@ func tomlValueStringRepresentation(v interface{}, commented string, indent strin var values []string for i := 0; i < rv.Len(); i++ { item := rv.Index(i).Interface() - itemRepr, err := tomlValueStringRepresentation(item, commented, indent, arraysOneElementPerLine) + itemRepr, err := tomlValueStringRepresentation(item, indent, arraysOneElementPerLine) if err != nil { return "", err } @@ -167,12 +166,12 @@ func tomlValueStringRepresentation(v interface{}, commented string, indent strin for _, value := range values { stringBuffer.WriteString(valueIndent) - stringBuffer.WriteString(commented + value) + stringBuffer.WriteString(value) stringBuffer.WriteString(`,`) stringBuffer.WriteString("\n") } - stringBuffer.WriteString(indent + commented + "]") + stringBuffer.WriteString(indent + "]") return stringBuffer.String(), nil } @@ -271,10 +270,10 @@ func sortAlphabetical(t *Tree) (vals []sortNode) { } func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool) (int64, error) { - return t.writeToOrdered(w, indent, keyspace, bytesCount, arraysOneElementPerLine, OrderAlphabetical, false) + return t.writeToOrdered(w, indent, keyspace, bytesCount, arraysOneElementPerLine, OrderAlphabetical) } -func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool, ord marshalOrder, parentCommented bool) (int64, error) { +func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool, ord marshalOrder) (int64, error) { var orderedVals []sortNode switch ord { @@ -294,6 +293,10 @@ func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount i if keyspace != "" { combinedKey = keyspace + "." + combinedKey } + var commented string + if t.commented { + commented = "# " + } switch node := v.(type) { // node has to be of those two types given how keys are sorted above @@ -314,33 +317,24 @@ func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount i return bytesCount, errc } } - - var commented string - if parentCommented || t.commented || tv.commented { - commented = "# " - } writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[", combinedKey, "]\n") bytesCount += int64(writtenBytesCount) if err != nil { return bytesCount, err } - bytesCount, err = node.writeToOrdered(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine, ord, parentCommented || t.commented || tv.commented) + bytesCount, err = node.writeToOrdered(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine, ord) if err != nil { return bytesCount, err } case []*Tree: for _, subTree := range node { - var commented string - if parentCommented || t.commented || subTree.commented { - commented = "# " - } writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[[", combinedKey, "]]\n") bytesCount += int64(writtenBytesCount) if err != nil { return bytesCount, err } - bytesCount, err = subTree.writeToOrdered(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine, ord, parentCommented || t.commented || subTree.commented) + bytesCount, err = subTree.writeToOrdered(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine, ord) if err != nil { return bytesCount, err } @@ -353,11 +347,7 @@ func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount i return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k]) } - var commented string - if parentCommented || t.commented || v.commented { - commented = "# " - } - repr, err := tomlValueStringRepresentation(v, commented, indent, arraysOneElementPerLine) + repr, err := tomlValueStringRepresentation(v, indent, arraysOneElementPerLine) if err != nil { return bytesCount, err } @@ -375,6 +365,10 @@ func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount i } } + var commented string + if v.commented { + commented = "# " + } quotedKey := quoteKeyIfNeeded(k) writtenBytesCount, err := writeStrings(w, indent, commented, quotedKey, " = ", repr, "\n") bytesCount += int64(writtenBytesCount) From 69cf66e4188ecea76f04b8e47e07f04bc76acd02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Fri, 8 May 2020 13:33:29 +0200 Subject: [PATCH 43/50] Updating codegen --- .../github.com/mitchellh/go-homedir/LICENSE | 21 ++ .../github.com/pelletier/go-toml/LICENSE | 21 ++ .../github.com/wavesoftware/go-ensure/LICENSE | 201 +++++++++++++++ .../github.com/mitchellh/go-homedir/README.md | 14 + vendor/github.com/mitchellh/go-homedir/go.mod | 1 + .../pelletier/go-toml/.dockerignore | 2 + .../github.com/pelletier/go-toml/.gitignore | 5 + .../pelletier/go-toml/CONTRIBUTING.md | 132 ++++++++++ .../github.com/pelletier/go-toml/Dockerfile | 11 + .../go-toml/PULL_REQUEST_TEMPLATE.md | 5 + vendor/github.com/pelletier/go-toml/README.md | 151 +++++++++++ .../pelletier/go-toml/azure-pipelines.yml | 167 ++++++++++++ .../pelletier/go-toml/benchmark.json | 164 ++++++++++++ .../github.com/pelletier/go-toml/benchmark.sh | 31 +++ .../pelletier/go-toml/benchmark.toml | 244 ++++++++++++++++++ .../pelletier/go-toml/benchmark.yml | 121 +++++++++ .../pelletier/go-toml/example-crlf.toml | 29 +++ .../github.com/pelletier/go-toml/example.toml | 29 +++ vendor/github.com/pelletier/go-toml/fuzz.sh | 15 ++ vendor/github.com/pelletier/go-toml/fuzzit.sh | 26 ++ vendor/github.com/pelletier/go-toml/go.mod | 9 + vendor/github.com/pelletier/go-toml/go.sum | 11 + .../go-toml/marshal_OrderPreserve_test.toml | 39 +++ .../pelletier/go-toml/marshal_test.toml | 39 +++ vendor/github.com/phayes/freeport/.gitignore | 1 + .../phayes/freeport/.goreleaser.yml | 134 ++++++++++ vendor/github.com/phayes/freeport/README.md | 58 +++++ vendor/github.com/phayes/freeport/freeport.go | 19 ++ .../wavesoftware/go-ensure/.editorconfig | 15 ++ .../wavesoftware/go-ensure/.gitignore | 17 ++ .../wavesoftware/go-ensure/.travis.yml | 15 ++ .../wavesoftware/go-ensure/Makefile | 32 +++ .../wavesoftware/go-ensure/README.md | 55 ++++ .../github.com/wavesoftware/go-ensure/go.mod | 5 + .../github.com/wavesoftware/go-ensure/go.sum | 2 + .../wavesoftware/go-ensure/revive.toml | 35 +++ vendor/modules.txt | 8 + 37 files changed, 1884 insertions(+) create mode 100644 third_party/VENDOR-LICENSE/github.com/mitchellh/go-homedir/LICENSE create mode 100644 third_party/VENDOR-LICENSE/github.com/pelletier/go-toml/LICENSE create mode 100644 third_party/VENDOR-LICENSE/github.com/wavesoftware/go-ensure/LICENSE create mode 100644 vendor/github.com/mitchellh/go-homedir/README.md create mode 100644 vendor/github.com/mitchellh/go-homedir/go.mod create mode 100644 vendor/github.com/pelletier/go-toml/.dockerignore create mode 100644 vendor/github.com/pelletier/go-toml/.gitignore create mode 100644 vendor/github.com/pelletier/go-toml/CONTRIBUTING.md create mode 100644 vendor/github.com/pelletier/go-toml/Dockerfile create mode 100644 vendor/github.com/pelletier/go-toml/PULL_REQUEST_TEMPLATE.md create mode 100644 vendor/github.com/pelletier/go-toml/README.md create mode 100644 vendor/github.com/pelletier/go-toml/azure-pipelines.yml create mode 100644 vendor/github.com/pelletier/go-toml/benchmark.json create mode 100644 vendor/github.com/pelletier/go-toml/benchmark.sh create mode 100644 vendor/github.com/pelletier/go-toml/benchmark.toml create mode 100644 vendor/github.com/pelletier/go-toml/benchmark.yml create mode 100644 vendor/github.com/pelletier/go-toml/example-crlf.toml create mode 100644 vendor/github.com/pelletier/go-toml/example.toml create mode 100644 vendor/github.com/pelletier/go-toml/fuzz.sh create mode 100644 vendor/github.com/pelletier/go-toml/fuzzit.sh create mode 100644 vendor/github.com/pelletier/go-toml/go.mod create mode 100644 vendor/github.com/pelletier/go-toml/go.sum create mode 100644 vendor/github.com/pelletier/go-toml/marshal_OrderPreserve_test.toml create mode 100644 vendor/github.com/pelletier/go-toml/marshal_test.toml create mode 100644 vendor/github.com/phayes/freeport/.gitignore create mode 100644 vendor/github.com/phayes/freeport/.goreleaser.yml create mode 100644 vendor/github.com/phayes/freeport/README.md create mode 100644 vendor/github.com/wavesoftware/go-ensure/.editorconfig create mode 100644 vendor/github.com/wavesoftware/go-ensure/.gitignore create mode 100644 vendor/github.com/wavesoftware/go-ensure/.travis.yml create mode 100644 vendor/github.com/wavesoftware/go-ensure/Makefile create mode 100644 vendor/github.com/wavesoftware/go-ensure/README.md create mode 100644 vendor/github.com/wavesoftware/go-ensure/go.mod create mode 100644 vendor/github.com/wavesoftware/go-ensure/go.sum create mode 100644 vendor/github.com/wavesoftware/go-ensure/revive.toml diff --git a/third_party/VENDOR-LICENSE/github.com/mitchellh/go-homedir/LICENSE b/third_party/VENDOR-LICENSE/github.com/mitchellh/go-homedir/LICENSE new file mode 100644 index 00000000000..f9c841a51e0 --- /dev/null +++ b/third_party/VENDOR-LICENSE/github.com/mitchellh/go-homedir/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 Mitchell Hashimoto + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/third_party/VENDOR-LICENSE/github.com/pelletier/go-toml/LICENSE b/third_party/VENDOR-LICENSE/github.com/pelletier/go-toml/LICENSE new file mode 100644 index 00000000000..583bdae6282 --- /dev/null +++ b/third_party/VENDOR-LICENSE/github.com/pelletier/go-toml/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2013 - 2017 Thomas Pelletier, Eric Anderton + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/third_party/VENDOR-LICENSE/github.com/wavesoftware/go-ensure/LICENSE b/third_party/VENDOR-LICENSE/github.com/wavesoftware/go-ensure/LICENSE new file mode 100644 index 00000000000..6c180a6f23d --- /dev/null +++ b/third_party/VENDOR-LICENSE/github.com/wavesoftware/go-ensure/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2020 Wave Software + + 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/vendor/github.com/mitchellh/go-homedir/README.md b/vendor/github.com/mitchellh/go-homedir/README.md new file mode 100644 index 00000000000..d70706d5b35 --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/README.md @@ -0,0 +1,14 @@ +# go-homedir + +This is a Go library for detecting the user's home directory without +the use of cgo, so the library can be used in cross-compilation environments. + +Usage is incredibly simple, just call `homedir.Dir()` to get the home directory +for a user, and `homedir.Expand()` to expand the `~` in a path to the home +directory. + +**Why not just use `os/user`?** The built-in `os/user` package requires +cgo on Darwin systems. This means that any Go code that uses that package +cannot cross compile. But 99% of the time the use for `os/user` is just to +retrieve the home directory, which we can do for the current user without +cgo. This library does that, enabling cross-compilation. diff --git a/vendor/github.com/mitchellh/go-homedir/go.mod b/vendor/github.com/mitchellh/go-homedir/go.mod new file mode 100644 index 00000000000..7efa09a0432 --- /dev/null +++ b/vendor/github.com/mitchellh/go-homedir/go.mod @@ -0,0 +1 @@ +module github.com/mitchellh/go-homedir diff --git a/vendor/github.com/pelletier/go-toml/.dockerignore b/vendor/github.com/pelletier/go-toml/.dockerignore new file mode 100644 index 00000000000..7b5883475df --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/.dockerignore @@ -0,0 +1,2 @@ +cmd/tomll/tomll +cmd/tomljson/tomljson diff --git a/vendor/github.com/pelletier/go-toml/.gitignore b/vendor/github.com/pelletier/go-toml/.gitignore new file mode 100644 index 00000000000..e6ba63a5c5c --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/.gitignore @@ -0,0 +1,5 @@ +test_program/test_program_bin +fuzz/ +cmd/tomll/tomll +cmd/tomljson/tomljson +cmd/tomltestgen/tomltestgen diff --git a/vendor/github.com/pelletier/go-toml/CONTRIBUTING.md b/vendor/github.com/pelletier/go-toml/CONTRIBUTING.md new file mode 100644 index 00000000000..405c911c903 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/CONTRIBUTING.md @@ -0,0 +1,132 @@ +## Contributing + +Thank you for your interest in go-toml! We appreciate you considering +contributing to go-toml! + +The main goal is the project is to provide an easy-to-use TOML +implementation for Go that gets the job done and gets out of your way – +dealing with TOML is probably not the central piece of your project. + +As the single maintainer of go-toml, time is scarce. All help, big or +small, is more than welcomed! + +### Ask questions + +Any question you may have, somebody else might have it too. Always feel +free to ask them on the [issues tracker][issues-tracker]. We will try to +answer them as clearly and quickly as possible, time permitting. + +Asking questions also helps us identify areas where the documentation needs +improvement, or new features that weren't envisioned before. Sometimes, a +seemingly innocent question leads to the fix of a bug. Don't hesitate and +ask away! + +### Improve the documentation + +The best way to share your knowledge and experience with go-toml is to +improve the documentation. Fix a typo, clarify an interface, add an +example, anything goes! + +The documentation is present in the [README][readme] and thorough the +source code. On release, it gets updated on [GoDoc][godoc]. To make a +change to the documentation, create a pull request with your proposed +changes. For simple changes like that, the easiest way to go is probably +the "Fork this project and edit the file" button on Github, displayed at +the top right of the file. Unless it's a trivial change (for example a +typo), provide a little bit of context in your pull request description or +commit message. + +### Report a bug + +Found a bug! Sorry to hear that :(. Help us and other track them down and +fix by reporting it. [File a new bug report][bug-report] on the [issues +tracker][issues-tracker]. The template should provide enough guidance on +what to include. When in doubt: add more details! By reducing ambiguity and +providing more information, it decreases back and forth and saves everyone +time. + +### Code changes + +Want to contribute a patch? Very happy to hear that! + +First, some high-level rules: + +* A short proposal with some POC code is better than a lengthy piece of + text with no code. Code speaks louder than words. +* No backward-incompatible patch will be accepted unless discussed. + Sometimes it's hard, and Go's lack of versioning by default does not + help, but we try not to break people's programs unless we absolutely have + to. +* If you are writing a new feature or extending an existing one, make sure + to write some documentation. +* Bug fixes need to be accompanied with regression tests. +* New code needs to be tested. +* Your commit messages need to explain why the change is needed, even if + already included in the PR description. + +It does sound like a lot, but those best practices are here to save time +overall and continuously improve the quality of the project, which is +something everyone benefits from. + +#### Get started + +The fairly standard code contribution process looks like that: + +1. [Fork the project][fork]. +2. Make your changes, commit on any branch you like. +3. [Open up a pull request][pull-request] +4. Review, potential ask for changes. +5. Merge. You're in! + +Feel free to ask for help! You can create draft pull requests to gather +some early feedback! + +#### Run the tests + +You can run tests for go-toml using Go's test tool: `go test ./...`. +When creating a pull requests, all tests will be ran on Linux on a few Go +versions (Travis CI), and on Windows using the latest Go version +(AppVeyor). + +#### Style + +Try to look around and follow the same format and structure as the rest of +the code. We enforce using `go fmt` on the whole code base. + +--- + +### Maintainers-only + +#### Merge pull request + +Checklist: + +* Passing CI. +* Does not introduce backward-incompatible changes (unless discussed). +* Has relevant doc changes. +* Has relevant unit tests. + +1. Merge using "squash and merge". +2. Make sure to edit the commit message to keep all the useful information + nice and clean. +3. Make sure the commit title is clear and contains the PR number (#123). + +#### New release + +1. Go to [releases][releases]. Click on "X commits to master since this + release". +2. Make note of all the changes. Look for backward incompatible changes, + new features, and bug fixes. +3. Pick the new version using the above and semver. +4. Create a [new release][new-release]. +5. Follow the same format as [1.1.0][release-110]. + +[issues-tracker]: https://github.com/pelletier/go-toml/issues +[bug-report]: https://github.com/pelletier/go-toml/issues/new?template=bug_report.md +[godoc]: https://godoc.org/github.com/pelletier/go-toml +[readme]: ./README.md +[fork]: https://help.github.com/articles/fork-a-repo +[pull-request]: https://help.github.com/en/articles/creating-a-pull-request +[releases]: https://github.com/pelletier/go-toml/releases +[new-release]: https://github.com/pelletier/go-toml/releases/new +[release-110]: https://github.com/pelletier/go-toml/releases/tag/v1.1.0 diff --git a/vendor/github.com/pelletier/go-toml/Dockerfile b/vendor/github.com/pelletier/go-toml/Dockerfile new file mode 100644 index 00000000000..fffdb016668 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/Dockerfile @@ -0,0 +1,11 @@ +FROM golang:1.12-alpine3.9 as builder +WORKDIR /go/src/github.com/pelletier/go-toml +COPY . . +ENV CGO_ENABLED=0 +ENV GOOS=linux +RUN go install ./... + +FROM scratch +COPY --from=builder /go/bin/tomll /usr/bin/tomll +COPY --from=builder /go/bin/tomljson /usr/bin/tomljson +COPY --from=builder /go/bin/jsontoml /usr/bin/jsontoml diff --git a/vendor/github.com/pelletier/go-toml/PULL_REQUEST_TEMPLATE.md b/vendor/github.com/pelletier/go-toml/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 00000000000..041cdc4a2f1 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,5 @@ +**Issue:** add link to pelletier/go-toml issue here + +Explanation of what this pull request does. + +More detailed description of the decisions being made and the reasons why (if the patch is non-trivial). diff --git a/vendor/github.com/pelletier/go-toml/README.md b/vendor/github.com/pelletier/go-toml/README.md new file mode 100644 index 00000000000..4ef303af03a --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/README.md @@ -0,0 +1,151 @@ +# go-toml + +Go library for the [TOML](https://github.com/mojombo/toml) format. + +This library supports TOML version +[v0.5.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md) + +[![GoDoc](https://godoc.org/github.com/pelletier/go-toml?status.svg)](http://godoc.org/github.com/pelletier/go-toml) +[![license](https://img.shields.io/github/license/pelletier/go-toml.svg)](https://github.com/pelletier/go-toml/blob/master/LICENSE) +[![Build Status](https://dev.azure.com/pelletierthomas/go-toml-ci/_apis/build/status/pelletier.go-toml?branchName=master)](https://dev.azure.com/pelletierthomas/go-toml-ci/_build/latest?definitionId=1&branchName=master) +[![codecov](https://codecov.io/gh/pelletier/go-toml/branch/master/graph/badge.svg)](https://codecov.io/gh/pelletier/go-toml) +[![Go Report Card](https://goreportcard.com/badge/github.com/pelletier/go-toml)](https://goreportcard.com/report/github.com/pelletier/go-toml) +[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fpelletier%2Fgo-toml.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fpelletier%2Fgo-toml?ref=badge_shield) + +## Features + +Go-toml provides the following features for using data parsed from TOML documents: + +* Load TOML documents from files and string data +* Easily navigate TOML structure using Tree +* Mashaling and unmarshaling to and from data structures +* Line & column position data for all parsed elements +* [Query support similar to JSON-Path](query/) +* Syntax errors contain line and column numbers + +## Import + +```go +import "github.com/pelletier/go-toml" +``` + +## Usage example + +Read a TOML document: + +```go +config, _ := toml.Load(` +[postgres] +user = "pelletier" +password = "mypassword"`) +// retrieve data directly +user := config.Get("postgres.user").(string) + +// or using an intermediate object +postgresConfig := config.Get("postgres").(*toml.Tree) +password := postgresConfig.Get("password").(string) +``` + +Or use Unmarshal: + +```go +type Postgres struct { + User string + Password string +} +type Config struct { + Postgres Postgres +} + +doc := []byte(` +[Postgres] +User = "pelletier" +Password = "mypassword"`) + +config := Config{} +toml.Unmarshal(doc, &config) +fmt.Println("user=", config.Postgres.User) +``` + +Or use a query: + +```go +// use a query to gather elements without walking the tree +q, _ := query.Compile("$..[user,password]") +results := q.Execute(config) +for ii, item := range results.Values() { + fmt.Println("Query result %d: %v", ii, item) +} +``` + +## Documentation + +The documentation and additional examples are available at +[godoc.org](http://godoc.org/github.com/pelletier/go-toml). + +## Tools + +Go-toml provides two handy command line tools: + +* `tomll`: Reads TOML files and lint them. + + ``` + go install github.com/pelletier/go-toml/cmd/tomll + tomll --help + ``` +* `tomljson`: Reads a TOML file and outputs its JSON representation. + + ``` + go install github.com/pelletier/go-toml/cmd/tomljson + tomljson --help + ``` + + * `jsontoml`: Reads a JSON file and outputs a TOML representation. + + ``` + go install github.com/pelletier/go-toml/cmd/jsontoml + jsontoml --help + ``` + +### Docker image + +Those tools are also availble as a Docker image from +[dockerhub](https://hub.docker.com/r/pelletier/go-toml). For example, to +use `tomljson`: + +``` +docker run -v $PWD:/workdir pelletier/go-toml tomljson /workdir/example.toml +``` + +Only master (`latest`) and tagged versions are published to dockerhub. You +can build your own image as usual: + +``` +docker build -t go-toml . +``` + +## Contribute + +Feel free to report bugs and patches using GitHub's pull requests system on +[pelletier/go-toml](https://github.com/pelletier/go-toml). Any feedback would be +much appreciated! + +### Run tests + +`go test ./...` + +### Fuzzing + +The script `./fuzz.sh` is available to +run [go-fuzz](https://github.com/dvyukov/go-fuzz) on go-toml. + +## Versioning + +Go-toml follows [Semantic Versioning](http://semver.org/). The supported version +of [TOML](https://github.com/toml-lang/toml) is indicated at the beginning of +this document. The last two major versions of Go are supported +(see [Go Release Policy](https://golang.org/doc/devel/release.html#policy)). + +## License + +The MIT License (MIT). Read [LICENSE](LICENSE). diff --git a/vendor/github.com/pelletier/go-toml/azure-pipelines.yml b/vendor/github.com/pelletier/go-toml/azure-pipelines.yml new file mode 100644 index 00000000000..d8d7944b79d --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/azure-pipelines.yml @@ -0,0 +1,167 @@ +trigger: +- master + +stages: +- stage: fuzzit + displayName: "Run Fuzzit" + dependsOn: [] + condition: and(succeeded(), eq(variables['Build.SourceBranchName'], 'master')) + jobs: + - job: submit + displayName: "Submit" + pool: + vmImage: ubuntu-latest + steps: + - task: GoTool@0 + displayName: "Install Go 1.13" + inputs: + version: "1.13" + - script: echo "##vso[task.setvariable variable=PATH]${PATH}:/home/vsts/go/bin/" + - script: mkdir -p ${HOME}/go/src/github.com/pelletier/go-toml + - script: cp -R . ${HOME}/go/src/github.com/pelletier/go-toml + - task: Bash@3 + inputs: + filePath: './fuzzit.sh' + env: + TYPE: fuzzing + FUZZIT_API_KEY: $(FUZZIT_API_KEY) + +- stage: run_checks + displayName: "Check" + dependsOn: [] + jobs: + - job: fmt + displayName: "fmt" + pool: + vmImage: ubuntu-latest + steps: + - task: GoTool@0 + displayName: "Install Go 1.13" + inputs: + version: "1.13" + - task: Go@0 + displayName: "go fmt ./..." + inputs: + command: 'custom' + customCommand: 'fmt' + arguments: './...' + - job: coverage + displayName: "coverage" + pool: + vmImage: ubuntu-latest + steps: + - task: GoTool@0 + displayName: "Install Go 1.13" + inputs: + version: "1.13" + - task: Go@0 + displayName: "Generate coverage" + inputs: + command: 'test' + arguments: "-race -coverprofile=coverage.txt -covermode=atomic" + - task: Bash@3 + inputs: + targetType: 'inline' + script: 'bash <(curl -s https://codecov.io/bash) -t $(CODECOV_TOKEN)' + - job: benchmark + displayName: "benchmark" + pool: + vmImage: ubuntu-latest + steps: + - task: GoTool@0 + displayName: "Install Go 1.13" + inputs: + version: "1.13" + - script: echo "##vso[task.setvariable variable=PATH]${PATH}:/home/vsts/go/bin/" + - task: Bash@3 + inputs: + filePath: './benchmark.sh' + arguments: "master $(Build.Repository.Uri)" + + - job: fuzzing + displayName: "fuzzing" + pool: + vmImage: ubuntu-latest + steps: + - task: GoTool@0 + displayName: "Install Go 1.13" + inputs: + version: "1.13" + - script: echo "##vso[task.setvariable variable=PATH]${PATH}:/home/vsts/go/bin/" + - script: mkdir -p ${HOME}/go/src/github.com/pelletier/go-toml + - script: cp -R . ${HOME}/go/src/github.com/pelletier/go-toml + - task: Bash@3 + inputs: + filePath: './fuzzit.sh' + env: + TYPE: local-regression + + - job: go_unit_tests + displayName: "unit tests" + strategy: + matrix: + linux 1.13: + goVersion: '1.13' + imageName: 'ubuntu-latest' + mac 1.13: + goVersion: '1.13' + imageName: 'macos-10.13' + windows 1.13: + goVersion: '1.13' + imageName: 'vs2017-win2016' + linux 1.12: + goVersion: '1.12' + imageName: 'ubuntu-latest' + mac 1.12: + goVersion: '1.12' + imageName: 'macos-10.13' + windows 1.12: + goVersion: '1.12' + imageName: 'vs2017-win2016' + pool: + vmImage: $(imageName) + steps: + - task: GoTool@0 + displayName: "Install Go $(goVersion)" + inputs: + version: $(goVersion) + - task: Go@0 + displayName: "go test ./..." + inputs: + command: 'test' + arguments: './...' + +- stage: build_docker_image + displayName: "Build Docker image" + dependsOn: run_checks + jobs: + - job: build + displayName: "Build" + pool: + vmImage: ubuntu-latest + steps: + - task: Docker@2 + inputs: + command: 'build' + Dockerfile: 'Dockerfile' + buildContext: '.' + addPipelineData: false + +- stage: publish_docker_image + displayName: "Publish Docker image" + dependsOn: build_docker_image + condition: and(succeeded(), eq(variables['Build.SourceBranchName'], 'master')) + jobs: + - job: publish + displayName: "Publish" + pool: + vmImage: ubuntu-latest + steps: + - task: Docker@2 + inputs: + containerRegistry: 'DockerHub' + repository: 'pelletier/go-toml' + command: 'buildAndPush' + Dockerfile: 'Dockerfile' + buildContext: '.' + tags: 'latest' \ No newline at end of file diff --git a/vendor/github.com/pelletier/go-toml/benchmark.json b/vendor/github.com/pelletier/go-toml/benchmark.json new file mode 100644 index 00000000000..86f99c6a877 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/benchmark.json @@ -0,0 +1,164 @@ +{ + "array": { + "key1": [ + 1, + 2, + 3 + ], + "key2": [ + "red", + "yellow", + "green" + ], + "key3": [ + [ + 1, + 2 + ], + [ + 3, + 4, + 5 + ] + ], + "key4": [ + [ + 1, + 2 + ], + [ + "a", + "b", + "c" + ] + ], + "key5": [ + 1, + 2, + 3 + ], + "key6": [ + 1, + 2 + ] + }, + "boolean": { + "False": false, + "True": true + }, + "datetime": { + "key1": "1979-05-27T07:32:00Z", + "key2": "1979-05-27T00:32:00-07:00", + "key3": "1979-05-27T00:32:00.999999-07:00" + }, + "float": { + "both": { + "key": 6.626e-34 + }, + "exponent": { + "key1": 5e+22, + "key2": 1000000, + "key3": -0.02 + }, + "fractional": { + "key1": 1, + "key2": 3.1415, + "key3": -0.01 + }, + "underscores": { + "key1": 9224617.445991227, + "key2": 1e+100 + } + }, + "fruit": [{ + "name": "apple", + "physical": { + "color": "red", + "shape": "round" + }, + "variety": [{ + "name": "red delicious" + }, + { + "name": "granny smith" + } + ] + }, + { + "name": "banana", + "variety": [{ + "name": "plantain" + }] + } + ], + "integer": { + "key1": 99, + "key2": 42, + "key3": 0, + "key4": -17, + "underscores": { + "key1": 1000, + "key2": 5349221, + "key3": 12345 + } + }, + "products": [{ + "name": "Hammer", + "sku": 738594937 + }, + {}, + { + "color": "gray", + "name": "Nail", + "sku": 284758393 + } + ], + "string": { + "basic": { + "basic": "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF." + }, + "literal": { + "multiline": { + "lines": "The first newline is\ntrimmed in raw strings.\n All other whitespace\n is preserved.\n", + "regex2": "I [dw]on't need \\d{2} apples" + }, + "quoted": "Tom \"Dubs\" Preston-Werner", + "regex": "\u003c\\i\\c*\\s*\u003e", + "winpath": "C:\\Users\\nodejs\\templates", + "winpath2": "\\\\ServerX\\admin$\\system32\\" + }, + "multiline": { + "continued": { + "key1": "The quick brown fox jumps over the lazy dog.", + "key2": "The quick brown fox jumps over the lazy dog.", + "key3": "The quick brown fox jumps over the lazy dog." + }, + "key1": "One\nTwo", + "key2": "One\nTwo", + "key3": "One\nTwo" + } + }, + "table": { + "inline": { + "name": { + "first": "Tom", + "last": "Preston-Werner" + }, + "point": { + "x": 1, + "y": 2 + } + }, + "key": "value", + "subtable": { + "key": "another value" + } + }, + "x": { + "y": { + "z": { + "w": {} + } + } + } +} diff --git a/vendor/github.com/pelletier/go-toml/benchmark.sh b/vendor/github.com/pelletier/go-toml/benchmark.sh new file mode 100644 index 00000000000..7914fff49c9 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/benchmark.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +set -ex + +reference_ref=${1:-master} +reference_git=${2:-.} + +if ! `hash benchstat 2>/dev/null`; then + echo "Installing benchstat" + go get golang.org/x/perf/cmd/benchstat +fi + +tempdir=`mktemp -d /tmp/go-toml-benchmark-XXXXXX` +ref_tempdir="${tempdir}/ref" +ref_benchmark="${ref_tempdir}/benchmark-`echo -n ${reference_ref}|tr -s '/' '-'`.txt" +local_benchmark="`pwd`/benchmark-local.txt" + +echo "=== ${reference_ref} (${ref_tempdir})" +git clone ${reference_git} ${ref_tempdir} >/dev/null 2>/dev/null +pushd ${ref_tempdir} >/dev/null +git checkout ${reference_ref} >/dev/null 2>/dev/null +go test -bench=. -benchmem | tee ${ref_benchmark} +popd >/dev/null + +echo "" +echo "=== local" +go test -bench=. -benchmem | tee ${local_benchmark} + +echo "" +echo "=== diff" +benchstat -delta-test=none ${ref_benchmark} ${local_benchmark} diff --git a/vendor/github.com/pelletier/go-toml/benchmark.toml b/vendor/github.com/pelletier/go-toml/benchmark.toml new file mode 100644 index 00000000000..dfd77e09622 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/benchmark.toml @@ -0,0 +1,244 @@ +################################################################################ +## Comment + +# Speak your mind with the hash symbol. They go from the symbol to the end of +# the line. + + +################################################################################ +## Table + +# Tables (also known as hash tables or dictionaries) are collections of +# key/value pairs. They appear in square brackets on a line by themselves. + +[table] + +key = "value" # Yeah, you can do this. + +# Nested tables are denoted by table names with dots in them. Name your tables +# whatever crap you please, just don't use #, ., [ or ]. + +[table.subtable] + +key = "another value" + +# You don't need to specify all the super-tables if you don't want to. TOML +# knows how to do it for you. + +# [x] you +# [x.y] don't +# [x.y.z] need these +[x.y.z.w] # for this to work + + +################################################################################ +## Inline Table + +# Inline tables provide a more compact syntax for expressing tables. They are +# especially useful for grouped data that can otherwise quickly become verbose. +# Inline tables are enclosed in curly braces `{` and `}`. No newlines are +# allowed between the curly braces unless they are valid within a value. + +[table.inline] + +name = { first = "Tom", last = "Preston-Werner" } +point = { x = 1, y = 2 } + + +################################################################################ +## String + +# There are four ways to express strings: basic, multi-line basic, literal, and +# multi-line literal. All strings must contain only valid UTF-8 characters. + +[string.basic] + +basic = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF." + +[string.multiline] + +# The following strings are byte-for-byte equivalent: +key1 = "One\nTwo" +key2 = """One\nTwo""" +key3 = """ +One +Two""" + +[string.multiline.continued] + +# The following strings are byte-for-byte equivalent: +key1 = "The quick brown fox jumps over the lazy dog." + +key2 = """ +The quick brown \ + + + fox jumps over \ + the lazy dog.""" + +key3 = """\ + The quick brown \ + fox jumps over \ + the lazy dog.\ + """ + +[string.literal] + +# What you see is what you get. +winpath = 'C:\Users\nodejs\templates' +winpath2 = '\\ServerX\admin$\system32\' +quoted = 'Tom "Dubs" Preston-Werner' +regex = '<\i\c*\s*>' + + +[string.literal.multiline] + +regex2 = '''I [dw]on't need \d{2} apples''' +lines = ''' +The first newline is +trimmed in raw strings. + All other whitespace + is preserved. +''' + + +################################################################################ +## Integer + +# Integers are whole numbers. Positive numbers may be prefixed with a plus sign. +# Negative numbers are prefixed with a minus sign. + +[integer] + +key1 = +99 +key2 = 42 +key3 = 0 +key4 = -17 + +[integer.underscores] + +# For large numbers, you may use underscores to enhance readability. Each +# underscore must be surrounded by at least one digit. +key1 = 1_000 +key2 = 5_349_221 +key3 = 1_2_3_4_5 # valid but inadvisable + + +################################################################################ +## Float + +# A float consists of an integer part (which may be prefixed with a plus or +# minus sign) followed by a fractional part and/or an exponent part. + +[float.fractional] + +key1 = +1.0 +key2 = 3.1415 +key3 = -0.01 + +[float.exponent] + +key1 = 5e+22 +key2 = 1e6 +key3 = -2E-2 + +[float.both] + +key = 6.626e-34 + +[float.underscores] + +key1 = 9_224_617.445_991_228_313 +key2 = 1e1_00 + + +################################################################################ +## Boolean + +# Booleans are just the tokens you're used to. Always lowercase. + +[boolean] + +True = true +False = false + + +################################################################################ +## Datetime + +# Datetimes are RFC 3339 dates. + +[datetime] + +key1 = 1979-05-27T07:32:00Z +key2 = 1979-05-27T00:32:00-07:00 +key3 = 1979-05-27T00:32:00.999999-07:00 + + +################################################################################ +## Array + +# Arrays are square brackets with other primitives inside. Whitespace is +# ignored. Elements are separated by commas. Data types may not be mixed. + +[array] + +key1 = [ 1, 2, 3 ] +key2 = [ "red", "yellow", "green" ] +key3 = [ [ 1, 2 ], [3, 4, 5] ] +#key4 = [ [ 1, 2 ], ["a", "b", "c"] ] # this is ok + +# Arrays can also be multiline. So in addition to ignoring whitespace, arrays +# also ignore newlines between the brackets. Terminating commas are ok before +# the closing bracket. + +key5 = [ + 1, 2, 3 +] +key6 = [ + 1, + 2, # this is ok +] + + +################################################################################ +## Array of Tables + +# These can be expressed by using a table name in double brackets. Each table +# with the same double bracketed name will be an element in the array. The +# tables are inserted in the order encountered. + +[[products]] + +name = "Hammer" +sku = 738594937 + +[[products]] + +[[products]] + +name = "Nail" +sku = 284758393 +color = "gray" + + +# You can create nested arrays of tables as well. + +[[fruit]] + name = "apple" + + [fruit.physical] + color = "red" + shape = "round" + + [[fruit.variety]] + name = "red delicious" + + [[fruit.variety]] + name = "granny smith" + +[[fruit]] + name = "banana" + + [[fruit.variety]] + name = "plantain" diff --git a/vendor/github.com/pelletier/go-toml/benchmark.yml b/vendor/github.com/pelletier/go-toml/benchmark.yml new file mode 100644 index 00000000000..0bd19f08a69 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/benchmark.yml @@ -0,0 +1,121 @@ +--- +array: + key1: + - 1 + - 2 + - 3 + key2: + - red + - yellow + - green + key3: + - - 1 + - 2 + - - 3 + - 4 + - 5 + key4: + - - 1 + - 2 + - - a + - b + - c + key5: + - 1 + - 2 + - 3 + key6: + - 1 + - 2 +boolean: + 'False': false + 'True': true +datetime: + key1: '1979-05-27T07:32:00Z' + key2: '1979-05-27T00:32:00-07:00' + key3: '1979-05-27T00:32:00.999999-07:00' +float: + both: + key: 6.626e-34 + exponent: + key1: 5.0e+22 + key2: 1000000 + key3: -0.02 + fractional: + key1: 1 + key2: 3.1415 + key3: -0.01 + underscores: + key1: 9224617.445991227 + key2: 1.0e+100 +fruit: +- name: apple + physical: + color: red + shape: round + variety: + - name: red delicious + - name: granny smith +- name: banana + variety: + - name: plantain +integer: + key1: 99 + key2: 42 + key3: 0 + key4: -17 + underscores: + key1: 1000 + key2: 5349221 + key3: 12345 +products: +- name: Hammer + sku: 738594937 +- {} +- color: gray + name: Nail + sku: 284758393 +string: + basic: + basic: "I'm a string. \"You can quote me\". Name\tJosé\nLocation\tSF." + literal: + multiline: + lines: | + The first newline is + trimmed in raw strings. + All other whitespace + is preserved. + regex2: I [dw]on't need \d{2} apples + quoted: Tom "Dubs" Preston-Werner + regex: "<\\i\\c*\\s*>" + winpath: C:\Users\nodejs\templates + winpath2: "\\\\ServerX\\admin$\\system32\\" + multiline: + continued: + key1: The quick brown fox jumps over the lazy dog. + key2: The quick brown fox jumps over the lazy dog. + key3: The quick brown fox jumps over the lazy dog. + key1: |- + One + Two + key2: |- + One + Two + key3: |- + One + Two +table: + inline: + name: + first: Tom + last: Preston-Werner + point: + x: 1 + y: 2 + key: value + subtable: + key: another value +x: + y: + z: + w: {} diff --git a/vendor/github.com/pelletier/go-toml/example-crlf.toml b/vendor/github.com/pelletier/go-toml/example-crlf.toml new file mode 100644 index 00000000000..12950a163d3 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/example-crlf.toml @@ -0,0 +1,29 @@ +# This is a TOML document. Boom. + +title = "TOML Example" + +[owner] +name = "Tom Preston-Werner" +organization = "GitHub" +bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." +dob = 1979-05-27T07:32:00Z # First class dates? Why not? + +[database] +server = "192.168.1.1" +ports = [ 8001, 8001, 8002 ] +connection_max = 5000 +enabled = true + +[servers] + + # You can indent as you please. Tabs or spaces. TOML don't care. + [servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + + [servers.beta] + ip = "10.0.0.2" + dc = "eqdc10" + +[clients] +data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it diff --git a/vendor/github.com/pelletier/go-toml/example.toml b/vendor/github.com/pelletier/go-toml/example.toml new file mode 100644 index 00000000000..3d902f28207 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/example.toml @@ -0,0 +1,29 @@ +# This is a TOML document. Boom. + +title = "TOML Example" + +[owner] +name = "Tom Preston-Werner" +organization = "GitHub" +bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." +dob = 1979-05-27T07:32:00Z # First class dates? Why not? + +[database] +server = "192.168.1.1" +ports = [ 8001, 8001, 8002 ] +connection_max = 5000 +enabled = true + +[servers] + + # You can indent as you please. Tabs or spaces. TOML don't care. + [servers.alpha] + ip = "10.0.0.1" + dc = "eqdc10" + + [servers.beta] + ip = "10.0.0.2" + dc = "eqdc10" + +[clients] +data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it diff --git a/vendor/github.com/pelletier/go-toml/fuzz.sh b/vendor/github.com/pelletier/go-toml/fuzz.sh new file mode 100644 index 00000000000..3204b4c4463 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/fuzz.sh @@ -0,0 +1,15 @@ +#! /bin/sh +set -eu + +go get github.com/dvyukov/go-fuzz/go-fuzz +go get github.com/dvyukov/go-fuzz/go-fuzz-build + +if [ ! -e toml-fuzz.zip ]; then + go-fuzz-build github.com/pelletier/go-toml +fi + +rm -fr fuzz +mkdir -p fuzz/corpus +cp *.toml fuzz/corpus + +go-fuzz -bin=toml-fuzz.zip -workdir=fuzz diff --git a/vendor/github.com/pelletier/go-toml/fuzzit.sh b/vendor/github.com/pelletier/go-toml/fuzzit.sh new file mode 100644 index 00000000000..b575a6081f0 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/fuzzit.sh @@ -0,0 +1,26 @@ +#!/bin/bash +set -xe + +# go-fuzz doesn't support modules yet, so ensure we do everything +# in the old style GOPATH way +export GO111MODULE="off" + +# install go-fuzz +go get -u github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-build + +# target name can only contain lower-case letters (a-z), digits (0-9) and a dash (-) +# to add another target, make sure to create it with `fuzzit create target` +# before using `fuzzit create job` +TARGET=toml-fuzzer + +go-fuzz-build -libfuzzer -o ${TARGET}.a github.com/pelletier/go-toml +clang -fsanitize=fuzzer ${TARGET}.a -o ${TARGET} + +# install fuzzit for talking to fuzzit.dev service +# or latest version: +# https://github.com/fuzzitdev/fuzzit/releases/latest/download/fuzzit_Linux_x86_64 +wget -q -O fuzzit https://github.com/fuzzitdev/fuzzit/releases/download/v2.4.52/fuzzit_Linux_x86_64 +chmod a+x fuzzit + +# TODO: change kkowalczyk to go-toml and create toml-fuzzer target there +./fuzzit create job --type $TYPE go-toml/${TARGET} ${TARGET} diff --git a/vendor/github.com/pelletier/go-toml/go.mod b/vendor/github.com/pelletier/go-toml/go.mod new file mode 100644 index 00000000000..a17e9331f1f --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/go.mod @@ -0,0 +1,9 @@ +module github.com/pelletier/go-toml + +go 1.12 + +require ( + github.com/BurntSushi/toml v0.3.1 + github.com/davecgh/go-spew v1.1.1 + gopkg.in/yaml.v2 v2.2.4 +) diff --git a/vendor/github.com/pelletier/go-toml/go.sum b/vendor/github.com/pelletier/go-toml/go.sum new file mode 100644 index 00000000000..1cd2613ddd6 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/go.sum @@ -0,0 +1,11 @@ +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI= +gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/pelletier/go-toml/marshal_OrderPreserve_test.toml b/vendor/github.com/pelletier/go-toml/marshal_OrderPreserve_test.toml new file mode 100644 index 00000000000..792b72ed721 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/marshal_OrderPreserve_test.toml @@ -0,0 +1,39 @@ +title = "TOML Marshal Testing" + +[basic_lists] + floats = [12.3,45.6,78.9] + bools = [true,false,true] + dates = [1979-05-27T07:32:00Z,1980-05-27T07:32:00Z] + ints = [8001,8001,8002] + uints = [5002,5003] + strings = ["One","Two","Three"] + +[[subdocptrs]] + name = "Second" + +[basic_map] + one = "one" + two = "two" + +[subdoc] + + [subdoc.second] + name = "Second" + + [subdoc.first] + name = "First" + +[basic] + uint = 5001 + bool = true + float = 123.4 + float64 = 123.456782132399 + int = 5000 + string = "Bite me" + date = 1979-05-27T07:32:00Z + +[[subdoclist]] + name = "List.First" + +[[subdoclist]] + name = "List.Second" diff --git a/vendor/github.com/pelletier/go-toml/marshal_test.toml b/vendor/github.com/pelletier/go-toml/marshal_test.toml new file mode 100644 index 00000000000..ba5e110bf04 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/marshal_test.toml @@ -0,0 +1,39 @@ +title = "TOML Marshal Testing" + +[basic] + bool = true + date = 1979-05-27T07:32:00Z + float = 123.4 + float64 = 123.456782132399 + int = 5000 + string = "Bite me" + uint = 5001 + +[basic_lists] + bools = [true,false,true] + dates = [1979-05-27T07:32:00Z,1980-05-27T07:32:00Z] + floats = [12.3,45.6,78.9] + ints = [8001,8001,8002] + strings = ["One","Two","Three"] + uints = [5002,5003] + +[basic_map] + one = "one" + two = "two" + +[subdoc] + + [subdoc.first] + name = "First" + + [subdoc.second] + name = "Second" + +[[subdoclist]] + name = "List.First" + +[[subdoclist]] + name = "List.Second" + +[[subdocptrs]] + name = "Second" diff --git a/vendor/github.com/phayes/freeport/.gitignore b/vendor/github.com/phayes/freeport/.gitignore new file mode 100644 index 00000000000..1521c8b7652 --- /dev/null +++ b/vendor/github.com/phayes/freeport/.gitignore @@ -0,0 +1 @@ +dist diff --git a/vendor/github.com/phayes/freeport/.goreleaser.yml b/vendor/github.com/phayes/freeport/.goreleaser.yml new file mode 100644 index 00000000000..48044ea396b --- /dev/null +++ b/vendor/github.com/phayes/freeport/.goreleaser.yml @@ -0,0 +1,134 @@ +project_name: freeport + +release: + github: + owner: phayes + name: freeport + +builds: + - binary: freeport + goos: + - linux + - darwin + goarch: + - amd64 + - "386" + goarm: + - "6" + main: ./cmd/freeport + ldflags: -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}} + +archive: + format: tar.gz + name_template: '{{ .Binary }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ + .Arm }}{{ end }}' + files: + - licence* + - LICENCE* + - license* + - LICENSE* + - readme* + - README* + - changelog* + - CHANGELOG* + +snapshot: + name_template: SNAPSHOT-{{ .Commit }} + +checksum: + name_template: '{{ .ProjectName }}_{{ .Version }}_checksums.txt' + +# Create RPM and .DEB files +fpm: + vendor: Patrick Hayes + + # Your app's homepage. + #homepage: https://example.com/ + + # Your app's maintainer + maintainer: Patrick Hayes + + # Your app's description. + description: Get a free open TCP port that is ready to use. + + # Your app's license. + # Default is empty. + license: BSD + + # Formats to be generated. + formats: + - deb + - rpm + + # Packages your package depends on. + #dependencies: + # - git + # - zsh + + # Packages that conflict with your package. + #conflicts: + # - svn + # - bash + + # Files or directories to add to your package (beyond the binary). + # Keys are source paths to get the files from. + # Values are the destination locations of the files in the package. + #files: + # "scripts/etc/init.d/": "/etc/init.d" + +# Homebrew repos +brew: + # Reporitory to push the tap to. + github: + owner: phayes + name: homebrew-repo + + # Git author used to commit to the repository. + # Defaults are shown. + commit_author: + name: goreleaserbot + email: goreleaser@carlosbecker.com + + # Folder inside the repository to put the formula. + # Default is the root folder. + # folder: . + + # Caveats for the user of your binary. + # Default is empty. + # caveats: "How to use this binary" + + # Your app's homepage. + # Default is empty. + # homepage: "https://example.com/" + + # Your app's description. + # Default is empty. + description: "Get a free open TCP port that is ready to use." + + # Packages your package depends on. + #dependencies: + # - git + # - zsh + + # Packages that conflict with your package. + #conflicts: + # - svn + # - bash + + # Specify for packages that run as a service. + # Default is empty. + #plist: | + # + # ... + + # So you can `brew test` your formula. + # Default is empty. + #test: | + # system "#{bin}/program --version" + # ... + + # Custom install script for brew. + # Default is 'bin.install "program"'. + #install: | + # bin.install "program" + # ... \ No newline at end of file diff --git a/vendor/github.com/phayes/freeport/README.md b/vendor/github.com/phayes/freeport/README.md new file mode 100644 index 00000000000..1665ccf4d4f --- /dev/null +++ b/vendor/github.com/phayes/freeport/README.md @@ -0,0 +1,58 @@ +FreePort +======== + +Get a free open TCP port that is ready to use. + +## Command Line Example: +```bash +# Ask the kernel to give us an open port. +export port=$(freeport) + +# Start standalone httpd server for testing +httpd -X -c "Listen $port" & + +# Curl local server on the selected port +curl localhost:$port +``` + +## Golang example: +```go +package main + +import "github.com/phayes/freeport" + +func main() { + port, err := freeport.GetFreePort() + if err != nil { + log.Fatal(err) + } + // port is ready to listen on +} + +``` + +## Installation + +#### Mac OSX +```bash +brew install phayes/repo/freeport +``` + + +#### CentOS and other RPM based systems +```bash +wget https://github.com/phayes/freeport/releases/download/1.0.2/freeport_1.0.2_linux_386.rpm +rpm -Uvh freeport_1.0.2_linux_386.rpm +``` + +#### Ubuntu and other DEB based systems +```bash +wget wget https://github.com/phayes/freeport/releases/download/1.0.2/freeport_1.0.2_linux_amd64.deb +dpkg -i freeport_1.0.2_linux_amd64.deb +``` + +#### Building From Source +```bash +sudo apt-get install golang # Download go. Alternativly build from source: https://golang.org/doc/install/source +go get github.com/phayes/freeport +``` diff --git a/vendor/github.com/phayes/freeport/freeport.go b/vendor/github.com/phayes/freeport/freeport.go index c44b60df278..fcfb6bab036 100644 --- a/vendor/github.com/phayes/freeport/freeport.go +++ b/vendor/github.com/phayes/freeport/freeport.go @@ -28,3 +28,22 @@ func GetPort() int { } return port } + +// GetFreePort asks the kernel for free open ports that are ready to use. +func GetFreePorts(count int) ([]int, error) { + var ports []int + for i := 0; i < count; i++ { + addr, err := net.ResolveTCPAddr("tcp", "localhost:0") + if err != nil { + return nil, err + } + + l, err := net.ListenTCP("tcp", addr) + if err != nil { + return nil, err + } + defer l.Close() + ports = append(ports, l.Addr().(*net.TCPAddr).Port) + } + return ports, nil +} diff --git a/vendor/github.com/wavesoftware/go-ensure/.editorconfig b/vendor/github.com/wavesoftware/go-ensure/.editorconfig new file mode 100644 index 00000000000..25d2a11a993 --- /dev/null +++ b/vendor/github.com/wavesoftware/go-ensure/.editorconfig @@ -0,0 +1,15 @@ +# EditorConfig is awesome: https://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = space +indent_size = 2 + +[*.go] +indent_style = tab diff --git a/vendor/github.com/wavesoftware/go-ensure/.gitignore b/vendor/github.com/wavesoftware/go-ensure/.gitignore new file mode 100644 index 00000000000..e67b8a3c6f4 --- /dev/null +++ b/vendor/github.com/wavesoftware/go-ensure/.gitignore @@ -0,0 +1,17 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +vendor/ + +build/ diff --git a/vendor/github.com/wavesoftware/go-ensure/.travis.yml b/vendor/github.com/wavesoftware/go-ensure/.travis.yml new file mode 100644 index 00000000000..2f4b5c2f147 --- /dev/null +++ b/vendor/github.com/wavesoftware/go-ensure/.travis.yml @@ -0,0 +1,15 @@ +--- +language: go +sudo: false +dist: bionic +go: + - 1.13.x +script: + - make clean test +branches: + only: + - master + - develop + - "/^v\\d/" +notifications: + email: onchange diff --git a/vendor/github.com/wavesoftware/go-ensure/Makefile b/vendor/github.com/wavesoftware/go-ensure/Makefile new file mode 100644 index 00000000000..afa4896e3a7 --- /dev/null +++ b/vendor/github.com/wavesoftware/go-ensure/Makefile @@ -0,0 +1,32 @@ +PROJECT_DIR = $(shell readlink -f .) +BUILD_DIR = "$(PROJECT_DIR)/build" + +GO ?= go +RICHGO ?= rich$(GO) + +.PHONY: default +default: binaries + +.PHONY: builddeps +builddeps: + @GO111MODULE=off $(GO) get github.com/kyoh86/richgo + @GO111MODULE=off $(GO) get github.com/mgechev/revive + +.PHONY: builddir +builddir: + @mkdir -p build + +.PHONY: clean +clean: builddeps + @echo "🛁 Cleaning" + @rm -frv $(BUILD_DIR) + +.PHONY: check +check: builddeps + @echo "🛂 Checking" + revive -config revive.toml -formatter stylish ./... + +.PHONY: test +test: builddir check + @echo "✔️ Testing" + $(RICHGO) test -v -covermode=count -coverprofile=build/coverage.out ./... diff --git a/vendor/github.com/wavesoftware/go-ensure/README.md b/vendor/github.com/wavesoftware/go-ensure/README.md new file mode 100644 index 00000000000..82e73e4525d --- /dev/null +++ b/vendor/github.com/wavesoftware/go-ensure/README.md @@ -0,0 +1,55 @@ +# Ensure for Go + +A simple ensure package for Golang + +## Use case + +Writing a Go code makes a lot of repetition, regarding error checking. That's +especially true for end user code like e2e tests when we expect that something +will work. In other cases that's a bug and should code should panic then. + +## Usage + +Instead of writing: + +```go +func DeployAllComponents() error { + alpha, err := deployAlpha() + if err != nil { + return errors.WithMessage(err, "unexpected error") + } + beta, err := deployBeta(alpha) + if err != nil { + return errors.WithMessage(err, "unexpected error") + } + _, err := deployGamma(beta) + if err != nil { + return errors.WithMessage(err, "unexpected error") + } + return nil +} + +// execution isn't simple +err = DeployAllComponents() +if err != nil { + panic(err) +} +``` + +with this PR I can write it like: + +```go +func DeployAllComponents() { + alpha, err := deployAlpha() + ensure.NoError(err) + beta, err := deployBeta(alpha) + ensure.NoError(err) + _, err := deployGamma(beta) + ensure.NoError(err) +} + +// execution is simple +DeployAllComponents() +``` + +Above is much more readable and pleasant to see. diff --git a/vendor/github.com/wavesoftware/go-ensure/go.mod b/vendor/github.com/wavesoftware/go-ensure/go.mod new file mode 100644 index 00000000000..06dbff11848 --- /dev/null +++ b/vendor/github.com/wavesoftware/go-ensure/go.mod @@ -0,0 +1,5 @@ +module github.com/wavesoftware/go-ensure + +go 1.13 + +require github.com/pkg/errors v0.9.1 diff --git a/vendor/github.com/wavesoftware/go-ensure/go.sum b/vendor/github.com/wavesoftware/go-ensure/go.sum new file mode 100644 index 00000000000..7c401c3f58b --- /dev/null +++ b/vendor/github.com/wavesoftware/go-ensure/go.sum @@ -0,0 +1,2 @@ +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= diff --git a/vendor/github.com/wavesoftware/go-ensure/revive.toml b/vendor/github.com/wavesoftware/go-ensure/revive.toml new file mode 100644 index 00000000000..a4cb9ecd72e --- /dev/null +++ b/vendor/github.com/wavesoftware/go-ensure/revive.toml @@ -0,0 +1,35 @@ +# When set to false, ignores files with "GENERATED" header, similar to golint +ignoreGeneratedHeader = true + +# Sets the default severity to "warning" +severity = "warning" + +# Sets the default failure confidence. This means that linting errors +# with less than 0.8 confidence will be ignored. +confidence = 0.8 + +# Sets the error code for failures with severity "error" +errorCode = 102 + +# Sets the error code for failures with severity "warning" +warningCode = 102 + +[rule.blank-imports] +[rule.context-as-argument] +[rule.context-keys-type] +[rule.dot-imports] +[rule.error-return] +[rule.error-strings] +[rule.error-naming] +[rule.exported] +[rule.if-return] +[rule.increment-decrement] +[rule.var-naming] +[rule.var-declaration] +[rule.package-comments] +[rule.range] +[rule.receiver-naming] +[rule.time-naming] +[rule.unexported-return] +[rule.indent-error-flow] +[rule.errorf] diff --git a/vendor/modules.txt b/vendor/modules.txt index d6f20b7a692..91b4c442567 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -199,6 +199,8 @@ github.com/mailru/easyjson/jwriter github.com/markbates/inflect # github.com/matttproud/golang_protobuf_extensions v1.0.1 github.com/matttproud/golang_protobuf_extensions/pbutil +# github.com/mitchellh/go-homedir v1.1.0 +github.com/mitchellh/go-homedir # github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd github.com/modern-go/concurrent # github.com/modern-go/reflect2 v1.0.1 @@ -210,6 +212,10 @@ github.com/openzipkin/zipkin-go/model github.com/openzipkin/zipkin-go/propagation github.com/openzipkin/zipkin-go/reporter github.com/openzipkin/zipkin-go/reporter/http +# github.com/pelletier/go-toml v1.6.0 +github.com/pelletier/go-toml +# github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 +github.com/phayes/freeport # github.com/pkg/errors v0.9.1 github.com/pkg/errors # github.com/pmezard/go-difflib v1.0.0 @@ -245,6 +251,8 @@ github.com/stretchr/testify/require github.com/tsenart/vegeta/lib # github.com/valyala/bytebufferpool v1.0.0 github.com/valyala/bytebufferpool +# github.com/wavesoftware/go-ensure v1.0.0 +github.com/wavesoftware/go-ensure # go.opencensus.io v0.22.3 go.opencensus.io go.opencensus.io/internal From 36b0a943666935173ac3566fcca26d68a7d84c0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Fri, 8 May 2020 13:55:20 +0200 Subject: [PATCH 44/50] Cleanups after automatic review --- test/lib/resources/serving.go | 24 +++++++++++++++++++ test/prober/wathola/README.md | 2 +- test/prober/wathola/client/receiver.go | 2 +- test/prober/wathola/config/defaults.go | 2 +- test/prober/wathola/config/reader_test.go | 2 +- test/prober/wathola/event/types.go | 6 ++--- test/prober/wathola/event/types_test.go | 4 ++-- .../wathola-forwarder/main_test.go | 2 +- .../test_images/wathola-receiver/main_test.go | 2 +- 9 files changed, 35 insertions(+), 11 deletions(-) diff --git a/test/lib/resources/serving.go b/test/lib/resources/serving.go index f3cdc63dd6a..11cbab1800a 100644 --- a/test/lib/resources/serving.go +++ b/test/lib/resources/serving.go @@ -26,6 +26,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/client-go/dynamic" + eventingv1alpha1 "knative.dev/eventing/pkg/apis/eventing/v1alpha1" + duckv1 "knative.dev/pkg/apis/duck/v1" pkgTest "knative.dev/pkg/test" ) @@ -41,6 +43,28 @@ type KServiceRoute struct { DeploymentName string } +// WithSubscriberKServiceRefForTrigger returns an option that adds a Subscriber +// Knative Service Ref for the given Trigger. +func WithSubscriberKServiceRefForTrigger(name string) TriggerOption { + return func(t *eventingv1alpha1.Trigger) { + if name != "" { + t.Spec.Subscriber = duckv1.Destination{ + Ref: KnativeRefForKservice(name, t.Namespace), + } + } + } +} + +// KnativeRefForKservice return a duck reference for Knative Service +func KnativeRefForKservice(name, namespace string) *duckv1.KReference { + return &duckv1.KReference{ + Kind: KServiceKind, + APIVersion: ServingAPIVersion, + Name: name, + Namespace: namespace, + } +} + // KServiceRef returns a Knative Service ObjectReference for a given Service name. func KServiceRef(name string) *corev1.ObjectReference { return pkgTest.CoreV1ObjectReference(KServiceKind, ServingAPIVersion, name) diff --git a/test/prober/wathola/README.md b/test/prober/wathola/README.md index 2abfc564c65..a1b1dbf7fb4 100644 --- a/test/prober/wathola/README.md +++ b/test/prober/wathola/README.md @@ -1,3 +1,3 @@ # Wathola -A cloudevents mass assurer tool (wathola - "he receive" in zulu) +A cloudevents mass assurer tool (wathola - "he receive" in zulu) diff --git a/test/prober/wathola/client/receiver.go b/test/prober/wathola/client/receiver.go index 0792f8aa7a7..300aed431f5 100644 --- a/test/prober/wathola/client/receiver.go +++ b/test/prober/wathola/client/receiver.go @@ -36,7 +36,7 @@ func Receive( port int, cancelRegistrar func(*context.CancelFunc), receiveEvent ReceiveEvent, - middlewares ... cloudeventshttp.Middleware) { + middlewares ...cloudeventshttp.Middleware) { portOpt := cloudevents.WithPort(port) opts := make([]cloudeventshttp.Option, 0) opts = append(opts, portOpt) diff --git a/test/prober/wathola/config/defaults.go b/test/prober/wathola/config/defaults.go index e2bfd8ced14..ff28864a429 100644 --- a/test/prober/wathola/config/defaults.go +++ b/test/prober/wathola/config/defaults.go @@ -28,7 +28,7 @@ import ( const ( // DefaultReceiverPort point to a default port of receiver component, and is // unique so that components can be easily run on localhost for easy debugging - DefaultReceiverPort = 22111 + DefaultReceiverPort = 22111 // DefaultForwarderPort point to a default port of forwarder component DefaultForwarderPort = 22110 ) diff --git a/test/prober/wathola/config/reader_test.go b/test/prober/wathola/config/reader_test.go index 13f03c8e83b..aac038d53f2 100644 --- a/test/prober/wathola/config/reader_test.go +++ b/test/prober/wathola/config/reader_test.go @@ -53,7 +53,7 @@ address = 'http://default-broker.event-example.svc.cluster.local/' func TestReadIfPresentAndInvalid(t *testing.T) { // given origLogFatal := logFatal - defer func() { logFatal = origLogFatal } () + defer func() { logFatal = origLogFatal }() expanded := ensureConfigFileNotPresent() data := []byte(`[sender] address = 'http://default-broker.event-example.svc.cluster.local/ diff --git a/test/prober/wathola/event/types.go b/test/prober/wathola/event/types.go index 020913dd5f8..3fb16f007d3 100644 --- a/test/prober/wathola/event/types.go +++ b/test/prober/wathola/event/types.go @@ -19,7 +19,7 @@ import "knative.dev/eventing/test/prober/wathola/config" const ( // StepType is a string type representation of step event - StepType = "com.github.cardil.wathola.step" + StepType = "com.github.cardil.wathola.step" // FinishedType os a string type representation of finished event FinishedType = "com.github.cardil.wathola.finished" ) @@ -49,11 +49,11 @@ type State int const ( // Active == 1 (iota has been reset) - Active State = 1 << iota + Active State = 1 << iota // Success == 2 Success State = 1 << iota // Failed == 4 - Failed State = 1 << iota + Failed State = 1 << iota ) var log = config.Log diff --git a/test/prober/wathola/event/types_test.go b/test/prober/wathola/event/types_test.go index 9080fb4c7e4..c73049b3e89 100644 --- a/test/prober/wathola/event/types_test.go +++ b/test/prober/wathola/event/types_test.go @@ -22,13 +22,13 @@ import ( ) func TestStepType(t *testing.T) { - s1 := Step{Number:1} + s1 := Step{Number: 1} assert.Equal(t, StepType, s1.Type()) } func TestFinishedType(t *testing.T) { - f1 := Finished{Count:441} + f1 := Finished{Count: 441} assert.Equal(t, FinishedType, f1.Type()) } diff --git a/test/test_images/wathola-forwarder/main_test.go b/test/test_images/wathola-forwarder/main_test.go index 2ad263f37b3..496db9119b4 100644 --- a/test/test_images/wathola-forwarder/main_test.go +++ b/test/test_images/wathola-forwarder/main_test.go @@ -15,7 +15,7 @@ func TestForwarderMain(t *testing.T) { config.Instance.Forwarder.Port = freeport.GetPort() go main() defer forwarder.Stop() - err := lib.WaitUntil(forwarder.IsRunning, 10 * time.Minute) + err := lib.WaitUntil(forwarder.IsRunning, 10*time.Minute) if err != nil { t.Error(err) } diff --git a/test/test_images/wathola-receiver/main_test.go b/test/test_images/wathola-receiver/main_test.go index 8fd139d01f9..156307f9993 100644 --- a/test/test_images/wathola-receiver/main_test.go +++ b/test/test_images/wathola-receiver/main_test.go @@ -16,7 +16,7 @@ func TestReceiverMain(t *testing.T) { config.Instance.Receiver.Port = freeport.GetPort() go main() defer receiver.Stop() - err := lib.WaitUntil(receiver.IsRunning, 10 * time.Minute) + err := lib.WaitUntil(receiver.IsRunning, 10*time.Minute) if err != nil { t.Error(err) } From 8b94303b79011718b3cfed1a8600cfd749975299 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Mon, 11 May 2020 17:51:10 +0200 Subject: [PATCH 45/50] Fixing race conditions on wathola --- test/lib/await.go | 15 ------- test/prober/wathola/client/receiver.go | 11 +++-- test/prober/wathola/config/reader_test.go | 1 + test/prober/wathola/forwarder/services.go | 31 +++---------- test/prober/wathola/receiver/services.go | 26 +++-------- test/prober/wathola/receiver/services_test.go | 3 +- test/prober/wathola/sender/operations.go | 1 - test/prober/wathola/sender/services.go | 26 ++++++----- test/test_images/wathola-forwarder/main.go | 15 +++++++ .../wathola-forwarder/main_test.go | 24 +++++++--- test/test_images/wathola-receiver/main.go | 15 +++++++ .../test_images/wathola-receiver/main_test.go | 24 +++++++--- test/test_images/wathola-sender/main.go | 15 +++++++ test/test_images/wathola-sender/main_test.go | 45 ++++++++++++++++++- 14 files changed, 163 insertions(+), 89 deletions(-) diff --git a/test/lib/await.go b/test/lib/await.go index bd9a427ef12..5703240ac75 100644 --- a/test/lib/await.go +++ b/test/lib/await.go @@ -16,27 +16,12 @@ package lib import ( - "fmt" "time" "go.uber.org/zap" "golang.org/x/sync/errgroup" ) -// WaitUntil a condition is met -func WaitUntil(condition func() bool, timeout time.Duration) error { - deadline := time.Now().Add(timeout) - for { - if condition() { - return nil - } - if time.Now().After(deadline) { - return fmt.Errorf("wait for condition exceed timeout of %v", timeout) - } - time.Sleep(25 * time.Millisecond) - } -} - // WaitFor will register a wait routine to be resolved later func WaitFor(name string, routine AwaitRoutine) { w := &namedAwait{ diff --git a/test/prober/wathola/client/receiver.go b/test/prober/wathola/client/receiver.go index 300aed431f5..541849a7429 100644 --- a/test/prober/wathola/client/receiver.go +++ b/test/prober/wathola/client/receiver.go @@ -34,9 +34,10 @@ type ReceiveEvent func(e cloudevents.Event) // Receive events and push then to passed fn func Receive( port int, - cancelRegistrar func(*context.CancelFunc), + starting chan context.CancelFunc, receiveEvent ReceiveEvent, middlewares ...cloudeventshttp.Middleware) { + portOpt := cloudevents.WithPort(port) opts := make([]cloudeventshttp.Option, 0) opts = append(opts, portOpt) @@ -57,8 +58,12 @@ func Receive( log.Fatalf("failed to create client, %v", err) } log.Infof("listening for events on port %v", port) - ctx, ccancel := context.WithCancel(context.Background()) - cancelRegistrar(&ccancel) + ctx, cancel := context.WithCancel(context.Background()) + starting <- func() { + log.Infof("stopping event receiver on port %v", port) + cancel() + } + close(starting) err = c.StartReceiver(ctx, receiveEvent) if err != nil { log.Fatal(err) diff --git a/test/prober/wathola/config/reader_test.go b/test/prober/wathola/config/reader_test.go index aac038d53f2..72c4370e9bf 100644 --- a/test/prober/wathola/config/reader_test.go +++ b/test/prober/wathola/config/reader_test.go @@ -17,6 +17,7 @@ package config import ( "fmt" + "github.com/google/uuid" "github.com/mitchellh/go-homedir" "github.com/stretchr/testify/assert" diff --git a/test/prober/wathola/forwarder/services.go b/test/prober/wathola/forwarder/services.go index 2e91f098655..bb6cad16941 100644 --- a/test/prober/wathola/forwarder/services.go +++ b/test/prober/wathola/forwarder/services.go @@ -18,7 +18,7 @@ package forwarder import ( "context" - "github.com/cloudevents/sdk-go" + cloudevents "github.com/cloudevents/sdk-go" "knative.dev/eventing/test/prober/wathola/client" "knative.dev/eventing/test/prober/wathola/config" "knative.dev/eventing/test/prober/wathola/sender" @@ -26,8 +26,11 @@ import ( "time" ) -var log = config.Log -var lastProgressReport = time.Now() +var ( + log = config.Log + lastProgressReport = time.Now() + Starting = make(chan context.CancelFunc) +) // New creates new forwarder func New() Forwarder { @@ -38,29 +41,9 @@ func New() Forwarder { return f } -// Stop will stop running forwarder if there is one -func Stop() { - if IsRunning() { - log.Info("stopping forwarder") - cf := *cancel - cf() - cancel = nil - } -} - -// IsRunning checks if receiver is operating and can be stopped -func IsRunning() bool { - return cancel != nil -} - -var cancel *context.CancelFunc - func (f *forwarder) Forward() { port := config.Instance.Forwarder.Port - cancelRegistrar := func(cc *context.CancelFunc) { - cancel = cc - } - client.Receive(port, cancelRegistrar, f.forwardEvent) + client.Receive(port, Starting, f.forwardEvent) } func (f *forwarder) forwardEvent(e cloudevents.Event) { diff --git a/test/prober/wathola/receiver/services.go b/test/prober/wathola/receiver/services.go index 3bbe102f908..f6b77452026 100644 --- a/test/prober/wathola/receiver/services.go +++ b/test/prober/wathola/receiver/services.go @@ -29,8 +29,10 @@ import ( "net/http" ) -var log = config.Log -var cancel *context.CancelFunc +var ( + log = config.Log + Starting = make(chan context.CancelFunc) +) // New creates new Receiver func New() Receiver { @@ -42,27 +44,9 @@ func New() Receiver { return r } -// Stop will stop running receiver if there is one -func Stop() { - if IsRunning() { - log.Info("stopping receiver") - cancelFunc := *cancel - cancelFunc() - cancel = nil - } -} - -// IsRunning checks if receiver is operating and can be stopped -func IsRunning() bool { - return cancel != nil -} - func (r receiver) Receive() { port := config.Instance.Receiver.Port - cancelRegistrar := func(cc *context.CancelFunc) { - cancel = cc - } - client.Receive(port, cancelRegistrar, r.receiveEvent, r.reportMiddleware) + client.Receive(port, Starting, r.receiveEvent, r.reportMiddleware) } func (r receiver) receiveEvent(e cloudevents.Event) { diff --git a/test/prober/wathola/receiver/services_test.go b/test/prober/wathola/receiver/services_test.go index ade50d4081b..779a933cd17 100644 --- a/test/prober/wathola/receiver/services_test.go +++ b/test/prober/wathola/receiver/services_test.go @@ -40,7 +40,8 @@ func TestReceiverReceive(t *testing.T) { config.Instance.Receiver.Port = port go instance.Receive() time.Sleep(time.Second) - defer Stop() + cancel := <-Starting + defer cancel() // when sendEvent(e, port) diff --git a/test/prober/wathola/sender/operations.go b/test/prober/wathola/sender/operations.go index de0a452e27a..c33ef270132 100644 --- a/test/prober/wathola/sender/operations.go +++ b/test/prober/wathola/sender/operations.go @@ -26,7 +26,6 @@ import ( func New() Sender { config.ReadIfPresent() return &sender{ - active: true, counter: 0, } } diff --git a/test/prober/wathola/sender/services.go b/test/prober/wathola/sender/services.go index 7b4736dd0eb..d184749d55e 100644 --- a/test/prober/wathola/sender/services.go +++ b/test/prober/wathola/sender/services.go @@ -35,21 +35,27 @@ var senderConfig = &config.Instance.Sender type sender struct { counter int - active bool } func (s *sender) SendContinually() { - c := make(chan os.Signal, 1) - signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) + var shutdownCh = make(chan struct{}) + defer s.sendFinished() + go func() { - for sig := range c { - // sig is a ^C or term, handle it - log.Infof("Received: %v, closing", sig.String()) - s.active = false - s.sendFinished() - } + c := make(chan os.Signal, 1) + signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) + sig := <-c + // sig is a ^C or term, handle it + log.Infof("%v signal received, closing", sig.String()) + close(shutdownCh) }() - for s.active { + + for { + select { + case <-shutdownCh: + return + default: + } err := s.sendStep() if err != nil { log.Warnf("Could not send step event, retry in %v", senderConfig.Cooldown) diff --git a/test/test_images/wathola-forwarder/main.go b/test/test_images/wathola-forwarder/main.go index b25a6ae3716..44cd4f64e48 100644 --- a/test/test_images/wathola-forwarder/main.go +++ b/test/test_images/wathola-forwarder/main.go @@ -1,3 +1,18 @@ +/* + * Copyright 2020 The Knative 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. + */ + package main import "knative.dev/eventing/test/prober/wathola/forwarder" diff --git a/test/test_images/wathola-forwarder/main_test.go b/test/test_images/wathola-forwarder/main_test.go index 496db9119b4..626748a7c02 100644 --- a/test/test_images/wathola-forwarder/main_test.go +++ b/test/test_images/wathola-forwarder/main_test.go @@ -1,3 +1,18 @@ +/* + * Copyright 2020 The Knative 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. + */ + package main import ( @@ -6,7 +21,6 @@ import ( "github.com/phayes/freeport" "github.com/stretchr/testify/assert" - "knative.dev/eventing/test/lib" "knative.dev/eventing/test/prober/wathola/config" "knative.dev/eventing/test/prober/wathola/forwarder" ) @@ -14,10 +28,8 @@ import ( func TestForwarderMain(t *testing.T) { config.Instance.Forwarder.Port = freeport.GetPort() go main() - defer forwarder.Stop() - err := lib.WaitUntil(forwarder.IsRunning, 10*time.Minute) - if err != nil { - t.Error(err) - } + cancel := <-forwarder.Starting + time.Sleep(100 * time.Millisecond) assert.NotNil(t, instance) + cancel() } diff --git a/test/test_images/wathola-receiver/main.go b/test/test_images/wathola-receiver/main.go index f640d1ca580..d32594eb20c 100644 --- a/test/test_images/wathola-receiver/main.go +++ b/test/test_images/wathola-receiver/main.go @@ -1,3 +1,18 @@ +/* + * Copyright 2020 The Knative 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. + */ + package main import "knative.dev/eventing/test/prober/wathola/receiver" diff --git a/test/test_images/wathola-receiver/main_test.go b/test/test_images/wathola-receiver/main_test.go index 156307f9993..6978f0ae9e0 100644 --- a/test/test_images/wathola-receiver/main_test.go +++ b/test/test_images/wathola-receiver/main_test.go @@ -1,3 +1,18 @@ +/* + * Copyright 2020 The Knative 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. + */ + package main import ( @@ -5,7 +20,6 @@ import ( "time" "github.com/phayes/freeport" - "knative.dev/eventing/test/lib" "knative.dev/eventing/test/prober/wathola/config" "knative.dev/eventing/test/prober/wathola/receiver" @@ -15,10 +29,8 @@ import ( func TestReceiverMain(t *testing.T) { config.Instance.Receiver.Port = freeport.GetPort() go main() - defer receiver.Stop() - err := lib.WaitUntil(receiver.IsRunning, 10*time.Minute) - if err != nil { - t.Error(err) - } + cancel := <-receiver.Starting + time.Sleep(100 * time.Millisecond) assert.NotNil(t, instance) + cancel() } diff --git a/test/test_images/wathola-sender/main.go b/test/test_images/wathola-sender/main.go index 0fc1b7fc52a..4d0455fc682 100644 --- a/test/test_images/wathola-sender/main.go +++ b/test/test_images/wathola-sender/main.go @@ -1,3 +1,18 @@ +/* + * Copyright 2020 The Knative 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. + */ + package main import "knative.dev/eventing/test/prober/wathola/sender" diff --git a/test/test_images/wathola-sender/main_test.go b/test/test_images/wathola-sender/main_test.go index 2ba33527e3c..a7b8a35680f 100644 --- a/test/test_images/wathola-sender/main_test.go +++ b/test/test_images/wathola-sender/main_test.go @@ -1,17 +1,58 @@ +/* + * Copyright 2020 The Knative 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. + */ + package main import ( + "fmt" + "net" + "net/http" + "net/http/httptest" "syscall" "testing" "time" "github.com/wavesoftware/go-ensure" + "knative.dev/eventing/test/prober/wathola/config" ) func TestSenderMain(t *testing.T) { + ts := createMockServer() + defer ts.Close() + p := syscall.Getpid() go main() - time.Sleep(time.Second) - err := syscall.Kill(p, syscall.SIGINT) + time.Sleep(500 * time.Millisecond) + err := syscall.Kill(p, syscall.SIGTERM) + ensure.NoError(err) + time.Sleep(500 * time.Millisecond) +} + +func createMockServer() *httptest.Server { + l, err := net.Listen("tcp", + fmt.Sprintf(":%d", config.DefaultForwarderPort), + ) ensure.NoError(err) + ts := &httptest.Server{ + Listener: l, + Config: &http.Server{ + Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(200) + }), + }, + } + ts.Start() + return ts } From 803ce3766bc280c4debf2660a263484c3f98a62b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Fri, 15 May 2020 13:21:46 +0200 Subject: [PATCH 46/50] E2E Upgrade tests scripts --- test/e2e-common.sh | 50 +++++++++++++++-------- test/e2e-upgrade-tests.sh | 2 +- test/prober/receiver.go | 5 ++- test/prober/wathola/config/reader_test.go | 2 +- 4 files changed, 37 insertions(+), 22 deletions(-) diff --git a/test/e2e-common.sh b/test/e2e-common.sh index 8986bfed46c..3a143bd38c7 100755 --- a/test/e2e-common.sh +++ b/test/e2e-common.sh @@ -43,27 +43,40 @@ readonly MT_CHANNEL_BASED_BROKER_DEFAULT_CONFIG="test/config/mt-channel-broker.y # Channel Based Broker Controller. readonly CHANNEL_BASED_BROKER_CONTROLLER="config/brokers/channel-broker" +# Should deploy a Knative Monitoring as well +readonly DEPLOY_KNATIVE_MONITORING="${DEPLOY_KNATIVE_MONITORING:-1}" + # Latest release. If user does not supply this as a flag, the latest # tagged release on the current branch will be used. readonly LATEST_RELEASE_VERSION=$(git describe --match "v[0-9]*" --abbrev=0) UNINSTALL_LIST=() -# Setup the Knative environment for running tests. This installs -# Everything from the config dir but then removes the Channel Based Broker. -function knative_setup { +# Setup the Knative environment for running tests. +function knative_setup() { install_knative_eventing } +# This installs everything from the config dir but then removes the Channel Based Broker. # TODO: This should only install the core. +# Args: +# - $1 - if passed, it will be used as eventing config directory function install_knative_eventing() { - # Install the latest Knative/eventing in the current cluster. - echo ">> Starting Knative Eventing" - echo "Installing Knative Eventing" - ko apply --strict -f ${EVENTING_CONFIG} || return 1 + local kne_config + kne_config="${1:-${EVENTING_CONFIG}}" + # Install Knative Eventing in the current cluster. + echo "Installing Knative Eventing from: ${kne_config}" + if [ -f "${kne_config}" ] || [ -d "${kne_config}" ]; then + ko apply --strict -f "${kne_config}" || return $? + else + kubectl apply -f "${kne_config}" || return $? + UNINSTALL_LIST+=( "${kne_config}" ) + fi wait_until_pods_running knative-eventing || fail_test "Knative Eventing did not come up" + if ! (( DEPLOY_KNATIVE_MONITORING )); then return 0; fi + # Ensure knative monitoring is installed only once knative_monitoring_pods=$(kubectl get pods -n knative-monitoring \ --field-selector status.phase=Running 2> /dev/null | tail -n +2 | wc -l) @@ -77,19 +90,20 @@ function install_knative_eventing() { } function install_head { - ko apply -f ${EVENTING_CONFIG} || return $? - wait_until_pods_running knative-eventing || fail_test "Knative Eventing did not come up" + # Install Knative Eventing from HEAD in the current cluster. + echo ">> Installing Knative Eventing from HEAD" + install_knative_eventing || \ + fail_test "Knative HEAD installation failed" } -function install_latest_release { - header "Installing Knative latest public release" +function install_latest_release() { + header ">> Installing Knative Eventing latest public release" local url="https://github.com/knative/eventing/releases/download/${LATEST_RELEASE_VERSION}" local yaml="eventing.yaml" install_knative_eventing \ - "${url}/${yaml}" \ - || fail_test "Knative latest release installation failed" - wait_until_pods_running knative-eventing || fail_test "Knative Eventing did not come up" + "${url}/${yaml}" || \ + fail_test "Knative latest release installation failed" } function install_broker() { @@ -144,12 +158,12 @@ function test_setup() { echo ">> Setting up logging..." # Install kail if needed. - if ! which kail > /dev/null; then - bash <( curl -sfL https://raw.githubusercontent.com/boz/kail/master/godownloader.sh) -b "$GOPATH/bin" + if ! which kail >/dev/null; then + bash <(curl -sfL https://raw.githubusercontent.com/boz/kail/master/godownloader.sh) -b "$GOPATH/bin" fi # Capture all logs. - kail > ${ARTIFACTS}/k8s.log.txt & + kail >${ARTIFACTS}/k8s.log.txt & local kail_pid=$! # Clean up kail so it doesn't interfere with job shutting down add_trap "kill $kail_pid || true" EXIT @@ -200,7 +214,7 @@ function dump_extra_cluster_state() { done } -function wait_for_file { +function wait_for_file() { local file timeout waits file="$1" waits=300 diff --git a/test/e2e-upgrade-tests.sh b/test/e2e-upgrade-tests.sh index 17d2701244a..75d835d638d 100755 --- a/test/e2e-upgrade-tests.sh +++ b/test/e2e-upgrade-tests.sh @@ -26,7 +26,6 @@ source "$(dirname "$0")/e2e-common.sh" function knative_setup { install_latest_release || fail_test 'Installing latest release of Knative Eventing failed' - install_broker || fail_test 'Could not install Channel Based Broker' } function install_test_resources { @@ -58,6 +57,7 @@ wait_for_file /tmp/prober-ready || fail_test header "Performing upgrade to HEAD" install_head || fail_test 'Installing HEAD version of eventing failed' install_channel_crds || fail_test 'Installing HEAD channel CRDs failed' +install_mt_broker || fail_test 'Installing HEAD MT Broker failed' header "Running postupgrade tests" go_test_e2e -tags=postupgrade -timeout="${TIMEOUT}" ./test/upgrade || fail_test diff --git a/test/prober/receiver.go b/test/prober/receiver.go index 9564216529b..cc4a5a92bff 100644 --- a/test/prober/receiver.go +++ b/test/prober/receiver.go @@ -23,6 +23,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "knative.dev/eventing/test/lib" + watholaconfig "knative.dev/eventing/test/prober/wathola/config" pkgTest "knative.dev/pkg/test" ) @@ -77,7 +78,7 @@ func (p *prober) deployReceiverPod() { Handler: corev1.Handler{ HTTPGet: &corev1.HTTPGetAction{ Path: healthEndpoint, - Port: intstr.FromInt(22111), + Port: intstr.FromInt(watholaconfig.DefaultReceiverPort), }, }, }, @@ -108,7 +109,7 @@ func (p *prober) deployReceiverService() { Port: 80, TargetPort: intstr.IntOrString{ Type: intstr.Int, - IntVal: 22111, + IntVal: watholaconfig.DefaultReceiverPort, }, }, }, diff --git a/test/prober/wathola/config/reader_test.go b/test/prober/wathola/config/reader_test.go index 72c4370e9bf..fff158b8a41 100644 --- a/test/prober/wathola/config/reader_test.go +++ b/test/prober/wathola/config/reader_test.go @@ -82,7 +82,7 @@ func TestReadIfNotPresent(t *testing.T) { // then assert.Equal(t, - "http://localhost:22110/", + fmt.Sprintf("http://localhost:%d/", DefaultForwarderPort), Instance.Sender.Address) assert.Equal(t, DefaultReceiverPort, Instance.Receiver.Port) assert.Equal(t, DefaultForwarderPort, Instance.Forwarder.Port) From 44a5c2af703104ec7c332be2e3dba7b9eebeb006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Mon, 18 May 2020 11:58:31 +0200 Subject: [PATCH 47/50] Wathola receiver non-blocking and without race --- test/e2e-upgrade-tests.sh | 2 +- test/lib/await.go | 22 +++++++++++++++++++ test/prober/wathola/client/receiver.go | 18 +++++++++------ test/prober/wathola/forwarder/services.go | 4 ++-- test/prober/wathola/receiver/services.go | 6 ++--- test/prober/wathola/receiver/services_test.go | 2 +- .../wathola-forwarder/main_test.go | 12 ++++++---- .../test_images/wathola-receiver/main_test.go | 13 +++++++---- 8 files changed, 57 insertions(+), 22 deletions(-) diff --git a/test/e2e-upgrade-tests.sh b/test/e2e-upgrade-tests.sh index 75d835d638d..fdc55c205df 100755 --- a/test/e2e-upgrade-tests.sh +++ b/test/e2e-upgrade-tests.sh @@ -57,7 +57,7 @@ wait_for_file /tmp/prober-ready || fail_test header "Performing upgrade to HEAD" install_head || fail_test 'Installing HEAD version of eventing failed' install_channel_crds || fail_test 'Installing HEAD channel CRDs failed' -install_mt_broker || fail_test 'Installing HEAD MT Broker failed' +install_broker || fail_test 'Installing HEAD Broker failed' header "Running postupgrade tests" go_test_e2e -tags=postupgrade -timeout="${TIMEOUT}" ./test/upgrade || fail_test diff --git a/test/lib/await.go b/test/lib/await.go index 5703240ac75..65c35a1341e 100644 --- a/test/lib/await.go +++ b/test/lib/await.go @@ -16,10 +16,14 @@ package lib import ( + "fmt" + "io/ioutil" + "net/http" "time" "go.uber.org/zap" "golang.org/x/sync/errgroup" + "k8s.io/apimachinery/pkg/util/wait" ) // WaitFor will register a wait routine to be resolved later @@ -57,6 +61,24 @@ func AwaitForAll(log *zap.SugaredLogger) error { return nil } +// WaitForReadiness will wait until readiness endpoint reports OK +func WaitForReadiness(port int) error { + return wait.Poll(25 * time.Millisecond, 5 * time.Minute, func() (done bool, err error) { + resp, err := http.Get(fmt.Sprintf("http://localhost:%d/healthz", port)) + if err != nil { + return false, err + } + defer func() { + _ = resp.Body.Close() + }() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return false, err + } + return resp.StatusCode == 200 && string(body) == "OK", nil + }) +} + type AwaitRoutine func() error type namedAwait struct { diff --git a/test/prober/wathola/client/receiver.go b/test/prober/wathola/client/receiver.go index 541849a7429..8e5dbf6c78d 100644 --- a/test/prober/wathola/client/receiver.go +++ b/test/prober/wathola/client/receiver.go @@ -34,10 +34,10 @@ type ReceiveEvent func(e cloudevents.Event) // Receive events and push then to passed fn func Receive( port int, - starting chan context.CancelFunc, + canceling chan context.CancelFunc, receiveEvent ReceiveEvent, - middlewares ...cloudeventshttp.Middleware) { - + middlewares ...cloudeventshttp.Middleware, +) { portOpt := cloudevents.WithPort(port) opts := make([]cloudeventshttp.Option, 0) opts = append(opts, portOpt) @@ -57,13 +57,17 @@ func Receive( if err != nil { log.Fatalf("failed to create client, %v", err) } - log.Infof("listening for events on port %v", port) + log.Infof("Listening for events on port %v", port) ctx, cancel := context.WithCancel(context.Background()) - starting <- func() { - log.Infof("stopping event receiver on port %v", port) + cancelFunc := func() { + log.Infof("Stopping event receiver on port %v", port) cancel() } - close(starting) + // https://gobyexample.com/non-blocking-channel-operations + select { + case canceling <- cancelFunc: + default: + } err = c.StartReceiver(ctx, receiveEvent) if err != nil { log.Fatal(err) diff --git a/test/prober/wathola/forwarder/services.go b/test/prober/wathola/forwarder/services.go index bb6cad16941..669f0378df5 100644 --- a/test/prober/wathola/forwarder/services.go +++ b/test/prober/wathola/forwarder/services.go @@ -29,7 +29,7 @@ import ( var ( log = config.Log lastProgressReport = time.Now() - Starting = make(chan context.CancelFunc) + Canceling = make(chan context.CancelFunc) ) // New creates new forwarder @@ -43,7 +43,7 @@ func New() Forwarder { func (f *forwarder) Forward() { port := config.Instance.Forwarder.Port - client.Receive(port, Starting, f.forwardEvent) + client.Receive(port, Canceling, f.forwardEvent) } func (f *forwarder) forwardEvent(e cloudevents.Event) { diff --git a/test/prober/wathola/receiver/services.go b/test/prober/wathola/receiver/services.go index f6b77452026..e237feff006 100644 --- a/test/prober/wathola/receiver/services.go +++ b/test/prober/wathola/receiver/services.go @@ -30,8 +30,8 @@ import ( ) var ( - log = config.Log - Starting = make(chan context.CancelFunc) + log = config.Log + Canceling = make(chan context.CancelFunc) ) // New creates new Receiver @@ -46,7 +46,7 @@ func New() Receiver { func (r receiver) Receive() { port := config.Instance.Receiver.Port - client.Receive(port, Starting, r.receiveEvent, r.reportMiddleware) + client.Receive(port, Canceling, r.receiveEvent, r.reportMiddleware) } func (r receiver) receiveEvent(e cloudevents.Event) { diff --git a/test/prober/wathola/receiver/services_test.go b/test/prober/wathola/receiver/services_test.go index 779a933cd17..48c613728fa 100644 --- a/test/prober/wathola/receiver/services_test.go +++ b/test/prober/wathola/receiver/services_test.go @@ -40,7 +40,7 @@ func TestReceiverReceive(t *testing.T) { config.Instance.Receiver.Port = port go instance.Receive() time.Sleep(time.Second) - cancel := <-Starting + cancel := <-Canceling defer cancel() // when diff --git a/test/test_images/wathola-forwarder/main_test.go b/test/test_images/wathola-forwarder/main_test.go index 626748a7c02..8071e9a3b42 100644 --- a/test/test_images/wathola-forwarder/main_test.go +++ b/test/test_images/wathola-forwarder/main_test.go @@ -17,19 +17,23 @@ package main import ( "testing" - "time" "github.com/phayes/freeport" "github.com/stretchr/testify/assert" + "go.uber.org/zap/zapcore" + "knative.dev/eventing/test/lib" "knative.dev/eventing/test/prober/wathola/config" "knative.dev/eventing/test/prober/wathola/forwarder" ) func TestForwarderMain(t *testing.T) { - config.Instance.Forwarder.Port = freeport.GetPort() + port := freeport.GetPort() + config.Instance.LogLevel = zapcore.DebugLevel + config.Instance.Forwarder.Port = port go main() - cancel := <-forwarder.Starting - time.Sleep(100 * time.Millisecond) + cancel := <-forwarder.Canceling + err := lib.WaitForReadiness(port) + assert.NoError(t, err) assert.NotNil(t, instance) cancel() } diff --git a/test/test_images/wathola-receiver/main_test.go b/test/test_images/wathola-receiver/main_test.go index 6978f0ae9e0..db96997ea30 100644 --- a/test/test_images/wathola-receiver/main_test.go +++ b/test/test_images/wathola-receiver/main_test.go @@ -17,9 +17,10 @@ package main import ( "testing" - "time" "github.com/phayes/freeport" + "go.uber.org/zap/zapcore" + "knative.dev/eventing/test/lib" "knative.dev/eventing/test/prober/wathola/config" "knative.dev/eventing/test/prober/wathola/receiver" @@ -27,10 +28,14 @@ import ( ) func TestReceiverMain(t *testing.T) { - config.Instance.Receiver.Port = freeport.GetPort() + port := freeport.GetPort() + config.Instance.LogLevel = zapcore.DebugLevel + config.Instance.Receiver.Port = port go main() - cancel := <-receiver.Starting - time.Sleep(100 * time.Millisecond) + cancel := <-receiver.Canceling + err := lib.WaitForReadiness(port) + assert.NoError(t, err) assert.NotNil(t, instance) + cancel() } From fe54820baf4e5f0156b8bf071172601b91d20514 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Mon, 18 May 2020 15:14:33 +0200 Subject: [PATCH 48/50] Migrate to cloudevents v2 --- test/lib/await.go | 2 +- test/prober/wathola/client/receiver.go | 6 ++-- test/prober/wathola/forwarder/services.go | 2 +- test/prober/wathola/receiver/services.go | 2 +- test/prober/wathola/receiver/services_test.go | 12 ++++---- test/prober/wathola/sender/services.go | 30 +++++++++++-------- test/test_images/wathola-forwarder/pod.yaml | 2 +- test/test_images/wathola-receiver/pod.yaml | 2 +- test/test_images/wathola-sender/pod.yaml | 2 +- 9 files changed, 32 insertions(+), 28 deletions(-) diff --git a/test/lib/await.go b/test/lib/await.go index 65c35a1341e..b02da0d4241 100644 --- a/test/lib/await.go +++ b/test/lib/await.go @@ -63,7 +63,7 @@ func AwaitForAll(log *zap.SugaredLogger) error { // WaitForReadiness will wait until readiness endpoint reports OK func WaitForReadiness(port int) error { - return wait.Poll(25 * time.Millisecond, 5 * time.Minute, func() (done bool, err error) { + return wait.Poll(25*time.Millisecond, 5*time.Minute, func() (done bool, err error) { resp, err := http.Get(fmt.Sprintf("http://localhost:%d/healthz", port)) if err != nil { return false, err diff --git a/test/prober/wathola/client/receiver.go b/test/prober/wathola/client/receiver.go index 8e5dbf6c78d..1b64b4fe3bb 100644 --- a/test/prober/wathola/client/receiver.go +++ b/test/prober/wathola/client/receiver.go @@ -20,8 +20,8 @@ import ( nethttp "net/http" "strings" - cloudevents "github.com/cloudevents/sdk-go" - cloudeventshttp "github.com/cloudevents/sdk-go/pkg/cloudevents/transport/http" + cloudevents "github.com/cloudevents/sdk-go/v2" + cloudeventshttp "github.com/cloudevents/sdk-go/v2/protocol/http" "github.com/wavesoftware/go-ensure" "knative.dev/eventing/test/prober/wathola/config" ) @@ -49,7 +49,7 @@ func Receive( opt := cloudevents.WithMiddleware(m) opts = append(opts, opt) } - http, err := cloudevents.NewHTTPTransport(opts...) + http, err := cloudevents.NewHTTP(opts...) if err != nil { log.Fatalf("failed to create http transport, %v", err) } diff --git a/test/prober/wathola/forwarder/services.go b/test/prober/wathola/forwarder/services.go index 669f0378df5..6791f5c3543 100644 --- a/test/prober/wathola/forwarder/services.go +++ b/test/prober/wathola/forwarder/services.go @@ -18,7 +18,7 @@ package forwarder import ( "context" - cloudevents "github.com/cloudevents/sdk-go" + cloudevents "github.com/cloudevents/sdk-go/v2" "knative.dev/eventing/test/prober/wathola/client" "knative.dev/eventing/test/prober/wathola/config" "knative.dev/eventing/test/prober/wathola/sender" diff --git a/test/prober/wathola/receiver/services.go b/test/prober/wathola/receiver/services.go index e237feff006..fcc45fd099e 100644 --- a/test/prober/wathola/receiver/services.go +++ b/test/prober/wathola/receiver/services.go @@ -20,7 +20,7 @@ import ( "encoding/json" "fmt" - cloudevents "github.com/cloudevents/sdk-go" + cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/wavesoftware/go-ensure" "knative.dev/eventing/test/prober/wathola/client" "knative.dev/eventing/test/prober/wathola/config" diff --git a/test/prober/wathola/receiver/services_test.go b/test/prober/wathola/receiver/services_test.go index 48c613728fa..56b5a0170c4 100644 --- a/test/prober/wathola/receiver/services_test.go +++ b/test/prober/wathola/receiver/services_test.go @@ -18,7 +18,7 @@ package receiver import ( "fmt" - cloudevents "github.com/cloudevents/sdk-go" + cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/phayes/freeport" "github.com/stretchr/testify/assert" "knative.dev/eventing/test/prober/wathola/config" @@ -39,13 +39,12 @@ func TestReceiverReceive(t *testing.T) { port := freeport.GetPort() config.Instance.Receiver.Port = port go instance.Receive() - time.Sleep(time.Second) cancel := <-Canceling defer cancel() // when - sendEvent(e, port) - sendEvent(f, port) + sendEvent(t, e, port) + sendEvent(t, f, port) // then rr := instance.(*receiver) @@ -59,7 +58,8 @@ func TestMain(m *testing.M) { os.Exit(exitcode) } -func sendEvent(e cloudevents.Event, port int) { +func sendEvent(t *testing.T, e cloudevents.Event, port int) { url := fmt.Sprintf("http://localhost:%v/", port) - sender.SendEvent(e, url) + err := sender.SendEvent(e, url) + assert.NoError(t, err) } diff --git a/test/prober/wathola/sender/services.go b/test/prober/wathola/sender/services.go index d184749d55e..76c893282bc 100644 --- a/test/prober/wathola/sender/services.go +++ b/test/prober/wathola/sender/services.go @@ -19,7 +19,7 @@ import ( "context" "fmt" - cloudevents "github.com/cloudevents/sdk-go" + cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/wavesoftware/go-ensure" "knative.dev/eventing/test/prober/wathola/config" "knative.dev/eventing/test/prober/wathola/event" @@ -76,24 +76,28 @@ func NewCloudEvent(data interface{}, typ string) cloudevents.Event { e.SetSource(fmt.Sprintf("knative://%s/wathola/sender", host)) e.SetID(NewEventID()) e.SetTime(time.Now()) - err = e.SetData(data) + err = e.SetData(cloudevents.ApplicationJSON, data) ensure.NoError(err) - ensure.NoError(e.Validate()) + errs := e.Validate() + if errs != nil { + ensure.NoError(errs) + } return e } // SendEvent will send cloud event to given url func SendEvent(e cloudevents.Event, url string) error { - ht, err := cloudevents.NewHTTPTransport( - cloudevents.WithTarget(url), - cloudevents.WithEncoding(cloudevents.HTTPBinaryV02), - ) - ensure.NoError(err) - c, err := cloudevents.NewClient(ht) - ensure.NoError(err) - ctx := context.Background() - _, _, err = c.Send(ctx, e) - return err + c, err := cloudevents.NewDefaultClient() + if err != nil { + return err + } + ctx := cloudevents.ContextWithTarget(context.Background(), url) + + result := c.Send(ctx, e) + if cloudevents.IsACK(result) { + return nil + } + return result } func (s *sender) sendStep() error { diff --git a/test/test_images/wathola-forwarder/pod.yaml b/test/test_images/wathola-forwarder/pod.yaml index d46df9257c9..33e872919fe 100644 --- a/test/test_images/wathola-forwarder/pod.yaml +++ b/test/test_images/wathola-forwarder/pod.yaml @@ -5,4 +5,4 @@ metadata: spec: containers: - name: wathola-forwarder - image: knative.dev/eventing/test/test_images/wathola-forwarder + image: ko://knative.dev/eventing/test/test_images/wathola-forwarder diff --git a/test/test_images/wathola-receiver/pod.yaml b/test/test_images/wathola-receiver/pod.yaml index f170f7dd0b7..860e97a4c36 100644 --- a/test/test_images/wathola-receiver/pod.yaml +++ b/test/test_images/wathola-receiver/pod.yaml @@ -5,4 +5,4 @@ metadata: spec: containers: - name: wathola-receiver - image: knative.dev/eventing/test/test_images/wathola-receiver + image: ko://knative.dev/eventing/test/test_images/wathola-receiver diff --git a/test/test_images/wathola-sender/pod.yaml b/test/test_images/wathola-sender/pod.yaml index 5b85e6058a5..cd9faf120e2 100644 --- a/test/test_images/wathola-sender/pod.yaml +++ b/test/test_images/wathola-sender/pod.yaml @@ -5,4 +5,4 @@ metadata: spec: containers: - name: wathola-sender - image: knative.dev/eventing/test/test_images/wathola-sender + image: ko://knative.dev/eventing/test/test_images/wathola-sender From 823bdf6188a132b0abc29875f42417552e437ad1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Mon, 18 May 2020 18:44:59 +0200 Subject: [PATCH 49/50] Move prober + wathola tool to upgrade directory --- test/test_images/wathola-forwarder/main.go | 2 +- test/test_images/wathola-forwarder/main_test.go | 4 ++-- test/test_images/wathola-receiver/main.go | 2 +- test/test_images/wathola-receiver/main_test.go | 4 ++-- test/test_images/wathola-sender/main.go | 2 +- test/test_images/wathola-sender/main_test.go | 2 +- test/upgrade/probe_test.go | 2 +- test/{ => upgrade}/prober/config.toml | 0 test/{ => upgrade}/prober/configuration.go | 0 test/{ => upgrade}/prober/forwarder.go | 0 test/{ => upgrade}/prober/prober.go | 0 test/{ => upgrade}/prober/receiver.go | 2 +- test/{ => upgrade}/prober/sender.go | 0 test/{ => upgrade}/prober/verify.go | 0 test/{ => upgrade}/prober/wathola/README.md | 0 test/{ => upgrade}/prober/wathola/client/receiver.go | 2 +- test/{ => upgrade}/prober/wathola/config/defaults.go | 0 test/{ => upgrade}/prober/wathola/config/defaults_test.go | 0 test/{ => upgrade}/prober/wathola/config/logger.go | 0 test/{ => upgrade}/prober/wathola/config/reader.go | 0 test/{ => upgrade}/prober/wathola/config/reader_test.go | 0 test/{ => upgrade}/prober/wathola/config/structure.go | 0 test/{ => upgrade}/prober/wathola/event/operations.go | 0 test/{ => upgrade}/prober/wathola/event/services.go | 2 +- test/{ => upgrade}/prober/wathola/event/services_test.go | 2 +- test/{ => upgrade}/prober/wathola/event/types.go | 2 +- test/{ => upgrade}/prober/wathola/event/types_test.go | 0 test/{ => upgrade}/prober/wathola/forwarder/operations.go | 0 test/{ => upgrade}/prober/wathola/forwarder/services.go | 6 +++--- test/{ => upgrade}/prober/wathola/receiver/operations.go | 0 test/{ => upgrade}/prober/wathola/receiver/services.go | 6 +++--- test/{ => upgrade}/prober/wathola/receiver/services_test.go | 6 +++--- test/{ => upgrade}/prober/wathola/sender/operations.go | 2 +- test/{ => upgrade}/prober/wathola/sender/services.go | 4 ++-- test/{ => upgrade}/prober/wathola/sender/types.go | 0 35 files changed, 26 insertions(+), 26 deletions(-) rename test/{ => upgrade}/prober/config.toml (100%) rename test/{ => upgrade}/prober/configuration.go (100%) rename test/{ => upgrade}/prober/forwarder.go (100%) rename test/{ => upgrade}/prober/prober.go (100%) rename test/{ => upgrade}/prober/receiver.go (98%) rename test/{ => upgrade}/prober/sender.go (100%) rename test/{ => upgrade}/prober/verify.go (100%) rename test/{ => upgrade}/prober/wathola/README.md (100%) rename test/{ => upgrade}/prober/wathola/client/receiver.go (98%) rename test/{ => upgrade}/prober/wathola/config/defaults.go (100%) rename test/{ => upgrade}/prober/wathola/config/defaults_test.go (100%) rename test/{ => upgrade}/prober/wathola/config/logger.go (100%) rename test/{ => upgrade}/prober/wathola/config/reader.go (100%) rename test/{ => upgrade}/prober/wathola/config/reader_test.go (100%) rename test/{ => upgrade}/prober/wathola/config/structure.go (100%) rename test/{ => upgrade}/prober/wathola/event/operations.go (100%) rename test/{ => upgrade}/prober/wathola/event/services.go (98%) rename test/{ => upgrade}/prober/wathola/event/services_test.go (97%) rename test/{ => upgrade}/prober/wathola/event/types.go (95%) rename test/{ => upgrade}/prober/wathola/event/types_test.go (100%) rename test/{ => upgrade}/prober/wathola/forwarder/operations.go (100%) rename test/{ => upgrade}/prober/wathola/forwarder/services.go (89%) rename test/{ => upgrade}/prober/wathola/receiver/operations.go (100%) rename test/{ => upgrade}/prober/wathola/receiver/services.go (94%) rename test/{ => upgrade}/prober/wathola/receiver/services_test.go (90%) rename test/{ => upgrade}/prober/wathola/sender/operations.go (95%) rename test/{ => upgrade}/prober/wathola/sender/services.go (96%) rename test/{ => upgrade}/prober/wathola/sender/types.go (100%) diff --git a/test/test_images/wathola-forwarder/main.go b/test/test_images/wathola-forwarder/main.go index 44cd4f64e48..5f45b2be67e 100644 --- a/test/test_images/wathola-forwarder/main.go +++ b/test/test_images/wathola-forwarder/main.go @@ -15,7 +15,7 @@ package main -import "knative.dev/eventing/test/prober/wathola/forwarder" +import "knative.dev/eventing/test/upgrade/prober/wathola/forwarder" var instance forwarder.Forwarder diff --git a/test/test_images/wathola-forwarder/main_test.go b/test/test_images/wathola-forwarder/main_test.go index 8071e9a3b42..28ffffa3f79 100644 --- a/test/test_images/wathola-forwarder/main_test.go +++ b/test/test_images/wathola-forwarder/main_test.go @@ -22,8 +22,8 @@ import ( "github.com/stretchr/testify/assert" "go.uber.org/zap/zapcore" "knative.dev/eventing/test/lib" - "knative.dev/eventing/test/prober/wathola/config" - "knative.dev/eventing/test/prober/wathola/forwarder" + "knative.dev/eventing/test/upgrade/prober/wathola/config" + "knative.dev/eventing/test/upgrade/prober/wathola/forwarder" ) func TestForwarderMain(t *testing.T) { diff --git a/test/test_images/wathola-receiver/main.go b/test/test_images/wathola-receiver/main.go index d32594eb20c..719946cf360 100644 --- a/test/test_images/wathola-receiver/main.go +++ b/test/test_images/wathola-receiver/main.go @@ -15,7 +15,7 @@ package main -import "knative.dev/eventing/test/prober/wathola/receiver" +import "knative.dev/eventing/test/upgrade/prober/wathola/receiver" var instance receiver.Receiver diff --git a/test/test_images/wathola-receiver/main_test.go b/test/test_images/wathola-receiver/main_test.go index db96997ea30..98116ccb946 100644 --- a/test/test_images/wathola-receiver/main_test.go +++ b/test/test_images/wathola-receiver/main_test.go @@ -21,8 +21,8 @@ import ( "github.com/phayes/freeport" "go.uber.org/zap/zapcore" "knative.dev/eventing/test/lib" - "knative.dev/eventing/test/prober/wathola/config" - "knative.dev/eventing/test/prober/wathola/receiver" + "knative.dev/eventing/test/upgrade/prober/wathola/config" + "knative.dev/eventing/test/upgrade/prober/wathola/receiver" "github.com/stretchr/testify/assert" ) diff --git a/test/test_images/wathola-sender/main.go b/test/test_images/wathola-sender/main.go index 4d0455fc682..21e97c42fa6 100644 --- a/test/test_images/wathola-sender/main.go +++ b/test/test_images/wathola-sender/main.go @@ -15,7 +15,7 @@ package main -import "knative.dev/eventing/test/prober/wathola/sender" +import "knative.dev/eventing/test/upgrade/prober/wathola/sender" func main() { sender.New().SendContinually() diff --git a/test/test_images/wathola-sender/main_test.go b/test/test_images/wathola-sender/main_test.go index a7b8a35680f..0aa3bc8fc7e 100644 --- a/test/test_images/wathola-sender/main_test.go +++ b/test/test_images/wathola-sender/main_test.go @@ -25,7 +25,7 @@ import ( "time" "github.com/wavesoftware/go-ensure" - "knative.dev/eventing/test/prober/wathola/config" + "knative.dev/eventing/test/upgrade/prober/wathola/config" ) func TestSenderMain(t *testing.T) { diff --git a/test/upgrade/probe_test.go b/test/upgrade/probe_test.go index 04683b7f9b3..a8949855d52 100644 --- a/test/upgrade/probe_test.go +++ b/test/upgrade/probe_test.go @@ -25,7 +25,7 @@ import ( "github.com/wavesoftware/go-ensure" "go.uber.org/zap" - "knative.dev/eventing/test/prober" + "knative.dev/eventing/test/upgrade/prober" ) const ( diff --git a/test/prober/config.toml b/test/upgrade/prober/config.toml similarity index 100% rename from test/prober/config.toml rename to test/upgrade/prober/config.toml diff --git a/test/prober/configuration.go b/test/upgrade/prober/configuration.go similarity index 100% rename from test/prober/configuration.go rename to test/upgrade/prober/configuration.go diff --git a/test/prober/forwarder.go b/test/upgrade/prober/forwarder.go similarity index 100% rename from test/prober/forwarder.go rename to test/upgrade/prober/forwarder.go diff --git a/test/prober/prober.go b/test/upgrade/prober/prober.go similarity index 100% rename from test/prober/prober.go rename to test/upgrade/prober/prober.go diff --git a/test/prober/receiver.go b/test/upgrade/prober/receiver.go similarity index 98% rename from test/prober/receiver.go rename to test/upgrade/prober/receiver.go index cc4a5a92bff..aa6a3ea44f1 100644 --- a/test/prober/receiver.go +++ b/test/upgrade/prober/receiver.go @@ -23,7 +23,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" "knative.dev/eventing/test/lib" - watholaconfig "knative.dev/eventing/test/prober/wathola/config" + watholaconfig "knative.dev/eventing/test/upgrade/prober/wathola/config" pkgTest "knative.dev/pkg/test" ) diff --git a/test/prober/sender.go b/test/upgrade/prober/sender.go similarity index 100% rename from test/prober/sender.go rename to test/upgrade/prober/sender.go diff --git a/test/prober/verify.go b/test/upgrade/prober/verify.go similarity index 100% rename from test/prober/verify.go rename to test/upgrade/prober/verify.go diff --git a/test/prober/wathola/README.md b/test/upgrade/prober/wathola/README.md similarity index 100% rename from test/prober/wathola/README.md rename to test/upgrade/prober/wathola/README.md diff --git a/test/prober/wathola/client/receiver.go b/test/upgrade/prober/wathola/client/receiver.go similarity index 98% rename from test/prober/wathola/client/receiver.go rename to test/upgrade/prober/wathola/client/receiver.go index 1b64b4fe3bb..0571abfada9 100644 --- a/test/prober/wathola/client/receiver.go +++ b/test/upgrade/prober/wathola/client/receiver.go @@ -23,7 +23,7 @@ import ( cloudevents "github.com/cloudevents/sdk-go/v2" cloudeventshttp "github.com/cloudevents/sdk-go/v2/protocol/http" "github.com/wavesoftware/go-ensure" - "knative.dev/eventing/test/prober/wathola/config" + "knative.dev/eventing/test/upgrade/prober/wathola/config" ) var log = config.Log diff --git a/test/prober/wathola/config/defaults.go b/test/upgrade/prober/wathola/config/defaults.go similarity index 100% rename from test/prober/wathola/config/defaults.go rename to test/upgrade/prober/wathola/config/defaults.go diff --git a/test/prober/wathola/config/defaults_test.go b/test/upgrade/prober/wathola/config/defaults_test.go similarity index 100% rename from test/prober/wathola/config/defaults_test.go rename to test/upgrade/prober/wathola/config/defaults_test.go diff --git a/test/prober/wathola/config/logger.go b/test/upgrade/prober/wathola/config/logger.go similarity index 100% rename from test/prober/wathola/config/logger.go rename to test/upgrade/prober/wathola/config/logger.go diff --git a/test/prober/wathola/config/reader.go b/test/upgrade/prober/wathola/config/reader.go similarity index 100% rename from test/prober/wathola/config/reader.go rename to test/upgrade/prober/wathola/config/reader.go diff --git a/test/prober/wathola/config/reader_test.go b/test/upgrade/prober/wathola/config/reader_test.go similarity index 100% rename from test/prober/wathola/config/reader_test.go rename to test/upgrade/prober/wathola/config/reader_test.go diff --git a/test/prober/wathola/config/structure.go b/test/upgrade/prober/wathola/config/structure.go similarity index 100% rename from test/prober/wathola/config/structure.go rename to test/upgrade/prober/wathola/config/structure.go diff --git a/test/prober/wathola/event/operations.go b/test/upgrade/prober/wathola/event/operations.go similarity index 100% rename from test/prober/wathola/event/operations.go rename to test/upgrade/prober/wathola/event/operations.go diff --git a/test/prober/wathola/event/services.go b/test/upgrade/prober/wathola/event/services.go similarity index 98% rename from test/prober/wathola/event/services.go rename to test/upgrade/prober/wathola/event/services.go index e9cbb14ddbf..61e3c2c8635 100644 --- a/test/prober/wathola/event/services.go +++ b/test/upgrade/prober/wathola/event/services.go @@ -20,7 +20,7 @@ import ( "sync" "time" - "knative.dev/eventing/test/prober/wathola/config" + "knative.dev/eventing/test/upgrade/prober/wathola/config" ) var mutex = sync.RWMutex{} diff --git a/test/prober/wathola/event/services_test.go b/test/upgrade/prober/wathola/event/services_test.go similarity index 97% rename from test/prober/wathola/event/services_test.go rename to test/upgrade/prober/wathola/event/services_test.go index a0ee9b38b00..5b9f963533d 100644 --- a/test/prober/wathola/event/services_test.go +++ b/test/upgrade/prober/wathola/event/services_test.go @@ -17,7 +17,7 @@ package event import ( "github.com/stretchr/testify/assert" - "knative.dev/eventing/test/prober/wathola/config" + "knative.dev/eventing/test/upgrade/prober/wathola/config" "os" "testing" diff --git a/test/prober/wathola/event/types.go b/test/upgrade/prober/wathola/event/types.go similarity index 95% rename from test/prober/wathola/event/types.go rename to test/upgrade/prober/wathola/event/types.go index 3fb16f007d3..377f50ceafb 100644 --- a/test/prober/wathola/event/types.go +++ b/test/upgrade/prober/wathola/event/types.go @@ -15,7 +15,7 @@ package event -import "knative.dev/eventing/test/prober/wathola/config" +import "knative.dev/eventing/test/upgrade/prober/wathola/config" const ( // StepType is a string type representation of step event diff --git a/test/prober/wathola/event/types_test.go b/test/upgrade/prober/wathola/event/types_test.go similarity index 100% rename from test/prober/wathola/event/types_test.go rename to test/upgrade/prober/wathola/event/types_test.go diff --git a/test/prober/wathola/forwarder/operations.go b/test/upgrade/prober/wathola/forwarder/operations.go similarity index 100% rename from test/prober/wathola/forwarder/operations.go rename to test/upgrade/prober/wathola/forwarder/operations.go diff --git a/test/prober/wathola/forwarder/services.go b/test/upgrade/prober/wathola/forwarder/services.go similarity index 89% rename from test/prober/wathola/forwarder/services.go rename to test/upgrade/prober/wathola/forwarder/services.go index 6791f5c3543..1e37cc980b6 100644 --- a/test/prober/wathola/forwarder/services.go +++ b/test/upgrade/prober/wathola/forwarder/services.go @@ -19,9 +19,9 @@ import ( "context" cloudevents "github.com/cloudevents/sdk-go/v2" - "knative.dev/eventing/test/prober/wathola/client" - "knative.dev/eventing/test/prober/wathola/config" - "knative.dev/eventing/test/prober/wathola/sender" + "knative.dev/eventing/test/upgrade/prober/wathola/client" + "knative.dev/eventing/test/upgrade/prober/wathola/config" + "knative.dev/eventing/test/upgrade/prober/wathola/sender" "time" ) diff --git a/test/prober/wathola/receiver/operations.go b/test/upgrade/prober/wathola/receiver/operations.go similarity index 100% rename from test/prober/wathola/receiver/operations.go rename to test/upgrade/prober/wathola/receiver/operations.go diff --git a/test/prober/wathola/receiver/services.go b/test/upgrade/prober/wathola/receiver/services.go similarity index 94% rename from test/prober/wathola/receiver/services.go rename to test/upgrade/prober/wathola/receiver/services.go index fcc45fd099e..3e047d802f3 100644 --- a/test/prober/wathola/receiver/services.go +++ b/test/upgrade/prober/wathola/receiver/services.go @@ -22,9 +22,9 @@ import ( cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/wavesoftware/go-ensure" - "knative.dev/eventing/test/prober/wathola/client" - "knative.dev/eventing/test/prober/wathola/config" - "knative.dev/eventing/test/prober/wathola/event" + "knative.dev/eventing/test/upgrade/prober/wathola/client" + "knative.dev/eventing/test/upgrade/prober/wathola/config" + "knative.dev/eventing/test/upgrade/prober/wathola/event" "net/http" ) diff --git a/test/prober/wathola/receiver/services_test.go b/test/upgrade/prober/wathola/receiver/services_test.go similarity index 90% rename from test/prober/wathola/receiver/services_test.go rename to test/upgrade/prober/wathola/receiver/services_test.go index 56b5a0170c4..cc7d7d7df88 100644 --- a/test/prober/wathola/receiver/services_test.go +++ b/test/upgrade/prober/wathola/receiver/services_test.go @@ -21,9 +21,9 @@ import ( cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/phayes/freeport" "github.com/stretchr/testify/assert" - "knative.dev/eventing/test/prober/wathola/config" - "knative.dev/eventing/test/prober/wathola/event" - "knative.dev/eventing/test/prober/wathola/sender" + "knative.dev/eventing/test/upgrade/prober/wathola/config" + "knative.dev/eventing/test/upgrade/prober/wathola/event" + "knative.dev/eventing/test/upgrade/prober/wathola/sender" "os" "testing" diff --git a/test/prober/wathola/sender/operations.go b/test/upgrade/prober/wathola/sender/operations.go similarity index 95% rename from test/prober/wathola/sender/operations.go rename to test/upgrade/prober/wathola/sender/operations.go index c33ef270132..05f77fb65bb 100644 --- a/test/prober/wathola/sender/operations.go +++ b/test/upgrade/prober/wathola/sender/operations.go @@ -19,7 +19,7 @@ import ( "math/rand" "time" - "knative.dev/eventing/test/prober/wathola/config" + "knative.dev/eventing/test/upgrade/prober/wathola/config" ) // New creates new Sender diff --git a/test/prober/wathola/sender/services.go b/test/upgrade/prober/wathola/sender/services.go similarity index 96% rename from test/prober/wathola/sender/services.go rename to test/upgrade/prober/wathola/sender/services.go index 76c893282bc..8db8837a342 100644 --- a/test/prober/wathola/sender/services.go +++ b/test/upgrade/prober/wathola/sender/services.go @@ -21,8 +21,8 @@ import ( cloudevents "github.com/cloudevents/sdk-go/v2" "github.com/wavesoftware/go-ensure" - "knative.dev/eventing/test/prober/wathola/config" - "knative.dev/eventing/test/prober/wathola/event" + "knative.dev/eventing/test/upgrade/prober/wathola/config" + "knative.dev/eventing/test/upgrade/prober/wathola/event" "os" "os/signal" diff --git a/test/prober/wathola/sender/types.go b/test/upgrade/prober/wathola/sender/types.go similarity index 100% rename from test/prober/wathola/sender/types.go rename to test/upgrade/prober/wathola/sender/types.go From 4739de50e9823d725252f00f82b72b8492775f17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Chris=20Suszy=C5=84ski?= Date: Mon, 18 May 2020 19:45:22 +0200 Subject: [PATCH 50/50] Use of latest version of TOML parser --- go.mod | 3 +- go.sum | 4 + vendor/github.com/pelletier/go-toml/Makefile | 29 + vendor/github.com/pelletier/go-toml/README.md | 12 +- .../pelletier/go-toml/azure-pipelines.yml | 109 +++- .../pelletier/go-toml/example-crlf.toml | 1 + .../github.com/pelletier/go-toml/example.toml | 1 + vendor/github.com/pelletier/go-toml/go.mod | 2 +- vendor/github.com/pelletier/go-toml/go.sum | 8 + .../pelletier/go-toml/keysparsing.go | 3 +- vendor/github.com/pelletier/go-toml/lexer.go | 61 +- .../github.com/pelletier/go-toml/marshal.go | 536 +++++++++++++++--- vendor/github.com/pelletier/go-toml/parser.go | 24 +- vendor/github.com/pelletier/go-toml/token.go | 9 +- vendor/github.com/pelletier/go-toml/toml.go | 6 + .../pelletier/go-toml/tomltree_write.go | 94 ++- vendor/gopkg.in/yaml.v2/apic.go | 1 + vendor/modules.txt | 4 +- 18 files changed, 732 insertions(+), 175 deletions(-) create mode 100644 vendor/github.com/pelletier/go-toml/Makefile diff --git a/go.mod b/go.mod index 19aacb7478b..81071562a33 100644 --- a/go.mod +++ b/go.mod @@ -17,8 +17,7 @@ require ( github.com/mailru/easyjson v0.7.1-0.20191009090205-6c0755d89d1e // indirect github.com/mitchellh/go-homedir v1.1.0 github.com/openzipkin/zipkin-go v0.2.2 - // TODO(ksuszyns): Unpin when https://github.com/pelletier/go-toml/issues/406 is fixed - github.com/pelletier/go-toml v1.6.0 + github.com/pelletier/go-toml v1.8.0 github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/pkg/errors v0.9.1 github.com/robfig/cron/v3 v3.0.1 diff --git a/go.sum b/go.sum index 3fb392a97c3..c93c2890a8b 100644 --- a/go.sum +++ b/go.sum @@ -765,6 +765,8 @@ github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/9 github.com/pelletier/go-toml v1.3.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= github.com/pelletier/go-toml v1.6.0 h1:aetoXYr0Tv7xRU/V4B4IZJ2QcbtMUFoNb3ORp7TzIK4= github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= +github.com/pelletier/go-toml v1.8.0 h1:Keo9qb7iRJs2voHvunFtuuYFsbWeOBh8/P9v/kVMFtw= +github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc= github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= @@ -1357,6 +1359,8 @@ gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20190709130402-674ba3eaed22/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= helm.sh/helm/v3 v3.1.1/go.mod h1:WYsFJuMASa/4XUqLyv54s0U/f3mlAaRErGmyy4z921g= diff --git a/vendor/github.com/pelletier/go-toml/Makefile b/vendor/github.com/pelletier/go-toml/Makefile new file mode 100644 index 00000000000..9e4503aea65 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/Makefile @@ -0,0 +1,29 @@ +export CGO_ENABLED=0 +go := go +go.goos ?= $(shell echo `go version`|cut -f4 -d ' '|cut -d '/' -f1) +go.goarch ?= $(shell echo `go version`|cut -f4 -d ' '|cut -d '/' -f2) + +out.tools := tomll tomljson jsontoml +out.dist := $(out.tools:=_$(go.goos)_$(go.goarch).tar.xz) +sources := $(wildcard **/*.go) + + +.PHONY: +tools: $(out.tools) + +$(out.tools): $(sources) + GOOS=$(go.goos) GOARCH=$(go.goarch) $(go) build ./cmd/$@ + +.PHONY: +dist: $(out.dist) + +$(out.dist):%_$(go.goos)_$(go.goarch).tar.xz: % + if [ "$(go.goos)" = "windows" ]; then \ + tar -cJf $@ $^.exe; \ + else \ + tar -cJf $@ $^; \ + fi + +.PHONY: +clean: + rm -rf $(out.tools) $(out.dist) diff --git a/vendor/github.com/pelletier/go-toml/README.md b/vendor/github.com/pelletier/go-toml/README.md index 4ef303af03a..6831deb5bd1 100644 --- a/vendor/github.com/pelletier/go-toml/README.md +++ b/vendor/github.com/pelletier/go-toml/README.md @@ -3,7 +3,7 @@ Go library for the [TOML](https://github.com/mojombo/toml) format. This library supports TOML version -[v0.5.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md) +[v1.0.0-rc.1](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v1.0.0-rc.1.md) [![GoDoc](https://godoc.org/github.com/pelletier/go-toml?status.svg)](http://godoc.org/github.com/pelletier/go-toml) [![license](https://img.shields.io/github/license/pelletier/go-toml.svg)](https://github.com/pelletier/go-toml/blob/master/LICENSE) @@ -18,7 +18,7 @@ Go-toml provides the following features for using data parsed from TOML document * Load TOML documents from files and string data * Easily navigate TOML structure using Tree -* Mashaling and unmarshaling to and from data structures +* Marshaling and unmarshaling to and from data structures * Line & column position data for all parsed elements * [Query support similar to JSON-Path](query/) * Syntax errors contain line and column numbers @@ -74,7 +74,7 @@ Or use a query: q, _ := query.Compile("$..[user,password]") results := q.Execute(config) for ii, item := range results.Values() { - fmt.Println("Query result %d: %v", ii, item) + fmt.Printf("Query result %d: %v\n", ii, item) } ``` @@ -87,7 +87,7 @@ The documentation and additional examples are available at Go-toml provides two handy command line tools: -* `tomll`: Reads TOML files and lint them. +* `tomll`: Reads TOML files and lints them. ``` go install github.com/pelletier/go-toml/cmd/tomll @@ -99,9 +99,9 @@ Go-toml provides two handy command line tools: go install github.com/pelletier/go-toml/cmd/tomljson tomljson --help ``` - + * `jsontoml`: Reads a JSON file and outputs a TOML representation. - + ``` go install github.com/pelletier/go-toml/cmd/jsontoml jsontoml --help diff --git a/vendor/github.com/pelletier/go-toml/azure-pipelines.yml b/vendor/github.com/pelletier/go-toml/azure-pipelines.yml index d8d7944b79d..242b5b5403b 100644 --- a/vendor/github.com/pelletier/go-toml/azure-pipelines.yml +++ b/vendor/github.com/pelletier/go-toml/azure-pipelines.yml @@ -13,9 +13,9 @@ stages: vmImage: ubuntu-latest steps: - task: GoTool@0 - displayName: "Install Go 1.13" + displayName: "Install Go 1.14" inputs: - version: "1.13" + version: "1.14" - script: echo "##vso[task.setvariable variable=PATH]${PATH}:/home/vsts/go/bin/" - script: mkdir -p ${HOME}/go/src/github.com/pelletier/go-toml - script: cp -R . ${HOME}/go/src/github.com/pelletier/go-toml @@ -36,9 +36,9 @@ stages: vmImage: ubuntu-latest steps: - task: GoTool@0 - displayName: "Install Go 1.13" + displayName: "Install Go 1.14" inputs: - version: "1.13" + version: "1.14" - task: Go@0 displayName: "go fmt ./..." inputs: @@ -51,9 +51,9 @@ stages: vmImage: ubuntu-latest steps: - task: GoTool@0 - displayName: "Install Go 1.13" + displayName: "Install Go 1.14" inputs: - version: "1.13" + version: "1.14" - task: Go@0 displayName: "Generate coverage" inputs: @@ -62,16 +62,18 @@ stages: - task: Bash@3 inputs: targetType: 'inline' - script: 'bash <(curl -s https://codecov.io/bash) -t $(CODECOV_TOKEN)' + script: 'bash <(curl -s https://codecov.io/bash) -t ${CODECOV_TOKEN}' + env: + CODECOV_TOKEN: $(CODECOV_TOKEN) - job: benchmark displayName: "benchmark" pool: vmImage: ubuntu-latest steps: - task: GoTool@0 - displayName: "Install Go 1.13" + displayName: "Install Go 1.14" inputs: - version: "1.13" + version: "1.14" - script: echo "##vso[task.setvariable variable=PATH]${PATH}:/home/vsts/go/bin/" - task: Bash@3 inputs: @@ -84,9 +86,9 @@ stages: vmImage: ubuntu-latest steps: - task: GoTool@0 - displayName: "Install Go 1.13" + displayName: "Install Go 1.14" inputs: - version: "1.13" + version: "1.14" - script: echo "##vso[task.setvariable variable=PATH]${PATH}:/home/vsts/go/bin/" - script: mkdir -p ${HOME}/go/src/github.com/pelletier/go-toml - script: cp -R . ${HOME}/go/src/github.com/pelletier/go-toml @@ -100,24 +102,24 @@ stages: displayName: "unit tests" strategy: matrix: + linux 1.14: + goVersion: '1.14' + imageName: 'ubuntu-latest' + mac 1.14: + goVersion: '1.14' + imageName: 'macOS-latest' + windows 1.14: + goVersion: '1.14' + imageName: 'windows-latest' linux 1.13: goVersion: '1.13' imageName: 'ubuntu-latest' mac 1.13: goVersion: '1.13' - imageName: 'macos-10.13' + imageName: 'macOS-latest' windows 1.13: goVersion: '1.13' - imageName: 'vs2017-win2016' - linux 1.12: - goVersion: '1.12' - imageName: 'ubuntu-latest' - mac 1.12: - goVersion: '1.12' - imageName: 'macos-10.13' - windows 1.12: - goVersion: '1.12' - imageName: 'vs2017-win2016' + imageName: 'windows-latest' pool: vmImage: $(imageName) steps: @@ -130,6 +132,67 @@ stages: inputs: command: 'test' arguments: './...' +- stage: build_binaries + displayName: "Build binaries" + dependsOn: run_checks + jobs: + - job: build_binary + displayName: "Build binary" + strategy: + matrix: + linux_amd64: + GOOS: linux + GOARCH: amd64 + darwin_amd64: + GOOS: darwin + GOARCH: amd64 + windows_amd64: + GOOS: windows + GOARCH: amd64 + pool: + vmImage: ubuntu-latest + steps: + - task: GoTool@0 + displayName: "Install Go" + inputs: + version: 1.14 + - task: Bash@3 + inputs: + targetType: inline + script: "make dist" + env: + go.goos: $(GOOS) + go.goarch: $(GOARCH) + - task: CopyFiles@2 + inputs: + sourceFolder: '$(Build.SourcesDirectory)' + contents: '*.tar.xz' + TargetFolder: '$(Build.ArtifactStagingDirectory)' + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: '$(Build.ArtifactStagingDirectory)' + artifactName: binaries +- stage: build_binaries_manifest + displayName: "Build binaries manifest" + dependsOn: build_binaries + jobs: + - job: build_manifest + displayName: "Build binaries manifest" + steps: + - task: DownloadBuildArtifacts@0 + inputs: + buildType: 'current' + downloadType: 'single' + artifactName: 'binaries' + downloadPath: '$(Build.SourcesDirectory)' + - task: Bash@3 + inputs: + targetType: inline + script: "cd binaries && sha256sum --binary *.tar.xz | tee $(Build.ArtifactStagingDirectory)/sha256sums.txt" + - task: PublishBuildArtifacts@1 + inputs: + pathtoPublish: '$(Build.ArtifactStagingDirectory)' + artifactName: manifest - stage: build_docker_image displayName: "Build Docker image" @@ -164,4 +227,4 @@ stages: command: 'buildAndPush' Dockerfile: 'Dockerfile' buildContext: '.' - tags: 'latest' \ No newline at end of file + tags: 'latest' diff --git a/vendor/github.com/pelletier/go-toml/example-crlf.toml b/vendor/github.com/pelletier/go-toml/example-crlf.toml index 12950a163d3..780d9c68f2d 100644 --- a/vendor/github.com/pelletier/go-toml/example-crlf.toml +++ b/vendor/github.com/pelletier/go-toml/example-crlf.toml @@ -27,3 +27,4 @@ enabled = true [clients] data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it +score = 4e-08 # to make sure leading zeroes in exponent parts of floats are supported \ No newline at end of file diff --git a/vendor/github.com/pelletier/go-toml/example.toml b/vendor/github.com/pelletier/go-toml/example.toml index 3d902f28207..f45bf88b8f6 100644 --- a/vendor/github.com/pelletier/go-toml/example.toml +++ b/vendor/github.com/pelletier/go-toml/example.toml @@ -27,3 +27,4 @@ enabled = true [clients] data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it +score = 4e-08 # to make sure leading zeroes in exponent parts of floats are supported \ No newline at end of file diff --git a/vendor/github.com/pelletier/go-toml/go.mod b/vendor/github.com/pelletier/go-toml/go.mod index a17e9331f1f..c7faa6b3e11 100644 --- a/vendor/github.com/pelletier/go-toml/go.mod +++ b/vendor/github.com/pelletier/go-toml/go.mod @@ -5,5 +5,5 @@ go 1.12 require ( github.com/BurntSushi/toml v0.3.1 github.com/davecgh/go-spew v1.1.1 - gopkg.in/yaml.v2 v2.2.4 + gopkg.in/yaml.v2 v2.3.0 ) diff --git a/vendor/github.com/pelletier/go-toml/go.sum b/vendor/github.com/pelletier/go-toml/go.sum index 1cd2613ddd6..6f356470d7c 100644 --- a/vendor/github.com/pelletier/go-toml/go.sum +++ b/vendor/github.com/pelletier/go-toml/go.sum @@ -9,3 +9,11 @@ gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI= gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= +gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/vendor/github.com/pelletier/go-toml/keysparsing.go b/vendor/github.com/pelletier/go-toml/keysparsing.go index e923bc4f9b7..e091500b246 100644 --- a/vendor/github.com/pelletier/go-toml/keysparsing.go +++ b/vendor/github.com/pelletier/go-toml/keysparsing.go @@ -5,7 +5,6 @@ package toml import ( "errors" "fmt" - "unicode" ) // Convert the bare key group string to an array. @@ -109,5 +108,5 @@ func parseKey(key string) ([]string, error) { } func isValidBareChar(r rune) bool { - return isAlphanumeric(r) || r == '-' || unicode.IsNumber(r) + return isAlphanumeric(r) || r == '-' || isDigit(r) } diff --git a/vendor/github.com/pelletier/go-toml/lexer.go b/vendor/github.com/pelletier/go-toml/lexer.go index 735673bd7c1..425e847a7aa 100644 --- a/vendor/github.com/pelletier/go-toml/lexer.go +++ b/vendor/github.com/pelletier/go-toml/lexer.go @@ -26,7 +26,7 @@ type tomlLexer struct { currentTokenStart int currentTokenStop int tokens []token - depth int + brackets []rune line int col int endbufferLine int @@ -123,6 +123,8 @@ func (l *tomlLexer) lexVoid() tomlLexStateFn { for { next := l.peek() switch next { + case '}': // after '{' + return l.lexRightCurlyBrace case '[': return l.lexTableKey case '#': @@ -140,10 +142,6 @@ func (l *tomlLexer) lexVoid() tomlLexStateFn { l.skip() } - if l.depth > 0 { - return l.lexRvalue - } - if isKeyStartChar(next) { return l.lexKey } @@ -167,10 +165,8 @@ func (l *tomlLexer) lexRvalue() tomlLexStateFn { case '=': return l.lexEqual case '[': - l.depth++ return l.lexLeftBracket case ']': - l.depth-- return l.lexRightBracket case '{': return l.lexLeftCurlyBrace @@ -188,12 +184,10 @@ func (l *tomlLexer) lexRvalue() tomlLexStateFn { fallthrough case '\n': l.skip() - if l.depth == 0 { - return l.lexVoid + if len(l.brackets) > 0 && l.brackets[len(l.brackets)-1] == '[' { + return l.lexRvalue } - return l.lexRvalue - case '_': - return l.errorf("cannot start number with underscore") + return l.lexVoid } if l.follow("true") { @@ -236,10 +230,6 @@ func (l *tomlLexer) lexRvalue() tomlLexStateFn { return l.lexNumber } - if isAlphanumeric(next) { - return l.lexKey - } - return l.errorf("no value can start with %c", next) } @@ -250,13 +240,18 @@ func (l *tomlLexer) lexRvalue() tomlLexStateFn { func (l *tomlLexer) lexLeftCurlyBrace() tomlLexStateFn { l.next() l.emit(tokenLeftCurlyBrace) + l.brackets = append(l.brackets, '{') return l.lexVoid } func (l *tomlLexer) lexRightCurlyBrace() tomlLexStateFn { l.next() l.emit(tokenRightCurlyBrace) - return l.lexVoid + if len(l.brackets) == 0 || l.brackets[len(l.brackets)-1] != '{' { + return l.errorf("cannot have '}' here") + } + l.brackets = l.brackets[:len(l.brackets)-1] + return l.lexRvalue } func (l *tomlLexer) lexDate() tomlLexStateFn { @@ -302,6 +297,9 @@ func (l *tomlLexer) lexEqual() tomlLexStateFn { func (l *tomlLexer) lexComma() tomlLexStateFn { l.next() l.emit(tokenComma) + if len(l.brackets) > 0 && l.brackets[len(l.brackets)-1] == '{' { + return l.lexVoid + } return l.lexRvalue } @@ -332,7 +330,26 @@ func (l *tomlLexer) lexKey() tomlLexStateFn { } else if r == '\n' { return l.errorf("keys cannot contain new lines") } else if isSpace(r) { - break + str := " " + // skip trailing whitespace + l.next() + for r = l.peek(); isSpace(r); r = l.peek() { + str += string(r) + l.next() + } + // break loop if not a dot + if r != '.' { + break + } + str += "." + // skip trailing whitespace after dot + l.next() + for r = l.peek(); isSpace(r); r = l.peek() { + str += string(r) + l.next() + } + growingString += str + continue } else if r == '.' { // skip } else if !isValidBareChar(r) { @@ -361,6 +378,7 @@ func (l *tomlLexer) lexComment(previousState tomlLexStateFn) tomlLexStateFn { func (l *tomlLexer) lexLeftBracket() tomlLexStateFn { l.next() l.emit(tokenLeftBracket) + l.brackets = append(l.brackets, '[') return l.lexRvalue } @@ -512,7 +530,7 @@ func (l *tomlLexer) lexStringAsString(terminator string, discardLeadingNewLine, } else { r := l.peek() - if 0x00 <= r && r <= 0x1F && !(acceptNewLines && (r == '\n' || r == '\r')) { + if 0x00 <= r && r <= 0x1F && r != '\t' && !(acceptNewLines && (r == '\n' || r == '\r')) { return "", fmt.Errorf("unescaped control character %U", r) } l.next() @@ -543,7 +561,6 @@ func (l *tomlLexer) lexString() tomlLexStateFn { } str, err := l.lexStringAsString(terminator, discardLeadingNewLine, acceptNewLines) - if err != nil { return l.errorf(err.Error()) } @@ -615,6 +632,10 @@ func (l *tomlLexer) lexInsideTableKey() tomlLexStateFn { func (l *tomlLexer) lexRightBracket() tomlLexStateFn { l.next() l.emit(tokenRightBracket) + if len(l.brackets) == 0 || l.brackets[len(l.brackets)-1] != '[' { + return l.errorf("cannot have ']' here") + } + l.brackets = l.brackets[:len(l.brackets)-1] return l.lexRvalue } diff --git a/vendor/github.com/pelletier/go-toml/marshal.go b/vendor/github.com/pelletier/go-toml/marshal.go index 2a6cfbae423..db5a7b4f09a 100644 --- a/vendor/github.com/pelletier/go-toml/marshal.go +++ b/vendor/github.com/pelletier/go-toml/marshal.go @@ -2,6 +2,7 @@ package toml import ( "bytes" + "encoding" "errors" "fmt" "io" @@ -22,6 +23,7 @@ const ( type tomlOpts struct { name string + nameFromTag bool comment string commented bool multiline bool @@ -68,6 +70,9 @@ const ( var timeType = reflect.TypeOf(time.Time{}) var marshalerType = reflect.TypeOf(new(Marshaler)).Elem() +var unmarshalerType = reflect.TypeOf(new(Unmarshaler)).Elem() +var textMarshalerType = reflect.TypeOf(new(encoding.TextMarshaler)).Elem() +var textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem() var localDateType = reflect.TypeOf(LocalDate{}) var localTimeType = reflect.TypeOf(LocalTime{}) var localDateTimeType = reflect.TypeOf(LocalDateTime{}) @@ -88,12 +93,16 @@ func isPrimitive(mtype reflect.Type) bool { case reflect.String: return true case reflect.Struct: - return mtype == timeType || mtype == localDateType || mtype == localDateTimeType || mtype == localTimeType || isCustomMarshaler(mtype) + return isTimeType(mtype) default: return false } } +func isTimeType(mtype reflect.Type) bool { + return mtype == timeType || mtype == localDateType || mtype == localDateTimeType || mtype == localTimeType +} + // Check if the given marshal type maps to a Tree slice or array func isTreeSequence(mtype reflect.Type) bool { switch mtype.Kind() { @@ -106,6 +115,30 @@ func isTreeSequence(mtype reflect.Type) bool { } } +// Check if the given marshal type maps to a slice or array of a custom marshaler type +func isCustomMarshalerSequence(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Ptr: + return isCustomMarshalerSequence(mtype.Elem()) + case reflect.Slice, reflect.Array: + return isCustomMarshaler(mtype.Elem()) || isCustomMarshaler(reflect.New(mtype.Elem()).Type()) + default: + return false + } +} + +// Check if the given marshal type maps to a slice or array of a text marshaler type +func isTextMarshalerSequence(mtype reflect.Type) bool { + switch mtype.Kind() { + case reflect.Ptr: + return isTextMarshalerSequence(mtype.Elem()) + case reflect.Slice, reflect.Array: + return isTextMarshaler(mtype.Elem()) || isTextMarshaler(reflect.New(mtype.Elem()).Type()) + default: + return false + } +} + // Check if the given marshal type maps to a non-Tree slice or array func isOtherSequence(mtype reflect.Type) bool { switch mtype.Kind() { @@ -140,12 +173,42 @@ func callCustomMarshaler(mval reflect.Value) ([]byte, error) { return mval.Interface().(Marshaler).MarshalTOML() } +func isTextMarshaler(mtype reflect.Type) bool { + return mtype.Implements(textMarshalerType) && !isTimeType(mtype) +} + +func callTextMarshaler(mval reflect.Value) ([]byte, error) { + return mval.Interface().(encoding.TextMarshaler).MarshalText() +} + +func isCustomUnmarshaler(mtype reflect.Type) bool { + return mtype.Implements(unmarshalerType) +} + +func callCustomUnmarshaler(mval reflect.Value, tval interface{}) error { + return mval.Interface().(Unmarshaler).UnmarshalTOML(tval) +} + +func isTextUnmarshaler(mtype reflect.Type) bool { + return mtype.Implements(textUnmarshalerType) +} + +func callTextUnmarshaler(mval reflect.Value, text []byte) error { + return mval.Interface().(encoding.TextUnmarshaler).UnmarshalText(text) +} + // Marshaler is the interface implemented by types that // can marshal themselves into valid TOML. type Marshaler interface { MarshalTOML() ([]byte, error) } +// Unmarshaler is the interface implemented by types that +// can unmarshal a TOML description of themselves. +type Unmarshaler interface { + UnmarshalTOML(interface{}) error +} + /* Marshal returns the TOML encoding of v. Behavior is similar to the Go json encoder, except that there is no concept of a Marshaler interface or MarshalTOML @@ -190,20 +253,23 @@ type Encoder struct { w io.Writer encOpts annotation - line int - col int - order marshalOrder + line int + col int + order marshalOrder + promoteAnon bool + indentation string } // NewEncoder returns a new encoder that writes to w. func NewEncoder(w io.Writer) *Encoder { return &Encoder{ - w: w, - encOpts: encOptsDefaults, - annotation: annotationDefault, - line: 0, - col: 1, - order: OrderAlphabetical, + w: w, + encOpts: encOptsDefaults, + annotation: annotationDefault, + line: 0, + col: 1, + order: OrderAlphabetical, + indentation: " ", } } @@ -255,6 +321,12 @@ func (e *Encoder) Order(ord marshalOrder) *Encoder { return e } +// Indentation allows to change indentation when marshalling. +func (e *Encoder) Indentation(indent string) *Encoder { + e.indentation = indent + return e +} + // SetTagName allows changing default tag "toml" func (e *Encoder) SetTagName(v string) *Encoder { e.tag = v @@ -279,8 +351,31 @@ func (e *Encoder) SetTagMultiline(v string) *Encoder { return e } +// PromoteAnonymous allows to change how anonymous struct fields are marshaled. +// Usually, they are marshaled as if the inner exported fields were fields in +// the outer struct. However, if an anonymous struct field is given a name in +// its TOML tag, it is treated like a regular struct field with that name. +// rather than being anonymous. +// +// In case anonymous promotion is enabled, all anonymous structs are promoted +// and treated like regular struct fields. +func (e *Encoder) PromoteAnonymous(promote bool) *Encoder { + e.promoteAnon = promote + return e +} + func (e *Encoder) marshal(v interface{}) ([]byte, error) { + // Check if indentation is valid + for _, char := range e.indentation { + if !isSpace(char) { + return []byte{}, fmt.Errorf("invalid indentation: must only contains space or tab characters") + } + } + mtype := reflect.TypeOf(v) + if mtype == nil { + return []byte{}, errors.New("nil cannot be marshaled to TOML") + } switch mtype.Kind() { case reflect.Struct, reflect.Map: @@ -288,6 +383,9 @@ func (e *Encoder) marshal(v interface{}) ([]byte, error) { if mtype.Elem().Kind() != reflect.Struct { return []byte{}, errors.New("Only pointer to struct can be marshaled to TOML") } + if reflect.ValueOf(v).IsNil() { + return []byte{}, errors.New("nil pointer cannot be marshaled to TOML") + } default: return []byte{}, errors.New("Only a struct or map can be marshaled to TOML") } @@ -296,13 +394,16 @@ func (e *Encoder) marshal(v interface{}) ([]byte, error) { if isCustomMarshaler(mtype) { return callCustomMarshaler(sval) } + if isTextMarshaler(mtype) { + return callTextMarshaler(sval) + } t, err := e.valueToTree(mtype, sval) if err != nil { return []byte{}, err } var buf bytes.Buffer - _, err = t.writeToOrdered(&buf, "", "", 0, e.arraysOneElementPerLine, e.order) + _, err = t.writeToOrdered(&buf, "", "", 0, e.arraysOneElementPerLine, e.order, e.indentation, false) return buf.Bytes(), err } @@ -320,20 +421,28 @@ func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, er tval := e.nextTree() switch mtype.Kind() { case reflect.Struct: - for i := 0; i < mtype.NumField(); i++ { - mtypef, mvalf := mtype.Field(i), mval.Field(i) - opts := tomlOptions(mtypef, e.annotation) - if opts.include && (!opts.omitempty || !isZero(mvalf)) { - val, err := e.valueToToml(mtypef.Type, mvalf) - if err != nil { - return nil, err + switch mval.Interface().(type) { + case Tree: + reflect.ValueOf(tval).Elem().Set(mval) + default: + for i := 0; i < mtype.NumField(); i++ { + mtypef, mvalf := mtype.Field(i), mval.Field(i) + opts := tomlOptions(mtypef, e.annotation) + if opts.include && ((mtypef.Type.Kind() != reflect.Interface && !opts.omitempty) || !isZero(mvalf)) { + val, err := e.valueToToml(mtypef.Type, mvalf) + if err != nil { + return nil, err + } + if tree, ok := val.(*Tree); ok && mtypef.Anonymous && !opts.nameFromTag && !e.promoteAnon { + e.appendTree(tval, tree) + } else { + tval.SetPathWithOptions([]string{opts.name}, SetOptions{ + Comment: opts.comment, + Commented: opts.commented, + Multiline: opts.multiline, + }, val) + } } - - tval.SetWithOptions(opts.name, SetOptions{ - Comment: opts.comment, - Commented: opts.commented, - Multiline: opts.multiline, - }, val) } } case reflect.Map: @@ -358,18 +467,21 @@ func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, er } for _, key := range keys { mvalf := mval.MapIndex(key) + if (mtype.Elem().Kind() == reflect.Ptr || mtype.Elem().Kind() == reflect.Interface) && mvalf.IsNil() { + continue + } val, err := e.valueToToml(mtype.Elem(), mvalf) if err != nil { return nil, err } if e.quoteMapKeys { - keyStr, err := tomlValueStringRepresentation(key.String(), "", e.arraysOneElementPerLine) + keyStr, err := tomlValueStringRepresentation(key.String(), "", "", e.order, e.arraysOneElementPerLine) if err != nil { return nil, err } tval.SetPath([]string{keyStr}, val) } else { - tval.Set(key.String(), val) + tval.SetPath([]string{key.String()}, val) } } } @@ -406,17 +518,29 @@ func (e *Encoder) valueToOtherSlice(mtype reflect.Type, mval reflect.Value) (int func (e *Encoder) valueToToml(mtype reflect.Type, mval reflect.Value) (interface{}, error) { e.line++ if mtype.Kind() == reflect.Ptr { - return e.valueToToml(mtype.Elem(), mval.Elem()) + switch { + case isCustomMarshaler(mtype): + return callCustomMarshaler(mval) + case isTextMarshaler(mtype): + return callTextMarshaler(mval) + default: + return e.valueToToml(mtype.Elem(), mval.Elem()) + } + } + if mtype.Kind() == reflect.Interface { + return e.valueToToml(mval.Elem().Type(), mval.Elem()) } switch { case isCustomMarshaler(mtype): return callCustomMarshaler(mval) + case isTextMarshaler(mtype): + return callTextMarshaler(mval) case isTree(mtype): return e.valueToTree(mtype, mval) + case isOtherSequence(mtype), isCustomMarshalerSequence(mtype), isTextMarshalerSequence(mtype): + return e.valueToOtherSlice(mtype, mval) case isTreeSequence(mtype): return e.valueToTreeSlice(mtype, mval) - case isOtherSequence(mtype): - return e.valueToOtherSlice(mtype, mval) default: switch mtype.Kind() { case reflect.Bool: @@ -440,6 +564,19 @@ func (e *Encoder) valueToToml(mtype reflect.Type, mval reflect.Value) (interface } } +func (e *Encoder) appendTree(t, o *Tree) error { + for key, value := range o.values { + if _, ok := t.values[key]; ok { + continue + } + if tomlValue, ok := value.(*tomlValue); ok { + tomlValue.position.Col = t.position.Col + } + t.values[key] = value + } + return nil +} + // Unmarshal attempts to unmarshal the Tree into a Go struct pointed by v. // Neither Unmarshaler interfaces nor UnmarshalTOML functions are supported for // sub-structs, and only definite types can be unmarshaled. @@ -492,6 +629,8 @@ type Decoder struct { tval *Tree encOpts tagName string + strict bool + visitor visitorState } // NewDecoder returns a new decoder that reads from r. @@ -522,8 +661,18 @@ func (d *Decoder) SetTagName(v string) *Decoder { return d } +// Strict allows changing to strict decoding. Any fields that are found in the +// input data and do not have a corresponding struct member cause an error. +func (d *Decoder) Strict(strict bool) *Decoder { + d.strict = strict + return d +} + func (d *Decoder) unmarshal(v interface{}) error { mtype := reflect.TypeOf(v) + if mtype == nil { + return errors.New("nil cannot be unmarshaled from TOML") + } if mtype.Kind() != reflect.Ptr { return errors.New("only a pointer to struct or map can be unmarshaled from TOML") } @@ -536,12 +685,23 @@ func (d *Decoder) unmarshal(v interface{}) error { return errors.New("only a pointer to struct or map can be unmarshaled from TOML") } + if reflect.ValueOf(v).IsNil() { + return errors.New("nil pointer cannot be unmarshaled from TOML") + } + vv := reflect.ValueOf(v).Elem() + if d.strict { + d.visitor = newVisitorState(d.tval) + } + sval, err := d.valueFromTree(elem, d.tval, &vv) if err != nil { return err } + if err := d.visitor.validate(); err != nil { + return err + } reflect.ValueOf(v).Elem().Set(sval) return nil } @@ -552,6 +712,17 @@ func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree, mval1 *reflect.V if mtype.Kind() == reflect.Ptr { return d.unwrapPointer(mtype, tval, mval1) } + + // Check if pointer to value implements the Unmarshaler interface. + if mvalPtr := reflect.New(mtype); isCustomUnmarshaler(mvalPtr.Type()) { + d.visitor.visitAll() + + if err := callCustomUnmarshaler(mvalPtr, tval.ToMap()); err != nil { + return reflect.ValueOf(nil), fmt.Errorf("unmarshal toml: %v", err) + } + return mvalPtr.Elem(), nil + } + var mval reflect.Value switch mtype.Kind() { case reflect.Struct: @@ -561,11 +732,17 @@ func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree, mval1 *reflect.V mval = reflect.New(mtype).Elem() } - for i := 0; i < mtype.NumField(); i++ { - mtypef := mtype.Field(i) - an := annotation{tag: d.tagName} - opts := tomlOptions(mtypef, an) - if opts.include { + switch mval.Interface().(type) { + case Tree: + mval.Set(reflect.ValueOf(tval).Elem()) + default: + for i := 0; i < mtype.NumField(); i++ { + mtypef := mtype.Field(i) + an := annotation{tag: d.tagName} + opts := tomlOptions(mtypef, an) + if !opts.include { + continue + } baseKey := opts.name keysToTry := []string{ baseKey, @@ -575,20 +752,25 @@ func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree, mval1 *reflect.V } found := false - for _, key := range keysToTry { - exists := tval.Has(key) - if !exists { - continue - } - val := tval.Get(key) - fval := mval.Field(i) - mvalf, err := d.valueFromToml(mtypef.Type, val, &fval) - if err != nil { - return mval, formatError(err, tval.GetPosition(key)) + if tval != nil { + for _, key := range keysToTry { + exists := tval.HasPath([]string{key}) + if !exists { + continue + } + + d.visitor.push(key) + val := tval.GetPath([]string{key}) + fval := mval.Field(i) + mvalf, err := d.valueFromToml(mtypef.Type, val, &fval) + if err != nil { + return mval, formatError(err, tval.GetPositionPath([]string{key})) + } + mval.Field(i).Set(mvalf) + found = true + d.visitor.pop() + break } - mval.Field(i).Set(mvalf) - found = true - break } if !found && opts.defaultValue != "" { @@ -596,37 +778,52 @@ func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree, mval1 *reflect.V var val interface{} var err error switch mvalf.Kind() { + case reflect.String: + val = opts.defaultValue case reflect.Bool: val, err = strconv.ParseBool(opts.defaultValue) - if err != nil { - return mval.Field(i), err - } + case reflect.Uint: + val, err = strconv.ParseUint(opts.defaultValue, 10, 0) + case reflect.Uint8: + val, err = strconv.ParseUint(opts.defaultValue, 10, 8) + case reflect.Uint16: + val, err = strconv.ParseUint(opts.defaultValue, 10, 16) + case reflect.Uint32: + val, err = strconv.ParseUint(opts.defaultValue, 10, 32) + case reflect.Uint64: + val, err = strconv.ParseUint(opts.defaultValue, 10, 64) case reflect.Int: - val, err = strconv.Atoi(opts.defaultValue) - if err != nil { - return mval.Field(i), err - } - case reflect.String: - val = opts.defaultValue + val, err = strconv.ParseInt(opts.defaultValue, 10, 0) + case reflect.Int8: + val, err = strconv.ParseInt(opts.defaultValue, 10, 8) + case reflect.Int16: + val, err = strconv.ParseInt(opts.defaultValue, 10, 16) + case reflect.Int32: + val, err = strconv.ParseInt(opts.defaultValue, 10, 32) case reflect.Int64: val, err = strconv.ParseInt(opts.defaultValue, 10, 64) - if err != nil { - return mval.Field(i), err - } + case reflect.Float32: + val, err = strconv.ParseFloat(opts.defaultValue, 32) case reflect.Float64: val, err = strconv.ParseFloat(opts.defaultValue, 64) - if err != nil { - return mval.Field(i), err - } default: - return mval.Field(i), fmt.Errorf("unsuported field type for default option") + return mvalf, fmt.Errorf("unsupported field type for default option") + } + + if err != nil { + return mvalf, err } - mval.Field(i).Set(reflect.ValueOf(val)) + mvalf.Set(reflect.ValueOf(val).Convert(mvalf.Type())) } - // save the old behavior above and try to check anonymous structs - if !found && opts.defaultValue == "" && mtypef.Anonymous && mtypef.Type.Kind() == reflect.Struct { - v, err := d.valueFromTree(mtypef.Type, tval, nil) + // save the old behavior above and try to check structs + if !found && opts.defaultValue == "" && mtypef.Type.Kind() == reflect.Struct { + tmpTval := tval + if !mtypef.Anonymous { + tmpTval = nil + } + fval := mval.Field(i) + v, err := d.valueFromTree(mtypef.Type, tmpTval, &fval) if err != nil { return v, err } @@ -637,13 +834,15 @@ func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree, mval1 *reflect.V case reflect.Map: mval = reflect.MakeMap(mtype) for _, key := range tval.Keys() { + d.visitor.push(key) // TODO: path splits key val := tval.GetPath([]string{key}) mvalf, err := d.valueFromToml(mtype.Elem(), val, nil) if err != nil { - return mval, formatError(err, tval.GetPosition(key)) + return mval, formatError(err, tval.GetPositionPath([]string{key})) } mval.SetMapIndex(reflect.ValueOf(key).Convert(mtype.Key()), mvalf) + d.visitor.pop() } } return mval, nil @@ -651,20 +850,30 @@ func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree, mval1 *reflect.V // Convert toml value to marshal struct/map slice, using marshal type func (d *Decoder) valueFromTreeSlice(mtype reflect.Type, tval []*Tree) (reflect.Value, error) { - mval := reflect.MakeSlice(mtype, len(tval), len(tval)) + mval, err := makeSliceOrArray(mtype, len(tval)) + if err != nil { + return mval, err + } + for i := 0; i < len(tval); i++ { + d.visitor.push(strconv.Itoa(i)) val, err := d.valueFromTree(mtype.Elem(), tval[i], nil) if err != nil { return mval, err } mval.Index(i).Set(val) + d.visitor.pop() } return mval, nil } // Convert toml value to marshal primitive slice, using marshal type func (d *Decoder) valueFromOtherSlice(mtype reflect.Type, tval []interface{}) (reflect.Value, error) { - mval := reflect.MakeSlice(mtype, len(tval), len(tval)) + mval, err := makeSliceOrArray(mtype, len(tval)) + if err != nil { + return mval, err + } + for i := 0; i < len(tval); i++ { val, err := d.valueFromToml(mtype.Elem(), tval[i], nil) if err != nil { @@ -675,6 +884,41 @@ func (d *Decoder) valueFromOtherSlice(mtype reflect.Type, tval []interface{}) (r return mval, nil } +// Convert toml value to marshal primitive slice, using marshal type +func (d *Decoder) valueFromOtherSliceI(mtype reflect.Type, tval interface{}) (reflect.Value, error) { + val := reflect.ValueOf(tval) + length := val.Len() + + mval, err := makeSliceOrArray(mtype, length) + if err != nil { + return mval, err + } + + for i := 0; i < length; i++ { + val, err := d.valueFromToml(mtype.Elem(), val.Index(i).Interface(), nil) + if err != nil { + return mval, err + } + mval.Index(i).Set(val) + } + return mval, nil +} + +// Create a new slice or a new array with specified length +func makeSliceOrArray(mtype reflect.Type, tLength int) (reflect.Value, error) { + var mval reflect.Value + switch mtype.Kind() { + case reflect.Slice: + mval = reflect.MakeSlice(mtype, tLength, tLength) + case reflect.Array: + mval = reflect.New(reflect.ArrayOf(mtype.Len(), mtype.Elem())).Elem() + if tLength > mtype.Len() { + return mval, fmt.Errorf("unmarshal: TOML array length (%v) exceeds destination array length (%v)", tLength, mtype.Len()) + } + } + return mval, nil +} + // Convert toml value to marshal value, using marshal type. When mval1 is non-nil // and the given type is a struct value, merge fields into it. func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}, mval1 *reflect.Value) (reflect.Value, error) { @@ -692,18 +936,53 @@ func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}, mval1 *ref if isTree(mtype) { return d.valueFromTree(mtype, t, mval11) } + + if mtype.Kind() == reflect.Interface { + if mval1 == nil || mval1.IsNil() { + return d.valueFromTree(reflect.TypeOf(map[string]interface{}{}), t, nil) + } else { + return d.valueFromToml(mval1.Elem().Type(), t, nil) + } + } + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a tree", tval, tval) case []*Tree: if isTreeSequence(mtype) { return d.valueFromTreeSlice(mtype, t) } + if mtype.Kind() == reflect.Interface { + if mval1 == nil || mval1.IsNil() { + return d.valueFromTreeSlice(reflect.TypeOf([]map[string]interface{}{}), t) + } else { + ival := mval1.Elem() + return d.valueFromToml(mval1.Elem().Type(), t, &ival) + } + } return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to trees", tval, tval) case []interface{}: + d.visitor.visit() if isOtherSequence(mtype) { return d.valueFromOtherSlice(mtype, t) } + if mtype.Kind() == reflect.Interface { + if mval1 == nil || mval1.IsNil() { + return d.valueFromOtherSlice(reflect.TypeOf([]interface{}{}), t) + } else { + ival := mval1.Elem() + return d.valueFromToml(mval1.Elem().Type(), t, &ival) + } + } return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a slice", tval, tval) default: + d.visitor.visit() + // Check if pointer to value implements the encoding.TextUnmarshaler. + if mvalPtr := reflect.New(mtype); isTextUnmarshaler(mvalPtr.Type()) && !isTimeType(mtype) { + if err := d.unmarshalText(tval, mvalPtr); err != nil { + return reflect.ValueOf(nil), fmt.Errorf("unmarshal text: %v", err) + } + return mvalPtr.Elem(), nil + } + switch mtype.Kind() { case reflect.Bool, reflect.Struct: val := reflect.ValueOf(tval) @@ -754,38 +1033,50 @@ func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}, mval1 *ref } return reflect.ValueOf(d), nil } - if !val.Type().ConvertibleTo(mtype) { + if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Float64 { return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) } - if reflect.Indirect(reflect.New(mtype)).OverflowInt(val.Convert(mtype).Int()) { + if reflect.Indirect(reflect.New(mtype)).OverflowInt(val.Convert(reflect.TypeOf(int64(0))).Int()) { return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String()) } return val.Convert(mtype), nil case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: val := reflect.ValueOf(tval) - if !val.Type().ConvertibleTo(mtype) { + if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Float64 { return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) } if val.Convert(reflect.TypeOf(int(1))).Int() < 0 { return reflect.ValueOf(nil), fmt.Errorf("%v(%T) is negative so does not fit in %v", tval, tval, mtype.String()) } - if reflect.Indirect(reflect.New(mtype)).OverflowUint(uint64(val.Convert(mtype).Uint())) { + if reflect.Indirect(reflect.New(mtype)).OverflowUint(val.Convert(reflect.TypeOf(uint64(0))).Uint()) { return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String()) } return val.Convert(mtype), nil case reflect.Float32, reflect.Float64: val := reflect.ValueOf(tval) - if !val.Type().ConvertibleTo(mtype) { + if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Int64 { return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) } - if reflect.Indirect(reflect.New(mtype)).OverflowFloat(val.Convert(mtype).Float()) { + if reflect.Indirect(reflect.New(mtype)).OverflowFloat(val.Convert(reflect.TypeOf(float64(0))).Float()) { return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String()) } return val.Convert(mtype), nil + case reflect.Interface: + if mval1 == nil || mval1.IsNil() { + return reflect.ValueOf(tval), nil + } else { + ival := mval1.Elem() + return d.valueFromToml(mval1.Elem().Type(), t, &ival) + } + case reflect.Slice, reflect.Array: + if isOtherSequence(mtype) && isOtherSequence(reflect.TypeOf(t)) { + return d.valueFromOtherSliceI(mtype, t) + } + return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v(%v)", tval, tval, mtype, mtype.Kind()) default: return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v(%v)", tval, tval, mtype, mtype.Kind()) } @@ -795,7 +1086,7 @@ func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}, mval1 *ref func (d *Decoder) unwrapPointer(mtype reflect.Type, tval interface{}, mval1 *reflect.Value) (reflect.Value, error) { var melem *reflect.Value - if mval1 != nil && !mval1.IsNil() && mtype.Elem().Kind() == reflect.Struct { + if mval1 != nil && !mval1.IsNil() && (mtype.Elem().Kind() == reflect.Struct || mtype.Elem().Kind() == reflect.Interface) { elem := mval1.Elem() melem = &elem } @@ -809,6 +1100,12 @@ func (d *Decoder) unwrapPointer(mtype reflect.Type, tval interface{}, mval1 *ref return mval, nil } +func (d *Decoder) unmarshalText(tval interface{}, mval reflect.Value) error { + var buf bytes.Buffer + fmt.Fprint(&buf, tval) + return callTextUnmarshaler(mval, buf.Bytes()) +} + func tomlOptions(vf reflect.StructField, an annotation) tomlOpts { tag := vf.Tag.Get(an.tag) parse := strings.Split(tag, ",") @@ -821,6 +1118,7 @@ func tomlOptions(vf reflect.StructField, an annotation) tomlOpts { defaultValue := vf.Tag.Get(tagDefault) result := tomlOpts{ name: vf.Name, + nameFromTag: false, comment: comment, commented: commented, multiline: multiline, @@ -833,6 +1131,7 @@ func tomlOptions(vf reflect.StructField, an annotation) tomlOpts { result.include = false } else { result.name = strings.Trim(parse[0], " ") + result.nameFromTag = true } } if vf.PkgPath != "" { @@ -849,11 +1148,7 @@ func tomlOptions(vf reflect.StructField, an annotation) tomlOpts { func isZero(val reflect.Value) bool { switch val.Type().Kind() { - case reflect.Map: - fallthrough - case reflect.Array: - fallthrough - case reflect.Slice: + case reflect.Slice, reflect.Array, reflect.Map: return val.Len() == 0 default: return reflect.DeepEqual(val.Interface(), reflect.Zero(val.Type()).Interface()) @@ -866,3 +1161,80 @@ func formatError(err error, pos Position) error { } return fmt.Errorf("%s: %s", pos, err) } + +// visitorState keeps track of which keys were unmarshaled. +type visitorState struct { + tree *Tree + path []string + keys map[string]struct{} + active bool +} + +func newVisitorState(tree *Tree) visitorState { + path, result := []string{}, map[string]struct{}{} + insertKeys(path, result, tree) + return visitorState{ + tree: tree, + path: path[:0], + keys: result, + active: true, + } +} + +func (s *visitorState) push(key string) { + if s.active { + s.path = append(s.path, key) + } +} + +func (s *visitorState) pop() { + if s.active { + s.path = s.path[:len(s.path)-1] + } +} + +func (s *visitorState) visit() { + if s.active { + delete(s.keys, strings.Join(s.path, ".")) + } +} + +func (s *visitorState) visitAll() { + if s.active { + for k := range s.keys { + if strings.HasPrefix(k, strings.Join(s.path, ".")) { + delete(s.keys, k) + } + } + } +} + +func (s *visitorState) validate() error { + if !s.active { + return nil + } + undecoded := make([]string, 0, len(s.keys)) + for key := range s.keys { + undecoded = append(undecoded, key) + } + sort.Strings(undecoded) + if len(undecoded) > 0 { + return fmt.Errorf("undecoded keys: %q", undecoded) + } + return nil +} + +func insertKeys(path []string, m map[string]struct{}, tree *Tree) { + for k, v := range tree.values { + switch node := v.(type) { + case []*Tree: + for i, item := range node { + insertKeys(append(path, k, strconv.Itoa(i)), m, item) + } + case *Tree: + insertKeys(append(path, k), m, node) + case *tomlValue: + m[strings.Join(append(path, k), ".")] = struct{}{} + } + } +} diff --git a/vendor/github.com/pelletier/go-toml/parser.go b/vendor/github.com/pelletier/go-toml/parser.go index 1b344fee6c5..7bf40bbdc7e 100644 --- a/vendor/github.com/pelletier/go-toml/parser.go +++ b/vendor/github.com/pelletier/go-toml/parser.go @@ -158,6 +158,11 @@ func (p *tomlParser) parseGroup() tomlParserStateFn { if err := p.tree.createSubTree(keys, startToken.Position); err != nil { p.raiseError(key, "%s", err) } + destTree := p.tree.GetPath(keys) + if target, ok := destTree.(*Tree); ok && target != nil && target.inline { + p.raiseError(key, "could not re-define exist inline table or its sub-table : %s", + strings.Join(keys, ".")) + } p.assume(tokenRightBracket) p.currentTable = keys return p.parseStart @@ -201,6 +206,11 @@ func (p *tomlParser) parseAssign() tomlParserStateFn { strings.Join(tableKey, ".")) } + if targetNode.inline { + p.raiseError(key, "could not add key or sub-table to exist inline table or its sub-table : %s", + strings.Join(tableKey, ".")) + } + // assign value to the found table keyVal := parsedKey[len(parsedKey)-1] localKey := []string{keyVal} @@ -411,12 +421,13 @@ Loop: if tokenIsComma(previous) { p.raiseError(previous, "trailing comma at the end of inline table") } + tree.inline = true return tree } func (p *tomlParser) parseArray() interface{} { var array []interface{} - arrayType := reflect.TypeOf(nil) + arrayType := reflect.TypeOf(newTree()) for { follow := p.peek() if follow == nil || follow.typ == tokenEOF { @@ -427,11 +438,8 @@ func (p *tomlParser) parseArray() interface{} { break } val := p.parseRvalue() - if arrayType == nil { - arrayType = reflect.TypeOf(val) - } if reflect.TypeOf(val) != arrayType { - p.raiseError(follow, "mixed types in array") + arrayType = nil } array = append(array, val) follow = p.peek() @@ -445,6 +453,12 @@ func (p *tomlParser) parseArray() interface{} { p.getToken() } } + + // if the array is a mixed-type array or its length is 0, + // don't convert it to a table array + if len(array) <= 0 { + arrayType = nil + } // An array of Trees is actually an array of inline // tables, which is a shorthand for a table array. If the // array was not converted from []interface{} to []*Tree, diff --git a/vendor/github.com/pelletier/go-toml/token.go b/vendor/github.com/pelletier/go-toml/token.go index 36a3fc88f2f..6af4ec46bcf 100644 --- a/vendor/github.com/pelletier/go-toml/token.go +++ b/vendor/github.com/pelletier/go-toml/token.go @@ -1,9 +1,6 @@ package toml -import ( - "fmt" - "unicode" -) +import "fmt" // Define tokens type tokenType int @@ -112,7 +109,7 @@ func isSpace(r rune) bool { } func isAlphanumeric(r rune) bool { - return unicode.IsLetter(r) || r == '_' + return 'a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' || r == '_' } func isKeyChar(r rune) bool { @@ -127,7 +124,7 @@ func isKeyStartChar(r rune) bool { } func isDigit(r rune) bool { - return unicode.IsNumber(r) + return '0' <= r && r <= '9' } func isHexDigit(r rune) bool { diff --git a/vendor/github.com/pelletier/go-toml/toml.go b/vendor/github.com/pelletier/go-toml/toml.go index 358a9be5ce8..d323c39bce9 100644 --- a/vendor/github.com/pelletier/go-toml/toml.go +++ b/vendor/github.com/pelletier/go-toml/toml.go @@ -23,6 +23,7 @@ type Tree struct { values map[string]interface{} // string -> *tomlValue, *Tree, []*Tree comment string commented bool + inline bool position Position } @@ -222,8 +223,12 @@ func (t *Tree) SetPathWithOptions(keys []string, opts SetOptions, value interfac switch v := value.(type) { case *Tree: v.comment = opts.Comment + v.commented = opts.Commented toInsert = value case []*Tree: + for i := range v { + v[i].commented = opts.Commented + } toInsert = value case *tomlValue: v.comment = opts.Comment @@ -307,6 +312,7 @@ func (t *Tree) createSubTree(keys []string, pos Position) error { if !exists { tree := newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col}) tree.position = pos + tree.inline = subtree.inline subtree.values[intermediateKey] = tree nextTree = tree } diff --git a/vendor/github.com/pelletier/go-toml/tomltree_write.go b/vendor/github.com/pelletier/go-toml/tomltree_write.go index 43c63030d26..2d6487ede4a 100644 --- a/vendor/github.com/pelletier/go-toml/tomltree_write.go +++ b/vendor/github.com/pelletier/go-toml/tomltree_write.go @@ -28,23 +28,35 @@ type sortNode struct { // Encodes a string to a TOML-compliant multi-line string value // This function is a clone of the existing encodeTomlString function, except that whitespace characters // are preserved. Quotation marks and backslashes are also not escaped. -func encodeMultilineTomlString(value string) string { +func encodeMultilineTomlString(value string, commented string) string { var b bytes.Buffer - - for _, rr := range value { + adjacentQuoteCount := 0 + + b.WriteString(commented) + for i, rr := range value { + if rr != '"' { + adjacentQuoteCount = 0 + } else { + adjacentQuoteCount++ + } switch rr { case '\b': b.WriteString(`\b`) case '\t': b.WriteString("\t") case '\n': - b.WriteString("\n") + b.WriteString("\n" + commented) case '\f': b.WriteString(`\f`) case '\r': b.WriteString("\r") case '"': - b.WriteString(`"`) + if adjacentQuoteCount >= 3 || i == len(value)-1 { + adjacentQuoteCount = 0 + b.WriteString(`\"`) + } else { + b.WriteString(`"`) + } case '\\': b.WriteString(`\`) default: @@ -91,7 +103,30 @@ func encodeTomlString(value string) string { return b.String() } -func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElementPerLine bool) (string, error) { +func tomlTreeStringRepresentation(t *Tree, ord marshalOrder) (string, error) { + var orderedVals []sortNode + switch ord { + case OrderPreserve: + orderedVals = sortByLines(t) + default: + orderedVals = sortAlphabetical(t) + } + + var values []string + for _, node := range orderedVals { + k := node.key + v := t.values[k] + + repr, err := tomlValueStringRepresentation(v, "", "", ord, false) + if err != nil { + return "", err + } + values = append(values, quoteKeyIfNeeded(k)+" = "+repr) + } + return "{ " + strings.Join(values, ", ") + " }", nil +} + +func tomlValueStringRepresentation(v interface{}, commented string, indent string, ord marshalOrder, arraysOneElementPerLine bool) (string, error) { // this interface check is added to dereference the change made in the writeTo function. // That change was made to allow this function to see formatting options. tv, ok := v.(*tomlValue) @@ -123,12 +158,12 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen return strings.ToLower(strconv.FormatFloat(value, 'f', -1, bits)), nil case string: if tv.multiline { - return "\"\"\"\n" + encodeMultilineTomlString(value) + "\"\"\"", nil + return "\"\"\"\n" + encodeMultilineTomlString(value, commented) + "\"\"\"", nil } return "\"" + encodeTomlString(value) + "\"", nil case []byte: b, _ := v.([]byte) - return tomlValueStringRepresentation(string(b), indent, arraysOneElementPerLine) + return tomlValueStringRepresentation(string(b), commented, indent, ord, arraysOneElementPerLine) case bool: if value { return "true", nil @@ -142,6 +177,8 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen return value.String(), nil case LocalTime: return value.String(), nil + case *Tree: + return tomlTreeStringRepresentation(value, ord) case nil: return "", nil } @@ -152,7 +189,7 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen var values []string for i := 0; i < rv.Len(); i++ { item := rv.Index(i).Interface() - itemRepr, err := tomlValueStringRepresentation(item, indent, arraysOneElementPerLine) + itemRepr, err := tomlValueStringRepresentation(item, commented, indent, ord, arraysOneElementPerLine) if err != nil { return "", err } @@ -166,16 +203,16 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen for _, value := range values { stringBuffer.WriteString(valueIndent) - stringBuffer.WriteString(value) + stringBuffer.WriteString(commented + value) stringBuffer.WriteString(`,`) stringBuffer.WriteString("\n") } - stringBuffer.WriteString(indent + "]") + stringBuffer.WriteString(indent + commented + "]") return stringBuffer.String(), nil } - return "[" + strings.Join(values, ",") + "]", nil + return "[" + strings.Join(values, ", ") + "]", nil } return "", fmt.Errorf("unsupported value type %T: %v", v, v) } @@ -270,10 +307,10 @@ func sortAlphabetical(t *Tree) (vals []sortNode) { } func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool) (int64, error) { - return t.writeToOrdered(w, indent, keyspace, bytesCount, arraysOneElementPerLine, OrderAlphabetical) + return t.writeToOrdered(w, indent, keyspace, bytesCount, arraysOneElementPerLine, OrderAlphabetical, " ", false) } -func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool, ord marshalOrder) (int64, error) { +func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool, ord marshalOrder, indentString string, parentCommented bool) (int64, error) { var orderedVals []sortNode switch ord { @@ -289,14 +326,10 @@ func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount i k := node.key v := t.values[k] - combinedKey := k + combinedKey := quoteKeyIfNeeded(k) if keyspace != "" { combinedKey = keyspace + "." + combinedKey } - var commented string - if t.commented { - commented = "# " - } switch node := v.(type) { // node has to be of those two types given how keys are sorted above @@ -317,24 +350,33 @@ func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount i return bytesCount, errc } } + + var commented string + if parentCommented || t.commented || tv.commented { + commented = "# " + } writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[", combinedKey, "]\n") bytesCount += int64(writtenBytesCount) if err != nil { return bytesCount, err } - bytesCount, err = node.writeToOrdered(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine, ord) + bytesCount, err = node.writeToOrdered(w, indent+indentString, combinedKey, bytesCount, arraysOneElementPerLine, ord, indentString, parentCommented || t.commented || tv.commented) if err != nil { return bytesCount, err } case []*Tree: for _, subTree := range node { + var commented string + if parentCommented || t.commented || subTree.commented { + commented = "# " + } writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[[", combinedKey, "]]\n") bytesCount += int64(writtenBytesCount) if err != nil { return bytesCount, err } - bytesCount, err = subTree.writeToOrdered(w, indent+" ", combinedKey, bytesCount, arraysOneElementPerLine, ord) + bytesCount, err = subTree.writeToOrdered(w, indent+indentString, combinedKey, bytesCount, arraysOneElementPerLine, ord, indentString, parentCommented || t.commented || subTree.commented) if err != nil { return bytesCount, err } @@ -347,7 +389,11 @@ func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount i return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k]) } - repr, err := tomlValueStringRepresentation(v, indent, arraysOneElementPerLine) + var commented string + if parentCommented || t.commented || v.commented { + commented = "# " + } + repr, err := tomlValueStringRepresentation(v, commented, indent, ord, arraysOneElementPerLine) if err != nil { return bytesCount, err } @@ -365,10 +411,6 @@ func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount i } } - var commented string - if v.commented { - commented = "# " - } quotedKey := quoteKeyIfNeeded(k) writtenBytesCount, err := writeStrings(w, indent, commented, quotedKey, " = ", repr, "\n") bytesCount += int64(writtenBytesCount) diff --git a/vendor/gopkg.in/yaml.v2/apic.go b/vendor/gopkg.in/yaml.v2/apic.go index 1f7e87e6727..d2c2308f1f4 100644 --- a/vendor/gopkg.in/yaml.v2/apic.go +++ b/vendor/gopkg.in/yaml.v2/apic.go @@ -86,6 +86,7 @@ func yaml_emitter_initialize(emitter *yaml_emitter_t) { raw_buffer: make([]byte, 0, output_raw_buffer_size), states: make([]yaml_emitter_state_t, 0, initial_stack_size), events: make([]yaml_event_t, 0, initial_queue_size), + best_width: -1, } } diff --git a/vendor/modules.txt b/vendor/modules.txt index 686bf187d66..8458b395a96 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -231,7 +231,7 @@ github.com/openzipkin/zipkin-go/model github.com/openzipkin/zipkin-go/propagation github.com/openzipkin/zipkin-go/reporter github.com/openzipkin/zipkin-go/reporter/http -# github.com/pelletier/go-toml v1.6.0 +# github.com/pelletier/go-toml v1.8.0 github.com/pelletier/go-toml # github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 github.com/phayes/freeport @@ -505,7 +505,7 @@ google.golang.org/grpc/status google.golang.org/grpc/tap # gopkg.in/inf.v0 v0.9.1 gopkg.in/inf.v0 -# gopkg.in/yaml.v2 v2.2.8 +# gopkg.in/yaml.v2 v2.3.0 gopkg.in/yaml.v2 # honnef.co/go/tools v0.0.1-2020.1.3 honnef.co/go/tools/arg